Skip to content

牛顿法 vs 梯度下降——二阶优化的力量 ​

2026年5月25日 · 预计阅读20分钟

核心结论:牛顿法利用二阶导数(Hessian矩阵)同时考虑梯度方向和曲率,在极值点附近达到二次收敛——每步有效数字翻倍。梯度下降只用一阶导数,线性收敛。本文从多元牛顿法推导到阻尼牛顿法、BFGS拟牛顿法,完整代码见第四节。在Rosenbrock函数上,牛顿法13步收敛,梯度下降用了247步。

关键词:牛顿法,梯度下降,Hessian矩阵,二次收敛,BFGS,Rosenbrock函数,阻尼牛顿法


01 目标函数与极值分析 ​

为便于量化对比,首先选定合成目标函数:

f(x)=x4−3x3+2

其一阶和二阶导数解析表达式如下:

f′(x)=4x3−9x2=x2(4x−9)f″(x)=12x2−18x=6x(2x−3)

令 f′(x)=0 解得两个驻点:

  • x=0:f″(0)=0,为鞍点(saddle point)
  • x=2.25:f″(2.25)=20.25>0,确认该点为局部极小值点

全局极小值即 x∗=2.25,对应的函数值 f(2.25)≈−6.54。该极值点解析已知,便于后续精确比较两类算法的收敛速度和精度。

02 算法原理 ​

2.1 梯度下降法(一阶) ​

梯度下降法的核心思想是沿负梯度方向迭代,因为梯度指向函数值上升最快的方向:

xk+1=xk−α⋅f′(xk)

其中 α>0 为步长(学习率)。该方法仅利用一阶导数信息,实现简单,但存在以下问题:

  • 步长敏感:α 过大导致震荡发散,过小则收敛极慢
  • 线性收敛:误差 ek=|xk−x∗| 满足 ek+1≈C⋅ek,收敛因子 C<1 但接近 1 时速度极慢
  • 山谷效应:在狭长山谷区域容易反复震荡

2.2 牛顿法(二阶) ​

牛顿法利用二阶导数信息,通过局部二次泰勒展开构造逼近函数,直接跳到近似极值点。

对目标函数 f(x) 在当前点 xk 处做二阶泰勒展开:

f(xk+Δx)≈f(xk)+f′(xk)Δx+12f″(xk)(Δx)2

将右侧视为 Δx 的二次函数,令其导数等于零:

ddΔx[f(xk)+f′(xk)Δx+12f″(xk)(Δx)2]=f′(xk)+f″(xk)Δx=0

解得:

Δx=−f′(xk)f″(xk)

于是牛顿法迭代公式为:

xk+1=xk−f′(xk)f″(xk)

直观理解:牛顿法在每一步用二次抛物线逼近原函数,然后直接走到该抛物线的极值点。在极值点附近,原函数本身近似二次,因此牛顿法能实现极速收敛。

2.3 二次收敛性证明 ​

设 x∗ 为极小值点,满足 f′(x∗)=0。在当前点 xk 处对 f′(x) 做一阶泰勒展开:

f′(xk)=f′(x∗)+f″(x∗)(xk−x∗)+O((xk−x∗)2)

由于 f′(x∗)=0,代入牛顿法迭代公式:

xk+1−x∗=xk−x∗−f′(xk)f″(xk)=xk−x∗−f″(x∗)(xk−x∗)+O((xk−x∗)2)f″(xk)

在 xk 充分接近 x∗ 时,f″(xk)≈f″(x∗),于是:

xk+1−x∗≈f‴(x∗)2f″(x∗)(xk−x∗)2

即误差满足二次收敛关系:

|ek+1|≈C⋅|ek|2

这意味着每迭代一次,有效数字翻倍。例如若当前误差为 10−3,下一步误差降至 10−6,再下一步降至 10−12。相比之下,梯度下降的线性收敛 ek+1≈C⋅ek 只能实现每步固定倍率衰减,差距在接近极值点时尤为显著。

2.4 收敛阶对比:线性 vs 二次 ​

收敛类型递推关系特点典型迭代次数(精度 10−6)
线性收敛(梯度下降)ek+1=Cek每步误差固定比例衰减数十至数百步
二次收敛(牛顿法)ek+1=Cek2每步有效数字翻倍5-8 步

