一、简介
softmax函数是在深度学习和神经网络中常用的函数,主要用于多分类问题和概率分布。在反向传播算法中,softmax函数的求导是一个非常重要的过程,本文将从多个方面阐述softmax函数的求导方法。
二、softmax函数的定义
在介绍softmax函数的求导方法之前,我们先来了解一下softmax函数的定义和基本性质。
def softmax(x): shift_x = x - np.max(x) exp_x = np.exp(shift_x) return exp_x / np.sum(exp_x)
softmax函数的定义是将任意的实数向量$\mathbf{x}$映射成一个概率分布$\mathbf{p}$的函数,即:
$$ \mathrm{softmax}(\mathbf{x})_i = \frac{\exp(x_i)}{\sum_{j=1}^k \exp(x_j)} $$其中,$i \in \{1,2,\dots,k\}$,$k$ 是 $\mathbf{x}$ 中元素的个数,$x_i$ 是 $\mathbf{x}$ 的第 $i$ 个元素。
softmax函数具有以下性质:
- 每个元素都非负,并且所有元素之和为1。
- softmax函数是单调递增函数,即对于所有 $i,j$,如果 $i
- softmax函数是一个连续可微的函数。
三、softmax函数的求导方法
1. 简单情况下的求导方法
在简单情况下,我们可以根据softmax函数的定义求导。
设 $\mathbf{p} = \mathrm{softmax}(\mathbf{x})$,则:
$$ \begin{aligned} \frac{\partial p_i}{\partial x_j} &= \frac{\partial}{\partial x_j}\frac{\exp(x_i)}{\sum_{k=1}^k \exp(x_k)} \\ &= \frac{\exp(x_i) \cdot \frac{\partial}{\partial x_j}\sum_{k=1}^k \exp(x_k) - \exp(x_j) \cdot \frac{\partial}{\partial x_j}\exp(x_i)}{\left(\sum_{k=1}^k \exp(x_k)\right)^2} \\ &= \frac{\exp(x_i)}{\sum_{k=1}^k \exp(x_k)} \cdot \left(\frac{\partial}{\partial x_j}\sum_{k=1}^k \exp(x_k)\right) - \frac{\exp(x_i) \cdot \exp(x_j)}{\left(\sum_{k=1}^k \exp(x_k)\right)^2} \\ &= \frac{\exp(x_i)}{\sum_{k=1}^k \exp(x_k)} \cdot \frac{\partial}{\partial x_j}(\exp(x_j)) - \frac{\exp(x_i) \cdot \exp(x_j)}{\left(\sum_{k=1}^k \exp(x_k)\right)^2} \\ &= \begin{cases} \mathrm{softmax}(\mathbf{x})_i \cdot (1 - \mathrm{softmax}(\mathbf{x})_j) & i=j \\ -\mathrm{softmax}(\mathbf{x})_i \cdot \mathrm{softmax}(\mathbf{x})_j & i \neq j \end{cases} \end{aligned} $$这里我们使用了两个基本公式:
$$ \begin{aligned} \frac{\partial}{\partial x}\exp(x) &= \exp(x) \\ \frac{\partial}{\partial x}\sum_{i=1}^k g(x_i) &= \sum_{i=1}^k \frac{\partial}{\partial x_i} g(x_i) \end{aligned} $$2. 计算交叉熵损失函数的梯度
在深度学习中,我们通常使用交叉熵损失函数来评价模型的预测结果,交叉熵损失函数的定义是:
$$ L(y, \hat{y}) = -\sum_{i=1}^k y_i \log \hat{y}_i $$其中,$y$ 是真实的标签向量,$\hat{y}$ 是模型的预测向量。
由于交叉熵损失函数是关于$\hat{y}$的函数,因此我们需要计算 $\frac{\partial L}{\partial \hat{y}}$ 来更新模型的参数。
设 $p = \mathrm{softmax}(\mathbf{x})$,则 $\hat{y} = p$,交叉熵损失函数可以表示为:
$$ L(y, p) = -\sum_{i=1}^k y_i \log p_i $$我们需要计算 $\frac{\partial L}{\partial x_i}$ 来更新模型的参数,根据链式法则,有:
$$ \frac{\partial L}{\partial x_i} = \sum_{j=1}^k \frac{\partial L}{\partial p_j} \cdot \frac{\partial p_j}{\partial x_i} $$由于 $p$ 与 $x$ 之间的关系已经求出,我们只需要计算 $\frac{\partial L}{\partial p_j}$ 即可。
根据交叉熵损失函数的定义,有:
$$ \frac{\partial L}{\partial p_j} = -\frac{y_j}{p_j} $$将其代入上式,有:
$$ \frac{\partial L}{\partial x_i} = -\sum_{j=1}^k \frac{y_j}{p_j} \cdot \frac{\partial p_j}{\partial x_i} $$接下来,我们将 $\frac{\partial L}{\partial x_i}$ 带入求导公式,得到:
$$ \frac{\partial L}{\partial x_i} = \begin{cases} (p_i - y_i) & i \in \{1,2,\dots,k\} \\ \end{cases} $$这个式子非常有用,我们可以直接使用它来更新模型的参数,例如在使用SGD、Adam等优化算法的时候。
3. 使用矩阵运算简化求导过程
在实际中,我们通常使用矩阵形式表示softmax函数,即:
$$ \mathrm{softmax}(\mathbf{x}) = \frac{\exp(\mathbf{x})}{\mathbf{1}^\mathrm{T} \exp(\mathbf{x})} $$其中,$\mathbf{x} \in \mathbb{R}^d$ 是输入向量,$\mathbf{1}$ 是全1向量。
我们可以使用矩阵运算来简化求导过程。
首先,我们定义:
$$ \mathbf{P} = \mathrm{softmax}(\mathbf{x}) \\ \mathbf{Y} = \mathrm{diag}(\mathbf{y}) \\ \mathbf{J} = \mathbf{P} - \mathbf{Y} $$其中,$\mathrm{diag}(\cdot)$ 表示将向量转化成对角矩阵。
根据第2节的求导公式,我们有:
$$ \frac{\partial L}{\partial x_i} = \sum_{j=1}^k \frac{\partial L}{\partial p_j} \cdot \frac{\partial p_j}{\partial x_i} $$根据求导公式,我们可以将 $\frac{\partial L}{\partial p_j}$ 表示为:
$$ \frac{\partial L}{\partial p_j} = -\frac{y_j}{p_j} = -y_j \cdot (\mathbf{P})_j = (\mathbf{Y})_{jj}(\mathbf{P})_{j} = (\mathbf{Y} \odot \mathbf{P})_{j} $$其中,$\odot$ 表示依元素相乘。
同样的,我们可以将 $\frac{\partial p_j}{\partial x_i}$ 表示为:
$$ \frac{\partial p_j}{\partial x_i} = \begin{cases} p_i \cdot (1 - p_i) & i=j \\ -p_i \cdot p_j & i \neq j \end{cases} = \begin{cases} (\mathbf{P})_i (1 - (\mathbf{P})_i) & i=j \\ -(\mathbf{P})_i (\mathbf{P})_j & i \neq j \end{cases} = \begin{cases} (\mathbf{P} \odot (1-\mathbf{P}))_i & i=j \\ -(\mathbf{P} \odot \mathbf{P})_{i,j} & i \neq j \end{cases} $$使用矩阵运算,我们可以得到:
$$ \frac{\partial L}{\partial x} = \mathbf{J}^\mathrm{T} $$这个式子跟第2节的公式是等价的。
总结
本文从多个方面详细阐述了softmax函数的求导方法,并介绍了如何使用矩阵运算来简化求导过程。在深度学习和神经网络中,softmax函数是非常重要的函数,softmax函数的求导是深度学习算法中必不可少的环节,对于深入理解深度学习算法具有重要意义。