前言
分类问题是深度学习中的最基本的问题,而分类问题中,我们使用最多的就是利用\(softmax\)函数并结合\(cross \; entropy\)计算最后的损失值\(Loss\)。所以我们有必要对其进行一定的了解,并进行其求导的操作,这里的求导就相当于进行反向传播。
一、参数设置
假设我们输入一个样本,并经过一定的操作,例如卷积,全连接,dropout等一系列操作,最后,我们可以得到关于这个样本的一个长度为\(n\)的特征向量,拿到这个特征向量之后,我们往往需要对其使用\(softmax\)函数进行归一化,使之满足一个概率分布的基本条件(即所有的概率分量之和为1),然后我们使用\(cross \; entropy\)来计算最后的损失值。所以,我们不妨假设我们经过深度学习模型前向传播之后的特征向量为\(x\),所以,我们有:
\[
x = [x_1, x_2, x_3, \cdots, x_n]
\] 根据\(softmax\)的定义,我们会得到以下的特征向量经过变化之后的概率分布,有:
\[
softmax(x) = [\frac{e^{x_1}}{\sum_{i=1}^n e^{x_i}}, \frac{e^{x_2}}{\sum_{i=1}^n e^{x_i}}, \frac{e^{x_3}}{\sum_{i=1}^n e^{x_i}}, \cdots, \frac{e^{x_n}}{\sum_{i=1}^n e^{x_i}}]
\] 很容易验证上面的结果满足一个概率分布的基本条件(即所有的概率分量之和为1)。
为了表述方便,我们将上面的式子表示为:
\[
softmax(x) = [a_1, a_2, a_3, \cdots, a_n]
\] 其中,\(a_k = \frac{e^{x_k}}{\sum_{i=1}^n e^{x_i}}, \; \;(1 \leq k \leq n)\)。
我们对上面的结果和实际上给的标签\(y\)进行一定的计算,可以得到最后的损失值\(Loss\),然后我们根据这个损失值\(Loss\)进行反向传播,因此,我们不妨假设标签\(y\)为如下的形式:
\[
y = [y_1, y_2, y_3, \cdots, y_n]
\] 根据交叉熵\(cross \; entropy\)的定义,最后我们的损失值为:
\[
Loss = -\sum_{i = 1}^n y_i \; ln \;a_i
\]
二、Softmax求导
可以发现,我们改动\(x\)的任何一个分量,最后的结果会影响到每一个分量,所以,当我们需要求\(x\)的一个分量\(x_k\)的偏导数时,我们需要对上面的每一个分量\(a_i\)对\(x_k\)求偏导数。
但是,很容易可以发现上面的\(a\)的分量可以分成两类,一类是\(a_k\),另一类是\(a_i\),其中\(i \neq k\),所以不同的\(a\)的分量有不同的对\(x_k\)的偏导数求法。
\[
[\frac{\partial a_1}{\partial x_k}, \frac{\partial a_2}{\partial x_k}, \cdots, \frac{\partial a_k}{\partial x_k}, \cdots, \frac{\partial a_n}{\partial x_k}]
\]
所以,对于偏导数\(\frac{\partial a_k}{\partial x_k}\)来说,我们的计算过程如下:
\[
\frac{\partial a_k}{\partial x_k}
= \frac{\partial \frac{e^{x_k}}{\sum_{i=1}^n e^{x_i}}}{\partial x_k}
= \frac{e^{x_k}(\sum_{i=1}^n e^{x_i}) - e^{x_k}(e^{x_k})}{(\sum_{i=1}^n e^{x_i})^2}
= \frac{e^{x_k}}{\sum_{i=1}^n e^{x_i}} \cdot (1 - \frac{e^{x_k}}{\sum_{i=1}^n e^{x_i}}) = a_k \cdot (1 - a_k)
\] 对于其他的\(\frac{\partial a_j}{\partial x_k}\),其中\(j \neq k\)来说,它的偏导数计算过程如下:
\[
\frac{\partial a_j}{\partial x_k}
= \frac{\partial \frac{e^{x_j}}{\sum_{i=1}^n e^{x_i}}}{\partial x_k}
= \frac{- e^{x_j}(e^{x_k})}{(\sum_{i=1}^n e^{x_i})^2}
= - \frac{e^{x_j}}{\sum_{i=1}^n e^{x_i}} \cdot \frac{e^{x_k}}{\sum_{i=1}^n e^{x_i}}
= - a_j \cdot a_k
\]
假设我们从上一层接收到的误差为\(\delta = [\frac{\partial L}{\partial a_1}, \frac{\partial L}{\partial a_2},\frac{\partial L}{\partial a_3}, \cdots, \frac{\partial L}{\partial a_n}]\),那么,根据求导的链式法则,我们需要计算的偏导数\(\frac{\partial L}{\partial x_k}\)有:
\[
\begin{aligned}
\frac{\partial L}{\partial x_k}
&= \sum_{i = 1}^n \frac{\partial L}{\partial a_i} \cdot \frac{\partial a_i}{\partial x_k} \\
&= \sum_{i = 1, i \neq k}^n \frac{\partial L}{\partial a_i} \cdot \frac{\partial a_i}{\partial x_k} + \frac{\partial L}{\partial a_k} \cdot \frac{\partial a_k}{\partial x_k} \\
&= \sum_{i = 1, i \neq k}^n \frac{\partial L}{\partial a_i} \cdot (- a_i \cdot a_k) + \frac{\partial L}{\partial a_k} \cdot (a_k \cdot (1 - a_k)) \\
&= a_k \{\sum_{i = 1, i \neq k}^n \frac{\partial L}{\partial a_i} \cdot (- a_i) + \frac{\partial L}{\partial a_k} \cdot (1 - a_k) \} \\
&= a_k \{\sum_{i = 1, i \neq k}^n \frac{\partial L}{\partial a_i} \cdot (- a_i) + \frac{\partial L}{\partial a_k} \cdot (- a_k) + \frac{\partial L}{\partial a_k} \} \\
&= a_k \{\sum_{i = 1}^n \frac{\partial L}{\partial a_i} \cdot (- a_i)+ \frac{\partial L}{\partial a_k} \}
\end{aligned}
\] 到此为止,我们计算出了\(softmax\)层的反向传播的计算公式,下一步就是讨论交叉熵的反向传播(误差计算)。
三、交叉熵\(cross \; entropy\)的误差计算
本质上,我们的交叉熵有如下的计算公式:
\[
Loss = -\sum_{i = 1}^n y_i \; ln \;a_i
\] 根据对数的求导公式,我们很容易有:
\[
\frac{\partial L}{\partial a_i} = - y_i \frac{1}{a_i}
\] 我们下面就将上面的公式代入\(softmax\)的反向传播的公式中。
四、综合
经过前面的计算,我们有:
\[
\frac{\partial L}{\partial x_k} = a_k \{\sum_{i = 1}^n \frac{\partial L}{\partial a_i} \cdot (- a_i)+ \frac{\partial L}{\partial a_k} \}
\] 接着,我们将\(\frac{\partial L}{\partial a_i} = - y_i \frac{1}{a_i}\)代入上面的式子中,即有:
\[
\begin{aligned}
\frac{\partial L}{\partial x_k}
&= a_k \{\sum_{i = 1}^n \frac{\partial L}{\partial a_i} \cdot (- a_i)+ \frac{\partial L}{\partial a_k} \} \\
&= a_k \{\sum_{i = 1}^n - y_i \frac{1}{a_i} (-a_i) + - y_k \frac{1}{a_k} \} \\
&= a_k \{ \sum_{i = 1}^n y_i + - y_k \frac{1}{a_k} \} \\
&= a_k (\sum_{i = 1}^n y_i) + a_k (- y_k \frac{1}{a_k}) \\
&= a_k (\sum_{i = 1}^n y_i) - y_k
\end{aligned}
\] 考虑到在绝大多数情况下,给定的标签\(y\)往往是一个one-hot的向量,即\(y\)的所有分量中有且仅有一个分量的值是1,剩下的所有分量的值都是0,所以,我们有:\(\sum_{i = 1}^n y_i = 1\)。将这个式子代入上面的公式,我们可以得到一个十分简单的表达:
\[
\frac{\partial L}{\partial x_k} = a_k (\sum_{i = 1}^n y_i) - y_k = a_k - y_k = \frac{e^{x_k}}{\sum_{i=1}^n e^{x_i}} - y_k
\] 需要注意的是上面这个简单表达的使用条件:
- 使用softmax函数计算概率分布。
- 使用交叉熵计算最后的损失值。
- 标签必须是one-hot向量。
五、总结
总的来说,softmax和交叉熵的组合可以优化神经网络的表达,同时也不会引入过多的反向传播的计算开销。