Theano梯度计算创建float64
Theano gradient calculation creates float64
我在 Theano 上有一些标准的 NN 代码,带有两个独立的编译函数。一种是计算成本,一种是用AdaGrad更新计算成本。
对于 GPU 速度,我试图保持一切 float32
。问题是我收到警告,梯度计算正在创建 float64
。特别是对于以下代码行。
gradients = TT.grad(lossFn, self.params)
paramUpdates = [(param, param - TT.inv(TT.sqrt(sumGrad)) * grad) for param, grad, sumGrad in zip(self.params, gradients, self.gradSums)]
如果我注释掉梯度计算并将第二行替换为占位符,一切都很好。显然这是一个垃圾更新,但它有助于查明问题。
paramUpdates = [(self.params[0], self.params[0])]
供参考,这是损失函数:
self.loss = TT.mean(TT.sqr(self.logisticLayer.yHat - TT.cast(self.inputs[1:-1, :], floatX)), acc_dtype=floatX, dtype=floatX)
仅成本编译函数是:
self._calculateCost = theano.function(
inputs=[self.inputs],
outputs=self.loss,
)
而成本 + 更新函数是:
self._calculateCostAndUpdate = theano.function(
inputs=[self.inputs],
outputs=self.loss,
updates=updates
)
更新
我将问题确定为 LSTM 层。这是最少的代码
class TestLSTMLayer(object):
def __init__(self, inputs, outputSize, dropout=0.9, inputSize=None, adagradInit=1, forgetGateBias=3, srng=None):
self.h0 = theano.shared(np.random.randn(outputSize).astype(floatX))
self.params = [self.h0]
def _recurrence(hBelow):
return hBelow
hOutputs, _ = theano.scan(
fn=_recurrence,
outputs_info=self.h0,
n_steps=inputs.shape[0]
)
self.hOutputs = hOutputs
def getUpdates(self):
gradients = TT.grad(TT.sum(self.hOutputs), self.params)
paramUpdates = [(self.params[0], self.params[0])]
return paramUpdates
当我调用getUpdates()
获取渐变时出现问题(例如这里是垃圾更新)。我发现注释掉 gradients = ...
或将 scan()
替换为重复 h0
所需形状的东西可以解决问题。
更新 2
调试显示 scan
函数中的 int64
乱七八糟。
|Subtensor{int64::} [@B] <TensorType(float32, matrix)> ''
|for{cpu,scan_fn} [@C] <TensorType(float32, matrix)> ''
| |Subtensor{int64} [@D] <TensorType(int64, scalar)> ''
| | |Shape [@E] <TensorType(int64, vector)> ''
| | | |<TensorType(float32, matrix)> [@F] <TensorType(float32, matrix)>
| | |Constant{0} [@G] <int64>
| |IncSubtensor{Set;:int64:} [@H] <TensorType(float32, matrix)> ''
| |Alloc [@I] <TensorType(float32, matrix)> ''
| | |TensorConstant{0.0} [@J] <TensorType(float32, scalar)>
| | |Elemwise{add,no_inplace} [@K] <TensorType(int64, scalar)> ''
| | | |Subtensor{int64} [@D] <TensorType(int64, scalar)> ''
| | | |Subtensor{int64} [@L] <TensorType(int64, scalar)> ''
| | | |Shape [@M] <TensorType(int64, vector)> ''
| | | | |Rebroadcast{0} [@N] <TensorType(float32, matrix)> ''
| | | | |DimShuffle{x,0} [@O] <TensorType(float32, row)> ''
| | | | |<TensorType(float32, vector)> [@P] <TensorType(float32, vector)>
| | | |Constant{0} [@Q] <int64>
| | |Subtensor{int64} [@R] <TensorType(int64, scalar)> ''
| | |Shape [@S] <TensorType(int64, vector)> ''
| | | |Rebroadcast{0} [@N] <TensorType(float32, matrix)> ''
| | |Constant{1} [@T] <int64>
| |Rebroadcast{0} [@N] <TensorType(float32, matrix)> ''
| |ScalarFromTensor [@U] <int64> ''
| |Subtensor{int64} [@L] <TensorType(int64, scalar)> ''
|Constant{1} [@V] <int64>
您可以使用 theano.printing.debugprint
和 print_type=True
来查看各种组件的类型。
例如,
class TestLSTMLayer(object):
def __init__(self, inputs, outputSize, dropout=0.9, inputSize=None, adagradInit=1, forgetGateBias=3, srng=None):
self.h0 = theano.shared(np.random.randn(outputSize).astype(floatX))
self.params = [self.h0]
def _recurrence(hBelow):
print 'hBelow', theano.printing.debugprint(hBelow, print_type=True)
return hBelow
print 'h0', theano.printing.debugprint(self.h0, print_type=True)
hOutputs, _ = theano.scan(
fn=_recurrence,
outputs_info=self.h0,
n_steps=inputs.shape[0]
)
self.hOutputs = hOutputs
def getUpdates(self):
print 'sum', theano.printing.debugprint(TT.sum(self.hOutputs), print_type=True)
gradients = TT.grad(TT.sum(self.hOutputs), self.params)
paramUpdates = [(self.params[0], self.params[0])]
return paramUpdates
我通过更新到最新版本(GitHub 上的最新版本)解决了这个问题。 http://deeplearning.net/software/theano/install.html#bleeding-edge-install-instructions
有点奇怪,但仍然是一个解决方案。
我在 Theano 上有一些标准的 NN 代码,带有两个独立的编译函数。一种是计算成本,一种是用AdaGrad更新计算成本。
对于 GPU 速度,我试图保持一切 float32
。问题是我收到警告,梯度计算正在创建 float64
。特别是对于以下代码行。
gradients = TT.grad(lossFn, self.params)
paramUpdates = [(param, param - TT.inv(TT.sqrt(sumGrad)) * grad) for param, grad, sumGrad in zip(self.params, gradients, self.gradSums)]
如果我注释掉梯度计算并将第二行替换为占位符,一切都很好。显然这是一个垃圾更新,但它有助于查明问题。
paramUpdates = [(self.params[0], self.params[0])]
供参考,这是损失函数:
self.loss = TT.mean(TT.sqr(self.logisticLayer.yHat - TT.cast(self.inputs[1:-1, :], floatX)), acc_dtype=floatX, dtype=floatX)
仅成本编译函数是:
self._calculateCost = theano.function(
inputs=[self.inputs],
outputs=self.loss,
)
而成本 + 更新函数是:
self._calculateCostAndUpdate = theano.function(
inputs=[self.inputs],
outputs=self.loss,
updates=updates
)
更新
我将问题确定为 LSTM 层。这是最少的代码
class TestLSTMLayer(object):
def __init__(self, inputs, outputSize, dropout=0.9, inputSize=None, adagradInit=1, forgetGateBias=3, srng=None):
self.h0 = theano.shared(np.random.randn(outputSize).astype(floatX))
self.params = [self.h0]
def _recurrence(hBelow):
return hBelow
hOutputs, _ = theano.scan(
fn=_recurrence,
outputs_info=self.h0,
n_steps=inputs.shape[0]
)
self.hOutputs = hOutputs
def getUpdates(self):
gradients = TT.grad(TT.sum(self.hOutputs), self.params)
paramUpdates = [(self.params[0], self.params[0])]
return paramUpdates
当我调用getUpdates()
获取渐变时出现问题(例如这里是垃圾更新)。我发现注释掉 gradients = ...
或将 scan()
替换为重复 h0
所需形状的东西可以解决问题。
更新 2
调试显示 scan
函数中的 int64
乱七八糟。
|Subtensor{int64::} [@B] <TensorType(float32, matrix)> ''
|for{cpu,scan_fn} [@C] <TensorType(float32, matrix)> ''
| |Subtensor{int64} [@D] <TensorType(int64, scalar)> ''
| | |Shape [@E] <TensorType(int64, vector)> ''
| | | |<TensorType(float32, matrix)> [@F] <TensorType(float32, matrix)>
| | |Constant{0} [@G] <int64>
| |IncSubtensor{Set;:int64:} [@H] <TensorType(float32, matrix)> ''
| |Alloc [@I] <TensorType(float32, matrix)> ''
| | |TensorConstant{0.0} [@J] <TensorType(float32, scalar)>
| | |Elemwise{add,no_inplace} [@K] <TensorType(int64, scalar)> ''
| | | |Subtensor{int64} [@D] <TensorType(int64, scalar)> ''
| | | |Subtensor{int64} [@L] <TensorType(int64, scalar)> ''
| | | |Shape [@M] <TensorType(int64, vector)> ''
| | | | |Rebroadcast{0} [@N] <TensorType(float32, matrix)> ''
| | | | |DimShuffle{x,0} [@O] <TensorType(float32, row)> ''
| | | | |<TensorType(float32, vector)> [@P] <TensorType(float32, vector)>
| | | |Constant{0} [@Q] <int64>
| | |Subtensor{int64} [@R] <TensorType(int64, scalar)> ''
| | |Shape [@S] <TensorType(int64, vector)> ''
| | | |Rebroadcast{0} [@N] <TensorType(float32, matrix)> ''
| | |Constant{1} [@T] <int64>
| |Rebroadcast{0} [@N] <TensorType(float32, matrix)> ''
| |ScalarFromTensor [@U] <int64> ''
| |Subtensor{int64} [@L] <TensorType(int64, scalar)> ''
|Constant{1} [@V] <int64>
您可以使用 theano.printing.debugprint
和 print_type=True
来查看各种组件的类型。
例如,
class TestLSTMLayer(object):
def __init__(self, inputs, outputSize, dropout=0.9, inputSize=None, adagradInit=1, forgetGateBias=3, srng=None):
self.h0 = theano.shared(np.random.randn(outputSize).astype(floatX))
self.params = [self.h0]
def _recurrence(hBelow):
print 'hBelow', theano.printing.debugprint(hBelow, print_type=True)
return hBelow
print 'h0', theano.printing.debugprint(self.h0, print_type=True)
hOutputs, _ = theano.scan(
fn=_recurrence,
outputs_info=self.h0,
n_steps=inputs.shape[0]
)
self.hOutputs = hOutputs
def getUpdates(self):
print 'sum', theano.printing.debugprint(TT.sum(self.hOutputs), print_type=True)
gradients = TT.grad(TT.sum(self.hOutputs), self.params)
paramUpdates = [(self.params[0], self.params[0])]
return paramUpdates
我通过更新到最新版本(GitHub 上的最新版本)解决了这个问题。 http://deeplearning.net/software/theano/install.html#bleeding-edge-install-instructions
有点奇怪,但仍然是一个解决方案。