Python 张量流中具有未指定维度的张量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/34079787/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 14:26:55  来源:igfitidea点击:

Tensor with unspecified dimension in tensorflow

pythontensorflow

提问by erickrf

I'm playing around with tensorflow and ran into a problem with the following code:

我在玩 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')

(I'm using tf.packas suggested in this question, since I was getting the same error)

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

When I run it (from a larger script that invokes this one), I get this error:

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

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

I tried to replicate the process in the interactive shell. Indeed, the dimensions of normal_distare unspecified, although the supplied values do exist:

我试图在交互式 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)])

This is weird. Tensorflow generates the vector but can't say its shape. Am I doing something wrong?

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

采纳答案by mrry

As Ishamael says, all tensors have a static shape, which is known at graph construction time and accessible using Tensor.get_shape(); and a dynamic shape, which is only known at runtime and is accessible by fetching the value of the tensor, or passing it to an operator like tf.shape. In many cases, the static and dynamic shapes are the same, but they can be different - the static shape can be partially defined- in order allow the dynamic shape to vary from one step to the next.

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

In your code normal_disthas a partially-defined static shape, because w_shapeis a computed value. (TensorFlow sometimes attempts to evaluate these computed values at graph construction time, but it gets stuck at tf.pack.) It infers the shape TensorShape([Dimension(None), Dimension(None)]), which means "a matrix with an unknown number of rows and columns," because it knowns that w_shapeis a vector of length 2, so the resulting normal_distmust be 2-dimensional.

在您的代码中normal_dist有一个部分定义的静态形状,因为它w_shape是一个计算值。(TensorFlow 有时会尝试在图构建时评估这些计算值,但它会卡在tf.pack.)它推断形状TensorShape([Dimension(None), Dimension(None)]),这意味着“具有未知行数和列数的矩阵”,因为它知道这w_shape是一个长度向量2,所以结果normal_dist一定是二维的。

You have two options to deal with this. You can set the static shape as Ishamael suggests, but this requires you to know the shape at graph construction time. For example, the following may work:

您有两种选择来处理这个问题。您可以按照 Ishamael 的建议设置静态形状,但这需要您在图形构建时了解该形状。例如,以下可能有效:

normal_dist.set_shape([input_data.get_shape()[1], labels.get_shape()[1]])

Alternatively, you can pass validate_shape=Falseto the tf.Variableconstructor. This allows you to create a variable with a partially-defined shape, but it limits the amount of static shape information that can be inferred later on in the graph.

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

回答by Ishamael

The variable can have a dynamic shape. get_shape()returns the static shape.

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

In your case you have a tensor that has a dynamic shape, and currently happens to hold value that is 4x3 (but at some other time it can hold a value with a different shape -- because the shape is dynamic). To set the static shape, use set_shape(w_shape). After that the shape you set will be enforced, and the tensor will be a valid initial_value.

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

回答by Salvador Dali

Similar question is nicely explained in TF FAQ:

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

In TensorFlow, a tensor has both a static (inferred) shape and a dynamic (true) shape. The static shape can be read using the tf.Tensor.get_shapemethod: this shape is inferred from the operations that were used to create the tensor, and may be partially complete. If the static shape is not fully defined, the dynamic shape of a Tensor t can be determined by evaluating tf.shape(t).

在 TensorFlow 中,张量具有静态(推断)形状和动态(真实)形状。可以使用该tf.Tensor.get_shape方法读取静态形状 :该形状是从用于创建张量的操作中推断出来的,并且可能是部分完整的。如果静态形状没有完全定义,张量 t 的动态形状可以通过评估 来确定tf.shape(t)

So tf.shape()returns you a tensor, will always have a size of shape=(N,), and can be calculated in a session:

因此tf.shape()返回一个张量,其大小始终为shape=(N,),并且可以在会话中计算:

a = tf.Variable(tf.zeros(shape=(2, 3, 4)))
with tf.Session() as sess:
    print sess.run(tf.shape(a))

On the other hand you can extract the static shape by using x.get_shape().as_list()and this can be calculated anywhere.

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