03 多元牛顿法 ​

现实优化问题几乎都是多变量的。将一维牛顿法推广到 n 维空间,梯度变为向量,二阶导数变为 Hessian 矩阵。

3.1 向量形式推导 ​

设 f:Rn→R,在当前点 xk∈Rn 处做二阶泰勒展开:

f(xk+Δx)≈f(xk)+∇f(xk)⊤Δx+12Δx⊤HkΔx

其中 ∇f(xk)∈Rn 为梯度向量,Hk=∇2f(xk)∈Rn×n 为 Hessian 矩阵。对 Δx 求导并令其为零:

∇f(xk)+HkΔx=0

解得多元牛顿法更新公式:

xk+1=xk−Hk−1∇f(xk)

3.2 简单二维示例 ​

考虑二维二次函数:

f(x,y)=x2+2y2

梯度 ∇f=[2x,4y]⊤,Hessian 矩阵 H=[2004]。由于 Hessian 为常数正定矩阵,牛顿法一步即可收敛至极值点 (0,0),不受初始点影响。

python
import numpy as np

def f_2d(x):
    return x[0]**2 + 2*x[1]**2

def grad_2d(x):
    return np.array([2*x[0], 4*x[1]])

def hess_2d(x):
    return np.array([[2, 0], [0, 4]])

x0 = np.array([3.0, 4.0])
H_inv = np.linalg.inv(hess_2d(x0))
x1 = x0 - H_inv @ grad_2d(x0)

print(f"初始点: {x0}")
print(f"一步后: {x1}")
初始点: [3. 4.]
一步后: [0. 0.]

这就是牛顿法的魅力——对于二次函数,无论起始点在哪,牛顿法总能在一步内精确找到极值点。

左图:一维函数 f(x)=x4−3x3+2 上梯度下降与牛顿法的收敛路径。红色点线为梯度下降(28步收敛),蓝色点线为牛顿法(5步收敛)。右图:对数坐标下的误差衰减对比,牛顿法的二次收敛呈抛物线式下降,梯度下降呈线性衰减。

3.3 高维代价 ​

然而,多元牛顿法面临严重的计算负担:

  • Hessian 矩阵有 n2 个元素,存储开销 O(n2)
  • 矩阵求逆需 O(n3) 计算量
  • 当 n=106(典型深度学习规模)时,Hessian 存储需要 4×1012 字节(4TB),完全不可行

这就是为什么大规模优化仍需依赖仅使用一阶梯度的方法(如 SGD、Adam)。


04 阻尼牛顿法(Damped Newton) ​

纯牛顿法存在一个严重问题:当 Hessian 矩阵不正定(即存在负特征值或零特征值)时,牛顿步可能指向极大值方向或鞍点,导致迭代发散。

阻尼牛顿法的解决方案是在牛顿方向中加入步长搜索(line search):

xk+1=xk−αk⋅Hk−1∇f(xk)

其中步长 αk>0 通过一维搜索确定,确保每次迭代函数值下降。实践中多采用 Armijo 条件(充分下降条件)进行非精确线搜索:

f(xk+αdk)≤f(xk)+c⋅α⋅∇f(xk)⊤dk

其中 dk=−Hk−1∇f(xk) 为牛顿方向,c∈(0,1) 为常数(通常取 10−4)。

python
import numpy as np

def damped_newton_step(f, grad, hess, x, c=1e-4, beta=0.5, max_ls=30):
    """阻尼牛顿法单步迭代(含 Armijo 线搜索)"""
    g = grad(x)
    H = hess(x)
    d = -np.linalg.solve(H, g)  # 牛顿方向

    alpha = 1.0
    f_current = f(x)
    for _ in range(max_ls):
        x_new = x + alpha * d
        if f(x_new) <= f_current + c * alpha * g @ d:
            break
        alpha *= beta
    return x + alpha * d, alpha

关键点:在 Hessian 正定区域,αk=1 即为纯牛顿法,保持二次收敛速度;在非正定区域,通过缩小步长确保下降,避免发散。


05 拟牛顿法(BFGS / L-BFGS) ​

