首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >具有归一化二元交叉熵损失的模型不收敛

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

Stack Overflow用户
提问于 2022-11-15 10:23:13
回答 2查看 167关注 0票数 3

我试图为一项分类任务实现标准化的二进制交叉熵,这篇文章是:带噪声标签的深度学习的归一化损失函数。计算结果如下:

以下是我的实现:

代码语言:javascript
复制
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。为了验证分子的实现,我尝试了通过去掉分母来进行训练,它运行得很好。

代码语言:javascript
复制
# 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个任务都是二进制分类,所有任务的损失被加到一起以获得最终的损失。

EN

回答 2

Stack Overflow用户

发布于 2022-11-17 14:24:09

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

代码语言:javascript
复制
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

我已经更新了解决方案,如果您的日志是一个,则有两种计算BCE的方法--然后设置from_logit=False,否则设置为True

票数 1
EN

Stack Overflow用户

发布于 2022-11-18 17:25:21

我将尽量避免log-Sigmoid稳定性问题,并尝试将上述模型实现为Softmax Binary cross entropy.的2类问题。

NormalizedCrossEntropy被定义为:

代码语言:javascript
复制
class NormalizedCrossEntropy(keras.layers.Layer):
    def __init__(self, num_classes):
        super(NormalizedCrossEntropy, self).__init__()
        self.num_classes = num_classes

    def call(self, pred, labels):
        pred = tf.nn.log_softmax(pred, axis=1,)
        label_one_hot = tf.one_hot(labels, self.num_classes)
        numer = -1 * tf.reduce_sum(label_one_hot * pred, axis=1) 
        denom = -1* tf.reduce_sum(pred, axis=1)
        nce = numer/ denom
        return nce

示例用法:

代码语言:javascript
复制
NormalizedCrossEntropy(num_classes=2)(np.array([[-1.024, 0.5], [0.1, 2.506], [1, .0], [0., 1.], [-0.89, -2.0]]), np.array([0, 1, 0, 0, 0]) )
#array([0.89725673, 0.03348167, 0.19259584, 0.80740416, 0.16958274]
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74444011

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档