CE损失函数入门指南:从数学原理到PyTorch实战

1次阅读
没有评论

共计 1420 个字符,预计需要花费 4 分钟才能阅读完成。

image.webp

信息论基础与 CE 推导

交叉熵(Cross-Entropy)本质是信息论的产物。要理解它,我们需要先明确三个概念:

CE 损失函数入门指南:从数学原理到 PyTorch 实战

  1. 信息熵:描述事件的不确定性,公式 $H(p)=-\sum p(x)\log p(x)$。比如抛硬币时,正面概率 0.5 的熵比 0.9 时更大。

  2. KL 散度:衡量两个概率分布的差异,$D_{KL}(p||q)=\sum p(x)\log\frac{p(x)}{q(x)}$。注意它不对称,即 $D_{KL}(p||q) \neq D_{KL}(q||p)$。

  3. 交叉熵:可拆解为 $H(p,q)=H(p)+D_{KL}(p||q)$。当 p 是真实分布(one-hot 标签),$H(p)=0$,此时交叉熵等于 KL 散度。这就是分类任务中 CE 损失的理论依据。

CE vs MSE:为什么分类任务不用均方误差

  • 梯度对比:
  • MSE 的梯度包含 $(\hat{y}-y)\hat{y}(1-\hat{y})$,当预测值接近 0 / 1 时梯度消失
  • CE 的梯度简化为 $(\hat{y}-y)$,始终保持有效梯度

  • 二分类示例:
    假设真实标签 y =1,模型输出概率 0.01:

  • MSE 损失:$(1-0.01)^2=0.98$
  • CE 损失:$-\log(0.01)=4.6$
    CE 对错误预测的惩罚更严厉,更适合概率输出

代码实战:PyTorch 与 TensorFlow 实现

PyTorch 基础版

import torch.nn as nn

# 假设 3 分类任务,batch_size=2
logits = torch.randn(2, 3)  # 未经 softmax 的模型输出
labels = torch.tensor([1, 2])  # 真实类别索引

loss_fn = nn.CrossEntropyLoss()
loss = loss_fn(logits, labels)  # 内部自动做 log_softmax

处理类别不平衡(weight 参数)

class_weights = torch.tensor([0.2, 0.3, 0.5])  # 假设第 0 类样本少
loss_fn = nn.CrossEntropyLoss(weight=class_weights)

TensorFlow 实现

tf_loss = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)
loss = tf_loss([1, 2], logits)  # 标签不需要 one-hot

Label Smoothing 技术揭秘

传统 one-hot 标签会导致模型过度自信。标签平滑通过混合均匀分布来缓解:

  1. 原始标签:[0, 1, 0]
  2. 平滑后(ε=0.1):[0.05, 0.9, 0.05]

PyTorch 实现:

loss_fn = nn.CrossEntropyLoss(label_smoothing=0.1)

三大避坑指南

  1. log(0)问题:
  2. 总在 softmax 后加 epsilon(如 1e-8)
  3. 或直接使用nn.CrossEntropyLoss(内部已处理)

  4. 数值稳定性:

  5. 优先让模型输出 logits(未归一化),而非直接输出概率
  6. 使用 log_softmax 而非分开计算

  7. 多标签任务:

  8. 普通 CE 要求单标签,多标签需改用BCEWithLogitsLoss
  9. 或对每个类别独立计算 CE

开放性问题

当类别数量极大时(如推荐系统中的百万级物品):
1. CE 计算涉及全体类别的 exp 求和,计算成本高昂
2. 改进方案包括:噪声对比估计(NCE)、分层 softmax、采样 softmax 等

你遇到过哪些 CE 损失的计算瓶颈?欢迎分享你的实战经验!

正文完
 0
评论(没有评论)