Transformer 入门:从 RNN 到 GPT 生成,6 个问题全部手算
想弄懂 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:
| 传了几步 | 梯度还剩 |
|---|---|
| 1 | 0.9 |
| 10 | 0.9¹⁰ ≈ 0.35 |
| 50 | 0.9⁵⁰ ≈ 0.005 |
50 步以后只剩 0.5%,句首的词对训练几乎没有影响。另外它必须等前一个词算完才能算下一个,没法并行。所以我们需要一种方式,让每个词能直接看到任何其他词,而且一次算完。
问题 2:Self-Attention 怎么让相隔很远的词直接比对?
用一个只有两个词的句子"我吃",每个词先变成 Q、K、V 三个向量(可以理解成:Q 是"我在找什么",K 是"我能提供什么",V 是"选中我就给你的内容")。数值是为了演示取的:
| 词 | Q | K | V |
|---|---|---|---|
| 我 | [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.0 | 0 | 0 |
| 爱 | 0.40 | 0.60 | 0 |
| 你 | 0.25 | 0.30 | 0.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-Attention | Q·K → 缩放 → softmax → 加权 V |
| 不能偷看未来 | Causal Mask | 填负无穷,不是 0 |
| BERT 与 GPT | 训练目标不同 | 遮 15% 对比逐字预测 |
| 多头 | 每头专注一种关系 | 512 = 8 × 64 |
| 重复计算 | KV Cache | 15 次变 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
更多推荐

所有评论(0)