人工智能之语言领域
第十二章 Transformer架构
文章目录
- 人工智能之语言领域
- [前言 Transformer架构](#前言 Transformer架构)
- [12.1 Transformer的整体架构](#12.1 Transformer的整体架构)
- [12.1.1 编码器(Encoder)结构详解](#12.1.1 编码器(Encoder)结构详解)
- [12.1.2 解码器(Decoder)结构详解](#12.1.2 解码器(Decoder)结构详解)
- [12.1.3 残差连接与层归一化](#12.1.3 残差连接与层归一化)
- [残差连接(Residual Connection)](#残差连接(Residual Connection))
- [层归一化(Layer Normalization)](#层归一化(Layer Normalization))
- [12.2 Transformer的核心组件](#12.2 Transformer的核心组件)
- [12.2.1 位置编码(Positional Encoding)](#12.2.1 位置编码(Positional Encoding))
- [正弦位置编码(Sinusoidal PE)](#正弦位置编码(Sinusoidal PE))
- [12.2.2 前馈神经网络(FFN)](#12.2.2 前馈神经网络(FFN))
- [12.3 Transformer的训练与优化](#12.3 Transformer的训练与优化)
- [12.4 Transformer的变体](#12.4 Transformer的变体)
- [12.4.1 轻量化Transformer](#12.4.1 轻量化Transformer)
- [12.4.2 长文本Transformer](#12.4.2 长文本Transformer)
- [12.5 实战:基于Transformer的机器翻译模型搭建](#12.5 实战:基于Transformer的机器翻译模型搭建)
- [Transformer 架构对比总结](#Transformer 架构对比总结)
- 小结
- 资料
前言 Transformer架构
Transformer 是自然语言处理(NLP)领域的革命性架构 ,由 Google 在 2017 年论文《Attention Is All You Need》中提出。它完全摒弃了 RNN 和 CNN ,仅依靠注意力机制实现序列建模,在机器翻译任务上首次超越传统模型,并成为 BERT、GPT 等大语言模型的基石。本章将系统解析 Transformer 的整体结构、核心组件、训练技巧、主流变体,并通过机器翻译实战完整演示其构建过程。
12.1 Transformer的整体架构
Transformer 采用经典的 Encoder-Decoder 架构,但内部完全由注意力和前馈网络堆叠而成。
源序列
(e.g., 'Hello world')
Encoder Layer 1
...
Encoder Layer N
Decoder Layer 1
...
Decoder Layer N
目标序列
(e.g., '你好 世界')
📌 关键特点:
- 并行化:无 RNN 时序依赖,训练速度极快
- 全局依赖:自注意力直接建模任意距离词间关系
- 可扩展性:堆叠更多层可提升性能(如 BERT-base: 12 层, BERT-large: 24 层)
12.1.1 编码器(Encoder)结构详解
每个 Encoder 层包含两个子层:
- 多头自注意力机制(Multi-Head Self-Attention)
- 前馈神经网络(Feed-Forward Network, FFN)
每层后接 残差连接 + 层归一化(LayerNorm)。
输入 X
+
Multi-Head
Self-Attention
LayerNorm
输出 Y
+
Position-wise
FFN
LayerNorm
✅ 作用:
- 自注意力:捕获词间依赖
- FFN:非线性变换,增强表达能力
12.1.2 解码器(Decoder)结构详解
每个 Decoder 层包含三个子层:
- 掩码多头自注意力(Masked Multi-Head Self-Attention)
- 多头跨注意力(Multi-Head Cross-Attention)
- 前馈神经网络(FFN)
同样使用残差连接 + LayerNorm。
目标输入
(已生成部分)
Masked
Self-Attention
+
LayerNorm
Cross-Attention
(K,V=Encoder输出)
Encoder输出
+
LayerNorm
FFN
+
输出
🔒 掩码机制(Masking) :
防止解码器在预测第 t 个词时"偷看"未来词( t+1, t+2, ... )。
实现:在注意力分数矩阵中,将未来位置设为 -\\infty ,经 Softmax 后权重为 0。
12.1.3 残差连接与层归一化
残差连接(Residual Connection)
- 公式: \\text{Output} = \\text{Layer}(X) + X
- 作用:缓解梯度消失,支持深层网络训练
层归一化(Layer Normalization)
- 对单个样本的所有特征做归一化(与 BatchNorm 不同)
- 公式: \\text{LayerNorm}(x) = \\gamma \\frac{x - \\mu}{\\sigma} + \\beta
- 作用:稳定训练,加速收敛
💡 顺序:先残差连接,再 LayerNorm(Post-LN);也有 Pre-LN 变体(先归一化)
12.2 Transformer的核心组件
12.2.1 位置编码(Positional Encoding)
问题 :Transformer 无 RNN/CNN,丢失序列顺序信息 !
解决方案:将位置信息注入输入嵌入。
正弦位置编码(Sinusoidal PE)
P E ( p o s , 2 i ) = sin ( p o s 10000 2 i / d ) P E ( p o s , 2 i + 1 ) = cos ( p o s 10000 2 i / d ) \begin{aligned} PE_{(pos, 2i)} &= \sin\left(\frac{pos}{10000^{2i/d}}\right) \\ PE_{(pos, 2i+1)} &= \cos\left(\frac{pos}{10000^{2i/d}}\right) \end{aligned} PE(pos,2i)PE(pos,2i+1)=sin(100002i/dpos)=cos(100002i/dpos)
其中:
- pos :词在序列中的位置(0,1,2,...)
- i :维度索引(0 到 d/2 )
- d :嵌入维度
python
import torch
import math
def positional_encoding(seq_len, d_model):
pe = torch.zeros(seq_len, d_model)
position = torch.arange(0, seq_len, dtype=torch.float).unsqueeze(1) # [seq_len, 1]
div_term = torch.exp(torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model))
pe[:, 0::2] = torch.sin(position * div_term) # 偶数维
pe[:, 1::2] = torch.cos(position * div_term) # 奇数维
return pe.unsqueeze(0) # [1, seq_len, d_model]
# 使用示例
pe = positional_encoding(50, 512) # 50个位置,512维
✅ 优势:
- 可处理任意长度序列(理论上)
- 不同位置编码正交,利于模型学习相对位置
🆚 可学习位置编码:BERT 等模型使用可训练的 Position Embedding(长度固定)
12.2.2 前馈神经网络(FFN)
每个位置独立应用相同的两层全连接网络:
FFN ( x ) = max ( 0 , x W 1 + b 1 ) W 2 + b 2 \text{FFN}(x) = \max(0, xW_1 + b_1) W_2 + b_2 FFN(x)=max(0,xW1+b1)W2+b2
- 输入/输出维度: d_{\\text{model}} (如 512)
- 隐藏层维度:通常 d_{\\text{ff}} = 2048 (4倍扩大)
💡 作用:为每个 token 提供非线性变换能力,增强模型表达力
12.3 Transformer的训练与优化
12.3.1 损失函数与优化器选择
损失函数
- 标准交叉熵损失(Cross-Entropy Loss)
- 忽略填充 token(Padding):
ignore_index=pad_id
python
criterion = nn.CrossEntropyLoss(ignore_index=0) # 假设0是<PAD>
loss = criterion(logits.view(-1, vocab_size), targets.view(-1))
优化器
- Adam 优化器(带 warmup)
- 超参: \\beta_1=0.9, \\beta_2=0.98, \\epsilon=10\^{-9}
12.3.2 训练技巧
(1)学习率调度:Warmup + Decay
- Warmup:前 n 步线性增大学习率(防早期不稳定)
- Decay:之后按平方根衰减
lr = d model − 0.5 ⋅ min ( step − 0.5 , step ⋅ warmup_steps − 1.5 ) \text{lr} = d_{\text{model}}^{-0.5} \cdot \min(\text{step}^{-0.5}, \text{step} \cdot \text{warmup\_steps}^{-1.5}) lr=dmodel−0.5⋅min(step−0.5,step⋅warmup_steps−1.5)
python
from transformers import get_linear_schedule_with_warmup
optimizer = torch.optim.Adam(model.parameters(), lr=0)
scheduler = get_linear_schedule_with_warmup(
optimizer,
num_warmup_steps=4000,
num_training_steps=total_steps
)
(2)梯度裁剪(Gradient Clipping)
- 防止梯度爆炸
- 通常裁剪到 1.0
python
torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)
12.4 Transformer的变体
12.4.1 轻量化Transformer
| 模型 | 核心思想 | 压缩方式 |
|---|---|---|
| DistilBERT | 知识蒸馏 | 用 BERT 教小模型,移除 token-type emb 和 pooler |
| MobileBERT | 瓶颈结构 | 引入 bottleneck 层减少计算量 |
| ALBERT | 参数共享 | 跨层共享参数,降低内存 |
✅ 适用场景:移动端、边缘设备部署
12.4.2 长文本Transformer
标准 Transformer 的自注意力复杂度为 O(n\^2) ,难以处理长文本(>512 tokens)。
| 模型 | 核心思想 | 复杂度 |
|---|---|---|
| Longformer | 局部窗口 + 全局注意力 | O(n) |
| BigBird | 随机注意力 + 滑动窗口 | O(n) |
| Reformer | LSH 哈希近似注意力 | O(n \\log n) |
📊 应用场景:法律文档、科研论文、书籍摘要
12.5 实战:基于Transformer的机器翻译模型搭建
任务目标
构建一个英译德的小型 Transformer,训练数据使用 Multi30k(3万句对)。
完整代码实现(PyTorch)
python
# Step 1: 安装依赖
# pip install torch torchtext spacy
import torch
import torch.nn as nn
import torch.nn.functional as F
import math
import spacy
from torchtext.data.utils import get_tokenizer
from torchtext.vocab import build_vocab_from_iterator
# Step 2: 数据预处理(简化版)
# 实际项目建议使用 torchtext.datasets.Multi30k
# 假设已有平行语料: [(src_sent, tgt_sent), ...]
train_data = [
("hello world", "hallo welt"),
("good morning", "guten morgen"),
# ... 更多数据
]
# 构建词表
def yield_tokens(data_iter, language):
for src, tgt in data_iter:
if language == 'en':
yield src.split()
else:
yield tgt.split()
vocab_en = build_vocab_from_iterator(yield_tokens(train_data, 'en'), specials=['<unk>', '<pad>', '<sos>', '<eos>'])
vocab_de = build_vocab_from_iterator(yield_tokens(train_data, 'de'), specials=['<unk>', '<pad>', '<sos>', '<eos>'])
vocab_en.set_default_index(vocab_en['<unk>'])
vocab_de.set_default_index(vocab_de['<unk>'])
# Step 3: 位置编码
class PositionalEncoding(nn.Module):
def __init__(self, d_model, max_len=5000):
super().__init__()
pe = torch.zeros(max_len, d_model)
position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1)
div_term = torch.exp(torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model))
pe[:, 0::2] = torch.sin(position * div_term)
pe[:, 1::2] = torch.cos(position * div_term)
self.register_buffer('pe', pe.unsqueeze(0))
def forward(self, x):
return x + self.pe[:, :x.size(1), :]
# Step 4: Transformer 模型
class TransformerModel(nn.Module):
def __init__(self, src_vocab_size, tgt_vocab_size, d_model=512, nhead=8,
num_encoder_layers=6, num_decoder_layers=6, dim_feedforward=2048, max_len=5000):
super().__init__()
self.d_model = d_model
self.embedding_src = nn.Embedding(src_vocab_size, d_model)
self.embedding_tgt = nn.Embedding(tgt_vocab_size, d_model)
self.pos_encoder = PositionalEncoding(d_model, max_len)
self.transformer = nn.Transformer(
d_model=d_model, nhead=nhead,
num_encoder_layers=num_encoder_layers,
num_decoder_layers=num_decoder_layers,
dim_feedforward=dim_feedforward,
batch_first=True
)
self.fc_out = nn.Linear(d_model, tgt_vocab_size)
def generate_square_subsequent_mask(self, sz):
mask = torch.triu(torch.ones(sz, sz), diagonal=1)
return mask.masked_fill(mask==1, float('-inf'))
def forward(self, src, tgt):
src_emb = self.pos_encoder(self.embedding_src(src) * math.sqrt(self.d_model))
tgt_emb = self.pos_encoder(self.embedding_tgt(tgt) * math.sqrt(self.d_model))
tgt_mask = self.generate_square_subsequent_mask(tgt.size(1)).to(src.device)
output = self.transformer(src_emb, tgt_emb, tgt_mask=tgt_mask)
return self.fc_out(output)
# Step 5: 训练设置
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = TransformerModel(len(vocab_en), len(vocab_de)).to(device)
criterion = nn.CrossEntropyLoss(ignore_index=vocab_de['<pad>'])
optimizer = torch.optim.Adam(model.parameters(), lr=0.0001, betas=(0.9, 0.98), eps=1e-9)
# Step 6: 训练循环(简化)
for epoch in range(10):
model.train()
total_loss = 0
for src_batch, tgt_batch in train_loader: # 假设有数据加载器
src = [vocab_en[token] for token in src_batch.split()]
tgt = [vocab_de[token] for token in tgt_batch.split()]
# 添加 <sos> 和 <eos>
tgt_in = [vocab_de['<sos>']] + tgt[:-1]
tgt_out = tgt
src_tensor = torch.tensor(src).unsqueeze(0).to(device)
tgt_in_tensor = torch.tensor(tgt_in).unsqueeze(0).to(device)
tgt_out_tensor = torch.tensor(tgt_out).unsqueeze(0).to(device)
optimizer.zero_grad()
output = model(src_tensor, tgt_in_tensor)
loss = criterion(output.view(-1, len(vocab_de)), tgt_out_tensor.view(-1))
loss.backward()
torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)
optimizer.step()
total_loss += loss.item()
print(f"Epoch {epoch}, Loss: {total_loss/len(train_data):.4f}")
# Step 7: 翻译函数(贪心解码)
def translate(model, src_sentence, max_len=50):
model.eval()
src = [vocab_en[token] for token in src_sentence.split()]
src_tensor = torch.tensor(src).unsqueeze(0).to(device)
tgt_tokens = [vocab_de['<sos>']]
for _ in range(max_len):
tgt_tensor = torch.tensor(tgt_tokens).unsqueeze(0).to(device)
with torch.no_grad():
output = model(src_tensor, tgt_tensor)
pred_token = output.argmax(2)[:, -1].item()
if pred_token == vocab_de['<eos>']:
break
tgt_tokens.append(pred_token)
return " ".join([vocab_de.get_itos()[i] for i in tgt_tokens[1:]])
# 测试
print(translate(model, "hello world")) # 输出: hallo welt
关键说明
| 组件 | 实现要点 |
|---|---|
| 位置编码 | 使用正弦函数,与嵌入相加 |
| 掩码 | 解码器自注意力需 future masking |
| 嵌入缩放 | 乘以 \\sqrt{d_{\\text{model}}} 保持方差一致 |
| 解码策略 | 贪心搜索(可升级为 Beam Search) |
Transformer 架构对比总结
| 模型类型 | 编码器 | 解码器 | 典型应用 |
|---|---|---|---|
| 原始 Transformer | ✓ | ✓ | 机器翻译 |
| BERT | ✓ | ✗ | 文本理解(分类、NER) |
| GPT | ✗ | ✓ | 文本生成 |
| T5 | ✓ | ✓ | 文本到文本(统一框架) |
小结
Transformer 通过纯注意力机制 实现了高效、强大的序列建模,其核心创新------自注意力、位置编码、残差连接------已成为现代 NLP 的标配。尽管存在计算开销大等挑战,但其变体(如轻量化、长文本模型)不断拓展应用边界。掌握 Transformer 架构,是理解 BERT、GPT、T5 等大模型的基础,也是迈向 NLP 前沿的关键一步。
资料
咚咚王
《Python 编程:从入门到实践》
《利用 Python 进行数据分析》
《算法导论中文第三版》
《概率论与数理统计(第四版) (盛骤) 》
《程序员的数学》
《线性代数应该这样学第 3 版》
《微积分和数学分析引论》
《(西瓜书)周志华-机器学习》
《TensorFlow 机器学习实战指南》
《Sklearn 与 TensorFlow 机器学习实用指南》
《模式识别(第四版)》
《深度学习 deep learning》伊恩·古德费洛著 花书
《Python 深度学习第二版(中文版)【纯文本】 (登封大数据 (Francois Choliet)) (Z-Library)》
《深入浅出神经网络与深度学习 +(迈克尔·尼尔森(Michael+Nielsen)》
《自然语言处理综论 第 2 版》
《Natural-Language-Processing-with-PyTorch》
《计算机视觉-算法与应用(中文版)》
《Learning OpenCV 4》
《AIGC:智能创作时代》杜雨 +&+ 张孜铭
《AIGC 原理与实践:零基础学大语言模型、扩散模型和多模态模型》
《从零构建大语言模型(中文版)》
《实战 AI 大模型》
《AI 3.0》