我在0.6.0分支上使用了here描述的模型。代码可以找到here。我对链接代码做了一些小改动。
在我的代码中,我创建了两个模型,一个用于训练,一个用于验证,与Tensorflow教程中的模型非常相似。
with tf.variable_scope("model", reuse=None, initializer=initializer):
m = PTBModel_User(is_training=True, config=config, name='Training model')
with tf.variable_scope("model", reuse=True, initializer=initializer):
mtest = PTBModel_User(is_training=False, config=config_valid, name='Validation model')
第一个模型,一个用于训练,似乎创建得很好,但第二个用于验证,但没有。输出获得None维度!我引用的行位于linked代码中的第134行:
output = tf.reshape(tf.concat(1, outputs), [-1, size])
我在输出重塑后立即添加了这些行:
output_shape = output.get_shape()
print("Model num_steps:", num_steps)
print("Model batch_size:", batch_size)
print("Output dims", output_shape[0], output_shape[1])
这给了我这个:
Model num_steps: 400
Model batch_size: 1
Output dims Dimension(None) Dimension(650)
此问题仅发生在“验证模式”中,而不是“培训模型”。对于培训模式'我得到预期的输出:
Model num_steps: 400
Model batch_size: 2
Output dims Dimension(800) Dimension(650)
(请注意,使用'验证模型'我使用batch_size=1
代替我用于培训模型的batch_size=2
根据我的理解,使用-1
作为reshape
函数的输入,将自动计算出输出形状!但是为什么我会得到无?馈送到模型的配置中没有任何内容具有None值。
感谢您提供所有帮助和提示!
答案 0 :(得分:6)
TL; DR:维度None
只是意味着形状推断无法确定output
张量的精确形状,在图形构建时。运行图形时,张量将具有相应的运行时形状。
如果您对形状推断的工作方式不感兴趣,可以立即停止阅读。
形状推断基于“形状函数”应用局部规则,该形状函数将输入的形状取为操作并计算操作输出的(可能不完整的)形状。要弄清楚tf.reshape()
给出不完整形状的原因,我们必须查看其输入,并向后工作:
shape
的{{1}}参数包含tf.reshape()
,表示“根据[-1]
输入的形状”自动计算输出形状。tensor
输入是tf.concat()
上same line的输出。tensor
的输入由tf.mul()
中的BasicLSTMCell.__call__()
计算。 tf.concat()
操作符会将tf.tanh()
和tf.sigmoid()
操作的结果相乘。tf.mul()
操作会生成大小为tf.tanh()
的输出,[?, hidden_size]
操作会生成大小为tf.sigmoid()
的输出。 [batch_size, hidden_size]
操作执行NumPy-style broadcasting。只有尺寸为1时才会广播尺寸。请考虑我们计算tf.mul()
的三种情况:
tf.mul(x, y)
的形状为x
,而[1, 10]
的形状为y
,则会进行广播,输出形状为[5, 10]
。[5, 10]
的形状为x
,而[1, 10]
的形状为y
,则不会进行广播,输出形状将为[1, 10]
。 [1, 10]
的形状为x
,而[1, 10]
的形状为y
,则静态信息不足以判断广播是否会发生(即使我们碰巧发生了知道案例2适用于运行时)。因此,当[?, 10]
为1时,batch_size
op会生成形状为tf.mul()
的输出;但是当[?, hidden_size]
大于1时,输出形状为batch_size
。
如果形状推断出现故障,可以使用Tensor.set_shape()
方法添加信息。这可能在[batch_size, hidden_size]
实现中很有用,我们知道的不仅仅是可以推断出输出的形状。