ChatGPT、Claude、通义千问、DeepSeek——底层骨架几乎都叫 Transformer。名字像变形金刚,机制却朴素:用注意力让任意两个位置直接对话,再堆深、训壮。
一句话:Transformer = 自注意力(谁该看谁)+ 前馈网络(各自变换)+ 残差与归一化(堆得住)。GPT 一脉再加因果掩码:生成时只能看左边。
- 入门:第 1–3、5、9 节
- 读论文 / 源码:第 4–8、10、12、14 节
- 推理 / 平台:第 11、13、15 节
目录
1 | 1. 它解决了什么问题 |
1. 它解决了什么问题
1.1 RNN 的两记硬伤
Transformer 之前,序列主力是 RNN / LSTM / GRU:
1 | 词1 → h₁ → 词2 → h₂ → … → 词 n → hₙ |
| 硬伤 | 后果 |
|---|---|
| 难并行 | 第 100 步必须等第 99 步,GPU 吃不饱 |
| 长程靠状态链 | 第 1 个词影响第 100 个,要穿过 99 次隐状态;信息淡、梯度弱 |
The animal didn’t cross the street because it was too tired.
it 该绑 animal。RNN 只能把信息塞进隐状态再一跳一跳传过去。LSTM 缓解遗忘,但路径仍是长链,训练仍难并行。
1.2 Attention 不是 2017 才有的
- Word2Vec(2013):词变向量,但静态、无上下文
- Seq2Seq(2014):整句压成一个向量再解码;一长就挤爆
- Bahdanau Attention(2014/15):解码时按相关性回看源句——仍是 RNN + Attention
Google 再问:若 Attention 已能建模依赖,还要 RNN 干什么?《Attention Is All You Need》——注意力就够了。
1.3 换了什么假设
把「时间上的接力」换成「空间上的开会」:
- 每个位置同时看见(被允许看见的)所有位置
- 训练时整句可并行算矩阵
- 任意两词一步相连——用 (O(n^2)) 换短路径与可规模化
RNN 像传话游戏;Transformer 像圆桌会议,声调高低就是注意力权重。
结构允许大力出奇迹,所以撑得起后来的千亿参数训练。论文没证明「注意力=意识」,也没说平方复杂度不是问题;它证明的是更窄的一件事:翻译等任务上,去掉循环也能训得又快又好。
2. 鸟瞰:整体结构
原版为机器翻译而设计:左右两塔,各堆 (N) 层(论文 (N=6))。数据自下而上;每一层里都是 先 Attention,再 FFN。
| 侧 | 干什么 | 一层里有什么 |
|---|---|---|
| Encoder | 读懂源句 | Self-Attn(双向)→ FFN |
| Decoder | 写出目标句 | Masked Self-Attn(因果)→ Cross-Attn(查编码器)→ FFN |
外加残差与 Norm。顶上 Linear + Softmax 得到词表分布。
| 模块 | Q | K/V | 权限 |
|---|---|---|---|
| Encoder Self-Attn | 源句 | 源句 | 双向 |
| Decoder Self-Attn | 已生成前缀 | 已生成前缀 | 因果 |
| Cross-Attn | 解码器当前层 | 编码器输出 | 解码看编码 |
1 | 输入:Token → Embedding → 位置 |
今天聊天模型多半只留 Decoder:系统提示、检索、工具结果直接拼进前缀,交叉注意力塔被省掉——不是它不重要,而是条件改成了自注意力可见的上下文。
3. 输入:分词、Embedding、位置
1 | 文本 → Tokenizer → Embedding 查表 → 注入位置 → 第一层 |
Token:英文常见 BPE / WordPiece(playing → play + ##ing);中文常见字词混合或纯 BPE。词表固定,未知词靠子词拼。模型看见的是 id,不是「词」的日常含义。
Embedding:表大小 (V\times d_{\text{model}})。查表得到无上下文起点。bank 在「河岸 / 银行」里是同一行,要靠后面的 Attention 才分化。
1 | ids: (batch, seq_len) |
位置:纯 Attention 对词序置换近似不敏感。
- 正弦/余弦(论文):sin/cos 加到 embedding 上
- RoPE(现代主流):在 Q·K 时把相对位置编进旋转角;LLaMA、Qwen 等基本走这条
Embedding:「我是什么」。位置:「我在哪」。
「128k 上下文」通常是位置方案 + 长序列训练/微调 + 推理优化。RoPE 常再配插值 / YaRN 做外推。
4. 核心:自注意力
4.1 Q、K、V
每个位置 (x_i) 经三个线性投影:
| 人话 | 搜索类比 | |
|---|---|---|
| (Q) | 我在找什么 | 搜索词 |
| (K) | 我能被怎样检索 | 标题 / 标签 |
| (V) | 我贡献什么 | 正文 |
同一序列、三套投影,所以叫 Self。
[
\operatorname{Attention}(Q,K,V)=\operatorname{softmax}!\left(\frac{QK^{\top}}{\sqrt{d_k}}\right)V
]
1 | 打分 QKᵀ → 缩放 /√d_k → softmax 成权重 → 加权混合 V |
(\sqrt{d_k}) 防止高维点积过大、softmax 塌成 one-hot。输出是 Value 的凸组合。
4.2 热力图与动画
玩具句:The cat sat on mat。第 3 行 sat 对 cat 很亮——像动词找主语。颜色是配方,不是真理;别把每一格讲成人类故事。
- Self-Attention:Q、K、V 同一序列
- Cross-Attention:Q 来自解码器,K/V 来自编码器
换一个形容词,路由就会改:
… it was too tired → 更常绑
animal
… it was too wide → 更常绑street
不是 if-else,是统计上有利于猜对后面的词。
长度 (n)、维度 (d):形成 QKV 约 (O(nd^2)),(QK^{\top}) 与乘 V 约 (O(n^2d))。(n) 大时 (n^2) 会压过 (d^2)。FlashAttention 不改渐进复杂度量级,但大幅降显存流量。
5. 动手算一遍
1 | 位置: 我 爱 这 模型 |
「爱」的 Query=((1,1)),点积得分(忽略缩放):[1, 2, 1, 1]。
(\operatorname{softmax}\approx[0.17,\ 0.48,\ 0.17,\ 0.17]),
输出 (\approx(0.34,\ 0.65))——混进了邻居,自己仍占大头。
因果掩码下,「爱」不能看「这 / 模型」,后两格变 (-\infty),权重归零。否则训练等于偷看未来。
权重若永远均匀,Attention 退化成全句平均;可学之处在于权重依赖内容。
6. 多头注意力
多组投影各自算 Attention,拼接后再经 (W^O) 映回。
[
\operatorname{MultiHead}=\operatorname{Concat}(\mathrm{head}_1,\ldots,\mathrm{head}_h)W^O
]
「有的头偏语法」只是方便记忆。真实训练里分工常很乱,还有闲置头。工程价值是表达力 + 并行。
GQA / MQA:Query 仍多头,KV 头更少,减小 KV Cache。配置项 num_key_value_heads。
7. 掩码:谁能看见谁
| 掩码 | 谁能看见谁 | 典型 |
|---|---|---|
| 双向 | 全句 | BERT、多数 Embedding |
| 因果 | 自己及左边 | GPT、LLaMA、Qwen |
| Padding | 忽略填充位 | 训练 batch 对齐 |
1 | scores = Q @ K.T / sqrt(d_k) |
Padding 与因果常叠加。整行被掩光时 softmax 会 NaN,需保护。
「只能看左边」仍能写长文:续写策略在权重里,未来在一步步采样里展开——边写边定。高质量长输出往往还要外层提纲、检索或多轮改写。
8. 一层 Block
现代 Decoder-only 多为 Pre-Norm:
1 | x |
残差实际是:
[
x + \operatorname{Sublayer}(\operatorname{Norm}(x))
]
(论文原版偏 Post-Norm:(x+\mathrm{Sublayer}) 后再 Norm。)
RMSNorm / LayerNorm 稳住尺度。FFN 中间宽常约 (4\times d_{\text{model}}),激活从 ReLU → GELU → SwiGLU。
Attention = 路由;FFN = 变换。参数量很大一块在 FFN。
非线性细节:激活函数的前世今生。
一层 = 开会 + 写纪要。堆 N 层是反复打磨:浅层更局部,深层更抽象——经验观察,不是定理。
9. 完整数据流:从提示到下一个词
前缀 今天天气,Decoder-only 生成下一个词:
- 分词 → ids
- Embedding + 位置 → (X)
- (N) 层 Masked Attn + FFN
- 最后位置 × LM Head(有的与 embedding 绑权,有的不绑)
- logits → 采样 / 贪心
- 追加 token,回到 2
训练用教师强制:整句右移当标签,一次并行算所有位置损失。目标是:
[
\mathcal{L}=-\sum_{t}\log P(x_t\mid x_{<t})
]
| 推理阶段 | 做什么 |
|---|---|
| Prefill | 整段提示一次前向,写出 KV |
| Decode | 逐 token 生成,读 KV Cache |
首字慢或长提示 TTFT 高,多半是 Prefill。Temperature / top-k / top-p 只改采样性格。
能力来自「为猜对词被迫学到的结构」;幻觉来自「似然 ≠ 求真」;对齐试图把续写拧成助手。
10. 三条岔路
| 类型 | 注意力 | 擅长 | 代表 |
|---|---|---|---|
| Encoder-only | 双向 | 理解、检索向量 | BERT、多数 Embedding |
| Decoder-only | 因果 | 生成、对话、代码 | GPT、LLaMA、Qwen、DeepSeek |
| Enc–Dec | 双向编码 + 因果解码 + 交叉注意 | 翻译、摘要 | 原版、T5、BART |
聊天一边倒 Decoder-only:万物可改写成「前缀→续写」,规模化与部署经验最多。Enc–Dec 没死。检索要整段摘要,双向仍然更合适。
11. 从论文到 ChatGPT
| 节点 | 叠加 |
|---|---|
| 2017 | 可并行、可堆叠的翻译骨架 |
| 2018 | GPT-1 / BERT;预训练成默认范式 |
| 2020 | GPT-3 ≈175B;提示即接口;Scaling Law |
| 2022+ | SFT + RLHF/DPO;对齐成产品 |
| 开源浪潮 | LLaMA / Qwen / DeepSeek… 配方收敛 |
1 | Decoder-only + Pre-Norm/RMSNorm + RoPE + SwiGLU + GQA |
差异多在数据、训练日程、分词器与推理优化。「涌现」有争议;工程事实:大力有效,Transformer 让大力变得可行。
12. 对照配置文件
| 配置项 | 含义 | 见 |
|---|---|---|
hidden_size / d_model |
宽度 | 第 3 节 |
num_hidden_layers |
层数 | 第 8 节 |
num_attention_heads |
多头 | 第 6 节 |
num_key_value_heads |
KV 头(GQA) | 第 6、13 节 |
intermediate_size |
FFN 中间宽 | 第 8 节 |
vocab_size |
词表 | 第 3 节 |
max_position_embeddings |
位置上限 | 第 3 节 |
rope_theta / rope_scaling |
RoPE | 第 3 节 |
tie_word_embeddings |
是否绑 LM Head | 第 9 节 |
1 | layers.i.self_attn.{q,k,v,o}_proj → 注意力线性层 |
13. 工程:复杂度、KV Cache、FlashAttention
两两打分 → (n\times n)。常见对策:FlashAttention(少物化大矩阵)、GQA/MQA(少存 KV)、滑动窗口/稀疏、YaRN 等外推、以及 SSM 等另一类混合。
KV Cache:历史 K、V 不变,新 token 只算自己的 Q。用显存换时间;长对话显存上涨主因常在这里。Continuous batching、PagedAttention 都是在管 KV。
| 训练 | 推理 | |
|---|---|---|
| 并行 | 序列内可并行 | 自回归;靠 batch 挤吞吐 |
| 显存大户 | 激活、优化器、梯度 | 权重 + KV Cache |
1 | 权重 ∝ 参数量 × 字节/参数 |
权重装不下 → 量化 / 张量并行;KV 撑爆 → 分页缓存 / 短窗口 / GQA。别听成「换个注意力变体就解决一切」。
14. 最小可读代码
1 | import numpy as np |
因果掩码:
1 | mask = np.triu(np.ones((4, 4)), k=1).astype(bool) |
| 张量 | 形状((d=H d_h)) |
|---|---|
| (X) | (B\times S\times d) |
| Q/K/V | (B\times H\times S\times d_h) |
| 分数 | (B\times H\times S\times S) |
| 输出 | (B\times S\times d) |
有 KV Cache 时:历史走缓存,当前步常 (S=1)(prefill 除外)。
15. 一次对话如何映射回结构
- 系统提示 + 历史 + 用户句 → 前缀
- Tokenizer → ids
- Prefill 写 KV
- Decode 自回归吐词
- 结束符 / 长度上限停下
- 可选:工具调用 → 结果写回前缀 → 再跑
Agent / RAG / 多轮没有换掉 Transformer;它们改桌上的材料。提示词工程有用,是因为推理时改不了权重,但改得了 Attention 能看见什么。检索条文拼进提示、工具 JSON 追加回去——都是同一座 Decoder,前缀变长而已。
16. 常见误解与问题
- 注意力权重 ≠ 可解释的「想法」
- 下一词预测 ≠ 理解世界;幻觉与似然目标同源
- 参数大 ≠ 一定更强
- BERT 做生成过时,做检索/编码仍香
- 没有 RNN ≠ 没有顺序(位置编码 + 因果掩码)
- 多头未必美丽分工
- (O(n^2)) 是真约束,但硬件 + 算法 + 产品窗口把可用区推得很远
Transformer vs GPT:架构族 vs 其中一条 Decoder-only + 语言建模 + 对齐的产品线。
还是 2017 那张图吗:积木语法还在;塔形、位置、Norm、激活、对齐与系统层已迭代多轮。
下一步:nanoGPT 级实现,或打开一份 config.json 对照第 12 节。
MoE / Mamba:前者多半是 Transformer + 专家 FFN;后者是另一类序列混合。先懂 QKV。
17. 收束
- 开会代替传话 → 可并行、短路径
- QKV → 找什么、怎么被找到、贡献什么
- 掩码 → 能否看未来
- Attention 路由,FFN 变换;残差与 Norm 让深度成立
- 大模型 = 同骨架 × 规模 × 数据 × 对齐
1 | 文本 → Token / 向量 / 位置 |
延伸阅读
- Attention Is All You Need
- The Illustrated Transformer(Jay Alammar)
- The Annotated Transformer(哈佛 NLP)
- 同站:激活函数的前世今生 · 人工智能发展路线 · 什么是RAG