笃行
首页
个人 & 心法
互联网/硬件后台
游戏基础架构
UE 引擎
游戏业务
AI / 大模型
数据结构与算法
机器学习数学
通用基础
GitHub
首页
个人 & 心法
互联网/硬件后台
游戏基础架构
UE 引擎
游戏业务
AI / 大模型
数据结构与算法
机器学习数学
通用基础
GitHub
  • 向量入门

    • 看得见的机器学习数学
    • 向量是什么
    • 向量的加减与数乘
    • 线性组合与张成
  • 矩阵与变换

    • 矩阵是一次变换
    • 矩阵乘法
  • 度量与求解

    • 行列式与面积
    • 解方程组就是倒着走回去
    • 特征向量的直觉
    • 点积与相似度
  • 高维与结构

    • 高维空间的直觉
    • 正交基与投影
    • 秩与低秩
    • 长度与归一化
    • 线性与非线性
  • 概率与信息

    • 概率分布与采样
    • 期望与方差
    • 指数与 softmax
    • 对数与信息量
    • 交叉熵
  • 学习与优化

    • 导数就是坡度
    • 梯度下降
    • 链式法则与反向传播

矩阵乘法:连做两次变换,顺序还不能换

先把照片转 90 度,再横着拉宽一倍。跟先横着拉宽一倍、再转 90 度——结果一样吗?

🧠 一句话结论

两个矩阵相乘,就是"先做一次变换、再做一次变换",合并成一次等效的变换。但顺序不能换:先转再拉和先拉再转,出来的东西完全不同。


场景问题

上一篇你学会了用矩阵记录一次搬家。现在自然要问:能不能连做两次?

当然能。抓住纸拉一把,再抓住拉一把,没人拦你。

有意思的是接下来这个问题:做完两次之后,纸的样子还是"格子平行等距、原点不动"吗?

想一秒钟——是的。第一次拉扯后格子还是平行等距的,在这个基础上再拉一次,还是平行等距。原点两次都没动。

所以连做两次的总效果,本身也是一次线性变换。 而既然是线性变换,它就该有一个自己的矩阵。

那个矩阵,就是这两个矩阵的乘积。 这就是矩阵乘法的全部来头——它不是一套凭空规定的算术,它是"两次变换能合并成一次"这个事实的记账方式。

实现方案

先做 B,再做 A

假设:

  • BBB 是"逆时针转 90 度"
  • AAA 是"横向拉到 2 倍"

我们想先转、后拉。那么一个点 v⃗\vec{v}v 的下场是:

  1. 先被 BBB 搬走,到了 Bv⃗B\vec{v}Bv
  2. 这个新位置再被 AAA 搬走,到了 A(Bv⃗)A(B\vec{v})A(Bv)

看动画,分两段走完这个过程——先转,再拉:

第一段:转 90 度 → 第二段:横向拉 2 倍橙 = 向右这块底砖,青 = 向上这块底砖

盯住那个紫色小方块:它先整体转了个方向,然后被横向抻开。两个动作先后发生,最后停在一个特定的形状上。

现在的问题是:能不能一步到位算出那个最终形状?

合并:只要看两块底砖最后落在哪

能,而且方法你已经会了。上一篇说过,要描述一次变换,只需要知道两块底砖最后落在哪儿。那就让两块底砖自己走一遍这两步:

第一块底砖"向右" (10)\begin{pmatrix} 1 \\ 0 \end{pmatrix}(10​):

  • 先被 BBB(转 90 度)搬走 → 转到朝上,成了 (01)\begin{pmatrix} 0 \\ 1 \end{pmatrix}(01​)
  • 再被 AAA(横向拉 2 倍)搬走 → 它现在朝上,横向分量是 0,拉了也白拉 → 还是 (01)\begin{pmatrix} 0 \\ 1 \end{pmatrix}(01​)

