VOL.II · 矩阵CH 09( 09 , 24 )

逆矩阵与解方程 Ax=b

你在相册里给照片加了一层透视变形,导出时后悔了——「撤销」按钮做的事,是找到一个恰好抵消原变换的反变换。矩阵世界的 Ctrl+Z 叫逆矩阵。它同时是另一个古老问题的钥匙:解方程组 Ax = b,「已知输出,反求输入」。这一章用一个双视角 Demo 把方程组拆成两幅画——初中老师画过的「两条直线求交点」,和一幅你多半没见过、但更接近 AI 本质的「凑配方」图。最后送你一条工程铁律:这辈子几乎不需要真的算出逆矩阵,以及为什么。

逆矩阵Ax=b行图像与列图像solve 不 inv

撤销键的规格说明

矩阵 A 的,记作 A⁻¹,定义是「做完 A 再做它,等于什么都没做」:

A⁻¹A = AA⁻¹ = I左撤右撤都得干净

几何读法:A 把空间拧了一把,A⁻¹ 就是那只把空间原样拧回来的手,每一支箭头都被送回出发点。旋转 30° 的逆是旋转 −30°;放大 2 倍的逆是缩小一半;剪切的逆是反向剪切扶正。每个可撤销的动作,撤销方式唯一——逆矩阵如果存在,就只有一个。

谁没有撤销键?上一章已经宣判过:det = 0 的压扁变换。平面被拍成一条线,无穷多个输入挤在同一个输出上,「撤销」无从谈起——你看着地上的影子,还原不出那只 3D 的手。存在性判据就一条:A 可逆 ⇔ det A ≠ 0。「可逆」「非奇异」「满秩」(第 12 章)是同一张身份证的三个译名。

二维的逆有个值得一看的公式(n 维的就不必了,交给数值库):

abcd−1 = 1ad−bc d−b−ca

看结构,别背数字:分母是 det——再次确认 det = 0 时无逆(除不了零);矩阵部分是「主对角线互换、副对角线取负」,恰好把原变换的拉伸方向对调、剪切方向反接。公式在二维还算眉清目秀,到三维就开始狰狞,到 n 维就是纯粹的数值任务了。

几条顺手的小账,配几何画面白送:逆的逆是自己(撤销撤销 = 原操作);I⁻¹ = I(什么都没做,不用撤);(kA)⁻¹ = A⁻¹/k;对角矩阵的逆 = 对角线逐个取倒数(每个轴独立回缩)——只要对角线上没有 0,又一次和 det ≠ 0 对上。还有一条美得反常的:旋转矩阵的逆恰好等于它的转置,R⁻¹ = Rᵀ——转置这么廉价的操作居然能当撤销键用,这不是巧合,是「正交矩阵」家族的族徽,下一章动物园里给它立正式档案。

Ax = b:同一个方程,两幅画

逆矩阵的第一个正经工作岗位,是那个人类算了两千年的问题:解线性方程组。「鸡兔同笼」是它,GPS 定位解算是它,给神经网络求闭式解的一切场合还是它。初中解过的方程组,比如「x + y = 2 且 x − y = 0.5」,用矩阵写就是:

111−1xy = 20.5即 A x = b

这行式子可以从两个方向看,两幅画各有各的洞见,Demo 里可以来回切换:

Ax=b 双视角:行图像 vs 列图像DEMO 07

行图像(直线求交)。读:每一行是一个方程,一条直线上的所有点都满足它;两个方程都满足的点 = 两条直线的交点。这是初中老师画的那幅画。Demo 默认就停在这个视角:橙红、青蓝两条直线各代表一行,紫色圆点是解;拖动四个系数滑杆,直线转动,交点滑走。它的优点是直观,缺点是难推广——四十个未知数就是四十张超平面在 40 维空间里求交,画不出也想不动。

列图像(凑配方)。读:还记得第 06 章「Ax = 以 x 为配方组合 A 的列」吗?那么 Ax = b 是在问:「A 的两根列向量,各取多少份,能凑出目标 b?」解 (x, y) 就是那份配方。切到列视角,拖动紫色的 b 点试试:配方读数实时变化,浅色路径显示「先走 x 份列₁,再走 y 份列₂」正好踩到 b。这幅画的优点是无限可推广——它就是第 03 章的张成问题:「b 在不在列们的张成里?配方是多少?」

