Part I · 第 1 章 线性代数 · 1.5

行列式

矩阵可以把平面拉伸、剪切、旋转,但有一件事对所有形状都一样:面积被放大了同一个倍数。这个倍数就是行列式。它为正,空间保持朝向;为负,空间被翻了面;为零,空间被压扁,再也回不来。

约 25 分钟 前置:1.3 矩阵即变换 · 1.4 矩阵乘法 8 个交互

    1为什么机器人需要它

    行列式只是一个数,却能一眼看出一个矩阵"好不好用"。机器人里有三个场合天天碰到它。

    • 奇异位形。机械臂的雅可比矩阵 \(J\) 把关节速度变成手端速度。一旦 \(\det J = 0\),手端就丢了一个运动方向:不管关节怎么转,手都不能往那个方向动。手臂完全伸直就是典型例子(本课第 8 节会亲手试;3.3、3.4 节会深入)。
    • 手性(handedness)。你用标定数据拟合出一个"旋转矩阵",或者从文件里读到一个"旋转",它的行列式却是 \(-1\)。那不是旋转,而是带镜像的变换。机器人会很听话地伸向目标的镜像位置,左手变右手,而且没有任何报错。这是机器人代码里的经典 bug。
    • 概率密度的变换。变量经过线性(或局部线性)变换后,概率密度要除以 \(|\det|\):同样多的概率被摊到了面积放大后的区域上。粒子滤波、扩展卡尔曼滤波和之后的归一化流(normalizing flow)都离不开它。

    2直觉:同一个面积倍数

    回到 1.3 节的实验室。\(\ihat\) 被送到第一列,\(\jhat\) 被送到第二列,面积为 1 的单位正方形变成了一个平行四边形。这个平行四边形的面积,就是本课的主角。

    但这只是一个正方形。换成一个圆、一个三角形、一个机器人的轮廓,会怎样?想一想:把任何形状切成很多很多小方格。线性变换把网格变成平行、等距的平行四边形网格,每一个小方格都变成同样大小的平行四边形。所以每个小格子的面积都乘以同一个数,加起来,整块区域的面积也乘以这个数。

    这个数叫行列式,记作 \(\det A\)。它还带一个符号:如果变换把平面"翻了面"(像照镜子,\(\ihat\) 转到了 \(\jhat\) 的顺时针一侧),我们就记为负数。

    FIG 1三个形状,同一个倍数
    淡色虚线是变换前,实色是变换后。右侧列出每个形状变换前后的面积(带符号)和它们的比值:方形、圆、三角形长得完全不同,比值却一模一样,都等于 \(\det A\)。选"翻面",面积变成负数;选"压扁",所有形状的面积都变成 0。
    核心洞见

    行列式是矩阵作用下面积(三维里是体积)的缩放倍数,对所有形状相同。\(|\det A| > 1\) 放大,\(|\det A| < 1\) 缩小,\(\det A < 0\) 表示空间被翻了面,\(\det A = 0\) 表示空间被压到更低的维度(一条线,甚至一个点)。

    3动手玩:行列式实验室

    拖动红色 Aî 和绿色 Aĵ 的箭头尖,或者直接改矩阵里的数,或者点一个预设。图里有三样东西:单位正方形(它的像是平行四边形)、一块不规则的"轮廓",以及一个不对称的字母 F。虚线是变换前,实色是变换后。小弧线从 Aî 转向 Aĵ:逆时针说明朝向保持,顺时针说明被翻了面,这时平行四边形变紫,F 变成镜像。

    FIG 2行列式实验室
    矩阵 A(拖动或输入)
    预设
    淡色网格是变换后的坐标网格:每个小格子的面积都是 \(|\det A|\)。右侧读数里,单位正方形和"轮廓"变换前后的面积比是同一个数,且带符号,等于 \(\det A\)。紫色表示 \(\det A < 0\),青色表示 \(\det A > 0\),红色表示接近 0(平面被压扁)。
    试一试
    • 让 \(\det A = 2\)(误差 ±0.05)。不止一种做法,试试看能找到几种。
    • 做出一个保持面积(\(\det A = 1\))但形状变了的矩阵,而且它不是旋转。提示:剪切。
    • 找一个非零矩阵,让 \(\det A = 0\)。单位正方形变成了什么?
    • 让平面翻面(\(\det A < 0\)),但不要用纯镜像(对角线上只有 ±1 的那种)。提示:把 Aî 和 Aĵ 互换位置,看看会怎样。

    小游戏:估一估面积

    下面随机给一个矩阵,单位正方形被变成了平行四边形。不要算,凭眼睛估计它的 \(\det\):数一数平行四边形盖住了几个原来的方格(每格面积 1),注意颜色和 F 的方向(紫色表示负)。用滑块给出你的猜测,点"检查"。误差在 10% 以内算猜中。

    FIG 3估一估面积
    虚线是单位正方形,实色是它的像。背景里的方格是原来的单位网格,每格面积为 1:平行四边形盖住了大约几格?这个数就是 \(|\det|\),符号看颜色和 F。青色的斜网格是变换后的格子,平行四边形本身正好是其中一格。想让游戏变简单,可以点"显示矩阵",直接用 \(ad - bc\) 算,但那样练不到眼力。
    • 累计猜中 3 次(误差在 10% 以内)。

    4第二视角:\(ad - bc\) 从哪里来

    二阶行列式的公式 \(\det\begin{bmatrix}a&b\\c&d\end{bmatrix} = ad - bc\) 看起来像是凭空冒出来的。其实它就是一幅小图。平行四边形的两条边是 \((a, c)\) 和 \((b, d)\):先用一个长方形把它框住,再把四周多出来的角减掉,剩下的就是它。

    按"下一步",一步步看。(图里取 \(a,b,c,d\) 全为正、\(\det > 0\);其他情形思路一样,只是要小心符号。)

    FIG 4框住它,再减去角落
    红色三角形的两条直角边是 \(a\) 和 \(c\),正是 Aî 的两个分量;绿色三角形的直角边是 \(b\) 和 \(d\),是 Aĵ 的分量;紫色长方形是 \(b\times c\)。拖动箭头尖换一个平行四边形,结论依然是 \(ad - bc\)(箭头被限制在四个数都为正、\(\det > 0\) 的区域内,这样图才成立)。
    • 走到最后一步,然后拖动一个箭头尖,确认剩下的面积始终等于 \(ad - bc\)。

    有符号面积:两个向量围成的平行四边形

    公式里没有绝对值,所以 \(ad - bc\) 可以是负的。把两列记作 \(\mathbf u = (a, c)\)、\(\mathbf w = (b, d)\),则 \(\det[\mathbf u\ \mathbf w] = u_x w_y - u_y w_x\) 是 \(\mathbf u\) 和 \(\mathbf w\) 围成的平行四边形的有符号面积:\(\mathbf w\) 在 \(\mathbf u\) 的逆时针一侧(左边)为正,在顺时针一侧(右边)为负,两者共线时为 0。等价地,\(\det[\mathbf u\ \mathbf w] = |\mathbf u||\mathbf w|\sin\theta\),\(\theta\) 是从 \(\mathbf u\) 转到 \(\mathbf w\) 的有向夹角。这就是二维叉积;1.8 节会用它做"左转还是右转"的判断,并推广到三维。

    FIG 5有符号面积
    拖动 u 和 w 的箭头尖。小弧线表示从 u 转向 w 的方向。把 w 拖过 u 所在的直线,符号会翻转,经过共线的瞬间面积为 0。
    • 让 u 和 w 保持足够长(都大于 0.8),但面积为 0(共线)。
    • 点"交换 u 与 w",观察符号怎么变。交换两列,行列式发生了什么?

    5第三视角:复合时面积相乘

    1.4 节说过,先做 \(B\) 再做 \(A\) 就是乘积 \(AB\)。既然每个矩阵都对所有面积乘一个固定倍数,那么两步下来,面积就连续乘了两次:\(B\) 乘以 \(\det B\),\(A\) 再乘以 \(\det A\)。所以

    $$ \det(AB) \;=\; \det A \cdot \det B. $$

    拖动阶段滑块(或点"播放"),看单位正方形先被 \(B\) 变换、再被 \(A\) 变换,面积一步步变化。可以改两个矩阵,也可以点例子。

    FIG 6先 B,后 A:面积相乘
    ① 先做 B
    ② 再做 A
    例子
    虚线紫色平行四边形是第 ① 步之后的位置,虚线方框是起点。滑块到 1 时面积等于 \(|\det B|\),到 2 时等于 \(|\det A\cdot\det B|\)。右侧最后一行同时给出直接算出的 \(\det(AB)\),两者始终一致。
    • 让 \(A\) 和 \(B\) 各自都翻面(行列式都为负),看乘积会怎样。负负得正,翻两次又翻回来了。
    • 让 \(B\) 把平面压扁(\(\det B = 0\)),而 \(A\) 的行列式的绝对值大于 0.5。后面的 \(A\) 能把它"救回来"吗?
    • 让 \(\det(AB) = 1\),同时 \(A\) 和 \(B\) 的行列式都不是 1(偏离 1 超过 0.4):一个放大,一个正好缩回去。
    两个推论

    逆矩阵:\(AA^{-1} = I\),且 \(\det I = 1\),所以 \(\det(A^{-1}) = 1/\det A\)。压扁不可逆:\(\det A = 0\) 时 \(1/\det A\) 不存在。平面被压到一条线上后,不同的点已经叠在了一起,没有任何矩阵能把它们重新分开,这是 1.6 节要讲的内容。上面的第二个任务就是这个道理:只要 \(B\) 压扁了平面,不管后面接什么,乘积的行列式永远是 0。

    6三维:体积与手性

    一切照搬到三维:\(3\times3\) 矩阵把单位立方体变成一个平行六面体(parallelepiped),它的体积就是 \(|\det A|\),三条棱是 \(A\) 的三列。符号讲的是手性:右手系的三根轴 \((\ihat, \jhat, \khat)\) 被送到 \((A\ihat, A\jhat, A\khat)\) 后,如果仍然满足右手定则(右手四指从 \(A\ihat\) 弯向 \(A\jhat\),拇指指向 \(A\khat\) 一侧),则 \(\det A > 0\);如果变成了左手系,则 \(\det A < 0\)。\(\det A = 0\) 时立方体被压成一块平板、一条线,甚至一个点。

    选一个预设或编辑矩阵,拖动画面转动视角。

    FIG 7单位立方体 → 平行六面体
    矩阵 A(3×3)
    预设
    虚线是原来的单位立方体,红、绿、蓝箭头是 \(A\ihat, A\jhat, A\khat\),也就是新坐标系的三根轴。青色表示右手系(\(\det > 0\)),紫色表示左手系(\(\det < 0\)),红色表示被压扁(\(\det \approx 0\))。体积等于三列的混合积 \(\mathbf a\cdot(\mathbf b\times\mathbf c)\),1.8 节会讲。
    • 让右手系变成左手系:右上角的标签变成"左手系"。提示:交换两列。
    • 让立方体塌成一个平面(\(\det \approx 0\),矩阵非零)。三列之间是什么关系?

    7再看数学

    提示:把鼠标悬停在公式中带底色的符号上,FIG 2 中对应的元素会被高亮。

    用三条性质定义

    行列式是方阵的一个数,把方阵看成 \(n\) 个列向量 \([\mathbf a_1\ \cdots\ \mathbf a_n]\),它由三条性质唯一确定:

    1. 单位不变:\(\det I = 1\)。单位正方形(立方体)体积为 1。
    2. 对每一列线性:把某一列放大 \(s\) 倍,行列式放大 \(s\) 倍;\(\det[\mathbf u+\mathbf u',\ \mathbf w] = \det[\mathbf u,\ \mathbf w] + \det[\mathbf u',\ \mathbf w]\)。几何上:拉长一条边,面积同比例变化。
    3. 交替:交换两列,行列式变号。于是两列相同时行列式为 0(与自己交换,结果既不变又变号,只能是 0)。结合第 2 条还能推出:把一列加上另一列的倍数(剪切)不改变行列式,因为 \(\det[\mathbf u + s\mathbf w,\ \mathbf w] = \det[\mathbf u,\ \mathbf w] + s\det[\mathbf w,\ \mathbf w] = \det[\mathbf u,\ \mathbf w]\)。

    二阶与三阶公式

    几何定义:\(S\) 取任意形状,面积比都是同一个数。二阶的具体公式是 \(ad-bc\)(第 4 节已经看到它从哪来):

    $$ \hl{det}{\det A} \;=\; \det\begin{bmatrix} \hl{a1}{\ci{\mathbf a_1}} & \hl{a2}{\cj{\mathbf a_2}} \end{bmatrix} \;=\; \frac{\hl{ratio}{\text{area}(A\,S)}}{\text{area}(S)}, \qquad \det\begin{bmatrix}\ci{a} & \cj{b}\\ \ci{c} & \cj{d}\end{bmatrix} = \ci{a}\cj{d} - \cj{b}\ci{c}. $$

    三阶可以沿第一行做余子式展开(cofactor expansion),符号按 \(+,-,+\) 交替:

    $$ \det A = a_{11}\begin{vmatrix}a_{22}&a_{23}\\a_{32}&a_{33}\end{vmatrix} - a_{12}\begin{vmatrix}a_{21}&a_{23}\\a_{31}&a_{33}\end{vmatrix} + a_{13}\begin{vmatrix}a_{21}&a_{22}\\a_{31}&a_{32}\end{vmatrix} \;=\; \mathbf a\cdot(\mathbf b\times\mathbf c). $$

    最右边是三列 \(\mathbf a, \mathbf b, \mathbf c\) 的混合积(triple product,1.8 节),它给出平行六面体的有符号体积。算一个例子:\(A = \begin{bmatrix}2&0&1\\1&3&2\\0&1&1\end{bmatrix}\),展开得 \(2(3\cdot1-2\cdot1) - 0 + 1(1\cdot1-3\cdot0) = 2 + 1 = 3\)。用混合积核对:三列是 \(\mathbf a=(2,1,0)\)、\(\mathbf b=(0,3,1)\)、\(\mathbf c=(1,2,1)\),\(\mathbf b\times\mathbf c = (1,1,-3)\),\(\mathbf a\cdot(1,1,-3) = 2+1+0 = 3\)。一致。

    常用性质

    性质几何含义
    \(\det(AB) = \det A\,\det B\)先后两次变换,面积倍数相乘(FIG 6)
    \(\det A^{\top} = \det A\)用行围成的平行四边形,面积与用列围成的相同
    \(\det(cA) = c^{n}\det A\)每个方向都放大 \(c\) 倍,\(n\) 维体积放大 \(c^n\)(二维面积放大 \(c^2\),不是 \(c\))
    \(\det A^{-1} = 1/\det A\)逆变换把面积倍数倒过来
    \(\det A = 0 \iff\) 列线性相关 \(\iff A\) 不可逆平行四边形(六面体)塌了;压扁的空间无法复原(1.6 节)
    三角矩阵:对角元之积这也是用 LU 分解算行列式的原理
    旋转 \(\det R = +1\),镜像 \(\det = -1\)旋转不改变面积和朝向;镜像不改变面积,但翻面(1.10 节)
    实际怎么算

    教科书里的余子式展开要做约 \(n!\) 次乘法,\(n=20\) 就已经不可能。数值库(NumPy、Eigen、LAPACK)先做 LU 分解 \(PA = LU\),行列式就是 \(U\) 对角线之积乘以置换的符号,代价约 \(n^3\)。矩阵稍大时行列式很容易上溢或下溢(\(100\times100\) 的 \(0.1I\) 的行列式是 \(10^{-100}\)),所以常算它的对数 np.linalg.slogdet。

    8机器人中的它:奇异位形与手性检查

    两连杆机械臂:行列式何时为零

    把雅可比 \(J\) 当成"把关节速度变成手端速度的矩阵":\(\dot{\mathbf x} = J\dot{\mathbf q}\)(它怎么来的是 3.3、3.4 节的内容)。\(J\) 的第 1 列是只转关节 1 时手端的速度,第 2 列是只转关节 2 时的速度。两个关节速度都在 \([0,1]\) 内时,手端的速度就落在 \(J\) 的两列围成的速度平行四边形里,它的面积是 \(|\det J|\)。对平面两连杆臂(杆长 \(\ell_1,\ell_2\)),

    $$ J = \begin{bmatrix} \ci{-\ell_1 s_1 - \ell_2 s_{12}} & \cj{-\ell_2 s_{12}} \\ \ci{\ell_1 c_1 + \ell_2 c_{12}} & \cj{\ell_2 c_{12}} \end{bmatrix}, \qquad \det J = \ell_1\ell_2\,\sin\theta_2 . $$

    (\(s_1=\sin\theta_1\),\(c_{12}=\cos(\theta_1+\theta_2)\),依此类推。)注意 \(\det J\) 只和肘关节角 \(\theta_2\) 有关,与肩关节角 \(\theta_1\) 无关:手臂整体转一个角度,只是把速度平行四边形整个转一下,面积不变。\(\theta_2 = 0\)(手臂完全伸直)或 \(\theta_2 = \pm\pi\)(完全折叠)时 \(\det J = 0\),两列平行,平行四边形塌成线段:手端不能沿手臂方向运动。\(\theta_2\) 的符号决定 \(\det J\) 的符号:肘朝两侧弯,是两种"手性"不同的位形。

    拖动肘部(圆圈)或手端,或者用滑块。右侧小图画出 \(\det J\) 随 \(\theta_2\) 的变化。

    FIG 8速度平行四边形与 \(\det J\)
    杆长 \(\ell_1 = 1.2\),\(\ell_2 = 1.0\)。手端处的红、绿箭头是 \(J\) 的两列(缩小到 0.6 倍),它们围成的平行四边形是"单位关节速度"能产生的手端速度范围;\(\det J > 0\) 时青色,\(< 0\) 时紫色,接近 0 时红色。右侧曲线是 \(\ell_1\ell_2\sin\theta_2\),圆点是当前位形,红点标出奇异位形 \(\theta_2 = 0\) 和 \(\theta_2 = \pm\pi\)(\(-\pi\) 与 \(\pi\) 是同一个姿态)。
    • 把机械臂带到奇异位形(\(|\det J| < 0.07\))。平行四边形变成了什么?手端被"锁"住了哪个方向?
    • 让 \(\det J\) 分别取到一次明显为正、一次明显为负(绝对值大于 0.3)。你是怎么过去的?必须经过什么?
    真实系统里:手性检查

    凡是"估计出来"或"从文件里读出来"的旋转矩阵,都应该检查 assert abs(np.linalg.det(R) - 1) < 1e-6(同时 \(R^\top R = I\),1.10 节)。常见的出错来源:(1) 基于 SVD 的位姿拟合(如 Kabsch / Umeyama 算法)在点几乎共面或噪声较大时,可能返回 \(\det R = -1\) 的"最佳正交矩阵",必须修正符号:\(R = V\,\mathrm{diag}(1,1,\operatorname{sign}\det(VU^\top))\,U^\top\)(SVD 见 1.12 节);(2) 左手系与右手系之间的转换:Unity 用左手系,ROS 用右手系,从一个引擎搬位姿到另一个,要做一次镜像,漏掉就是镜像世界;(3) 图像坐标 \(y\) 轴朝下,相机内参和坐标轴的约定一旦写错一个符号,也会让整个场景左右翻转。

    9常见误区

    误区 1:行列式小,就说明矩阵"快要奇异"

    不对。\(\det(0.1\,I_3) = 0.1^3 = 0.001\),可这个矩阵是均匀缩小,处处表现良好,求逆一点问题也没有。行列式把"整体尺度"和"有多扁"混在了一起。衡量"快要奇异"要用与尺度无关的量:奇异值之比,即条件数(1.12 节)。反过来也成立:\(\operatorname{diag}(10^6, 10^{-6})\) 的行列式是 1,却极其病态。

    误区 2:\(\det(A+B) = \det A + \det B\)

    不成立。行列式对乘积友好(\(\det AB = \det A\det B\)),对和不友好。反例:\(A = I\),\(B = -I\)(二维)。\(\det A = \det B = 1\),可 \(A + B = 0\),\(\det(A+B) = 0 \ne 2\)。同理 \(\det(cA) = c^n\det A\),而不是 \(c\det A\)。

    误区 3:任何矩阵都有行列式

    只有方阵才有。\(3\times2\) 的矩阵把平面送进三维空间,\(ad-bc\) 这类公式根本写不出来,"翻面"也没有意义(在三维里平面可以随意翻转)。它的面积缩放倍数依然存在,等于 \(\sqrt{\det(A^\top A)}\)(所有奇异值之积),但永远非负。机械臂的雅可比如果不是方阵(冗余臂),\(\det J\) 没有意义,该用奇异值或 Yoshikawa 可操作度 \(\sqrt{\det(JJ^\top)}\)(1.12 节)。

    误区 4:行列式告诉你变换的"样子"

    它只告诉你面积倍数,不告诉你形状怎么变。单位矩阵、旋转、剪切 \(\begin{bmatrix}1&1\\0&1\end{bmatrix}\) 的行列式全是 1,形状却天差地别(FIG 2 的第二个任务)。要知道"拉伸了多少、朝哪个方向",要看奇异值(1.12 节)和特征值(1.11 节)。

    误区 5:用余子式展开去算大矩阵的行列式

    展开公式适合手算 \(2\times2\)、\(3\times3\)。它的运算量按 \(n!\) 增长:\(10\times10\) 要三百多万次乘法,\(20\times20\) 要 \(10^{18}\) 次以上。代码里用 LU 分解(\(n^3\)),并且尽量不要判断 "det == 0" 来决定能否求逆:浮点数里几乎永远不会恰好等于 0,该看条件数或最小奇异值。

    10小练习

    1. \(A = \begin{bmatrix}2&1\\1&3\end{bmatrix}\)。一块面积为 3 的区域经过 \(A\) 变换后,面积是多少?
    \(\det A = 2\cdot3 - 1\cdot1 = 5\),任何形状的面积都乘以 5:\(3\times5 = 15\)。(5 是倍数本身,不是新面积;21 把行列式算成了 \(2\cdot3+1\cdot1 = 7\)。)
    2. 标定程序输出 \(R = \begin{bmatrix}0&1&0\\1&0&0\\0&0&1\end{bmatrix}\),三列长度都是 1、两两垂直,但 \(\det R = -1\)。这说明什么?
    正交归一的列保证长度和夹角不变,\(|\det| = 1\);符号才决定是旋转(+1)还是带镜像(−1)。这个矩阵交换了 x 和 y,是关于平面 \(x = y\) 的镜像。绕 z 转 180° 的矩阵是 \(\operatorname{diag}(-1,-1,1)\),行列式 \(+1\)。它显然可逆(\(|\det| = 1 \ne 0\)),所以"不可逆"不对。
    3. 已知 \(\det A = 2\),\(\det B = -3\)。\(\det(A^{-1}B^2)\) 是多少?
    \(\det(A^{-1}B^2) = \det(A^{-1})\,(\det B)^2 = \tfrac12\cdot9 = 4.5\)。\(B\) 用了两次,翻面两次又翻回来,所以符号为正。
    4. \(A = 0.1\,I_3\) 的行列式是 0.001。怎样理解?
    \(\det(cA) = c^n\det A\),所以 \(0.1^3 = 0.001\) 只反映整体尺度。\(A^{-1} = 10\,I\) 很规矩,条件数(最大奇异值比最小奇异值)是 1。体积被缩小到千分之一,不是放大。判断"快要奇异"要看奇异值之比,不是行列式的大小。
    5. 两连杆臂,\(\ell_1 = 0.4\ \text{m}\),\(\ell_2 = 0.3\ \text{m}\),肘关节角 \(\theta_2 = -30°\)。\(\det J\) 是多少?
    \(\det J = \ell_1\ell_2\sin\theta_2 = 0.4\times0.3\times\sin(-30°) = 0.12\times(-0.5) = -0.06\)。肘朝另一侧弯,符号为负;\(-0.12\) 忘了乘 \(\sin\theta_2\);\(-0.104\) 错用了 \(\cos 30°\)。|\(\det J\)| 与 \(\theta_1\) 无关。

    11延伸阅读