跳到主要内容

注意力机制

注意力机制(Attention)的核心问题是:当模型处理某个 token 时,它应该从上下文里的哪些 token 获取信息,以及各获取多少。

一句话理解:

注意力机制 = 给上下文里的 token 分配权重,然后按权重汇总信息

例如读这句话:

小明把书放进书包,因为它很重。

这里的“它”更可能指“书”,而不是“书包”。人类理解这句话时,会自动把注意力放到“书”上。模型也需要类似能力:在处理“它”时,从前文里找到更相关的信息。

1. 从生活例子理解注意力

假设你在回答问题:

问题:小明昨天买了一台新电脑,他今天用它写代码。“它”指什么?

你不会平均关注每个词。你会更关注:

  • “电脑”
  • “用它写代码”
  • “买了一台新电脑”

而不太关注:

  • “昨天”
  • “今天”
  • “小明”

这就是注意力的直觉:不同上下文信息的重要程度不同。

模型做的事情也类似,只是它不会用人类语言说“我关注电脑”,而是计算一组数字权重。

2. 一个最简单的注意力例子

假设当前 token 是“它”,上下文里有三个候选信息:

小明 / 电脑 / 桌子 / 它

模型可能计算出这样的注意力权重:

当前 token关注对象权重
小明0.10
电脑0.75
桌子0.10
它自己0.05

然后模型会按这些权重汇总信息:

新的“它”的表示
= 0.10 × 小明的信息
+ 0.75 × 电脑的信息
+ 0.10 × 桌子的信息
+ 0.05 × 它自己的信息

这样,“它”的向量表示里就会包含更多“电脑”的信息。后续模型生成答案时,就更容易回答“它指电脑”。

3. 为什么不能只看相邻词

早期序列模型常常更依赖局部顺序。但语言里很多关系不是相邻的。

例子:

那位昨天在会议上介绍新项目、并回答了很多问题的工程师,今天请假了。

“请假了”的主语是“工程师”,但中间隔了很多词。

注意力机制的优势是:它允许当前位置直接关注远处 token。

再比如:

如果明天下雨,我们就取消露营,否则按原计划出发。

理解“否则”时,需要回看前面的条件“明天下雨”。这种跨距离关系很适合用注意力建模。

4. Self-Attention 是什么

Self-Attention 指的是:同一个序列内部的 token 互相关注。

例如这句话:

猫坐在垫子上。

每个 token 都可以从句子里的其他 token 获取信息:

当前 token可能关注
坐、垫子
猫、垫子
垫子坐、上
垫子

Self-Attention 的“Self”表示 Query、Key、Value 都来自同一个序列。

在 LLM 中,Self-Attention 让每个 token 的表示不再只是自己,而是融合了上下文后的表示。

5. Q、K、V 的直觉

注意力机制里最容易卡住的是 Q、K、V。

可以用“图书馆检索”来理解:

  • Query(Q):我现在想找什么?
  • Key(K):每本书的索引标签是什么?
  • Value(V):这本书真正包含的内容是什么?

当你搜索“Transformer 注意力”时:

  1. 你的搜索词是 Query。
  2. 每本书的标题、标签、摘要是 Key。
  3. 书的正文内容是 Value。
  4. Query 和 Key 越匹配,就越应该读取那本书的 Value。

放到模型里:

组件直觉作用
Q当前 token 想找的信息用来匹配其他 token
K每个 token 提供的索引用来被 Q 匹配
V每个 token 提供的内容被加权汇总

所以注意力不是直接用 Q 去拿 K,而是:

Q 和 K 算相关性
相关性变成权重
权重去加权汇总 V

6. 为什么要分成 K 和 V

一个常见疑问是:为什么 Key 和 Value 要分开?不能一个向量既做索引又做内容吗?

直觉上,索引和内容本来就不是一回事。

例如一本书:

标题:Python 入门
标签:编程、Python、教程
正文:几百页内容

你检索时先看标题和标签,不会把整本书正文拿来做匹配。但真正读取时,你需要正文内容。

对应到 Attention:

  • Key 更像“我是否相关”的匹配信号。
  • Value 更像“如果相关,我提供什么内容”。

把 K 和 V 分开,模型可以学习更灵活的关系:一个 token 用一种方式被检索,用另一种方式贡献内容。

7. Attention 的三步计算

标准 Attention 可以拆成三步。

7.1 第一步:计算相关性分数

当前 token 的 Query 会和所有 token 的 Key 做点积。

score = Q · K

点积越大,表示越匹配。

例如当前 token 是“它”:

Key 对象分数
小明1.0
电脑4.0
桌子0.5
0.2

这表示“它”和“电脑”的匹配程度最高。

