将张量转换为 numpy 数组时出错
我正在尝试将张量 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.
我想知道为什么前者可以工作而后者却不行。
没有将符号张量“转换”为 numpy 数组之类的事情,因为后者无法保存与前者相同类型的信息。
当您使用
eval()
或
session.run()
时,您正在做的是
评估
符号表达式以获得数值结果,该结果是一个 numpy 数组,但这不是
转换
。评估表达式可能需要也可能不需要额外的输入数据(这就是
feed_dict
的用途),具体取决于表达式。
评估常量(
tf.constant
)不需要任何输入数据,但评估其他表达式确实需要输入数据,因此您无法将其“转换”为 numpy 数组。
只是补充(或详细说明)@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}))