我试图实现归一化的二进制交叉熵用于分类任务,遵循该论文:Normalized Loss Functions for Deep Learning with Noisy Labels。
其数学公式如下所示:
以下是我的实现代码:
![enter image description here](https://istack.dev59.com/leXDb.webp)
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
我正在使用这个损失函数来训练一个二元分类器(点击率预测器),但是模型的损失没有下降,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]])>
我手动检查了一些极端情况,发现这个损失并没有影响到NaN或0。
有人能帮我调试为什么模型不能收敛到这个损失吗?我的损失函数或实现有什么问题吗?
编辑1:模型架构是一个带有6个任务的多门混合专家模型。所有6个任务都是二元分类,从所有任务中添加损失以获得最终损失。
~.40
。 - Jatin Mandav