Series · Linear Algebra · Chapter 10

矩阵范数与条件数 -- 数值计算的健康体检

条件数是线性系统的'健康体检报告':它告诉你输入端的微小扰动会不会被放大成输出端的灾难。本章从向量范数、矩阵范数讲到谱范数、条件数与谱半径,剖析数值不稳定的根源,并给出预条件这一治本之策。

困扰工程师的那个问题

方程列对了,算法也写对了,为什么算出来的结果完全不对?

罪魁祸首往往是一个叫做条件数的量。它衡量一个线性系统有多"敏感"——输入端一点点抖动,会不会被放大成输出端的灾难。要谈条件数,得先有办法度量向量和矩阵的"大小",这就是范数要做的事。

本章要点

  • 三种向量范数($L^1$、$L^2$、$L^\infty$)以及它们的"单位球"长什么样。
  • 矩阵范数:Frobenius 范数、诱导范数,以及最关键的谱范数。
  • 条件数 $\kappa(A) = \sigma_{\max}/\sigma_{\min}$ 到底意味着什么。
  • 病态矩阵(如 Hilbert 矩阵)为什么会在双精度下完全失效。
  • 输入误差如何被条件数放大。
  • 谱半径与迭代法的收敛性。
  • 用预条件子驯服病态矩阵。

前置知识

  • 奇异值与 SVD(第 9 章)
  • 矩阵乘法与求逆(第 3 章)
  • 特征值(第 6 章)

向量范数:度量"大小"

什么是范数?

向量空间上的范数 $\|\cdot\|$ 是满足三条公理的函数:

  1. 非负性。 $\|\vec{x}\| \geq 0$,且等号当且仅当 $\vec{x} = \vec{0}$。
  2. 齐次性。 $\|c\vec{x}\| = |c|\,\|\vec{x}\|$。
  3. 三角不等式。 $\|\vec{x} + \vec{y}\| \leq \|\vec{x}\| + \|\vec{y}\|$。

这三条都和我们日常对"大小"的直觉一致:没有什么东西的大小可以是负数;放大两倍尺寸也变两倍;绕路永远不会比直走更短。

必须熟记的三种范数

对 $\vec{x} \in \mathbb{R}^n$:

$L^1$ 范数 —— 曼哈顿距离。 $\|\vec{x}\|_1 = |x_1| + |x_2| + \cdots + |x_n|.$ 出租车在网格街道上只能横平竖直地开,从原点到 $(3, 4)$ 要走 $3 + 4 = 7$ 个街区。

$L^2$ 范数 —— 欧几里得距离。 $\|\vec{x}\|_2 = \sqrt{x_1^2 + x_2^2 + \cdots + x_n^2}.$ “乌鸦直飞"的距离,从原点到 $(3, 4)$ 是 $\sqrt{9+16}=5$。

$L^\infty$ 范数 —— 切比雪夫距离。 $\|\vec{x}\|_\infty = \max_i |x_i|.$ 国际象棋的国王每步可走八方向中的一步。从 $(0,0)$ 到 $(3, 4)$ 共 $\max(3,4) = 4$ 步——因为国王能斜走,等于横竖两个方向同时推进。

单位球的几何

每种范数都对应一个"单位球” $\{\vec{x} : \|\vec{x}\| \leq 1\}$:

  • $L^1$:二维是菱形,三维是八面体——尖角正好戳在坐标轴上。
  • $L^2$:二维是圆,三维是球——完全旋转不变。
  • $L^\infty$:二维是正方形,三维是立方体——平面紧贴坐标轴。

随着 $p$ 从 $1$ 增大到 $\infty$,单位球从菱形"鼓"成圆,再"撑"成正方形。$L^1$ 球那几个尖角,正是 LASSO 回归能产生稀疏解的几何原因:损失函数的等高线很容易最先碰到 $L^1$ 球的尖角,而尖角位于坐标轴上——意味着某些坐标必然被压成零。

向量范数:单位球的形状随 p 变化

范数等价定理

$$c\|\vec{x}\|_a \leq \|\vec{x}\|_b \leq C\|\vec{x}\|_a.$$

