目录

矩阵

1. 先回顾一下向量

你刚才已经掌握:

snippet.text
A = [1, 2, 3]

这是一个 3 维向量。

可以把它想成:

snippet.text
CPU   Memory   GPU
 ↓      ↓       ↓
 80     60      90

也就是:

snippet.text
A = [80, 60, 90]

一个对象的一组特征。


2. 那么矩阵是什么?

最简单的理解:

**矩阵就是把很多向量按照一定规则排在一起。**

例如:

snippet.text
A =
[
  1  2  3
  4  5  6
  7  8  9
]

这个矩阵有:

snippet.text
3 行
3 列

所以叫:

**3 × 3 矩阵**

—

3. 用你的测试工作理解矩阵

假设你测试了 4 台服务器:

Server CPU Memory GPU
——– –: —–: –:
Server A 80 60 90
Server B 70 50 80
Server C 90 70 95
Server D 50 40 60

可以变成:

snippet.text
X =
[
  80  60  90
  70  50  80
  90  70  95
  50  40  60
]

那么:

snippet.text
X.shape = 4 × 3

意思就是:

snippet.text
4 个对象
3 个特征

这其实已经非常接近机器学习中的真实数据了。


4. 矩阵的行和列分别是什么?

例如:

snippet.text
X =
[
  80  60  90
  70  50  80
  90  70  95
  50  40  60
]

第一行

snippet.text
[80,60,90]

代表:

Server A

### 第二行

snippet.text
[70,50,80]

代表:

Server B

而第一列:

snippet.text
80
70
90
50

代表:

CPU

第二列:

snippet.text
60
50
70
40

代表:

Memory

第三列:

snippet.text
90
80
95
60

代表:

GPU

所以可以记:

**行通常代表样本,列通常代表特征。**

当然这不是数学上的硬性规定,实际工程里可以根据数据组织方式不同而变化。


5. 矩阵的“形状”

这个概念以后你会天天遇到。

比如:

snippet.text
X =
[
  1 2 3
  4 5 6
]

它有:

snippet.text
2 行
3 列

所以:

snippet.text
shape = (2,3)

注意:

snippet.text
(行, 列)

所以:

snippet.text
(2,3)

不是:

snippet.text
3行2列

而是:

**2 行 3 列**

—

6. 为什么 AI 特别需要矩阵?

假设你有:

snippet.text
10000 个样本

每个样本:

snippet.text
100 个特征

如果每个样本都是一个向量:

snippet.text
x1
x2
x3
...
x10000

就可以把它们组成:

snippet.text
X

形状:

snippet.text
10000 × 100

于是整个数据集可以一次性交给 GPU:

snippet.text
CPU
 ↓
Tensor
 ↓
GPU
 ↓
矩阵运算

而不是:

snippet.text
for 每一个样本:
    一个一个算

这就是 AI 为什么喜欢批量计算。


7. 矩阵加法

这个非常简单。

假设:

snippet.text
A =
[
  1 2
  3 4
]
snippet.text
B =
[
  5 6
  7 8
]

那么:

snippet.text
A+B

就是对应位置相加:

snippet.text
[
  1+5   2+6
  3+7   4+8
]

得到:

snippet.text
[
  6  8
  10 12
]

注意:

**两个矩阵必须具有相同的形状,才能直接做矩阵加法。**

—

8. 矩阵乘法才是重点

这部分我们慢慢来。

假设:

snippet.text
A =
[
  1 2
  3 4
]
snippet.text
B =
[
  5 6
  7 8
]

计算:

snippet.text
A × B

很多人第一次会误以为:

snippet.text
[
  1×5  2×6
  3×7  4×8
]

这是:

snippet.text
[
  5  12
  21 32
]

但是这个结果不是矩阵乘法。


9. 矩阵乘法真正的规则

记住一句:

**左边矩阵的“行”,乘右边矩阵的“列”。**

还是:

snippet.text
A =
[
  1 2
  3 4
]
snippet.text
B =
[
  5 6
  7 8
]

先算结果左上角:

snippet.text
A[第一行] · B[第一列]

也就是:

snippet.text
[1,2] · [5,7]

刚才我们已经学过点积:

snippet.text
1×5 + 2×7

所以:

snippet.text
= 19

10. 再算右上角

A 第一行:

snippet.text
[1,2]

B 第二列:

snippet.text
[6,8]

点积:

snippet.text
1×6 + 2×8

得到:

snippet.text
22

所以结果第一行:

snippet.text
[19,22]

11. 再算第二行

A 第二行:

snippet.text
[3,4]

B 第一列:

snippet.text
[5,7]

点积:

snippet.text
3×5 + 4×7

得到:

snippet.text
43

然后:

snippet.text
[3,4] · [6,8]

得到:

snippet.text
3×6 + 4×8 = 50

所以最终:

snippet.text
A × B =
[
  19 22
  43 50
]

12. 现在你应该发现一个很重要的东西

矩阵乘法:

snippet.text
A × B

其实就是:

**大量的向量点积。**

也就是说:

