且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

在定制的keras损失中使用keras模型

更新时间:2023-12-02 15:27:22

首先,让我们尝试了解您收到的错误消息:

First, let's try to understand the error message you're getting:

AttributeError:张量"对象没有属性"ndim"

AttributeError: 'Tensor' object has no attribute 'ndim'

让我们看看Keras文档,找到Keras模型的 predict 方法.我们可以看到函数参数的描述:

Let's take a look at the Keras documentation and find the predict method of Keras model. We can see the description of the function parameters:

x:输入数据,作为一个Numpy数组.

x: the input data, as a Numpy array.

因此,该模型试图获取numpy arrayndims属性,因为它希望将数组作为输入.另一方面,Keras框架的自定义损失函数将tensors作为输入.因此,请勿在其中编写任何python代码-永远不会在评估期间执行该代码.只是调用此函数来构造计算图.

So, the model is trying to get a ndims property of a numpy array, because it expects an array as input. On other hand, the custom loss function of the Keras framework gets tensors as inputs. So, don't write any python code inside it - it will never be executed during evaluation. This function is just called to construct the computational graph.

好吧,现在我们找到了该错误消息的含义,我们如何在自定义损失函数中使用Keras模型?简单的!我们只需要获取模型的评估图即可.

Okay, now that we found out the meaning behind that error message, how can we use a Keras model inside custom loss function? Simple! We just need to get the evaluation graph of the model.

使用global关键字是不好的编码习惯.此外,现在在2020年,我们会在Keras中使用更好的功能API 与不必要的层.***使用这样的东西:

The use of global keyword is a bad coding practice. Also, now in 2020 we have better functional API in Keras that makes hacks with layers uneccessary. Better use something like this:

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):


Deprecated

Try something like this (only for Sequential models and very old 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_truey_pred将通过它进行最终操作.

Please note that the code above is not tested. However, the general idea will stay the same regardless of the implementation: you need to construct a graph, in which the y_true and y_pred will flow through it to the final operations.