不同范数只是用不同的尺子量同一个向量。在某个范数下收敛的序列,在所有范数下都收敛。范数的选择更多是物理意义和计算便利的取舍——但一旦谈到收敛速度,范数的选择又重新重要起来。


矩阵范数:这个变换有多"猛"?

Frobenius 范数:把矩阵当成一个长向量

$$\|A\|_F = \sqrt{\sum_{i,j} a_{ij}^2}.$$

做法很朴素:把所有元素拉直成一个长向量,算它的 $L^2$ 范数。

图像类比。 把 $A$ 想成灰度图,每个元素是一个像素亮度。Frobenius 范数就是这张图的"总能量"。从图像压缩误差,到神经网络权重更新的幅度,工业界用它来度量"两个矩阵差多远"几乎是默认选项。

$$\|A\|_F = \sqrt{\sigma_1^2 + \sigma_2^2 + \cdots + \sigma_r^2}.$$

所以 Frobenius 范数是所有奇异值的均方根——它在意 $A$ 在每一个方向上的拉伸。

诱导范数:最大放大倍数

$$\|A\| = \max_{\|\vec{x}\|=1} \|A\vec{x}\|.$$

把 $A$ 想成放大镜——诱导范数问的是:这个放大镜最大能放多少倍?如果 $\|A\|_2 = 3$,就意味着存在某个输入,被 $A$ 作用后长度变成原来的 3 倍。

最常见的三种诱导范数:

范数公式怎么算
$\|A\|_1$(列和范数)$\max_j \sum_ia_{ij}
$\|A\|_2$(谱范数)$\sigma_{\max}(A)$最大奇异值
$\|A\|_\infty$(行和范数)$\max_i \sum_ja_{ij}

记忆口诀: $1$ → 列和,$\infty$ → 行和。

谱范数:当家花旦

谱范数 $\|A\|_2 = \sigma_1$ 是最有用的矩阵范数:

  • 等于最大奇异值
  • 几何上,$A$ 把单位球映成椭球,$\|A\|_2$ 就是椭球最长半轴的长度。
  • 它就是 $A$ 的最大放大倍数

算子范数:像椭圆最长半轴

上图把整件事讲完了。左边是单位圆和两个极端方向 $v_{\max}$、$v_{\min}$。右边是经过 $A$ 旋转拉伸后的椭圆——橙色箭头落在最长半轴上,长度是 $\sigma_{\max} = \|A\|_2$;绿色箭头被压缩到长度 $\sigma_{\min}$。

Frobenius 与谱范数:两种"大小观"

这两种范数在回答同一个矩阵的两个不同问题。谱范数是峰值拉伸——担心最坏情况的时候用它。Frobenius 范数是总体拉伸——关心整体行为时用它。

Frobenius 与谱范数

图中那个矩阵,$\|A\|_2 = \sigma_1 \approx 2.78$,而 $\|A\|_F \approx 2.93$。两者很接近,是因为 $\sigma_2$ 相对 $\sigma_1$ 已经不大;如果一个矩阵的奇异值都差不多大,二者会拉开明显的差距。

次乘性

$$\|AB\| \leq \|A\|\,\|B\|.$$

两次变换叠加的总放大倍数,不会超过两次单独放大倍数的乘积。这条不起眼的不等式,是分析所有迭代算法收敛性的基石——也解释了为什么深层神经网络容易出现梯度爆炸/消失。


条件数:线性系统的体检报告

定义

$$\kappa(A) = \|A\|\,\|A^{-1}\|.$$$$\kappa_2(A) = \frac{\sigma_{\max}}{\sigma_{\min}}.$$

最大奇异值除以最小奇异值。

过敏体质类比。

  • $\kappa \approx 1$:免疫系统强健,吹一阵冷风没事。
  • $\kappa \approx 10^{10}$:极度过敏,空气里飘一点花粉就送急诊。

条件数:良态 vs 病态

