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.debugprintprint_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

有点奇怪,但仍然是一个解决方案。