【问题标题】:How to get results from custom loss function in Keras?如何从 Keras 中的自定义损失函数中获取结果?
【发布时间】:2018-04-27 11:25:17
【问题描述】:

我想在 Python 中实现一个自定义损失函数,它应该像下面的伪代码一样工作:

aux = | Real - Prediction | / Prediction
errors = []
if aux <= 0.1:
 errors.append(0)
elif aux > 0.1 & <= 0.15:
 errors.append(5/3)
elif aux > 0.15 & <= 0.2:
 errors.append(5)
else:
 errors.append(2000)
return sum(errors)

我开始这样定义指标:

def custom_metric(y_true,y_pred):
    # y_true:
    res = K.abs((y_true-y_pred) / y_pred, axis = 1)
    ....

但我不知道如何获取 ifelse 的 res 值。另外我想知道什么必须返回函数。

谢谢

【问题讨论】:

    标签: python tensorflow machine-learning keras loss


    【解决方案1】:

    我也想知道什么必须返回函数。

    自定义指标可以在编译步骤中传递。

    该函数需要将(y_true, y_pred) 作为参数并返回一个tensor 值。

    但我不知道如何获取 if 和 else 的 res 值。

    您可以从result_metric 函数返回result

    def custom_metric(y_true,y_pred):
         result = K.abs((y_true-y_pred) / y_pred, axis = 1)
         return result
    

    第二步是使用keras 回调函数来查找错误的总和。

    回调可以定义并传递给fit方法。

    history = CustomLossHistory()
    model.fit(callbacks = [history])
    

    最后一步是创建CustomLossHistory 类,以便找出您预期的错误列表中的sum

    CustomLossHistory 将从keras.callbacks.Callback 继承一些默认方法。

    • on_epoch_begin:在每个 epoch 开始时调用。
    • on_epoch_end:在每个 epoch 结束时调用。
    • on_batch_begin:在每批开始时调用。
    • on_batch_end:在每批结束时调用。
    • on_train_begin:在模型训练开始时调用。
    • on_train_end:在模型训练结束时调用。

    您可以在Keras Documentation阅读更多内容

    但是对于这个例子,我们只需要on_train_beginon_batch_end 方法。

    实施

    class LossHistory(keras.callbacks.Callback):
        def on_train_begin(self, logs={}):
            self.errors= []
    
        def on_batch_end(self, batch, logs={}):
             loss = logs.get('loss')
             self.errors.append(self.loss_mapper(loss))
    
        def loss_mapper(self, loss):
             if loss <= 0.1:
                 return 0
             elif loss > 0.1 & loss <= 0.15:
                 return 5/3
             elif loss > 0.15 & loss <= 0.2:
                 return 5
             else:
                 return 2000
    

    您的模型经过训练后,您可以使用以下语句访问您的错误

    errors = history.errors
    

    【讨论】:

    • 起初从纯编程的角度来看这可能是一个有效的答案,但我仍然认为这行不通,因为渐变不会有用。不过我可能错了。
    • @Mihai Alexandru-Ionut 但是如何保存条件结果并使用回调,你能举个例子吗?谢谢
    • @AlexanderHarnisch,现在我明白了。我更新了我的答案。
    • @Aceconhielo,是的,我更新了我的答案,很快我会用一个完整的解决方案示例更新它。
    • @Mihai Alexandru-Ionut 没关系,已修复。但如果你不介意,我还有一个问题。我想要预测的值介于 0 和 1 之间,但我的预测输出有时是 1。你知道我该如何解决吗?
    【解决方案2】:

    我会在这里跳一下,说这行不通,因为它不可微。损失需要连续可微,以便您可以通过那里传播梯度。

    如果您想完成这项工作,您需要找到一种方法来做到这一点而不会中断。例如,您可以尝试对 4 个离散值进行加权平均,其中权重强烈倾向于最接近的值。

    【讨论】:

    • 我的错。我忘了说最后我想总结所有的错误。我修改了我的问题
    【解决方案3】:

    直接附加到 self 对我不起作用,而是附加到 self 的 params dict 完成了这项工作,回答 op 它将是 self.params['error'] = [],然后根据需要添加到数组中。

    class CustomCallback(tf.keras.callbacks.Callback):
         
         def on_train_begin(self, logs=None):
              self.params['error'] = []
    
         def on_epoch_end(self, epochs, logs=None):
              #do something with self.params['error']
    
    history = model.fit(callbacks = [CustomCallback()])
    
    #When train ends
    
    error = history.params['error']
    

    【讨论】:

      猜你喜欢
      • 2021-02-26
      • 2020-12-19
      • 2017-12-18
      • 2020-03-27
      • 1970-01-01
      • 2018-11-12
      • 2018-12-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多