第二块底砖"向上" (01)\begin{pmatrix} 0 \\ 1 \end{pmatrix}(01​):

  • 先被 BBB 搬走 → 转到朝左,成了 (−10)\begin{pmatrix} -1 \\ 0 \end{pmatrix}(−10​)
  • 再被 AAA 搬走 → 横向被拉到 2 倍 → 成了 (−20)\begin{pmatrix} -2 \\ 0 \end{pmatrix}(−20​)

两个落点并排竖着写,合并后的矩阵就出来了:

AB=(0−210)AB = \begin{pmatrix} 0 & -2 \\ 1 & 0 \end{pmatrix} AB=(01​−20​)

这就是矩阵乘法。 算法用一句话说完:

乘积的第一列 = 第一块底砖连走两步后的落点;第二列 = 第二块底砖连走两步后的落点。

课本会教"第一行乘第一列、对应相乘再相加"。那个口诀算出来的数一样,但它藏起了你在干什么。你现在知道了:你在追踪两块底砖的旅程。

为什么先做的那个写在右边

这是全篇最容易让人不舒服的地方,所以专门说清楚。

我们想"先转(BBB)再拉(AAA)",写出来却是 ABABAB ——先做的 BBB 反而站在右边。读起来是从右往左,跟中文的阅读顺序相反,很别扭。

为什么会这样?看这个式子就明白了:

A(Bv⃗)A(B\vec{v}) A(Bv)

向量 v⃗\vec{v}v 站在最右边。谁先动手,谁就得紧挨着 v⃗\vec{v}v——因为它得先拿到 v⃗\vec{v}v 才能干活。BBB 先动手,所以 BBB 贴着 v⃗\vec{v}v;AAA 后动手,只能站在更外面。

于是把括号去掉,就成了 ABv⃗AB\vec{v}ABv:从右往左,是动作发生的先后顺序。

这纯粹是一个记法约定带来的别扭,不是什么深刻的道理。它的根源是数学家习惯把函数写在输入的左边(就像 f(x)f(x)f(x) 里 fff 在左边)。既然向量在右边,那作用在它身上的东西就只能往左边排队,最后动手的排最外面。

记不住的话就记这句话:贴着向量的那个先干活。

三次变换:先合并哪两个都一样

如果连做三次变换 CCC、BBB、AAA(按这个顺序做),写成 ABCABCABC。你可以:

  • 先算出 ABABAB(前两次的合并),再和 CCC 相乘:(AB)C(AB)C(AB)C
  • 或者先算出 BCBCBC(后两次的合并),再左乘 AAA:A(BC)A(BC)A(BC)

两种算法结果一样。 这叫结合律。

为什么它成立?因为不管你怎么加括号,每个点实际经历的旅程一模一样:先被 CCC 搬、再被 BBB 搬、再被 AAA 搬。加括号只是改变了你"记账的分组方式",没有改变实际发生的事。

就像三个人接力送信:不管你说"前两个人先跑完再交给第三个"还是"第一个人跑完交给后两个",信的实际路线都是那一条。

注意:结合律说的是"分组方式可以变",不是"顺序可以变"。 顺序绝对不能变——这正是下一节的主题。

为什么这么做

为什么把它叫"乘法"?和 3×43 \times 43×4 有关系吗?

有一点血缘关系,但不多。共同点是:都表示"连续做某件事"。3×43 \times 43×4 可以理解成"把 3 这么大的东西重复 4 次",矩阵乘法是"把变换连续做两次"。

而且它们共享一些性质:都有结合律,都有个"乘了等于没乘"的单位(数字是 1,矩阵是单位矩阵 III)。所以数学家借用了乘法的名字和符号。

代价还是那个代价:名字借来了,性质没全借来。数字乘法可以交换,矩阵乘法不行。这是初学者最常摔的一跤。

为什么"追踪底砖"这个算法是对的?凭什么只算两块底砖就够?

凭上一篇那个大礼:线性变换的全部信息,就锁在两块底砖的落点里。 既然连做两次的总效果也是一次线性变换(本篇开头论证过),那它也只需要两块底砖的落点来描述。

