张量流中具有未指定尺寸的张量

时间:2015-12-04 02:11:34

标签: python tensorflow

我正在玩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生成矢量但不能说它的形状。我做错了吗?

3 个答案:

答案 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()提取静态形状,这可以在任何地方计算。