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

时间:2019-11-24 18:45:01

标签: python-3.x numpy tensorflow keras tensor

我正在尝试将张量的input_image转换为numpy数组。在已经回答的问题here和其他一些建议使用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 个答案:

答案 0 :(得分:2)

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

当您使用eval()session.run()时,您正在做的是求值以获取数字结果的符号表达式,该表达式是一个numpy数组,但这不是转化。根据表达式,求值表达式可能需要也可能不需要其他输入数据(这就是feed_dict的作用)。

求一个常量(tf.constant)不需要任何输入数据,但是求另一个表达式的确需要输入数据,因此您不能将其“转换”为numpy数组。

答案 1 :(得分:1)

只需添加(或详细说明)@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)依赖于placeholder时,您都无法执行它并获得结果,而无需将值馈给所有所有从属占位符。

示例2

定义tf.constant(1)时,它不依赖任何内容。换句话说,您不需要feed_dict,可以直接在其上运行eval()sess.run()

更新:为什么需要input_image

的feed_dict的进一步说明

TLDR:您需要一个feed_dict,因为您产生的TensorInput层产生。

您的input_image基本上是您通过向Input层输入内容而得到的张量。通常在Keras中,您不会接触到内部占位符级别的详细信息。但是您可以通过使用model.fit()model.evaluate()来实现。通过分析this line,您可以看到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}))