总结

总结一下为什么分类任务用 交叉熵损失 比较好,而不用 MSE 等损失函数:

  • 交叉熵的梯度便于计算,例如对于逻辑回归的线性层参数 $w_i$ 来说,交叉熵的梯度是 $(p-y)x_i$;而 MSE 的梯度是 $(p - y) \cdot p \cdot (1 - p) \cdot x_i$。
  • 交叉熵的梯度与预测误差成正比,误差越大梯度越大,有利于模型训练;而 MSE 的梯度还受到预测概率距离 $\frac{1}{2}$ 的距离影响,可能出现误差很大但几乎梯度几乎为 0 的情况。

Sigmoid + 交叉熵

对于使用了 Sigmoid 激活函数、交叉熵损失 的二分类问题来说,我们有: $$ \begin{aligned} z &= \mathbf{w}\mathbf{x} + b &\text{(线性层)}\\ p &= \sigma(z) = \frac{1}{1 + e^{-z}} &\text{(Sigmoid)}\\ \mathcal{L} &= -[y \log p + (1-y) \log (1 - p)] &\text{(交叉熵损失)}\\ \end{aligned} $$ 注意这里的 $\mathbf{w}$ 是一个 $n$ 维向量,对应样本的 $n$ 维特征 $\mathbf{x}$。

我们依次向前求导,首先求 $\mathcal{L}$ 对 $p$ 的导数(交叉熵损失): $$ \frac{\partial\mathcal{L}}{\partial p} = -\frac{y}{p} + \frac{1-y}{1-p} $$ 然后求 $p$ 对 $z$ 的导数(Sigmoid 函数): $$ \frac{\partial p}{\partial z} = \sigma(z)(1-\sigma(z)) = p (1 - p) $$ 再求 $z$ 对 $w_i$ 的导数(线性层): $$ \frac{\partial z}{\partial w_i} = x_i $$ 我们将以上三式的导数串起来,可以得到: $$ \begin{aligned} \frac{\partial\mathcal{L}}{\partial w_i} &= \frac{\partial\mathcal{L}}{\partial p} \frac{\partial p}{\partial z} \frac{\partial z}{\partial w_i} \\ &= (-\frac{y}{p} + \frac{1-y}{1-p}) \cdot (p (1 - p)) \cdot (x_i) \\ &= (-y \cdot (1 - p) + (1 - y) \cdot p) \cdot x_i \\ &= (p - y) \cdot x_i \end{aligned} $$

在此场景下,梯度的大小与输出的绝对误差 $(p-y)$ 成正比,错得越多,学得越快;当学习接近结束的时候,梯度逐渐趋近于 0。

Sigmoid + MSE

与前面类似,我们有: $$ \begin{aligned} z &= \mathbf{w}\mathbf{x} + b &\text{(线性层)}\\ p &= \sigma(z) = \frac{1}{1 + e^{-z}} &\text{(Sigmoid)}\\ \mathcal{L} &= \frac{1}{2} (y - p)^2 &\text{(MSE)}\\ \end{aligned} $$

我们求 $\mathcal{L}$ 对 $p$ 的导数(MSE): $$ \frac{\partial\mathcal{L}}{\partial p} = p - y $$ 而 $p$ 对 $z$ 的导数 $\frac{\partial p}{\partial z}$(Sigmoid 函数)、$z$ 对 $w_i$ 的导数 $\frac{\partial z}{\partial w_i}$(线性层)与前文一致,因此我们将他们相乘,可以得到 $\mathcal{L}$ 对第 $i$ 个参数 $w_i$ 的导数: $$ \begin{aligned} \frac{\partial\mathcal{L}}{\partial w_i} &= \frac{\partial\mathcal{L}}{\partial p} \frac{\partial p}{\partial z} \frac{\partial z}{\partial w_i} \\ &= (p - y) \cdot (p (1 - p)) \cdot (x_i) \\ &= (p - y) \cdot p \cdot (1 - p) \cdot x_i \\ \end{aligned} $$ 该梯度不仅与模型输出的误差 $(p-y)$ 成正比,也受到输出的概率值 $p$ 的影响。也就是说,当错误程度相当时,输出概率值越接近于 $\frac{1}{2}$,梯度越大;输出概率值越接近于 0 和 1 时,梯度越饱和。这就可能导致一个问题,当输出的误差 $(p-y)$ 较高时,若输出概率接近于 0 或 1(例如 $y\sim 1$、$p\sim 0$),那么模型也会几乎不更新。

