课程/M03/矩阵乘向量:线性映射
M03 · 矩阵与线性映射核心约 35 分钟

3.2 矩阵乘向量:线性映射

本节位置:模块 3 · 矩阵与线性映射 | 前置:3.1 | 预计:35 分钟

一句话: 同时是「列向量的加权和」「一排点积」和「对空间做一次变换」——三种算法,同一个结果。

0. 场景引入

周五下午,协作机器人调试现场。一台 6 轴机械臂要在 2 毫秒的控制周期里(500 Hz)走一条直线:末端以 0.25 m/s 沿桌面匀速前推,焊一条 300 mm 的缝。

控制器每一拍只做一件事:给定末端速度 (3 个线速度 + 3 个角速度),求 6 个关节的速度 ,满足

是 的雅可比矩阵(Jacobian),随姿态 变化,每一拍都要重算。

算错的代价很直接:缝偏 1 mm 就是废件。更糟的是某个关节的速度超过额定 180°/s(约 3.14 rad/s),驱动器过流保护直接抱闸——机械臂停在半空,工件和夹具一起报废。

这条缝要走 s,也就是 600 个控制周期。每一拍都要把新的 乘一次、解一次,中间任何一拍算错,后面的轨迹就全歪了。

问题: 为什么能算出一个速度,而不是六个互不相干的数?当 接近不可逆时, 为什么会突然爆掉?

读完本节,你应该能回答三件事:

  1. 三种算法(列组合、行点积、变换)在机器人上分别对应什么物理量;
  2. 为什么 的第 列就是「只动第 个关节、其余锁死」时末端的速度;
  3. 变大时,为什么解出的关节速度会失控,工程上怎么兜底。

1. 直觉

1.1 三种算,同一件事

一个 2 维向量 经过矩阵

之后变成什么?你可以按三种方式算:

  • 把 的两列按 加权相加;
  • 用 的每一行和 做点积;
  • 把 看成对平面的一次拉伸,看 这个点被搬到哪里。

列组合:把输入当配方。 有两列 、。输入 说的是:取 1 份第一列、2 份第二列。

这是「鸡尾酒配方」视角:输入是各原料的用量,矩阵的列是原料,输出是调好的酒。

矩阵乘向量:按输入系数把两列加权相加

图: 的两列 、;输入 表示取 1 份 、2 份 ,平行四边形的对角线就是 。

行点积:把矩阵当一组测量。 的第一行 与 做点积得 ;第二行 得 。输出分量就是每个行向量与输入的相似度/投影。

变换:把矩阵当动作。 把基向量 送到 ,把 送到 。单位正方形因此被拉成一个平行四边形, 跟着一起被搬走。

💡 一句话直觉:列组合是「怎么算」,行点积是「每个输出看什么」,变换是「几何上发生了什么」。

类比边界:只有当矩阵是方阵且可逆时,「变换」才是一个可来回搬运的坐标变换; 时它是升维/降维,信息一定丢失或冗余。

1.2 现实对应:一组传动比

把 的第 列单独拎出来看。若只有第 个关节在动(,其余为 0),则 。也就是说:

的第 列 = 只动第 个关节时,末端的速度方向;它的长度就是这个关节的「力臂」。

以连杆总长 0.4 m 的机械臂为例,第 6 个关节(腕部)转 1 rad/s,末端走 0.4 m/s。所以 的第 6 列范数约 0.4,单位是「米每弧度」。

这就是列组合视角在机器人上的样子:末端速度是 6 个关节各自贡献的线性叠加——每个关节按自己的角速度贡献一列,加起来就是末端的总速度。 里的 在机器人上就是 。

这个类比在哪里失效:传动比是常数,雅可比不是。 依赖当前姿态 ,机械臂一动 就变。把 当固定矩阵用(比如整条轨迹只算一次),等于假设机械臂没动——这是仿真与实机对不上的最常见原因。

1.3 量级直觉

关节速度的额定值是 180°/s,即 3.14 rad/s。连杆 0.4 m 时,末端速度上限约 m/s——比焊接要的 0.25 m/s 快 5 倍,看起来余量充足。

余量是被 吃掉的。末端要 0.25 m/s,若某个方向上 ,最坏方向上的关节速度就要 rad/s,直接超限。线性映射的增益不是均匀的:沿不同方向,它差 倍。

2. 定义

2.1 矩阵乘向量(matrix-vector product)

设 ,,则 ,其第 个分量为

逐项读法:输出的第 个分量,是 第 行与 的点积。形状:。

2.2 列组合形式

把 按列分块 ,则

这是与 §2.1 等价的写法,只是把「按行求和」换成了「按列加权」。

把 读成「列的组合」,也是 Trefethen & Bau 第一讲的开篇算法。

2.3 线性性

