如何在不启用 keras 中的 run_eagerly 标志的情况下将张量转换为 numpy 数组
Posted
技术标签:
【中文标题】如何在不启用 keras 中的 run_eagerly 标志的情况下将张量转换为 numpy 数组【英文标题】:how to convert a tensor to a numpy array without enabling the run_eagerly flag in keras 【发布时间】:2021-11-03 03:40:36 【问题描述】:我正在编写自己的指标回调函数,我使用 sklearn 来计算指标,为此我需要将 y_true 和 y_pred 张量作为 numpy 数组。我的函数如下所示:
def precision_macro(y_true, y_pred):
# get the y_true and y_pred tensors as 1-D numpy array
y_true_array = np.array(true)
y_pred_array = np.array(pred)
....................
....................
CALCULATIONS
....................
....................
precision = precision_score(y_true_array, y_pred_array, average="macro", zero_division=0)
return precision
如果我在编译调用期间像这样设置run_eargly=True
,一切正常:
model.compile(optimizer=keras.optimizers.RMSprop(learning_rate=lr),
loss='binary_crossentropy',
metrics=model_metrics,
run_eagerly=True)
但这比将标志设置为 False 成本高且速度慢,但如果我不将标志设置为 True,我的转换就会出现问题。以下是我在没有将 run_eagrly 标志设置为 True 的情况下尝试过的事情,但没有奏效:
如果我只是不设置 run_eagerly 标志,我会收到以下错误
NotImplementedError:无法将符号张量 (ExpandDims:0) 转换为 numpy 数组。此错误可能表明您正在尝试将张量传递给 NumPy 调用,这是不受支持的
然后我尝试了
import tensorflow.keras.backend as K
def precision_macro(y_true, y_pred):
# get the y_true and y_pred tensors as 1-D numpy array
y_true_array = K.eval(y_true)
y_pred_array = K.eval(y_pred)
....................
或者我尝试在张量上调用 numpy 函数
def precision_macro(y_true, y_pred):
# get the y_true and y_pred tensors as 1-D numpy array
y_true_array = y_true.numpy()
y_pred_array = y_pred.numpy()
....................
我也尝试在这样的会话中运行它:
import tensorflow.keras.backend as K
import tensorflow as tf
def precision_macro(y_true, y_pred):
sess = tf.compat.v1.Session()
# get the y_true and y_pred tensors as 1-D numpy array
with sess.as_default():
y_true_array = K.eval(y_true)
y_pred_array = K.eval(y_pred)
....................
对于所有 thress 情况,我都会收到以下错误
AttributeError: 'Tensor' 对象没有属性 'numpy'
我试着这样运行它:
import tensorflow.keras.backend as K
import tensorflow as tf
def precision_macro(y_true, y_pred):
sess = tf.compat.v1.Session()
# get the y_true and y_pred tensors as 1-D numpy array
with sess.as_default():
y_true_array = sess.run(y_true)
y_pred_array = sess.run(y_pred)
....................
我收到以下错误
InvalidArgumentError:找到 2 个根错误。 (0) 无效参数:您必须使用 dtype 资源为占位符张量“迭代器”提供值 (1) 无效参数:您必须使用 dtype 资源为占位符张量“迭代器”提供值
我尝试将 numpy 从 1.19.5
降级到 1.18.5
但这也没有用,我得到了同样的错误
正在尝试tf.numpy_function()
import tensorflow as tf
def numpy_function(y_true, y_pred):
# get the y_true and y_pred tensors as 1-D numpy array
y_true_array = y_true
y_pred_array = y_pred
.... calculations ....
precision = precision_score(y_true_array, y_pred_array, average="macro", zero_division=0)
precision_per_class.append(precision_score(y_true_array, y_pred_array, average=None, zero_division=0))
return precision
我作为度量传递的函数
@tf.function
def precision_macro(y_true, y_pred):
score = tf.numpy_function(numpy_function, [y_true, y_pred], tf.float32)
return score
我这样编译,model_metrics = ['accuracy', precision_macro]
model.compile(optimizer=keras.optimizers.RMSprop(learning_rate=lr),
loss='binary_crossentropy',
metrics=model_metrics)
我收到以下错误
TypeError: 'Tensor' 对象不支持项目分配
我正在使用keras = 2.6.
tensorflow = 2.6
numpy = 1.19.5
那么,谁能帮帮我?
【问题讨论】:
我还尝试在将 Tenosr 转换为 numpy 数组之前启用急切执行,然后通过调用 tf.compat.v1.enable_eager_execution() 和 tf.compat 在执行的其余部分禁用它。 v1.disable_eager_execution() 并且它不起作用,如果我在启用后直接打印 tf.executing_eagerly() 它仍然打印 False! 【参考方案1】:你可以试试tf.numpy_function
。它接收一个函数作为参数,并在传递给函数之前自动将张量转换为 numpy 数组,并将函数的输出转换回张量。见例子:
def my_numpy_func(y_true, y_pred):
# y_true and y_pred are already numpy arrays
# put all numpy or sklearn codes here
return metrics.mean_squared_error(y_true, y_pred)
@tf.function
def custom_metric(y_true, y_pred):
# y_true and y_pred are tensors
# no numpy or sklearn code is allowed here
score = tf.numpy_function(my_numpy_func, [y_true, y_pred], tf.float32)
return score
它将允许您拥有run_eagerly = False
,并且理论上运行速度更快,因为除了此自定义指标之外的大多数计算都在图形模式下工作。
【讨论】:
我禁用了 run_eagerly 并尝试过。我收到此错误 >TypeError: 'Tensor' object does not support item assignment 我在 my_numpy_func 中添加了一个 breakpoint() 调用,并且参数仍然作为张量传递! 如果我启用 run_eagerly 参数将作为 numpy 数组传递。所以也许问题是我可以只为度量计算启用标志吗? 请确保首先删除所有tf.compat.v1.X
或 tensorflow v1 代码(并且不要再次尝试这些代码),因为这些代码在 tensorflow v2 中有错误并会破坏。然后,请在您尝试tf.numpy_function
时发布指标代码,即precision_macro
和my_numpy_func
,包括显示您如何调用model.compile
。
例如,我可以重现您的错误的一种方法是执行 model.compile(loss='mse',optimizer='sgd',metrics=[my_numpy_func])
,而不是您应该调用 model.compile(loss='mse',optimizer='sgd',metrics=[custom_metric])
以使其正常工作。
你能检查一下问题的最后一部分吗,我修改了它,我没有使用tf.compat.v1
的任何内容以上是关于如何在不启用 keras 中的 run_eagerly 标志的情况下将张量转换为 numpy 数组的主要内容,如果未能解决你的问题,请参考以下文章
Keras - 如何在不改变纵横比的情况下使用 ImageDataGenerator
如何使用 Theano 启用 Keras 以利用多个 GPU