深入机器学习的“求解”之道:用Python揭秘迭代法解方程
摘要:当我们调用
model.fit()时,背后究竟发生了什么?机器学习的核心,在很多情况下,是一个求解复杂数学问题的过程。而“迭代法”正是这个过程中不可或缺的强大引擎。本文将从经典的数值分析出发,深入剖析迭代法如何“变形”并成为现代机器学习,特别是深度学习优化的基石。我们将通过丰富的Python代码案例,一步步揭开牛顿法、梯度下降、共轭梯度乃至Adam优化器的神秘面纱,并展望在2025年这个人工智能蓬勃发展的时代,迭代优化算法的最新趋势。
引言:从“解不了”到“求最优”
在数学和计算机科学中,我们经常需要求解各种形式的方程,例如 f(x) = 0 或者线性方程组 Ax = b。对于简单问题,我们或许能找到“一蹴而就”的解析解。然而,在机器学习的世界里,模型参数动辄成千上万,损失函数的形态极其复杂,直接求解几乎是不可能的任务 。
这时,迭代法 (Iterative Method) 闪亮登场。它的核心思想朴素而强大:从一个初始猜测值开始,通过一个固定的规则反复计算,一步步地逼近真实解 。这就像在漆黑的山谷中寻找最低点,我们无法一步到位,只能依靠当前位置的信息,一步一步向下走,最终到达谷底。
本文将带你踏上一段从经典数值计算到前沿机器学习优化的旅程。我们将看到,那些古老的迭代思想,如何在现代AI领域中焕发出新的生命力,并成为驱动模型“学习”的关键动力。作为一篇写于2025年的文章,我们不仅会回顾经典,更会关注当下最流行的技术和未来的发展趋势 。
一、 什么是迭代法?— 从经典数值分析谈起
在深入机器学习之前,让我们先回到迭代法的“故乡”——数值分析领域,理解其基本形态和运作原理。
1.1 核心思想:步步为营,逼近真相
所有迭代法的实现都包含三个基本要素 :
- 初始猜测 (Initial Guess) :一个求解过程的起点,通常记为
x_0。 - 迭代公式 (Iteration Formula) :如何从当前解
x_k计算出下一个更优的解x_{k+1}的规则。这是迭代法的灵魂。 - 收敛条件 (Convergence Condition) :判断迭代何时停止的准则。通常是两次迭代结果之差小于一个极小值(精度
ε),或者达到了预设的最大迭代次数 。
1.2 案例一:牛顿迭代法 (Newton's Method) — 切线的力量
牛顿法是求解非线性方程 f(x)=0 的一种极其高效的迭代法。其几何直觉是:在当前点 x_k 处画一条函数的切线,用该切线与x轴的交点作为下一个近似解 x_{k+1} 。
数学上,它的迭代公式非常简洁,利用了一阶导数信息 :

牛顿法在解的附近具有二次收敛的特性,这意味着每迭代一次,有效数字的位数大约会翻倍,速度极快。
【Python代码案例:用牛顿法求解 cos(x) - x^3 = 0】
手动计算导数既繁琐又容易出错。幸运的是,我们可以使用 sympy 库来自动完成符号计算,然后用 lambdify 将其转换为可供数值计算的快速函数 。
import numpy as np
import sympy as sp
import matplotlib.pyplot as plt
# --- 1. 定义问题 ---
# 使用 sympy 定义符号变量和函数
x_sym = sp.Symbol('x')
f_sym = sp.cos(x_sym) - x_sym**3
f_prime_sym = sp.diff(f_sym, x_sym) # 自动求导
# 使用 lambdify 将符号函数转换为可用于 numpy 的数值函数
f = sp.lambdify(x_sym, f_sym, 'numpy')
f_prime = sp.lambdify(x_sym, f_prime_sym, 'numpy')
# --- 2. 牛顿迭代法实现 ---
def newton_method(f, f_prime, x0, tol=1e-8, max_iter=100):
"""
使用牛顿法求解方程 f(x)=0。
参数:
f: 目标函数
f_prime: 目标函数的导数
x0: 初始猜测值
tol: 容忍误差
max_iter: 最大迭代次数
返回:
近似解和迭代历史
"""
x = x0
history = [x]
print(f"{'Iteration':<10}{'x':<20}{'f(x)':<20}")
print("-" * 50)
for i in range(max_iter):
fx = f(x)
fpx = f_prime(x)
print(f"{i:<10}{x:<20.15f}{fx:<20.15f}")
# 检查收敛
if abs(fx) < tol:
print(f"\n在 {i} 次迭代后收敛。")
return x, history
if fpx == 0:
print("导数为零,无法继续迭代。")
return None, history
# 迭代更新
x = x - fx / fpx
history.append(x)
print("\n达到最大迭代次数,未收敛。")
return x, history
# --- 3. 运行与可视化 ---
# 设置初始值并求解
initial_guess = 0.5
solution, history = newton_method(f, f_prime, initial_guess)
if solution is not None:
print(f"\n方程 cos(x) - x^3 = 0 的近似解为: {solution}")
# 可视化收敛过程
plt.figure(figsize=(10, 6))
x_range = np.linspace(min(history) - 0.2, max(history) + 0.2, 400)
plt.plot(x_range, f(x_range), label='f(x) = cos(x) - x^3')
plt.plot(history, f(np.array(history)), 'r-o', label='Newton Iteration Path')
plt.axhline(0, color='black', linewidth=0.5)
plt.title('Newton\'s Method Convergence')
plt.xlabel('x')
plt.ylabel('f(x)')
plt.legend()
plt.grid(True)
plt.show()
从输出可以看到,牛顿法仅需几次迭代就能达到非常高的精度,展示了其强大的收敛能力。
1.3 案例二:求解大型稀疏线性方程组
在许多科学计算和机器学习问题(如图神经网络、稀疏编码)中,我们需要求解形如 Ax=b 的大型线性方程组。当矩阵 A 非常大且稀疏(大部分元素为零)时,直接求解(如高斯消元法)会消耗巨大的内存和计算资源。迭代法,如 雅可比法 (Jacobi Iteration) 和 高斯-赛德尔法 (Gauss-Seidel Iteration) ,则显示出巨大优势,因为它们仅涉及矩阵和向量的乘法,内存占用小,计算效率高 。
高斯-赛德尔法是雅可比法的一个改进,它在计算 x 的新分量时,会立即使用刚刚计算出的最新值,这通常使其收敛得更快 。
【Python代码案例:用高斯-赛德尔法求解线性方程组】
我们来求解以下方程组:

import numpy as np
def gauss_seidel(A, b, x0=None, tol=1e-8, max_iter=1000):
"""
使用高斯-赛德尔法求解 Ax = b。
要求矩阵 A 是严格对角占优或对称正定的以保证收敛。
"""
n = len(b)
# 如果没有提供初始值,则用零向量开始
x = np.zeros(n) if x0 is None else np.copy(x0)
for k in range(max_iter):
x_old = np.copy(x)
# 遍历每个分量
for i in range(n):
# 计算 \sum_{j \neq i} A_ij * x_j
sigma = np.dot(A[i, :i], x[:i]) + np.dot(A[i, i+1:], x_old[i+1:])
# 更新 x_i
x[i] = (b[i] - sigma) / A[i, i]
# 检查收敛条件:前后两次迭代结果的无穷范数(最大绝对差)
if np.linalg.norm(x - x_old, ord=np.inf) < tol:
print(f"在 {k+1} 次迭代后收敛。")
return x
print("达到最大迭代次数,未收敛。")
return x
# --- 定义问题 ---
A = np.array([
[10, -1, 2, 0],
[-1, 11, -1, 3],
[2, -1, 10, -1],
[0, 3, -1, 8]
])
b = np.array([6, 25, -11, 15])
# --- 求解 ---
solution = gauss_seidel(A, b)
print(f"\n方程组的解为: {solution}")
# --- 验证 ---
print(f"验证 A * x: {np.dot(A, solution)}")
print(f"原始 b 值: {b}")
这个例子展示了如何用迭代的方式求解一个看似复杂但结构良好的线性系统。
二、 迭代法在机器学习中的“变形”与核心地位
迭代法的思想在机器学习领域被发扬光大,但其目标发生了微妙的转变:从 “解方程” 转变为 “找最优”。
2.1 从“解方程”到“找最优”:优化问题的视角
几乎所有的机器学习模型训练过程,本质上都是一个优化问题:寻找一组模型参数 θ,使得描述模型预测与真实数据差距的损失函数 L(θ) 达到最小值 。
根据微积分原理,函数的极值点通常出现在其导数(或梯度)为零的地方。因此,最小化 L(θ) 的问题,等价于求解一个方程:

其中 ∇ 是梯度算子。这个方程通常比我们之前遇到的要复杂得多,几乎不可能直接求解。于是,为优化而生的迭代法——梯度下降法应运而生。
2.2 案例三:梯度下降法 (Gradient Descent) — 机器学习的基石
梯度下降法 (Gradient Descent) 是机器学习中最核心、最基础的优化算法 。它的迭代逻辑非常直观:函数在某一点的负梯度方向是函数值下降最快的方向。因此,只要我们沿着负梯度方向不断前进,就能逐步逼近函数的最小值点 。
其迭代公式为:

θ_k:第k次迭代的参数。α: 学习率 (Learning Rate) ,一个控制每一步“走多远”的超参数。∇L(θ_k):损失函数在θ_k处的梯度。
根据计算梯度时使用的数据量,梯度下降法又分为三种变体 :
- 批量梯度下降 (Batch GD) :使用全部训练数据计算梯度,方向准确但计算量大。
- 随机梯度下降 (Stochastic GD, SGD) :每次仅使用一个样本计算梯度,速度快但梯度估计有噪声,收敛过程会“震荡”。
- 小批量梯度下降 (Mini-batch GD) :介于两者之间,每次使用一小批数据,是目前最主流的做法。
【Python代码案例:从零实现线性回归的梯度下降】
让我们用梯度下降法来解决一个最简单的机器学习问题:线性回归。目标是找到最佳的 w 和 b,使得直线 y = wx + b 最好地拟合数据点。
import numpy as np
import matplotlib.pyplot as plt
# --- 1. 生成模拟数据 ---
np.random.seed(42)
X = 2 * np.random.rand(100, 1)
y = 4 + 3 * X + np.random.randn(100, 1) # 真实 w=3, b=4
# 添加 x0 = 1 到每个实例,方便计算
X_b = np.c_[np.ones((100, 1)), X]
# --- 2. 梯度下降实现 ---
def gradient_descent(X_b, y, learning_rate=0.1, n_iterations=1000):
m = len(X_b)
# 随机初始化参数 theta (包含 b 和 w)
theta = np.random.randn(2, 1)
history = [theta]
for iteration in range(n_iterations):
# 计算梯度
gradients = 2/m * X_b.T.dot(X_b.dot(theta) - y)
# 更新参数
theta = theta - learning_rate * gradients
history.append(theta)
return theta, np.array(history)
# --- 3. 训练和可视化 ---
learning_rate = 0.1
n_iterations = 100
theta_final, history = gradient_descent(X_b, y, learning_rate, n_iterations)
print(f"训练完成!")
print(f"最终参数 (b, w): {theta_final.ravel()}")
# 可视化结果
plt.figure(figsize=(14, 6))
# a) 数据和拟合直线
plt.subplot(1, 2, 1)
plt.scatter(X, y)
X_new = np.array[[0]], [[2]]
X_new_b = np.c_[np.ones((2, 1)), X_new]
y_predict = X_new_b.dot(theta_final)
plt.plot(X_new, y_predict, "r-", label="Predictions")
plt.xlabel("X")
plt.ylabel("y")
plt.title("Linear Regression Fit")
plt.legend()
plt.grid(True)
# b) 参数收敛路径
plt.subplot(1, 2, 2)
plt.plot(history[:, 0], history[:, 1], 'b-o')
plt.xlabel("b (theta_0)")
plt.ylabel("w (theta_1)")
plt.title("Parameter Convergence Path")
plt.grid(True)
plt.tight_layout()
plt.show()
这个例子清晰地展示了梯度下降如何通过迭代更新,让参数从一个随机点逐步移动到能够最小化预测误差的最优位置。
2.3 案例四:共轭梯度法 (Conjugate Gradient) — 更快的下山路径
虽然梯度下降法很通用,但它有时会因为“Z”字形(zig-zagging)的路径而收敛缓慢。共轭梯度法 (Conjugate Gradient, CG) 是一种更先进的迭代优化算法,它在每一步更新时,不仅考虑当前梯度,还巧妙地结合了之前的搜索方向,确保新的搜索方向与所有历史方向“共轭”,从而避免走回头路,大大提高了收敛效率 。
对于二次型的目标函数(如线性回归的均方误差损失),CG 理论上可以在 n 次迭代内找到最优解(n 是参数数量)。
【Python代码案例:用共轭梯度法求解线性回归】
线性回归的优化目标 min ||Xθ - y||^2,其梯度为零的条件展开后是一个线性方程组 (X^T X)θ = X^T y。这正好是 CG 法的用武之地!我们可以直接用 CG 求解这个系统,从而得到最优参数 θ。
import numpy as np
def conjugate_gradient_for_linear_regression(X, y, tol=1e-8, max_iter=100):
"""
使用共轭梯度法求解线性回归问题。
等价于求解正规方程 (X.T @ X) @ theta = X.T @ y
"""
A = X.T @ X
b = X.T @ y
n = X.shape[[1]]
theta = np.zeros(n) # 初始猜测
r = b - A @ theta # 初始残差 r = b - A*theta
p = r.copy() # 初始搜索方向
rs_old = np.dot(r, r)
if rs_old < 1e-10: # 如果初始点就是解
return theta
history = [theta]
for i in range(max_iter):
Ap = A @ p
alpha = rs_old / np.dot(p, Ap) # 步长
theta = theta + alpha * p # 更新解
r = r - alpha * Ap # 更新残差
rs_new = np.dot(r, r)
# 检查收敛
if np.sqrt(rs_new) < tol:
print(f"CG 在 {i+1} 次迭代后收敛。")
history.append(theta)
return theta, np.array(history)
# 更新搜索方向
p = r + (rs_new / rs_old) * p
rs_old = rs_new
history.append(theta)
print("CG 达到最大迭代次数,未收敛。")
return theta, np.array(history)
# --- 使用之前的数据 ---
# X_b 和 y
theta_cg, history_cg = conjugate_gradient_for_linear_regression(X_b, y)
print(f"\nCG 求解得到的最终参数 (b, w): {theta_cg.ravel()}")
# --- 对比收敛速度(可视化) ---
# 运行梯度下降10次迭代
_, history_gd_10 = gradient_descent(X_b, y, learning_rate=0.1, n_iterations=10)
plt.figure(figsize=(8, 8))
plt.plot(history_gd_10[:, 0], history_gd_10[:, 1], 'r-o', label='Gradient Descent (10 steps)')
plt.plot(history_cg[:, 0], history_cg[:, 1], 'b-o', label='Conjugate Gradient')
# 真实解
true_solution = np.linalg.inv(X_b.T @ X_b) @ X_b.T @ y
plt.plot(true_solution[[0]], true_solution[[1]], 'g*', markersize=15, label='True Solution')
plt.xlabel("b (theta_0)")
plt.ylabel("w (theta_1)")
plt.title("GD vs. CG Convergence Path")
plt.legend()
plt.grid(True)
plt.show()
从对比图中可以直观地看到,共轭梯度法(通常只需2次迭代就接近最优解)的路径比梯度下降法直接得多,收敛速度优势明显。
三、 前沿与实践:现代优化器与性能展望
进入深度学习时代,损失函数变得高度非凸,充满了局部最小值和鞍点。简单的梯度下降法面临巨大挑战。为此,研究者们提出了一系列更强大的迭代优化器。
3.1 迈向自适应:从动量法到 Adam 优化器
为了克服梯度下降的缺点,研究者们引入了物理学中的“动量”概念。动量法 (Momentum) 在更新时,会加上一部分上一次的更新方向,仿佛给小球增加了惯性,使其能够冲过小的颠簸,加速收敛 。
而当今深度学习领域最受欢迎的优化器之一是 Adam (Adaptive Moment Estimation) 。Adam 可以看作是动量法和另一种自适应学习率算法 RMSProp 的结合体。它为每个参数都维护了一个独立的学习率,并利用梯度的一阶矩(动量)和二阶矩(梯度的平方的移动平均)来动态调整这个学习率 。
简单来说,Adam 的优点是 :
- 收敛速度快:结合了动量和自适应学习率的优点。
- 鲁棒性强:对初始学习率的选择不那么敏感。
- 资源高效:内存需求小,适合大规模数据和模型。
3.2 实证研究:Adam vs. SGD 在 MNIST 数据集上的性能对决
口说无凭,让我们看看在经典的 MNIST 手写数字识别任务上,Adam 和传统的 SGD(加动量)表现如何。MNIST 是检验优化器性能的“试金石” 。
大量研究和实践表明,Adam 在 MNIST 这类任务上通常能更快地降低训练损失,达到较高的准确率。例如,有研究显示,在同样的网络结构和训练轮数下,Adam 的测试准确率可以稳定地优于 SGD 。一些基准测试中,Adam 的准确率可以达到98%甚至更高 。不过,也有观点认为,在某些情况下,精调的 SGD+Momentum 可能在最终的泛化能力上略胜一筹。
【PyTorch/TensorFlow代码示例框架】
在现代深度学习框架中,使用这些优化器非常简单,只需一行代码即可切换。
# 以 PyTorch 为例
import torch.optim as optim
# model = ... (你的神经网络模型)
# loss_fn = ... (你的损失函数)
# 使用 SGD + Momentum
optimizer_sgd = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)
# 使用 Adam
optimizer_adam = optim.Adam(model.parameters(), lr=0.001) # Adam通常使用更小的学习率
# --- 在训练循环中 ---
# for data, labels in dataloader:
# optimizer.zero_grad() # 清空梯度
# outputs = model(data) # 前向传播
# loss = loss_fn(outputs, labels) # 计算损失
# loss.backward() # 反向传播计算梯度
# optimizer.step() # 更新参数
这种高级封装让开发者可以专注于模型架构,而不必手动实现复杂的迭代更新逻辑。
3.3 展望2025:迭代优化的未来趋势
站在2025年9月这个时间点,迭代优化领域依然充满活力,并呈现出以下趋势:
- 应对超大规模模型:随着模型规模(如大型语言模型)爆炸式增长,开发内存和计算效率更高的优化算法是当务之急。如何在分布式训练中高效地同步和更新参数,是研究的热点 。
- 自动化与自适应:自动超参数优化(如学习率调度、贝叶斯优化)的研究越来越深入,目标是让优化器更加“即插即用”,减少人工调参的负担 。
- 理论与实践的结合:对非凸优化 landscape 的理解正在加深,这有助于设计出能够更好逃离鞍点和局部最小值的算法。
- 新领域的交叉融合:迭代优化的思想正与强化学习、多目标优化等领域深度融合,催生出更智能的决策和优化策略 。我们期待在即将到来的 IJCNN 2025、ICDLT 2025 等顶级人工智能会议上,看到更多关于下一代优化算法的突破性研究 。
结论
从求解一个简单方程的牛顿法,到驱动复杂神经网络学习的 Adam 优化器,迭代法的核心思想——“步步为营,逼近最优”——贯穿始终。它完美地诠释了计算机科学中以计算换精度的哲学。
通过本文的剖析和代码实践,我们希望你不仅掌握了这些方法的“形”,更理解了其“神”。理解了梯度下降,你就理解了机器学习模型是如何“学习”的;理解了 Adam,你就拥有了驾驭现代深度学习模型的利器。
在人工智能的浪潮中,底层数学和算法的坚实基础,永远是开发者乘风破浪最可靠的船桨。希望这篇文章能成为你深入探索机器学习“求解”之道的一张有价值的航海图。
更多推荐



所有评论(0)