深入理解softmax求导

一、简介

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<j$,则 $\mathrm{softmax}(\mathbf{x})_i < \mathrm{softmax}(\mathbf{x})_j$。
  • 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函数的求导是深度学习算法中必不可少的环节,对于深入理解深度学习算法具有重要意义。

原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/162656.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
小蓝小蓝
上一篇 2024-11-21 22:46
下一篇 2024-11-21 22:46

相关推荐

  • diff函数是否能够实现数值求导?

    答案是可以的。下面将从数学原理、实现过程和可行性三个方面对此进行详细阐述。 一、数学原理 求导的定义是函数在某一点的变化率,也即在该点处的斜率。而数值求导便是使用有限差分近似求解该…

    编程 2025-04-28
  • 深入解析Vue3 defineExpose

    Vue 3在开发过程中引入了新的API `defineExpose`。在以前的版本中,我们经常使用 `$attrs` 和` $listeners` 实现父组件与子组件之间的通信,但…

    编程 2025-04-25
  • 深入理解byte转int

    一、字节与比特 在讨论byte转int之前,我们需要了解字节和比特的概念。字节是计算机存储单位的一种,通常表示8个比特(bit),即1字节=8比特。比特是计算机中最小的数据单位,是…

    编程 2025-04-25
  • 深入理解Flutter StreamBuilder

    一、什么是Flutter StreamBuilder? Flutter StreamBuilder是Flutter框架中的一个内置小部件,它可以监测数据流(Stream)中数据的变…

    编程 2025-04-25
  • 深入探讨OpenCV版本

    OpenCV是一个用于计算机视觉应用程序的开源库。它是由英特尔公司创建的,现已由Willow Garage管理。OpenCV旨在提供一个易于使用的计算机视觉和机器学习基础架构,以实…

    编程 2025-04-25
  • 深入了解scala-maven-plugin

    一、简介 Scala-maven-plugin 是一个创造和管理 Scala 项目的maven插件,它可以自动生成基本项目结构、依赖配置、Scala文件等。使用它可以使我们专注于代…

    编程 2025-04-25
  • 深入了解LaTeX的脚注(latexfootnote)

    一、基本介绍 LaTeX作为一种排版软件,具有各种各样的功能,其中脚注(footnote)是一个十分重要的功能之一。在LaTeX中,脚注是用命令latexfootnote来实现的。…

    编程 2025-04-25
  • 深入探讨冯诺依曼原理

    一、原理概述 冯诺依曼原理,又称“存储程序控制原理”,是指计算机的程序和数据都存储在同一个存储器中,并且通过一个统一的总线来传输数据。这个原理的提出,是计算机科学发展中的重大进展,…

    编程 2025-04-25
  • 深入理解Python字符串r

    一、r字符串的基本概念 r字符串(raw字符串)是指在Python中,以字母r为前缀的字符串。r字符串中的反斜杠(\)不会被转义,而是被当作普通字符处理,这使得r字符串可以非常方便…

    编程 2025-04-25
  • 深入了解Python包

    一、包的概念 Python中一个程序就是一个模块,而一个模块可以引入另一个模块,这样就形成了包。包就是有多个模块组成的一个大模块,也可以看做是一个文件夹。包可以有效地组织代码和数据…

    编程 2025-04-25

发表回复

登录后才能评论