想象一家全国连锁物流公司。左边的表格记录着每家工厂(行)向各个中转仓(列)发货的件数;右边的表格记录着每个中转仓(行)向各大门店(列)配货的件数。老板想知道“工厂 1 的货最终能送到门店 2 多少件”,答案既不在左边也不在右边,而要“过一遍所有中转仓”:工厂给中转仓的件数,乘以中转仓配送到门店的件数,再把每条路线的贡献统统加起来。这个“过一遍、乘起来、加起来”的动作,就是矩阵乘法——整个运算的目标,是把两张间接的表格合并成一张“工厂直达门店”的表。理解了这张物流表,你就同时理解了矩阵乘法的一切:为什么要行列相乘、为什么内维必须相等、为什么不能随便交换顺序、为什么括号放在哪里很要紧。本文就用这条物流线索,把规则、几何直觉、运算性质和高效实现串成一张完整的知识地图。

岗位关联

矩阵乘法是深度学习前向传播、Transformer 注意力机制、图像几何变换的底层运算。对 AI 从业者来说,它是阅读论文公式、推导模型结构、排查性能瓶颈的“乘法表”,越早吃透越受益。

目录
  1. 可视化演示
  2. 行列相乘规则
  3. 定义的动机
  4. 几何意义
  5. 运算性质
  6. 分块矩阵乘法
  7. 高效实现
  8. 计算复杂度
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

展示矩阵乘法A×B=C的行列点积计算过程,以及结合律、分配律等核心运算性质和维度匹配规则。

本节配有交互动效(进入视口后自动加载,约 3KB)。

矩阵乘法行列点积 行向量×列向量:A的行与B的列逐元素相乘求和 维度匹配:(m×k)×(k×n)=(m×n),内维必须相等 计算量:每个元素需k次乘加,共m×n个元素 C[i][j] = Σ A[i][k] × B[k][j] 矩阵乘法是线性代数最核心运算

行列相乘规则

物流老板面对两张表:左边 A 表记着每家工厂给每个中转仓发多少货,右边 B 表记着每个中转仓往每家门店送多少货。要回答“工厂 i 最终到门店 j 有多少货”,不能只看某一行某一列,而要走遍所有中转仓:先看工厂 i 给中转仓 k 发了几件(A 表里的数),再看中转仓 k 每发一件能变成送到门店 j 的几件(B 表里的数),两者相乘就是这条路的贡献;把每条中转线路的贡献全部加起来,才是最终答案。这就是矩阵乘法的全部直觉。

翻译成数学语言:A 是 m×n 的“工厂—中转仓”表,B 是 n×p 的“中转仓—门店”表。它们能相乘的前提是 A 的列数等于 B 的行数——因为中转仓的编号必须前后对得上,这个相等的维度叫“内维”。结果 AB 就是一张 m×p 的“工厂—门店”直达表,行数来自 A 的行数,列数来自 B 的列数。

(AB)ij=∑k=1nAikBkj\displaystyle (AB)_{ij} = \sum_{k=1}^{n} A_{ik}B_{kj}

1. 结果矩阵的元素:$(AB)_{ij}$ 表示直达表中第 i 行、第 j 列的那一个数字,回答“工厂 i 到门店 j 总共有多少货”。

(AB)ij\displaystyle (AB)_{ij}

2. 对中转仓求和:$\sum_{k=1}^{n}$ 的意思是让中转仓编号 k 从 1 数到 n,把每条中转线路的贡献都加进来,一条都不能漏。

∑k=1n\displaystyle \sum_{k=1}^{n}

3. A 表里的数:$A_{ik}$ 是 A 矩阵第 i 行第 k 列的元素,即工厂 i 发给中转仓 k 的件数。

Aik\displaystyle A_{ik}

4. B 表里的数:$B_{kj}$ 是 B 矩阵第 k 行第 j 列的元素,即中转仓 k 配送到门店 j 的件数;两者相乘再求和就是最终到达量。

AikBkj\displaystyle A_{ik}B_{kj}

