当输出的最后一个维度等于一时,Theano 中扫描的奇怪行为

Strange behavior of scan in Theano when outputs has last dimension equal to one

我在 Theano 中编译扫描运算符时遇到一个奇怪的错误,我无法理解。 当 outputs_info 初始化为最后一个维度等于一时,我得到这个错误:

TypeError: ('The following error happened while compiling the node', forall_inplace,cpu,
scan_fn}(TensorConstant{4}, IncSubtensor{InplaceSet;:int64:}.0, <TensorType(float32, vector)>), 
'\n', "Inconsistency in the inner graph of scan 'scan_fn' : an input and an output are 
associated with the same recurrent state and should have the same type but have type 
'TensorType(float32, (True,))' and 'TensorType(float32, vector)' respectively.")

虽然如果此维度设置为大于一的任何值,我不会收到任何错误。

这个错误发生在 gpu 和 cpu 目标上,使用 theano 0.7、0.8.0 和 0.8.2。

这是一段重现错误的代码:

import theano
import theano.tensor as T
import numpy as np

def rec_fun( prev_output, bias):        
    return prev_output + bias

n_steps = 4

# with state_size>1, compilation runs smoothly
state_size = 2

bias = theano.shared(np.ones((state_size),dtype=theano.config.floatX))
(outputs, updates) = theano.scan( fn=rec_fun,
                              sequences=[],
                              outputs_info=T.zeros([state_size,]),
                              non_sequences=[bias],
                              n_steps=n_steps
                              )
print outputs.eval()

# with state_size==1, compilation fails
state_size = 1

bias = theano.shared(np.ones((state_size),dtype=theano.config.floatX))
(outputs, updates) = theano.scan( fn=rec_fun,
                              sequences=[],
                              outputs_info=T.zeros([state_size,]),
                              non_sequences=[bias],
                              n_steps=n_steps
                              )
# compilation fails here
print outputs.eval()

因此,编译具有不同的行为,具体取决于 "state_size"。 是否有解决方法来处理 state_size==1 和 state_size>1 两种情况?

改变

outputs_info=T.zeros([state_size,])

outputs_info=T.zeros_like(bias)

使其在 state_size == 1 的情况下正常工作。

次要解释和不同的解决方案

所以我注意到这两种情况之间的关键区别。 在这两种情况下,都将这些代码行添加到偏置声明行之后。

bias = ....
print bias.broadcastable
print T.zeros([state_size,]).broadcastable

结果是

对于您的代码有效的第一种情况

(False,)
(False,)

而对于第二种情况,它似乎崩溃了

(False,)
(True,)

所以发生的事情是,当您添加相同维度(偏差和 T.zeros)但具有不同广播模式的两个张量时,结果继承的模式是来自偏差的模式。这最终导致 theano 错误识别它们不是同一类型。

T.zeros_like 有效,因为它使用 bias 变量生成零张量。

另一种解决问题的方法是像这样更改广播模式

outputs_info=T.patternbroadcast(T.zeros([state_size,]), (False,)),