【问题标题】:tf.reshape is not giving ?(None) for first elementtf.reshape 没有为第一个元素提供 ?(None)
【发布时间】:2019-10-30 07:39:53
【问题描述】:

我是 tensorflow 的新手,我有下面这样的张量,

a = tf.constant([[1, 2, 3], [4, 5, 6]])

a.shape 的输出是

TensorShape([Dimension(2), Dimension(3)])

对于我的计算过程,我想将张量重塑为 (?, 2, 3)

我无法将其重塑为所需的格式。

我试过了,

tf.reshape(a, [-1, 2, 3])

但它会返回,

<tf.Tensor 'Reshape_18:0' shape=(1, 2, 3) dtype=int32> # 1 has to be replaced by ?

我进一步尝试,

tf.reshape(a, [-1, -1, 2, 3])

它返回,

<tf.Tensor 'Reshape_19:0' shape=(?, ?, 2, 3) dtype=int32> # two ? are there

如何获得想要的结果?

对不起,如果这听起来很简单的问题。

【问题讨论】:

  • 还有什么问题?任何期望形状(?, 2, 3) 的东西也应该接受形状(1, 2, 3)。你有例外吗?
  • 是的。我得到一个例外,说张量的外部尺寸为 1 并且应该是 None 。这是 tensorflow 服务模型的一部分,它期望最外层维度为无,因此它可以提供批量输出。如果是一个,那么它只能提供一个输出。

标签: python python-3.x tensorflow


【解决方案1】:

“问题”是 TensorFlow 尽可能多地进行形状推断,这通常是件好事,但如果您明确想要有一个 None 维度,它会使它变得更加复杂。这不是一个理想的解决方案,但一种可能的解决方法是使用tf.placeholder_with_default,例如:

import tensorflow as tf

a = tf.constant([[1, 2, 3], [4, 5, 6]])
# This placeholder is never actually fed
z = tf.placeholder_with_default(tf.zeros([1, 1, 1], a.dtype), [None, 1, 1])
b = a + z
print(b)
# Tensor("add:0", shape=(?, 2, 3), dtype=int32)

或其他类似的选项,只是通过重塑:

import tensorflow as tf

a = tf.constant([[1, 2, 3], [4, 5, 6]])
s = tf.placeholder_with_default([1, int(a.shape[0]), int(a.shape[1])], [3])
b = tf.reshape(a, s)
b.set_shape(tf.TensorShape([None]).concatenate(a.shape))
print(b)
# Tensor("Reshape:0", shape=(?, 2, 3), dtype=int32)

【讨论】:

  • 感谢您的解决方案,我会检查并通知您。
  • 你能解释一下它是如何工作的吗? z = tf.placeholder_with_default(tf.zeros([1, 1, 1], a.dtype), [None, 1, 1]) 这一行。特别是 [1, 1, 1]
  • @MohamedThasinah 它的作用是创建一个形状为(?, 1, 1) 的占位符,默认值为[[[0]]],实际上它的形状为(1, 1, 1)。由于原则上您可以为占位符提供不同的值,TensorFlow 不能假设实际形状总是(1, 1, 1),因此它必须考虑第一个维度可以具有任何大小,这将导致广播添加使用a 给出新的初始? 维度。 “诀窍”是您实际上从未为占位符提供值,因此它就像一个具有部分未知形状的常量。
  • @MohamedThasinah 也就是说,如果可能的话,通常不是检查确切的形状相等性,而是检查形状兼容性,而不是使用tf.TensorShape.is_compatible_with
【解决方案2】:

你试图完成的任务根本上是错误的。您正在尝试从完全已知的形状 see the documentation 制作一个部分已知的形状。

当您在图形构建过程中不知道完全已知的形状时,将使用部分已知的形状。无论如何,您必须在执行图形时指定实际形状。因此,将任何形状完全已知的张量转换为部分已知的张量是没有意义的。

如果您想对一些部分已知的形状执行操作,请使用广播(例如,对形状为 (1, 2, 3)(None, 2, 3) 的张量进行add 操作会产生形状为 (None, 2, 3) 的张量)

【讨论】:

    猜你喜欢
    • 2010-09-23
    • 2018-11-28
    • 1970-01-01
    • 2014-02-12
    • 2018-10-25
    • 1970-01-01
    • 2018-09-02
    • 1970-01-01
    相关资源
    最近更新 更多