☰
二阶导数与海森矩阵:牛顿法在机器学习参数优化中的微积分原理与代码实现
2026/10/21 11:28:38 网站建设 项目流程

编程场景痛点

很多机器学习参数优化问题,并不只是 “找梯度方向” 这么简单。

  • 一阶梯度下降能确定更新方向,但对局部曲率信息一无所知
  • 损失函数曲面较病态时,SGD 会在狭长沟壑中震荡收敛
  • 学习率选择敏感:过大可能发散,过小收敛缓慢
  • 只打印 loss 和梯度范数,难以判断优化是否受曲率影响
  • 想理解为什么二阶方法收敛更快,却困在矩阵推导中

从工程角度看,二阶优化的核心价值是:用二阶导数刻画损失曲面的局部曲率,并据此构造更合理的参数更新步。

微积分核心公式

1. 二阶导数:函数局部曲率

一元函数的二阶导数是一阶导数的变化率:

\(f''(x)=\frac{d^2 f}{dx^2}=\frac{d}{dx}f'(x)\)

它描述函数曲线在某点的 “弯曲程度”。二阶导数绝对值越大,曲面越弯曲;符号决定局部是凸还是凹。

2. 海森矩阵:多元二阶导数推广

若 \(L(\theta)\) 是关于参数向量 \(\theta\in\mathbb{R}^n\) 的损失函数,则海森矩阵 H 是 \(n\times n\) 的二阶偏导数矩阵:

\(H(\theta)=\nabla^2 L(\theta) =\begin{bmatrix} \frac{\partial^2 L}{\partial \theta_1^2} & \frac{\partial^2 L}{\partial \theta_1 \partial \theta_2} & \dots & \frac{\partial^2 L}{\partial \theta_1 \partial \theta_n}\\[6pt] \frac{\partial^2 L}{\partial \theta_2 \partial \theta_1} & \frac{\partial^2 L}{\partial \theta_2^2} & \dots & \frac{\partial^2 L}{\partial \theta_2 \partial \theta_n}\\[6pt] \vdots & \vdots & \ddots & \vdots\\[6pt] \frac{\partial^2 L}{\partial \theta_n \partial \theta_1} & \frac{\partial^2 L}{\partial \theta_n \partial \theta_2} & \dots & \frac{\partial^2 L}{\partial \theta_n^2} \end{bmatrix}\)

海森矩阵的特征值决定局部曲率的方向和强度。

3. 牛顿法更新规则

牛顿法用海森矩阵逆修正梯度方向:

\(\theta_{k+1}=\theta_k-\eta H(\theta_k)^{-1}\nabla L(\theta_k)\)

其中 \(\eta\) 是学习率。在纯牛顿法中,\(\eta=1\),但工程实现中通常保留学习率以增强稳定性。

4. 二次近似视角

牛顿法可理解为在当前点对损失函数做二次近似:

\(L(\theta)\approx L(\theta_k)+\nabla L(\theta_k)^T(\theta-\theta_k)+\frac{1}{2}(\theta-\theta_k)^T H(\theta_k)(\theta-\theta_k)\)

对近似函数求导并令其为零,即可得到牛顿更新方向。

5. 有限差分近似海森矩阵

工程中可用一阶导数的中心差分近似二阶导数:

\(H_{ij}\approx\frac{\frac{\partial L}{\partial \theta_i}(\theta+h e_j)-\frac{\partial L}{\partial \theta_i}(\theta-h e_j)}{2h}\)

其中 \(e_j\) 是第 j 个标准基向量。

代码实操示例

下面实现一个基于 NumPy 的逻辑回归分类器,并加入牛顿法参数更新。重点展示梯度、海森矩阵和参数更新之间的工程关系。

import numpy as np def sigmoid(z): return 1 / (1 + np.exp(-z)) def logistic_loss(X, y, theta): m = len(y) h = sigmoid(X @ theta) h = np.clip(h, 1e-12, 1 - 1e-12) return -np.mean(y * np.log(h) + (1 - y) * np.log(1 - h)) def gradient(X, y, theta): m = len(y) h = sigmoid(X @ theta) return X.T @ (h - y) / m def hessian(X, theta): m = len(theta) h = sigmoid(X @ theta) S = np.diag(h * (1 - h)) return X.T @ S @ X / m def newton_update(X, y, theta, lr=1.0): grad = gradient(X, y, theta) H = hessian(X, y, theta) H += 1e-4 * np.eye(len(theta)) delta = np.linalg.solve(H, grad) return theta - lr * delta def train(X, y, lr=1.0, epochs=10): theta = np.zeros(X.shape[1]) for epoch in range(epochs): theta = newton_update(X, y, theta, lr) loss = logistic_loss(X, y, theta) print(f"Epoch {epoch+1:2d} | loss: {loss:.6f}") return theta np.random.seed(0) n_samples, n_features = 80, 3 X = np.random.randn(n_samples, n_features) true_theta = np.array([1.2, -0.8, 0.5]) y = (sigmoid(X @ true_theta + 0.1 * np.random.randn(n_samples)) > 0.5).astype(float) theta = train(X, y, lr=1.0, epochs=10) print("Final parameters:", np.round(theta, 4))

为了保证数值稳定性,代码在海森矩阵上加了一个小的单位矩阵正则项:

H += 1e-4 * np.eye(len(theta))

这一步能避免海森矩阵奇异或接近奇异时求解失败。

不同算法对比简表

表格

优化算法使用的微积分对象更新方向工程特点
梯度下降一阶导数 / 梯度 \(\nabla L\)沿梯度反方向更新实现简单,适合大规模参数
动量法梯度 + 历史速度积累历史方向,减少震荡训练更稳定,适合深度模型
Adam一阶矩、二阶矩估计自适应学习率方向工业界常用,调参相对友好
牛顿法一阶导数 + 海森矩阵 H\(H^{-1}\nabla L\)收敛快,但计算量大
拟牛顿法(如 BFGS)梯度 + 近似海森矩阵近似 \(H^{-1}\nabla L\)避免精确求逆,适合中小规模问题
高斯 - 牛顿法雅可比矩阵构造近似海森\((J^T J)^{-1}J^T r\)常用于非线性最小二乘

一句话解读:一阶方法关注 “往哪走”,二阶方法额外关注 “走多快、走多稳”,但代价是更高的计算与存储开销。

学习总结避坑

  1. 二阶导数不是 “更高级的一阶导数”一阶导数告诉你函数往哪个方向增长;二阶导数告诉你这个方向本身如何变化。
  2. 海森矩阵不一定需要显式构造在高维问题中,直接存储和求逆海森矩阵通常不现实。拟牛顿法的工程价值正在于用梯度变化近似曲率信息。
  3. 牛顿法不代表一定更好它对初始化、学习率和海森矩阵质量敏感。初始化太差时,牛顿法可能直接发散。
  4. 正则项不是可有可无海森矩阵条件数大或奇异时,\(H^{-1}\) 会放大数值误差。加入小正则项是工程常规操作。
  5. 不要把牛顿法理解成固定步长纯牛顿法理论步长为 1,但实际训练中仍建议从较小学习率开始测试。
  6. 关注损失曲面条件数如果不同参数方向收敛速度差异很大,说明曲面较病态。此时二阶方法或自适应学习率方法通常更有优势。
  7. 学习路线建议先理解一元二阶导数,再理解海森矩阵结构,最后再看牛顿法和拟牛顿法的工程差异。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询