Appearance
Encoder与Decoder
完整的 Transformer 由两个可独立使用的部件组成:编码器(Encoder)负责「理解输入」,解码器(Decoder)负责「生成输出」。理解它们的差异,是理解 BERT / GPT 为什么各自「只用一半」的基础。
1. 各自的结构
Encoder 层 Decoder 层
┌──────────────────┐ ┌──────────────────────┐
│ 多头自注意力(无掩码)│ │ 多头自注意力(因果掩码) │ ← 只看已生成部分
│ Add & Norm │ │ Add & Norm │
│ │ │ 交叉注意力(Q=解码,V/K=编)│ ← 回看源句
│ FFN │ │ Add & Norm │
│ Add & Norm │ │ FFN │
└──────────────────┘ │ Add & Norm │
2 个子层 └──────────────────────┘
3 个子层(多一个 Cross-Attn)2. 核心差异对照
| 维度 | Encoder | Decoder |
|---|---|---|
| 自注意力可见范围 | 双向(能看全句) | 单向(因果掩码,只看过去) |
| 是否有交叉注意力 | 无 | 有(看编码器输出) |
| 角色 | 理解 / 表示输入 | 条件生成输出 |
| 能否并行训练 | 能 | 训练能、生成不能 |
| 典型代表 | BERT | GPT |
3. 编码器:为什么能「双向看」
编码器处理的是已经完整给定的输入(源句、待分类的句子),没有「未来泄露」问题,所以每个词都能大方地看左右两边:
输入: 我 喜欢 你
"喜欢" 同时看 ← 我 和 你 → 得到最丰富的上下文表示这让编码器产出高质量的双向理解表示,非常适合「读懂任务」。
4. 解码器:为什么要「因果掩码」
解码器的任务是逐词生成。生成第 t 个词时,未来的词还不存在;若训练时能偷看未来,就和真实生成场景不一致(训练作弊)。于是用因果掩码把未来遮住:
生成 "我爱你" 时,位置"爱"的可见范围:
<bos> 我 [爱] 你?
✓ ✓ ✓ ✗ ← "你"还没生成,必须遮住5. 交叉注意力:连接两座岛的桥
这是 Decoder 独有、也最容易被忽视的一层:
自注意力: Q,K,V 都来自解码器 → "我生成的部分,自己理一理"
交叉注意力: Q 来自解码器, K/V 来自编码器 → "带着当前生成状态,去源句里找该翻的词" 编码器最终输出 (memory)
│ 作为 K, V
▼
Q(解码器) ──►[ Cross-Attention ]──► 融合源句信息翻译「I love you → 我爱你」时,生成「爱」这一刻,交叉注意力会让解码器把目光聚焦到源句的 "love" 上——这正是对齐(alignment) 的来源。
6. 只用一半会怎样?
前人在此基础上做了两个方向的「减法」,开创了两大家族:
完整 Transformer
├── 只保留 Encoder ──► BERT 家族(双向理解)
├── 只保留 Decoder ──► GPT 家族(单向生成)
└── 两者都保留 ──► T5 / 原始Transformer(序列到序列)- 想要「把一句话读透、抽特征」→ 用 Encoder。
- 想要「给个开头、续写下去」→ 用 Decoder。
小结
- Encoder:双向自注意力,无交叉注意力,擅长理解。
- Decoder:因果自注意力 + 交叉注意力,擅长条件生成。
- 交叉注意力是「解码器回看源句」的桥梁,也是翻译对齐的来源。
- 各取一半 → 得到 BERT(Encoder-only)与 GPT(Decoder-only)。
下一步
先看 Encoder 这一半被发挥到什么极致 → BERT架构。