自注意力与多头注意力
从查询-键-值推导缩放点积注意力,再拆解多头机制如何让模型关注不同子空间。
注意力机制回答一个朴素的问题:当前 token 应该「看」序列里的哪些位置? 自注意力让序列中每个位置都与其他位置交互,权重由内容动态决定。
缩放点积注意力
对输入 ,先经三个线性变换得到查询、键、值:
注意力权重是查询与键的点积相似度,除以 防止内积过大 导致 softmax 落入饱和区:
import torch
import torch.nn.functional as F
def scaled_dot_product_attention(q, k, v, mask=None):
d_k = q.size(-1)
scores = q @ k.transpose(-2, -1) / (d_k ** 0.5)
if mask is not None:
scores = scores.masked_fill(mask == 0, float('-inf'))
weights = F.softmax(scores, dim=-1)
return weights @ v
为什么叫「缩放」
若 各分量独立且均值为零,内积的方差随维度线性增长到 。 不缩放时 softmax 的输入落在饱和区,梯度趋近于零,训练不稳定。
多头注意力
单头注意力只在一个子空间里聚合信息。多头把 切成 份 并行计算,再拼接投影回原维度:
其中 。 不同头可以学会不同的关注模式:句法关系、共指、局部依赖……
复杂度
- 计算 :
- softmax:
- 加权求和:
序列长度 的平方项是大模型长上下文的主要瓶颈,也是 FlashAttention、稀疏注意力等优化的出发点(见第 2 章)。