例如 A 是 2×3、B 是 3×2:先算左上角 C[0][0] = 1×7 + 2×9 + 3×11 = 58,再算右上角 C[0][1] = 1×8 + 2×10 + 3×12 = 64,下半行同理得 139、154,最终结果是 [[58, 64], [139, 154]]。只要记住“工厂 → 中转仓 → 门店”这条链路,任何矩阵乘法都能手算出来,一行一行、一列一列慢慢磨即可。

定义的动机

有人会问:为什么不把两个矩阵对应位置的数直接相乘呢?那样简单多了。但物流公司要的不是两张表的“账目对碰”,而是一条完整的运输链路。矩阵 A 是一台“搬运机器”:输入仓库需求,输出工厂计划;矩阵 B 是另一台“搬运机器”:输入门店订单,输出仓库需求。把两台机器串起来使用,正是先 B 后 A 的层层汇总——矩阵乘法天生就是为“复合搬运”而生的。

从另一角度看,AB 的第 j 列只依赖 B 的第 j 列。B 的第 j 列里的每个数 B[k][j] 就像是“中转仓 k 的重要程度”,用它当权重去加权混合 A 的各列,就得到了结果的第 j 列。这就是“线性组合”视角:矩阵乘法不是在算一堆孤立的乘积,而是在按权重把整列货物重新混装。

(AB):j=∑k=1nBkj A:k\displaystyle (AB)_{:j} = \sum_{k=1}^{n} B_{kj}\, A_{:k}

1. 结果的第 j 列:$(AB)_{:j}$ 表示 AB 这个新矩阵的整列第 j 列,它是一组数而不是一个数。

(AB):j\displaystyle (AB)_{:j}

2. 权重来自 B:$B_{kj}$ 是 B 第 j 列的各个元素,它们扮演“配方比例”的角色,决定每列货物放多少。

∑k=1nBkj\displaystyle \sum_{k=1}^{n} B_{kj}

3. A 的第 k 列:$A_{:k}$ 表示 A 矩阵的第 k 列,它是一整批原始货物。

A:k\displaystyle A_{:k}

4. 加权混合:把 A 的每一列按对应权重加起来,就得到结果的一列——这正是“分列汇总”的数学表达。

∑k=1nBkjA:k\displaystyle \sum_{k=1}^{n} B_{kj} A_{:k}

为什么一定要这样定义?因为如果有 y = Ax 和 x = Bz,那么把 x 代进 y 的表达式就得到 y = A(Bz) = (AB)z。换句话说,两次搬运可以合并成一次,而矩阵乘法恰好定义成满足这种“换元复合”的运算。逐元素相乘做不到这一点——这就是矩阵乘法与逐元素积之间最本质的区别。

几何意义

把矩阵想象成一台“变形机器”:平面上每个点都是一件货物,矩阵接到这个点后,按固定规则把它搬到新位置。规则是“新坐标的每个分量都是旧坐标的加权混合”,这正是线性变换。旋转、拉伸、翻转、错切,全是这种变形机器的工作模式。用物流的话说:矩阵就是“全场货物重新摆放”的说明书。

两台变形机器串联会发生什么?先让 B 机器变形,再让 A 机器接着变形,效果等价于一台更复杂的“合成机器”,它的说明书就是矩阵 AB。注意顺序要从右往左读:先乘在右的 B,再乘在左的 A。为什么 AB 和 BA 不同?先旋转再拉伸,和先拉伸再旋转,得到的形状当然不一样——方向感变了,几何上非常直观。

(cos⁡θ−sin⁡θsin⁡θcos⁡θ)(xy)=(xcos⁡θ−ysin⁡θxsin⁡θ+ycos⁡θ)\displaystyle \begin{pmatrix} \cos\theta & -\sin\theta \\ \sin\theta & \cos\theta \end{pmatrix} \begin{pmatrix} x \\ y \end{pmatrix} = \begin{pmatrix} x\cos\theta - y\sin\theta \\ x\sin\theta + y\cos\theta \end{pmatrix}