snippet.text
矩阵乘法
    ↓
很多次点积
    ↓
很多次乘法 + 加法

这就开始和 GPU 联系起来了。


13. 为什么 GPU 特别擅长 AI?

刚才一个 2×2 矩阵,计算量很小。

但是如果:

snippet.text
A = 4096 × 4096
B = 4096 × 4096

那么需要做海量的:

snippet.text
乘法
+
加法

而 GPU 可以同时处理大量这些操作。

于是:

snippet.text
神经网络
 ↓
矩阵乘法
 ↓
大量乘加
 ↓
GPU
 ↓
Tensor Core

你作为测试工程师以后会经常看到:

snippet.text
FLOPS
TFLOPS
Matrix Multiplication
GEMM
Tensor Core

现在你已经知道它们背后的数学基础是什么了。


14. 一个非常重要的规则:维度必须匹配

假设:

snippet.text
A.shape = (2,3)

也就是:

snippet.text
A =
[
  1 2 3
  4 5 6
]

如果:

snippet.text
B.shape = (3,4)

那么:

snippet.text
A × B

是可以计算的。

因为:

snippet.text
(2 × 3)
×
(3 × 4)

中间两个:

snippet.text
3
3

匹配。

结果:

snippet.text
(2 × 4)

所以:

snippet.text
(2×3) × (3×4)
=
(2×4)

这个规则非常重要。


15. 记一个口诀

矩阵:

snippet.text
(m × n)

乘:

snippet.text
(n × p)

结果:

snippet.text
(m × p)

也就是:

snippet.text
(m × n) × (n × p)
          ↑
       中间必须相同

最终:

snippet.text
(m × p)

你以后看到 PyTorch:

snippet.python
A @ B

如果报:

snippet.text
mat1 and mat2 shapes cannot be multiplied

基本就是:

**矩阵维度对不上。**

—

16. 用神经网络理解矩阵乘法

假设一个神经网络有:

snippet.text
输入层:3 个特征
输出层:2 个神经元

输入:

snippet.text
X = [CPU, Memory, GPU]

比如:

snippet.text
X = [80,60,90]

模型有一个权重矩阵:

snippet.text
W =
[
  0.1  0.2
  0.3  0.4
  0.5  0.6
]

那么:

snippet.text
X × W

就是:

snippet.text
[80,60,90]
×
[
  0.1 0.2
  0.3 0.4
  0.5 0.6
]

得到两个输出:

snippet.text
Neuron 1
Neuron 2

所以你可以把神经网络的一层粗略理解成:

**输入向量 × 权重矩阵 → 输出向量**

也就是:

snippet.text
XW

这就是你以后会反复看到的:

snippet.text
Y = XW + b

17. 这就是“权重”到底是什么

以后你看到:

snippet.text
Model Parameters
Weights
Parameters

不要觉得玄学。

最简单的理解:

snippet.text
输入
 ↓
乘上一堆数字
 ↓
得到输出

这些“数字”就是:

**模型参数/权重。**

训练过程实际上就是:

**不断调整这些数字,让模型的预测越来越好。**

这就又和我们上一节说的:

snippet.text
Loss
 ↓
Gradient
 ↓
调整参数

连接起来了。


18. 到这里,把两节课串起来

你现在已经可以看到 AI 的一个基本骨架:

snippet.text
现实世界
   ↓
数字
   ↓
向量
   ↓
矩阵
   ↓
矩阵乘法
   ↓
神经网络
   ↓
预测
   ↓
Loss
   ↓
Gradient
   ↓
调整矩阵里的参数

这条链非常重要。


19. 再往前一步:转置

最后讲一个以后一定会遇到的概念:

**Transpose,转置。**

例如:

snippet.text
A =
[
  1 2 3
  4 5 6
]

这是:

snippet.text
2 × 3

转置之后:

snippet.text
Aᵀ =
[
  1 4
  2 5
  3 6
]

变成:

snippet.text
3 × 2

简单理解:

**行和列交换。**

所以:

snippet.text
(2×3)

转置:

snippet.text
(3×2)

20. 为什么转置很重要?

因为矩阵乘法经常需要调整维度。

例如:

snippet.text
Q × Kᵀ

你以后学 Attention 时一定会看到这个。

现在你已经知道:

snippet.text
Kᵀ

就是:

**把 K 的行列交换。**

所以以后看到:

snippet.text
QKᵀ

至少不会觉得像某种外星文明的符号。


21. 今天先到这里

你现在已经掌握了:

snippet.text
向量
 ↓
维度
 ↓
向量加减
 ↓
向量长度
 ↓
点积
 ↓
矩阵
 ↓
矩阵形状
 ↓
矩阵加法
 ↓
矩阵乘法
 ↓
矩阵维度匹配
 ↓
转置

其中最重要的是这三个:

① 点积

snippet.text
[a,b,c] · [x,y,z]
=
ax + by + cz

② 矩阵乘法

snippet.text
行 × 列

本质上就是:

snippet.text
很多个点积

③ 维度规则

snippet.text
(m×n) × (n×p)
=
(m×p)