4. 收敛判据与停止准则

迭代求解器每走一步都会产生一组“可观测信号”:当前残差向量、上一步的解向量、目标函数值。停止准则的本质,是从这些信号中挑出一个或几个,设定阈值,判断“是否已经足够好”。选错判据,轻则多迭代几十步浪费算力,重则在不该停的时候停下,得到一个看似收敛、实则偏离真解的近似解。本节围绕四类最常用的判据展开,说明它们各自度量什么、适合什么场景、在什么情况下会骗人。

四类判据各自度量什么

设当前迭代步为 k,线性系统为 Ax = b,非线性问题为求 F(x)=0 或 min f(x)。四类判据的定义与物理含义如下:

  • 绝对残差范数:‖r_k‖ = ‖b − A x_k‖(线性)或 ‖F(x_k)‖(非线性)。它度量“当前方程被满足的绝对程度”,量纲与右端项 b 相同。
  • 相对残差:‖r_k‖ / ‖r_0‖ 或 ‖r_k‖ / ‖b‖。它把残差归一化,消除了问题尺度的影响,是最常用的默认判据。
  • 更新量范数:‖x_k − x_{k−1}‖ 或其相对形式 ‖Δx‖ / ‖x_k‖。它度量“解本身是否还在明显移动”,与残差无直接量纲关系。
  • 目标函数变化:|f(x_k) − f(x_{k−1})| 或其相对形式。它只适用于有明确目标函数的优化类问题,度量“还能不能把目标压得更低”。

这四者并不等价。残差小不代表解误差小(问题可能病态),更新量小不代表残差小(可能步长被阻尼压得很小),目标函数变化小更不代表已到最优(可能停在平坦区域或鞍点附近)。理解这一点,是设计停止准则的前提。

四类停止判据的度量对象与典型陷阱 迭代求解器 第 k 步输出 x_k, r_k, f_k 绝对残差 ‖r_k‖ 度量方程满足的绝对程度 量纲同 b,随问题尺度漂移 相对残差 ‖r_k‖/‖b‖ 归一化,消除尺度影响 默认首选,但受条件数放大 更新量 ‖Δx‖ 度量解是否还在移动 步长被压小时会误判收敛 目标函数变化 |Δf| 度量还能否压低目标 平坦区/鞍点附近易早停 陷阱:病态问题残差小、误差大 ‖r‖ 小只说明 A x ≈ b,若 κ(A) 很大, 解误差 ‖e‖ 仍可能被放大 κ(A) 倍。 陷阱:‖b‖ 极小导致相对残差失真 b 接近零向量时分母过小,比值虚高; 应改用 max(‖b‖, ε) 或绝对残差兜底。 陷阱:阻尼/线搜索使 Δx 假性变小 步长因子 α 很小时 Δx 自然小, 需与残差判据联合,不可单独使用。 陷阱:目标平坦区早停于非最优点 |Δf| 小可能只是地形平坦, 应同时检查梯度范数是否也足够小。 工程实践:主判据(相对残差)+ 辅助判据(更新量或目标变化)+ 最大迭代数硬上限

相对残差:默认首选,但要防分母失真

相对残差 ‖r_k‖/‖r_0‖ 是最稳妥的默认选择,因为它把“当前残差”与“初始残差”比较,天然适应不同量级的问题。工程中常见的阈值是 1e-6 到 1e-8,具体取决于问题条件数与精度需求。但有两个细节必须处理。

第一,分母选择。用 ‖r_0‖ 作分母时,若初始猜测恰好极好,‖r_0‖ 很小,后续迭代的比值会虚高,导致过早停止;用 ‖b‖ 作分母时,若 b 本身接近零向量,同样会失真。稳妥写法是 ‖r_k‖ / max(‖b‖, ‖r_0‖, ε),其中 ε 取机器精度量级的小量,避免除零。

第二,条件数放大。相对残差小只保证 A x_k ≈ b,不保证 x_k 接近真解。若矩阵条件数 κ(A) = 10^8,相对残差 1e-8 对应的相对解误差上界仍可达 κ(A) · 1e-8 = 1,即解可能完全不可信。对病态问题,应额外用残差与解误差的经验关系估计,或改用能反映解误差的判据(如对预条件系统监控预条件残差)。

