自定义Keras损失函数二元交叉熵产生不正确的结果

3

有没有人有一个令人信服的解决方案使自定义二元交叉熵工作?

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

我的自定义二元交叉熵代码如下:

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'有什么特殊作用。当我使用我的自定义损失函数时,训练效果不佳,与预期的效果不符。

我需要使用自定义损失函数来根据误差调整损失函数,并对某种类型的分类错误进行更严厉的惩罚。

3个回答

0

我在编写自定义 BCE 时也遇到了同样的问题。这是我的解决方案:

def get_custom_bce(epsilon = 1e-2):
  def custom_bce(y_true, y_pred):
    return -tf.math.reduce_mean(y_true * tf.math.log(tf.math.maximum(y_pred, tf.constant(epsilon))) + (1. - y_true) * tf.math.log(tf.math.maximum(1. - y_pred, tf.constant(epsilon))))
return custom_bce

很抱歉我对Keras后端不是很熟悉,但我相信它们是可以互换的。 顺便说一下,这是在sigmoid激活之后使用的。


0

我已经找到了一种适用于这个需求的工作方式,并在这里发布了相同的内容: https://github.com/keras-team/keras/issues/4108

然而,为什么内置函数的表现与显式公式方法明显不同,目前还不清楚。但是,我预计这主要是由于对y_pred概率值的上下限处理方式不同所致。


0
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)

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