交叉熵损失(Cross-Entropy Loss)

交叉熵损失是分类任务里最常用的损失函数,用来衡量”模型预测的概率分布”和”真实答案”差多远。分类问题(判断这张图是猫还是狗、这个词后面接什么)几乎都用它。

一句话类比:交叉熵就像给模型的答卷打分,但它不只看对错,还看”你有多自信”。答对了且很自信 → 扣分很少;答对了但很心虚 → 扣一点分;答错了还特别自信 → 狠狠扣分。它逼着模型”要么别乱猜,要么就猜对”。

关联:交叉熵是训练模型的”评分标准”。语言模型预测”下一个 token”(见 ../ai-agent-guide/token.md)本质就是个超大分类问题(在整个词表上分类),训练时用的正是交叉熵。SFT 微调(见 ../ai-agent-guide/foundation_model.md)也是拿交叉熵当损失。

1. 先搞懂”熵”和”交叉熵”

  • 熵(Entropy):衡量一个概率分布的”不确定性”。越均匀(啥都可能)熵越大,越确定(几乎必然)熵越小。
  • 交叉熵(Cross-Entropy):用**分布 Q(模型预测)去编码分布 P(真实)**时,平均要花多少”信息量”。P 和 Q 越接近,交叉熵越小;完全一致时最小。

训练目标就是:让模型预测分布 Q 尽量逼近真实分布 P,也就是最小化交叉熵

2. 公式(别怕,拆开看很简单)

通用形式(真实分布 P,预测分布 Q,类别 i):

分类任务里真实标签通常是 one-hot(正确类别为 1,其余为 0),所以求和里只有正确类别那一项活下来,公式塌缩成:

这就是精髓:损失只取决于”模型给正确答案打了多少概率”。

模型给正确类别的概率−log(p) 损失解读
1.0(完全确定且答对)0满分,不扣分
0.90.105很小
0.50.693中等
0.1(答对但很心虚)2.303较大
0.01(几乎押错)4.605巨大惩罚

直觉:概率越接近正确答案,损失越小;越远离,惩罚指数级上升。 这就是 −log 的威力。

3. 两个常见变体

名称用于输出层说明
Binary Cross-Entropy (BCE)二分类 / 多标签Sigmoid每个类独立判断”是/否”
Categorical Cross-Entropy多分类(互斥)Softmax所有类概率和为 1,选一个
  • Softmax:把模型输出的原始分数(logits)变成一组和为 1 的概率。
  • Sigmoid:把单个分数压到 (0,1),表示某一类的独立概率。

4. 代码:PyTorch 里怎么用(易踩坑!)

import torch
import torch.nn as nn
 
# 多分类:nn.CrossEntropyLoss 内部【已经包含 Softmax】
loss_fn = nn.CrossEntropyLoss()
 
logits = torch.tensor([[2.0, 0.5, 0.1]])   # 模型原始输出(未经 softmax)
target = torch.tensor([0])                  # 正确类别索引(不是 one-hot!)
 
loss = loss_fn(logits, target)
print(loss.item())   # ≈ 0.34

⚠️ 头号坑:nn.CrossEntropyLoss 自带 Softmax,喂给它的必须是原始 logits,不要自己先做 softmax,否则等于做了两次,训练会出问题。这点和 sklearn / 手写公式的习惯不同。

对比:nn.NLLLoss 才需要你先手动 log_softmaxCrossEntropyLoss = LogSoftmax + NLLLoss 的打包版。

5. 常见坑(复习重点)

  • 重复做 Softmaxnn.CrossEntropyLoss 已含 Softmax,别再手动加一层。
  • 标签格式搞错:PyTorch 的 CrossEntropyLoss 要的是类别索引(如 2),不是 one-hot 向量。
  • log(0) 爆炸:预测概率若为 0,−log(0)=∞。框架内部用 log-sum-exp 等技巧数值稳定,自己手写公式时要加个极小值 eps 防溢出。
  • 和 MSE 混用:分类别用均方误差(MSE),交叉熵梯度性质更好、收敛更快;回归任务才用 MSE。
  • 类别不平衡:某类样本极少时,可给 CrossEntropyLoss(weight=...) 加权,或改用 Focal Loss。

关联概念