如果使用占位符指定的形状创建矩阵,则下面两个矩阵的乘积的形状为[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]
的形状,又如何获得合适的形状?
答案 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)
。