逆、秩与零空间
矩阵把空间变了形,我们能不能把这部电影倒着放?信息没丢的时候可以,这就是逆。平面被压成一条线时就不行了:有些输入被压到同一点(被压掉的方向叫零空间),有些输出再也够不到(够得到的部分叫列空间)。冗余机械臂正是靠这份“多余的自由”,在手纹丝不动的同时把手肘摆来摆去。
1为什么机器人需要它
机器人每天都在解“反问题”。我想让手以 0.1 m/s 向前走,每个关节该转多快?写成方程就是 \(J\,\dot{\mathbf q} = \dot{\mathbf x}\):矩阵 \(J\)(雅可比,3.3 节)和想要的手速 \(\dot{\mathbf x}\) 已知,要求关节速度 \(\dot{\mathbf q}\)。又比如:激光雷达看到了这些点,到底是哪个位姿产生了这些测量?
这类问题的答案有三种可能:恰好一个,一个也没有,或者无穷多个。六关节机械臂在一般姿态下,每个手速恰好对应一组关节速度。手想去的方向被关节锁死时,没有答案。而七关节机械臂有个有趣的现象:手可以纹丝不动,手肘却还能绕着转,于是有无穷多组关节速度给出同一个手速。这份多出来的自由叫零空间,机器人用它躲障碍、避开关节限位。
这一节回答三个问题:什么时候能“倒放”(逆)?不能倒放时,到底丢了什么(列空间与零空间)?答案有多少个(解集)?
2直觉:倒放电影
把矩阵 \(A\) 想成一部电影:每个点从原位置出发,滑到新位置。逆 \(A^{-1}\) 就是倒放这部电影,让每个点滑回去。要能倒放,有一个条件:不能有信息丢失。只要每个终点都能唯一地告诉你“我是从哪里来的”,倒放就成立。
剪切、旋转、拉伸都满足这个条件。但如果电影把整个平面压到一条线上(行列式 \(=0\),1.5 节),不同的起点就会挤到同一个终点,倒放时你根本不知道该把它送回哪里。下面选一种变换,把滑块拖到 1 看正放,再拖到 2 看倒放。
能不能求逆,问的是有没有信息被丢掉。丢掉的那部分有两个名字:被压成零的输入方向叫零空间;输出里真正够得到的那部分叫列空间,够不到的输出就是“信息缺口”。没有方向被压掉、所有输出都够得到,\(A\) 才可逆。
3动手玩:逆与压扁
这是 1.3 节矩阵实验室的升级版。拖动红绿箭头尖(或直接改矩阵里的数)。不带颜色的箭头是输入 \(\mathbf x\),黄色箭头是输出 \(A\mathbf x\)。右侧实时给出 \(A^{-1}\),以及它的元素有多大。点“▶”看 \(A\) 把网格拉变形,再由 \(A^{-1}\) 拉回来。把矩阵压成秩 1,看看会发生什么:青色线是列空间,紫色线是零空间,紫色虚线上的所有输入会落在同一个输出点上。
- 让 \(A\) 仍然可逆,但 \(A^{-1}\) 里某个元素的绝对值超过 10(右侧的“逆有多大”条会变红)。
- 做一个秩为 1 的矩阵,使零空间正好是直线 y = x。提示:输入 (1, 1) 要被压成 0,这对两列意味着什么?
- 在一个秩为 1 的矩阵上,把输入 \(\mathbf x\) 拖到一个非零位置,使 \(A\mathbf x = \mathbf 0\)。
小游戏:把它撤销掉
紫色网格是某个矩阵 \(A\) 作用后的样子。你的任务是找出它的逆 \(B\):拖动红绿箭头(\(B\) 的两列,也就是 \(B\hat\imath\) 和 \(B\hat\jmath\)),使 \(B\) 作用在紫色网格上之后,青色网格正好回到标准网格。读法提示:\(BA = I\) 的意思是 \(B\) 要把 \(A\hat\imath\) 送回 \(\hat\imath\),把 \(A\hat\jmath\) 送回 \(\hat\jmath\)。
- 不看答案,累计撤销 3 个矩阵。
4第二个视角:解方程 Ax = b 的几何
“倒放”换一种说法,就是解方程:给定想要的输出 \(\mathbf b\),哪个输入 \(\mathbf x\) 会产生它?两个面板对应两个空间:左边是输入空间(\(\mathbf x\) 住在这里),右边是输出空间(\(\mathbf b\) 住在这里)。拖动右边的黄色目标 \(\mathbf b\),左边会显示解的集合;也可以拖动左边的输入 \(\mathbf x\),右边会显示 \(A\mathbf x\)。
先用“可逆”预设:每个 \(\mathbf b\) 都有且只有一个 \(\mathbf x\)。再切到“秩 1”:输出被压在青色的列空间上。\(\mathbf b\) 在线上,解有一整条线;\(\mathbf b\) 离开了线,则一个解也没有。
- 选“秩 1”预设,让 \(\mathbf b\) 落在青色列空间上(且 \(\mathbf b \ne \mathbf 0\)),看解变成一整条线。拖动输入 \(\mathbf x\) 沿黄线滑动:\(\mathbf b\) 不动。
- 在秩 1 的矩阵上,找一个没有解的 \(\mathbf b\)。
5第三个视角:三维里的秩与零空间
在三维里,一个 \(3\times3\) 矩阵把单位立方体变成平行六面体。如果有信息丢失,六面体会塌掉:秩 3 是实心的,秩 2 压成一片平行四边形,秩 1 压成一根线,秩 0 压成一个点。能到达的地方(列空间)有多大,取决于秩;被压掉的方向(零空间)有多大,取决于“还剩多少自由”。两者的维数之和永远等于 3:
转动视角,点预设,或者直接编辑矩阵。立方体的红、绿、蓝三类边是 \(A\) 的第 1、2、3 列。
- 不用预设,只改矩阵里的数,让立方体压成一片(秩 2)。提示:把第 3 行全部改成 0。
- 让立方体压成一根线(秩 1),然后数一数:零空间的维数是几?
6再看数学
提示:把鼠标悬停在公式中带底色的符号上,FIG 2 和 FIG 4 里对应的元素会被加粗。
逆
如果存在矩阵 \(A^{-1}\),使得
就说 \(A\) 可逆,\(A^{-1}\) 是它的逆。\(A^{-1}A = I\) 的意思是:先做 \(A\),再做 \(A^{-1}\),等于什么都没做(回忆 1.4 节:右边的先作用)。对 \(2\times2\) 矩阵,逆有一个封闭公式:
不必死记,验证一下就会了。把两个矩阵乘起来:
除以 \(ad - bc\)(就是行列式)后得到 \(I\)。例如 \(A = \begin{bmatrix}2&1\\4&3\end{bmatrix}\),\(\det A = 6 - 4 = 2\),所以 \(A^{-1} = \tfrac12\begin{bmatrix}3&-1\\-4&2\end{bmatrix} = \begin{bmatrix}1.5&-0.5\\-2&1\end{bmatrix}\)。把两者相乘,确实得到 \(I\)。
除以行列式,是在抵消 \(A\) 对面积的缩放(1.5 节)。\(\det A \to 0\) 时分母趋于零,\(A^{-1}\) 的元素爆炸:这正是 FIG 2 里“逆有多大”条变红的原因。\(\det A = 0\) 时没有逆。
乘积的逆:先穿袜子,后穿鞋
\(AB\) 的意思是“先 \(B\) 后 \(A\)”(1.4 节)。撤销一串动作,要倒着撤:先脱鞋(撤销 \(A\)),再脱袜子(撤销 \(B\)):
验证:\((AB)(B^{-1}A^{-1}) = A(BB^{-1})A^{-1} = AA^{-1} = I\)。数值例子:\(A = \begin{bmatrix}1&1\\0&1\end{bmatrix}\),\(B = \begin{bmatrix}2&0\\0&1\end{bmatrix}\),则 \(AB = \begin{bmatrix}2&1\\0&1\end{bmatrix}\),\((AB)^{-1} = \begin{bmatrix}0.5&-0.5\\0&1\end{bmatrix}\),恰好等于 \(B^{-1}A^{-1}\),而 \(A^{-1}B^{-1} = \begin{bmatrix}0.5&-1\\0&1\end{bmatrix}\) 不对。
列空间与秩
\(A\mathbf x\) 是 \(A\) 各列的线性组合,系数是 \(\mathbf x\) 的各个分量(1.3 节的列视角)。所以所有能够作为输出的向量,恰好是各列的张成(1.2 节)。这个集合叫 \(A\) 的列空间:
它的维数叫秩(rank):\(\operatorname{rank}A = \dim C(A)\),也就是线性无关的列的个数。一个 \(2\times2\) 矩阵的秩是 2(列空间是整个平面)、1(一条线)或 0(只有原点)。同一个矩阵,线性无关的行也同样多(这是个定理,证明见 Strang)。
零空间与秩–零化度定理
被 \(A\) 压成零向量的所有输入,叫 \(A\) 的零空间:
它总是包含 \(\mathbf 0\),而且是子空间:若 \(A\mathbf u = A\mathbf w = \mathbf 0\),则 \(A(\mathbf u + s\mathbf w) = \mathbf 0\)。它的维数叫零化度(nullity)。例如 \(A = \begin{bmatrix}1&2\\2&4\end{bmatrix}\):第二列是第一列的 2 倍,列空间是 \((1,2)\) 方向的直线;\(A\mathbf x = \mathbf 0\) 等价于 \(x + 2y = 0\),零空间是 \((-2, 1)\) 方向的直线。
每个输入方向,要么“活下来”(贡献一维列空间),要么“被压掉”(贡献一维零空间),没有第三种命运。这就是秩–零化度定理:对有 \(n\) 列的矩阵,
FIG 5 里 \(n = 3\):秩 3 → 零化度 0;秩 2 → 1;秩 1 → 2;秩 0 → 3。
\(A\mathbf x = \mathbf b\) 的解集
有没有解:当且仅当 \(\mathbf b \in C(A)\)。有几个解:只要有一个特解 \(\mathbf x_p\)(\(A\mathbf x_p = \mathbf b\)),再加上零空间里任意向量 \(\mathbf n\),\(A(\mathbf x_p + \mathbf n) = \mathbf b + \mathbf 0 = \mathbf b\) 仍然成立。反过来,两个解的差 \(\mathbf x - \mathbf x_p\) 被 \(A\) 送到 \(\mathbf 0\),所以落在零空间里。因此解集就是零空间平移到 \(\mathbf x_p\),维数等于零化度:零空间只有 \(\{\mathbf 0\}\) 时解唯一,否则无穷多。例:\(A = \begin{bmatrix}1&2\\2&4\end{bmatrix}\),\(\mathbf b = (3, 6)\)。\(\mathbf x_p = (3, 0)\) 是一个特解,通解是 \((3,0) + t(-2, 1)\);取 \(t = 1\) 得 \((1,1)\),确有 \(A(1,1) = (3,6)\)。而 \(\mathbf b = (3,5)\) 不是 \((1,2)\) 的倍数,无解。
方阵:五句话说的是同一件事
对 \(n\times n\) 方阵 \(A\),下面几条互相等价:
几何读法:没有方向被压掉(零空间只有 \(\mathbf 0\)),所以也没有输出够不到(列空间是全空间),所以每个 \(\mathbf b\) 恰好有一个解 \(\mathbf x = A^{-1}\mathbf b\)。“压扁”这件事在 \(\det A = 0\) 时发生,它同时意味着零空间变大、列空间变小。对非方阵(\(m \ne n\))没有逆,\(m < n\) 时必有非零的零空间,\(m > n\) 时一般有够不到的 \(\mathbf b\),处理办法见 1.13 节。
教科书里 \(\mathbf x = A^{-1}\mathbf b\) 很漂亮,代码里很少这么写。库函数(np.linalg.solve、Eigen 的 A.lu().solve(b))先把 \(A\) 做 LU 分解(高斯消元的矩阵形式),再回代,既快又准。秩也不是靠行列式判断的:np.linalg.matrix_rank 会计算奇异值(1.12 节),把小于阈值的当作零。
7机器人中的它:手不动,肘在动
考虑一个平面三连杆机械臂:3 个关节 \(\mathbf q = (q_1,q_2,q_3)\),而手的位置只有 2 个坐标 \(\mathbf x = (x, y)\)。手速和关节速度之间是一个 \(2\times3\) 的雅可比矩阵:\(\dot{\mathbf x} = J(\mathbf q)\,\dot{\mathbf q}\)(3.3 节)。第 \(i\) 列是“只转第 \(i\) 个关节时手怎么动”:手相对于关节 \(i\) 的位置向量逆时针转 90°,即 \((-(y_h - y_i),\, x_h - x_i)\)。
\(J\) 有 3 列、2 行,秩至多是 2。由秩–零化度定理,零空间至少是 \(3 - 2 = 1\) 维:存在一个关节速度方向 \(\mathbf n\),使 \(J\mathbf n = \mathbf 0\)。沿着它转动关节,手一动也不动,但手肘和手腕都在动。这个方向可以直接算出来:\(J\) 的两行都是 \(\mathbb R^3\) 里的向量,\(\mathbf n\) 与两行都垂直,所以 \(\mathbf n\) 平行于两行的叉积(1.8 节)。
下面是这个想法的完整演示。拖动黄色的手,机械臂用阻尼伪逆迭代自己找关节角(伪逆见 1.13 节,这里是页内自带的简单实现)。拖动手肘(空心圆圈)或下方的“自运动”滑块,关节沿着零空间方向 \(\mathbf n(\mathbf q)\) 积分:\(\dot{\mathbf q} = \alpha\,\mathbf n(\mathbf q)\)。注意积分只在一阶意义上保持手不动,所以每一步都要小步前进、重新归一化,再用牛顿修正把手拉回原位。紫色小箭头是 \(\mathbf n\) 引起的各关节点的速度:手上的那个是零。
- 挑战:手保持在紫色任务点上,把手肘摆到连线的另一侧,整个过程不碰红色障碍物。提示:自运动有两个方向,其中一个会撞上去。一旦碰到,点“重置”重来。
Franka Panda、KUKA iiwa 这类 7 关节机械臂,手的位姿是 6 维(3 个位置加 3 个姿态),\(J\) 是 \(6\times7\),一般姿态下秩为 6,零空间正好 1 维:手肘可以绕着“肩–腕连线”转一圈,手完全不动。控制器常写成 \(\dot{\mathbf q} = J^{+}\dot{\mathbf x} + (I - J^{+}J)\,\mathbf z\):第一项完成手的任务,第二项把任意想要的关节运动 \(\mathbf z\)(离关节限位远一点、离障碍物远一点)投影进零空间,保证不影响手。伪逆 \(J^{+}\) 在 1.13 节展开。
8常见误区
先显式求逆再乘,比直接解方程慢,数值上也更不准,还会白白算出你根本不需要的整个矩阵。写 np.linalg.solve(A, b)。只有当你真的需要 \(A^{-1}\) 本身(比如要它的元素)时才去求逆。
几乎奇异的矩阵会把噪声放大。取 \(A = \begin{bmatrix}1&2\\0.5&1.1\end{bmatrix}\),\(\det A = 0.1\),\(A^{-1} = \begin{bmatrix}11&-20\\-5&10\end{bmatrix}\)。若 \(\mathbf b = (3, 1.6)\),解是 \((1, 1)\);传感器只让 \(b_2\) 变了 0.01,变成 \(\mathbf b = (3, 1.61)\),解就变成 \((0.8, 1.1)\)。输入误差 0.01,输出误差 0.22:约 20 倍。放大倍数由条件数决定(1.12 节),而不是行列式本身的大小:1.5 节说过,\(0.1\,I\) 的行列式也很小,却一点也不病态。这里各元素都是 1 左右的量级,行列式小才恰好意味着接近奇异。
\(2\times3\) 的雅可比没有逆:列比行多,必有零空间,不可能“一一对应”。需要的是伪逆(最小范数解或最小二乘解),见 1.13 节。
错,顺序要反过来:\((AB)^{-1} = B^{-1}A^{-1}\)。穿袜子再穿鞋,脱的时候必须先脱鞋。上一节的数值例子里,\(A^{-1}B^{-1}\) 和正确答案差一个元素。机器人里常见的情形:\(({}^{A}T_{B}\,{}^{B}T_{C})^{-1} = ({}^{B}T_{C})^{-1}({}^{A}T_{B})^{-1}\)。
数学上秩 1 的矩阵,经过浮点运算常常变成“秩 2,但第二个奇异值是 \(10^{-17}\)”。比如 0.1*3 - 0.3 的结果是 \(5.55\times10^{-17}\),不是 0。所以“\(\det = 0\)”这种判断在代码里几乎永远不成立;要看奇异值(1.12 节),并和一个相对阈值比较。
9小练习
10延伸阅读
- 3Blue1Brown, Essence of Linear Algebra — 第 7 章(逆矩阵、列空间与零空间)
- G. Strang, Introduction to Linear Algebra, Ch. 3 — 向量空间与子空间(列空间、零空间、秩与解 Ax = b);逆矩阵见 §2.5
- K. Lynch & F. Park, Modern Robotics, §6.2–6.3 — 数值逆运动学与冗余机械臂的速度求解
- B. Siciliano, L. Sciavicco, L. Villani, G. Oriolo, Robotics: Modelling, Planning and Control, Ch. 3 — 微分运动学,其中讲冗余分析与零空间投影(约 §3.4–3.5)