引言:Transformer的革命性意义
2017年,Google提出的Transformer架构彻底改变了深度学习领域。它抛弃了RNN和CNN,完全基于Self-Attention机制构建,成为现代NLP的基石。
为什么Transformer如此重要?
三大突破:
- 并行化:不再依赖顺序处理,训练速度大幅提升
- 长距离依赖:通过Self-Attention直接建立任意距离的连接
- 可扩展性:催生了BERT、GPT、T5等大规模预训练模型
核心思想:用Attention机制替代循环结构,让模型能够同时关注序列中的所有位置。
一、Transformer整体架构
Transformer采用经典的Encoder-Decoder结构,但完全基于Attention机制。
架构概览
输入序列 → Encoder → 编码表示 → Decoder → 输出序列核心组件:
- Encoder:将输入序列编码为上下文表示
- Decoder:基于编码表示生成输出序列
- Multi-Head Attention:多头注意力机制
- Feed-Forward Network:前馈神经网络
- Positional Encoding:位置编码
Encoder-Decoder结构
Encoder(编码器):
- 由N个相同的层堆叠(原论文N=6)
- 每层包含:Multi-Head Self-Attention + Feed-Forward Network
- 输出:输入序列的上下文表示
Decoder(解码器):
- 同样由N个相同的层堆叠
- 每层包含:Masked Self-Attention + Cross-Attention + Feed-Forward Network
- 输出:目标序列
二、Encoder详解
Encoder负责理解输入序列,提取上下文信息。
Encoder层结构
每个Encoder层包含两个子层:
1. Multi-Head Self-Attention
作用:让每个位置关注输入序列的所有位置
特点:
- 并行计算,无顺序依赖
- 捕捉序列内部的依赖关系
- 多个头关注不同的模式
并行化的物理基础:矩阵运算
Transformer 能够并行计算的根本原因是所有操作都是矩阵运算。
RNN 的串行瓶颈:
h_1 = f(x_1)h_2 = f(x_2, h_1) ← 必须等待 h_1 计算完成h_3 = f(x_3, h_2) ← 必须等待 h_2 计算完成Transformer 的并行计算:
Q = X · W^Q ← 所有位置同时计算K = X · W^K ← 所有位置同时计算V = X · W^V ← 所有位置同时计算
Attention = softmax(QK^T / √d_k) · V ← 矩阵乘法,GPU 高度优化关键洞察:
- 矩阵乘法天然并行:GPU 可以同时计算所有元素
- 无数据依赖:每个位置的 Q/K/V 计算互不依赖
- 批量处理:整个序列作为一个矩阵,一次性处理
这就是为什么 Transformer 训练速度远超 RNN 的根本原因!
2. Feed-Forward Network
作用:对每个位置独立进行非线性变换
特点:
- 两层全连接网络,中间使用ReLU激活
- 对每个位置使用相同的参数
- 增加模型的表达能力
残差连接与层归一化
每个子层后都有:
作用:
- 残差连接:帮助梯度传播
- 层归一化:稳定训练过程
为什么用 Layer Norm 而不是 Batch Norm?
这是一个重要的设计选择,背后有深刻的原因。
Batch Norm 的问题:
- 对 Batch 维度做归一化:
- 在 NLP 任务中,句子长度不一(有的长,有的短)
- 短句子需要 Padding,Padding 的值会影响统计量
- Batch 大小变化时,归一化效果不稳定
Layer Norm 的优势:
- 对单个样本的特征维度做归一化:
- 不受 Batch 大小影响
- 不受句子长度影响(Padding 不会干扰)
- 每个样本独立归一化,更稳定
直观对比:
Batch Norm: 对一个 Batch 内所有句子的"同一个位置"做归一化 → 受 Padding 和 Batch 大小影响
Layer Norm: 对单个句子的"所有维度"做归一化 → 只关注句子内部,不受外部影响关键洞察:Layer Norm 更适合序列模型(RNN/Transformer),因为它不依赖 Batch 统计量,训练和推理时行为一致。
三、Decoder详解
Decoder负责生成输出序列,同时利用Encoder的编码信息。
训练 vs 推理:Decoder的两种工作模式
这是Transformer最容易让人困惑的地方,理解这个区别至关重要。
推理(Inference):串行生成
工作方式:

