Runge-Kutta 方法:更精确的 ODE 求解利器
在数值分析和深度学习领域,常微分方程(Ordinary Differential Equation, ODE)的求解是许多问题的基础。虽然 Euler 方法简单直观,但其精度较低,误差随步长累积较快。为了提高精度,Runge-Kutta 方法(简称 RK 方法)成为更常用的 ODE 求解工具,尤其是经典的 RK-4(四阶 Runge-Kutta 方法)。本篇博客将面向深度学习研究者,介绍 RK 方法的原理、推导及其优势,并以直观的语言解释其核心思想,帮助你在实践中理解和应用。
什么是 Runge-Kutta 方法?
Runge-Kutta 方法是一类用于求解初值问题 ODE 的数值方法,形式为:
d
x
(
t
)
d
t
=
f
(
t
,
x
)
,
x
(
t
0
)
=
x
0
\frac{dx(t)}{dt} = f(t, x), \quad x(t_0) = x_0
dtdx(t)=f(t,x),x(t0)=x0
其中:
- ( x ( t ) x(t) x(t) ) 是待求解函数。
- ( f ( t , x ) f(t, x) f(t,x) ) 是导数函数。
- ( x 0 x_0 x0 ) 是初始条件。
RK 方法通过多步斜率加权平均来预测下一步的值,比 Euler 方法更精确。经典的 RK-4 方法是四阶精度(误差为 ( O ( α 4 ) O(\alpha^4) O(α4) )),在实际应用中非常流行。
RK-4 方法的迭代公式
RK-4 方法的迭代公式为:
x
i
+
1
=
x
i
+
α
6
⋅
(
k
1
+
2
k
2
+
2
k
3
+
k
4
)
,
i
=
0
,
1
,
…
,
N
−
1
x_{i+1} = x_i + \frac{\alpha}{6} \cdot (k_1 + 2k_2 + 2k_3 + k_4), \quad i = 0, 1, \dots, N-1
xi+1=xi+6α⋅(k1+2k2+2k3+k4),i=0,1,…,N−1
其中:
- ( α \alpha α ):步长(step size)。
- (
k
1
,
k
2
,
k
3
,
k
4
k_1, k_2, k_3, k_4
k1,k2,k3,k4 ) 是四个斜率,定义如下:
k 1 = f ( t i , x i ) k_1 = f(t_i, x_i) k1=f(ti,xi)
k 2 = f ( t i + α 2 , x i + α 2 k 1 ) k_2 = f\left(t_i + \frac{\alpha}{2}, x_i + \frac{\alpha}{2} k_1\right) k2=f(ti+2α,xi+2αk1)
k 3 = f ( t i + α 2 , x i + α 2 k 2 ) k_3 = f\left(t_i + \frac{\alpha}{2}, x_i + \frac{\alpha}{2} k_2\right) k3=f(ti+2α,xi+2αk2)
k 4 = f ( t i + α , x i + α k 3 ) k_4 = f(t_i + \alpha, x_i + \alpha k_3) k4=f(ti+α,xi+αk3)
直观理解
- ( k 1 k_1 k1 ):当前点 ( ( t i , x i ) (t_i, x_i) (ti,xi) ) 的斜率,类似 Euler 方法。
- ( k 2 k_2 k2 ):用 ( k 1 k_1 k1 ) 预测中点 ( t i + α 2 t_i + \frac{\alpha}{2} ti+2α ) 的值,再计算中点斜率。
- ( k 3 k_3 k3 ):用 ( k 2 k_2 k2 ) 重新预测中点,再计算中点斜率。
- ( k 4 k_4 k4 ):用 ( k 3 k_3 k3 ) 预测终点 ( t i + α t_i + \alpha ti+α ),计算终点斜率。
- 加权平均:用 ( k 1 + 2 k 2 + 2 k 3 + k 4 6 \frac{k_1 + 2k_2 + 2k_3 + k_4}{6} 6k1+2k2+2k3+k4 ) 综合四个斜率,得到更精确的步进。
这种“多点采样 + 加权平均”的方式让 RK-4 方法在每一步都更好地逼近真实曲线的变化。
为什么 RK-4 更精确?
Euler 方法的局限
Euler 方法(请参考笔者的另一篇博客:Euler 方法:解 ODE 的简单利器):
x
i
+
1
=
x
i
+
α
⋅
f
(
t
i
,
x
i
)
x_{i+1} = x_i + \alpha \cdot f(t_i, x_i)
xi+1=xi+α⋅f(ti,xi)
只用当前点斜率预测下一步,等价于用直线近似曲线,忽略了曲线的弯曲(高阶导数)。其误差为 (
O
(
α
)
O(\alpha)
O(α) ),步长稍大时偏差明显。
RK-4 的改进
RK-4 方法通过在每步内计算四个斜率(起点、中点、终点),并以特定权重组合,模拟了曲线的非线性变化。它的设计目标是匹配泰勒展开的高阶项:
x
(
t
+
α
)
=
x
(
t
)
+
α
x
′
(
t
)
+
α
2
2
x
′
′
(
t
)
+
α
3
6
x
′
′
′
(
t
)
+
α
4
24
x
(
4
)
(
t
)
+
O
(
α
5
)
x(t + \alpha) = x(t) + \alpha x'(t) + \frac{\alpha^2}{2} x''(t) + \frac{\alpha^3}{6} x'''(t) + \frac{\alpha^4}{24} x^{(4)}(t) + O(\alpha^5)
x(t+α)=x(t)+αx′(t)+2α2x′′(t)+6α3x′′′(t)+24α4x(4)(t)+O(α5)
RK-4 的加权公式确保误差高达 (
O
(
α
4
)
O(\alpha^4)
O(α4) ),比 Euler 方法的 (
O
(
α
)
O(\alpha)
O(α) ) 小得多。
几何直觉
- Euler 方法:用起点斜率画一条直线,走一步。
- RK-4 方法:先试探性地走半步(( k 2 , k 3 k_2, k_3 k2,k3 )),调整方向,再走完整一步(( k 4 k_4 k4 )),最后综合四段路径,像用“曲线段”逼近真实轨迹。
示例:用 RK-4 方法解 ODE
考虑之前的 ODE:
d
x
(
t
)
d
t
=
x
(
t
)
+
t
2
−
2
t
+
1
,
x
(
0
)
=
1.0
\frac{dx(t)}{dt} = \frac{x(t) + t^2 - 2}{t + 1}, \quad x(0) = 1.0
dtdx(t)=t+1x(t)+t2−2,x(0)=1.0
对应的 (
f
(
t
,
x
)
=
x
+
t
2
−
2
t
+
1
f(t, x) = \frac{x + t^2 - 2}{t + 1}
f(t,x)=t+1x+t2−2 )。用 RK-4 方法:
- 计算 ( k 1 = x i + t i 2 − 2 t i + 1 k_1 = \frac{x_i + t_i^2 - 2}{t_i + 1} k1=ti+1xi+ti2−2 )。
- 计算 ( k 2 = f ( t i + α 2 , x i + α 2 k 1 ) k_2 = f\left(t_i + \frac{\alpha}{2}, x_i + \frac{\alpha}{2} k_1\right) k2=f(ti+2α,xi+2αk1) )。
- 计算 ( k 3 , k 4 k_3, k_4 k3,k4 ) 类似。
- 更新:
x i + 1 = x i + α 6 ( k 1 + 2 k 2 + 2 k 3 + k 4 ) x_{i+1} = x_i + \frac{\alpha}{6} (k_1 + 2k_2 + 2k_3 + k_4) xi+1=xi+6α(k1+2k2+2k3+k4)
Python 代码实现
以下是用 RK-4 方法求解该 ODE 的代码:
import numpy as np
import matplotlib.pyplot as plt
# 定义导数函数 f(t, x)
def f(t, x):
return (x + t**2 - 2) / (t + 1)
# RK-4 方法求解 ODE
def rk4_method(t0, x0, alpha, t_end):
"""
Args:
t0: 初始时间
x0: 初始值 x(t0)
alpha: 步长
t_end: 结束时间
Returns:
t_values: 时间点数组
x_values: 解的数组
"""
N = int((t_end - t0) / alpha)
t_values = np.linspace(t0, t_end, N + 1)
x_values = np.zeros(N + 1)
x_values[0] = x0
# RK-4 迭代
for i in range(N):
t_i = t_values[i]
x_i = x_values[i]
# 计算 k1, k2, k3, k4
k1 = f(t_i, x_i)
k2 = f(t_i + alpha/2, x_i + (alpha/2) * k1)
k3 = f(t_i + alpha/2, x_i + (alpha/2) * k2)
k4 = f(t_i + alpha, x_i + alpha * k3)
# 更新 x
x_values[i + 1] = x_i + (alpha/6) * (k1 + 2*k2 + 2*k3 + k4)
return t_values, x_values
# 参数设置
t0 = 0.0 # 初始时间
x0 = 1.0 # 初始值
alpha = 0.1 # 步长
t_end = 2.0 # 结束时间
# 运行 RK-4 方法
t_values, x_values = rk4_method(t0, x0, alpha, t_end)
# 可视化
plt.plot(t_values, x_values, label=f'RK-4 Method (step size = {alpha})', marker='o')
plt.xlabel('t')
plt.ylabel('x(t)')
plt.title('RK-4 Method for dx/dt = (x + t^2 - 2) / (t + 1)')
plt.legend()
plt.grid(True)
plt.show()
代码说明
- 导数函数:
f(t, x)
定义 ODE 的右端。 - RK-4 方法:
rk4_method
函数实现四阶迭代,计算 ( k 1 k_1 k1 ) 到 ( k 4 k_4 k4 ),加权更新。 - 可视化:绘制解的轨迹,与 Euler 方法相比,曲线更平滑。
RK-4 方法的优缺点
优点
- 高精度:四阶精度,误差为 ( O ( α 4 ) O(\alpha^4) O(α4)),远优于 Euler 方法的 ( O ( α ) O(\alpha) O(α))。
- 稳定性:对大多数 ODE 更稳定,能用较大步长仍保持精度。
缺点
- 计算复杂:每步需要计算四次 ( f ( t , x ) f(t, x) f(t,x) ),比 Euler 方法(一次计算)更耗时。
- 复杂 ODE 的局限:对于刚性(stiff)方程,可能仍需更高级方法(如隐式 RK)。
与深度学习的联系
- 优化算法:RK-4 的思想启发了高阶优化方法(如 Adam 的动量改进)。
- 扩散模型:SDE 的求解(如 DDPM 的逆向采样)可用 RK 方法提升精度。
- Neural ODE:深度学习中的连续模型直接用 RK-4 求解 ODE。
总结
RK-4 方法通过:
x
i
+
1
=
x
i
+
α
6
(
k
1
+
2
k
2
+
2
k
3
+
k
4
)
x_{i+1} = x_i + \frac{\alpha}{6} (k_1 + 2k_2 + 2k_3 + k_4)
xi+1=xi+6α(k1+2k2+2k3+k4)
在每步内计算四个斜率,综合预测下一步的值,比 Euler 方法更精确。它的四阶精度使其成为 ODE 求解的常用工具,尤其适合需要高精度的场景。对于深度学习研究者,RK-4 方法不仅能帮助理解数值解法,还为优化和生成模型中的连续动态提供了更可靠的工具。试试上面的代码,与 Euler 方法对比,看看精度提升吧!
注:本文以直观解释为主,代码可直接运行验证。
后记
2025年3月9日17点05分于上海,在Grok 3大模型辅助下完成。