一:自注意力Self-Attention¶
来源:http://mp.weixin.qq.com/s?__biz=MzYyNTk3Njg1NA==&mid=2247483713&idx=1&sn=fb7afe9b4a5c916fbc2c58f6519e668b&chksm=f01eb238c7693b2ecc6e215769972ed78e850afcf9f89f3fe2b23bd60937984f6356d813f564#rd
1. 学习定位¶
self-attention 是 Transformer 架构的核心机制,也是理解现代大语言模型的入口。它的作用是让序列中每个 token 根据当前输入内容,动态读取同一序列中其他 token 的信息,并形成上下文相关的表示。 第一天学习的重点集中在 self-attention 的基本原理,而不是 Transformer 的全部细节。需要掌握的范围包括: - self-attention 的直观含义和计算流程。
-
Query、Key、Value 的角色划分。
-
scaled dot-product attention 的数学公式。
-
attention score、softmax、mask、value 聚合的语义。
-
单头 attention 和多头 attention 的张量形状。
-
causal mask 与 padding mask 的作用。
-
self-attention 的复杂度、并行性和长上下文瓶颈。
-
最小 PyTorch 风格实现中的关键细节。
2. 序列表示与上下文依赖¶
自然语言中的 token 不是孤立存在的。一个 token 的含义经常由上下文决定。同一个词在不同句子中可以表示不同实体、不同语义角色或不同指代关系。模型如果只使用静态 token embedding,就只能得到“词本身”的表示,无法充分表达它在当前句子中的语义。 序列建模的目标之一,是把每个位置的原始 token 表示转换成上下文相关表示。上下文相关表示不仅包含当前 token 的信息,也包含与当前 token 相关的其他位置的信息。 传统 RNN 通过时间步递推建模上下文,长距离信息需要一步步传递。CNN 通过局部卷积捕捉邻域模式,长距离交互通常需要堆叠多层。self-attention 采用另一种方式:直接计算序列中任意两个位置之间的相关性,让信息可以在一层内跨任意距离流动。 核心思想可以概括为:
3. Self-Attention 的整体流程¶
给定输入序列表示 X,self-attention 的计算过程可以分为六步:
- 从输入 X 线性投影得到 Q、K、V。
-
用
QK^T计算每个 query 对所有 key 的匹配分数。 -
对匹配分数除以
sqrt(d_k)做缩放。 -
根据任务需要加入 attention mask。
-
沿 key 维度做 softmax,得到 attention weights。
-
用 attention weights 对
V加权求和,得到每个位置的新表示。
流程图如下:
X
|
|-- W_Q --> Q
|-- W_K --> K
|-- W_V --> V
QK^T / sqrt(d_k)
|
+ mask
|
softmax
|
attention weights @ V
|
contextual output
4. Query、Key、Value¶
self-attention 中每个 token 都会生成三种向量:Query、Key、Value。 Query 表示当前位置想要查找的信息。Key 表示当前位置可以被什么查询匹配。Value 表示当前位置在被关注时实际提供的信息内容。 可以用检索系统类比: - Query 类似用户输入的搜索请求。
-
Key 类似文档索引或可检索字段。
-
Value 类似文档正文或返回内容。
某个 token 的 Query 会和所有 token 的 Key 计算匹配分数。匹配分数经过 softmax 后变成权重,这些权重再用于聚合所有 token 的 Value。
Q、K、V 都来自同一个输入 X,这是 self-attention 中 “self” 的含义。它们不是三份不同数据,而是同一份序列表示经过三组不同可学习线性变换得到:
5. Scaled Dot-Product Attention¶
标准 scaled dot-product attention 公式为:
加入 mask 后,常见形式为: 各部分含义如下: -QK^T:计算 query 与 key 的点积相似度。
-
d_k:key/query 的维度。 -
sqrt(d_k):缩放因子,用于稳定 softmax 输入尺度。 -
softmax:将匹配分数转成非负且归一化的注意力权重。 -
V:被加权聚合的信息内容。
attention 的输出是 value 的加权和,而不是 query 或 key 的加权和。Q 和 K 的主要职责是计算位置间的匹配关系,V 才是被读取和传递的信息载体。
6. 点积相似度¶
点积用于衡量两个向量的匹配程度。若 query 和 key 在向量空间中方向接近、模长较大,点积值通常更大,表示该 key 对当前 query 更相关。
对一组 query 和 key 使用矩阵乘法可以一次性得到所有位置两两之间的匹配分数。对于长度为 T 的 self-attention,score 矩阵通常是 T x T:
k1 k2 k3 ... kT
q1 . . . .
q2 . . . .
q3 . . . .
...
qT . . . .
i 行表示第 i 个 token 作为 query 时对所有 key 的匹配分数。第 i 行第 j 列表示第 i 个 token 对第 j 个 token 的关注强度。
这种矩阵化计算方式是 Transformer 易于并行训练的重要原因。
7. 缩放因子 sqrt(d_k)¶
当 query 和 key 的维度 d_k 较大时,点积值的方差会随维度增大。若每一维近似独立且方差相近,则点积可以看作 d_k 个随机变量的和,其方差大致与 d_k 成正比。
未缩放的点积分数过大时,softmax 会进入饱和区。饱和的 softmax 会产生极端尖锐的分布,最大位置接近 1,其他位置接近 0,导致梯度变小并影响训练稳定性。
除以 sqrt(d_k) 可以把点积分数拉回更稳定的尺度:
为了更透彻地理解,图片中是Attention is all you need原文描述:我们推测 d_k 数值偏大时,点积结果幅值会随之变大。简单理解就是,当维度更大的时候,维度越多,相加的随机项数量越多,叠加后总和绝对值更容易冲高,点积数值量级随之膨胀。幅值过大会让 softmax 输入落入梯度极小饱和区,所以除以 sqrt(d_k) 做幅度归一。
8. Softmax 与注意力权重¶
softmax 将 attention score 转换为注意力权重。权重具有两个重要性质: - 每个权重非负。
- 对同一个 query,所有 key 位置的权重和为 1。
如果 attention score 的 shape 是:
softmax 应沿最后一维T_k 执行:
这表示每个 query 位置都会在所有 key 位置上形成一个注意力分布。
softmax 后的权重再乘以 V:
输出可以理解为对 value 信息的动态加权平均。不同输入样本、不同位置、不同层和不同 head 都可能产生不同的权重分布。
9. 单头 Attention 的张量形状¶
设输入 X 的 shape 为:
B 是 batch size。
-
T是序列长度。 -
d_model是模型隐藏维度。
单头 self-attention 中,线性投影参数常写为:
投影后: 计算 attention score: softmax 后: 聚合 value: 在 self-attention 中,T_q = T_k = T。在 cross-attention 中,query 和 key/value 可以来自不同序列,因此 T_q 和 T_k 可以不同。
10. Multi-Head Attention¶
单头 attention 只在一个表示子空间中计算相关性。multi-head attention 将模型维度拆分成多个 head,让模型在多个子空间中并行学习不同类型的关系。 标准公式:
其中: -h 是 head 数。
-
每个 head 有独立的 Q/K/V 投影。
-
Concat将所有 head 的输出拼接。 -
W_O将拼接后的表示重新映射回d_model。
常见设置为:
这样多个 head 拼接后仍然回到d_model 维度,整体计算量与单头完整维度 attention 保持同阶。
示例:
shape 变化:
X: [2, 4, 8]
Q/K/V after linear: [2, 4, 8]
reshape: [2, 4, 2, 4]
transpose: [2, 2, 4, 4] # [B, H, T, d_head]
score: [2, 2, 4, 4]
weights: [2, 2, 4, 4]
head output: [2, 2, 4, 4]
transpose + concat: [2, 4, 8]
output projection: [2, 4, 8]
d_head,若 d_head 过小,单个 head 的表达能力可能不足。实际模型需要在效果、计算效率、显存和硬件实现之间折中。
11. Attention Mask¶
attention mask 用于控制哪些位置可以被关注。mask 通常在 softmax 前加入 attention score,使被屏蔽的位置在 softmax 后权重为 0。 常见写法:
使用-inf 或极大负数的原因是:
在过了Softmax的exp后就会变成0,因此被屏蔽位置不会参与 value 聚合。
mask 通常需要能 broadcast 到 attention score 的形状:
padding mask 常见形状可以是:
causal mask 常见形状可以是:
两类 mask 可以合并使用。
12. Causal Mask¶
decoder-only 语言模型采用自回归训练目标。每个位置只能依赖自己和之前的 token,不能看到未来 token。causal mask 用来保证这种因果约束。 长度为 5 的 causal mask 允许关注位置如下:
k1 k2 k3 k4 k5
q1 1 0 0 0 0
q2 1 1 0 0 0
q3 1 1 1 0 0
q4 1 1 1 1 0
q5 1 1 1 1 1
i 行只允许关注 0..i 的 key 位置。
causal mask 避免训练时的信息泄漏。若不加 causal mask,当前位置可以看到未来 token,训练 loss 会不真实地降低,但推理生成时未来 token 不存在,训练和推理条件不一致。
causal mask 不影响训练并行性。训练时仍可以一次性输入完整序列,矩阵乘法仍然并行执行;mask 只是在 attention score 中屏蔽未来位置。
13. Padding Mask¶
batch 训练通常需要把不同长度的样本 padding 到同一长度。padding token 是补齐用的无效内容,不应该被真实 token 关注,也不应该参与语言模型 loss 或分类 loss。 padding mask 的作用是屏蔽 padding 对应的 key 位置。例如:
真实 token 的 query 不应该从` 的 value 中读取信息。实现时通常把 padding key 位置对应的 score 置为-inf`。
在 decoder-only LM 中,padding mask 和 causal mask 经常同时存在:
- padding mask 屏蔽无效补齐位置。
- causal mask 屏蔽未来位置。
14. Self-Attention 与位置信息¶
纯 self-attention 本身不包含顺序信息。若没有位置编码,attention 主要根据 token 内容计算相关性,对输入顺序的区分能力不足。 Transformer 需要显式引入位置相关信息。常见方式包括: - sinusoidal positional encoding
-
learned positional embedding
-
RoPE
-
ALiBi
位置机制让模型可以区分相同 token 集合的不同排列,并学习距离、先后顺序、相对位置等结构信息。 self-attention 负责内容相关的信息聚合,位置编码负责提供顺序结构。二者共同构成 Transformer 序列建模能力的重要基础。
15. 复杂度与并行性¶
self-attention 的核心计算包括 QK^T 和 attention weights @ V。
设序列长度为 T,模型维度为 d_model。attention 核心计算复杂度近似为:
T x T score 矩阵的元素数量变为原来的 4 倍。这使 self-attention 在长上下文场景中成本显著增加。
Transformer 的训练并行性来自矩阵化计算。所有位置的 Q/K/V 投影可以并行完成,所有 query-key 匹配也可以通过大矩阵乘法并行完成。相比 RNN 的顺序递推,这种计算模式更适合 GPU/TPU。
16. 与 RNN 和 CNN 的对比¶
RNN、CNN、self-attention 都可以用于序列建模,但建模方式不同。 RNN 按时间步递推,天然适合流式输入,但序列维度并行性较弱,长距离依赖需要经过多步传播。 CNN 通过局部窗口提取特征,并行性较好,但单层感受野有限。长距离依赖需要堆叠多层、扩大卷积核或使用膨胀卷积。 self-attention 允许任意两个位置在一层内直接交互,长距离路径短,并行性强。主要代价是序列长度二次复杂度。 对比总结:
17. 最小实现参考¶
下面是 scaled dot-product attention 的 PyTorch 风格伪代码:
import math
import torch
import torch.nn.functional as F
def scaled_dot_product_attention(q, k, v, attn_mask=None, dropout_p=0.0, training=True):
# q: [B, H, T_q, d_head]
# k: [B, H, T_k, d_head]
# v: [B, H, T_k, d_v]
d_head = q.size(-1)
scores = torch.matmul(q, k.transpose(-2, -1)) / math.sqrt(d_head)
if attn_mask is not None:
scores = scores.masked_fill(attn_mask == 0, float("-inf"))
weights = torch.softmax(scores, dim=-1)
weights = F.dropout(weights, p=dropout_p, training=training)
out = torch.matmul(weights, v)
return out, weights
k.transpose(-2, -1) 将 key 的最后两个维度从 [T_k, d_head] 变为 [d_head, T_k]。
-
scores的 shape 是[B, H, T_q, T_k]。 -
softmax 使用
dim=-1,表示每个 query 对所有 key 归一化。 -
mask 必须能 broadcast 到 score 的形状。
-
attention dropout 通常作用在 softmax 后的 attention weights 上。
-
输出 shape 是
[B, H, T_q, d_v]。
18. 数值稳定与调试要点¶
attention 实现中常见的数值问题包括 NaN、softmax 饱和、mask 语义反转和 shape 错位。
NaN 常见来源:
- 某一行 query 对应的所有 key 都被 mask,导致 softmax 输入全为 -inf。
-
mixed precision 下使用过大的负数造成溢出或 kernel 不兼容。
-
忘记除以
sqrt(d_head),score 过大。 -
上游 Q/K/V 已经出现 inf 或 NaN。
-
学习率过大或归一化层异常导致激活爆炸。
shape 错误常见来源:
- multi-head reshape 后没有 transpose 到 [B, H, T, d_head]。
-
K转置维度错误。 -
mask 维度无法正确 broadcast。
-
softmax 沿错误维度执行。
最小调试策略:
- 用很小的 B、H、T 构造可打印样例。
-
打印 score、mask、weights 的 shape。
-
检查 softmax 后每行和是否接近 1。
-
检查 mask 位置的权重是否接近 0。
-
与框架内置
scaled_dot_product_attention在无 dropout 场景下对齐数值。
19. Attention 权重与可解释性¶
attention weights 表示某一层某个 head 中,每个 query 对不同 value 的聚合权重。它可以作为模型行为分析的线索,但不能直接等同于模型最终决策的因果解释。 Transformer 的最终输出经过多层 attention、MLP、残差连接和归一化。某个 head 的高权重只说明该层该 head 在聚合信息时偏向某个位置,不足以证明该位置对最终预测具有决定性影响。 更严谨的解释需要结合: - token masking 或遮挡实验
-
反事实替换
-
gradient-based attribution
-
head ablation
-
activation patching
面试中适合表述为:attention 权重有分析价值,但不是完整解释。
20. 第一层知识闭环¶
self-attention 的知识闭环可以压缩为下面几条:
输入 X 通过三套线性投影得到 Q、K、V。
Q 和 K 的点积产生 token 之间的匹配分数。
分数除以 sqrt(d_k) 后进入 softmax,形成每个 query 对所有 key 的权重分布。
mask 用来屏蔽 padding 或未来位置。
权重乘 V 得到上下文相关表示。
multi-head attention 在多个子空间中并行执行上述过程。
self-attention 的优势是全局交互和并行训练,限制是序列长度二次复杂度。
预览时标签不可点
修改于
<div class="