D2L(2) — softmax回归

30 阅读2分钟

0. 简介

线性回归是预测多少的问题,而回归亦可被用于预测哪一个的问题:

  • 某个电子邮件是否属于垃圾邮件文件夹?
  • 某个用户可能注册不注册订阅服务?
  • 某个图像描绘的是驴、狗、猫、还是鸡?
  • 某人接下来最有可能看哪部电影?

0.1 softmax和hardmax

softmax本质上就是将一个序列,变成相应的概率,并满足以下条件:

  • 所有概率值都在 [0,1][0,1] 之间;
  • 所有值加起来是 11
yj^=softmax(oj)=eoji=1neoi\hat{y_j} = softmax(o_j) = \frac{e^{o_j}}{\sum_{i=1}^{n}e^{o_i}}

假设有个输入是 [0.0,1.0,2.0][0.0, 1.0, 2.0],那么softmax计算后就是 [0.0900,0.2447,0.6652][0.0900, 0.2447, 0.6652],假设输入变为 [0.0,1.0,3.0][0.0, 1.0, 3.0],而softmax计算后就变成了 [0.0420,0.1142,0.8438][0.0420, 0.1142, 0.8438]。可以看出,softmax本质上有很强的马太效应强(大)的更强(大),弱(小)的更弱(小)

hardmax就更暴力了,针对以上两种输入,输出都是 [0.0,0.0,1.0][0.0, 0.0, 1.0],这使得其函数本身的梯度是非常稀疏的,只有被选中的变量上面才有梯度,这对于一些任务来说几乎是不可接受的。

1. 基本推导

前面的具体的推导过程我就不详述了,可以参考3.4. softmax回归。这里我说一下我个人的疑惑:

  1. 为啥使用交叉熵损失而不是平方误差?
  2. 不管是前面的线性回归,还是现在的softmax回归,其实真实的求导过程都是求得损失函数针对于参数 w\mathbf{w}bb 的导数,从而朝着梯度下降的方向挪动,为什么书上只推导了 Loj\frac{\partial L}{\partial o_j},而省略了 Lwj\frac{\partial L}{\partial w_j}

1.1 交叉熵损失

假设我们选择平方误差作为softmax的损失函数

L=12i=1m(yi^yi)2L = \frac{1}{2}\sum_{i=1}^{m}(\hat{y_i} - y_i)^2

那么其对模型logits输出的导数如下:

Loj=i=1mLyi^yi^oj\frac{\partial L}{\partial o_j} = \sum_{i=1}^{m}\frac{\partial L}{\partial \hat{y_i}} \cdot \frac{\partial \hat{y_i}}{\partial o_j}

根据之前的求导:

Lyi^=yi^yi\frac{\partial L}{\partial \hat{y_i}} = \hat{y_i} - y_i

而计算yi^oj\frac{\partial \hat{y_i}}{\partial o_j} 就需要分两种情况了:

i=ji = j 时:

yj^oj=oj(eojk=1meok)=eojk=1meokeojeoj(k=1meok)2=yi^(1yi^)\frac{\partial \hat{y_j}}{\partial o_j} = \frac{\partial}{\partial o_j}(\frac{e^{o_j}}{\sum_{k=1}^{m}e^{o_k}}) = \frac{e^{o_j}\sum_{k=1}^{m}e^{o_k} - e^{o_j}e^{o_j}}{(\sum_{k=1}^{m}e^{o_k})^2} = \hat{y_i}(1-\hat{y_i})

iji \neq j 时:

yi^oj=oj(eoik=1meok)=0k=1meokeoieoj(k=1meok)2=yi^yj^\frac{\partial \hat{y_i}}{\partial o_j} = \frac{\partial}{\partial o_j}(\frac{e^{o_i}}{\sum_{k=1}^{m}e^{o_k}}) = \frac{0 \cdot \sum_{k=1}^{m}e^{o_k} - e^{o_i}e^{o_j}}{(\sum_{k=1}^{m}e^{o_k})^2} = -\hat{y_i}\hat{y_j}

统一表达式:

yi^oj=yi^(δijyj^)δij={1,i=j0,ij\frac{\partial \hat{y_i}}{\partial o_j} = \hat{y_i}(\delta_{ij}-\hat{y_j}), \delta_{ij} = \left\{ \begin{aligned} 1, i =j \\ 0, i \neq j \end{aligned} \right.

所以最终的表达式为:

Loj=i=1m(yi^yi)yi^(δijyi^)\frac{\partial L}{\partial o_j} = \sum_{i=1}^{m}(\hat{y_i} - y_i)\hat{y_i}(\delta_{ij}-\hat{y_i})

然后这个公式面临着梯度消失问题,假设 yi=1y_i = 1,而预测值如下:

  • 当预测正确时,即 yi^1\hat{y_i}\approx1,梯度趋近于0,此时正常;
  • 当预测错误时,即 yi^0\hat{y_i}\approx0,此时梯度也趋近于0,这就不正常了,因为预测值和实际值相差很远,即错误很大,但是更新的步长也很小,这就导致训练过程会非常缓慢甚至停滞,难以逃离这个“局部陷阱”!

而当我们使用交叉熵损失时

L=i=1myilogyj^L = -\sum_{i=1}^{m}y_i\log\hat{y_j}

和上面一样:

Loj=i=1mLyi^yi^oj\frac{\partial L}{\partial o_j} = \sum_{i=1}^{m}\frac{\partial L}{\partial \hat{y_i}} \cdot \frac{\partial \hat{y_i}}{\partial o_j}

因为都是softmax表达式,所以:

yi^oj=yi^(δijyj^)δij={1,i=j0,ij\frac{\partial \hat{y_i}}{\partial o_j} = \hat{y_i}(\delta_{ij}-\hat{y_j}), \delta_{ij} = \left\{ \begin{aligned} 1, i =j \\ 0, i \neq j \end{aligned} \right.

重点是求导 Lyi^\frac{\partial L}{\partial \hat{y_i}}

Lyi^=yi^(i=1myilogyj^)=yiyi^\frac{\partial L}{\partial \hat{y_i}} = \frac{\partial}{\partial \hat{y_i}}(-\sum_{i=1}^{m}y_i\log\hat{y_j}) = -\frac{y_i}{\hat{y_i}}

其导数始终为:

Loj=i=1m(yiyi^)yi^(δijyj^)=(i=1myiδiji=1myiyj^)\frac{\partial L}{\partial o_j} = \sum_{i=1}^{m}(-\frac{y_i}{\hat{y_i}})\hat{y_i}(\delta_{ij}-\hat{y_j}) = -(\sum_{i=1}^{m}y_i\delta_{ij} - \sum_{i=1}^{m}y_i\hat{y_j})

因为i=1myi=1\sum_{i=1}^{m}y_i = 1i=1myiδij=yj(i=j时起作用)\sum_{i=1}^{m}y_i\delta_{ij} = y_j(i =j时起作用),所以:

Loj=yj^yj\frac{\partial L}{\partial o_j} = \hat{y_j} - y_j

就不会存在以上问题,其梯度与误差成正比,梯度越大,更新力度越大。

1.2 为什么书上只推导了 Loj\frac{\partial L}{\partial o_j},而省略了 Lwj\frac{\partial L}{\partial w_j}

我们的最终必然是要求损失函数针对于参数 w\mathbf{w}bb 的导数,而以上推导是是对于softmax+交叉熵损失,softmax这一层的梯度公式就是 yj^yj\hat{y_j} - y_j,与前面网络的结构没有关系。

而在softmax之前:

O=XW+b\mathbf{O} = \mathbf{X}\mathbf{W} + \mathbf{b}

这是一个线性层,所以 owj=xj\frac{\partial o}{\partial w_j} = x_j

它之所以被单独提出来详细推导,是因为:

  1. 它是一个核心且通用的结果:只要输出层是Softmax+交叉熵损失,这个梯度公式就永远是 Y^−Y,与网络前面的结构无关。
  2. 它极其简洁,体现了数学的美感。
  3. 理解这一步是理解整个反向传播过程的基础。现代的深度学习框架(如PyTorch、TensorFlow)会自动完成链式法则的其他部分,但理解这个起点的计算原理至关重要。

2. softmax回归为什么是线性模型

尽管softmax是一个非线性函数,但softmax回归的输出仍然由输入特征的仿射变换决定。 因此,softmax回归是一个线性模型(linear model)。

总的来说,softmax回归分为两个步骤:

  1. 线性部分(仿射变换)o=wx+b\mathbf{o} = \mathbf{w}\mathbf{x} + b;
  2. 非线性部分(softmax函数)yj^=softmax(oj)=eoji=1neoi\hat{y_j} = softmax(o_j) = \frac{e^{o_j}}{\sum_{i=1}^{n}e^{o_i}}

而线性部分定义了决策的边界,最终的分类决策规则始终取决于线性部分的结果,第二部分只是将输出校准为有意义的概率值,便于解释和计算损失。

一个比喻: 想象你用三个不同的秤(对应三个类别)去称一个物体(对应一个样本)。每个秤给出一个读数(对应ojo_j)。

  • softmax函数的作用就像是把这三个读数都转换成“这个物体最可能被哪个秤称出来”的概率百分比。这是一个非线性转换。
  • 但最终你判断物体属于哪个类别,依据仍然是哪个秤的原始读数最大。这个“找最大值”的决策规则是线性的。