三种剧情,两幅画对照着看,把「det = 0 会发生什么」演完整:

  • 唯一解(det ≠ 0):行图像里两线交于一点;列图像里两列不共线、张成整个平面,任何 b 都有且只有一份配方。
  • 无解(det = 0,b 不配合):行图像里两线平行;列图像里两列共线、张成只剩一条线,而 b 偏偏不在线上——够不着。把滑杆调成第二行 = 第一行的倍数,再把 b 拖离那条线,亲眼看看。
  • 无穷多解(det = 0,b 恰好在线上):行图像里两线重合;列图像里 b 躺在共线的方向上,配方随便凑——多退少补,一条直线的解。
◈ 几何直觉

行图像与列图像的分工值得记一辈子:行视角好判断「有没有解」的病理(平行?重合?),列视角好理解「解是什么」的本质(配方)。AI 里几乎总是列视角占上风——「b 能不能被列们表示」「表示系数是多少」正是 embedding、字典学习、压缩感知的语言。而当第 14 章遇到「无解但要硬解」的最小二乘时,列视角会直接给出答案:b 够不着,就投影到够得着的地方。

用函数的语言再说一遍

把 A 看作函数(第 06 章的老规矩),「解 Ax = b」的三种剧情能翻译成程序员熟悉的语言,而且这套语言在高维照样好使:

  • 每个 b 都有解 = 函数是满射(输出空间没有死角)= A 的列张成整个输出空间。列不够多或者共线,输出空间就有够不着的地址——「404 Not Found」。
  • 解从不撞车(不同 x 必给不同 b)= 函数是单射 = 没有两个输入被压到同一处 = 「被 A 压到原点的向量只有零向量自己」。这批「被压到原点的倒霉蛋」有正式名字:零空间(null space),第 12 章立档。零空间越大,信息压损越狠。
  • 可逆 = 满射 + 单射 = 双射:输入输出一一对应,像一张无损的双向映射表。方阵世界还有条免费彩蛋:满射与单射二者有其一,必有其二(维数守恒逼的),所以判可逆只需验一头。

这套翻译的价值在于换挡:低维时你用几何(直线、平面)想问题,高维画不出来时,切到「满射/单射/零空间」的函数语言继续推理——第 12 章的秩-零度定理会把这两套语言焊死在一起。

病态:两条几乎平行的直线

「det ≈ 0 比 det = 0 更阴险」值得一个具体的数字现场。看这个方程组:

ill_conditioned.py
A = np.array([[1.00, 1.00],
              [1.00, 1.01]])
b1 = np.array([2.00, 2.01])
b2 = np.array([2.00, 2.02])   # b 只动了 0.01

np.linalg.solve(A, b1)        # [1., 1.]
np.linalg.solve(A, b2)        # [0., 2.] —— 解跳了一整格!

b 的第二个分量抖了 0.5%,解从 (1, 1) 跳到 (0, 2)——扰动被放大了上百倍。det 呢?0.01,不为零,solve 照常工作、绝不报错。这就是「阴险」的含义:合法但不可靠。行图像一看便知:两条直线的斜率是 −1 和 −1/1.01,几乎平行,像一把快合拢的剪刀;剪刀口附近,刀刃的一丝颤动都会让交点沿着刀刃狂奔。你可以在上面的 Demo 里复刻:把第二行滑杆调到几乎是第一行的倍数(但别完全相等),然后轻轻拖动 b——看紫色交点如何大幅跳动。这样的方程组叫病态(ill-conditioned)。真实数据的测量误差远大于 0.5%,所以病态系统解出来的数字可以毫无意义——哪怕 solve 一声不吭地返回了结果。「解出来了」和「解可信」是两回事,这个区分在第 14 章(共线特征的回归)和第 17 章(条件数)还会加码。

高斯消元:被误解的优等生