良态的矩阵把输入圆映成一个接近圆的椭圆(虚线灰圆几乎和绿色实线椭圆重合)。病态的矩阵把同一个圆压成一根针:在输入空间里有那么些方向,矩阵几乎"看不见"——做反演时就得把这些被压扁的输出再放大回去,于是噪声也跟着一起放大了。

关键性质

  • 下界。 $\kappa(A) \geq 1$,等号只在 $A$ 是正交矩阵的标量倍时成立。
  • 正交不变性。 对正交矩阵 $Q$,$\kappa(QA) = \kappa(A)$——旋转和反射不改变病态程度。
  • 缩放不变性。 $\kappa(\alpha A) = \kappa(A)$——决定健康的是椭圆的形状,不是大小。
  • 求逆对称性。 $\kappa(A^{-1}) = \kappa(A)$——解方程和求逆一样难。

一句话几何意义

$$\kappa = \frac{\text{最长半轴}}{\text{最短半轴}}.$$

$\kappa = 1$ 椭圆退化为圆;$\kappa = \infty$ 椭圆塌成一条线段(矩阵奇异)。

速记例子。 $A = I$,$\kappa = 1$。$B = \begin{pmatrix} 1 & 0 \\ 0 & 10^{-5} \end{pmatrix}$,$\kappa = 10^{5}$——某个方向被压扁了 $10^{5}$ 倍。


病态矩阵:数值计算的噩梦

Hilbert 矩阵

$$H_{ij} = \frac{1}{i + j - 1}.$$

它的条件数增长得快到让人胆寒。

阶数 $n$$\kappa(H_n)$双精度下可信位数
5$\sim 10^{5}$约 10 位
10$\sim 10^{13}$约 3 位
12$\sim 10^{16}$几乎为 0
15$\sim 10^{18}$完全不可靠
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import numpy as np
from scipy.linalg import hilbert

n = 12
H = hilbert(n)
x_true = np.ones(n)
b = H @ x_true
x_hat = np.linalg.solve(H, b)

print(f"kappa(H_{n})    = {np.linalg.cond(H):.2e}")
print(f"相对误差       = {np.linalg.norm(x_true - x_hat) / np.linalg.norm(x_true):.2e}")

到 $n = 12$,相对误差就已经在 $1$ 这个量级——算法本身没错,但答案就是可以错 100%。

把"爆炸"画出来

奇异值谱与 Hilbert 矩阵的 κ(n) 增长

左图是两个 $20 \times 20$ 矩阵的奇异值:一个温顺,奇异值平缓下降;一个病态,奇异值跨越六个数量级。右图把 $\kappa_2(H_n)$ 画在对数坐标里——几乎是一条直线,每两个 $n$ 值条件数就翻一番左右。红色虚线是双精度的天花板 $10^{16}$,越过这条线,IEEE 754 双精度的任何算法都救不回来。

病态从哪儿来?

  • 多项式拟合。 高次拟合产生的 Vandermonde 矩阵,条件数随阶数指数增长。
  • 细网格。 有限元网格细化 $h$ 倍,条件数大致变为原来的 $h^{-2}$ 倍。
  • 正规方程。 $\kappa(A^TA) = \kappa(A)^2$——把最小二乘问题硬推成正规方程,条件数直接平方,业内有人称之为"数值线性代数的原罪"。
  • 接近奇异。 两行(或两列)“几乎"线性相关。

误差分析:条件数到底放大了多少

右端项扰动

求解 $A\vec{x} = \vec{b}$,但右端 $\vec{b}$ 被一点点 $\delta\vec{b}$ 污染了。解会变多少?

$$\frac{\|\delta\vec{x}\|}{\|\vec{x}\|} \;\leq\; \kappa(A)\,\frac{\|\delta\vec{b}\|}{\|\vec{b}\|}.$$

条件数就是相对误差的最大放大因子

具体地:

  • $\kappa = 10$:$1\%$ 的输入误差最多变成 $10\%$ 的输出误差。
  • $\kappa = 10^{10}$:$1\%$ 的输入误差可能放成 $10^{8}\%$——结果就是噪声。
  • $\kappa = 10^{16}$:连机器精度(约 $10^{-16}$)的舍入都足以毁掉答案。