映射 满足:对任意 和标量 ,

满足这条性质的映射叫线性映射(linear map)。注意 是它的必要条件:原点必须不动。

3. 为什么这样定义

为什么不逐元素乘?因为逐元素乘 要求形状相同,而且它不满足「先组合再变换 = 先变换再组合」。线性映射的价值恰恰在于这条可交换性:你可以先把输入拆成基向量的组合,分别看它们去哪,再加起来。

为什么行点积和列组合必须一致?因为矩阵只有一份数字。行定义给出计算顺序,列定义给出几何含义;两者一致,才能让「代数计算」和「空间变换」互相翻译。

为什么原点必须不动?如果 ,映射就是 仿射(affine) 的。线性层里的偏置 正是干这个的: 是仿射,不是严格线性。把 增广成 、 增广一列 ,就又能写成线性形式。

3.1 反事实:如果 定义成「第 个输出只看第 个输入」

逐元素乘 要求形状相同,所以对 的矩阵和 2 维向量来说,形状上说得通。把它明确写成:第 个输出取 。

取一个 90° 姿态下的平面二连杆,只保留两个关节对末端线速度的贡献:

第 1 列 :动第 1 关节,末端沿 走;第 2 列 :动第 2 关节,末端沿 走。两个力臂都是 0.4 m。

让第 1 个关节以 1 rad/s 转动,第 2 个锁死:。

正确算法(行点积):

末端沿 走 0.4 m/s,符合「力臂 × 角速度」。

逐元素算法:

末端速度为零。也就是说:电机在转、关节在动、连杆扫过 0.4 m 的弧,末端却「没动」。

一眼可见的荒谬:末端固定在连杆上,关节一动它必动(除非力臂为 0)。逐元素算法做了两件错事:把「第 2 个关节锁死」误读成「整行归零」;同时丢掉了 对第 1 个输出的贡献——那正是「第 2 个关节也在推着末端往 走」这件事。

结论: 的每个输出分量必须把所有输入维度都看一遍(行点积),才能表达「多个关节共同决定一个方向的速度」。任何「第 个输出只看第 个输入」的定义,都会把耦合整个删掉。

4. 性质与推导

4.1 两种算法为什么相等

把 的第 个分量写出来:

第一步是向量线性组合按分量展开,第二步用「第 列的第 个分量就是 」。列组合与行点积不是两个定义,而是同一个求和的两种分组方式。

4.2 线性性的推导

逐分量相等,所以向量相等。

4.3 基本性质

性质式子说明
零矩阵 是所有元素为 0 的矩阵
单位阵 对角为 1、其余为 0
加法分配形状必须相同
数乘先缩放矩阵等于先缩放输出
原点不动线性的必要条件

单位阵的列是标准基:,所以 。

5. 例子

5.1 手算:三种算法算同一个

取 ,。

列组合:

行点积:第一行 ;第二行 。

变换:,。单位正方形被拉成顶点依次为 的平行四边形; 被送到 。

验证线性性:取 ,则 ,;而 ,一致。

5.2 场景:带偏置的线性层

线性层实际算的是 。取 、、,则 ,加偏置得 。因为 时 ,这个映射是仿射的;偏置让输出整体平移。

5.3 场景闭环:500 Hz 的速度环

输入:(fp64,288 字节),末端目标速度 (沿 匀速下降 0.25 m/s),控制周期 ms。

计算:每一拍解 。用 LU:分解约 FLOPs,回代 FLOPs,合计 216 FLOPs。若 在 6 拍内不变,分解可以复用,每拍只花 72 FLOPs。

输出:6 个关节速度指令,先过一道限幅 rad/s。通过才下发;任一关节超限,就按比例整体缩放(保方向、降速度),并上报「接近奇异位形」。

成本:算力完全不紧张—— FLOP/s,一块几十 MHz 的 MCU 都绰绰有余;内存也只是 36 个数。真正的成本在重算 本身:6 个关节角要做十几次三角函数、几十次乘法,比解方程贵一个数量级。所以瓶颈从来不是「算不动 」,而是「来不及更新 」。

失败条件与兜底:

  • 奇异位形:手臂完全伸直时,末端沿手臂方向无法产生速度, 某列退化,,,解出的 可以是 rad/s。兜底:阻尼最小二乘,把 换成 , 随 增大(第 3.4 节的伪逆,第 4.5 节的一般形式)。代价是末端速度略小于目标——宁可慢,不要抱闸。
  • 编码器噪声:关节角读数上 rad 的噪声经 放大 倍。 时,速度指令上就有 rad/s 的抖动,表现为末端高频震颤。兜底:对 低通滤波,但会引入相位滞后,直线走成轻微弧线。
  • 过期:若为省算力每 10 拍才更新一次 ,中间 20 ms 里机械臂已经转了几度, 与实际姿态不符,直线误差到毫米级。兜底:让 的更新与插补周期对齐,宁可多算三角函数。