1. 旋转矩阵:第一行 $(\cos\theta, -\sin\theta)$ 和第二行 $(\sin\theta, \cos\theta)$ 共同定义了“逆时针转 θ 度”的搬运规则。

(cos⁡θ−sin⁡θsin⁡θcos⁡θ)\displaystyle \begin{pmatrix} \cos\theta & -\sin\theta \\ \sin\theta & \cos\theta \end{pmatrix}

2. 被移动的点:$\begin{pmatrix} x \\ y \end{pmatrix}$ 是平面上等待变形的点坐标,相当于一件待搬运的货物。

(xy)\displaystyle \begin{pmatrix} x \\ y \end{pmatrix}

3. 新坐标的 x 分量:$x\cos\theta - y\sin\theta$ 是旧坐标按规则混合出来的新横坐标。

xcos⁡θ−ysin⁡θ\displaystyle x\cos\theta - y\sin\theta

4. 新坐标的 y 分量:$x\sin\theta + y\cos\theta$ 是新的纵坐标。把 θ 换成 90°,代入 (1, 0) 就能验证它确实被转到了 (0, 1)。

xsin⁡θ+ycos⁡θ\displaystyle x\sin\theta + y\cos\theta

回到送货比喻:几何意义其实是“质量再分配”的另一种语言。每一行的混合系数,就是“把旧位置的货按比例挪到新位置”的搬运指令。深度学习里的权重矩阵也因此不再神秘——它们就是一台台把数据摆来摆去的变形机器。

运算性质

物流公司有三条交通规则。第一条是结合律:先让“工厂→中转仓→门店”跑一趟,再统一把货物送到总仓;或者先把“中转仓→门店→总仓”合成一条直达线,再让工厂按新线路发货。两种方案最终每家门店收到的货量完全一致——括号放在哪里,不影响结果。

第二条是分配律:两家供应商先各自到货再合起来盘点,和先把两家到货量加在一起再统一配送,结果一模一样。第三条也是最容易踩坑的:没有交换律。工厂发货给门店,和门店发货给工厂,是两套方向完全相反的物流网络,绝不能倒过来算。就算两个矩阵同尺寸,交换后通常也不相等。

(AB)C=A(BC),A(B+C)=AB+AC,AB≠BA\displaystyle (AB)C = A(BC), \qquad A(B+C) = AB + AC, \qquad AB \ne BA

1. 结合律:$(AB)C = A(BC)$ 表示乘法结果与“先算哪两个”无关,括号可以自由移动而不改变最终矩阵。

(AB)C=A(BC)\displaystyle (AB)C = A(BC)

2. 分配律:$A(B+C) = AB + AC$ 表示先把 B 和 C 并表相加,等于分别乘完再相加,账目对得上。

A(B+C)=AB+AC\displaystyle A(B+C) = AB + AC

3. 无交换律:$AB \ne BA$ 说明矩阵乘法一般不满足交换律。例如 $A=\begin{pmatrix}0&1\\0&0\end{pmatrix}$、$B=\begin{pmatrix}0&0\\1&0\end{pmatrix}$ 时,左右两边结果完全不同。

AB=(1000),BA=(0001)\displaystyle AB = \begin{pmatrix}1&0\\0&0\end{pmatrix}, \quad BA = \begin{pmatrix}0&0\\0&1\end{pmatrix}

三条规则里,结合律最“值钱”:它保证了无论怎么加括号,最终答案都一样。但注意——答案一样,不等于成本一样。不同括号方案下中间仓库需要的存储和运输量可能天差地别,这正是后面“高效实现”与“计算复杂度”两章的钥匙。

分块矩阵乘法

当物流网络太庞大时,公司会按区域划分管理:华东仓、华南仓各自核算,互不干扰。矩阵也一样,可以用横竖切割线把一个大矩阵切成若干小块,每一块本身仍是一个小矩阵。切完以后,把每个小块当成一个“数字”参与乘法运算——块内部再用普通矩阵乘法处理。

