我在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
调试显示int64
函数中的scan
混乱。
|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>
答案 0 :(得分:0)
您可以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
答案 1 :(得分:0)
我通过更新到最新版本(GitHub上的最新版本)来解决这个问题。 http://deeplearning.net/software/theano/install.html#bleeding-edge-install-instructions
有点奇怪,但仍然是一个解决方案。