Softmax + 交叉熵

对于使用了 Softmax 函数、交叉熵损失 的 $K$ 分类问题来说,我们有:

$$ \begin{aligned} z &= \mathbf{w}\mathbf{x} + b &\text{(线性层)} \\ p_i &= \frac{e^{z_i}}{\sum_{j=1}^K e^{z_j}} &\text{(Softmax 函数)} \\ \mathcal{L} &= - \sum_{i=1}^K y_i \log p_i &\text{(交叉熵损失函数)} \\ \end{aligned} $$

我们依次向前求导,首先求 $\mathcal{L}$ 对第 $i$ 个类别 $p_i$ 的导数(交叉熵损失):

$$ \frac{\partial\mathcal{L}}{\partial p_i} = - \frac{y_i}{p_i} $$

事实上,因为多分类任务中只有一个类别为真,因此在后面的步骤中我们会在某个地方约掉其他类别的梯度反传。

然后我们求 $p_i$ 对 $z_j$ 的导数(Softmax 函数),注意这里 $p_i$ 表示经过 Softmax 之后的第 $i$ 个类别的输出概率,$z_j$ 表示经过线性层之后的第 $j$ 个类别的输出,即: $$ \frac{\partial p_i}{\partial z_j} = \frac{\partial}{\partial z_j} (\frac{e^{z_i}}{\sum_{k=1}^K e^{z_k}}) $$ 因为分母受所有类别 $z_k$($1\le k\le K$)影响,而分子只受第 $i$ 个类别 $z_i$ 影响,而我们要求对 $z_j$ 的偏导,这里应该分为 $i=j$、$i\ne j$ 两种情况求导: $$ \begin{aligned} &\text{if } i=j \text{: } &\frac{\partial p_i}{\partial z_j} &= \frac{(e^{z_i} \cdot \sum_{k=1}^K e^{z_k}) - (e^{z_i} \cdot e^{z_i})} {(\sum_{k=1}^K e^{z_k})^2} \\ &&&= \frac{e^{z_i}}{\sum_{k=1}^K e^{z_k}} - (\frac{e^{z_i}}{\sum_{k=1}^K e^{z_k}})^2 \\ &&&= p_i - p_i^2 \\ &&&= p_i(1 - p_i) \\ &\text{if } i\ne j \text{: } &\frac{\partial p_i}{\partial z_j} &= \frac{(0 \cdot \sum_{k=1}^K e^{z_k}) - (e^{z_j} \cdot e^{z_i})} {(\sum_{k=1}^K e^{z_k})^2} \\ &&&= - \frac{e^{z_i}}{\sum_{k=1}^K e^{z_k}} \frac{e^{z_j}}{\sum_{k=1}^K e^{z_k}} \\ &&&= - p_i p_j\\ \end{aligned} $$

然后求 $z$ 对 $w_i$ 的导数(线性层): $$ \frac{\partial z}{\partial w_i} = x_i $$ 至此,我们将前面求得的结果串起来求对参数 $w_j$ 的导数,注意其中的 $i$ 指示了唯一正确的类别 $y_i = 1$: $$ \begin{aligned} \frac{\partial\mathcal{L}}{\partial w_j} &= \frac{\partial\mathcal{L}}{\partial\mathcal{p}} \frac{\partial\mathcal{p}}{\partial \mathbf{z}} \frac{\partial \mathbf{z}}{\partial w_j} \\ &= (\sum_{k=1}^K \frac{\partial\mathcal{L}}{\partial p_k} \frac{\partial p_k} {\partial \mathbf{z}}) \frac{\partial \mathbf{z}}{\partial w_j} \\ &= ( \left[ (-\frac{y_i}{p_i}) (p_i(1-p_i)) \right] + \left[ \sum_{k=1, k\ne i}^K (-\frac{y_k}{p_k}) (- p_i p_k) \right]) x_j \\ &= \left[ y_i (p_i - 1) + \sum_{k=1, k\ne i}^K y_k p_i \right] x_j \\ &= \left[ -y_i + \sum_{k=1}^K y_kp_i \right] x_j \\ &= (p_i-y_i) \cdot x_j \end{aligned} $$ 其实跟 Sigmoid + 交叉熵最后算出来的结果 $(p - y) \cdot x_j$ 基本一致。