关键前提是切割线要对齐:A 的横向分块列数必须等于 B 的横向分块行数,就像中转仓数量必须前后一致。只要对齐了,分块乘法的结果与整体直接相乘完全一致——这不是近似近似,而是严格的数学定理。它告诉我们:表格怎么切不改变真实账目。

(A11A12A21A22)(B11B12B21B22)=(A11B11+A12B21A11B12+A12B22A21B11+A22B21A21B12+A22B22)\displaystyle \begin{pmatrix} A_{11} & A_{12} \\ A_{21} & A_{22} \end{pmatrix} \begin{pmatrix} B_{11} & B_{12} \\ B_{21} & B_{22} \end{pmatrix} = \begin{pmatrix} A_{11}B_{11} + A_{12}B_{21} & A_{11}B_{12} + A_{12}B_{22} \\ A_{21}B_{11} + A_{22}B_{21} & A_{21}B_{12} + A_{22}B_{22} \end{pmatrix}

1. 把 A 切四块:$A_{11}, A_{12}, A_{21}, A_{22}$ 是把 A 按横竖各切一刀得到的四块子矩阵。

(A11A12A21A22)\displaystyle \begin{pmatrix} A_{11} & A_{12} \\ A_{21} & A_{22} \end{pmatrix}

2. 块当元素相乘:$A_{11}B_{11} + A_{12}B_{21}$ 表示左上角结果块由两块子矩阵乘积相加得到。

A11B11+A12B21\displaystyle A_{11}B_{11} + A_{12}B_{21}

3. 对齐条件:要求 A 的分块列数与 B 的分块行数一致,即 $A_{11}$ 的列数等于 $B_{11}$ 的行数。

A11B11,A12B21\displaystyle A_{11}B_{11}, \quad A_{12}B_{21}

4. 拼回大矩阵:右下角结果块 $A_{21}B_{12} + A_{22}B_{22}$ 同理得到,四块拼回去就是完整乘积。

C21=A21B11+A22B21\displaystyle C_{21} = A_{21}B_{11} + A_{22}B_{21}

分块的意义在工程上极其巨大:GPU 可以把不同块分给不同计算核心同时处理,互不等待;深度学习里的 batch 操作本质上就是按批分块。物流分区管理,数学上完全等价,效率上却快出几个量级——这正是分块矩阵乘法的价值所在。

高效实现

结合律告诉我们“结果都一样”,那到底选哪种括号方案?答案是看成本。A 是 m×n、B 是 n×p 时,要算完整个乘积需要 m×n×p 次标量乘法——这是一个固定的“运输总里程”,由三个维度共同决定。n 越大(中转仓越多),成本涨得越凶。

对三个矩阵的链式乘法,选择更关键:X 是 100×10、Y 是 10×50、Z 是 50×5。先算 (XY),中间结果是 100×50,总成本 100×10×50 + 100×50×5 = 75000;先算 (YZ),中间结果是 10×5,总成本 10×50×5 + 100×10×5 = 7500。同样是三个矩阵相乘,成本差 10 倍——括号位置决定了中间结果的大小,也就决定了总运量。

cost(Am×nBn×p)=m⋅n⋅p\displaystyle \text{cost}(A_{m\times n} B_{n\times p}) = m \cdot n \cdot p

1. 外层行循环:$m$ 是结果矩阵的行数,每一行都要独立算一遍。

m\displaystyle m

2. 内层累加项:$n$ 是求和号里的项数,也就是内维的长度,每个结果元素都要累加 n 项。

n\displaystyle n

3. 外层列循环:$p$ 是结果矩阵的列数,每一列也都要独立算一遍。

p\displaystyle p

4. 总次数:$m \cdot n \cdot p$ 三者相乘就是标量乘法总次数,复杂度写作 $O(mnp)$。

m⋅n⋅p\displaystyle m \cdot n \cdot p

