开发者问题收集

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

2019-11-24
1575

我正在尝试将张量 input_image 转换为 numpy 数组。按照 这里 已经回答的问题和其他几个建议使用 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.

我想知道为什么前者可以工作而后者却不行。

2个回答

没有将符号张量“转换”为 numpy 数组之类的事情,因为后者无法保存与前者相同类型的信息。

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

评估常量( tf.constant )不需要任何输入数据,但评估其他表达式确实需要输入数据,因此您无法将其“转换”为 numpy 数组。

Dr. Snoopy
2019-11-24

只是补充(或详细说明)@MatiasValdenegro 所说的内容,

TensorFlow 遵循所谓的图形执行(或定义然后运行)。换句话说,当您编写 TensorFlow 程序时,它会定义一个称为数据流图的东西,它显示了您定义的操作是如何相互关联的。然后,您可以根据所追求的结果执行该图的片段。

让我们考虑两个例子。 (我正在切换到一个简单的 TensorFlow 程序而不是 Keras 位,因为它使事情变得更清晰 - 毕竟 K.get_session() 返回一个 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 )依赖于 占位符 时,您都无法执行它并获取结果,而无需将值提供给 所有 依赖的占位符。

示例 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() 来实现这一点。通过分析 此行 ,您可以看到 Keras Input 层实际上使用了占位符。

希望我的观点清楚,您 确实 需要向占位符输入一个值,才能成功评估 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}))
thushv89
2019-11-24