大学教的高斯消元,你记住的可能只剩「一行减去另一行的倍数,消出上三角」。它值得一个更体面的画像。每一步「行 i 减 k 倍行 j」,几何上是对方程组的解释方式做一次剪切变形——关键是,它不动解本身:两条直线各自旋摆,交点纹丝不动。消元的全过程,是把一组歪歪扭扭的直线逐步摆成「一条竖线 + 一条横线」的标准姿势,交点坐标直接读出。

这套流程的工业版叫 LU 分解:把 A 拆成「下三角 L × 上三角 U」,消元的账都记在 L 里,解方程变成两次「三角矩阵回代」——每次 O(n²),比重新消元省得多。np.linalg.solve(A, b) 底下调的就是它(LAPACK 的百炼成钢实现)。你不需要会笔算,但值得知道:三角矩阵是数值线性代数的通用中间格式,像编译器的 IR——LU、Cholesky、QR,全是「把矩阵搞成三角形再快速回代」的变奏。

当矩阵大到 solve 也吃不下:迭代法一瞥

LU 分解是 O(n³):n = 一万还算轻松,n = 一千万(推荐系统的用户数、科学计算的网格点数)就是天文数字,而且那种规模的矩阵通常根本存不下稠密形式。这时换第三种哲学:迭代法——不去「解」方程,而是从一个猜测 x₀ 出发,反复用「A 乘一次向量」这种便宜操作(稀疏矩阵乘向量只花非零元个数的代价)把猜测越磨越准,到误差够小就收工。共轭梯度(CG)、GMRES 是这一族的明星,它们把「解方程」变成了「优化」:最小化残差 ‖Ax − b‖。

眼熟吗?这正是深度学习训练的世界观:神经网络的「方程」没有闭式解,所以我们从随机初始化出发,用梯度下降迭代磨,磨到损失够低为止。「直接法失效时退而求迭代」,是数值计算与机器学习共享的一条祖训——从这个角度看,梯度下降只是迭代解法家族里最能吃苦的那个孩子。

工程铁律:要 solve,不要 inv

现在是本章最有含金量的一段。教科书思路:「解 Ax = b?两边左乘 A⁻¹,x = A⁻¹b,收工。」真实世界:几乎永远不要这么写。

solve_vs_inv.py
import numpy as np

A = np.random.randn(2000, 2000)
b = np.random.randn(2000)

x_bad  = np.linalg.inv(A) @ b     # ✗ 慢一倍以上,误差更大
x_good = np.linalg.solve(A, b)    # ✓ 更快、更稳

# 精度对比(残差范数,越小越好)
np.linalg.norm(A @ x_bad  - b)    # 典型值:~1e-10
np.linalg.norm(A @ x_good - b)    # 典型值:~1e-12,好两个数量级

原因有三。① 浪费:求出完整的 A⁻¹ 等于解了 n 个方程组(A⁻¹ 的每一列是一个 Ax = eᵢ 的解),而你只需要一个;② 精度:inv 的舍入误差在「先求逆、再乘 b」两步中被放大,solve 的 LU 路线一步到位;③ 结构:A 若是稀疏的(大图的邻接矩阵、有限元的刚度阵),A⁻¹ 几乎必然是稠密的——一求逆,内存爆炸;solve 能全程保持稀疏。把「见到 inv 就皱眉」练成条件反射,是数值素养的第一课。真正需要 A⁻¹ 整体的场合罕见(比如要读它的元素做统计推断),那时才请它出山。

彩蛋:改一点,不必重解

一个漂亮的进阶事实,放在这里当本章的甜点。假设你辛苦解完了一个大系统(或者攒好了 A⁻¹ 的某种分解),这时矩阵被轻微修改了——加上一个秩一补丁 uv(第 07 章的外积,还记得吗)。要从头再解一遍吗?不用。Sherman–Morrison 公式说,打补丁后的逆可以用旧的逆拼几次矩阵乘向量直接修出来,代价从 O(n³) 掉到 O(n²)。在线学习里模型每来一条新样本更新一次、卡尔曼滤波每帧修正一次,靠的都是这类「增量更新」而不是重算。