阻尼牛顿法虽解决了稳定性问题,但 Hessian 矩阵的计算和求逆成本依然高昂。拟牛顿法(Quasi-Newton Methods) 的核心思想是:不直接计算 Hessian,而是利用相邻两步的梯度差来近似 Hessian(或其逆矩阵)。

5.1 BFGS 算法 ​

BFGS(Broyden-Fletcher-Goldfarb-Shanno)是最流行的拟牛顿法之一。它维护一个 Hessian 逆矩阵的近似 Bk≈Hk−1,并在每步利用梯度差进行对称秩二更新。

定义:

sk=xk+1−xk,yk=∇f(xk+1)−∇f(xk)

BFGS 更新公式:

Bk+1=(I−skyk⊤yk⊤sk)⊤Bk(I−yksk⊤yk⊤sk)+sksk⊤yk⊤sk

使用 Bk 后,牛顿步变为:

xk+1=xk−αk⋅Bk∇f(xk)

这样避免了显式计算 Hessian 和矩阵求逆,每步仅需 O(n2) 计算量。

5.2 L-BFGS ​

L-BFGS(Limited-memory BFGS) 进一步优化了存储。它不存储完整的 n×n 矩阵,而是仅存储最近 m 步的 {si,yi} 对(通常 m=5∼20),利用这些向量隐式重建 Hessian 近似。这使得 L-BFGS 的存储和计算量降至 O(mn),可以处理百万级参数的问题,是中小规模机器学习(如逻辑回归、CRF)的标准优化器。


06 收敛速度对比实验 ​

下面用代码对比梯度下降、牛顿法和阻尼牛顿法在一维目标函数上的表现。

python
import numpy as np

f  = lambda x: x**4 - 3*x**3 + 2
df = lambda x: 4*x**3 - 9*x**2
d2f = lambda x: 12*x**2 - 18*x

x0, n_iter = 3.0, 30

# ===== 梯度下降 =====
alpha_gd = 0.01
x_gd = np.zeros(n_iter); x_gd[0] = x0
for i in range(1, n_iter):
    x_gd[i] = x_gd[i-1] - alpha_gd * df(x_gd[i-1])

# ===== 纯牛顿法 =====
x_nt = np.zeros(n_iter); x_nt[0] = x0
for i in range(1, n_iter):
    h = d2f(x_nt[i-1])
    if abs(h) > 1e-12:
        x_nt[i] = x_nt[i-1] - df(x_nt[i-1]) / h
    else:
        x_nt[i] = x_nt[i-1]

# ===== 阻尼牛顿法(Armijo 线搜索) =====
x_dnt = np.zeros(n_iter); x_dnt[0] = x0
for i in range(1, n_iter):
    h = d2f(x_dnt[i-1])
    if abs(h) < 1e-12:
        x_dnt[i] = x_dnt[i-1]; continue
    d = -df(x_dnt[i-1]) / h
    alpha = 1.0
    f_cur = f(x_dnt[i-1])
    for _ in range(20):
        x_try = x_dnt[i-1] + alpha * d
        if f(x_try) <= f_cur + 1e-4 * alpha * df(x_dnt[i-1]) * d:
            break
        alpha *= 0.5
    x_dnt[i] = x_dnt[i-1] + alpha * d
python
tol = 1e-3
x_star = 2.25

gd_steps = np.argmax(np.abs(x_gd - x_star) < tol) + 1
nt_steps = np.argmax(np.abs(x_nt - x_star) < tol) + 1
dnt_steps = np.argmax(np.abs(x_dnt - x_star) < tol) + 1

print(f"梯度下降收敛步数: {gd_steps}")
print(f"纯牛顿法收敛步数: {nt_steps}")
print(f"阻尼牛顿法收敛步数: {dnt_steps}")
梯度下降收敛步数: 28
纯牛顿法收敛步数: 5
阻尼牛顿法收敛步数: 5

纯牛顿法和阻尼牛顿法均只需 5 步即收敛至精度 10−3,而梯度下降需 28 步——效率差距超过 5 倍。在接近极值点处,牛顿法的二次收敛优势尤为明显:最后几步误差呈平方级骤降。

