我正在玩tensorflow并遇到以下代码的问题:
def _init_parameters(self, input_data, labels):
# the input shape is (batch_size, input_size)
input_size = tf.shape(input_data)[1]
# labels in one-hot format have shape (batch_size, num_classes)
num_classes = tf.shape(labels)[1]
stddev = 1.0 / tf.cast(input_size, tf.float32)
w_shape = tf.pack([input_size, num_classes], 'w-shape')
normal_dist = tf.truncated_normal(w_shape, stddev=stddev, name='normaldist')
self.w = tf.Variable(normal_dist, name='weights')
(我正在this question中建议使用tf.pack
,因为我收到同样的错误)
当我运行它时(从一个调用此脚本的较大脚本),我收到此错误:
ValueError: initial_value must have a shape specified: Tensor("normaldist:0", shape=TensorShape([Dimension(None), Dimension(None)]), dtype=float32)
我试图在交互式shell中复制该过程。实际上,normal_dist
的维度未指定,尽管提供的值确实存在:
In [70]: input_size.eval()
Out[70]: 4
In [71]: num_classes.eval()
Out[71]: 3
In [72]: w_shape.eval()
Out[72]: array([4, 3], dtype=int32)
In [73]: normal_dist.eval()
Out[73]:
array([[-0.27035281, -0.223277 , 0.14694688],
[-0.16527176, 0.02180306, 0.00807841],
[ 0.22624688, 0.36425814, -0.03099642],
[ 0.25575709, -0.02765726, -0.26169327]], dtype=float32)
In [78]: normal_dist.get_shape()
Out[78]: TensorShape([Dimension(None), Dimension(None)])
这很奇怪。 Tensorflow生成矢量但不能说它的形状。我做错了吗?
答案 0 :(得分:36)
正如Ishamael所说,所有张量都具有静态形状,这在图形构造时已知并且可以使用Tensor.get_shape()
访问;和动态形状,仅在运行时已知,可通过获取张量的值或将其传递给tf.shape
等运算符来访问。在许多情况下,静态和动态形状是相同的,但它们可以是不同的 - 静态形状可以部分定义 - 以便允许动态形状从一个步骤变化到下一个步骤。 / p>
在您的代码normal_dist
中有一个部分定义的静态形状,因为w_shape
是一个计算值。 (TensorFlow有时会尝试评估
图形构造时的这些计算值,但它被卡在tf.pack
。)它推断出形状TensorShape([Dimension(None), Dimension(None)])
,这意味着"一个行数和列数未知的矩阵,&#34 ;因为它知道w_shape
是长度为2的向量,所以得到的normal_dist
必须是2维的。
您有两种方法可以解决这个问题。您可以像Ishamael建议的那样设置静态形状,但这需要您了解图形构建时的形状。例如,以下内容可能有效:
normal_dist.set_shape([input_data.get_shape()[1], labels.get_shape()[1]])
或者,您可以将validate_shape=False
传递给tf.Variable
constructor。这允许您创建具有部分定义形状的变量,但它限制了可以在图形中稍后推断的静态形状信息量。
答案 1 :(得分:3)
变量可以具有动态形状。 get_shape()
返回静态形状。
在你的情况下,你有一个具有动态形状的张量,并且当前碰巧保持4x3的值(但在其他时候它可以保持具有不同形状的值 - 因为形状是动态的)。要设置静态形状,请使用set_shape(w_shape)
。之后,您设置的形状将被强制执行,张量将是有效的initial_value
。
答案 2 :(得分:3)
在TF FAQ中很好地解释了类似的问题:
在TensorFlow中,张量具有静态(推断)形状和a 动态(真实)形状。可以使用以下方法读取静态形状
tf.Tensor.get_shape
方法:从操作中推断出这种形状 用于创建张量的,可能是部分完成的。如果 静态形状没有完全定义,Tensor t的动态形状 可以通过评估tf.shape(t)
来确定。
所以tf.shape()
会给你一个张量,它的大小总是shape=(N,)
,并且可以在一个会话中计算出来:
a = tf.Variable(tf.zeros(shape=(2, 3, 4)))
with tf.Session() as sess:
print sess.run(tf.shape(a))
另一方面,您可以使用x.get_shape().as_list()
提取静态形状,这可以在任何地方计算。