7.2 第二步:用 softmax 变成权重

原始分数需要变成权重,权重总和为 1。

[1.0, 4.0, 0.5, 0.2]
-> softmax
-> [0.04, 0.86, 0.02, 0.08]

softmax 会放大高分项,让模型更集中关注相关 token。

7.3 第三步:加权汇总 Value

最后用这些权重汇总 Value。

output
= 0.04 × V_小明
+ 0.86 × V_电脑
+ 0.02 × V_桌子
+ 0.08 × V_它

这样输出向量就主要吸收了“电脑”的信息。

8. Attention 公式

标准 Scaled Dot-Product Attention 写作:

Attention(Q,K,V)=softmax(QKdk)V\operatorname{Attention}(Q, K, V) = \operatorname{softmax}\left(\frac{QK^\top}{\sqrt{d_k}}\right)V

这条公式可以逐段读:

片段含义
QKQK^\top每个 Query 和每个 Key 算相似度
dk\sqrt{d_k}缩放因子,避免分数过大
softmax把分数变成权重
乘以 VV用权重汇总内容

不用一开始就记公式。只要先记住:

Q 找 K,得到权重,再汇总 V

公式只是把这个过程写成矩阵计算。

9. 一个小矩阵例子

假设有 3 个 token:

我 / 喜欢 / 苹果

每个 token 都会生成自己的 Q、K、V。

Attention 分数矩阵可能长这样:

当前 token \ 被关注 token喜欢苹果
0.60.30.1
喜欢0.20.50.3
苹果0.10.40.5

按行看:

  • “我”主要关注自己。
  • “喜欢”关注自己,也关注“苹果”。
  • “苹果”关注自己,也关注“喜欢”。

每一行都是当前 token 对所有 token 的注意力分布。

注意力矩阵不是固定规则,而是模型根据输入动态算出来的。

10. Causal Mask 是什么

在 GPT 这类自回归模型里,模型生成下一个 token 时不能看到未来。

例如训练句子:

我 喜欢 苹果

预测“喜欢”时,模型不能看到“苹果”;预测“苹果”时,才能看到“我”和“喜欢”。

所以注意力矩阵要加 mask:

当前 token \ 可见 token喜欢苹果
可见不可见不可见
喜欢可见可见不可见
苹果可见可见可见

这叫 causal mask。

它保证模型只能根据过去预测未来。

如果没有 causal mask,模型训练时就会偷看答案,生成能力会失真。

11. 双向注意力与单向注意力

不同模型使用不同注意力可见范围。

类型可见范围代表模型适合任务
双向 Attention可以看左右上下文BERT理解、分类、Embedding
单向 / Causal Attention只能看当前位置之前GPT、LLaMA、Qwen生成、对话

例子:

我把苹果放在桌上,因为它很甜。

BERT 在处理“它”时,可以同时看前后文。GPT 在生成到“它”时,只能看已经生成出来的前文。

这就是为什么 Encoder-only 模型更适合理解任务,而 Decoder-only 模型更适合生成任务。

12. Multi-Head Attention 是什么

单个注意力头只能从一个角度看上下文。Multi-Head Attention 就是让模型从多个角度同时看。

比如句子:

小王把蛋糕给了小李,因为他不饿。

不同 attention head 可能关注不同关系:

Head可能关注
Head 1“他”指代谁
Head 2“给了”的动作关系
Head 3“不饿”和“给蛋糕”的因果关系
Head 4名词之间的距离和位置

每个 head 都会独立计算一套 Q/K/V 和注意力权重,最后把结果拼起来,再通过 o_proj 整合。

简化流程:

输入 hidden states
-> 分成多个 head
-> 每个 head 独立做 attention
-> concat
-> o_proj
-> 输出

多头注意力的价值不是简单“多算几遍”,而是让模型可以并行学习多种关系。

13. 例子:指代消解

看这句话:

张三把钥匙交给李四,因为他要出门。

“他”可能指张三,也可能指李四,需要结合语义判断。

如果模型处理“他”,可能会关注:

token注意力
张三0.45
钥匙0.05
李四0.20
要出门0.25
其他0.05

这个分布表示模型更倾向于把“他”和“张三”关联起来。

但如果句子变成:

张三把钥匙交给李四,因为他忘带钥匙了。

“他”更可能指李四。注意力权重就可能变成:

token注意力
张三0.20
钥匙0.15
李四0.45
忘带钥匙0.15
其他0.05

注意力是动态的,同一个词在不同上下文里的关注对象会变化。

14. 例子:翻译

翻译时,生成目标词需要关注源句里的相关词。

例如:

英文:The cat sat on the mat.
中文:猫坐在垫子上。

生成“猫”时,模型应该关注 cat

生成“垫子”时,模型应该关注 mat

生成中文 token主要关注英文 token
cat
sat
垫子mat
on

这类跨序列注意力在 Encoder-Decoder 模型中叫 Cross-Attention。虽然现代聊天 LLM 多是 Decoder-only,但这个例子很适合理解“注意力就是对齐相关信息”。

15. 例子:代码理解

注意力机制也适合代码。

def add_tax(price):
tax = price * 0.08
return price + tax

模型处理 return price + tax 时,需要知道:

  • price 来自函数参数。
  • tax 在上一行定义。
  • taxprice 有计算关系。

注意力可以让 return 这一行直接关注前面的变量定义,而不是只依赖相邻 token。

在长代码里,这种能力更重要:

  • 函数调用要关注函数定义。
  • 变量使用要关注变量声明。
  • 类方法要关注类属性。
  • import 要影响后续 API 使用。

16. Attention 和 KV Cache 的关系

推理时,模型是一个 token 一个 token 生成的。

如果每生成一个新 token,都重新计算所有历史 token 的 K 和 V,会很浪费。

KV Cache 的作用是缓存历史 token 的 Key 和 Value。

生成新 token 时:

新 token 生成 Q
历史 token 的 K/V 从 cache 里读取
Q 和历史 K 计算注意力
用注意力权重汇总历史 V

所以:

  • Q 通常只需要为当前新 token 计算。
  • K/V 会为历史 token 缓存起来。
  • 上下文越长,KV Cache 越大。
  • 并发越高,KV Cache 显存压力越大。

这也是为什么注意力机制和推理显存强相关。

17. Attention 的计算成本

Self-Attention 需要每个 token 和其他 token 计算关系。

如果序列长度是 nn,注意力矩阵大致是 n×nn \times n

序列长度注意力关系数量
1,0001,000,000
10,000100,000,000
100,00010,000,000,000

这就是长上下文昂贵的原因之一。

虽然现代推理框架有 FlashAttention、PagedAttention、KV Cache 优化等技术,但基本事实仍然是:上下文越长,注意力相关成本越高。

18. Attention 权重能解释模型吗

Attention 权重有一定参考价值,但不能简单等同于“模型为什么这么回答”。

原因:

  • 模型有很多层,每层都有不同 attention。
  • 每层有多个 head。
  • FFN 也会大量加工信息。
  • 残差连接会混合不同路径的信息。
  • 最终输出由整个网络共同决定。

所以可以说:

Attention 权重能帮助观察模型关注了哪里,
但不能完整解释模型为什么这么输出。

19. 常见误区

19.1 注意力就是找关键词

不只是。注意力可以关注关键词,也可以关注语法、位置、格式、指代、因果、代码变量等抽象关系。

19.2 权重最高的 token 一定最重要

不一定。单层单头的权重只是一部分信息。模型最终输出还会经过多层、多头和 FFN。

19.3 注意力越集中越好

不一定。有些任务需要集中关注一个证据,有些任务需要综合多个信息。过度集中可能忽略必要上下文。

19.4 长上下文就是无限记忆

不是。长上下文只是允许模型看到更多 token,不保证模型能稳定使用所有信息。长输入还会增加干扰和成本。

20. 怎么真正理解注意力

可以按这个顺序记:

  1. 每个 token 都会变成向量。
  2. 每个 token 的向量会生成 Q、K、V。
  3. Q 是“我想找什么”。
  4. K 是“我有什么索引特征”。
  5. V 是“我真正提供什么内容”。
  6. Q 和 K 算相似度。
  7. 相似度经过 softmax 变成权重。
  8. 权重加权汇总 V。
  9. 多个 head 从不同角度重复这个过程。
  10. 多层 Transformer 不断重复,token 表示就越来越包含上下文信息。

最短版本:

Q 找 K,得到权重,汇总 V。

21. 总结

注意力机制让模型在处理每个 token 时,不是只看当前位置,而是动态读取上下文中相关 token 的信息。

它的关键点是:

  • Attention 是加权汇总上下文信息。
  • Self-Attention 是同一序列内部 token 互相关注。
  • Q/K/V 分别对应查询、索引和内容。
  • softmax 把相关性分数变成注意力权重。
  • causal mask 防止生成模型偷看未来。
  • multi-head attention 让模型从多个角度理解上下文。
  • KV Cache 让自回归推理可以复用历史 K/V。

理解注意力后,再看 Transformer、KV Cache、长上下文、多头注意力、GQA、LoRA 里的 q_proj/k_proj/v_proj/o_proj,都会更容易串起来。