指标梯度下降纯牛顿法阻尼牛顿法
收敛迭代次数(|x−2.25|<10−3)2855
收敛速度线性二次二次
步长依赖敏感(需调参)无需自适应
每步计算量O(n)O(n3)O(n3)

07 Rosenbrock函数等高线对比 ​

Rosenbrock 函数是优化领域的经典测试函数,其定义如下:

f(x,y)=(1−x)2+100(y−x2)2

该函数在 (1,1) 处取全局极小值 f=0,但围绕该点形成一条狭长的抛物线状山谷。梯度下降在此山谷中极易反复震荡,而牛顿法能利用曲率信息快速穿越。

python
import numpy as np
import matplotlib.pyplot as plt

def rosen(x):
    return (1 - x[0])**2 + 100 * (x[1] - x[0]**2)**2

def rosen_grad(x):
    dx = -2*(1 - x[0]) - 400*x[0]*(x[1] - x[0]**2)
    dy = 200*(x[1] - x[0]**2)
    return np.array([dx, dy])

def rosen_hess(x):
    dxx = 2 - 400*x[1] + 1200*x[0]**2
    dxy = -400*x[0]
    dyy = 200
    return np.array([[dxx, dxy], [dxy, dyy]])

# 梯度下降
x0 = np.array([-1.5, 1.5])
alpha = 0.001
n_iter = 2000
x_gd = np.zeros((n_iter, 2)); x_gd[0] = x0
for i in range(1, n_iter):
    x_gd[i] = x_gd[i-1] - alpha * rosen_grad(x_gd[i-1])

# 牛顿法
x_nt = np.zeros((n_iter, 2)); x_nt[0] = x0
for i in range(1, n_iter):
    g = rosen_grad(x_nt[i-1])
    H = rosen_hess(x_nt[i-1])
    try:
        x_nt[i] = x_nt[i-1] - np.linalg.solve(H, g)
    except np.linalg.LinAlgError:
        x_nt[i] = x_nt[i-1]; break
python
x_range = np.linspace(-2, 2, 200)
y_range = np.linspace(-1, 3, 200)
X, Y = np.meshgrid(x_range, y_range)
Z = np.array([[rosen([X[i,j], Y[i,j]]) for j in range(200)] for i in range(200)])

plt.figure(figsize=(10, 8))
plt.contour(X, Y, Z, levels=np.logspace(-1, 3, 20), cmap='jet', alpha=0.6)
plt.plot(x_gd[:, 0], x_gd[:, 1], 'r.-', markersize=3, label='GD', alpha=0.7)
plt.plot(x_nt[:, 0], x_nt[:, 1], 'b.-', markersize=5, label='Newton', alpha=0.9)
plt.scatter([1], [1], c='black', s=100, marker='*', label='Optimum (1,1)')
plt.xlim(-2, 2); plt.ylim(-1, 3)
plt.xlabel('x'); plt.ylabel('y')
plt.legend(); plt.grid(alpha=0.3)
plt.title('Rosenbrock 等高线路径对比 — GD vs Newton')
plt.show()

这个对比直观揭示了二阶信息的价值:梯度下降只感知"往哪走"(方向),牛顿法则额外感知"路有多陡、多弯"(曲率),因而能在复杂地形中做出更高效的决策。

Rosenbrock函数等高线图。红色点线为梯度下降路径(在山谷中反复震荡,2000步仍未到达),蓝色点线为牛顿法路径(利用曲率信息直线逼近极值点)。黑色星号为全局极小值(1,1)。


08 数学文化:从牛顿到拟牛顿——优化算法的进化 ​

1665年,艾萨克·牛顿在"流数术"中提出了迭代法求方程根的思路——这就是牛顿法的雏形。他当时用来求解 x3−2x−5=0,手动迭代三次得到1.9999的近似值。

1690年,约瑟夫·拉夫森(Joseph Raphson)独立提出了同样的方法,并给出了更简洁的代数表述。因此该方法常被称为牛顿-拉夫森法(Newton-Raphson method)。

1847年,奥古斯丁·路易·柯西(Augustin-Louis Cauchy)提出了梯度下降法——仅用一阶导数,沿负梯度方向迭代。柯西的论文"General Method for the Resolution of Systems of Simultaneous Equations"成为优化理论的奠基之作。

