在自定义 keras 损失中使用 keras 模型
Using a keras model in a custom keras loss
我有一个名为 e
的常规 keras 模型,我想在我的自定义损失函数中比较其 y_pred
和 y_true
的输出。
from keras import backend as K
def custom_loss(y_true, y_pred):
return K.mean(K.square(e.predict(y_pred)-e.predict(y_true)), axis=-1)
我收到错误:AttributeError: 'Tensor' object has no attribute 'ndim'
这是因为 y_true
和 y_pred
都是张量对象,并且 keras.model.predict
期望传递一个 numpy.array
.
知道如何在自定义损失函数中成功使用 keras.model
吗?
如果需要,我愿意获取指定层的输出,或者将我的 keras.model
转换为 tf.estimator
对象(或其他任何对象)。
首先,让我们试着理解您收到的错误消息:
AttributeError: 'Tensor' object has no attribute 'ndim'
我们看一下Keras文档,找到Keras模型的predict方法。我们可以看到函数参数的说明:
x: the input data, as a Numpy array.
因此,该模型正在尝试获取 numpy array
的 ndims
属性,因为它需要一个数组作为输入。另一方面,Keras 框架的自定义损失函数将 tensors
作为输入。因此,不要在其中编写任何 python 代码 - 它永远不会在评估期间执行。这个函数只是为了构建计算图而被调用。
好的,既然我们知道了错误消息背后的含义,我们如何在自定义损失函数中使用 Keras 模型?简单的!我们只需要得到模型的评估图即可。
更新
使用 global
关键字是一种糟糕的编码习惯。此外,现在到 2020 年,我们在 Keras 中有了更好的 functional API,这使得对层的破解变得不必要。最好使用这样的东西:
from keras import backend as K
def make_custom_loss(model):
"""Creates a loss function that uses `model` for evaluation
"""
def custom_loss(y_true, y_pred):
return K.mean(K.square(model(y_pred) - model(y_true)), axis=-1)
return custom_loss
custom_loss = make_custom_loss(e)
已弃用
尝试这样的事情(仅适用于 Sequential
型号和非常旧的 API):
def custom_loss(y_true, y_pred):
# Your model exists in global scope
global e
# Get the layers of your model
layers = [l for l in e.layers]
# Construct a graph to evaluate your other model on y_pred
eval_pred = y_pred
for i in range(len(layers)):
eval_pred = layers[i](eval_pred)
# Construct a graph to evaluate your other model on y_true
eval_true = y_true
for i in range(len(layers)):
eval_true = layers[i](eval_true)
# Now do what you wanted to do with outputs.
# Note that we are not returning the values, but a tensor.
return K.mean(K.square(eval_pred - eval_true), axis=-1)
请注意,以上代码未经测试。然而,无论实现如何,总体思路将保持不变:您需要构建一个图形,其中 y_true
和 y_pred
将通过它流向最终操作。
我有一个名为 e
的常规 keras 模型,我想在我的自定义损失函数中比较其 y_pred
和 y_true
的输出。
from keras import backend as K
def custom_loss(y_true, y_pred):
return K.mean(K.square(e.predict(y_pred)-e.predict(y_true)), axis=-1)
我收到错误:AttributeError: 'Tensor' object has no attribute 'ndim'
这是因为 y_true
和 y_pred
都是张量对象,并且 keras.model.predict
期望传递一个 numpy.array
.
知道如何在自定义损失函数中成功使用 keras.model
吗?
如果需要,我愿意获取指定层的输出,或者将我的 keras.model
转换为 tf.estimator
对象(或其他任何对象)。
首先,让我们试着理解您收到的错误消息:
AttributeError: 'Tensor' object has no attribute 'ndim'
我们看一下Keras文档,找到Keras模型的predict方法。我们可以看到函数参数的说明:
x: the input data, as a Numpy array.
因此,该模型正在尝试获取 numpy array
的 ndims
属性,因为它需要一个数组作为输入。另一方面,Keras 框架的自定义损失函数将 tensors
作为输入。因此,不要在其中编写任何 python 代码 - 它永远不会在评估期间执行。这个函数只是为了构建计算图而被调用。
好的,既然我们知道了错误消息背后的含义,我们如何在自定义损失函数中使用 Keras 模型?简单的!我们只需要得到模型的评估图即可。
更新
使用 global
关键字是一种糟糕的编码习惯。此外,现在到 2020 年,我们在 Keras 中有了更好的 functional API,这使得对层的破解变得不必要。最好使用这样的东西:
from keras import backend as K
def make_custom_loss(model):
"""Creates a loss function that uses `model` for evaluation
"""
def custom_loss(y_true, y_pred):
return K.mean(K.square(model(y_pred) - model(y_true)), axis=-1)
return custom_loss
custom_loss = make_custom_loss(e)
已弃用
尝试这样的事情(仅适用于 Sequential
型号和非常旧的 API):
def custom_loss(y_true, y_pred):
# Your model exists in global scope
global e
# Get the layers of your model
layers = [l for l in e.layers]
# Construct a graph to evaluate your other model on y_pred
eval_pred = y_pred
for i in range(len(layers)):
eval_pred = layers[i](eval_pred)
# Construct a graph to evaluate your other model on y_true
eval_true = y_true
for i in range(len(layers)):
eval_true = layers[i](eval_true)
# Now do what you wanted to do with outputs.
# Note that we are not returning the values, but a tensor.
return K.mean(K.square(eval_pred - eval_true), axis=-1)
请注意,以上代码未经测试。然而,无论实现如何,总体思路将保持不变:您需要构建一个图形,其中 y_true
和 y_pred
将通过它流向最终操作。