所以算法不是"简化",而是恰好够用、一点不多。

为什么不能把两个矩阵"对应位置相乘"就完事?

因为那样算出来的东西不对应任何真实发生的事。下一节细说。

为什么别的选择不行

死胡同一:以为矩阵相乘是"对应位置的数相乘"

这个猜法太自然了——毕竟向量相加就是"对应位置相加",那矩阵相乘不该是"对应位置相乘"吗?

用我们的例子试试。BBB 是转 90 度,AAA 是横向拉 2 倍:

A=(2001)B=(0−110)A = \begin{pmatrix} 2 & 0 \\ 0 & 1 \end{pmatrix} \qquad B = \begin{pmatrix} 0 & -1 \\ 1 & 0 \end{pmatrix} A=(20​01​)B=(01​−10​)

"对应位置相乘"会得到:

(2×00×(−1)0×11×0)=(0000)\begin{pmatrix} 2 \times 0 & 0 \times (-1) \\ 0 \times 1 & 1 \times 0 \end{pmatrix} = \begin{pmatrix} 0 & 0 \\ 0 & 0 \end{pmatrix} (2×00×1​0×(−1)1×0​)=(00​00​)

全是 0! 这个矩阵的含义是"把整个平面压成一个点"。

但真实发生的事情是什么?先转个方向,再抻宽一点——纸还在那儿,好端端的,只是变了形状。它绝对没有被压成一个点。

所以"对应位置相乘"给出的答案不只是数值不对,而是在描述一件根本没发生过的事。它错在原理上:向量相加之所以能"对应位置相加",是因为向右和向上两笔账互不干扰(第二篇讲过);而变换的叠加根本不是"两笔账各自算总",而是一块底砖走完第一步之后,整个新位置再一起走第二步。前一步的结果会喂给后一步,两步是串联的,没法分开算。

记住这个反例。 只要你想不起矩阵乘法怎么算,就想"对应位置相乘会得出全 0,那显然是错的",然后回到"追踪两块底砖"。

死胡同二:以为 ABABAB 和 BABABA 一样

这是从数字世界带来的最顽固的错误习惯。3×4=4×33 \times 4 = 4 \times 33×4=4×3,从小学到大,交换律像呼吸一样自然。

在矩阵这里,它不成立。而且不是"偶尔不成立",是通常都不成立。

回到开头那个问题:先转 90 度再横向拉宽,跟先横向拉宽再转 90 度,一样吗?

看图,左右两边就是这两种顺序的结果:

先转 90 度,再横向拉 2 倍宽 2 格 × 高 3 格先横向拉 2 倍,再转 90 度宽 1 格 × 高 2 格虚线 = 原来的小方块

拿原来那个 1×1 的小方块(虚线)做实验:

顺序第一步之后第二步之后
先转,再拉方块转了个身,还是 1×1横向抻开 → 变成 2 宽 × 1 高……
先拉,再转横向抻开,变成 2 宽 × 1 高转 90 度 → 变成 1 宽 × 2 高

一个躺着,一个立着。这不是"差一点",这是两个不同的东西。

用矩阵算也一样:

AB=(0−210)BA=(0−120)AB = \begin{pmatrix} 0 & -2 \\ 1 & 0 \end{pmatrix} \qquad BA = \begin{pmatrix} 0 & -1 \\ 2 & 0 \end{pmatrix} AB=(01​−20​)BA=(02​−10​)

那个 2 从上排跑到了下排。换了顺序,纸的变形方式就不一样了。

为什么会这样?因为第二次变换作用的对象,是第一次变换留下的结果。第一次干了什么,会改变第二次能干什么。就像"先切菜再下锅"和"先下锅再切菜"——后者你根本没法切了。

所以:在矩阵世界里,动作的先后顺序是有意义的信息,不能随便挪。

(顺便说一句:确实有些特殊的矩阵对是可以交换的,比如两个都是纯拉伸的时候。但那是例外,不是规律。默认假设它们不能交换,才是安全的习惯。)