6. 常见误区

  1. 误区: 是 的每个元素乘 的对应元素。 纠正:逐元素乘是 Hadamard 积 ,要求同形状; 是行点积/列组合,输出维度由 的行数决定。

  2. 误区:行向量也能直接写 。 纠正:本书约定 是列向量。若在代码里拿到行向量 x,应写 x @ A.T,本质仍是 。

  3. 误区: 是线性映射。 纠正:只要 就是仿射映射,原点被搬到了 。深度学习里习惯把整层叫「线性层」,是工程叫法。

7. 概念网络

8. 通往大模型:线性层就是一次矩阵乘向量

出现位置:Transformer 的每个线性层、QKV 投影、FFN 的第一层与第二层、输出 logits 层,本质都是对每个 token 做一次 。

形状:隐藏状态 ,权重 。代码写作 X @ W.T + b,逐 token 展开就是 次矩阵乘向量;这一层在 BLAS 里叫 GEMV,即第 2 层矩阵–向量例程(Golub & Van Loan)。QKV 投影常把三个矩阵拼成 ,一次算出 (三组投影的原始定义见 Vaswani 等,2017);当 时输出维是 12288。

为什么需要:线性层是模型里把特征维度线性组合起来的主要运算:attention 混合的是不同 token 的信息,LayerNorm 做的是逐 token 的归一化,它们都不提供可学习的跨维线性权重。没有 ,每个特征维度永远独立,模型无法组合特征。

可检验结论:对 、、 的 QKV 投影,FLOPs 约为 ,即约 412 GFLOP。把 翻倍,FLOPs 变为 4 倍——这就是大模型算力随宽度平方增长的来源。

如果这一步算错,用户会看到什么现象: 少算一项,最典型的症状是「某些东西永远不变」——某个注意力头对某些 token 的分数恒为 0,模型对这些词完全无感,表现为系统性忽略某类实体。把输出维度方向搞反(x @ W 写成本该 x @ W.T),如果形状恰好还能对上,模型会照常训练、loss 照常下降,只是学到的东西整体「错位」,最终效果比随机初始化好不了多少。符号错(少一个负号)则常表现为训练早期 loss 突然变 NaN 或爆炸——因为残差流被反复放大而不是相互抵消。

9. 练习

  1. 概念:用列组合语言解释「 的第 列等于 」。
  2. 计算:,,分别用列组合与行点积求 。
  3. 计算:接上题,求 ,并验证它等于 ,其中 。
  4. 场景:,,,求 ,并说明为什么它不是线性映射。
  5. 开放:如果线性层去掉偏置,表达能力会损失什么?在什么情况下偏置是冗余的?
参考答案
  1. 表示「只取第 份原料」,列组合 ,其余系数为 0,所以结果就是第 列。
  2. 列组合:;行点积:,。
  3. ;。,,一致。
  4. ,加偏置得 。 时输出 ,原点被平移,故不是线性映射。
  5. 偏置让每个输出维度可以整体平移,相当于给决策边界/激活阈值一个可学习的起点;如果数据已经中心化、或下一层有 LayerNorm,偏置的作用会大幅减弱,甚至可省略。

10. 一页速记

  • ;形状 。
  • 物理意义 / 现实对应: 是「每个输入的贡献按列加权求和」;在机械臂上就是各关节速度按各自力臂叠加成末端速度, 的列就是力臂。
  • 列组合:;行点积:每个输出是一次点积。
  • 线性:,且 。
  • ,。
  • 线性层实际是仿射:,偏置让原点平移。

11. 参考文献与致谢

这一页的知识不是凭空来的。下面列出本页直接借用的原始工作与权威整理;正文中的人名、定理名已链接到对应条目。链接优先指向 DOI、arXiv 或可长期访问的原文存档。

  • Golub & Van Loan(2013):Matrix Computations(第 4 版)。把 定为 BLAS 第 2 层的 GEMV,并给出 FLOPs 与访存计数,本页的行点积/列组合在实现里就是它。Johns Hopkins University Press
  • Trefethen & Bau(1997):Numerical Linear Algebra。第一讲就把 解释成列向量的线性组合,本页「列组合」视角的标准出处。SIAM
  • Vaswani 等(2017):Attention Is All You Need。给出 的线性层与 三组投影,本页 §8 的形状推导直接沿用。arXiv:1706.03762

下一篇 → 3.3 矩阵乘法:四种视角

返回 M03 导览去练习场

随堂测 · 4 题

数值难度 1第 1 / 4 题
设 、, 的第二个分量是多少?

源文件:03-矩阵与线性映射/02-矩阵乘向量.md

输入关键词开始搜索