Softmax 与交叉熵
Softmax 将原始分数取指数,再除以总和,得到非负且总和为 1 的概率分布。交叉熵用正确类别的 −log p_y 评分,对 softmax 输入的梯度为 p − y。
Softmax 是平滑的 argmax:分数差变成指数级的概率比。交叉熵在正确类别概率趋近零时无界增长,反向传播时抵消 softmax 的饱和因子。本课的手写 3 被网络以 99.86% 的置信度识别成 2;同一预测下,交叉熵对正确类别的纠正梯度比平方误差大 361 倍。
从分数到概率和梯度
分类器每个类别的原始分数称为 logit。它可正可负,没有概率约束。本例十个分数中八个为负,总和为 −29.52。
计算 softmax 前先减最大分数 c,再取指数、求和、相除。对任意常数都有 softmax(s) = softmax(s − c),因为分子分母中的 e^(−c) 会约去。减最大值使所有指数的输入不大于零,防止指数溢出。若直接计算 logit 800 的指数,会出现 inf / inf = NaN。这个平移不改变数学上的概率;浮点计算仍有舍入和下溢边界。
交叉熵的一般式为 −Σ yᵢ log pᵢ。独热目标只有正确类别为一,所以化成 −log p_y。当 p_y → 0,损失没有有限上界。经过对数、除法和指数的链式求导:
∂L/∂s = p − y
s 是送入 softmax 的值。默认 s = z,即原始 logit。若先除以温度 T,则对原始分数的梯度为 (p − y) / T;温度同时改变 p,不能只看外面的缩放。
逐步演示
默认使用真实 MNIST 测试集中的一张 3,网络为 784 → 25 → 25 → 10,温度 T = 1.0。
- 原始分数:
z₂ = 10.00,第二名z₃ = 3.42,其余在−1.79到−18.15之间。 - 平移:减去
10.00,类别 2 变为零,类别 3 为−6.578。概率不变,指数溢出风险消除。 - 取指数:类别 2 为
e⁰ = 1;类别 3 为e^(−6.578) = 0.0014,分数差变为约 719 倍的比值。八个指数小于1e-5。 - 求和:总和
Σ = 1.0014。减最大值后的总和接近一,说明质量集中在一个类别。 - 相除:
p₂ = 0.9986、p₃ = 0.0014,其余八类合计1.57e-5。这些显示值经过舍入;未舍入的概率和为一,浮点误差除外。 - 比较标签:预测为 2,置信度
99.86%;正确标签是 3。 - 计算两种损失:交叉熵
−log p₃ = 6.5794nat;本课称为 MSE 的½Σ(pᵢ − yᵢ)² = 0.9972。对独热目标和概率分布,这种平方误差最多为1.0,已达到上界的约 99.7%。交叉熵无上界,不能称其达到最坏值。 - 经过同一个雅可比矩阵:
J = diag(p) − p pᵀ,两者都计算∂L/∂s = J · ∂L/∂p。交叉熵在正确类的输入梯度为−1/p₃ = −720.11,其他类为零。它选中J的第 3 列,抵消其中的p₃:(−1/p₃)·p₃(1 − p₃) = p₃ − 1 = −0.9986。平方误差输入的是普通幅度的p − y,结果为p₃·((p₃ − 1) − pᵀ(p − y)),仍带p₃。 - 比较分数梯度:交叉熵在正确类为
−0.9986,错误领先类为+0.9986;梯度下降会抬高 3、压低 2。平方误差正确类梯度约为0.0014 × (−1.9944) = −0.0028,约弱 361 倍。
为什么分类常配交叉熵
同一个饱和错误,平方误差能给出高损失,却只给出很小的更新信号。本例错误预测的平方误差为 0.9972、梯度幅度 0.0028;另一个几乎完全正确的样本显示损失 0.0000、梯度 9.6e-22。在容纳交叉熵梯度的坐标轴上,两者都接近平线,但错误例的梯度并非数学上的零。
温度升到 T = 3.0 后,不重训网络,只缩放固定 logit,正确类概率从 0.0014 升至 0.0935,梯度比从 361 降至 6.4。这说明差距与饱和有关;换成极其自信的正确样本,升温也可能打开原本未显示的差距,不能概括为升温总会缩小差距。
朴素实现 grad_mse = J @ (p - t) 构造稠密 C × C 矩阵,时间与空间均为 O(C²)。p pᵀ 会填满矩阵,所以 J 不是对角矩阵。词表 50,000 时有 25 亿项。但本课使用等价式:
J(p − y) = p ⊙ ((p − y) − pᵀ(p − y))
它只需 O(C) 时间和空间,不构造 J。平方复杂度属于朴素实现;softmax 饱和造成的梯度衰减不会因这种改写消失。线性输出的回归常用平方误差,不受这里同一种输出饱和机制影响。
边界情况
p_y下溢到零:直接取对数得到无穷大。生产中优先用融合的 log-sum-exp 形式,如 PyTorchcross_entropy、TensorFlowsoftmax_cross_entropy_with_logits,避免先算极小概率再取对数;非有限输入仍需处理。- 删除减最大值:数学概率不变。本例最大分数只有 10,
e^10 ≈ 22026,尚不会溢出;float64 接近e^710才遇到指数范围边界。 - 正确类概率舍入为一:交叉熵损失显示
0.0000,T = 1时梯度约2.5e-11。两个梯度都低于1e-6时,本课隐藏 CE/MSE 比值,避免用两个极小数的商制造没有意义的差距。 - 软目标:标签平滑或蒸馏可用非独热的归一化目标分布。
p − y仍成立,但不能再只算−log p_y,因为多个目标项非零。
常见错误
- 做两次 softmax:PyTorch 的交叉熵和标明接收 logits 的接口会内部处理 softmax,应按接口约定传分数。传入概率会再次变换分布,并改变梯度。不是所有框架接口默认都接收 logits。
- 把 nat 当 bit:自然对数的单位为 nat;
ln 10 ≈ 2.3对应十类均匀预测的损失,单个相同损失不能描述所有模型行为。转 bit 要除以ln 2。 - 把分数差当概率比:差
6.578对应约 719 倍,不是 6.6 倍。 - 让概率轴自动缩放:固定为
[0, 1]才能比较集中和平坦分布。 - 断言平方误差不能用于分类:它能定义概率评分;这里说明的是与 softmax 组合时的饱和优化问题,不能把它推广成所有用途的禁令。
模型范围
这里只计算一个样本,不是小批量平均。梯度止于 logit,不继续到权重;后续见反向传播。温度只缩放已训练网络的固定分数。概率和两组梯度来自真实模型与测试图像的实际计算。