tf.zeros() 的动态大小(用于具有 None 尺寸的占位符)
Dynamic size for tf.zeros() (for use with placeholders with None dimensions)
考虑以下代码:
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'
我发现如果我将零张量的第一维设置为非 None,例如 1:
,它不会产生错误
x = tf.placeholder("float", shape=[None, 4])
y = tf.zeros([1, 4], "float")
xy_stacked = tf.concat(1, [x, y])
但是随后生成的 xy_stacked
张量 t运行 适合这个大小:
TensorShape([Dimension(None), Dimension(4)])
TensorShape([Dimension(1), Dimension(4)])
TensorShape([Dimension(1), Dimension(8)])
如何用零填充占位符张量,以便在此示例中得到形状为 TensorShape([Dimension(None), Dimension(8)])
的张量?
到目前为止我发现的唯一 "solutions" 是以下内容之一:
x = tf.placeholder("float", shape=[None, 4])
y = 0 * x
xy_stacked = tf.concat(1, [x, y])
或者简单地将 y
声明为占位符并始终传递正确大小的零数组。
但这两个看起来都不是问题的干净解决方案,而且在比这个简单示例更复杂的应用程序中,这样的 hacks 很快就会失控。
我正在使用 tensorflow-0.6.0-py3
。
制作与另一个张量 相同 形状的零张量的推荐方法是使用 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,它应该很快就会被修复。
编辑: 在您的评论中,您询问了如何处理零张量的形状基于但不同于[=39 的情况=] 原始张量。这也是可能的,使用 tf.shape()
and tf.stack()
to build the dimensions, and 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 = 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'
我发现如果我将零张量的第一维设置为非 None,例如 1:
,它不会产生错误x = tf.placeholder("float", shape=[None, 4])
y = tf.zeros([1, 4], "float")
xy_stacked = tf.concat(1, [x, y])
但是随后生成的 xy_stacked
张量 t运行 适合这个大小:
TensorShape([Dimension(None), Dimension(4)])
TensorShape([Dimension(1), Dimension(4)])
TensorShape([Dimension(1), Dimension(8)])
如何用零填充占位符张量,以便在此示例中得到形状为 TensorShape([Dimension(None), Dimension(8)])
的张量?
到目前为止我发现的唯一 "solutions" 是以下内容之一:
x = tf.placeholder("float", shape=[None, 4])
y = 0 * x
xy_stacked = tf.concat(1, [x, y])
或者简单地将 y
声明为占位符并始终传递正确大小的零数组。
但这两个看起来都不是问题的干净解决方案,而且在比这个简单示例更复杂的应用程序中,这样的 hacks 很快就会失控。
我正在使用 tensorflow-0.6.0-py3
。
制作与另一个张量 相同 形状的零张量的推荐方法是使用 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,它应该很快就会被修复。
编辑: 在您的评论中,您询问了如何处理零张量的形状基于但不同于[=39 的情况=] 原始张量。这也是可能的,使用 tf.shape()
and tf.stack()
to build the dimensions, and 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)