首页 / 资讯中心 / 文章详情

矩阵左乘与右乘的几何意义:从线性变换到基变换

矩阵左乘与右乘的几何意义:从线性变换到基变换 ★ FEATURED ARTICLE
1. 先把矩阵看成“动作”线性变换的几何直觉很多学生第一次学矩阵乘法时最困惑的不是怎么算而是“算完之后到底发生了什么”。尤其是AB和BA明明只是调换了一下左右位置结果却经常不一样甚至形状都变了。我想说的是这个困惑很正常因为如果只看数字你很难发现规律但只要把矩阵当成一个“动作”在二维平面上一画左右乘的几何意义立刻就会清晰起来。矩阵最朴素的理解就是一台线性变换机器输入一个向量输出另一个向量。它保持原点不动、把直线变成直线、把平行线变成平行线。二维平面里最常见的线性变换有四种旋转、缩放、切变、投影。旋转矩阵让图形转一个角度缩放矩阵把某一方向的长度拉长或压扁切变矩阵把图形斜着推一下投影矩阵把整个平面压到一条直线或者一个点上。单位矩阵是什么都不做的机器零矩阵则是把所有向量都压到原点的机器。这种“机器视角”的关键在于矩阵对向量施加作用时遵循线性叠加原则。简单说如果你先给了两个输入向量各自过一遍机器再相加和先把两个输入向量相加再一起过机器结果是一样的。这就是线性代数里最核心的线性性。正因为有这个性质当我们有一大堆点要处理时不需要一个个单独看而是可以把它们拼成一个矩阵一次性“过机器”这就是后面要讲的左乘批量处理点集的基础。1.1 矩阵不是数字盒子而是一台几何机器我见过太多人把矩阵单纯看作“一堆数字的表格”然后去背乘法口诀。这样背下来你只知道怎么算不知道为什么这么算。比如二维旋转矩阵[ R(\theta) \begin{bmatrix} \cos\theta -\sin\theta \ \sin\theta \cos\theta \end{bmatrix} ]当你把向量 ((1, 0)) 左乘这个矩阵就得到 ((\cos\theta, \sin\theta))这正好是把x轴上的单位向量逆时针旋转 (\theta) 角后的结果。你把向量 ((0, 1)) 左乘它得到 ((-\sin\theta, \cos\theta))也正好是y轴单位向量旋转后的位置。所以这个矩阵的每一列其实是标准基向量经过旋转之后的“照片”。记住这个结论矩阵的列向量就是标准基向量被这个矩阵映射后的目标位置。这也是为什么矩阵乘法有“按列理解”的方法。一旦你习惯了“矩阵的列就是基向量的归宿”后面理解左乘右乘就顺了。把矩阵当数字盒子和当成几何机器学习效率完全是两回事。1.2 复合变换为什么矩阵要从右往左读假设你有一台旋转机器 (R)一台缩放机器 (S)现在你想先让向量旋转再让结果缩放。如果直接写“旋转加缩放”很多初学者会写成 (R S)但线性变换的复合用的是乘法先旋转再缩放对应的矩阵是 (S R)。注意旋转矩阵写在左边缩放矩阵写在右边。为什么因为矩阵乘法作用于向量时从右往左执行。表达式 (S R \mathbf{v}) 的意思是先把 (\mathbf{v}) 交给 (R)得到旋转后的向量再把这个结果交给 (S)。所以右边的矩阵先接触输入向量左边的矩阵后接触。复合变换的顺序和你写字从左到右的顺序正好相反。这个规律可以类比成排队右边的人先动。如果某天你看到一行矩阵连乘 (M_3 M_2 M_1)不要慌先执行的永远是 (M_1)然后才是 (M_2)最后 (M_3)。很多图形学、机器人的代码里从右往左读变换链就是这个原因。1.3 用二维平面实验旋转与缩放的非交换为什么矩阵乘法普遍不满足交换律我们用一个直观例子说明。设 (R) 是逆时针旋转90度的矩阵(S) 是把水平方向拉伸2倍的矩阵[ R \begin{bmatrix} 0 -1 \ 1 0 \end{bmatrix}, \quad S \begin{bmatrix} 2 0 \ 0 1 \end{bmatrix} ]先让向量 ((1, 0)) 做“先水平拉伸再旋转90度”。水平拉伸后变成 ((2, 0))旋转90度后变成 ((0, 2))。对应的矩阵是 (R S)。如果换过来先旋转90度再水平拉伸。((1, 0)) 旋转后变成 ((0, 1))水平拉伸对竖直方向的y坐标没有影响所以结果还是 ((0, 1))。对应的矩阵是 (S R)。同样的两个动作只是换了顺序最终一个落在 ((0, 2))一个落在 ((0, 1))。这就是矩阵乘法不交换的几何原因旋转会改变拉伸的方向拉伸也会改变旋转后向量的落点两个动作耦合在一起先后顺序没法随便换。所以我一直认为“矩阵乘法不满足交换律”这句话不该被当成抽象结论背下来而应该当成“先穿袜子再穿鞋”和“先穿鞋再穿袜子”的区别。穿对了没事顺序反了结果就非常别扭。2. 左乘和右乘的分工列向量视角与行向量视角理解了矩阵是动作、乘法顺序从右往左之后我们就可以正式回答“矩阵的左乘和右乘的几何意义”。这里有一个非常实用的观察角度矩阵乘法的左乘主要作用在列向量上矩阵乘法的右乘主要作用在行向量上。这个简单区分能解释绝大多数应用场景。左乘可以理解为一个变换矩阵作用到另一个矩阵的每一列上。比如 (A B)结果矩阵的第 (j) 列就等于 (A) 乘以 (B) 的第 (j) 列。如果 (B) 的每一列都是一个二维或三维点那么 (A B) 就是对这一组点同时施加同一个线性变换。这是图形学里最常见的“对象变换”模型。右乘的视角相对隐蔽(B A) 的结果矩阵每一列是 (B) 的各列按 (A) 的某一列系数做线性组合的结果等价地每一行是 (B) 的对应行向量被 (A) 映射后的结果。如果把 (B) 的列理解为坐标轴方向那么右乘更像是在“改变坐标系”而不是直接推动几何对象。下面我把两种视角拆开细讲。2.1 左乘对列向量逐个施加变换设 (A) 是一个 (m \times n) 矩阵(B) 是 (n \times p) 矩阵。计算 (C A B) 时(C) 的第 (j) 列可以写成[ C[:, j] A \cdot B[:, j] ]这里的冒号表示取列。这个等式说明左乘 (A) 时(A) 会依次作用到 (B) 的每一列上。如果 (B) 是多个点的坐标矩阵比如每一列存一个点的x、y坐标那么 (A B) 就是把所有点整体搬运到新位置。举个具体例子。假设平面有一个三角形三个顶点分别是 ((0,0))、((1,0))、((1,1))你把这些点按列排成[ B \begin{bmatrix} 0 1 1 \ 0 0 1 \end{bmatrix} ]用旋转矩阵 (R) 左乘 (B)得到 (R B)。因为 (R) 会分别作用到三列上所以三角形的三个顶点都被旋转了整个三角形随之旋转。这就是左乘的几何意义对象在动。更进一步矩阵 (A) 的列本身就是标准基向量被 (A) 映射后的结果。所以 (A) 左乘一个单位矩阵 (I)得到的就是 (A) 自己换句话左乘相当于把标准基下的坐标全部替换成 (A) 的各列所代表的新位置。这个理解在后续学习特征值、SVD时特别有用。2.2 右乘对行向量坐标分量重组现在看右乘。设 (D B A)其中 (B) 是 (p \times m)(A) 是 (m \times n)。结果 (D) 的每一行等于 (B) 的对应行向量乘以 (A)。如果从列的角度看(D) 的第 (j) 列等于[ D[:, j] B \cdot A[:, j] ]这个式子表明右乘矩阵 (A) 时原矩阵 (B) 的每一列不是被单独旋转或缩放而是按照 (A) 各列给出的系数重新组合。说得更直白右乘做的是“列向量的线性混合”。这个区别非常重要。假设 (B) 的两列分别是两个基向量比如 ((2,0)) 和 ((0,1))。左乘一个90度旋转矩阵 (R)会把这两个向量各自旋转基向量还是互相垂直的长度保持的向量。右乘 (R) 则不同它会产生两个新列每一列都是原来两列的混合混合系数来自 (R) 的列。如果 (R) 是旋转矩阵结果相当于把原始的坐标轴方向重新组合了一遍几何上更像是在换坐标系。所以在实际工程里如果你看到“右乘一个变换矩阵”通常意味着你在改变基、改变坐标系、改变特征空间而不是在推动一堆点。当然这个说法并不是绝对的因为行向量版本的变换也可以通过转置转换成左乘但作为直观记忆“左乘让对象动右乘让坐标系动”非常好用。2.3 关键陷阱行向量左乘需要用转置矩阵学到这里一个很常见的坑出现了。有些人把点坐标写成行向量比如 ((x, y))然后用变换矩阵 (A) 去乘就写成[ \begin{bmatrix}x y\end{bmatrix} \cdot A ]这个写法在数学上是合法的但它对应的不是“用 (A) 变换这个点”而是“用 (A^T) 变换这个点的转置版本”。因为列向量变换是[ \mathbf{v} A \mathbf{v} ]两边转置就得到[ (\mathbf{v})^T \mathbf{v}^T A^T ]也就是说若你的点以行向量存储想让每个点被 (A) 变换正确写法是 (\mathbf{v}^T A^T)不是 (\mathbf{v}^T A)。用之前的旋转矩阵验证一下。90度逆时针旋转 (R)行向量 ((1, 0)) 乘以 (R) 得到 ((0, -1))方向反了乘以 (R^T) 得到 ((0, 1))方向才对。很多三维引擎里点坐标用行向量存储时变换矩阵经常要预先转置就是这个道理。这不是矩阵左乘右乘本身变了而是行向量和列向量之间的转置关系在做怪。2.4 用表格看清三种位置的区别表达式作用对象通俗几何说法典型场景(A \mathbf{v})单个列向量对这个向量施加变换最基本的分(A B)B的每一列对一组列向量整体变换点云、顶点变换(B A)B的每一行 / 列混合改变基向量组合方式坐标系变换、基变换(A B \mathbf{x})先B后A作用x复合变换顺序机械臂、动画层级每次写代码前先问自己三个问题我的数据是行向量还是列向量我要让对象动还是要换坐标系我期望的变换顺序是从右往左写还是从左往右写想清楚这三个问题左右乘基本不会再错。3. 动手实验用NumPy看左乘右乘的几何差异光看公式还是有点干我建议你打开Python亲手画一画。下面这个实验用NumPy和Matplotlib生成一个正方形分别用两种不同的矩阵顺序去变换它看一眼图形就知道左乘和右乘差在哪里。这个过程不超过五分钟但收获比背十遍定义都大。3.1 实验设计一个正方形的两种变换顺序先定义两个基础变换90度逆时针旋转矩阵 (R)水平方向拉伸矩阵 (S)。正方形的五个顶点按列排成矩阵 (sq)每个点是一列最后一个点回到起点方便画闭合图形。代码如下import numpy as np import matplotlib.pyplot as plt theta np.pi / 2 R np.array([[np.cos(theta), -np.sin(theta)], [np.sin(theta), np.cos(theta)]]) S np.array([[2.0, 0.0], [0.0, 1.0]]) # 每个点是列向量最后一列重复第一列 sq np.array([[0, 1, 1, 0, 0], [0, 0, 1, 1, 0]])接下来我们要对比trans1 R S sq # 先水平拉伸 S再旋转 R trans2 S R sq # 先旋转 R再水平拉伸 S注意Python里是矩阵乘法最右边的矩阵先执行。所以R S sq的真实顺序是先 (S)再 (R)。S R sq的真实顺序是先 (R)再 (S)。3.2 代码实现与输出解读把三个图形画在一张图上fig, axes plt.subplots(1, 3, figsize(12, 4)) names [original, R S, S R] all_data [sq, trans1, trans2] for ax, data, name in zip(axes, all_data, names): ax.plot(data[0, :], data[1, :], markero) ax.set_title(name) ax.set_aspect(equal) ax.grid(True) plt.show()打印一下变换后的坐标print(trans1:\n, trans1) print(trans2:\n, trans2)R S先拉伸后旋转正方形的边长从水平方向被拉长然后整个形状被旋转90度所以最终是一个竖着的矩形。S R先旋转后拉伸正方形先转90度边长没有变化再水平拉伸所以最终是一个横着的矩形。方向完全不一样。这个实验直接展现了矩阵乘法非交换的几何本质交换左乘和右乘等于交换两个动作的先后顺序。对新手来说画一次图比盯着公式想半天有用得多。我建议你把角度从90度改成30度、45度再试试斜向矩形会看得更清楚。3.3 右乘一个旋转变换坐标轴旋转还是图形旋转现在我们把问题再推进一步不左乘旋转矩阵而是右乘旋转矩阵结果会怎样为了能观察到列的组合我们用一个非单位矩阵 (B) 当“基向量集合”[ B \begin{bmatrix} 2 0 \ 0 1 \end{bmatrix} ]分别计算 (R B) 和 (B R)。(R B) 的意思是把 (B) 的两列 ((2,0)) 和 ((0,1)) 分别旋转90度得到 ((0,2)) 和 ((-1,0))。图形的两个“方向箭头”都被旋转了但箭头之间的相对关系保持不变这是“对象整体旋转”。(B R) 呢它的第一列是 (B) 的两列按旋转矩阵第一列的系数组合第二列是按旋转矩阵第二列的系数组合。计算出来是[ B R \begin{bmatrix} 0 -2 \ 1 0 \end{bmatrix} ]第一列变成 ((0,1))第二列变成 ((-2,0))。看起来好像还是旋转后的方向但仔细看原来的x轴方向 ((2,0)) 并没有被单独旋转到 ((0,2))而是被重新分配到了两个新列里。这种效果更像是“坐标系整体换了一套基”而不是“基向量各自转”。所以当你看到右乘一个变换矩阵时心里要自动翻译成“原来的向量集合正在被变换矩阵的各个列线性混合。” 这在信号处理、数据降维里非常常见你有一组特征向量右乘一个正交矩阵得到的是一组新的正交基而不是简单地把每个特征向量转一下。3.4 实操心得什么时候用左乘、右乘做实际项目时我一般按下面几个场景来选如果你有一堆顶点、点云、向量想让它们在世界坐标系里被同一个变换作用用左乘。列向量存点直接 (M P)行向量存点先转置一下用 (P M^T)。如果你在做基变换、坐标系变换比如把某个向量从局部坐标系变换到世界坐标系通常要把基向量按列排成矩阵 (P)然后右乘一个坐标变换矩阵或者用 (P^{-1} M P) 这种相似变换形式。如果你在搭复合变换比如机器人的关节链条记住“先进行的操作写在右边后进行的操作写在左边”。从右往左读代码里的矩阵链你就知道每个组件到底先做了什么。有一次我帮人调试图形程序发现物体旋转方向总是反的。查了半天问题出在他把顶点坐标存成了行向量却用左乘的方式写了变换矩阵。改正成右乘转置矩阵后立刻正常。这种问题在实际开发里非常典型提前养成“先判断行列向量”的习惯能省很多时间。4. 更深一层基变换与相似变换中的左右乘如果你只是想应付考试前面两节已经够用了。但如果想真正把左乘右乘用起来尤其是接触到特征值、主成分分析、振动分析这些内容时还需要理解一个更完整的图景同一个线性变换在不同基底下表示成不同的矩阵。这个过程里左乘和右乘会同时出现。我经常举一个例子你站在一个房间里看到墙上有一个影子影子确实存在但你换个角度去看影子的形状就变了。线性变换 (A) 就是那个“影子本体”不管你在哪个坐标系下描述它它本身不会变。可你观察用的坐标系一变描述它的矩阵就会变成另一个样子。这个“换成另一个矩阵”的操作就是相似变换。4.1 基变换矩阵与坐标向量设有一组新基它的各个基向量在旧坐标系下的坐标按列拼成一个矩阵 (P)。例如新基是把旧基旋转45度得到的那么 (P) 就是旋转45度的矩阵。如果某个向量在新基下的坐标是 (\mathbf{v})那么它在旧基下的坐标是[ \mathbf{x} P \mathbf{v} ]这里 (P) 右乘坐标向量 (\mathbf{v})意味着什么它把“新基下的读数”翻译成“旧基下的实际位置”。所以右乘 (P) 在基变换中扮演的角色是从新坐标到旧坐标的翻译官。反过来如果你知道一个向量在旧基下的坐标 (\mathbf{x})想求它在刚建立的新基下的坐标就要用[ \mathbf{v} P^{-1} \mathbf{x} ]这里 (P^{-1}) 左乘旧坐标把数据从旧坐标系翻译回新坐标系。一个右乘负责“进入”一个左乘负责“离开”基变换中的左右位置一下子就不神秘了。4.2 (P^{-1} A P) 的几何故事现在假设在旧基下有一个线性变换用矩阵 (A) 表示。如果我想知道同一个变换在新基下长什么样不能直接写 (A)也不能只乘一个 (P)。你需要完整走一遍流程新基下的坐标 (\mathbf{v})先右乘 (P)换算成旧基下的实际位置 (\mathbf{x})在旧基下做变换(\mathbf{y} A \mathbf{x})再把变换结果 (\mathbf{y}) 左乘 (P^{-1})换算回新基坐标。合并起来就是[ \mathbf{w} P^{-1} A P \mathbf{v} ]这个 (P^{-1} A P) 就是 (A) 在新基下的表示。注意左右乘的分工右边的 (P) 是“输入翻译”左边的 (P^{-1}) 是“输出翻译”。两个翻译夹着中间那个真正干活的 (A)。很多教材直接给这个公式却不解释为什么右边是 (P) 而不是 (P^{-1})。你只要记住那个三步流程就不会记反先右乘进入旧世界在旧世界发作再左乘回到新世界。这是我在实际教学中发现最有效的记忆方式。4.3 具体例子旋转拉伸在不同基下的表现拿前面用过的水平拉伸矩阵 (A \mathrm{diag}(2, 1)) 举例旧基就是标准基。现在把坐标系整体旋转45度新基矩阵 (P) 为[ P \begin{bmatrix} \cos 45^\circ -\sin 45^\circ \ \sin 45^\circ \cos 45^\circ \end{bmatrix} ]因为旋转矩阵是正交矩阵(P^{-1} P^T)。于是新基下的变换矩阵是[ P^{-1} A P P^T \begin{bmatrix} 2 0 \ 0 1 \end{bmatrix} P \begin{bmatrix} 1.5 -0.5 \ -0.5 1.5 \end{bmatrix} ]这个结果不再是简单的对角拉伸而是出现了一对反对角元素。但从几何上说它描述的仍然是同一个“沿旧x轴方向拉长到2倍沿旧y轴方向保持”的动作。只是坐标系转了45度之后这个动作看起来变成了“沿着新坐标轴的45度方向拉长同时沿另一个垂直方向压缩/保持”。这正好解释了为什么我们在标准坐标系下看一个矩阵感觉它是旋转带剪切但换到特征向量坐标系下它就变成一个纯粹的对角缩放矩阵。矩阵还是那个动作变的是你看它的角度。4.4 这解释了为什么特征向量是“不动方向”特征向量的定义是 (A \mathbf{v} \lambda \mathbf{v})几何意思非常直白存在某些方向矩阵 (A) 只会把向量拉长或缩短不会改变它的方向。这些方向就是矩阵的“主轴”。当我们把这些特征向量按列排成 (P)得到[ P^{-1} A P \Lambda ]这里的 (\Lambda) 是对角矩阵对角线上的元素就是特征值。放到前面的三步流程里看先把坐标翻译到特征向量张成的坐标系然后在这个坐标系下变换变成沿每个坐标轴独立缩放再翻译回原坐标系。整个过程里左乘右乘正好把复杂的“旋转拉伸”拆成了“旋转进去、缩放、旋转回来”。这也是为什么主成分分析要去找协方差矩阵的特征向量因为只有把坐标系旋转到特征方向原本复杂的相关性结构才会变成互不相关的独立缩放轴。理解和掌握了 (P^{-1} A P) 的几何画面再回头看左乘右乘你已经不是背公式而是在心里“看”变换过程了。5. 常见错误与排查思路代码写得多了难免会遇到左右乘混用、顺序写反、结果方向不对这类问题。我整理了一份速查表外加几个高频踩坑细节。如果你正在做图形学、机器人、数据科学相关的东西建议先收藏等遇到问题再回来对号入座。5.1 常见问题速查表症状可能原因解决办法图形方向反了行向量点直接右乘变换矩阵忘了转置改为右乘变换矩阵的转置或用列向量左乘复合变换结果和预期不符矩阵连乘顺序和动作顺序反了先执行的动作写在最右边从右往左读左乘右乘算出来差很多把“对象变换”当成了“坐标系变换”先想清楚你要让对象动还是换坐标系矩阵能乘但图形看起来奇怪点坐标的存储格式和矩阵维度不匹配确认每个点是列向量还是行向量统一约定结果矩阵维数正确但数值全错把 (P^{-1} A P) 写成了 (P A P^{-1})记住右边进入旧坐标系左边回到新坐标系这些坑我都踩过而且踩得很狼狈。尤其是行向量和列向量混用在C、Python、Matlab里都有不同的默认约定稍不注意就会翻车。最好的办法就是在代码开头写清楚注释“所有点的存储方式为列向量变换顺序从左到右依次后执行”。5.2 四个容易踩坑的细节第一个细节行向量版本要转置。如果某个库默认点坐标是行向量那么左乘变换矩阵 (A) 应该写成 (P A^T)而不是 (P A)。这不是矩阵乘法本身变了而是转置把左右关系调换了一下。第二个细节矩阵乘法有结合律但没有交换律。你可以先算 (A B) 再乘 (\mathbf{v})也可以先算 (B \mathbf{v}) 再用 (A) 作用结果一样。但不能把 (A B) 换成 (B A)。结合律给了计算上的便利交换律不要乱用。第三个细节非方阵也有几何意义。(m \times n) 矩阵把 (n) 维空间映到 (m) 维空间可能降维也可能升维。左乘右乘的规则依然成立只是这时候“行混合”和“列变换”会伴随维度变化不能死套“旋转”“拉伸”这种二维直觉。第四个细节右乘不一定是“转置”。 (B A) 的每一行是 (B) 的对应行向量被 (A) 映射但如果想把它改写成列向量左乘确实要用 (A^T)。所以看到右乘时脑子里要分两条线一条是“列向量被线性组合”一条是“行向量被 (A^T) 变换”。两条线都对但别混着用。5.3 给学习者的自检流程我建议你在学完左右乘之后做这套五分钟自检第一步画一个简单图形比如三角形或正方形把它表示成矩阵。第二步写下你想要的两个动作比如“先旋转再拉伸”和“先拉伸再旋转”。第三步按列向量约定写出对应的矩阵链左乘到图形上。第四步用手算或代码画出结果。第五步把其中一个矩阵从左边挪到右边再算一遍观察图形的变化差异。做完这五步你不仅会理解左乘和右乘的几何意义还会发现矩阵乘法的顺序本质上就是“动作发生的顺序”。我在教朋友线性代数时从来不让大家死记硬背 (AB \ne BA)而是让他们亲手画一幅图把 (AB) 和 (BA) 两个结果并排放在一起。见过一次之后这个知识点就再也忘不掉了。最后再分享一个小技巧当你不确定该左乘还是右乘时用一个最简单的情况验证。比如把一个点放在 ((1,0))把变换矩阵取成 (R)算一遍看看方向是否符合直觉。单位向量、单位矩阵、零矩阵都是很好的“测试用例”。这些不起眼的验证往往比反复查公式更可靠。
阅读完成 · 觉得有帮助?
咨询建站