更新量范数:辅助判据,不能单打独斗

更新量 ‖Δx‖ 回答的是“解还在不在动”。它在两类场景中有独特价值:一是解向量量级很大而残差量级很小时,相对残差可能因浮点舍入而停滞在某个平台不再下降,此时更新量能反映迭代是否已实质停滞;二是带阻尼或线搜索的算法中,步长因子 α 被压得很小时,Δx = α·d 自然很小,若单独用更新量判据,会在远未收敛时误停。

因此更新量判据的正确用法是“联合”:当相对残差已降到某个较宽松的量级(如 1e-4),再用 ‖Δx‖/‖x_k‖ < 1e-10 判断是否已进入数值停滞平台,两者同时满足才停止。单独使用更新量,几乎必然在阻尼场景下早停。

目标函数变化:只属于优化问题,且要防平坦区

对最小化 f(x) 的优化问题,|f(x_k) − f(x_{k−1})| < tol 是常见判据。它的陷阱在于:目标函数在远离最优点处也可能很平坦,此时 Δf 很小但梯度并不小,迭代其实还在缓慢推进;反之在接近最优时 Δf 可能因浮点噪声而反复跳动,永远达不到严格阈值。工程做法是同时监控梯度范数 ‖∇f‖,并要求 |Δf| 连续若干步小于阈值,而不是单步判断。

避免早停与过迭代的联合准则

单一判据都有盲区,实践中普遍采用“主判据 + 辅助判据 + 硬上限”的组合。下面是一份可直接套用的停止准则配置示例(参数为教学示例值,需按实际问题调整):

stop_criteria:
  primary:   relative_residual        # 主判据
  tol_rel:   1.0e-8                   # ‖r_k‖ / max(‖b‖, ‖r_0‖, eps)
  secondary: update_norm              # 辅助判据
  tol_dx:    1.0e-10                  # ‖Δx‖ / max(‖x_k‖, eps)
  require:   primary AND secondary    # 两者同时满足才停
  max_iter:  5000                     # 硬上限,防死循环
  stagnation_window: 20               # 连续 20 步残差下降不足 1% 则告警
  stagnation_ratio: 0.99

# 判定逻辑(伪代码)
for k in 1..max_iter:
    r = b - A @ x
    rel = norm(r) / max(norm(b), norm(r0), eps)
    dx  = norm(x - x_prev) / max(norm(x), eps)
    if rel < tol_rel and dx < tol_dx:
        return CONVERGED
    if k >= stagnation_window and rel > stagnation_ratio * rel_history[-stagnation_window]:
        return STAGNATED          # 停滞,需检查预条件或改用直接法
return MAX_ITER_REACHED           # 未收敛,结果不可直接采信

这段逻辑的关键点有三:其一,主判据用相对残差保证尺度无关;其二,辅助判据用更新量捕捉数值停滞,两者“与”关系避免阻尼场景早停;其三,停滞检测与最大迭代数兜底,把“没收敛”显式暴露出来,而不是悄悄返回一个不可信的解。实际调参时,若发现频繁触发 STAGNATED,优先检查预条件子是否失效或矩阵是否接近奇异;若频繁触发 MAX_ITER_REACHED,则先确认阈值是否过严,再考虑换求解器或改进预条件。

停止准则返回“收敛”只代表所选判据达标,不代表解一定正确。对病态问题、非线性多解问题,建议在收敛后做一次残差回代验证(计算 ‖b − A x‖ 并与阈值比对),必要时用更高精度或直接法在小规模子问题上交叉验证。

最后要强调“过迭代”同样有害。阈值设得过严(如 1e-14),在双精度下残差早已被舍入误差主导,继续迭代只会让解在噪声中漂移,甚至破坏已获得的精度。合理的阈值应与问题条件数、数据精度和下游用途匹配:工程仿真常用 1e-6 到 1e-8,高精度科学计算才需要逼近机器精度,且此时应配合更高精度的算术或迭代精化,而不是一味压低阈值。