我正在试验Theano,特别是函数scan。
我想用它将线性分类器应用于存储为矩阵X列的一组特征向量(我确信有更好的方法可以做到这一点,这只是为了熟悉函数扫描)。
这是我的代码段:
T_W = T.fmatrix('W')
T_b = T.fmatrix('b')
T_X = T.fmatrix('X')
T_x = T.fmatrix('x')
# this is the linear classifier
T_f = T.dot(T_W, T_x) + T_b
f = theano.function(inputs=[T_x, theano.Param(T_W), theano.Param(T_b)],outputs=T_f)
T_outputs, T_updates = theano.scan(fn=lambda x,W,b : T_f, sequences=[T_X], non_sequences=[T_W,T_b])
F = theano.function(inputs=[T_X, theano.Param(T_W), theano.Param(T_b)],outputs=T_outputs)
从iPython执行代码片段时,我收到以下错误(由最后一条指令触发):
MissingInputError: A variable that is an input to the graph was neither provided as an input to the function nor given a value. A chain of variables leading from this input to an output is [x, for{cpu,scan_fn}.0]. This chain may not be unique
Backtrace when the variable is created:
File "<ipython-input-40-72b539c54ff4>", line 5, in <module>
T_x = T.fmatrix('x')
答案 0 :(得分:1)
目前还不完全清楚你在这里要做什么,但我的猜测是你正在实现两个不同版本的线性分类器,一个不使用扫描而另一个不使用扫描。
下面的代码演示了我这样做的方法。
回答您的具体问题:
出现错误消息是因为您的扫描版本在扫描步骤功能中使用T_f
(这很奇怪,其中一个原因是您不清楚您要尝试做什么;步骤功能不使用任何一个输入变量x
,W
或b
完全!)和T_f
使用T_x
,但您的扫描版本的函数不会将T_x
视为T_X
输入。相反,需要v1
(注意案例差异),然后根本不使用。
以下是您和我的代码之间差异的一些提示和解释。
将事物分成不连续的方法非常有帮助。通过将代码拆分为v2
和strict
方法,我们可以确保两种不同的实现不会相互干扰。
建议始终使用theano.scan
的{{1}}参数。它确保您不会意外地引入由步骤函数的参数中的命名冲突引起的错误。默认情况下不启用它,因为当严格不存在时,这可能会破坏旧代码。
使用完全成熟的函数而不是lambda来执行扫描的步进功能。与严格模式一样,这有助于避免意外命名冲突,并使步骤代码更容易遵循。步进功能也可以单独测试。
使用compute_test_value
确保计算适用于简单的样本数据。特别是,这将识别形状不匹配(例如,使用错误顺序的参数执行dot
),并通过在计算图形构建时能够打印/探索中间值来简化调试而不是稍后执行计算时。
此代码将每个输入样本编码为一行x
,而不是x
列。这需要后乘w
而不是预乘。可以这样做,但是预先乘以w
会使b
的加法更加混乱(需要引入dimshuffle
)。
除非您需要使用与默认值等相关的非标准行为,否则无需使用theano.Param
。
避免将这些内容命名为仅限于大小写!一般来说,坚持Python style guide(即实例变量应为小写,单词用下划线分隔)。
在扫描版本的步骤函数中需要一个dimshuffle和第一行的选择,以确保偏移的点积和子序列添加是尺寸兼容的。在非扫描版本中不需要这样做,因为我们正在做矩阵矩阵点积。
代码:
import numpy
import theano
import theano.tensor as T
def create_inputs(x_value, w_value, b_value):
x, w = T.matrices(2)
b = T.vector()
x.tag.test_value = x_value
w.tag.test_value = w_value
b.tag.test_value = b_value
return x, w, b
def v1(x_value, w_value, b_value):
x, w, b = create_inputs(x_value, w_value, b_value)
y = T.dot(x, w) + b
f = theano.function(inputs=[x, w, b], outputs=y)
print f(x_value, w_value, b_value)
def v2_step(x, w, b):
return (T.dot(x.dimshuffle('x', 0), w) + b)[0]
def v2(x_value, w_value, b_value):
x, w, b = create_inputs(x_value, w_value, b_value)
y, _ = theano.scan(v2_step, sequences=[x], non_sequences=[w, b], strict=True)
f = theano.function(inputs=[x, w, b], outputs=y)
print f(x_value, w_value, b_value)
def main():
batch_size = 2
input_size = 3
hidden_size = 4
theano.config.compute_test_value = 'raise'
numpy.random.seed(1)
x_value = numpy.random.standard_normal(size=(batch_size, input_size))
w_value = numpy.random.standard_normal(size=(input_size, hidden_size))
b_value = numpy.zeros((hidden_size,))
v1(x_value, w_value, b_value)
v2(x_value, w_value, b_value)
main()