1. 矩阵的"站位"决定身份:左乘右乘从来不是一回事
总有学生抱着线性代数课本跑来问我:矩阵的左乘和右乘到底有什么几何意义?为什么 AB 和 BA 不能随便交换顺序?这类问题几乎每学期都会出现,因为教材里通常只给了运算法则,没有讲清楚"位置"本身带着含义。简单说,在默认列向量的约定下,矩阵放在向量的左边,叫左乘;行向量放在矩阵的左边、矩阵在右,叫右乘。位置不同,矩阵扮演的角色就完全不同。
先说结论性的框架:左乘时,矩阵是一个"空间变换器",它把一个向量当作空间里的点或箭头,整体搬动到新的位置;右乘时,行向量更像一台"测量仪",矩阵的行是一组测量设备,右乘的结果是给这些设备做加权组合,得到一台新的测量仪。一个是改变对象,一个是改变看对象的方式。这两者互为对偶,但经常被混为一谈,后面所有内容都是围绕这个框架展开的。
为了让你对"两者真的不一样"有体感,用一个具体矩阵反复对照:
A = [1 2] [3 4]系数向量取 u = (2, 1)。先左乘:
Au = [1 2] [2] = [1×2 + 2×1] = [ 4] [3 4] [1] [3×2 + 4×1] [10]再看右乘,此时 u 要写成行向量:
uA = [2 1] [1 2] = [2×1 + 1×3 2×2 + 1×4] = [5 8] [3 4]同一个 u、同一个 A,左乘得到 (4, 10),右乘得到 (5, 8)。可见左乘和右乘不是同一种操作的两种写法,而是两种本质不同的操作。
| 操作 | 写法 | 向量是什么 | 矩阵的角色 | 结果的几何含义 |
|---|---|---|---|---|
| 左乘 | Ax | 列向量,空间里的点或箭头 | 变换器 | 把点搬到新位置 |
| 右乘 | xA | 行向量,线性函数/测量仪 | 被组合的对象 | 组合出行空间里的新函数 |
1.1 两种约定:列向量和行向量看到的矩阵完全不同
线性代数教材默认向量是列向量,矩阵在左边,于是 Ax 成了最常见的形式。但在不少工程领域,比如某些图形学库和概率论教材,习惯把向量写成行向量,这时候矩阵在右边,写成 xA。同一个数学对象,换了站位之后,公式里的乘法顺序会整体倒过来。
这不是排版偏好问题。列向量约定下,矩阵 A 的第 j 列就是标准基向量 eⱼ 经过变换后的像;行向量约定下,矩阵 A 的第 i 行才是基础测量单元。你选择站在哪一边,就决定了你看到的是"列的故事"还是"行的故事"。
很多人学完线性代数只记住了"怎么算",却从没问过"这一行一列乘出来到底在图什么"。等到了实际项目里,碰到法向量变换、相似变换、马尔可夫链的转移矩阵、图形学的投影矩阵,才被左乘右乘的坑反复绊倒。这篇文章就是想把这些坑一次性填平。
1.2 一个数字例子:同样的矩阵,左乘右乘得到不同结果
回到刚才的 A 和 u。Au = (4, 10) 还能换一种方式看:矩阵 A 的两列分别是 a₁ = (1, 3) 和 a₂ = (2, 4),那么
Au = 2 × (1, 3) + 1 × (2, 4) = (2, 6) + (2, 4) = (4, 10)也就是说,Au 是对矩阵 A 的列做线性组合,组合系数正好是 u 的分量。而 uA = (5, 8) 是对 A 的行做线性组合:
uA = 2 × (1, 2) + 1 × (3, 4) = (2, 4) + (3, 4) = (5, 8)一个用的是列,一个用的是行。这就是后面所有几何意义的计算根源。接下来分别把这两条路线展开。
2. 左乘 Ax 的几何意义:矩阵的列就是掰弯后的基向量
2.1 Ax 的本质:对矩阵的列做线性组合
把 A 按列分块,写成 A = [a₁ a₂ ... aₙ],其中 aⱼ 是第 j 列。那么对任意列向量 x = (x₁, x₂, ..., xₙ)ᵀ,有:
Ax = x₁·a₁ + x₂·a₂ + ... + xₙ·aₙ这个公式看着简单,却是左乘的全部几何奥秘:矩阵的每一列,是标准基向量 eⱼ 被变换后的落点。因为 e₁ = (1, 0, ..., 0)ᵀ 乘进去,取出来正好是 a₁;e₂ 取出来是 a₂,依此类推。矩阵 A 完全由它把基向量变成什么决定。
举个例子。A = [[2, 1], [1, 3]],它的第一列是 (2, 1),第二列是 (1, 3)。也就是说,在 A 的作用下,原来 x 轴方向的单位向量 (1, 0) 被搬到了 (2, 1),原来 y 轴方向的单位向量 (0, 1) 被搬到了 (1, 3)。现在取 x = (1, 2)ᵀ:
Ax = [2 1] [1] = [2×1 + 1×2] = [4] [1 3] [2] [1×1 + 3×2] [7]几何上,x 本来表示"沿 x 轴走 1 格、沿 y 轴走 2 格"。经过 A 之后,坐标系本身被掰弯了:现在要沿新 x 轴方向 (2, 1) 走 1 格,再沿新 y 轴方向 (1, 3) 走 2 格。最终落点 (4, 7) 是这两段"新路程"的向量和。换句话说,左乘就是在告诉你:在 A 定义的扭曲坐标系里,同样的坐标分量对应原空间里的哪个点。
这里还有一个附带效果:矩阵的行列式 det A 告诉你这个变换对面积的缩放倍数。A 的行列式是 2×3 − 1×1 = 5,所以单位正方形经过 A 后会变成面积 5 的平行四边形,方向没反转。如果 det A 是负数,说明变换把空间"翻了个面",左右手坐标系互换了。
2.2 旋转矩阵为什么天然适合用左乘理解
旋转是理解左乘最直观的场景。在二维平面里,逆时针旋转 θ 角的矩阵是:
R(θ) = [cos θ −sin θ] [sin θ cos θ]为什么要长这样?就是因为它的两列分别是 e₁ 和 e₂ 旋转后的位置。e₁ = (1, 0) 旋转 θ 后变成 (cos θ, sin θ);e₂ = (0, 1) 旋转 θ 后变成 (−sin θ, cos θ)。矩阵的写法完全是由"基向量被搬到哪"决定的,这就是左乘视角最标准的体现。
取 θ = 90°,R(90°) = [[0, −1], [1, 0]]。用 x = (1, 1)ᵀ 左乘:
R x = [0 −1] [1] = [−1] [1 0] [1] [ 1](1, 1) 这个点绕原点逆时针转 90°,确实落在 (−1, 1)。整个变换可以想象成把整个坐标网格一起拧了 90°,所有点跟着网格走。矩阵的每一列,恰好是原来网格的两个轴方向在新网格里的样子。理解了这一步,你就不会再觉得矩阵乘法是"一行乘一列的机械操作"了。
2.3 复合变换的先来后到:右边那个矩阵先动手
左乘的意义一旦建立,复合变换的顺序就顺理成章了。对 ABx,因为矩阵乘法满足结合律,(AB)x = A(Bx)。所以向量 x 先被 B 变换,再被 A 变换。换句话说:在一串矩阵乘法的右边,永远站着最先动手的那个变换。
这点经常被反直觉。看到 M = A·B·C,很多初学者以为从左往右执行,先 A 再 B 再 C。实际上对列向量 v 来说,执行顺序是 C 先、B 其次、A 最后。可以把这串乘法想象成工厂流水线:原料 v 先进 C 车间,再进 B 车间,最后进 A 车间,产品才是 Mv。
为什么结合律能保证这件事?因为 A(Bx) 明确告诉你:先算括号里的 Bx,也就是先让 B 作用在 x 上,再让 A 作用在结果上。一旦你接受"最右边的先动手"这个习惯,后面图形学、机器人学里那些复杂的变换链就不会读错了。
3. 右乘 xA 的几何意义:行向量是一台测量仪
3.1 行向量代表一个线性函数,而不是一个点
要理解右乘,得先换一个看向量的方式。列向量是空间里的点或箭头,这个大家都熟。行向量 wᵀ 呢?它可以看成一个线性函数 f_w(v) = w·v,输入一个列向量 v,输出一个数——也就是点积。
这个函数有直观的几何图像。在二维平面上,方程 w·v = c 表示一条直线,这条直线的法向量就是 w。改变 c,得到一簇互相平行的直线。所以一个行向量并不指向某个点,它定义的是"一簇等值线"的朝向和疏密。比如 w = (1, 2),那么 w·v = x + 2y = c 画出来是一组斜率为 −1/2 的平行线,间距由 w 的长度决定。
这种"测量仪"的视角在生活里到处都是。地图上的等高线是高度测量仪;天气预报里的气压线是气压测量仪;神经网络最后一层的权重向量,则是对输入特征做某种综合打分的测量仪。行向量就是这些测量仪的数学抽象。
3.2 xA 是在对矩阵的行做加权求和
现在看右乘 xA。设 A 的行向量分别是 r₁, r₂, ..., rₙ,那么:
xA = x₁·r₁ + x₂·r₂ + ... + xₙ·rₙ还是用前面的例子。A = [[1, 2], [3, 4]],两行分别是 r₁ = (1, 2),r₂ = (3, 4)。取 x = (2, 1):
xA = 2 × (1, 2) + 1 × (3, 4) = (2, 4) + (3, 4) = (5, 8)几何上,这不是在搬动一个点,而是在混合两台测量仪:一台读数规则是 (1, 2),另一台是 (3, 4)。现在按 2:1 的权重把它们组合起来,得到一台新的测量仪 (5, 8)。新测量仪在任意方向 v 上测到的读数,恰好等于原来两台测量仪读数的加权和。
右乘还有一层点积视角。xA 的第 j 个分量,等于 x 和 A 的第 j 列做点积。比如上面 (5, 8) 的第 1 个分量 5 = x·(1, 3) = 2×1 + 1×3,第 2 个分量 8 = x·(2, 4) = 2×2 + 1×4。所以 xA 的每一个输出,都是 x 这台测量仪依次去测 A 的每一列,把读数排成一行。右边乘法的过程,就是"用行向量逐个测试矩阵列向量"的过程。
3.3 法向量必须用 M⁻ᵀ 变换:右乘思想在图形学里的铁证
行向量的右乘不是纯理论,它在图形学和物理模拟里有一个极其经典的落点:法向量变换。
三维模型表面上的一个点有一个法向量 n,它垂直于该点的切向量 t,也就是 n·t = 0。现在对整个模型施加一个线性变换 M,顶点位置变成 p' = M p,切向量自然变成 t' = M t。问题来了:法向量是不是也跟着 M 变?直觉上很多人觉得是,实际上不是。
要求变换后的法向量 n' 仍然垂直于变换后的切向量 t',也就是对任意切向量 t 满足 n'ᵀ(M t) = 0。整理一下,需要 n'ᵀ M 和 nᵀ 的作用效果一致,于是:
n'ᵀ = nᵀ M⁻¹等价写成列向量形式:
n' = M⁻ᵀ n也就是说,法向量作为行向量,是被 M⁻¹ 从右乘的,而不是像顶点那样被 M 左乘。这就是右乘在三维空间里的几何意义:切线方向属于"列向量空间",法线方向属于"行向量空间"(对偶空间),两者在变换下遵循完全不同的规则。
用一个简单的二维例子验证。设 M = [[2, 0], [0, 1]],这是把 x 方向拉伸两倍。考虑直线 y = x,它的切向量是 t = (1, 1),法向量是 n = (1, −1)。M 作用后,直线变成 y = x/2,新法向量应该指向 (1/2, −1) 的方向。按公式算:M⁻¹ = [[1/2, 0], [0, 1]],它的转置还是自己,所以 n' = (1/2, −1),完全正确。如果错误地把法向量当顶点一样左乘 M,就会得到 (2, −1),对应的是 y = 2x 的法线方向,明显错了。
这个例子说明:右乘处理的是一套和左乘平行但不同的几何世界。列向量被 M 推着走,行向量却要跟着 M⁻ᵀ 走,两台"测量仪"在变换面前的身段完全不同。
4. AB 与 BA 差在哪:组合变换的顺序不能颠倒
4.1 列视角下,AB 的每一列都被 A"接管"
矩阵乘矩阵是左乘右乘的进一步延伸。设 C = AB,把 B 按列分块:B = [b₁ b₂ ... bₚ],那么 C 的第 j 列是:
cⱼ = A·bⱼ这告诉了我们一个非常干净的结论:AB 的每一列,都是 A 作用在 B 的每一列上得到的结果。因此 AB 的列空间一定包含在 A 的列空间里。用大白话说,A 这个变换把 B 的每一列都"吸"进了自己的列空间,A 在左右乘里是主导者。
看个极端例子。A = [[1, 0], [0, 0]],它把一切向量投影到 x 轴。B = [[1, 2], [3, 4]] 的列是 (1, 3) 和 (2, 4)。那么 AB = [[1, 2], [0, 0]],两列变成 (1, 0) 和 (2, 0),全都在 x 轴上。B 原来的二维列空间,被 A 左乘后压缩成了一维。哪怕 B 里有再丰富的信息,左边站着投影矩阵 A,结果就只能留在 A 的列空间里。
这个包含关系还有个实用推论:rank(AB) ≤ rank(A)。左边矩阵的秩是一道天花板,右乘的任何矩阵都无法把这道天花板顶高。深度学习里面很多关于特征退化、秩坍缩的讨论,根子就在这条性质上。
4.2 行视角下,AB 的每一行都被 B"接管"
同样一件事,从行的方向看,结论正好对称。AB 的第 i 行等于 A 的第 i 行右乘 B:
(AB)的第i行 = (A的第i行) × B行向量右乘 B,是对 B 的行做线性组合(上一节刚讲过)。所以 AB 的每一行都落在 B 的行空间里,于是 rank(AB) ≤ rank(B)。方向非常对称:左乘管列,右乘管行。AB 的列空间被左边矩阵 A 控制,行空间被右边矩阵 B 控制。记住这句话,很多矩阵不等式和秩的结论都可以直接背出来。
把视角换到 BA,角色就互换了。BA 的每一列是 B 作用在 A 的每一列上,所以 BA 的列空间落在 B 的列空间里;BA 的每一行是 B 的行右乘 A,行空间落在 A 的行空间里。A 和 B 谁在左、谁在右,决定了谁在列方向上做主,谁在行方向上做主。
4.3 旋转配缩放:一个 2×2 反例看穿不可交换
理论说再多,不如一个具体反例直观。设 R 是逆时针 90° 旋转,S 是 x 方向拉伸 2 倍:
R = [0 −1] S = [2 0] [1 0] [0 1]先算 RS:
RS = [0 −1] [2 0] = [0 −1] [1 0] [0 1] [2 0]再算 SR:
SR = [2 0] [0 −1] = [0 −2] [0 1] [1 0] [1 0]两个结果明显不一样。取标准基向量 e₁ = (1, 0) 看几何过程:
- RS 作用 e₁:先被 S 拉伸,x 方向变 2 倍,得到 (2, 0);再被 R 旋转 90°,变成 (0, 2)。
- SR 作用 e₁:先被 R 旋转 90°,变成 (0, 1);再被 S 拉伸,因为 S 只拉伸 x 方向,(0, 1) 纹丝不动,还是 (0, 1)。
同样的两个变换,顺序一换,(1, 0) 的最终落点从 (0, 2) 变成了 (0, 1),差了整整一倍。原因在于:旋转改变了"哪个方向是 x 方向",而缩放是沿着固定轴进行的。先旋转再缩放,缩放轴跟着物体一起转了;先缩放再旋转,旋转把已经拉长的形状整个拧过去。两件事在三维空间里造成的形状完全不同。
生活中的类比是穿袜子穿鞋的顺序。先穿袜子再穿鞋,和先穿鞋再穿袜子,虽然最后都"穿了袜子和鞋",但体验和结果天差地别。矩阵乘法的不可交换性和这个道理一模一样。
值得一提的细节是,det(RS) = det(SR) = 2,两个变换对面积的缩放倍数完全相同。所以 AB ≠ BA 不是体现在"总效果"上,而是体现在方向上。这也是为什么行列式可以交换、矩阵本身却不能交换,因为行列式只关心面积体积的缩放,不关心方向。
4.4 什么情况下左右乘可以交换
不是说所有矩阵都不可交换,有两类常见情形可以交换,理解它们能帮你更敏锐地判断变换结构。
第一类,两个矩阵都是对角矩阵时,显然可以交换。更一般地,如果 B 是 A 的多项式,比如 B = A²,或者 B = 2A + 3I,那么 AB = BA。几何上,这类矩阵共享同一组特征方向,每个方向只是被不同程度地缩放,谁先缩放谁后缩放自然无关紧要。
第二类,二维平面里的多个旋转矩阵。R(α)R(β) = R(β)R(α) = R(α+β),因为旋转的复合就是角度相加,加法是交换的。这里的关键是:旋转不挑方向,它把所有方向一视同仁地转过同样的角度,因此两个旋转之间没有"先来后到"的次序问题。
反过来说,一旦变换里同时存在"旋转"和"沿特定方向的缩放/剪切",顺序几乎必然影响结果。看见一个变换会改变方向、另一个会沿固定轴变形,就要警惕不可交换性。工程里判断一个变换链能不能安全重排,看的就是这一点。
5. P⁻¹AP 的秘密:相似变换里左乘右乘的分工
5.1 P 是坐标翻译官
矩阵的左乘右乘还有一个经常被误解的组合:P⁻¹AP。这个结构在相似变换、对角化、特征值计算里反复出现,但初学者往往只背公式,不理解为什么左边是 P⁻¹、右边是 P。
先给 P 一个身份:P 的每一列是新坐标系的基向量在旧坐标系下的坐标。假设我们有两套坐标系描述同一个空间,P 负责把"新坐标"翻译成"旧坐标":
v_old = P · v_new这个翻译关系是右乘:把新坐标向量放进 P 的右边,P 的列做线性组合,得到旧坐标。对应的,P⁻¹ 负责反方向翻译,把旧坐标换回新坐标。
举个例子。P = [[1, 1], [0, 1]],它的两列分别是 (1, 0) 和 (1, 1)。这是说:新坐标系的第一根基轴和旧 x 轴重合,第二根基轴指向旧坐标系里的 (1, 1) 方向。如果某个点在新坐标系里的坐标是 (u, v),那么它在旧坐标系里的坐标是 P(u, v) = (u+v, v)。沿着新坐标的 u 方向走一格,在旧坐标里既动了 x 也动了 y,这就是"坐标系换掉"带来的直观后果。
5.2 三步走:翻译进去、作用、翻译回来
现在有个旧坐标系下的变换 A,你想知道:在新坐标系下,这个变换长什么样?设新坐标系下的某个向量是 v_new,把它完整走一遍:
- 先翻译到旧坐标:v_old = P·v_new。这里 P 在右边乘 v_new,是右乘。
- 在旧坐标下施加 A:w_old = A·v_old = A·P·v_new。
- 把结果翻译回新坐标:w_new = P⁻¹·w_old = P⁻¹·A·P·v_new。
所以 A 在新坐标系下的表示就是:
B = P⁻¹·A·P为什么这个顺序不能反?根本原因在于 P 和 P⁻¹ 分工不同。P 站在右边,负责把新坐标系的"输入"翻译成旧坐标;P⁻¹ 站在左边,负责把旧坐标的"输出"翻译回新坐标。输入侧需要的是 P,输出侧需要的是 P⁻¹。翻译动作必须发生在 A 作用之前和作用之后,顺序就被锁死了。
如果写反成 P·A·P⁻¹,那是在说另一套约定:先把旧坐标翻译成新坐标,作用 A,再翻回旧坐标。这不是我们想要的"在新坐标系里看 A",而是"在旧坐标系里看一个新变换",两者通常不相等。很多对角化算错的同学,问题就出在把 P 和 P⁻¹ 的位置弄反,最后特征值对不上。
5.3 对角化的例子:P⁻¹AP 如何把矩阵变成纯缩放
用具体数字验证。设:
A = [2 1] P = [1 1] [0 3] [0 1]先算 AP,也就是把 A 的每一列和 P 的列组合:
AP = [2 1] [1 1] = [2 3] [0 3] [0 1] [0 3]再算 P⁻¹AP。P 的逆是 P⁻¹ = [[1, −1], [0, 1]]:
P⁻¹AP = [1 −1] [2 3] = [2 0] [0 1] [0 3] [0 3]结果是一个对角矩阵 diag(2, 3)。这意味着,在由 (1, 0) 和 (1, 1) 构成的坐标系下,A 的行为极其简单:沿第一根新坐标轴方向拉伸 2 倍,沿第二根新坐标轴方向拉伸 3 倍,完全不需要旋转和剪切。
原因也清楚:A 的特征向量正好是 (1, 0) 和 (1, 1)。在这两个方向上,A 只改变长度,不改变方向。P 把坐标轴转到特征向量方向,A 在"自己擅长"的方向上做纯缩放,P⁻¹ 再把结果转回来。整个过程就是:右乘 P 选好视角,A 在最佳视角下做最简单的事,左乘 P⁻¹ 回到原视角。相似变换 P⁻¹AP 保持特征值、行列式、迹不变,因为这些量是变换的内在属性,和坐标系无关;而对角化就是找到一个视角,让内在属性直接亮出来。
6. 实际工程中左右乘最容易翻车的三个现场
6.1 图形学:行主序与列主序约定直接决定乘法顺序
图形学是左右乘重灾区。同一个变换链,在 OpenGL 风格的列向量约定下写成:
v' = Proj × View × Model × v最右边的 Model 先作用在 v 上,然后依次是 View、Proj,所以读法是从右往左:先模型变换,再视图变换,再投影变换。想让物体先绕自身旋转再平移到 (5, 0),就应该把旋转矩阵放最右,写成 T(5,0) × R(θ),因为 R 先作用,物体先转再挪;如果写反成 R(θ) × T(5,0),物体先被平移,再绕原点旋转,效果变成"绕原点公转加自转",完全不是想要的结果。
但在某些行向量约定的数学库或 DirectX 风格代码里,同一个链写成:
v' = v × Model × View × Proj读法变成从左往右,模型变换在最左,先执行。同一个变换链,两种约定的矩阵乘法顺序正好完全相反。工程里最常见的 bug 就是:从一篇讲列向量约定的文章里抄来矩阵顺序,放进行向量约定的代码里,渲染结果各种错位,还找不到原因。
这里要特别提醒:存储顺序(行主序还是列主序)和数学上的"向量在左还是在右"是两件不同的事。行主序存储只影响内存布局和传参方式,并不直接决定乘法顺序;决定乘法顺序的是你采用的向量约定。很多人把这两件事混在一起,修 bug 时越改越乱。我的一般建议是:拿到一段矩阵代码,先确认它用行向量还是列向量约定,再想变换顺序,最后才谈存储布局。
6.2 数据科学里 Xw 和 wᵀX 的两种身份
在机器学习里,左乘右乘也无处不在。设 X 是 n 行 p 列的设计矩阵,每一行是一个样本,每一列是一个特征;w 是 p 维权重列向量。线性回归的预测值是:
y_pred = Xw它的第 i 个分量是样本 xᵢ 与 w 的点积。这里 X 的每一行是一台"测量仪",w 是被测量的对象,Xw 是把所有样本的测量读数排成一列。注意,这和"左乘是变换"的直观不同:X 并不是在空间里搬动 w,而是在逐行"检测" w。这个视角转换很重要,因为数据科学里矩阵往往通过行表示样本,行向量的测量仪身份比列向量的点身份更常用。
反过来,wᵀX 是一个 1×n 的行向量,它的含义是对 X 的行做加权组合:用 w 的分量把 n 个样本混合成一个新样本。PCA 里的得分向量、推荐系统里的用户表示聚合,本质上都是这种行组合操作。同样是 w 和 X,写成 Xw 是对样本逐行打分,写成 wᵀX 是对样本逐行混合,输出形状完全不同。写代码前先确认你要的是 n×1 的打分列,还是 1×n 的聚合行,能避免大量维度不匹配的报错。
这里还有一个隐藏的右乘场景:最小二乘的梯度。损失函数 ‖Xw − y‖² 对 w 求导得到 2Xᵀ(Xw − y),Xᵀ 左乘残差向量。Xᵀ 左乘的几何本质,是把残差从"样本空间"投影回"特征空间",这个过程正是行向量测量仪的组合逻辑在起作用。看懂这一层,线性代数和机器学习的接口就打通了。
6.3 马尔可夫链的行随机和列随机约定
马尔可夫链的转移矩阵也有左右乘之分,而且在不同的书里约定相反,极其容易踩坑。
列随机约定下,转移矩阵 P 的每一列之和为 1,状态分布写成列向量,一步转移是:
p_{t+1} = P · p_t平稳分布满足 P·π = π。这是把 P 当左乘变换,把分布当列向量,每一步都是矩阵在左边推着分布前进。
行随机约定下,转移矩阵的每一行之和为 1,状态分布写成行向量,一步转移是:
p_{t+1} = p_t · P平稳分布满足 π·P = π。这时分布站在 P 的左边,P 在右边乘它,是典型的右乘操作。
两种约定其实是同一个模型,写成矩阵时互为转置。但如果你读了一篇用行随机约定的论文,拿到代码里却按列随机约定写,转移方向就会完全颠倒,模拟出来的轨迹、稳态分布全部对不上。我见过不止一个做推荐系统、做 PageRank 的朋友在这个坑里耗掉好几天。解决办法很简单:拿到任意一段马尔可夫代码,先看它是把分布放在矩阵左边还是右边,再确认矩阵是行和还是列和为 1,两个信息对齐了再动逻辑。
6.4 我的调试土办法:用单位基向量当探针
最后分享一个我用了很多年的土办法,对付所有左右乘混乱的场景都有效:拿标准基向量当探针。
矩阵 A 和标准基向量 eⱼ 左乘,A·eⱼ 的结果正好是 A 的第 j 列。同理,eᵢᵀA 的结果是 A 的第 i 行。这一条规则是调试矩阵代码的利器。当你不确定一段代码里的矩阵是不是你要的变换时,不要盯着几十个浮点数看,直接把 (1, 0)、 (0, 1) 这样的基向量喂进去,看输出落在了哪里。如果预期是旋转 90° 后拉伸,e₁ 应该先到 (0, 1) 再到 (0, 2),实际输出对不上,立刻就能定位是哪一步顺序错了。
我的习惯是:先算维度,左边矩阵的列数必须等于右边矩阵的行数;再用 e₁ 和 e₂ 分别作为输入跑一次;最后用人眼检查结果的方向对不对。维度错了是低级错误,方向错了是左右乘顺序问题,这两个检查基本能排查掉九成以上的矩阵 bug。矩阵乘法的结合律一直成立,所以调试时可以放心加括号、拆开逐步验证,不用担心改变结果;不可交换的只是顺序,不是结合方式。
从最开始讲"左乘是搬运、右乘是测量",到后来用列空间、行空间、相似变换把这些串起来,我想表达的核心只有一句话:遇到任何矩阵乘法,先问自己一句——此刻谁在作用谁,哪个矩阵先动手。把这个问题想清楚,法向量为什么用逆的转置、P⁻¹AP 为什么是那个顺序、随机矩阵要不要转置,这些公式都不再需要背,而是能顺着几何逻辑推出来。这也是我在图形学和数据分析项目里,左右乘这个知识点最值回票价的地方。