- 自回归(Autoregressive):一个词一个词地生成
- 上一步的输出是下一步的输入
- 必须等待前一个词生成完才能生成下一个词
示例:
步骤1: <START> → "我"步骤2: <START> "我" → "爱"步骤3: <START> "我" "爱" → "学习"步骤4: <START> "我" "爱" "学习" → <END>停止机制:
Decoder 如何知道什么时候停止生成?答案是
工作原理:
- 词表中包含特殊标记
<EOS>(或<END>、</s>等) - Decoder 每步输出一个词的概率分布:
- 当模型输出
<EOS>的概率最高时,生成停止
具体流程:
步骤1: softmax([0.8(我), 0.1(你), 0.05(他), 0.001(<EOS>), ...]) → 选择"我"步骤2: softmax([0.7(爱), 0.2(是), 0.05(在), 0.002(<EOS>), ...]) → 选择"爱"步骤3: softmax([0.6(学习), 0.3(编程), 0.08(<EOS>), ...]) → 选择"学习"步骤4: softmax([0.05(。), 0.02(!), 0.85(<EOS>), ...]) → 选择<EOS>,停止关键洞察:
<EOS>是模型学习到的”句子结束信号”- 训练时,正确答案的最后一个词后面就是
<EOS> - 推理时,模型自己决定何时输出
<EOS>
问题:
- 串行处理:无法并行,速度慢
- 误差累积(Error Propagation):一步错,步步错
训练(Training):并行计算
工作方式:
- Teacher Forcing:把正确答案直接喂给模型
- 配合 Masked Attention,所有位置可以同时计算
- 虽然结构是串行的,但训练时是并行的
示例:
输入(正确答案): <START> "我" "爱" "学习"目标输出: "我" "爱" "学习" <END>
通过 Mask 确保:- 位置1只能看到 <START>- 位置2只能看到 <START> "我"- 位置3只能看到 <START> "我" "爱"- 位置4只能看到 <START> "我" "爱" "学习"优势:
- 并行训练:所有位置同时计算损失和梯度
- 训练效率高:这是Transformer相比RNN的核心优势
- 稳定训练:使用正确答案,避免误差累积
关键洞察:Decoder在训练和推理时的行为完全不同!训练时的并行化是Transformer训练速度快的根本原因。
Decoder层结构
每个Decoder层包含三个子层:
1. Masked Multi-Head Self-Attention
作用:让每个位置只能关注之前的位置,防止”看到未来”
实现:通过掩码矩阵将未来位置的注意力分数设为
位置1: 只能看到位置1位置2: 只能看到位置1, 2位置3: 只能看到位置1, 2, 32. Cross-Attention(Encoder-Decoder Attention)
作用:让Decoder关注Encoder的输出
机制:
- Query来自Decoder
- Key和Value来自Encoder
- 建立输入和输出之间的对应关系
生动理解:读书找线索
把 Encoder 的输出想象成**“一本读完的书(上下文)”**:
- 书里记录了输入序列的所有信息
- 每个词的表示就是书中的一个”知识点”
Decoder 每生成一个字(Query),就像是**“拿着放大镜去书里找线索”**:
-
Query(当前状态):决定了”我要找什么”
- 例如:正在翻译”机器学习”,Query 就是”当前翻译进度和需求”
-
Attention Score:决定了”我从书里提取多少信息”
- 高分:这个位置的信息很重要,多看看
- 低分:这个位置的信息不太相关,略过
-
加权求和:把找到的线索综合起来
- 最终输出 = 从书中提取的相关信息的加权组合
关键洞察:Cross-Attention 是 Decoder 和 Encoder 之间的”桥梁”,让生成过程能够动态地参考输入信息。
3. Feed-Forward Network
与Encoder中的FFN结构相同。
四、关键组件详解
1. Positional Encoding
问题:Self-Attention不知道词的顺序
解决方案:在输入嵌入中加入位置信息
特点:
- 使用正弦和余弦函数
- 可以处理任意长度的序列
- 相对位置关系可以通过三角函数性质表示
为什么是相加而不是拼接?
这是一个非常重要的问题:为什么位置编码要加到词向量上,而不是拼接在一起?
直觉理解:
在高维空间中,相加其实等同于一种特殊的拼接。
假设词嵌入是 ,位置编码是 :
拼接方案:
- 需要更大的模型维度
- 参数量翻倍
相加方案:
- 保持原有维度
- 参数量不变
关键洞察:经过线性变换后,两种方案在数学上是等价的!
为什么相加不会”破坏”语义?
在高维空间(如512维)中,两个向量相加后:
- 原始信息并不会丢失
- 通过不同的投影矩阵(),模型可以提取出词向量和位置编码的不同组合
- 就像把两种颜料混合,虽然看起来是一种颜色,但通过光谱分析仍然可以分离出原始成分
优势:
- 参数效率:维度不变,参数量不增加
- 维度一致性:所有层的输入输出维度保持一致
- 信息融合:词义和位置在输入时就已经融合,模型可以直接使用
2. Multi-Head Attention
核心思想:从多个角度理解序列
计算流程:
- 将输入投影到多个子空间(多个头)
- 每个头独立计算注意力
- 拼接所有头的输出
- 通过线性变换融合信息
物理意义:不同的头学习不同的模式
Multi-Head 不仅仅是”多做几次”,而是让模型在不同的子空间里互不干扰地学习不同的语法/语义模式。
具体例子:
Head 1:关注局部信息(Local)
- 捕捉相邻词之间的关系
- 例如:“机器学习”中,“机器”主要关注”学习”
- 识别固定搭配、短语结构
Head 2:关注长距离依赖(Global)
- 捕捉句子中远距离的语法关系
- 例如:“我昨天把那台坏掉的电脑修好了”
- “我”(主语)需要关注”修好了”(谓语)
- 虽然中间隔了很多词,但主谓关系必须建立
Head 3:关注语义相似性
- 捕捉语义相关的词
- 例如:“深度学习是机器学习的一个分支”
- “深度学习”和”机器学习”语义相关
Head 4:关注句法结构
- 捕捉修饰关系、从属关系
- 例如:“那只在公园里奔跑的狗”
- “狗”需要关注”奔跑”(动作)和”公园”(地点)
关键洞察:
- 每个头在自己的子空间里成为”专家”
- 不同类型的相关性不会互相干扰
- 最后通过 矩阵融合所有头的发现
为什么需要多个头?
- 单个头可能只关注一种模式,容易遗漏重要信息
- 多个头可以同时捕捉语法、语义、位置等多种关系
- 就像一个团队,每个人负责不同的视角,最后综合所有意见
3. Feed-Forward Network
结构:
FFN(x) = ReLU(xW1 + b1)W2 + b2参数:
- 输入/输出维度:512(d_model)
- 隐藏层维度:2048(d_ff)
五、训练技巧
1. 学习率调度
使用Warmup策略:
特点:
- 前期学习率线性增加(warmup)
- 后期学习率逐渐衰减
2. Label Smoothing
作用:防止模型过度自信
3. Dropout
在以下位置应用Dropout:
- 注意力权重
- Feed-Forward Network的输出
- 残差连接之前
六、PyTorch实现
Transformer Block
import torchimport torch.nn as nn
class TransformerBlock(nn.Module): def __init__(self, d_model, num_heads, d_ff, dropout=0.1): super().__init__() self.attention = nn.MultiheadAttention(d_model, num_heads, dropout=dropout) self.norm1 = nn.LayerNorm(d_model) self.norm2 = nn.LayerNorm(d_model)
self.ffn = nn.Sequential( nn.Linear(d_model, d_ff), nn.ReLU(), nn.Dropout(dropout), nn.Linear(d_ff, d_model) )
self.dropout = nn.Dropout(dropout)
def forward(self, x, mask=None): # Self-Attention attn_output, _ = self.attention(x, x, x, attn_mask=mask) x = self.norm1(x + self.dropout(attn_output))
# Feed-Forward ffn_output = self.ffn(x) x = self.norm2(x + self.dropout(ffn_output))
return x完整Encoder
class TransformerEncoder(nn.Module): def __init__(self, num_layers, d_model, num_heads, d_ff, dropout=0.1): super().__init__() self.layers = nn.ModuleList([ TransformerBlock(d_model, num_heads, d_ff, dropout) for _ in range(num_layers) ])
def forward(self, x, mask=None): for layer in self.layers: x = layer(x, mask) return x七、Transformer的影响与应用
预训练模型时代
Transformer催生了大规模预训练模型:
BERT(2018):
- 只使用Encoder
- 双向编码,适合理解任务
- 应用:文本分类、问答、命名实体识别
GPT系列(2018-至今):
- 只使用Decoder
- 单向生成,适合生成任务
- 应用:文本生成、对话、代码生成
T5(2019):
- 完整的Encoder-Decoder结构
- 统一的Text-to-Text框架
- 应用:翻译、摘要、问答
跨领域应用
计算机视觉:
- Vision Transformer (ViT)
- DETR(目标检测)
语音处理:
- Speech Transformer
- Wav2Vec 2.0
多模态:
- CLIP
- DALL-E
八、Transformer 与其他模型的关系
理解 Transformer 与传统模型的关系,有助于从更高的理论视角理解其设计。
Self-Attention vs CNN
CNN 可以看作是一种受限的 Self-Attention。
CNN 的局限性:
- 固定的感受野:卷积核大小固定(如 3×3),只能看到局部信息
- 权重共享:所有位置使用相同的卷积核
- 需要堆叠多层:才能扩大感受野,捕捉长距离依赖
Self-Attention 的优势:
- 全局感受野:每个位置可以直接关注所有位置
- 动态权重:注意力权重根据输入内容动态计算
- 一步到位
(1) 复杂度建立任意距离的连接
直观对比:
CNN: 每个位置只能看到固定窗口内的邻居 [●]---[●]---[●] (3×3 卷积核)
Self-Attention: 每个位置可以看到所有位置,权重动态调整 [●]←→[●]←→[●]←→[●] (全连接,权重可学习)关键洞察
Self-Attention vs GNN
Self-Attention 本质上是一个全连接的图神经网络(GNN)。
图神经网络视角:
- 节点(Node):序列中的每个 token
- 边(Edge):任意两个 token 之间都有连接(全连接图)
- 边权重:注意力分数
- 消息传递:通过注意力机制聚合邻居信息
数学形式对比:
GNN 的消息传递:
Self-Attention:
关键区别:
- GNN:图结构通常是稀疏的,只聚合邻居节点信息
- Self-Attention:图结构是完全图,每个节点与所有节点相连
九、Transformer vs RNN/CNN
| 特性 | RNN | CNN | Transformer |
|---|---|---|---|
| 并行化 | 不可并行 | 可并行 | 完全并行 |
| 长距离依赖 | 困难 | 需要堆叠多层 | O(1)直接连接 |
| 计算复杂度 | O(n·d²) | O(k·n·d²) | O(n²·d) |
| 归纳偏置 | 顺序性 | 局部性 | 无 |
| 数据需求 | 中等 | 较少 | 大量 |
关键洞察:
- Transformer用计算换灵活性
- 需要大量数据学习有效的模式
- 在大规模数据上表现最佳
九、总结
Transformer架构的核心创新:
- 完全基于Attention:抛弃RNN和CNN
- 并行化训练:大幅提升训练效率
- 可扩展性:支持大规模预训练
关键组件:
- Multi-Head Self-Attention:捕捉序列依赖
- Positional Encoding:编码位置信息
- Encoder-Decoder:统一的序列到序列框架
致谢
本笔记在学习李宏毅老师的深度学习课程(LeeDL)时完成。感谢李宏毅老师对Transformer架构的详细讲解。
相关资源:
部分信息可能已经过时