我们可以把它真切地"看到”。下图把同样幅度($2\%$)但方向各异的扰动加到 $b$ 上,画出每个扰动对应的解 $x + \delta x$ 形成的点云。

扰动敏感性:微小 δb,巨大 δx

$\kappa \approx 2$ 时,点云缩成围着真解 $x$ 的一小圈,放大倍数约 $1$。$\kappa \approx 200$ 时,完全相同幅度的扰动让解沿着一条对角长针来回滑动——最坏放大倍数大约就是 $\kappa$ 本身。

矩阵扰动

$$\frac{\|\delta\vec{x}\|}{\|\vec{x}\|} \;\leq\; \kappa(A)\!\left(\frac{\|\delta A\|}{\|A\|} + \frac{\|\delta\vec{b}\|}{\|\vec{b}\|}\right).$$

公式还是同样的"罚款率"——矩阵元素的误差也照样被 $\kappa(A)$ 放大。

经验法则:损失多少位有效数字

如果 $\kappa(A) \approx 10^k$,在双精度下解 $A\vec{x} = \vec{b}$ 大约会损失 $k$ 位有效数字

$\kappa(A)$损失位数可靠位数
$10^{4}$4≈ 12
$10^{8}$8≈ 8
$10^{12}$12≈ 4
$10^{16}$160(完全不可信)

谱半径与迭代收敛

定义

$$\rho(A) = \max_i |\lambda_i|.$$

它被任何矩阵范数从上方控制:$\rho(A) \leq \|A\|$。

收敛判据

迭代格式 $\vec{x}_{k+1} = B\vec{x}_k + \vec{c}$,从任意初值都收敛当且仅当 $\rho(B) < 1$。

淋浴水温类比。 如果系统稳定($\rho < 1$),每次调节都更接近目标温度;如果不稳定($\rho \geq 1$),水温就会在冰水和滚烫之间反复横跳。

收敛速度。 每迭代一次误差大约缩小为 $\rho(B)$ 倍,所以达到误差 $\epsilon$ 大约需要 $\log\epsilon / \log\rho(B)$ 步。$\rho$ 越小,收敛越快。

Neumann 级数

$$(I - A)^{-1} = I + A + A^2 + A^3 + \cdots,$$

正是 $\frac{1}{1-x} = 1 + x + x^2 + \cdots$ 的矩阵版本。在摄动分析和小矩阵逆的近似计算中很常用。


数值稳定性:算法挑选学

为什么正规方程是个陷阱

$$\kappa(A^TA) = \kappa(A)^2.$$

$A$ 的条件数是 $10^6$,正规方程的条件数就成了 $10^{12}$——这是你自己亲手制造的灾难。

QR:稳定的替代

用 $A = QR$ 求解 $R\hat{\vec{x}} = Q^T\vec{b}$。因为 $Q$ 是正交矩阵,问题的条件数仍然是 $\kappa(A)$,没有被平方。这是几乎所有现代最小二乘库的默认做法。

SVD:最稳定但最贵

用伪逆 $\hat{\vec{x}} = V\Sigma^+U^T\vec{b}$ 求解。SVD 优雅地处理秩亏问题,给出最小范数解,并把奇异值送给你做"赠品"。代价是大约 2–3 倍 QR 的开销。

三种解法的对比

下图用同一个 $50 \times 50$ 系统 $Ax = b$,把三种解法在条件数从 $10^2$ 一路加到 $10^{14}$ 的过程中,相对误差的演化画出来:

数值稳定性:三种解法的误差 vs 条件数

三个值得注意的现象。(1) QR 和 SVD 的曲线几乎重合,沿着 $\varepsilon_{\text{mach}} \cdot \kappa$ 这条参考线一路向上。(2) 正规方程的曲线在双对数坐标下斜率是它们的两倍——这就是 $\kappa^2$ 的"税金"。(3) 在 $\kappa \approx 10^8$ 附近,正规方程已经穿过了"完全不可信"的红线,QR / SVD 这时候还有八位有效数字。算法的选择,要在数据进入之前就做好。


