【问题标题】:Keras custom loss implementation : ValueError: An operation has `None` for gradientKeras 自定义损失实现:ValueError: An operation has `None` for gradient
【发布时间】:2018-08-19 21:09:44
【问题描述】:

我正在尝试实现这个损失函数:MCFD_loss_function 来自本文档(P6):Loss functions

所以我创建了一个这样的新函数:

def mcfd_loss(y_true, y_pred):
    return K.sum( # ∑
        K.cast(
            K.greater( # only values greater than 0 (+ float32 cast)
                  K.dot(K.sign(y_pred),  # π
                        K.sign(y_true))
           , 0)
        , 'float32')
    )

但是当我开始训练时,就会出现这个错误:

ValueError: 一个操作有None 用于梯度。请确保您的所有操作都定义了渐变(即可微分)。无梯度的常用操作:K.argmax、K.round、K.eval。

我不知道我错过了哪一点。似乎引发了错误,因为我使用了更大的功能。我不知道这个错误是什么意思以及如何纠正我的问题。

谢谢。

【问题讨论】:

  • 就像错误所说的那样。训练 NN 意味着从损失函数开始计算梯度。因此,损失函数中使用的每个运算都必须是可微的。因此,只需检查哪个操作导致此错误。然后,您可以将 op 替换为可微分且近似其行为的 op,例如标志 op 的陡峭 tanh。
  • 感谢您的回答。我知道在 Keras 中,每个操作的损失函数都必须是可微的。我不太了解的是“更大”或“演员”操作如何区分。此外,符号 op 是可微的,除了 0,不是吗?
  • 嗯,你必须测试一下什么是 tensorflow 可以接受的,什么不是。所以也许 tf 不关心符号中的零,但也许它关心。您可以使用 sigmoid 逼近 K.greater 函数,该函数非常陡峭,看起来像一个更大的函数(您还必须沿 x 轴移动它)。那么你可能不再需要演员表了。

标签: python tensorflow keras backend algebraic-number


【解决方案1】:

您希望损失函数检查 sign(f_(t,1))*sign(Y_(t+1)) 是否大于 0。由于 sign 在 0 处不可微,我建议改用 softsign

由于大于函数也是不可微分的,因此可以使用以下近似值(参见here):maxϵ(x,y):= 0.5(x + y + absϵ(x − y)),其中absϵ(x):=sqrt(x^2 + ϵ)ϵ > 0。为简单起见,我将在下面的代码示例中将此近似称为greater_approx。 (注意,你只需要插入上面的计算)

查看损失函数的定义,您必须将总和除以预测数 (K.get_variable_shape(y_pred)[0])(还要加上一个减号)。 P对应根据Loss Functions in Time Series Forecasting paper的预测次数。

总而言之,您的损失函数应该如下所示:

def mcfd_loss(y_true, y_pred):
   return - (1/K.get_variable_shape(y_pred)[0]) * K.sum( # ∑
      K.cast(
         greater_approx( # only values greater than 0 (+ float32 cast)
            K.dot(K.softsign(y_pred),  # π
                    K.softsign(y_true))
         , 0)
      , 'float32')
   )

最后一句话:要在 Keras 中使用自定义损失函数,请查看 SO question

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-29
    • 2020-12-24
    • 1970-01-01
    • 2020-10-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多