You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多标签分类中from_logits=True的BinaryCrossentropy结果不符问题

问题原因解析

两种损失计算结果不匹配的核心原因有两个:

  1. 数值稳定性优化的实现差异

    • 当from_logits=True时,TensorFlow使用稳定的损失公式直接计算:
      loss = max(z, 0) - y*z + log(1 + exp(-abs(z)))
      
      这个公式避免了直接计算sigmoid(z)带来的数值溢出问题,也不需要对输入做任何截断处理。
    • 当from_logits=False时,输入是经过sigmoid后的概率值,TensorFlow会默认对概率值做截断处理:将概率限制在[epsilon, 1-epsilon]范围内(默认epsilon=1e-7),避免计算log(0)或log(1)时出现无穷大。这种截断会引入微小的误差,尤其当logit绝对值很大时(比如你的示例中18、-20、20),sigmoid后的概率接近1或0,截断操作带来的误差会被放大。
  2. sigmoid计算的数值精度损失
    当logit的绝对值很大时(比如18、20),sigmoid(z)的结果在浮点数中会被近似为1.0,而实际值是略小于1的。这种近似会导致后续log(1-p)的计算出现偏差,进一步拉大与from_logits=True时的损失差距。

验证示例

通过设置reduction=NONE查看每个标签的损失值,可以清晰看到差异:

lf_none = tf.keras.losses.BinaryCrossentropy(reduction=tf.keras.losses.Reduction.NONE)
lt_none = tf.keras.losses.BinaryCrossentropy(from_logits=True, reduction=tf.keras.losses.Reduction.NONE)

# 查看每个标签的损失
print(lf_none(a, b_sigmoid))
print(lt_none(a, b))

输出中,第一个样本的第一个标签(logit=18,y=0):

  • from_logits=False时损失为1.6118e+01(因截断操作,log(1-p)被计算为log(1e-7))
  • from_logits=True时损失为1.8e+01(用稳定公式计算的真实损失)
    这是两者总损失差异的主要来源。

结论

在多标签分类任务中,推荐始终使用from_logits=True的BinaryCrossentropy损失函数:既可以避免数值溢出,也能保证损失计算的准确性,无需手动添加sigmoid激活层(TensorFlow会在损失计算中自动处理)。

内容的提问来源于stack exchange,提问作者Green Falcon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 20:17:02