预条件:驯服病态矩阵

核心想法

$$M^{-1}A\vec{x} = M^{-1}\vec{b}.$$

若 $M \approx A$,则 $M^{-1}A \approx I$,新系统 $\kappa(M^{-1}A) \approx 1$。

类比。 用厨房秤称大象毫无意义——但如果你已经粗略知道大象重多少,秤只需要量误差就行。预条件就是把一个"尺度不对"的问题,搬到你的工具能称量的尺度上。

常见预条件子

预条件子$M$优点缺点
Jacobi$\text{diag}(A)$实现简单,天然并行提升有限
Gauss–Seidel$A$ 的下三角部分比 Jacobi 强不易并行
不完全 LU(ILU)稀疏近似 $LU$通用且强力需要控制填入元
不完全 Cholesky(ICC)稀疏近似 $LL^T$存储减半仅适用于对称正定

权衡是一致的:预条件越强,迭代次数越少,但每步代价更高。最强的预条件子往往利用问题本身的结构(PDE 用几何多重网格,并行求解用域分解,等等)。


应用拾遗

有限元分析

结构力学里的刚度矩阵 $K$ 满足 $\kappa(K) \propto h^{-2}$,$h$ 是网格尺寸。为捕捉几何细节而细化网格,会让矩阵越来越难解。如果网格高度不均匀,或者材料属性差异巨大(比如钢筋混凝土,钢和混凝土的刚度差好几个数量级),情况更糟——预条件几乎是必需的。

图像去模糊

$$\min_{\vec{x}} \|B\vec{x} - \vec{y}\|^2 + \lambda\|\vec{x}\|^2.$$

正则化参数 $\lambda$ 在保真度和稳定性之间做权衡——本质上是把条件数里的 $\sigma_{\min}$ 换成了 $\sqrt{\sigma_{\min}^2 + \lambda}$,哪怕 $\lambda$ 很小,也能救活整个问题。

深度学习:梯度消失与爆炸

权重矩阵的谱范数控制信号传播:

  • 大量层 $\|W\|_2 > 1$:前向信号(和反向梯度)指数爆炸。
  • 大量层 $\|W\|_2 < 1$:信号指数衰减;梯度消失。

应对手段——批归一化、合适的初始化(Xavier、He)、残差连接、梯度裁剪——都可以理解为:让网络雅可比矩阵的有效谱范数尽量贴近 $1$。

机器学习中的正则化

$$\kappa(X^TX + \lambda I) = \frac{\sigma_1^2 + \lambda}{\sigma_n^2 + \lambda}.$$

不大的 $\lambda$ 就能把条件数砍下好几个数量级。同样的思路(Levenberg–Marquardt、信赖域、weight decay)在优化里反复出现。


Python 示例

计算各种范数和条件数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import numpy as np

A = np.array([[1, 2],
              [3, 4]], dtype=float)

print(f"Frobenius 范数 : {np.linalg.norm(A, 'fro'):.4f}")
print(f"谱范数         : {np.linalg.norm(A, 2):.4f}")
print(f"1 范数         : {np.linalg.norm(A, 1):.4f}")
print(f"无穷范数       : {np.linalg.norm(A, np.inf):.4f}")
print(f"条件数         : {np.linalg.cond(A):.4f}")

Hilbert 矩阵实验

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
from scipy.linalg import hilbert
import matplotlib.pyplot as plt

sizes = range(2, 16)
conds = [np.linalg.cond(hilbert(n)) for n in sizes]

plt.semilogy(list(sizes), conds, "o-")
plt.xlabel("矩阵阶 n")
plt.ylabel("条件数")
plt.axhline(1e16, ls="--")  # 双精度天花板
plt.title("Hilbert 矩阵:条件数随 n 爆炸")
plt.show()

