在上一篇文章中,我们精读了 Transformer 原论文 Attention Is All You Need。Transformer 的核心思想是:不再使用 RNN 或 CNN,而是完全基于 Attention 机制构建序列建模结构。原论文提出的 Transformer 由 Encoder 和 Decoder 组成,其中最关键的模块就是 Scaled Dot-Product Attention 和 Multi-Head Attention。论文摘要中也明确指出,Transformer 是一种完全基于 attention mechanism 的网络结构,去掉了 recurrence 和 convolution,并且更容易并行训练。
一、Self-Attention 要解决什么问题?
在自然语言中,一个词的含义往往不能只看它自己,而要看上下文。
例如下面这句话:苹果发布了新的芯片,性能提升非常明显。这里的"苹果"不是水果,而是公司。
再看另一个句子:我买了一个苹果,吃起来很甜。这里的"苹果"才是水果。
同一个词,在不同上下文中含义不同。
所以语言模型必须解决一个问题:当前 token 应该根据上下文中的哪些 token 来更新自己的表示?Self-Attention 的作用就是让每个 token 都可以主动去"查看"序列中的其他 token,并根据相关程度聚合信息。
简单来说:Self-Attention = 让序列内部的 token 彼此交流信息
假设有一句话:小明 因为 考试 没考好 所以 他 很难过
模型在处理"他"这个 token 时,需要知道"他"指的是"小明"。如果是 RNN,这个信息需要从"小明"一步一步传递到"他"。而 Self-Attention 可以让"他"直接关注"小明"。
这就是 Self-Attention 的直观意义:不再依赖顺序递推,而是让任意 token 之间直接建立联系。
二、从一个句子开始理解 Self-Attention
假设输入句子是:我 喜欢 机器 学习,分词后有 4 个 token:
x1 = 我
x2 = 喜欢
x3 = 机器
x4 = 学习
经过 embedding 层后,每个 token 会变成一个向量:
这些向量可以组成一个矩阵:
假设每个 token 的 embedding 维度是 ,序列长度是 n,那么:
其中:
- n是 token 数量;
是每个 token 向量的维度。
Self-Attention 要做的事情是:根据所有 token 之间的关系,为每个 token 生成一个新的上下文表示。也就是说,原来的 token 表示只包含自身信息,而经过 Self-Attention 后,每个 token 的表示都会融合其他 token 的信息。
三、为什么需要 Q、K、V?
Self-Attention 中最核心的三个概念是:
Q:Query
K:Key
V:Value
中文通常翻译为:
Query:查询
Key:键
Value:值
这三个词看起来有点抽象,可以先用一个生活化例子理解。假设你去图书馆找书。
你的需求是:我想找一本关于深度学习的书。这个需求就像 Query。图书馆中每本书都有一些标签,例如:
机器学习
深度学习
计算机视觉
自然语言处理
数学基础
这些标签就像 Key。每本书的实际内容就是 Value。你找书的过程可以理解为:
用 Query 去匹配每本书的 Key
找到最相关的书
读取这些书的 Value
对应到 Self-Attention 中:
Query:当前 token 想找什么信息
Key:每个 token 能提供什么匹配信号
Value:每个 token 真正携带的内容信息
所以 Q、K、V 的直观含义是:
| 符号 | 含义 | 直观理解 |
|---|---|---|
| Q | Query | 我想找什么 |
| K | Key | 我有什么特征可供匹配 |
| V | Value | 我真正要提供什么信息 |
注意,这只是帮助理解的比喻。在模型中,Q、K、V 并不是人工定义的,而是通过训练自动学出来的向量表示。
四、Q、K、V 是怎么生成的?
输入矩阵为:
Self-Attention 会通过三个不同的线性变换,把 XXX 映射成 Q、K、V:
其中:
是 Query 投影矩阵;
是 Key 投影矩阵;
是 Value 投影矩阵;
- 这些矩阵都是模型训练过程中学习得到的参数。
假设:
那么:
可以看到,Q、K、V 都来自同一个输入 X,只是经过了不同的线性映射。这也是为什么叫 Self-Attention。如果 Q 来自 Decoder,K 和 V 来自 Encoder,那就不是 Self-Attention,而是 Cross-Attention。
五、为什么不直接用 X,而要变成 Q、K、V?
这是一个很重要的问题。既然每个 token 已经有 embedding 表示 X,为什么还要额外生成 Q、K、V?原因是:同一个 token 在不同角色下需要表达不同信息。
例如句子:
小明 因为 考试 没考好 所以 他 很难过
对于"小明"这个 token 来说,它可能需要同时承担多种角色:
作为 Query:它想从其他词中查找什么信息?
作为 Key:它如何被其他词识别和匹配?
作为 Value:它被别人关注时,应该提供什么内容?
这三种角色不一定相同。如果只用一个向量表示所有角色,表达能力会受限。通过三个不同的投影矩阵,模型可以学习:
用 Q 表达"查询需求"
用 K 表达"匹配特征"
用 V 表达"内容信息"
所以,Q、K、V 的本质是:同一个 token 在注意力计算中的三种不同角色表示。
六、为什么要计算
?
生成 Q 和 K 后,下一步是计算:
假设:
那么:
这个矩阵表示什么?它表示序列中每个 token 对其他 token 的相关性分数。设:
那么:
其中:
是第 i 个 token 的 Query 向量;
是第 j 个 token 的 Key 向量;
表示第 i 个 token 对第 j 个 token 的注意力打分。
通俗地说:
第 i 个 token 拿着自己的 Query
去和第 j 个 token 的 Key 做匹配
匹配程度越高,说明第 i 个 token 越应该关注第 j 个 token
例如:
小明 因为 考试 没考好 所以 他 很难过
当模型处理"他"时,"他"的 Query 可能会和"小明"的 Key 得到较高分数。
也就是说:"他"应该重点关注"小明"
七、注意力矩阵是什么?
计算完后,我们会得到一个 n×n 的分数矩阵。假设句子有 4 个 token:我 喜欢 机器 学习
那么注意力打分矩阵大致是:
| 我 | 喜欢 | 机器 | 学习 | |
|---|---|---|---|---|
| 我 | s11 | s12 | s13 | s14 |
| 喜欢 | s21 | s22 | s23 | s24 |
| 机器 | s31 | s32 | s33 | s34 |
| 学习 | s41 | s42 | s43 | s44 |
其中第 i 行表示:第 i 个 token 对所有 token 的关注分数
例如"学习"这一行表示:
学习 对 我 的关注分数
学习 对 喜欢 的关注分数
学习 对 机器 的关注分数
学习 对 学习 的关注分数
如果"学习"和"机器"关系很强,那么:可能较大。因为"机器学习"是一个整体短语。注意力矩阵的作用就是告诉模型:每个 token 应该从哪些 token 中获取信息,以及获取多少信息。
八、为什么要除以
?
Transformer 原论文中的 Scaled Dot-Product Attention 公式是:
其中有一个缩放项:
为什么需要除以它?因为 Q 和 K 的点积会随着维度 增大而变大。假设
和
的每一维都是均值为 0、方差为 1 的随机变量,那么它们的点积:
会随着 增大而方差变大。如果点积数值太大,Softmax 会变得非常尖锐。
直观理解:
缩放因子的作用是防止点积结果过大,使 Softmax 更稳定。
九、Softmax 在 Attention 中做了什么?
缩放之后,下一步是 Softmax:
这个矩阵 AAA 就是注意力权重矩阵。Softmax 会对每一行进行归一化,使每一行的权重和为 1。
也就是说:
表示第 i个 token 对第 j个 token 的注意力权重。例如对于"他"这个 token,Softmax 后可能得到:
| token | 注意力权重 |
|---|---|
| 小明 | 0.60 |
| 因为 | 0.05 |
| 考试 | 0.10 |
| 没考好 | 0.10 |
| 所以 | 0.05 |
| 他 | 0.05 |
| 很难过 | 0.05 |
这表示模型在更新"他"的表示时,主要从"小明"那里获取信息。所以 Softmax 的作用是:把相关性分数转换成可用于加权求和的注意力分布。
十、为什么最后要乘以 V?
Attention 的最后一步是:
AV
其中:
A 是注意力权重矩阵;
V 是 Value 矩阵。
对于第 i 个 token,它的新表示为:
这表示:第 i 个 token 的新表示,是所有 token 的 Value 按注意力权重加权求和得到的。
还是用"他"这个例子:如果"他"对"小明"的注意力权重很高,那么"他"的新表示中会融合很多来自"小明"的信息。
也就是说:
原来的"他":只知道自己是一个代词
更新后的"他":知道自己很可能指代"小明"
这就是 Self-Attention 的真正作用:每个 token 根据上下文重新构造自己的表示。所以完整过程可以总结为:
Q 和 K 用来算"关注谁"
Softmax 得到"关注多少"
V 提供"真正被聚合的信息"
十一、Self-Attention 和普通 Attention 有什么区别?
在上一篇文章中,我们提到早期 Seq2Seq 中也有 Attention。那么 Self-Attention 和普通 Attention 有什么区别?
1. Seq2Seq Attention
在早期机器翻译模型中,Attention 通常发生在 Decoder 和 Encoder 之间。也就是说:
Decoder 当前状态作为 Query
Encoder 输出作为 Key 和 Value
这种 Attention 的作用是:Decoder 在生成目标词时,关注源句子中的不同位置。
例如生成中文"机器"时,关注英文 "machine"。
2. Self-Attention
Self-Attention 中:Q、K、V 都来自同一个序列
它的作用是:序列内部的 token 互相关注,更新自身表示。例如在中文句子中,"他"关注"小明","学习"关注"机器"。
3. Cross-Attention
后来在 Encoder-Decoder Transformer 中,还有 Cross-Attention。
它的形式是:
Q 来自 Decoder
K、V 来自 Encoder
所以三者区别可以总结为:
| 类型 | Q 来源 | K/V 来源 | 作用 |
|---|---|---|---|
| Self-Attention | 当前序列 | 当前序列 | 序列内部 token 互相建模 |
| Cross-Attention | Decoder | Encoder | Decoder 关注 Encoder 输出 |
| Seq2Seq Attention | Decoder 状态 | Encoder 状态 | 生成时动态对齐源序列 |