🧠 目标
我们要计算的是:
给定模型输出 logits z=[z1,z2,...,zC]\mathbf{z} = [z_1, z_2, ..., z_C]z=[z1,z2,...,zC],Softmax 后得到预测概率 y^=[y^1,...,y^C]\hat{\mathbf{y}} = [\hat{y}_1, ..., \hat{y}_C]y^=[y^1,...,y^C],交叉熵损失函数为:
L=−∑i=1Cyilog(y^i) L = -\sum_{i=1}^C y_i \log(\hat{y}_i) L=−i=1∑Cyilog(y^i)
我们要推导损失对 z\mathbf{z}z 的梯度,也就是:
∂L∂zj \frac{\partial L}{\partial z_j} ∂zj∂L
📘 步骤概览:
-
定义 softmax:
y^i=ezi∑k=1Cezk \hat{y}i = \frac{e^{z_i}}{\sum{k=1}^C e^{z_k}} y^i=∑k=1Cezkezi
-
定义交叉熵:
L=−∑i=1Cyilog(y^i) L = -\sum_{i=1}^C y_i \log(\hat{y}_i) L=−i=1∑Cyilog(y^i)
-
合并并对 zjz_jzj 求导:
🧮 步骤一:对 softmax 求导
对于 softmax 输出的 y^i\hat{y}_iy^i,对 zjz_jzj 求导:
- 当 i=ji = ji=j 时:
∂y^i∂zj=y^i(1−y^i) \frac{\partial \hat{y}_i}{\partial z_j} = \hat{y}_i (1 - \hat{y}_i) ∂zj∂y^i=y^i(1−y^i)
- 当 i≠ji \ne ji=j 时:
∂y^i∂zj=−y^iy^j \frac{\partial \hat{y}_i}{\partial z_j} = -\hat{y}_i \hat{y}_j ∂zj∂y^i=−y^iy^j
或者统一地写成:
∂y^i∂zj=y^i(δij−y^j) \frac{\partial \hat{y}_i}{\partial z_j} = \hat{y}i (\delta{ij} - \hat{y}_j) ∂zj∂y^i=y^i(δij−y^j)
其中 δij\delta_{ij}δij 是 Kronecker delta,若 i=ji = ji=j 则为 1,否则为 0。
🧮 步骤二:对损失函数求导
回忆损失函数:
L=−∑i=1Cyilog(y^i) L = -\sum_{i=1}^C y_i \log(\hat{y}_i) L=−i=1∑Cyilog(y^i)
对 zjz_jzj 求导(链式法则):
∂L∂zj=−∑i=1Cyi⋅1y^i⋅∂y^i∂zj \frac{\partial L}{\partial z_j} = -\sum_{i=1}^C y_i \cdot \frac{1}{\hat{y}_i} \cdot \frac{\partial \hat{y}_i}{\partial z_j} ∂zj∂L=−i=1∑Cyi⋅y^i1⋅∂zj∂y^i
代入 softmax 的导数:
∂L∂zj=−∑i=1Cyi⋅1y^i⋅y^i(δij−y^j)=−∑i=1Cyi(δij−y^j) \frac{\partial L}{\partial z_j} = -\sum_{i=1}^C y_i \cdot \frac{1}{\hat{y}i} \cdot \hat{y}i (\delta{ij} - \hat{y}j) = -\sum{i=1}^C y_i (\delta{ij} - \hat{y}_j) ∂zj∂L=−i=1∑Cyi⋅y^i1⋅y^i(δij−y^j)=−i=1∑Cyi(δij−y^j)
展开求和:
∂L∂zj=−yj(1−y^j)+∑i≠jyiy^j \frac{\partial L}{\partial z_j} = -y_j (1 - \hat{y}j) + \sum{i \ne j} y_i \hat{y}_j ∂zj∂L=−yj(1−y^j)+i=j∑yiy^j
由于 ∑i≠jyi=1−yj\sum_{i \ne j} y_i = 1 - y_j∑i=jyi=1−yj,可化简为:
∂L∂zj=y^j−yj \frac{\partial L}{\partial z_j} = \hat{y}_j - y_j ∂zj∂L=y^j−yj
✅ 结论:最终梯度公式
∂L∂zj=y^j−yj \boxed{ \frac{\partial L}{\partial z_j} = \hat{y}_j - y_j } ∂zj∂L=y^j−yj
也就是说,Softmax + 交叉熵一起用时,最终反向传播时的梯度是预测概率减去真实标签。
📌 优点
- ✅ 数值稳定 :因为常用实现将 Softmax + CrossEntropy 合并在一起(如 PyTorch 中的
CrossEntropyLoss
),避免了显式计算 log(softmax(x)),从而防止 underflow/overflow。 - ✅ 高效:只需要一减法操作,计算非常快。
- ✅ 简单清晰:可以直接用误差向量反向传播。