矩阵运算¶
一句话总结:矩阵加法、标量乘法、矩阵-向量乘、矩阵乘法、Hadamard 积、外积、Kronecker 积与广播——深度学习每一次前向与反向的计算引擎。
矩阵运算是深度学习的计算引擎。 本节覆盖矩阵加法、标量乘法、矩阵-向量积、矩阵乘法、逐元素运算、Kronecker 积以及广播——每一次前向传播和梯度更新背后的操作.
-
矩阵可以像向量一样做加法与缩放。
-
加法要求两个矩阵维度相同,然后逐元素相加:
- 标量乘法就是把每个元素乘以那个标量:
- 对矩阵能做的最简单的事,就是拿它去乘一个向量。 矩阵-向量乘法 (matrix-vector multiplication) \(A\mathbf{x}\) 把 \(A\) 的各列按 \(\mathbf{x}\) 的各分量作为权重线性组合起来:
-
这是机器学习里的核心操作。 每一层神经网络算的都是 \(A\mathbf{x} + \mathbf{b}\):矩阵乘输入向量,再加一个偏置。
-
更一般的情况就是矩阵乘法 (matrix multiplication). 给定 \(A\) (\(m \times n\)) 和 \(B\) (\(n \times p\)),乘积 \(C = AB\) 是一个 \(m \times p\) 矩阵,每个元素都是一个点积:
-
结果矩阵里每一项,都是 \(A\) 的某一行与 \(B\) 的某一列的点积。 内部维度必须匹配 (\(n\)),结果保留外部维度 (\(m \times p\)).
-
换个角度看:结果的每一列都是 \(A\) 各列的加权和 (weighted sum),权重来自 \(B\) 对应的那一列。
-
如果 \(B\) 有一列是 \([2, 3]^T\),那么结果对应那一列就是 \(2 \times (A \text{ 的第 1 列}) + 3 \times (A \text{ 的第 2 列})\).
-
有个实用的特例:矩阵乘它自己的转置,结果一定是方阵。 \(AA^T\) 是 \(m \times m\), \(A^TA\) 是 \(n \times n\):
-
矩阵乘法有几条重要规则:
-
不满足交换律:一般情况下 \(AB \neq BA\). 顺序有讲究。
-
满足结合律: \((AB)C = A(BC)\). 你想怎么分组都行。
-
满足分配律: \(A(B + C) = AB + AC\).
-
单位元: \(AI = IA = A\).
-
-
Hadamard 积 (逐元素乘) 把两个同尺寸的矩阵对应位置相乘,记作 \(A \odot B\):
-
和标准矩阵乘法不同,Hadamard 积满足交换律 (\(A \odot B = B \odot A\)),但要求两个矩阵尺寸完全相同。 它在机器学习里被大量用于门控 (gating):用一个取值在 0 和 1 之间的掩码逐元素相乘,就能控制每个元素"通过多少".
-
两个向量 \(\mathbf{u}\) 和 \(\mathbf{v}\) 的外积 (outer product) 会产生一个矩阵:\(\mathbf{u}\mathbf{v}^T\). 每一项都是 \(\mathbf{u}\) 的一个分量乘 \(\mathbf{v}\) 的一个分量:
-
结果的秩始终是 1,因为每一行都是 \(\mathbf{v}^T\) 的缩放版本。 任何矩阵都可以写成若干个秩 1 外积的和——奇异值分解 (Singular Value Decomposition, SVD) 做的正是这件事 (在分解那一节会讲到).
-
矩阵乘法计算开销很大。 两个 \(n \times n\) 矩阵相乘要做 \(O(n^3)\) 次运算。 \(1000 \times 1000\) 的矩阵就是十亿次乘法。
-
当矩阵是稀疏 (sparse) 的 (大部分是零) 时,朴素乘法会浪费时间在乘零上。 压缩稀疏行 (Compressed Sparse Row, CSR) 格式只存非零元素,外加它们的位置信息:
- 值 (values):按行顺序排列的非零元素
- 列索引 (column indices):每个值属于哪一列
- 行偏移 (row offsets):每一行在值列表里的起始位置
-
举个例子,下面这个矩阵:
-
存成:values = [5, 2, 3, -1], columns = [0, 3, 2, 3], row offsets = [0, 2, 3, 4]. 这样就跳过了所有零,稀疏运算快很多。
-
矩阵的一大核心用途是求解线性方程组 (systems of linear equations). 方程组 \(A\mathbf{x} = \mathbf{b}\) 问的是:"哪个向量 \(\mathbf{x}\),被 \(A\) 变换之后能得到 \(\mathbf{b}\)?"
-
举个例子,假设你去买水果。 每个苹果 \(x_1\) 元,每根香蕉 \(x_2\) 元。 你知道 2 个苹果加 1 根香蕉是 $5, 1 个苹果加 3 根香蕉是 $10. 写成矩阵形式:
- 用矩阵逐行乘向量 (每一行与 \([x_1, x_2]^T\) 做点积),就得到两个方程:
-
由第 1 行得 \(x_2 = 5 - 2x_1\). 代入第 2 行:\(x_1 + 3(5 - 2x_1) = 10\),得到 \(x_1 = 1\),再得 \(x_2 = 3\). 苹果 $1, 香蕉 $3.
-
验证一下——完全对得上:
-
如果 \(A\) 有逆矩阵,解就是 \(\mathbf{x} = A^{-1}\mathbf{b}\). 但直接求逆开销大,数值上也不稳定。 实践里我们用分解代替。
-
不是每个矩阵都是方阵,也不是每个方阵都可逆。 伪逆 (pseudo-inverse) \(A^+\) 把逆的概念推广到任意矩阵。 它总是存在,并给出"尽可能好"的那个逆:
-
当 \(A\) 是下三角矩阵时,解 \(L\mathbf{x} = \mathbf{b}\) 用前向代入 (forward substitution) 很简单:先解出 \(x_1\),再用它去求 \(x_2\),一路往下。
-
当 \(A\) 是上三角矩阵时,解 \(U\mathbf{x} = \mathbf{b}\) 就用回代 (back substitution):先解最后一个变量,再往上推。
-
这就是为什么把矩阵分解成三角因子 (在分解那一节会看到) 这么有用。 它把一个难题变成两个易题。
Coding Tasks (use CoLab or notebook)¶
-
Multiply two matrices and verify the dimensions. Then swap the order and observe that the result changes (or that it fails if dimensions don't match).
-
Solve a system of linear equations \(A\mathbf{x} = \mathbf{b}\) and verify the solution by multiplying back. Try changing \(\mathbf{b}\) to see how the solution shifts.
📌 本节要点¶
- 加法与标量乘:同尺寸矩阵逐元素相加,标量乘法把每个元素乘以标量。
- 矩阵-向量乘法: \(A\mathbf{x}\) 把 \(A\) 各列按 \(\mathbf{x}\) 分量线性组合,是神经网络层 \(A\mathbf{x} + \mathbf{b}\) 的核心。
- 矩阵乘法:内部维度必须相配,结果 \((m \times p)\) 每项是行点积;不满足交换律,但满足结合律与分配律。
- Hadamard 积:同尺寸矩阵逐元素相乘 \(A \odot B\),交换律成立,ML 里用于门控。
- 外积: \(\mathbf{u}\mathbf{v}^T\) 产生秩 1 矩阵,是 SVD 分解的基本积木。
- 计算复杂度:两个 \(n \times n\) 矩阵相乘 \(O(n^3)\),稀疏矩阵用 CSR 格式跳过零元素。
- 线性方程组: \(A\mathbf{x} = \mathbf{b}\) 求"什么向量经 \(A\) 变换后得到 \(\mathbf{b}\)";直接求逆昂贵且不稳,实际用分解。
- 伪逆: \(A^+ = (A^TA)^{-1}A^T\) 把逆推广到任意矩阵,总是存在。
- 三角矩阵求解:下三角用前向代入,上三角用回代——把难题化为两个易题,是矩阵分解威力所在。