Transformer 与大模型原理
Transformer 与注意力机制详解:Q、K、V、多头注意力与解码器结构
进阶 25 分钟 适合: 初学者 / 开发者 / 研究者
本课要点
- ▸自注意力让每个 token 把其他 token 的信息按权重混合,生成自己的新表示;权重由查询和键的相似度算出。
- ▸Attention(Q, K, V) = softmax(QKᵀ / √dₖ) · V;多头注意力并行运行多组这样的计算,捕捉不同类型的关系。
- ▸GPT 类大模型是纯解码器 Transformer:因果掩码让每个 token 看不到后面的内容,这正是“预测下一个 token”训练的前提。
- ▸一个 Transformer 层 = 注意力 + 前馈网络,各自包着残差连接和归一化,再叠几十层。
注意力要解决什么问题
看这句话:“那只动物没有过马路,因为它太累了。” 要理解“它”,模型得把它和“动物”而不是“马路”联系起来。把“太累了”换成“太宽了”,答案就反过来。词的含义取决于其他词,而且有时离得很远。
早期模型(RNN、LSTM)一次读一个 token,把一切压进一个不断更新的记忆里,远距离的联系难以建立,训练也慢。注意力最早是加在这类模型上做翻译的(Bahdanau 等,2014);Transformer(Vaswani 等,2017)更进一步,整个模型都用注意力搭建,论文标题就叫 Attention Is All You Need。
自注意力四步走
每个 token 一开始是一个向量(它的 embedding,见 Token 与 Embedding)。对每个 token,这一层用三个学出来的矩阵分别算出三个新向量:
- 查询(Query,Q):“我在找什么?”
- 键(Key,K):“我身上有什么?”
- 值(Value,V):“如果被选中,我传递什么信息?”
然后:
- 打分:用点积比较这个 token 的查询和每个 token 的键,分数高表示“相关”。
- 缩放:除以 √dₖ(键向量长度的平方根),让分数保持在训练稳定的范围。
- 归一化:用 softmax 把分数变成加起来等于 1 的正权重。
- 混合:这个 token 的输出 = 所有值向量的加权和。
写成矩阵形式,一次算出所有 token:
Attention(Q, K, V) = softmax(Q·Kᵀ / √dₖ) · V
flowchart LR X["token 向量"] --> Q["Q = X·Wq"] X --> K["K = X·Wk"] X --> V["V = X·Wv"] Q --> S["分数 = Q·Kᵀ / √dk"] K --> S S --> M["因果掩码(遮住后面的 token)"] M --> SM["softmax → 注意力权重"] SM --> O["权重 · V = 新的 token 向量"] V --> O
对例句中的“它”,训练好的注意力头会给“动物”很大的权重,于是“它”的新向量就带上了关于那只动物的信息。
多头注意力
一组权重一次只能表达一种关系。多头注意力并行运行多个注意力计算(称为“头”),每个头有自己的 Q/K/V 矩阵,最后把输出拼起来。原始 Transformer 用 8 个头,大模型用几十个。不同的头会各自追踪不同的东西:前一个 token、句法主语、配对的括号、重复出现的短语等(见 大模型内部学到了什么)。
词序从哪里来?
注意力本身把输入当成一个集合:打乱 token 顺序,分数不会变。所以 Transformer 要额外加入位置信息。2017 年的论文把固定的正弦/余弦模式加到 embedding 上;如今多数大模型使用旋转位置编码(RoPE)(苏剑林等,2021),按位置旋转 Q 和 K 向量,让分数取决于相对距离。
纯解码器 Transformer(GPT 式)
原始 Transformer 有编码器(读原文)和解码器(写译文)。GPT 系列(Radford 等,2019)和几乎所有聊天大模型只保留了解码器,并加上因果掩码:每个 token 只能关注自己和前面的 token。这样,过一遍训练文本,就能同时在每一个位置上得到“下一个 token”的预测,训练效率极高。
一个 Transformer 层(block) 包括:
- 归一化 → 带掩码的多头自注意力 → 把输入加回来(残差连接)。
- 归一化 → 前馈网络(两层线性变换夹一个非线性,对每个 token 单独计算)→ 残差连接。
flowchart TB
IN["token 向量(embedding + 位置)"] --> N1["归一化"] --> A["带掩码的多头注意力"] --> R1(("+"))
IN --> R1
R1 --> N2["归一化"] --> F["前馈网络"] --> R2(("+"))
R1 --> R2
R2 --> NEXT["…… 重复 N 层 ……"] --> HEAD["最终归一化 → 线性层 → 词表上的 softmax"]把这个层叠几十次(GPT-3 最大的版本有 96 层),最后加一层把末尾的向量变成词表上的概率,就是一个大模型。残差连接就像一条共享的“信息流”,每一层都从中读取、再往里写入。
注意力的代价
因为每个 token 都要和其他所有 token 比较,分数矩阵随序列长度的平方增长:上下文翻倍,这部分工作量大约变成四倍。FlashAttention(Dao 等,2022)、分组查询注意力、生成时使用的 KV Cache(见 大模型如何生成文本)等工程进展,才让百万 token 级别的上下文窗口变得可用。
亲眼看看
小型开源模型可以用 llama.cpp 或苹果的 MLX LM 在笔记本上运行;它们的模型卡会写明层数、注意力头数和隐藏层大小,正是本课讲的这些量。想看图解,推荐 Jay Alammar 的 The Illustrated Transformer 和哈佛的 The Annotated Transformer(附代码)。
算法卡片
| 算法 | 一句话 | 原始论文 |
|---|---|---|
| Transformer 与自注意力 | 完全基于注意力、可并行训练的序列模型,是所有大模型的骨架 | Vaswani 等,2017 |
| BERT | 双向 Transformer 编码器,通过“完形填空”预训练 | Devlin 等,2018 |
| T5 | 把所有 NLP 任务统一成“输入文本→输出文本” | Raffel 等,2019 |
| GPT-3 与上下文学习 | 足够大的模型只看几个例子就能完成新任务 | Brown 等,2020 |
| 旋转位置编码 RoPE | 旋转 Q/K 向量来编码位置,让注意力天然感知相对距离 | Su 等,2021 |
| 层归一化 LayerNorm | 在单个样本内部做标准化,不依赖 batch | Ba 等,2016 |
必读论文
- Attention Is All You Need(2017)——提出 Transformer,本课的全部内容都出自这篇。arXiv:1706.03762
- BERT(2018)——只用编码器、双向注意力的路线,理解“编码器 vs 解码器”的最好对照。arXiv:1810.04805
- Language Models are Few-Shot Learners(GPT-3,2020)——纯解码器 Transformer 放大后出现上下文学习。arXiv:2005.14165
动手项目(约 16 学时)
照着 nanoGPT 在莎士比亚或中文古诗语料上训练一个字符级 GPT,然后取出某一层的注意力权重画成热力图,看看不同注意力头分别在“看”什么。想先理解代码,可配合 The Annotated Transformer 和 Karpathy 的 Let's reproduce GPT-2 (124M);系统学习可看 Stanford CS224N。
自测
1. 注意力分数为什么要除以 √dₖ?
维度越高,点积的数值越大,softmax 会变得极端(几乎只剩一个 1),梯度也随之消失;除以 √dₖ 把分数拉回合适的范围。
2. 因果掩码有什么作用?
让每个位置只能看到它之前的 token,看不到“答案”,这样才能用“预测下一个 token”来训练,也和生成时一次出一个 token 的方式一致。
3. 多头注意力比单头好在哪?
不同的头在不同的子空间里计算注意力,可以同时关注不同类型的关系(例如语法搭配和指代),再把结果拼起来。
4. 上下文长度翻倍,注意力分数矩阵的计算量大约变成多少倍?
大约 4 倍,因为它随序列长度的平方增长。
常见问题
为什么叫“注意力”?
因为模型会为每个 token 计算它应该“关注”其他每个 token 多少,得到一组加起来等于 1 的权重,再主要从权重高的 token 那里读取信息。
Transformer 为什么取代了 RNN?
RNN 必须一个接一个地处理 token,训练慢,也难以捕捉远距离依赖。注意力把所有位置直接连起来,还能在 GPU 上并行计算,所以 Transformer 能扩展到大得多的数据和参数规模。
为什么上下文越长,注意力越贵?
每个 token 都要和其他所有 token 比较,所以注意力分数的计算量和内存随序列长度的平方增长。FlashAttention、分组查询注意力和 KV Cache 等技术降低了实际开销。