除了选括号,实现层面还有两个常用优化:循环顺序调整成 i→k→j 能保证内层访问连续内存,提高缓存命中率;GPU 上每个线程独立计算一个输出元素,天然可以大规模并行。回到物流比喻:挑对配送路线、装好货箱顺序,运输成本可能差 10 倍甚至更多——算法优化的精髓就在于此。

计算复杂度

两个 n×n 的方阵相乘,朴素算法要做 n³ 次标量乘法。n 每翻一倍,耗时涨 8 倍——这就是深度学习训练慢的根源之一:大模型的权重矩阵乘来乘去,底层全是 n³ 级别的成本。所以“怎么让矩阵乘法更快”一直是计算机科学的重要课题。

数学家们想尽办法降低指数。Strassen 算法是第一个大突破:把 2×2 分块乘法的 8 次乘法降为 7 次,用额外的加法换取乘法次数减少。每次递归都少一次乘法,规模越大省得越多,最终把指数从 3 压到约 2.807。

T(n)=7 T ⁣(n2)+O(n2)  ⟹  T(n)=O ⁣(nlog⁡27)≈O ⁣(n2.807)\displaystyle T(n) = 7\,T\!\left(\frac{n}{2}\right) + O(n^2) \;\Longrightarrow\; T(n) = O\!\left(n^{\log_2 7}\right) \approx O\!\left(n^{2.807}\right)

1. 递归关系:$T(n) = 7T(n/2) + O(n^2)$ 表示把 n 阶问题切成若干个 n/2 阶子问题,7 次子乘法加一次合并。

T(n)=7 T ⁣(n2)+O(n2)\displaystyle T(n) = 7\,T\!\left(\frac{n}{2}\right) + O(n^2)

2. 7 次子问题:$7T(n/2)$ 里的 7 来自 Strassen 精心构造的 7 个中间矩阵,比普通分块的 8 次少一次。

7 T ⁣(n2)\displaystyle 7\,T\!\left(\frac{n}{2}\right)

3. 加法换乘法:$O(n^2)$ 是拼出这 7 个中间矩阵所需的加法成本,加法比乘法便宜得多。

O(n2)\displaystyle O(n^2)

4. 解出复杂度:$O(n^{\log_2 7}) \approx O(n^{2.807})$,因为 $\log_2 7 \approx 2.807$,小于 3,n 越大优势越明显。

O ⁣(nlog⁡27)≈O ⁣(n2.807)\displaystyle O\!\left(n^{\log_2 7}\right) \approx O\!\left(n^{2.807}\right)

不过 Strassen 在工程上并不总是最优:常数因子偏大、数值稳定性略差,只有超大矩阵才划算。现代 BLAS 库(深度学习的底层引擎)会混合使用朴素循环、分块并行与 Strassen 变体。回到比喻:与其纠结每辆车的装法,不如在“分段运输”的整体结构上动刀——这就是计算复杂度分析的真正意义。

AI 应用场景

深度学习全连接层的前向传播

阶段:模型前向传播

解决的问题:神经网络每一层都在做矩阵乘法:输入数据组成矩阵 X,权重组成矩阵 W,输出就是 XW。如果对每个样本写循环逐个计算,速度极慢;把整个批次拼成一个大矩阵一次性相乘,才能利用 GPU 并行能力。这正是矩阵乘法规则最直接的应用。

具体案例:一个 batch 有 128 张 28×28 的图片,展平后是 X(128×784),与权重 W(784×256) 相乘,一次得到 128×256 的激活矩阵。若内维不匹配,程序立刻报错——就像中转仓数量对不上,物流网络直接瘫痪。

Transformer 注意力机制中的矩阵乘法

阶段:注意力计算

解决的问题:GPT 等大模型的每一层都要算 Q、K、V 三个矩阵:先算 QKᵀ 得到注意力分数,再乘 V 得到加权结果。这些全是矩阵乘法,其性能直接决定大模型生成速度。分块矩阵乘法和 GPU 并行是实现万亿级参数模型的关键。

