一句话总结:Attention 用学出来的 Q、K 点积给位置之间打匹配分,再经过缩放、mask 和 Softmax 变成权重,最后按这些权重混合 V。
9.1 回顾:我们已经知道什么
在进入 Attention 之前,让我们回顾一下前面学到的内容:
| 章节 | 学到的概念 | 核心作用 |
|---|---|---|
| 第4章 | Tokenization + Embedding | 文字 → Token ID → 向量 |
| 第5章 | Positional Encoding | 给向量添加位置信息 |
| 第6章 | LayerNorm + Softmax | 稳定表示 + 把分数归一化成权重 |
| 第7章 | 神经网络层(FFN) | 逐 token 做非线性变换 |
| 第8章 | 线性变换 | 矩阵乘法批量算点积;点积可从夹角和投影理解 |
现在,我们终于要进入 Transformer 最核心的部分:Attention(注意力机制)。
9.2 Attention 在架构中的位置
看这张图,左边是一个完整的 Transformer Block,右边把 Multi-Head Attention 里的一个注意力头展开。
9.2.1 Transformer Block 的结构
图左画的是一个 GPT-2 风格的 Pre-Norm Block。不同模型会调整 Norm 类型、顺序和并行方式,但两个主要子层仍然是 Attention 与 FFN:
输入
↓
Layer Norm
↓
Masked Multi-Head Attention ← 这就是我们要学的!
↓
残差连接
↓
Layer Norm
↓
Feed Forward(FFN)
↓
残差连接
↓
输出
在这类 Block 里,Attention 是第一个主要子层,负责让不同位置的信息直接混合。一次 Attention 并不等于模型已经“理解”了词与词的全部关系。
9.2.2 Attention 的内部流程
右边的绿色框展示了 Scaled Dot-Product Attention 的完整流程:
输入 X
↓
生成 Q, K, V(通过 W_Q, W_K, W_V 三个权重矩阵)
↓
MatMul(Q @ K^T,计算匹配分数)
↓
Scale(除以 √d_k,缩放)
↓
Mask(Decoder 常用 causal mask;也可能有 padding 等 mask)
↓
Softmax(逐行变成总和为 1 的权重)
↓
MatMul(与 V 相乘,加权求和)
↓
Concatenate(多头合并)
↓
W_O(多头合并后的输出投影)
↓
输出
这一章,我们先建立 Attention 的几何直觉,理解为什么要用点积。下一章再详细讲 Q、K、V 是什么。
9.3 为什么需要 Attention?
9.3.1 语言理解的核心问题
考虑这个句子:
"小沈阳江西演唱会邀请了,"
当模型要预测下一个词时,它需要理解:
- "邀请了"后面应该跟什么?
- 是"谁"被邀请?还是"邀请了谁"?
- "小沈阳"和"邀请"有什么关系?
- "江西演唱会"是地点还是事件?
每个词的含义,都依赖于它和其他词的关系。
9.3.2 传统方法的局限
在 Transformer 之前,处理序列的主流方法是 RNN(循环神经网络):
词1 → 词2 → 词3 → 词4 → 词5 → ...
↘ ↘ ↘ ↘
隐状态传递
RNN 的问题:
- 顺序处理:必须一个词一个词地处理,无法并行
- 长距离依赖:信息在传递过程中会衰减,很难记住很远的词
- 计算效率低:序列越长,计算时间越长
9.3.3 Attention 的解决方案
Attention 的核心思想是:把位置之间的路径变短。双向 Attention 可以直接看所有位置;GPT 这样的 causal Attention 只能看自己和前面的位置。
词1 词2 词3 词4 词5
词1 ↔ ↔ ↔ ↔ ↔
词2 ↔ ↔ ↔ ↔ ↔
词3 ↔ ↔ ↔ ↔ ↔
词4 ↔ ↔ ↔ ↔ ↔
词5 ↔ ↔ ↔ ↔ ↔
允许连接的位置不需要经过一串中间隐藏状态:在计算图里,一个位置到另一个位置只隔着一次 Attention。
这就像一个班级讨论:
- RNN 模式:传话游戏,信息从第一个人传到最后一个人
- Attention 模式:圆桌会议;如果是 causal 模式,后发言的人能听见先发言的人,先发言的人不能偷听未来
这条直接路径让长距离信息更容易流动,但不保证模型一定会使用远处信息,也不代表距离影响完全消失。
9.4 点积:计算匹配分数的工具
9.4.1 回顾第8章的核心结论
在第8章,我们学到了点积的几何意义:
Q · K = |Q| × |K| × cos(θ)
点积同时受方向和长度影响。Attention 把它当作学出来的匹配分数,而不是纯余弦相似度。
这正是 Attention 需要的!
9.4.2 用点积找"相关的词"
下面手工造几个 3 维玩具向量,只演示怎么算分。真实 Attention 会先把输入分别投影成 Q 和 K:
小 = [0.2, 0.8, 0.3, ...]
沈 = [0.3, 0.7, 0.4, ...]
阳 = [0.1, 0.9, 0.2, ...]
邀请 = [0.8, 0.2, 0.7, ...]
把“邀请”的玩具 Query 分别和几个玩具 Key 做点积:
邀请 · 小 = 0.8×0.2 + 0.2×0.8 + 0.7×0.3 = 0.53
邀请 · 沈 = 0.8×0.3 + 0.2×0.7 + 0.7×0.4 = 0.66
邀请 · 阳 = 0.8×0.1 + 0.2×0.9 + 0.7×0.2 = 0.40
在这组手工数字里,分数排序是“沈”(0.66)、“小”(0.53)、“阳”(0.40)。这不是某个真实模型的测量,也不能证明“沈”在语言上比“小沈阳”其他字符更相关;真实的 W_Q、W_K 会在训练中学习怎样打分。
9.4.3 矩阵乘法:批量计算所有匹配分数
如果要计算所有 Query-Key 对的分数,一个个算太慢了。
用矩阵乘法,一次搞定!
Q [n, d_k] @ Kᵀ [d_k, n] = 分数矩阵 [n, n]
结果是一个 n×n 矩阵,其中 (i,j) 表示第 i 个 Query 对第 j 个 Key 的原始匹配分数。
9.5 Attention 热力图:可视化理解
9.5.1 从分数到权重矩阵
这张教学图展示的是 QKᵀ / √d_k + M 经过 Softmax 之后的权重矩阵,不是原始 QKᵀ。8 个位置会得到一个 8×8 矩阵,每一行总和为 1。
图里的 8 个字符只是为了讲清楚行列和 causal mask,不是某个真实模型某一层的测量结果。
9.5.2 如何解读热力图
- 横轴(列):Key,表示“被读取的位置”
- 纵轴(行):Query,表示“正在读取的位置”
- 颜色深浅:表示 Softmax 后的注意力权重
- 黄色(亮)= 这一行里权重相对高
- 深蓝色(暗)= 权重低;带斜线的未来区域被 mask 后权重为 0
9.5.3 从热力图中能看出什么
你可能看到这些图案:
-
对角线有时较亮:当前位置允许读自己,但并不是每个 head 都会强烈关注自己
-
对角线下方出现亮点:某个 Query 给较早的 Key 更高权重
-
上三角带斜线:causal mask 禁止当前位置读取未来,权重正好为 0
核心洞察:每一行是一组归一化权重,告诉这一层、这个 head、这个输入下,Value 向量怎样被混合。它不是“语义相关性的真值百分比”。
9.5.4 这就是"注意力"的含义
热力图很适合建立直觉和调试,但不能单独解释模型为什么得到某个输出。一张图只对应一个输入、一个层、一个 head;残差流、其他 heads、FFN 和后续层都还会继续改变表示。研究也表明,不同注意力分布可能产生相同预测,所以不要把“亮格子”直接当成完整因果解释。
9.6 从匹配分数到注意力权重
9.6.1 问题:原始点积的值范围不确定
直接用点积有一个问题:结果的范围不固定。
点积结果:[3.5, -2.1, 8.7, 0.3, ...]
这些数字:
- 可正可负
- 大小不一
- 无法直接解释为"百分比"
9.6.2 解决方案:Softmax
还记得第6章的 Softmax 吗?它可以把任意数字变成非负、总和为 1 的归一化权重!
Softmax([3.5, -2.1, 8.7, 0.3]) ≈ [0.0055, 0.0000, 0.9943, 0.0002]
现在结果变成了:
- 每个值都在 0-1 之间
- 所有值加起来 = 1(100%)
- 可以作为这一行混合 Value 的归一化权重
9.6.3 Scale:为什么要除以 √d
在 Softmax 之前,还有一个 Scale(缩放) 步骤:
Attention(Q, K, V) = softmax(QK^T / √d_k + M) × V
为什么要除以 √d_k?
原因:防止点积结果太大
原始 Transformer 给出的直觉是:如果 Q、K 的各维独立、均值 0、方差 1,那么点积由 d_k 项相加,方差约为 d_k,标准差约为 √d_k。
不缩放时,维度越大,logit 的典型幅度越大,Softmax 越容易进入很尖锐、梯度很小的区域:
- 最大值接近 1
- 其他值接近 0
- 梯度消失,难以训练
除以 √d_k(比如 √512 ≈ 22.6)把这个典型尺度拉回同一量级。它不是把 Q、K 变成单位向量,也不是余弦归一化。
9.7 完整的 Attention 公式
9.7.1 公式
9.7.2 拆解理解
让我们一步步理解这个公式:
第一步:Q @ K^T
- 计算 Query 和 Key 的原始匹配分数
- 结果是一个 [seq_len, seq_len] 的矩阵
- 每个位置
(i,j)表示:第i个 Query 与第j个 Key 的点积分数
第二步:/ √d_k
- 缩放,防止数值太大
d_k是每个 Key 向量的维度
第三步:+ M,再做 Softmax
M把未来位置或 padding 位置设为负无穷- Softmax 把每一行变成归一化权重
- 每一行加起来等于 1
第四步:× V
- 用注意力权重对 Value 进行加权求和
- 结果是"根据注意力分配重新组合"的新表示
9.7.3 一个直观的类比
想象你在图书馆找书:
- Query(Q):你心里想找的内容("我想找关于机器学习的书")
- Key(K):每本书的标签/关键词("Python", "机器学习", "烹饪", ...)
- 匹配分数(Q @ Kᵀ):你的需求和每本书标签的匹配程度
- Softmax:根据匹配程度分配注意力
- Value(V):每本书的实际内容
- 输出(Attention × V):你获取的信息,更多来自匹配度高的书
9.8 为什么通常选择点积?
9.8.1 计算效率
点积可以用矩阵乘法高效实现:
# 一行代码计算所有 Query-Key 分数
attention_scores = Q @ K.transpose(-2, -1)
GPU 对矩阵乘法有高度优化,这让 Attention 能够并行计算所有位置对。原始 Transformer 论文也比较了 additive attention:两者理论复杂度相近,但 dot-product attention 可以直接利用矩阵乘法,因此实践中更快、更省空间。它不是数学上唯一或永远“最佳”的打分函数。
9.8.2 几何意义清晰
点积 = |Q| × |K| × cos(θ)
这给了我们直观的理解:
- 在长度相近时,方向更对齐通常带来更高分数
- 但长度同样会改变分数,所以它不是余弦相似度
- 权重取决于同一行里各分数的相对大小,还要经过缩放、mask 和 Softmax
9.8.3 可学习的灵活性
虽然点积本身是固定操作,但 Q、K、V 是通过可学习的权重矩阵(W_Q、W_K、W_V)生成的。
这意味着模型可以学习:
- 什么样的 Query 能找到相关的 Key
- 如何把原始向量转换成有意义的 Q、K、V
9.9 Self-Attention vs Cross-Attention
9.9.1 Self-Attention(自注意力)
在 GPT 这样的 Decoder-only 模型中,Q、K、V 都来自同一个序列:
输入:"小沈阳江西演唱会邀请了,"
Q = 输入 @ W_Q
K = 输入 @ W_K
V = 输入 @ W_V
Q、K、V 都来自同一个序列——这叫 Self-Attention(自注意力)。在 causal decoder 中,每个位置只能读取自己和更早的位置。
9.9.2 Cross-Attention(交叉注意力)
在 Encoder-Decoder 模型(如原始 Transformer、翻译模型)中,Q 来自一个序列,K、V 来自另一个序列:
Encoder 输入:"Hello World"
Decoder 输入:"你好"
Q = Decoder 输入 @ W_Q
K = Encoder 输出 @ W_K
V = Encoder 输出 @ W_V
Decoder 的每个词关注的是 Encoder 中的词——这叫 Cross-Attention(交叉注意力)。
9.9.3 GPT 只用 Self-Attention
GPT 是 Decoder-only 架构,只使用 Self-Attention:
- 只有一个输入序列
- 每个词关注自己和之前的词
- 通过 Mask 防止"偷看"未来的词
9.10 本章总结
9.10.1 核心概念
| 概念 | 解释 |
|---|---|
| Attention | 让允许连接的位置通过加权混合直接交换信息 |
| 点积 | 给一个 Query-Key 对计算匹配分数 |
| Q @ Kᵀ | 批量计算所有 Query-Key 分数 |
| Scale | 除以 √d_k,稳定分数尺度 |
| Mask + Softmax | 屏蔽不允许的位置,再把每行变成归一化权重 |
| Self-Attention | Q、K、V 来自同一序列 |
9.10.2 Attention 公式
Attention(Q, K, V) = softmax(QK^T / √d_k + M) × V
9.10.3 核心认知
Attention 用 Q 和 K 的点积得到匹配分数,经过
√d_k缩放、mask 和 Softmax 变成权重,再用这些权重混合 V。权重说明这一层这个 head 怎样路由信息,不是模型“理解程度”的完整解释。
本章交付物
学完这一章,你应该能够:
- 解释为什么 Attention 比 RNN 更适合处理序列
- 说出点积在 Attention 中的作用(计算匹配分数)
- 理解 Attention 热力图的含义和局限
- 解释为什么要 Scale(除以
√d_k) - 区分 Self-Attention 和 Cross-Attention
下一章预告
现在我们理解了 Attention 的几何逻辑——用点积计算匹配分数,再把分数变成信息混合权重。
但还有一个关键问题没回答:Q、K、V 到底是什么?它们是怎么来的?
下一章,我们来详细拆解 Q、K、V 的生成过程,以及它们各自的含义。这是真正理解 Attention 的关键!