tf.zeros()的动态大小(用于具有无维度的占位符)

时间:2016-01-11 10:06:11

标签: tensorflow

请考虑以下代码:

x = tf.placeholder("float", shape=[42, 4])
y = tf.zeros([42, 4], "float")
xy_stacked = tf.concat(1, [x, y])

print(x.get_shape())
print(y.get_shape())
print(xy_stacked.get_shape())

这将产生以下输出,如预期的那样:

TensorShape([Dimension(42), Dimension(4)])
TensorShape([Dimension(42), Dimension(4)])
TensorShape([Dimension(42), Dimension(8)])

但是,如果占位符具有动态维度,该维度在运行时由传递给feed_dict=的值确定,如占位符通常那样:

x = tf.placeholder("float", shape=[None, 4])
y = tf.zeros([None, 4], "float")
xy_stacked = tf.concat(1, [x, y])

这会为tf.zeros([None, 4], "float")产生错误。显然Dimension(None)不允许tf.zeros

TypeError                                 Traceback (most recent call last)
<ipython-input-24-277eca38a392> in <module>()
      2 
      3 x = tf.placeholder("float", shape=[None, 4])
----> 4 y = tf.zeros([None, 4], "float")
      5 xy_stacked = tf.concat(1, [x, y])
      6 
[...]

/usr/local/lib/python3.4/dist-packages/numpy/core/_methods.py in _prod(a, axis, dtype, out, keepdims)
     33 
     34 def _prod(a, axis=None, dtype=None, out=None, keepdims=False):
---> 35     return umr_prod(a, axis, dtype, out, keepdims)
     36 
     37 def _any(a, axis=None, dtype=None, out=None, keepdims=False):

TypeError: unsupported operand type(s) for *: 'NoneType' and 'int'

我已经发现,如果我将零点张量的第一个维度设置为非无,例如1:

,它就不会产生错误
x = tf.placeholder("float", shape=[None, 4])
y = tf.zeros([1, 4], "float")
xy_stacked = tf.concat(1, [x, y])

但随后生成的xy_stacked张量将被截断为此大小:

TensorShape([Dimension(None), Dimension(4)])
TensorShape([Dimension(1), Dimension(4)])
TensorShape([Dimension(1), Dimension(8)])

如何用零填充占位符张量,以便在此示例中得到一个形状张量TensorShape([Dimension(None), Dimension(8)])

到目前为止,我发现的唯一“解决方案”是以下内容:

x = tf.placeholder("float", shape=[None, 4])
y = 0 * x
xy_stacked = tf.concat(1, [x, y])

或者只是将y声明为占位符并始终传递正确大小的零数组。

但对于这个问题来说,这两个问题看起来都不是一个干净的解决方案,并且像这样的黑客在一个比这个简单的例子更复杂的应用程序中快速失控。

我正在使用tensorflow-0.6.0-py3

1 个答案:

答案 0 :(得分:32)

使用相同形状作为另一个张量的零张量的推荐方法是使用tf.zeros_like() op:

x = tf.placeholder(tf.float32, shape=[None, 4])
y = tf.zeros_like(x)

根据Tensor.get_shape()生成的张量y似乎具有[None, None]形状,但在运行时它将扩展为与x相同的形状:

print y.get_shape()
# ==> TensorShape([Dimension(None), Dimension(None)])

sess = tf.Session()
y_result = sess.run(y, feed_dict={x: np.random.rand(4, 4)})

print y_result.shape
# ==> (4, 4)

返回[None, None]静态形状,因为形状推断尚未专门用于tf.zeros_like()。我已经提交了GitHub issue for that,应尽快解决。

编辑:在评论中,您询问如何处理零张量的形状基于但原始张量不同的情况。这也可以使用tf.shape()tf.stack()来构建维度,并使用tf.fill()来生成零张量:

x = tf.placeholder(tf.float32, shape=[None, 4])

# Use tf.shape() to get the runtime size of `x` in the 0th dimension.
zeros_dims = tf.stack([tf.shape(x)[0], 7])

y = tf.fill(zeros_dims, 0.0)

sess = tf.Session()
y_result = sess.run(y, feed_dict={x: np.random.rand(4, 4)})
print y_result.shape
# ==> (4, 7)