具体案例:序列长度 2048、隐藏维 768 的一层 Transformer,QKᵀ 是一次 2048×768 乘 768×2048 的巨型矩阵乘法。工程师在 GPU 上按块切分计算,避免显存爆炸,这正是分块矩阵乘法思想在工业界的实战。

推荐系统的矩阵分解打分

阶段:离线训练与在线召回

解决的问题:用户对物品的评分矩阵极度稀疏,无法直接存储。矩阵分解把它拆成“用户隐向量”和“物品隐向量”,预测评分 = 用户向量 × 物品向量,本质上是一次 1×k 乘 k×1 的矩阵乘法。维度 k 就像是“中转仓”数量,决定表达能力的上限。

具体案例:某电商有 1 亿用户、1000 万商品,离线用矩阵分解训练出 k=64 的隐向量;线上打分时把向量乘法优化成高速内积计算,毫秒级完成 top 商品召回。

Python 演示

python45 行
def matrix_mult(A, B):    rows_a = len(A)    cols_a = len(A[0])    rows_b = len(B)    cols_b = len(B[0])    if cols_a != rows_b:        raise ValueError('A 的列数必须等于 B 的行数')    C = [[0] * cols_b for _ in range(rows_a)]    for i in range(rows_a):        for j in range(cols_b):            for k in range(cols_a):                C[i][j] += A[i][k] * B[k][j]    return C  def mul_cost(m, n, p):    return m * n * p  def main():    A = [[1, 0, 2], [3, 1, 0], [0, 2, 1]]    B = [[2, 1, 0], [1, 0, 3], [1, 2, 1]]    C = matrix_mult(A, B)    print('A × B =')    for row in C:        print(row)    assert C[0] == [4, 5, 2]    assert C[1] == [7, 3, 3]    assert C[2] == [3, 2, 7]     X = [[1, 2], [3, 4]]    Y = [[0, 1], [1, 0]]    Z = [[2, 0], [0, 2]]    left = matrix_mult(matrix_mult(X, Y), Z)    right = matrix_mult(X, matrix_mult(Y, Z))    assert left == right    print('结合律验证通过:(XY)Z == X(YZ)')     print('链式乘法成本对比(标量乘法次数):')    print('  (XY)Z 成本 =', mul_cost(100, 10, 50) + mul_cost(100, 50, 5))    print('  X(YZ) 成本 =', mul_cost(10, 50, 5) + mul_cost(100, 10, 5))  if __name__ == '__main__':    main()
目的:用纯 Python 三重循环实现矩阵乘法,验证手算结果、结合律,以及不同括号方案的标量乘法成本差异。
  1. if cols_a != rows_b:内维匹配检查,对应“中转仓数量必须对得上”,不匹配直接报错。
  2. C = [[0] * cols_b for _ in range(rows_a)]预分配结果矩阵,避免动态扩容开销。
  3. C[i][j] += A[i][k] * B[k][j]核心累加语句,逐项相乘再求和,就是整篇文章反复强调的动作。
  4. assert C[0] == [4, 5, 2]拿手算结果做单元测试,确保实现与数学定义一致。
  5. left = matrix_mult(matrix_mult(X, Y), Z)按 (XY)Z 的括号顺序计算。
  6. right = matrix_mult(X, matrix_mult(Y, Z))按 X(YZ) 的括号顺序计算。
  7. assert left == right验证结合律:结果相同,验证“括号不影响答案”。
  8. mul_cost(100, 10, 50) + mul_cost(100, 50, 5)计算 (XY)Z 的总成本,对比可看出成本差 10 倍。

常见误区

误区“我以为矩阵乘法就是把两个矩阵相同位置的数乘起来,像逐元素乘法那样,比如两个 2×2 矩阵就各自乘自己的四个数。”

正解那是哈达玛积(逐元素积),是另一种运算。真正意义的矩阵乘法是“行×列、逐项相乘再累加”。用物流比喻说,逐元素乘法只比较同一家工厂自己的进出账,矩阵乘法才是打通“工厂→中转仓→门店”的全程运输——两者目标完全不同。