它的精神对 AI 读者尤其眼熟:「大矩阵 + 低秩补丁」是一种既表达了变化、又保留了旧结构的改法。第 23 章的 LoRA 微调——冻结原权重 W,只训练一个低秩的 ΔW = BA 贴上去——正是同一个思想从「解方程」搬到「改模型」:改动很便宜,因为补丁很薄。数学里的省钱套路,换个舞台还是省钱套路。

◆ AI 连接

深度学习对逆矩阵的态度很有意思:能躲就躲。前向传播没有逆,反向传播没有逆(链式法则只要转置),优化器 Adam 只用逐元素运算——因为上万维的求逆既昂贵又数值危险。逆真正出场的地方都经过精心包装:① 线性回归的闭式解 (XᵀX)⁻¹Xᵀy(第 14 章),实操中也用 solve/QR 而非 inv;② 二阶优化(牛顿法、K-FAC)要用曲率矩阵的逆,全都换成近似或低秩技巧;③ Normalizing Flows 需要每一层可逆,干脆把网络架构设计成逆有闭式解的形状(耦合层),而不是硬算。「怎么绕开求逆」本身就是一个研究方向——侧面证明了这一章工程铁律的分量。

▸ Android 类比

你写自定义 View 处理触摸时早就用过逆矩阵:View 被 rotation/scale 变换过,而 MotionEvent 给的是屏幕坐标——要判断手指点没点中图形,得把屏幕坐标逆映射回图形的本地坐标系:matrix.invert(inv); inv.mapPoints(pt)。这正是「已知输出(屏幕位置),反求输入(本地位置)」的 Ax = b。而上一章说过,当 scaleX 动画到 0 时 invert() 返回 false——现在你能说出完整的因果链:缩放到 0 → det = 0 → 压扁不可逆 → 触摸坐标还原失败 → 控件「点不到」。

⚠ 坑

顺序反转:(AB)⁻¹ = B⁻¹A⁻¹——脱衣服定律又来了(和转置同款):撤销「先 A 后 B」,得先撤 B 再撤 A。② 「近似奇异」比「奇异」更阴险:det 恰好为 0 会痛快地报错,det = 10⁻¹² 却会安静地给你一个误差爆表的解(两条几乎平行的直线,交点对系数的抖动极端敏感)。这就是「病态矩阵」,体检指标是条件数,第 17 章正式立案。③ 非方阵没有逆:3 个方程 2 个未知数(超定)通常无解,2 个方程 3 个未知数(欠定)解不唯一——但它们有「最像逆的东西」:伪逆,第 14 章用投影把它徒手造出来。

✋ 动手自测

① 旋转 90° 矩阵 [0,−1;1,0] 的逆是什么?先用几何猜,再用二维公式验证;

② 在 Demo 里制造「无解」:需要动哪几个滑杆、b 放哪?说出行、列两幅画里各自的病灶;

③ 为什么 A⁻¹ 的第 j 列恰好是方程 Ax = eⱼ 的解?(用列配方视角想);

④ 同事的代码里有 np.linalg.inv(K) @ y,你会怎么改、给出哪两条理由?

⑤ (ABC)⁻¹ 等于什么?

小结

逆矩阵是变换的撤销键,det ≠ 0 才发放,存在必唯一;Ax = b 的行图像是直线求交(好诊断),列图像是凑配方(好推广),唯一解/无解/无穷解对应交点/平行/重合与「b 在不在列空间里」;用函数语言说,可逆 = 满射 + 单射,零空间只剩零向量;两条几乎平行的直线是病态系统的原型,解得出不等于解得准;高斯消元是不动解集的剪切整形,工业形态叫 LU,巨型稀疏问题则交给迭代法磨;工程上永远 solve 不 inv,深度学习则干脆把逆设计出局。卷二的四大件——变换、复合、账本、撤销——至此配齐,你已经能读懂绝大多数论文里矩阵表达式的「动作含义」。下一章是卷二的轻松番外:逛一圈特殊矩阵动物园,把单位、对角、正交、对称、置换、稀疏这些 AI 代码里的常驻嘉宾一次认全,顺便发现「好性质的矩阵」为什么总在关键位置出现。