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

eri*_*krf 24 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')
Run Code Online (Sandbox Code Playgroud)

(我正在tf.pack按照这个问题的建议使用,因为我得到了同样的错误)

当我运行它(从一个更大的脚本调用这个),我得到这个错误:

ValueError: initial_value must have a shape specified: Tensor("normaldist:0", shape=TensorShape([Dimension(None), Dimension(None)]), dtype=float32)
Run Code Online (Sandbox Code Playgroud)

我试图在交互式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)])
Run Code Online (Sandbox Code Playgroud)

这很奇怪.Tensorflow生成矢量但不能说它的形状.难道我做错了什么?

mrr*_*rry 38

正如Ishamael所说,所有张量都具有静态形状,这在图形构造时已知并且可以使用Tensor.get_shape(); 和动态形状,仅在运行时已知,可通过获取张量的值或将其传递给运算符来访问tf.shape.在许多情况下,静态和动态形状是相同的,但它们可以是不同的 - 静态形状可以部分定义 - 以允许动态形状从一个步骤到下一个步骤变化.

在您的代码中normal_dist有一个部分定义的静态形状,因为它w_shape是一个计算值.(TensorFlow有时试图评估在图构造时间这些计算出的值,但它卡住在tf.pack.)它推断出的形状TensorShape([Dimension(None), Dimension(None)]),这意味着"具有未知数量的行和列的矩阵",因为它的已知,即w_shape是长度的矢量2,因此产生的normal_dist必须是二维的.

您有两种方法可以解决这个问题.您可以像Ishamael建议的那样设置静态形状,但这需要您了解图形构建时的形状.例如,以下可能有效:

normal_dist.set_shape([input_data.get_shape()[1], labels.get_shape()[1]])
Run Code Online (Sandbox Code Playgroud)

或者,您可以传递validate_shape=Falsetf.Variable构造函数.这允许您创建具有部分定义形状的变量,但它限制了稍后可以在图中推断的静态形状信息量.


Sal*_*ali 6

TF FAQ 中很好地解释了类似的问题:

在 TensorFlow 中,张量具有静态(推断)形状和动态(真实)形状。可以使用该tf.Tensor.get_shape方法读取静态形状 :该形状是从用于创建张量的操作中推断出来的,并且可能是部分完整的。如果静态形状没有完全定义,张量 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))
Run Code Online (Sandbox Code Playgroud)

另一方面,您可以使用提取静态形状x.get_shape().as_list(),这可以在任何地方计算。


Ish*_*ael 5

该变量可以具有动态形状。get_shape()返回静态形状。

在您的情况下,您有一个具有动态形状的张量,并且当前恰好保存 4x3 的值(但在其他时间它可以保存具有不同形状的值 - 因为形状是动态的)。要设置静态形状,请使用set_shape(w_shape)。之后,您设置的形状将被强制执行,并且张量将是有效的initial_value