为何常见:小学乘法都是两个数直接相乘,初学矩阵时很自然会把乘法推广成“对应位置相乘”,而忽略了矩阵乘法定义的深层动机是复合变换。

误区“我记得两个矩阵要一样大才能相乘,比如都是 3×3 才行,尺寸不同就是不能乘。”

正解正确条件只有一个:A 的列数等于 B 的行数(内维相等)。两个 3×3 能乘只是因为内维 3=3 碰巧成立;A(2×3) 乘 B(3×4) 完全合法,结果维度是 2×4。就像中转仓数量对得上,不管工厂和门店各多少家都能衔接。

为何常见:课本例题多是方阵相乘,加上“矩阵乘法要两个方阵”的误传,容易把“尺寸相同”错记成必要条件。

误区“结合律说 (AB)C = A(BC),结果都一样,所以先算哪边都一样,没什么区别。”

正解最终矩阵相同,但标量乘法次数可能差几十倍。100×10、10×50、50×5 的三矩阵例子中,(XY)Z 要 75000 次,X(YZ) 只要 7500 次,差整整 10 倍。结合律说的是“结果”不变,不是“成本”不变。

为何常见:只盯着等号两边的矩阵相等,忽视了过程中间结果的尺寸差异,这是初学者最容易忽略的维度。

误区“矩阵乘法跟数乘差不多,换个顺序顶多差个符号,通常还是可以交换的。”

正解矩阵乘法一般根本不能交换:A 是 2×3、B 是 3×2 时,AB 是 2×2,BA 是 3×3,连维度都对不上,无法比较。就算同为方阵,AB 和 BA 也通常不同。工厂发货给门店,和门店发货给工厂,是两套方向相反的物流网络。

为何常见:算术里乘法的交换律太根深蒂固,学习者容易把“数乘”的直觉错误迁移到“矩阵乘”上。

误区“分块矩阵乘法应该要求每个小块都是方阵吧,不然内部怎么对齐相乘?”

正解不要求块是方阵,只要求整体上 A 的分块列数等于 B 的分块行数。具体地,A 第 i 行分块的列宽要分别等于 B 第 i 行分块的行高,切割线必须对齐。块本身可以是任意长方形,只要对齐就能相乘。

为何常见:教材示意图常把矩阵切成 2×2 的方块,让人误以为分块等于“切成方阵”,忽略了分块的真正约束是对齐而非方形。

面试题

Q1. 两个矩阵 A(m×n) 与 B(p×q) 能够相乘的充要条件是?

单选题 · easy

  • A.A 的行数等于 B 的列数
  • B.A 的列数等于 B 的行数← 正确答案
  • C.A 的行数等于 B 的行数
  • D.A 的列数等于 B 的列数

答案:B。内维必须相等,即 A 的列数等于 B 的行数。用物流比喻,A 表中“中转仓”的编号必须和 B 表中“中转仓”的编号一一对应,这就像工厂发货给中转仓、中转仓再发货给门店,中转仓的数量必须对得上。

Q2. A 是 2×3 矩阵、B 是 3×4 矩阵,则 AB 的维度是?

单选题 · easy

  • A.2×4← 正确答案
  • B.3×3
  • C.4×2
  • D.3×4

答案:A。结果矩阵的行数取 A 的行数 2,列数取 B 的列数 4,所以是 2×4。就像直达表有 2 家工厂、4 家门店,中转仓的 3 只是中间的衔接维度,不体现在结果尺寸里。

Q3. 下列哪些维度组合的矩阵可以相乘?

多选题 · easy

  • A.2×3 乘 3×4← 正确答案
  • B.3×4 乘 2×3
  • C.4×3 乘 3×5← 正确答案
  • D.2×2 乘 3×3

答案:AC。能相乘的条件是第一个矩阵的列数等于第二个矩阵的行数。A 中 3=3,C 中 3=3,满足内维匹配;B 中 4≠2,D 中 2≠3,不满足。注意维度匹配和结果维度是两回事,别混淆。