沉淀结论

  1. 矩阵相乘 = 连做两次变换,合并成一次——乘法是这个事实的记账方式,不是凭空的算术规定
  2. 算法:追踪两块底砖走完两步的落点,并排竖着写就是乘积
  3. 先做的写在右边(ABABAB 表示先 BBB 后 AAA),因为贴着向量的那个先干活——这只是记法别扭,不是深刻道理
  4. 不能对应位置相乘(反例:转 90 度配横向拉伸,会算出"压成一个点",纯属胡说)
  5. AB≠BAAB \ne BAAB=BA,顺序是有意义的信息(先转再拉是躺着的,先拉再转是立着的)
  6. 结合律成立:分组方式可以变,但顺序不能变

下一篇换个角度:我们不再问"纸变成什么形状了",而是问一个能量出来的问题——纸上一块地方的面积,被放大了几倍?

记忆口诀

乘法就是连做两次,合并成一次。
算法只一句:追两块底砖走完两步落在哪。
先做的写右边——贴着向量的那个先干活。
对应位置相乘是错的(转+拉会算出压成一点)。
AB 不等于 BA:先转再拉躺着,先拉再转立着。
结合律可以换分组,不能换顺序。

长大以后它会变成什么

游戏里一个角色出现在你屏幕上,中间要连做好几次变换:模型自己的姿态 → 它在世界里的位置 → 镜头的角度 → 投影到屏幕。这一串全部乘成一个矩阵,每帧算一次。顺序错一个,画面就全乱——这就是为什么"顺序不能换"是图形程序员的日常。以后可以翻 UE 引擎架构。


自测:合上资料能说清楚吗?

  1. 为什么"连做两次线性变换"的总效果,也一定能用一个矩阵表示?
参考答案

因为第一次变换后格子仍是平行等距的直线、原点没动;在此基础上再变一次,这三条依然保持。所以总效果仍是一次线性变换,而任何线性变换都能由两块底砖的落点(也就是一个矩阵)完全描述。

  1. 想"先做 B 再做 A",为什么写成 ABABAB 而不是 BABABA?
参考答案

因为式子是 A(Bv⃗)A(B\vec{v})A(Bv)——向量在最右边,谁先干活谁就得贴着向量。BBB 先动手所以紧挨 v⃗\vec{v}v,AAA 后动手只能站外面。去掉括号就是 ABv⃗AB\vec{v}ABv,从右往左才是动作顺序。这纯粹是记法约定造成的别扭。

  1. 有人说矩阵相乘就是"对应位置的数相乘"。用"转 90 度 + 横向拉 2 倍"这个例子说明他错在哪。
参考答案

那样算出来是全 0 矩阵,意思是"把整个平面压成一个点"——可实际上纸只是转了个身又抻宽了点,根本没被压扁。它错在原理上:两步是串联的(第一步的结果喂给第二步),不是两笔互不干扰的账。

  1. 对比"先转 90 度再横向拉宽"和"先横向拉宽再转 90 度":拿一个 1×1 的小方块做实验,两种顺序各得到什么?
参考答案

先转再拉:方块转身后还是 1×1,再横向抻开 → 躺着的长方形。先拉再转:先变成 2 宽 1 高,再转 90 度 → 立着的长方形。一个躺一个立,完全不同——因为第二次变换作用的对象是第一次留下的结果。

  1. 结合律说 (AB)C=A(BC)(AB)C = A(BC)(AB)C=A(BC)。这是不是意味着顺序可以随便换?
参考答案

不是。 结合律只说分组方式(加括号的位置)可以变,因为每个点实际经历的旅程没变(还是先 C 再 B 再 A)。而顺序绝对不能换——ABCABCABC 和 CBACBACBA 通常是完全不同的变换。就像接力送信:怎么分组都行,跑的先后不能乱。

最近更新: 2026/9/10 11:38
Prev
矩阵是一次变换