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

时间:2018-02-23 15:24:10

标签: python keras loss-function

我尝试编写自定义二进制交叉熵损失函数。 这是我的剧本:

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 个答案:

答案 0 :(得分:0)

二进制交叉熵的简单实现将在0输出或大于一个输出上遇到数值问题,例如log(0) -> NaN。您发布的公式重新计算为ensure stability and avoid underflow。以下扣除来自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)))