自定义 keras 损失函数二元交叉熵给出不正确的结果

Posted

技术标签:

【中文标题】自定义 keras 损失函数二元交叉熵给出不正确的结果【英文标题】:Custom keras loss function binary cross entropy giving improper results 【发布时间】:2020-07-08 22:05:57 【问题描述】:

是否有人有令人信服的解决方案来使 custom_binarycrossentropy 起作用?

我尝试了所有可能的方法(甚至使整个训练数据大小与 bacth 大小相同,以消除批量处理期间对全局平均的依赖。)。但我发现我的二进制交叉熵实现与 keras 的实现之间存在显着差异(通过指定 loss = 'binary_crossentropy')

我的crustom二进制交叉熵代码如下

def _loss_tensor(y_true, y_pred):
y_pred = K.clip(y_pred, _EPSILON, 1.0-_EPSILON)
out = (y_true * K.log(y_pred) + (1.0 - y_true) * K.log(1.0 - y_pred))
return -K.mean(out)
def _loss_tensor2(y_true, y_pred):
y_pred = K.clip(y_pred, _EPSILON, 1.0-_EPSILON)
out = -(y_true * K.log(y_pred) + -(1.0 - y_true) * K.log(1.0 - y_pred))
return out
def _loss_tensor2(y_true, y_pred):
loss1 = K.binary_crossentropy(y_true, y_pred)
return loss1

这些方法都不起作用。即使我在返回自定义损失函数的结果之前执行 K.mean(),它也不起作用。

我无法理解使用 loss = 'binary_crossentropy' 有什么特别之处。当我使用我的自定义损失函数时,训练很糟糕,它确实按预期工作。

我需要我的自定义损失函数来根据错误来操纵损失函数并更多地惩罚某种类型的分类错误。

【问题讨论】:

【参考方案1】:

我找到了一种满足此要求的方法,并在此处发布了相同的内容: https://github.com/keras-team/keras/issues/4108

但是,为什么内置函数的性能与显式公式方法显着不同是未知的。然而,我预计这主要是由于对 y_pred 概率值的上限和下限的处理。

【讨论】:

【参考方案2】:
def custom_binary_loss(y_true, y_pred): 
    # https://github.com/tensorflow/tensorflow/blob/v2.3.1/tensorflow/python/keras/backend.py#L4826
    y_pred = K.clip(y_pred, K.epsilon(), 1 - K.epsilon())
    
    term_0 = (1 - y_true) * K.log(1 - y_pred + K.epsilon())  # Cancels out when target is 1 
    term_1 = y_true * K.log(y_pred + K.epsilon()) # Cancels out when target is 0

    return -K.mean(term_0 + term_1, axis=1)

【讨论】:

以上是关于自定义 keras 损失函数二元交叉熵给出不正确的结果的主要内容,如果未能解决你的问题,请参考以下文章

sklearn基于make_scorer函数为Logistic模型构建自定义损失函数+代码实战(二元交叉熵损失 binary cross-entropy loss)

交叉熵损失和后勤损失之间有什么区别吗?

Keras 自定义损失函数 - 生存分析截尾

实现二元交叉熵损失给出了与 Tensorflow 不同的答案

Keras 和 TensorFlow 中所有这些交叉熵损失之间有啥区别?

tf.keras之损失函数