gpt4 book ai didi

tensorflow - 具有归一化二元交叉熵损失的模型不收敛

转载 作者:行者123 更新时间:2023-12-05 04:20:28 24 4
gpt4 key购买 nike

我正在尝试为本文之后的分类任务实现归一化二元交叉熵:Normalized Loss Functions for Deep Learning with Noisy Labels .数学计算如下: enter image description here

这是我的实现:

import tensorflow as tf
from keras.utils import losses_utils

class NormalizedBinaryCrossentropy(tf.keras.losses.Loss):
def __init__(
self,
from_logits=False,
label_smoothing=0.0,
axis=-1,
reduction=tf.keras.losses.Reduction.NONE,
name="normalized_binary_crossentropy",
**kwargs
):
super().__init__(
reduction=reduction, name=name
)
self.from_logits = from_logits
self._epsilon = tf.keras.backend.epsilon()

def call(self, target, logits):
if tf.is_tensor(logits) and tf.is_tensor(target):
logits, target = losses_utils.squeeze_or_expand_dimensions(
logits, target
)
logits = tf.convert_to_tensor(logits)
target = tf.cast(target, logits.dtype)

if self.from_logits:
logits = tf.math.sigmoid(logits)

logits = tf.clip_by_value(logits, self._epsilon, 1.0 - self._epsilon)

numer = target * tf.math.log(logits) + (1 - target) * tf.math.log(1 - logits)
denom = - (tf.math.log(logits) + tf.math.log(1 - logits))
return - numer / denom

def get_config(self):
config = super().get_config()
config.update({"from_logits": self._from_logits})
return config

我正在使用此损失来训练二元分类器(CTR 预测器),但模型的损失并没有减少,ROC-AUC 保持在 ~0.49-0.5。为了验证分子的实现,我尝试通过删除分母进行训练,并且效果很好。

# Example Usage

labels = np.array([[0], [1], [0], [0], [0]]).astype(np.int64)

logits = np.array([[-1.024], [2.506], [1.43], [0.004], [-2.0]]).astype(np.float64)

tf_nce = NormalizedBinaryCrossentropy(
reduction=tf.keras.losses.Reduction.NONE,
from_logits=True
)
tf_nce(labels, logits)

#<tf.Tensor: shape=(5, 1), dtype=float64, numpy=
# array([[0.18737159],
# [0.02945536],
# [0.88459308],
# [0.50144269],
# [0.05631594]])>

我手动检查了一些极端情况,发现损失没有达到 nans 或 0。

谁能帮我调试为什么模型不能收敛到这个损失?我对损失函数或实现的理解有问题吗?

编辑 1:模型架构是具有 6 个任务的多门混合专家。所有 6 个任务都是二元分类,将所有任务的损失相加得到最终损失。

最佳答案

如上所述,论文中提到的一件事是损失的范数应包含在 [0 ~ 1] 之间,但由于您的损失是违反了 Normalized Binary Cross Entropy 的条件,另一个原因是你除以错误的分母,你必须将它除以你的 的交叉熵logits 为此采用logitsBinaryCrossEntropy()。所以,这些可能是您的功能没有减少的原因...我对您的代码做了一些更改以满足此规范属性...

import tensorflow as tf
from keras.utils import losses_utils

class NormalizedBinaryCrossentropy(tf.keras.losses.Loss):
def __init__(
self,
from_logits=False,
label_smoothing=0.0,
axis=-1,
reduction=tf.keras.losses.Reduction.NONE,
name="normalized_binary_crossentropy",
**kwargs
):
super().__init__(
reduction=reduction, name=name
)
self.from_logits = from_logits
self._epsilon = tf.keras.backend.epsilon()

def call(self, target, logits):
if tf.is_tensor(logits) and tf.is_tensor(target):
logits, target = losses_utils.squeeze_or_expand_dimensions(
logits, target
)
logits = tf.convert_to_tensor(logits)
target = tf.cast(target, logits.dtype)

logits = tf.clip_by_value(logits, self._epsilon, 1.0 - self._epsilon)

if self.from_logits:
numer = tf.keras.losses.binary_crossentropy(target, logits,from_logits=True)[:,tf.newaxis]
denom = -( tf.math.log(logits) + tf.math.log(1 - logits))
return numer * denom / tf.reduce_sum(denom)
else:
logits = tf.nn.log_softmax(logits)
num = - tf.math.reduce_sum(tf.multiply(target, logits), axis=1)
denom = -tf.math.reduce_sum(logits, axis=1)
return num / denom

def get_config(self):
config = super().get_config()
config.update({"from_logits": self._from_logits})
return config

我已经更新了解决方案,如果您的 logits 是单热的,则有两种计算 BCE 的方法,然后设置 from_logit=False,否则设置它 True

关于tensorflow - 具有归一化二元交叉熵损失的模型不收敛,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74444011/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com