2536c937e3
翻译自英文原版 maths-cs-ai-compendium,共 20 章全部完成。 第01章 向量 | 第02章 矩阵 | 第03章 微积分 第04章 统计学 | 第05章 概率论 | 第06章 机器学习 第07章 计算语言学 | 第08章 计算机视觉 | 第09章 音频与语音 第10章 多模态学习 | 第11章 自主系统 | 第12章 图神经网络 第13章 计算与操作系统 | 第14章 数据结构与算法 第15章 生产级软件工程 | 第16章 SIMD与GPU编程 第17章 AI推理 | 第18章 ML系统设计 第19章 应用人工智能 | 第20章 前沿人工智能 翻译说明: - 所有数学公式 $...$ / $$...$$、代码块、图片引用完整保留 - mkdocs.yml 配置中文导航 + language: zh - README.md 已翻译为中文(兼 docs/index.md) - docs/ 目录包含指向各章文件的 symlink - 约 29,000 行中文内容,排除 .cache/ 构建缓存
147 lines
6.7 KiB
Markdown
147 lines
6.7 KiB
Markdown
# 矩阵运算
|
||
|
||
*矩阵运算是深度学习的计算引擎。本文涵盖矩阵加法、标量乘法、矩阵-向量积、矩阵乘法、逐元素运算、Kronecker积和广播——支撑每一次前向传播和梯度更新的运算。*
|
||
|
||
- 矩阵可以像向量一样进行加法和缩放。
|
||
|
||
- 加法要求两个矩阵维度相同,然后逐元素相加:
|
||
|
||
```math
|
||
\begin{bmatrix} 1 & 2 \\ 3 & 4 \end{bmatrix} + \begin{bmatrix} 5 & 6 \\ 7 & 8 \end{bmatrix} = \begin{bmatrix} 6 & 8 \\ 10 & 12 \end{bmatrix}
|
||
```
|
||
|
||
- 标量乘法将每个元素乘以标量:
|
||
|
||
```math
|
||
3 \times \begin{bmatrix} 1 & 2 \\ 3 & 4 \end{bmatrix} = \begin{bmatrix} 3 & 6 \\ 9 & 12 \end{bmatrix}
|
||
```
|
||
|
||
- 矩阵能做的最简单的事情是乘以一个向量。**矩阵-向量乘法** $A\mathbf{x}$ 使用 $\mathbf{x}$ 的分量作为权重来组合 $A$ 的列:
|
||
|
||
```math
|
||
\begin{bmatrix} 1 & 2 \\ 3 & 4 \end{bmatrix} \begin{bmatrix} 5 \\ 6 \end{bmatrix} = 5 \begin{bmatrix} 1 \\ 3 \end{bmatrix} + 6 \begin{bmatrix} 2 \\ 4 \end{bmatrix} = \begin{bmatrix} 17 \\ 39 \end{bmatrix}
|
||
```
|
||
|
||
- 这是机器学习中的核心运算。每个神经网络层都计算 $A\mathbf{x} + \mathbf{b}$:矩阵乘以输入向量,再加上偏置。
|
||
|
||
- 一般情况是**矩阵乘法**。给定 $A$($m \times n$)和 $B$($n \times p$),乘积 $C = AB$ 是一个 $m \times p$ 矩阵,每个元素都是一个点积:
|
||
|
||
$$C_{ij} = \sum_{k=1}^{n} A_{ik} B_{kj}$$
|
||
|
||
- 结果中的每个条目都是 $A$ 的一行与 $B$ 的一列的点积。内部维度必须匹配($n$),结果取外部维度($m \times p$)。
|
||
|
||
- 另一种理解方式:结果的每一列都是 $A$ 的列的**加权和**,其中权重来自 $B$ 的对应列。
|
||
|
||
- 如果 $B$ 的某一列为 $[2, 3]^T$,则结果列就是 $2 \times (\text{A的第1列}) + 3 \times (\text{A的第2列})$。
|
||
|
||
- 一个有用的特例:矩阵与其转置相乘总是得到一个方阵。$AA^T$ 是 $m \times m$,$A^TA$ 是 $n \times n$:
|
||
|
||
```math
|
||
\begin{bmatrix} 1 & 2 & 3 \\ 4 & 5 & 6 \end{bmatrix} \begin{bmatrix} 1 & 4 \\ 2 & 5 \\ 3 & 6 \end{bmatrix} = \begin{bmatrix} 14 & 32 \\ 32 & 77 \end{bmatrix}
|
||
```
|
||
|
||
- 矩阵乘法有重要的运算规则:
|
||
|
||
- **不满足交换律**:通常 $AB \neq BA$。顺序很重要。
|
||
|
||
- **满足结合律**:$(AB)C = A(BC)$。你可以任意分组乘法。
|
||
|
||
- **满足分配律**:$A(B + C) = AB + AC$。
|
||
|
||
- **单位矩阵**:$AI = IA = A$。
|
||
|
||
- **Hadamard积**(逐元素乘积)将两个相同大小的矩阵逐项相乘,记作 $A \odot B$:
|
||
|
||
```math
|
||
\begin{bmatrix} 1 & 2 \\ 3 & 4 \end{bmatrix} \odot \begin{bmatrix} 5 & 6 \\ 7 & 8 \end{bmatrix} = \begin{bmatrix} 5 & 12 \\ 21 & 32 \end{bmatrix}
|
||
```
|
||
|
||
- 与标准矩阵乘法不同,Hadamard积满足交换律($A \odot B = B \odot A$),且要求两个矩阵维度相同。它在机器学习中广泛用于门控机制:通过与一个取值在0到1之间的掩码逐元素相乘,控制每个条目"通过"多少。
|
||
|
||
- 两个向量 $\mathbf{u}$ 和 $\mathbf{v}$ 的**外积**产生一个矩阵:$\mathbf{u}\mathbf{v}^T$。每个条目是 $\mathbf{u}$ 的一个元素与 $\mathbf{v}$ 的一个元素的乘积:
|
||
|
||
```math
|
||
\begin{bmatrix} 1 \\ 2 \\ 3 \end{bmatrix} \begin{bmatrix} 4 & 5 \end{bmatrix} = \begin{bmatrix} 4 & 5 \\ 8 & 10 \\ 12 & 15 \end{bmatrix}
|
||
```
|
||
|
||
- 结果总是秩为1,因为每一行都是 $\mathbf{v}^T$ 的缩放版本。任何矩阵都可以写成秩-1外积之和,这正是SVD所做的事情(见分解章节)。
|
||
|
||
- 矩阵乘法的计算开销很大。两个 $n \times n$ 矩阵相乘需要 $O(n^3)$ 次运算。对于一个 $1000 \times 1000$ 的矩阵,那就是十亿次乘法。
|
||
|
||
- 当矩阵是**稀疏的**(大部分为零)时,朴素的乘法会浪费时间乘以零。**压缩稀疏行(CSR)**格式只存储非零元素及其位置:
|
||
|
||
- **值**:按行顺序排列的非零条目
|
||
- **列索引**:每个值属于哪一列
|
||
- **行偏移**:每一行在值列表中的起始位置
|
||
|
||
- 例如,矩阵:
|
||
|
||
```math
|
||
A = \begin{bmatrix} 5 & 0 & 0 & 2 \\ 0 & 0 & 3 & 0 \\ 0 & 0 & 0 & -1 \end{bmatrix}
|
||
```
|
||
|
||
- 存储为:values = [5, 2, 3, -1], columns = [0, 3, 2, 3], row offsets = [0, 2, 3, 4]。这跳过了所有零,使稀疏运算快得多。
|
||
|
||
- 矩阵的一个核心用途是求解**线性方程组**。方程组 $A\mathbf{x} = \mathbf{b}$ 问的是:"什么向量 $\mathbf{x}$ 被 $A$ 变换后,会得到 $\mathbf{b}$?"
|
||
|
||
- 例如,假设你在买水果。苹果每个 $x_1$ 元,香蕉每个 $x_2$ 元。已知2个苹果和1个香蕉共5元,1个苹果和3个香蕉共10元。用矩阵形式表示:
|
||
|
||
```math
|
||
\begin{bmatrix} 2 & 1 \\ 1 & 3 \end{bmatrix} \begin{bmatrix} x_1 \\ x_2 \end{bmatrix} = \begin{bmatrix} 5 \\ 10 \end{bmatrix}
|
||
```
|
||
|
||
- 矩阵逐行乘以向量(每一行与 $[x_1, x_2]^T$ 点积)得到两个方程:
|
||
|
||
$$2x_1 + 1x_2 = 5 \qquad \text{(第1行)} \qquad \qquad x_1 + 3x_2 = 10 \qquad \text{(第2行)}$$
|
||
|
||
- 从第1行得 $x_2 = 5 - 2x_1$。代入第2行:$x_1 + 3(5 - 2x_1) = 10$,解得 $x_1 = 1$,则 $x_2 = 3$。苹果每个1元,香蕉每个3元。
|
||
|
||
- 验证——结果正确:
|
||
|
||
```math
|
||
\begin{bmatrix} 2 & 1 \\ 1 & 3 \end{bmatrix} \begin{bmatrix} 1 \\ 3 \end{bmatrix} = \begin{bmatrix} 2 + 3 \\ 1 + 9 \end{bmatrix} = \begin{bmatrix} 5 \\ 10 \end{bmatrix}
|
||
```
|
||
|
||
- 如果 $A$ 有逆矩阵,解就是简单的 $\mathbf{x} = A^{-1}\mathbf{b}$。但直接计算逆矩阵代价高昂且数值不稳定。实践中我们使用分解方法。
|
||
|
||
- 并非所有矩阵都是方阵,也不是所有方阵都可逆。**伪逆** $A^+$ 将逆推广到任意矩阵。它总是存在,并提供"尽可能好的"逆:
|
||
|
||
$$A^+ = (A^TA)^{-1}A^T$$
|
||
|
||
- 当 $A$ 是下三角矩阵时,通过**前向代入**求解 $L\mathbf{x} = \mathbf{b}$ 很容易:先解出 $x_1$,然后用它求出 $x_2$,依此类推。
|
||
|
||
- 当 $A$ 是上三角矩阵时,通过**回代**求解 $U\mathbf{x} = \mathbf{b}$:先解出最后一个变量,然后向上求解。
|
||
|
||
- 这就是为什么将矩阵分解为三角因子(如分解章节所述)如此有用——它将一个难题转化为两个简单问题。
|
||
|
||
## 编程练习(使用CoLab或Jupyter Notebook)
|
||
|
||
1. 将两个矩阵相乘并验证维度。然后交换顺序,观察结果如何变化(或者,如果维度不匹配,运算失败)。
|
||
|
||
```python
|
||
import jax.numpy as jnp
|
||
|
||
A = jnp.array([[1.0, 2.0],
|
||
[3.0, 4.0]])
|
||
B = jnp.array([[5.0, 6.0],
|
||
[7.0, 8.0]])
|
||
|
||
print(f"A @ B:\n{A @ B}")
|
||
print(f"B @ A:\n{B @ A}")
|
||
print(f"Equal: {jnp.allclose(A @ B, B @ A)}")
|
||
```
|
||
|
||
2. 求解线性方程组 $A\mathbf{x} = \mathbf{b}$,并通过回代乘法验证解。尝试改变 $\mathbf{b}$,观察解如何变化。
|
||
|
||
```python
|
||
import jax.numpy as jnp
|
||
|
||
A = jnp.array([[2.0, 1.0],
|
||
[5.0, 3.0]])
|
||
b = jnp.array([4.0, 7.0])
|
||
|
||
x = jnp.linalg.solve(A, b)
|
||
print(f"Solution x: {x}")
|
||
print(f"A @ x: {A @ x}")
|
||
```
|