机器学习中的雅可比行列式和梯度

2025 年 6 月 19 日 | 阅读 9 分钟

机器学习有各种基础数学结构,其中 Jacobian 和 Gradient 被认为是训练神经网络、对输入敏感的模型和优化的最突出的结构之一。

梯度是标量函数相对于其输入变量的偏导数向量,代表最陡峭上升或下降的方向。梯度在基于梯度的优化方法(如随机 梯度下降)中很重要,用于在模型训练期间最小化函数损失。Jacobian 是梯度对向量值函数的推广。它实际上是一个由一阶偏导数组成的矩阵,每个组成元素代表一个输出变量相对于一个输入变量的变化率。Jacobian 在 深度学习 中被广泛用于计算多输出系统的导数,例如,在使用反向传播处理神经网络时,为了有效地在层之间传播误差。

在这里,我们将使用 JAX 来查看 Jacobian 和 Gradient。

这种表示是一个多元函数,它接受 n 个输入并只产生一个标量。在计算这类函数时,我们将得到偏导数,假设其余变量为常数。然后,梯度向量 ∇f(x) 将这些偏导数组合为一个向量,该向量定义了函数相对于每个变量的变化率。

Python 中的 JAX 库包含转换器 jax.grad(),它计算用户定义的标量函数的梯度。这个工具可以自动计算梯度,因为它遵循梯度仅适用于函数 f: R^n →R 的原理。

因此,例如,通过使用 jax.grad(),我们可以计算一个 3D 抛物面的梯度,并将其正确性与显式数学梯度进行验证。

输出

Jacobian and Gradient in Machine Learning

除了输入变量,您还需要将这些变量的系数传递给您的 Python 函数。例如,我们想在 6 维空间中创建一个抛物面,并让每个维度中的变量与其系数相乘。这可以定义,以及它的梯度,如下所示:

∇f(x)=[ 6x1,4x2,10x3 ,2x4 ,8x5 ]^T

输出

[12.  4. 30.  4. 32.]

两个最受欢迎的深度学习库,TensorFlowPyTorch,都使用计算图来进行神经网络的高效微分。计算图被用作数据结构,用于跟踪与模型参数相关的所有数学运算,以便通过反向传播计算所有网络层的梯度。虽然这种方法在微分方面非常有效,但它与微积分背后的数学原理略有偏离。相反,JAX 直接在微分过程中处理函数,因此与微积分的核心数学非常吻合。这意味着我在数学上理论上的操作与在代码中实践的操作在使用 JAX 时不会偏离,就像这个 notebook 所展示的一样。

您可能还会问,通过 JAX 对网络进行微分需要什么。实际上非常简单。我们定义一个损失函数,该函数由两个操作组成,即在批次级别进行前向传播和误差计算,然后计算相对于模型参数的梯度。JAX 中的损失函数仅将模型参数和输入数据作为参数。它不会产生笨拙的参数列表,因为 JAX 具有高效的数据结构 **pytrees**,可以有效地处理大型和嵌套的数据格式。

在前向传播中,它首先计算预测值,然后使用基于这些预测值的损失函数计算总误差。在后向传播中,它找出损失相对于模型参数的梯度。JAX 引入了一个名为 `jax.value_and_grad()` 的转换器,它通过创建一个同时执行前向和后向传播的函数来简化上述过程。将损失函数通过此转换器会生成一个输出函数,该函数可以同时返回损失值及其梯度值。让我们将此转换器传递给上面的线性模型,以实现前向和后向传播。

输出

Jacobian and Gradient in Machine Learning

我们计算了总损失和即时梯度,同时还检查了 JAX 如何处理包含容器和结构的微分,就像示例中使用的这个小字典一样。要微分此函数,它会逐个叶子进行,并在结构中的每个“叶子”处进行微分。我们希望将神经网络参数封装在此类容器中,其结构类似于 pytree。此容器将包含几个子字典,并且特定部分、片段或网络参数的层将分配给它们。

有限差分

有限差分是估计输入变化如何导致函数输出变化的度量。它基于导数中提出的基本思想,意味着它是函数对其输入的敏感度。这些近似有助于通过验证导数来检查数值解是否确实满足微分方程。

有三种主要的有限差分方法:前向差分,其中输入增加;后向差分,其中输入减少;中心差分,其中考虑两侧的变化。所有方法都衡量输入变化的影响,但应用这些变化的方式不同。将差分除以输入的变动量可以近似导数。

全微分比偏微分更通用,因为它同时考虑所有输入变量。它可以看作是方向导数的扩展,特别适用于向量值函数 f: R^n →R^m。

这些函数由多个多元函数组成,每个函数产生输出的一个标量分量。对于这类函数,全微分会生成一个 Jacobian 矩阵,其中每一行对应于一个多元分量的梯度。

输出

True

Hessian 矩阵

我们讨论过,多元函数中的每个输入变量都会进行偏微分。这些被组合起来形成梯度,梯度是一个向量值函数。梯度微分得到 Hessian 矩阵,它是一个方阵,描述了函数的二阶偏导数。Hessian 矩阵始终是方形的 (n×n),因为梯度的定义域和余定义域都在同一个欧几里得空间中。

Hessian 矩阵使用二阶泰勒展开式(即牛顿法)来近似多元函数。这可能比梯度下降更快地收敛到最小值。例如,牛顿法可以在一次迭代中完全优化线性回归,并且由于 Hessian 的逆会自动调整步长,因此可以摆脱学习率。然而,牛顿法并非在所有情况下都是最佳的。如果给定的函数在该凹区域有一个局部最大值,优化可能不正确。此外,对于像神经网络这样的大型模型,计算和存储 Hessian 矩阵会导致计算复杂度随参数数量呈立方增长。尽管存在这些缺点,但 BFGS 和 Levenberg-Marquardt 等方法被用来克服牛顿法的问题。Hessian 矩阵在分析函数的凸性方面也很有用。通过将其分解为特征值,我们可以知道函数是凸的、凹的还是沿着每个坐标轴是平坦的,这有助于理解函数的行为。

Jacobian and Gradient in Machine Learning

我们可以直接从 Hessian 矩阵的对角线条目读取其特征值,因为所有其他条目都为零。函数的凸性

g 始终是均匀弯曲的;它在 x 轴方向上处处凸,在 y 轴方向上处处凹。相反,函数

f 在第二个基向量(y 轴)上的曲率取决于输入 y 的值。这些凸性性质在下面的图中得到了进一步说明。

Jacobian and Gradient in Machine Learning

当函数有超过两个输入变量时,函数会推入更高维空间,例如四维或更多。在这种情况下,探索这些函数的 Hessian 矩阵对于理解它们的凸性和整体行为至关重要。使用 JAX,我们可以计算多变量函数的 Hessian,并将结果与一些手动创建的 Hessian 矩阵进行比较。以下代码通过计算两个函数的 Hessian 并进行比较来说明此过程。

输出

Jacobian and Gradient in Machine Learning
Jacobian and Gradient in Machine Learning

我们试图区分多元函数和向量值函数。正如我们的目标那样,我们正在研究偏导数、全导数和有限差分。然而,这些概念如何应用于自动微分仍有待研究。这实际上将是下一个 notebook 的主要问题。