CE损失函数在分类任务中的实战优化:从理论到PyTorch实现

1次阅读
没有评论

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

image.webp

背景:交叉熵损失的数学本质

交叉熵损失 (Cross-Entropy Loss) 是分类任务中最常用的损失函数,其数学表达式为:

CE 损失函数在分类任务中的实战优化:从理论到 PyTorch 实现

$$
L_{CE} = -\sum_{i=1}^C y_i \log(p_i)
$$

其中 $y_i$ 是真实标签的 one-hot 编码,$p_i$ 是模型预测的类别概率。通过链式法则可推导出梯度:

$$
\frac{\partial L}{\partial z_i} = p_i – y_i
$$

这个简洁的梯度形式使得 CE 损失成为反向传播的高效选择。

传统 CE 的三大实战痛点

  1. 类别不平衡问题:当 90% 样本属于类别 A 时,模型只需将所有预测偏向 A 就能获得 90% 准确率,此时损失函数失去指导意义

  2. 噪声标签敏感:若标签存在错误(如将猫误标为狗),CE 会迫使模型拟合这些错误样本

  3. 过度自信预测:softmax 容易产生接近 1 的概率值,可能导致模型泛化能力下降

改进方案一:Focal Loss

Focal Loss 通过引入可调节的聚焦参数解决样本不平衡问题:

$$
L_{FL} = -\alpha_t (1-p_t)^\gamma \log(p_t)
$$

  • $\alpha$ 控制类别权重(常用 0.25-0.75)
  • $\gamma$ 调节难易样本关注度(常用 2.0)

在 CIFAR-10 上的消融实验显示:

配置 准确率
CE Baseline 92.1%
FL(γ=1) 92.3%
FL(γ=2,α=0.25) 93.7%

改进方案二:Label Smoothing

通过软化真实标签分布缓解过拟合:

$$
y_i^{LS} = y_i(1-\epsilon) + \epsilon/K
$$

其中 $\epsilon$ 建议设置在 0.05-0.2 之间。实验表明该技术对噪声标签的鲁棒性提升显著:

# PyTorch 实现示例
class LabelSmoothingCE(nn.Module):
    def __init__(self, epsilon=0.1):
        super().__init__()
        self.epsilon = epsilon

    def forward(self, preds, target):
        n_classes = preds.size(-1)
        log_probs = F.log_softmax(preds, dim=-1)
        loss = -log_probs.mean(dim=-1)
        smooth_loss = -log_probs.sum(dim=-1) / n_classes
        return (1-self.epsilon)*loss + self.epsilon*smooth_loss

工程实现避坑指南

  1. 数值稳定性 :始终使用log_softmax 而非 softmax+log 组合

  2. GPU 优化:避免在损失函数内部进行张量拷贝

  3. 随机种子固定:

    def set_seed(seed):
        torch.manual_seed(seed)
        np.random.seed(seed)
        random.seed(seed)
        if torch.cuda.is_available():
            torch.cuda.manual_seed_all(seed)

开放问题讨论

  1. 如何设计动态调整 γ 参数的策略?
  2. 在多任务学习中不同任务是否应该使用不同的损失函数?
  3. 当类别数极大(如推荐系统中的百万级分类)时,CE 损失应该如何优化?

期待大家在评论区分享实战经验!

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