Keras自定义二元交叉熵损失函数。获取NaN作为损失输出。

4

我尝试编写一个自定义的二元交叉熵损失函数。这是我的脚本:

def my_custom_loss(y_true,y_pred):
    t_loss = (-1)*(y_true * K.log(y_pred) + (1 - y_true) * K.log(1 - y_pred))
    return K.mean(t_loss)

当我使用该损失函数运行我的脚本时,经过几次迭代后,损失函数的输出为 NaN。
然后我查看了TensorFlow文档,将损失函数修改为以下内容:
 t_loss = K.max(y_pred,0)-y_pred * y_true + K.log(1+K.exp((-1)*K.abs(y_pred)))

这段代码没有问题。

我想知道为什么我的第一个损失函数会输出NaN,希望有人能提供一些解释。

二元交叉熵: y * log(p) + (1-y) * log(1-p)

我在最后一层使用了sigmoid函数作为激活函数。因此'p'的值应该在0到1之间。对于这个范围,log应该存在。

谢谢。

1个回答

6
一个天真的二元交叉熵实现在输出为0或大于1时会遭遇数值问题,例如 log(0) -> NaN。您发布的公式经过重新格式化以确保稳定性并避免下溢。以下推导来自tf.nn.sigmoid_cross_entropy_with_logits
z * -log(sigmoid(x)) + (1 - z) * -log(1 - sigmoid(x))
= z * -log(1 / (1 + exp(-x))) + (1 - z) * -log(exp(-x) / (1 + exp(-x)))
= z * log(1 + exp(-x)) + (1 - z) * (-log(exp(-x)) + log(1 + exp(-x)))
= z * log(1 + exp(-x)) + (1 - z) * (x + log(1 + exp(-x))
= (1 - z) * x + log(1 + exp(-x))
= x - x * z + log(1 + exp(-x))

对于 x < 0,为了避免 exp(-x) 中的溢出,我们重新制定如下方程:

x - x * z + log(1 + exp(-x))
= log(exp(x)) - x * z + log(1 + exp(-x))
= - x * z + log(1 + exp(x))

这个实现使用等价的形式:

max(x, 0) - x * z + log(1 + exp(-abs(x)))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接