深入理解 Transformer 架构:从注意力机制到完整计算流程
Transformer 是当今所有大语言模型(GPT、BERT、LLaMA、Claude……)的基础架构。2017 年,Vaswani 等人在论文 Attention Is All You Need 中提出了它,此后它几乎替代了 RNN 和 CNN,成为 NLP 乃至视觉、语音等领域的通用模型骨架。
这篇文章尝试从零讲清 Transformer 的完整计算流程:输入一个句子,数据在模型内部经历了什么?每一步的数学是什么?为什么这样设计?
建议搭配 3D 交互式模型阅读:Transformer Architecture 3D Explorer——可以在浏览器中旋转、点击每个组件查看内部结构和计算细节。
1. 整体架构:Encoder-Decoder
原始 Transformer 采用 Encoder-Decoder 结构:
- Encoder(编码器):读取输入序列,逐层提取表示。每一层包含两个子层:多头注意力 + 前馈网络。层数通常为 6-24 层(原始论文 6 层)。
- Decoder(解码器):逐个生成输出 token。每一层包含三个子层:掩码自注意力 + 交叉注意力 + 前馈网络。
- Nx:Encoder 和 Decoder 各重复 N 次,每层有独立的参数。
Encoder Decoder
┌──────────────────┐ ┌──────────────────────────┐
│ Add & Norm │ │ Add & Norm │
│ Feed Forward │ │ Feed Forward │
│ Add & Norm │ │ Add & Norm │
│ Multi-Head │ │ Cross-Attention ← Encoder│
│ Attention │ │ Add & Norm │
│ Add & Norm │ │ Masked Multi-Head │
│ Pos Encoding │ │ Attention │
│ Input Embedding │ │ Pos Encoding │
│ │ │ Output Embedding │
└──────────────────┘ └──────────────────────────┘
↑ 输入 ↑ 输出注意图中每条线除了串行连接外,还有残差连接(Skip Connection)——输入直接跳接到子层输出后面,这是一个关键设计。
2. 输入处理:从文字到向量
2.1 分词(Tokenization)
模型不直接处理文字,而是先将句子切分为 token。以「今天天气怎么样」为例:
今天天气怎么样 → [今, 天, 天, 气, 怎, 么, 样]
→ Token IDs: [1025, 2098, 2098, 3841, 5563, 3789, 4102]分词方式可以是字级别、子词级别(BPE、WordPiece)或词级别。现代模型多用 BPE,将常见词保持完整,罕见词拆成子词。
2.2 输入嵌入(Input Embedding)
每个 token ID 通过查表得到一个 d_model 维的向量:
$$E(x_i) = W_{\text{emb}}[x_i] \in \mathbb{R}^{d_{\text{model}}}$$
其中 $W_{\text{emb}}$ 是一个 (vocab_size, d_model) 的嵌入矩阵,通过训练学习。语义相近的 token 在向量空间中距离更近——比如「猫」和「狗」的向量会比「猫」和「汽车」更接近。
典型值:d_model = 512(原始论文)到 4096(GPT-3),vocab_size = 30,000 ~ 50,000。
2.3 位置编码(Positional Encoding)
Transformer 没有循环结构(不像 RNN 天然有序),需要额外注入位置信息。原始论文用正弦/余弦函数生成固定编码:
$$PE_{(pos, 2i)} = \sin\left(\frac{pos}{10000^{2i/d_{\text{model}}}}\right)$$
$$PE_{(pos, 2i+1)} = \cos\left(\frac{pos}{10000^{2i/d_{\text{model}}}}\right)$$
不同维度使用不同频率的正弦波——低维度变化快(区分相邻位置),高维度变化慢(区分远距离位置)。最终的输入是嵌入向量 + 位置编码的逐元素相加:
$$\text{Input} = E(x_i) + PE_{pos_i}$$
3. 核心机制:多头注意力(Multi-Head Attention)
这是 Transformer 的心脏。自注意力让模型在看每个词时,能动态关注序列中的其他词。
3.1 单头注意力的计算
给定输入 $X$,先通过三个线性投影得到 Query、Key、Value:
$$Q = X W^Q, \quad K = X W^K, \quad V = X W^V$$
然后计算注意力:
$$\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right) V$$
直觉理解:假设你在读「今天天气怎么样,今天是晴天」这句话,遇到「是」这个词时,注意力机制让模型回头看句子中每个词,计算「是」和每个词的关联度(QK 点积),然后用这个关联度加权求和(·V),得到「是」的上下文表示。
为什么除以 $\sqrt{d_k}$? 当维度 $d_k$ 较大时,点积的方差会很大,导致 softmax 输出接近 one-hot(梯度消失)。缩放后分布更平滑,梯度更稳定。
3.2 多头的意义
单头注意力只能学一种关联模式。多头注意力并行运行 h 个独立的注意力头,每个头用不同的 $W^Q, W^K, W^V$ 投影到不同的子空间:
$$\text{head}_i = \text{Attention}(QW_i^Q, KW_i^K, VW_i^V)$$
$$\text{MultiHead}(Q, K, V) = \text{Concat}(\text{head}_1, …, \text{head}_h) W^O$$
每个头可以关注不同的关系:一个头关注语法关系(主语-谓语),另一个关注语义关系(代词-指代对象),还有一个关注位置关系(相邻词)。
典型值:h = 8(原始论文)到 96(GPT-3),$d_k = d_v = d_{\text{model}} / h$。
3.3 三种注意力类型
Transformer 中有三种注意力,用途不同:
| 类型 | Q 来源 | K,V 来源 | 用途 |
|---|---|---|---|
| 自注意力 | Encoder 当前层 | Encoder 当前层 | 理解输入序列内部关系 |
| 掩码自注意力 | Decoder 当前层 | Decoder 当前层 | 理解已生成的输出(下三角掩码防止看到未来) |
| 交叉注意力 | Decoder 当前层 | Encoder 最后一层 | Decoder 在生成时参考 Encoder 的理解 |
掩码自注意力的掩码是一个下三角矩阵:
$$M_{ij} = \begin{cases} 0 & \text{if } i \geq j \ -\infty & \text{if } i < j \end{cases}$$
softmax 之前加上 $M$,使得位置 $i$ 只能看到位置 $\leq i$ 的信息——因为生成第 $i$ 个词时,第 $i+1$ 个词还没生成。
4. 残差连接与层归一化(Add & Norm)
每个子层(注意力或 FFN)都被包裹在一个 Add & Norm 结构中:
$$\text{output} = \text{LayerNorm}(x + \text{SubLayer}(x))$$
残差连接($x + \text{SubLayer}(x)$)的作用是:
- 梯度可以不经过子层直接回传,缓解深层网络的梯度消失
- 模型至少能学到恒等映射(skip 子层),不会比浅层网络更差
- 训练更稳定、收敛更快
层归一化(LayerNorm)对每个样本的特征维度做归一化:
$$\text{LN}(x) = \gamma \odot \frac{x - \mu}{\sqrt{\sigma^2 + \epsilon}} + \beta$$
其中 $\mu$ 和 $\sigma^2$ 是该样本在特征维度上的均值和方差,$\gamma$ 和 $\beta$ 是可学习的缩放和偏移参数。归一化稳定了每层输出的数值范围,加速训练收敛。
5. 前馈网络(Feed Forward Network)
每个层的第二个子层是一个逐位置的全连接网络:
$$\text{FFN}(x) = \max(0, xW_1 + b_1)W_2 + b_2$$
先从 $d_{\text{model}}$ 升维到 $d_{\text{ff}}$(通常 $4 \times d_{\text{model}}$),经过 ReLU(或 GELU)激活,再降回 $d_{\text{model}}$。
$$d_{\text{model}} \xrightarrow{W_1} 4 \times d_{\text{model}} \xrightarrow{\text{ReLU}} 4 \times d_{\text{model}} \xrightarrow{W_2} d_{\text{model}}$$
为什么需要 FFN? 注意力层负责信息混合(不同位置之间的交互),FFN 负责非线性变换(增加模型的表达能力)。两者缺一不可。
注意 FFN 是「逐位置」的——它对每个 token 独立作用,不同位置之间没有信息交换。信息交流完全由注意力层完成。
6. 输出层:线性投影 + Softmax
Decoder 最后一层的输出经过一个线性变换,投影到词汇表大小:
$$\text{logits} = X_{\text{final}} W_{\text{out}} + b$$
然后 Softmax 得到概率分布:
$$P(\text{token}_i) = \frac{e^{\text{logits}_i}}{\sum_j e^{\text{logits}_j}}$$
概率最高的 token 就是当前位置的预测输出。生成时通常用 beam search 或 top-k sampling 而不是简单的贪心选择。
训练时的损失函数是交叉熵:
$$\mathcal{L} = -\sum_i \log P(\text{token}_{\text{correct}}^{(i)})$$
7. 完整计算流程示例
以机器翻译为例,输入「今天天气怎么样」→ 输出「How is the weather today」:
Step 1: 分词 → Token IDs
Step 2: 查表得到嵌入向量 E(x_i)
Step 3: 加上位置编码 PE → Input = E + PE
Step 4: Encoder ×6 层(每层: Multi-Head Attention → Add&Norm → FFN → Add&Norm)
Step 5: Decoder 逐步生成:
- 输入已生成的 token(初始只有 <BOS>)
- Masked Self-Attention(只看已生成的部分)
- Cross-Attention(Q 来自 Decoder,K/V 来自 Encoder 输出)
- FFN → Add&Norm
- Linear → Softmax → 预测下一个 token
- 重复直到生成 <EOS>可以在 3D 交互式 Explorer 中点击「📊 开始数据流演示」按钮,看一个完整的数值计算示例(输入「今天天气怎么样」→ 输出「今天是晴天」),每一步都有具体的假想数值(d_model=4 简化展示)。
8. 变体与发展
原始 Transformer 之后出现了多种变体:
| 模型 | 架构变化 | 特点 |
|---|---|---|
| BERT | 只用 Encoder | 双向理解,适合分类、NER |
| GPT | 只用 Decoder | 自回归生成,适合文本生成 |
| T5 | Encoder-Decoder | 文本到文本统一框架 |
| LLaMA | Decoder-only,改进归一化和激活函数 | 开源大模型标杆 |
| Mixture of Experts | FFN 替换为多个专家子网络 | 稀疏激活,参数效率更高 |
现代大模型几乎都是 Decoder-only 架构(GPT 路线),原因是:
- 生成任务更通用(prompt + completion 统一了理解和生成)
- Encoder-Decoder 在大规模训练中效率不如纯 Decoder
- 自回归训练更简单,易于扩展
参考
- Vaswani, A., et al. Attention Is All You Need (2017) — 原始论文
- Jay Alammar, The Illustrated Transformer — 最经典的图文教程
- Lilian Weng, Attention? Attention! — 注意力机制的深入解析
- Peter Bloem, Transformers from Scratch — 从实现角度讲解
转载请注明出处