将张量转换为 numpy 数组时出错

error in converting tensor to numpy array

我正在尝试将张量 input_image 转换为 numpy array.Following 已经回答的问题 和其他几个建议使用 input_image.eval()或等效于此转换的 sess.run(),我做了同样的事情,但它抛出了一个错误,显然期望 sess.run() 的值是 feed_dict。但是因为在这里我没有尝试 运行 依赖于未知值的操作,所以我认为这里不需要 feed_dict 因为我在这里所做的只是转换。

此外,为了检查我也尝试使用相同的方法转换它上面的 tf.constant([1,2,3]) 值,尽管它的数据类型是与 input_image 相同。这是我的代码,它是较大脚本的一部分:

def call(self, x):
    input_image = Input(shape=(None, None, 3))
    print(input_image.shape)
    print(type(tf.constant([1,2,3])))
    print(type(input_image))
    print(type(K.get_session().run(tf.constant([1,2,3]))))
    print(type(K.get_session().run(input_image)))

这是错误:

(?, ?, ?, 3)
<class 'tensorflow.python.framework.ops.Tensor'>
<class 'tensorflow.python.framework.ops.Tensor'>
<class 'numpy.ndarray'>
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/dist-packages/tensorflow_core/python/client/session.py", line 1365, in _do_call
    return fn(*args)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow_core/python/client/session.py", line 1350, in _run_fn
    target_list, run_metadata)
  File "/usr/local/lib/python3.6/dist-packages/tensorflow_core/python/client/session.py", line 1443, in _call_tf_sessionrun
    run_metadata)
tensorflow.python.framework.errors_impl.InvalidArgumentError: 2 root error(s) found.
  (0) Invalid argument: You must feed a value for placeholder tensor 'input_1' with dtype float and shape [?,?,?,3]
     [[{{node input_1}}]]
     [[input_1/_1051]]
  (1) Invalid argument: You must feed a value for placeholder tensor 'input_1' with dtype float and shape [?,?,?,3]
     [[{{node input_1}}]]
0 successful operations.
0 derived errors ignored.

我想知道为什么前者会工作而后者不会。

没有 "converting" numpy 数组的符号张量这样的东西,因为后者不能保存与前者相同类型的信息。

当你使用eval()session.run()时,你所做的是评估一个符号表达式以获得数值结果,这是一个numpy数组,但这不是 转化 。计算表达式可能需要也可能不需要额外的输入数据(这就是 feed_dict 的用途),具体取决于表达式。

计算常量 (tf.constant) 不需要任何输入数据,但计算你的其他表达式确实需要输入数据,所以你不能 "convert" 将它转换为 numpy 数组。

只是添加(或详细说明)@MatiasValdenegro 所说的,

TensorFlow 遵循称为图形执行(或定义-然后-运行)的东西。换句话说,当你编写一个 TensorFlow 程序时,它定义了一个叫做数据流图的东西,它显示了你定义的操作是如何相互关联的。然后你根据你想要的结果执行该图的点点滴滴。

让我们考虑两个例子。 (我正在切换到一个简单的 TensorFlow 程序而不是 Keras 位,因为它使事情更清楚 - 毕竟 K.get_session() returns 一个 Session 对象)。

示例 1

假设您有以下程序。

import tensorflow as tf

a = tf.placeholder(shape=[2,2], dtype=tf.float32)
b = tf.constant(1, dtype=tf.float32)
c = a * b

# Wrong: This is what you're doing essentially when you do sess.run(input_image)
with tf.Session() as sess:
    print(sess.run(c))

# Right: You need to feed values that c is dependent on
with tf.Session() as sess:
    print(sess.run(c, feed_dict={a: np.array([[1,2],[2,3]])}))

每当生成的张量(例如 c)依赖于 placeholder 时,如果不向 all 提供值,则无法执行它并获得结果从属占位符。

示例 2

当您定义一个 tf.constant(1) 时,它不依赖于任何东西。换句话说,你不需要 feed_dict 并且可以直接 运行 eval()sess.run() 就可以了。

更新:进一步解释为什么 input_image

需要 feed_dict

TLDR:您需要一个 feed_dict,因为您得到的 Tensor 是由 Input 层生成的。

你的 input_image 基本上是你通过向 Input 层提供一些东西得到的结果张量。通常在 Keras 中,您不会接触到内部占位符级别的详细信息。但是您可以通过使用 model.fit()model.evaluate() 来做到这一点。通过分析this line.

可以看出Keras Input层其实是使用了占位符

希望我明确指出您 do 需要向占位符输入一个值才能成功评估 Input 层的输出。因为它基本上包含一个占位符。

更新 2:如何为您的 Input 层提供数据

因此,看来您可以通过以下方式将 feed_dict 与 Keras Input 层一起使用。您无需定义 shape 参数,而是直接将占位符传递给 tensor 参数,这将绕过图层中的内部占位符创建。

from tensorflow.keras.layers import InputLayer
import numpy as np
import tensorflow.keras.backend as K

x = tf.placeholder(shape=[None, None, None, 3], dtype=tf.float32)
input_image = Input(tensor=x)
arr = np.array([[[[1,1,1]]]])
print(arr.shape)
print(K.get_session().run(input_image, feed_dict={x: arr}))