是什么
求方程根的方法。给定可导函数 $f(x)$,在一条初值 $x_0$ 附近用切线逼近 $f$,并迭代得到根 $x^*$ 使 $f(x^*)=0$。
推导(1 维)
在 $x_k$ 处对 $f$ 作一阶泰勒展开:
$$
f(x)\approx f(x_k)+f'(x_k)(x-x_k).
$$
令右式为 0(即用切线与 $x$-轴的交点近似真正的根):
$$
x_{k+1}=x_k-\frac{f(x_k)}{f'(x_k)}.
$$
这就是 NR 迭代式。
算法步骤(1 维)
选初值 $x_0$(尽量靠近根,且 $f'(x_0)\neq 0$)。
反复计算
$$
x_{k+1}=x_k-\frac{f(x_k)}{f'(x_k)}.
$$
终止条件常用:
$|f(x_{k})| \le \varepsilon_f$,或
$|x_{k+1}-x_k| \le \varepsilon_x(1+|x_k|)$,或
达到最大迭代次数。
收敛性质
简单根($f'(x^*)\neq 0$):若起点足够近,二次收敛:
$\;e_{k+1}\approx \dfrac{f''(\xi)}{2f'(x^*)}\,e_k^2$($e_k=x_k-x^*$)。重根(重数 $m>1$):标准 NR 只有线性收敛;可改为
$$
x_{k+1}=x_k- m\frac{f(x_k)}{f'(x_k)}
$$恢复二次收敛。
若 $f'$ 在根附近接近 0 或起点离根较远,可能发散/震荡/落入其他根。
直观理解
每一步用“在 $x_k$ 处的切线”去碰 $x$-轴:谁离根更近就把谁当作下一步的近似。因为切线是一阶局部近似,靠近根就很准,所以能二次收敛。
例子($\sqrt{2}$)
令 $f(x)=x^2-2$,$f'(x)=2x$。迭代式化简为
$$
x_{k+1}=\tfrac12!\left(x_k+\frac{2}{x_k}\right).
$$
取 $x_0=1$:
$x_1=1.5$
$x_2=\tfrac12(1.5+2/1.5)=1.4166666667$
$x_3\approx 1.4142156863$
$x_4\approx 1.4142135624$(已到 $\sqrt{2}\approx1.4142135624$ 的 10⁻¹² 量级)
与优化的关系
若要最小化 $g(x)$,可令 $f(x)=g'(x)$ 解 $g'(x)=0$ 的驻点。NR 在优化中的形式为
$$
x_{k+1}=x_k-\frac{g'(x_k)}{g''(x_k)},
$$
这就是“一维牛顿法”。多维情形见下。
多维扩展
求 $F:\mathbb{R}^n\to\mathbb{R}^n$ 的根 $F(x)=0$。记雅可比 $J(x)=\nabla F(x)\in\mathbb{R}^{n\times n}$。
牛顿步:解线性方程
$$
J(x_k)\,p_k=-F(x_k),\quad x_{k+1}=x_k+p_k.
$$
实现上用 LU/QR/Cholesky(对称正定时)或共轭梯度(大型稀疏)求解,不显式求逆。
在最大似然/非线性最小二乘里,常用 近似牛顿(BFGS、Gauss–Newton、LM)避免计算真实 Hessian 或改善全局性。
代码骨架
Python(标量):
def newton(f, fp, x0, tol=1e-12, maxit=100, damping=1.0): x = x0 for _ in range(maxit): fx = f(x); dfx = fp(x) if dfx == 0: raise ZeroDivisionError("f'(x)=0") step = -fx/dfx x_new = x + damping * step # 阻尼/下山牛顿 if abs(x_new - x) <= tol * (1 + abs(x)): return x_new x = x_new raise RuntimeError("No convergence")
多维(框架):
import numpy as np from numpy.linalg import solve, norm def newton_nd(F, J, x0, tol=1e-10, maxit=50, alpha=1.0): x = np.array(x0, dtype=float) for _ in range(maxit): Fx = F(x); Jx = J(x) p = solve(Jx, -Fx) # 解 J p = -F x_new = x + alpha * p # 可配线搜索/信赖域 if norm(x_new - x, ord=2) <= tol * (1 + norm(x, ord=2)): return x_new x = x_new raise RuntimeError("No convergence")
实战技巧与坑
初值很重要:尽量靠近目标根;可用图像/物理直觉/二分法先粗定位。
导数为零或极小:会爆步或除零。对策:阻尼($x_{k+1}=x_k-\alpha f/f'$, $0<\alpha\le1$)、切换“二分/割线”一步。
不连续/不可导:NR 不适用,改用次梯度、分段方法或无导数法。
重根:使用“乘数修正”公式 $x_{k+1}=x_k-m f/f'$。
多维病态:$J$ 奇异/病态时解线性方程不稳定;用正则化(LM)、信赖域或预条件。
全局化:加入线搜索(Wolfe 条件)或信赖域(Dogleg/LM)可避免远离根时的发散。
停止准则:同时监控 $|F(x)|$ 与步长,避免“卡在平坦区”。
与其它方法对比
二分法:只要有跨越符号变化就全局收敛,但收敛慢(线性)。
割线法:不需要导数,收敛阶 $\approx 1.618$,通常比 NR 慢但每步更轻。
Halley 法:用二阶导,理论上三次收敛,但每步更贵。
金融中的常见用法
隐含波动率:解 $C_{\text{BS}}(\sigma)=C_{\text{mkt}}$ 的 $\sigma$。
$f(\sigma)=C_{\text{BS}}(\sigma)-C_{\text{mkt}}$,$f'(\sigma)=\text{Vega}$。
由于 Vega 在深度实值/虚值时很小,需阻尼或好初值(如用近似公式作初猜)。校准与均衡:解非线性方程组,用多维牛顿或其变体。
小抄
迭代式:$\displaystyle x_{k+1}=x_k-\frac{f(x_k)}{f'(x_k)}$。
多根修正:$\displaystyle x_{k+1}=x_k-m\frac{f(x_k)}{f'(x_k)}$。
多维:解 $J(x_k)p_k=-F(x_k)$,更新 $x_{k+1}=x_k+p_k$。
优点:局部二次收敛、迭代数少。
缺点:需要导数、对初值敏感、可能发散;需阻尼/全局化。
系统当前共有 470 篇文章