想弄懂 Transformer 和 Self-Attention,很多教程先讲架构图和公式,读完能复述,但合上页面推不出来。这篇换个顺序:先抛一个问题,用一个最小的数字例子算一遍,再看为什么会需要下一个机制。内容来自我做的一套 34 课大模型课程的第 1 课,一共 6 个问题,从 RNN 的问题一路走到 GPT 逐字生成。

  • 在线阅读(免登录、手机可看):https://zhuangzhaoyeye.github.io/llm-course/
  • 源码(MIT 许可):https://github.com/zhuangzhaoyeye/llm_course

问题 1:RNN 为什么记不住远处的词?

RNN 一个词接一个词地读。反向传播时,梯度要沿着时间步一路传回去,每传一步都要乘一个系数。假设这个系数是 0.9:

传了几步梯度还剩
10.9
100.9¹⁰ ≈ 0.35
500.9⁵⁰ ≈ 0.005

50 步以后只剩 0.5%,句首的词对训练几乎没有影响。另外它必须等前一个词算完才能算下一个,没法并行。所以我们需要一种方式,让每个词能直接看到任何其他词,而且一次算完。

问题 2:Self-Attention 怎么让相隔很远的词直接比对?

用一个只有两个词的句子"我吃",每个词先变成 Q、K、V 三个向量(可以理解成:Q 是"我在找什么",K 是"我能提供什么",V 是"选中我就给你的内容")。数值是为了演示取的:

词QKV
我[0.6, 0.2][0.4, 0.7][0.8, 0.3]
吃[0.3, 0.9][0.1, 0.5][0.6, 0.2]

“我"去看"我"和"吃”,分数是 Q 和 K 的点积:

  • Q我·K我 = 0.6×0.4 + 0.2×0.7 = 0.38
  • Q我·K吃 = 0.6×0.1 + 0.2×0.5 = 0.16

再除以 √d_k(这里 d_k=2,√2≈1.41)得到 0.27 和 0.11,过 softmax 变成权重 [0.54, 0.46],最后用权重对 V 加权求和:

0.54×[0.8, 0.3] + 0.46×[0.6, 0.2] ≈ [0.71, 0.25]

这个新向量同时带上了"我"和"吃"的信息。一次矩阵运算就能把所有词对比完,不再一步步传。

问题 3:生成时不能看后面的词,限制加在哪?

加在上一步算出的分数矩阵上。句子"我爱你",正常情况下"我"能看到后面的"爱"和"你",训练时等于偷看答案。做法是把"列号大于行号"的格子换成负无穷,再过 softmax:

我爱你
我1.000
爱0.400.600
你0.250.300.45

为什么是负无穷而不是 0?填 0 的话,softmax 后第一行会变成 [0.45, 0.27, 0.27],被遮住的词仍然分到了权重。只有 e^(-∞)=0 才是真正的"完全忽略"。

问题 4:同一个 Transformer,为什么分出 BERT 和 GPT?

区别在于要不要挡住未来:不挡的是 BERT(双向,做完形填空),必须挡的是 GPT(单向,逐字接龙)。训练方式不同,每次"教"到的位置数也不同。以 40 个 token 的句子为例:

  • BERT 只遮 15% 的词来预测:40 × 0.15 = 6 个位置
  • GPT 除第一个词外每个位置都在预测下一个词:40 − 1 = 39 个位置

BERT 训练时永远有左右两边的上下文,所以让它"只看左边猜右边"是它没学过的事。这不是能力问题,是训练方式的问题。

问题 5:多开几个注意力头,多看到了什么?

按原论文的设置,d_model=512,8 个头,每个头分到 512/8=64 维,各自算完再拼回 512 维,总计算量和单头差不多。好处是每个头可以专注一种关系。比如"苹果很甜,我昨天买了三斤"里,“苹果"同时和"甜”(属性)、“买”(动作)、“斤”(数量)有关。单头只有一个权重分布,三种关系互相稀释;多头里不同的头可以分别把 55%、62%、72% 的注意力给对应的词(这组权重是课程里为了演示设的)。

问题 6:解码时什么被重复计算了?

GPT 生成"我爱吃苹果"要一步步来:输入 [BOS] 得到"我",输入 [BOS, 我] 得到"爱"……直到预测出结束符 EOS。每一步都要把前面所有词的 K 和 V 重新算一遍:

  • 5 步里,不缓存的话累计 (1+2+3+4+5)=15 次,缓存之后只要 5 次,省 67%
  • 序列拉长到 100 步,省 98%

这就是 KV Cache:把算过的 K 和 V 存下来复用。注意这里只数了 K/V 投影,注意力打分本身每一步仍要和全部旧词比,所以整体计算量省得没这么多。

小结

问题机制一句话
RNN 记不住远处梯度连乘衰减0.9⁵⁰ ≈ 0.005
怎么直接比对Self-AttentionQ·K → 缩放 → softmax → 加权 V
不能偷看未来Causal Mask填负无穷,不是 0
BERT 与 GPT训练目标不同遮 15% 对比逐字预测
多头每头专注一种关系512 = 8 × 64
重复计算KV Cache15 次变 5 次

参考与说明

  • Self-Attention 与 Transformer:Vaswani 等,Attention Is All You Need,2017,https://arxiv.org/abs/1706.03762
  • BERT:Devlin 等,2018,https://arxiv.org/abs/1810.04805
  • GPT-3:Brown 等,2020,https://arxiv.org/abs/2005.14165
  • 文中数字(梯度衰减、注意力分数与加权、mask 后的 softmax、监督位置数、KV 投影次数)我都用代码独立复算过。带"为了演示取的"的数值是示意值,不是真实模型的输出。
  • 说明:这套课程由 AI 在我设计的规则下生成,再经过脚本检查和独立审查;审查时发现过不少问题,已写在仓库 README 里。如果你发现错误,欢迎在仓库提 Issue,写清位置,我会逐条核实。

继续学

完整课程有 34 课,从 Transformer 一路讲到训练与推理工程、Agent。每张卡片后面还有 AI 助教,可以接着追问(每人每天有次数限制)。

  • 课程:https://zhuangzhaoyeye.github.io/llm-course/
  • 源码:https://github.com/zhuangzhaoyeye/llm_course ,觉得有帮助的话欢迎点个 Star
Logo

更多推荐