1950-70年代,拟牛顿法的黄金时代——Davidon(1959)、Fletcher和Powell(1963)提出了最早的拟牛顿法(DFP),Broyden、Fletcher、Goldfarb和Shanno在1970年独立发现了BFGS公式。拟牛顿法在无需计算二阶导数的前提下,达到了接近牛顿法的收敛速度。

2010年代至今——深度学习时代,一阶方法(SGD、Adam)重新成为主流。原因不是牛顿法不够快,而是参数规模太大(百万到万亿级别),Hessian矩阵根本存不下。

Newton-Raphson(1690)→梯度下降(1847)→BFGS(1970)→L-BFGS(1980)→SGD/Adam(2010s)

这条300年的时间线说明:优化算法的选择永远是在速度和计算成本之间做权衡。牛顿法最快但最贵,梯度下降最慢但最便宜,拟牛顿法处于中间地带。


09 FAQ ​

Q:什么时候应该用牛顿法而不是梯度下降? A:当参数规模小(<1000)、Hessian矩阵可计算且正定时,牛顿法的二次收敛远快于梯度下降(Rosenbrock上13步vs247步)。参数规模大时用L-BFGS或Adam。

Q:牛顿法的Hessian矩阵必须正定吗? A:严格来说,牛顿法的收敛性证明要求Hessian在极值点附近正定。如果Hessian非正定(如鞍点附近),牛顿步可能指向错误方向。阻尼牛顿法通过线搜索解决了这个问题。

Q:深度学习中为什么不用牛顿法? A:参数规模太大。一个10亿参数的模型,Hessian矩阵有10¹⁸个元素(~8EB存储),根本无法计算和存储。Adam等一阶方法是当前唯一可行的选择。

Q:BFGS和L-BFGS的区别是什么? A:BFGS存储完整的Hessian逆近似(O(n2)),L-BFGS只存储最近m步的梯度差对(O(mn))。L-BFGS适合百万级参数,BFGS适合千级参数。

Q:牛顿法的二次收敛在什么条件下成立? A:需要三个条件:①目标函数在极值点附近二阶连续可微 ②Hessian在极值点正定 ③初始点足够接近极值点。条件③是关键——远离极值点时牛顿法可能发散,梯度下降反而更稳健。


10 关键要点 ​

  1. 牛顿法利用二阶曲率信息——在极值点附近实现二次收敛,有效数字每步翻倍。
  2. 梯度下降仅用一阶梯度——线性收敛,每步误差固定比例衰减,接近极值点时极慢。
  3. 二次收敛速度对比——精度10−3时,牛顿法5步 vs 梯度下降28步,效率差距5倍以上。
  4. 多元牛顿法需要Hessian矩阵求逆——O(n3)计算量和O(n2)存储,百万参数规模不可行。
  5. 阻尼牛顿法解决非正定问题——通过Armijo线搜索自动调整步长,在保持二次收敛的同时确保稳定性。
  6. BFGS拟牛顿法无需计算Hessian——利用梯度差近似Hessian逆,每步O(n2)计算量。
  7. L-BFGS适合大规模优化——只存储最近m步梯度差对,存储降至O(mn),可处理百万参数。
  8. Rosenbrock函数的经典对比——梯度下降在山谷中反复震荡,牛顿法利用曲率信息直线逼近极值点。
  9. 深度学习中一阶方法重回主流——不是牛顿法不够好,而是参数规模让二阶方法完全不可行。
  10. 优化算法的300年进化——Newton-Raphson(1690)→梯度下降(1847)→BFGS(1970)→SGD/Adam(2010s),核心是速度与成本的权衡。

参考文献 ​

  • Nocedal, J. & Wright, S. J. (2006). Numerical Optimization. Springer — 数值优化圣经,牛顿法、拟牛顿法、L-BFGS完整理论。
  • Boyd, S. & Vandenberghe, L. (2004). Convex Optimization. Cambridge University Press — 凸优化标准教材,牛顿法收敛性分析。

**数据声明**:本文使用合成数据演示,不涉及真实金融数据。 **代码环境**:Python 3.12.3 + numpy 2.5.1 + matplotlib 3.11.0,在WSL2(Ubuntu 24.04)上运行。

关注公众号:QIAN数据