【问题标题】:Dynamic size for tf.zeros() (for use with placeholders with None dimensions)tf.zeros() 的动态大小(用于无尺寸的占位符)
【发布时间】:2016-01-11 10:06:11
【问题描述】:

考虑以下代码:

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'

我发现如果我将 zeros 张量的第一个维度设置为 non-None,例如 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

【问题讨论】:

  • y=tf.zeros_like(x) 会发生什么?
  • @user728291 然后我得到一些形状 TensorShape([Dimension(None), Dimension(None)])yxy_stacked!?如果x 实际上应该与y 具有相同的形状,我在问题中提到的0 * x hack 似乎更有意义。在我的真实应用程序中,当然一切都更加复杂,我必须通过切片、复制和连接0 * &lt;placeholder&gt; 的结果来构造零张量,以获得我需要的形状的张量。

标签: tensorflow


【解决方案1】:

制作具有与另一个张量相同形状的零张量的推荐方法是使用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)

【讨论】:

  • 第二维不匹配怎么办?例如。我希望x 拥有shape=[None, 4]y 拥有shape=[None, 7]。 (在我的应用程序中,这些张量的第二维是独立的配置参数。我什至无法提前知道哪个更大。)抱歉,一开始在问题中没有提到这一点..
  • 更新了我的答案以涵盖您的情况。
  • 请注意,在 tf 1.x+ 上,tf.pack 被重命名为 tf.stack
猜你喜欢
  • 1970-01-01
  • 2016-10-27
  • 2019-10-09
  • 2019-06-28
  • 2015-09-04
  • 2020-07-30
  • 1970-01-01
  • 2022-11-28
  • 2013-03-17
相关资源
最近更新 更多