使用占位符创建时,Tensor的形状为[无,无]

时间:2018-09-04 11:16:41

标签: python tensorflow

如果使用占位符指定的形状创建矩阵,则下面两个矩阵的乘积的形状为[None,None],但是使用普通文字创建时,矩阵的形状正确:

带文字:

r1 = 3
r1f = 3.0
c2 = 2

#r1 = tf.placeholder(tf.int32)
#r1f = tf.cast(r1, tf.float32)
#c2 = tf.placeholder(tf.int32)

m1 = tf.reshape(tf.range(r1f), (r1, 1))
m2 = tf.ones((1, c2))
t = tf.matmul(m1, m2)
s0 = tf.constant(t.shape[0].value)

with tf.Session() as sess:
    print(sess.run(s0))
    #print(sess.run(s0, feed_dict={r1 : 3, c2 : 2}))


>>> 3

带占位符:

#r1 = 3
#r1f = 3.0
#c2 = 2

r1 = tf.placeholder(tf.int32)
r1f = tf.cast(r1, tf.float32)
c2 = tf.placeholder(tf.int32)

m1 = tf.reshape(tf.range(r1f), (r1, 1))
m2 = tf.ones((1, c2))
t = tf.matmul(m1, m2)
s0 = tf.constant(t.shape[0].value)

with tf.Session() as sess:
    #print(sess.run(s0))
    print(sess.run(s0, feed_dict={r1 : 3, c2 : 2}))


>>> ValueError: None values not supported.

然后我在图形t.shape.as_list()而不是t.shape[0].value上运行图形,但错误是形状为[None, None]

我正在运行tensorflow 1.10.1。

我的问题是:为什么在第二种情况下我得到[None, None]的形状,又如何获得合适的形状?

3 个答案:

答案 0 :(得分:1)

  

如何获得合适的形状?

张量tf.matmul(m1, m2)的动态形状可以这样获得。但是必须将价值带给它。

with tf.Session() as sess:
    print(tf.shape(t))
    #print(sess.run(t, feed_dict={r1 : 3, c2 : 2}))
    print(sess.run(tf.shape(t), feed_dict={r1 : 3, c2 : 2}))

答案 1 :(得分:1)

使用TensorFlow时,请务必记住有两个阶段:

  • 图形创建阶段。创建占位符,常量,变量并创建一些将应用于它们的操作时。
  • 计算阶段。当您调用sess.run时,图形中的实际计算就会发生。

在您执行t.shape[0].value的代码段中,您试图在图形创建阶段访问张量的形状。 TensorFlow总是尽可能在图创建阶段尝试预测张量形状。但是,由于您将张量整形应用于使用占位符值作为新形状的张量整形,因此在 computation phase 之前,无法推断结果的形状,因为占位符值未知。

要缓解此问题,您必须将张量的形状视为另一个张量,而不是在图创建阶段尝试访问其数值。

请查看更新的代码:

import tensorflow as tf

r1 = tf.placeholder(tf.int32)
r1f = tf.cast(r1, tf.float32)
c2 = tf.placeholder(tf.int32)

m1 = tf.reshape(tf.range(r1f), (r1, 1))
m2 = tf.ones((1, c2))
t = tf.matmul(m1, m2)
s0 = tf.shape(t)[0]

print(type(s0)) # <class 'tensorflow.python.framework.ops.Tensor'> # s0 is a Tensor!

with tf.Session() as sess:
    #print(sess.run(s0))
    print(sess.run(s0, feed_dict={r1 : 3, c2 : 2}))
  

为什么它适用于文字,但不适用于占位符

由于在图形创建阶段就知道了普通整数变量的值,因此Tensorflow可以预测在图形创建阶段进行整形运算结果的形状。因此,可以在图形创建期间访问结果的形状。

我们来看一个例子:

r1_placeholder = tf.placeholder(tf.int32)
r1f = tf.cast(r1_placeholder, tf.float32)
r1_int = 3

m1 = tf.reshape(tf.range(r1f), (r1_placeholder, 1))
print(m1.shape) # (?, 1) shape is unknown at graph creation stage, since r1_placeholder is a placeholder


m1 = tf.reshape(tf.range(r1f), (r1_int, 1))
print(m1.shape) # (3, 1) shape is known at graph creation stage, since r1_int is just a number
  

那么为什么它可以与tf.shape(t)一起使用而不能与t.shape一起使用?

t.shape可让您访问TensorFlow在图形创建阶段推断的张量形状,该状态可能是部分或完全未知的。

tf.shape(t)在您的图形中创建一个运算,该运算将在计算阶段

计算张量的实际形状

答案 2 :(得分:0)

占位符张量的默认形状为None(除非您指定它)。 (请参见here

因此,即使您在运行时为张量提供值,您的形状还是(None, None)