Q4. 关于矩阵乘法交换律,下列说法正确的是?

单选题 · mid

  • A.矩阵乘法一般不满足交换律← 正确答案
  • B.任意矩阵都满足交换律
  • C.方阵一定满足交换律
  • D.只有零矩阵满足交换律

答案:A。矩阵乘法一般不满足交换律。即使 AB 和 BA 的维度都能对齐(比如两个方阵),结果也通常不同。方向相反的物流网络结果自然不同:先旋转再拉伸与先拉伸再旋转,最终形状不一样。

Q5. 结合律 (AB)C = A(BC) 的最直接推论是?

单选题 · mid

  • A.结果相同但计算量可能不同← 正确答案
  • B.计算量一定完全相同
  • C.乘法顺序可以任意交换
  • D.内维约束可以被忽略

答案:A。结合律保证最终矩阵相同,但不保证计算量相同。不同括号方案产生不同尺寸的中间矩阵,标量乘法次数可能差很多。就像配送方案重排不影响最终到货量,但运输成本完全不同。

Q6. 关于分块矩阵乘法,下列说法正确的是?

单选题 · mid

  • A.把块当作数参与普通矩阵乘法← 正确答案
  • B.对块进行逐元素相乘
  • C.分块必须是方阵才行
  • D.分块结果是近似计算

答案:A。分块矩阵乘法把每个子块当成一个“元素”,按普通矩阵乘法规则相乘、相加,结果是严格精确的。块不要求是方阵,只要切割线对齐即可;它比整体相乘更快只是因为可以利用并行计算。

Q7. X 是 100×10、Y 是 10×50、Z 是 50×5,最省计算量的结合方式是?

单选题 · hard

  • A.A(BC) 最省计算量← 正确答案
  • B.(AB)C 最省计算量
  • C.两种方式成本一样
  • D.两种方式都无法计算

答案:A。A(BC) 先算 YZ,中间矩阵只有 10×5,总成本 10×50×5 + 100×10×5 = 7500;(AB)C 先算 XY,中间矩阵是 100×50,总成本 100×10×50 + 100×50×5 = 75000。差 10 倍,所以括号位置决定效率。

Q8. 下列关于矩阵乘法运算性质的描述,正确的有?

多选题 · mid

  • A.满足结合律 (AB)C = A(BC)← 正确答案
  • B.满足分配律 A(B+C) = AB + AC← 正确答案
  • C.满足交换律 AB = BA
  • D.分块乘法的结果与整体一致← 正确答案

答案:ABD。结合律和分配律都是矩阵乘法的基本性质;分块乘法只要切割线对齐,结果与整体相乘严格一致。交换律一般不成立,这是矩阵乘法与普通数乘最重要的区别。

Q9. 影响链式矩阵乘法总计算量的因素包括?

多选题 · hard

  • A.各矩阵的维度← 正确答案
  • B.括号的结合位置← 正确答案
  • C.矩阵内元素的大小
  • D.矩阵是否方阵且形状规则

答案:AB。总计算量由各矩阵维度决定,不同的括号位置会形成不同尺寸的中间矩阵,从而改变总标量乘法次数。元素大小只影响数值精度,不影响运算次数;是否方阵也只是维度的一种特殊情况,不是独立因素。

Q10. Strassen 算法的递归式 T(n) = 7T(n/2) + O(n²) 的渐进复杂度是?

单选题 · extreme

  • A.复杂度约为 O(n^2.807)← 正确答案
  • B.复杂度约为 O(n^3)
  • C.复杂度约为 O(n^2)
  • D.复杂度约为 O(n log n)

答案:A。主定理给出 T(n) = O(n^(log₂7)),而 log₂7 ≈ 2.807,小于朴素算法的 3。Strassen 用 7 次子乘法替代 8 次,每次递归少一次乘法,规模越大节省越多,这是矩阵乘法历史上第一次突破 O(n³)。