【问题标题】:Using Tensorflow Huber loss in Keras在 Keras 中使用 Tensorflow Huber 损失
【发布时间】:2018-05-30 03:31:36
【问题描述】:

我正在尝试在 keras 模型中使用 huber 损失(编写 DQN),但我得到了不好的结果,我认为我做错了什么。我的是代码如下。

model = Sequential()
model.add(Dense(output_dim=64, activation='relu', input_dim=state_dim))
model.add(Dense(output_dim=number_of_actions, activation='linear'))
loss = tf.losses.huber_loss(delta=1.0)
model.compile(loss=loss, opt='sgd')
return model

【问题讨论】:

    标签: python tensorflow keras reinforcement-learning


    【解决方案1】:

    我带着完全相同的问题来到这里。接受的答案使用logcosh,它可能具有相似的属性,但它不完全是 Huber Loss。以下是我为 Keras 实现 Huber Loss 的方法(请注意,我使用的是来自 Tensorflow 1.5 的 Keras)。

    import numpy as np
    import tensorflow as tf
    
    '''
     ' Huber loss.
     ' https://jaromiru.com/2017/05/27/on-using-huber-loss-in-deep-q-learning/
     ' https://en.wikipedia.org/wiki/Huber_loss
    '''
    def huber_loss(y_true, y_pred, clip_delta=1.0):
      error = y_true - y_pred
      cond  = tf.keras.backend.abs(error) < clip_delta
    
      squared_loss = 0.5 * tf.keras.backend.square(error)
      linear_loss  = clip_delta * (tf.keras.backend.abs(error) - 0.5 * clip_delta)
    
      return tf.where(cond, squared_loss, linear_loss)
    
    '''
     ' Same as above but returns the mean loss.
    '''
    def huber_loss_mean(y_true, y_pred, clip_delta=1.0):
      return tf.keras.backend.mean(huber_loss(y_true, y_pred, clip_delta))
    

    根据你是想减少损失还是损失的均值,使用上面对应的函数。

    【讨论】:

    • 嗨@avejidah。实际上它们非常相似。 Keras 的 Huber Loss 公开了 PR。你可以在这里看到。 github.com/keras-team/keras/pull/6410.
    • 嘿 hakaishinbeerus。我同意它们相似,但它们不一样。 the-moliver 和 Danielhiversen 在 PR 评论中指出了这一点,然后他们将 huber 重命名为 logcosh 以准确反映 Keras 的损失函数。 AFAIK,Keras 仍然没有 Huber Loss,所以对于那些有兴趣使用它的人来说,我的功能应该是正确的。
    【解决方案2】:

    您可以将 Tensorflow 的 tf.losses.huber_loss 包装在自定义 Keras 损失函数中,然后将其传递给您的模型。

    包装器的原因是 Keras 只会将 y_true, y_pred 传递给损失函数,并且您可能还希望将许多参数中的一些参数传递给 tf.losses.huber_loss。因此,您需要某种闭包,例如:

    def get_huber_loss_fn(**huber_loss_kwargs):
    
        def custom_huber_loss(y_true, y_pred):
            return tf.losses.huber_loss(y_true, y_pred, **huber_loss_kwargs)
    
        return custom_huber_loss
    
    # Later...
    model.compile(
        loss=get_huber_loss_fn(delta=0.1)
        ...
    )
    

    【讨论】:

    • 为什么不直接指定loss=tf.losses.huber_loss
    • @MikiP 你有想过这个吗?我也很好奇。
    • 如果我没记错的话,那就没有理由不直接说明了。
    • 我刚刚做了一个澄清的编辑 - 大概你想调整 delta 至少所以你需要一个包装器来传递它。
    • @MikiP 如果您想在 huber 计算之前修改 2 个张量(例如通过平方),这可能很有用,这样您就不必重写整个函数
    【解决方案3】:

    我正在查看 keras 的损失。显然 logcosh 具有与 huber loss 相同的属性。更多相似之处可见here

    【讨论】:

      【解决方案4】:

      怎么样:

          loss=tf.keras.losses.Huber(delta=100.0)
      

      【讨论】:

      • 我相信这已经被弃用了
      • 它不在文档中,但代码内文档中没有任何内容表明它已被弃用。这个答案相当于上面评分较高的答案,但需要编写的代码更少,所以更好!
      猜你喜欢
      • 2020-12-19
      • 2018-01-26
      • 1970-01-01
      • 2021-09-06
      • 1970-01-01
      • 2019-01-20
      • 2016-12-18
      • 2020-01-01
      • 2019-12-10
      相关资源
      最近更新 更多