【问题标题】:How to create a custom loss function in Keras that evaluates prediction after each epoch?如何在 Keras 中创建一个自定义损失函数来评估每个时期后的预测?
【发布时间】:2020-02-21 19:02:03
【问题描述】:

我正在使用 Keras 开发一个神经网络,可以将英语句子翻译成一种自定义语言。为此,我想创建一个自定义损失函数,它对每个句子进行预测并评估它是否符合自定义语言的语法规则,如果不符合标准损失函数的价值。

如何在每个 epoch 之后而不是在编译期间评估张量?

下面是我的自定义损失函数。由于在模型编译期间还没有批次,y_pred 的形状为 (None, x, y) 并且无法评估以获得预测。我的想法是在编译期间分配一个标准损失函数,当批次到达时计算自定义损失。不幸的是,从未达到自定义损失。

def custom_loss(tokenizer, punishment_rate):

    def compile_loss(y_true, y_pred):
        shape = K.int_shape(y_pred)
        #standard loss function
        loss = K.sparse_categorical_crossentropy(y_true, y_pred)

        if shape[0] is not None:
            #THIS is never reached and that's the problem
            prediction = logits_to_text(K.eval(y_pred), tokenizer)

            #test if prediction complies to grammar rules
            compileable = compiles(prediction) ^ 1

            compile_error = compileable * punishment_rate
            loss =  K.sparse_categorical_crossentropy(y_true, y_pred, axis=-1) * (1 + compile_error)

        return loss

    return compile_loss

是否有任何解决方法可以仅在填充批次时评估张量?或者,在模型编译后通过回调更改损失函数,而不必重新编译模型?

【问题讨论】:

    标签: python-3.x machine-learning keras nlp loss-function


    【解决方案1】:

    根据keras source,您可以使用损失函数包装器来创建自定义损失函数类,然后将其无缝传递给您的模型。

    举个例子:

    #Import the wrapper
    from keras.losses import LossFunctionWrapper
    
    #Create your class extending the wrapper
    class MyLossFunction(LossFunctionWrapper):
    
    #Implement the constructor - here you can give extended arguments to it.
       def __init__(self, 
                     tokenizer, 
                     punishment_rate,
                     reduction=losses_utils.Reduction.SUM_OVER_BATCH_SIZE,
                     name='my_custom_text_function'):
            super(MyLossFunction, self).__init__(
                my_function, 
                name=name,
                reduction=reduction,
                tokenizer = tokenizer, 
                punishment_rate= punishment_rate)
    
    #Now you have to define your function "my_function":
    #Please, notice that ALL loss functions that follow keras model needs two arguments: 
    #y_true (correct result) and y_pred (the result obtained in the network).
    def my_function(y_true, y_pred, tokenizer, punishment_rate):
       shape = K.int_shape(y_pred)
       if shape[0] is not None:
           prediction = logits_to_text(K.eval(y_pred), tokenizer)
    
           #test if prediction complies to grammar rules
           compileable = compiles(prediction) ^ 1
    
           compile_error = compileable * punishment_rate
           return K.sparse_categorical_crossentropy(y_true, y_pred, axis=-1) * (1 + compile_error)
       return K.sparse_categorical_crossentropy(y_true, y_pred)
    
    

    然后你可以实例化它并在你的编译器中使用:

    custom_loss= MyLossFunction(tokenizer = ..., punishment_rate = ...)
    classifier.compile(optimizer=optimizer, 
                          loss=custom_loss, 
                          metrics= ['binary_accuracy'])
    

    【讨论】:

    • 感谢您的回答,但也许我不够清楚:我的问题不是如何创建自定义损失函数,而是让函数在批次到达时评估张量。永远无法到达 if 子句的内部,这就是问题所在。
    • 从我在源代码中看到的,损失函数总是被计算得最少(不知道为什么)。我将更改代码以符合它。测试它并判断它是否有效。
    • 我测试了它,但它不起作用。它从不进入内部 if 子句
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-03
    • 2018-11-24
    • 1970-01-01
    • 2018-12-28
    • 2020-02-20
    • 1970-01-01
    • 2018-12-26
    相关资源
    最近更新 更多