三种最小二乘解法的对比

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
def compare_methods(cond_target=1e8, n=50, seed=0):
    rng = np.random.default_rng(seed)
    Q1, _ = np.linalg.qr(rng.standard_normal((n, n)))
    Q2, _ = np.linalg.qr(rng.standard_normal((n, n)))
    s = np.logspace(0, -np.log10(cond_target), n)
    A = Q1 @ np.diag(s) @ Q2

    x_true = rng.standard_normal(n)
    b = A @ x_true

    x_normal = np.linalg.solve(A.T @ A, A.T @ b)        # 危险解法
    Q, R = np.linalg.qr(A); x_qr = np.linalg.solve(R, Q.T @ b)
    x_svd = np.linalg.lstsq(A, b, rcond=None)[0]

    print(f"kappa(A)        : {np.linalg.cond(A):.2e}")
    print(f"正规方程误差     : {np.linalg.norm(x_normal - x_true):.2e}")
    print(f"QR 误差         : {np.linalg.norm(x_qr - x_true):.2e}")
    print(f"SVD 误差        : {np.linalg.norm(x_svd - x_true):.2e}")

compare_methods()

习题

热身

  1. 计算 $\vec{x} = (3, -4, 0, 1)$ 的 $\|\vec{x}\|_1$、$\|\vec{x}\|_2$、$\|\vec{x}\|_\infty$。
  2. 计算 $A = \begin{pmatrix} 1 & 2 \\ 3 & 4 \end{pmatrix}$ 的 Frobenius 范数和谱范数。
  3. 对对角矩阵 $D = \text{diag}(d_1, \ldots, d_n)$,证明 $\kappa_2(D) = \max|d_i| / \min|d_i|$。

进阶

  1. 证明:对任意矩阵范数都有 $\rho(A) \leq \|A\|$。
  2. 证明:若 $\|A\| < 1$(诱导范数),则 $I - A$ 可逆。
  3. 证明:正交矩阵 $Q$ 满足 $\kappa_2(Q) = 1$。
  4. np.linalg.cond 估计 $\kappa(H_n)$ 在 $n = 2, \ldots, 15$ 时的值,把它画在半对数坐标里并拟合直线,估计经验增长率。

编程题

  1. 不调用 np.linalg.norm,从头实现 $\|A\|_1$、$\|A\|_2$、$\|A\|_\infty$。
  2. 复现本章的稳定性图:在不断增大的条件数下,画出正规方程、QR、SVD 三种最小二乘解的相对误差。
  3. 实现带和不带对角预条件的 Jacobi 迭代,画出"达到收敛所需迭代次数 vs 迭代矩阵谱半径"的关系曲线。

工程实务速查表

$\kappa(A)$风险建议
$< 10^{4}$标准方法即可
$10^{4}$–$10^{8}$校验结果;优先 QR 或 SVD
$10^{8}$–$10^{12}$引入正则化或预条件
$> 10^{12}$极高退一步,重新建模

本章总结

概念关键公式直觉
向量范数$|\vec{x}|_p = (\sumx_i
Frobenius 范数$\|A\|_F = \sqrt{\sum a_{ij}^2}$矩阵的总能量
谱范数$\|A\|_2 = \sigma_{\max}$最大放大倍数
条件数$\kappa = \sigma_{\max}/\sigma_{\min}$误差放大上界
谱半径$\rho(A) = \max\lambda_i
正规方程$\kappa(A^TA) = \kappa(A)^2$它危险的根本原因

系列导航

参考资料

  • Golub, G. H. & Van Loan, C. F. (2013). Matrix Computations, 4th ed. —— 数值线性代数圣经,条件数分析的权威。
  • Trefethen, L. N. & Bau, D. (1997). Numerical Linear Algebra. —— 几何直觉极佳的稳定性讲解。
  • Higham, N. J. (2002). Accuracy and Stability of Numerical Algorithms, 2nd ed. —— 数值稳定性百科全书。
  • Demmel, J. W. (1997). Applied Numerical Linear Algebra. —— 理论与实践兼顾,应用案例丰富。
  • Saad, Y. (2003). Iterative Methods for Sparse Linear Systems, 2nd ed. —— 迭代方法与预条件技术的详尽指南。

本文是"线性代数的本质"系列第 10 章,共 18 章。

Liked this piece?

Follow on GitHub for the next one — usually one a week.

GitHub