Transformer 模型
2017 年,Google 在论文《Attention Is All You Need》中提出了 Transformer 模型。该模型彻底摒弃了传统的循环神经网络(RNN/LSTM)和卷积神经网络(CNN)架构,完全依托自注意力机制(Self-Attention) 构建。这一突破不仅彻底解决了长距离依赖与训练无法并行化的痛点,更为后来的 BERT、GPT 系列等现代大语言模型(LLM)奠定了基石。
6.1 概述
- 设计初衷:传统的 Seq2Seq+Attention 仍依赖 RNN 进行逐词编码与解码,存在计算无法高度并行化和超长序列信息衰减的问题。
- 核心变革:Transformer 提出了“注意力即一切”的理念,序列中任意两个词之间的交互距离直接缩短为 ,且训练时能够在时间维度实现全矩阵并行计算。
- 历史地位:Transformer 已成为现代自然语言处理、多模态大模型乃至计算机视觉(Vision Transformer)领域的通用骨干网络架构。
6.2 模型结构详解
6.2.1 核心思想
- 全局直接交互:通过自注意力机制,序列中的每个词都可以直接与所有其他词进行相关度计算,消除距离障碍。
- 多头表征子空间(Multi-Head):利用多个独立的投影头,让模型同时在不同语义层面捕获丰富的上下文关联。
- 无时序计算结构的并行化:抛弃 RNN 的循环迭代,借助位置编码(Positional Encoding)注入时序信息,换取极高的训练并行效率。
6.2.2 整体结构
Transformer 整体依然遵循标准的 Encoder-Decoder(编码器-解码器) 框架:
【输入序列】 【目标序列 (右移)】
│ │
[输入嵌入 + 位置编码] [输出嵌入 + 位置编码]
│ │
┌─────────▼─────────┐ ┌─────────▼─────────┐
│ N × Encoder 块 │ ──(Memory)─>│ N × Decoder 块 │
└───────────────────┘ └─────────┬─────────┘
│
[线性映射 + Softmax]
│
【预测概率】
- Encoder 栈:由 个相同的编码器层(Encoder Layer)堆叠而成,提取输入序列的高阶语义表征。
- Decoder 栈:由 个相同的解码器层(Decoder Layer)堆叠而成,结合源端特征与目标端已生成信息自回归输出。
6.2.3 编码器(Encoder)
6.2.3.1 概述
编码器接收输入序列并生成对应的上下文矩阵。每个 Encoder Layer 内部包含两个核心子层:多头自注意力子层 和 前馈神经网络子层,且每个子层周围均包裹了残差连接与层归一化。
6.2.3.2 自注意力层(Self-Attention & Multi-Head Attention)
-
缩放点积注意力(Scaled Dot-Product Attention): 将输入矩阵 分别乘以可学习权重矩阵 得到 Query ()、Key ()、Value (): 其中除以 是为了防止向量维度较大时点积结果过大,导致 Softmax 梯度饱和进入极小区域。
-
多头注意力(Multi-Head Attention): 将 投影到 个不同的低维子空间分别计算注意力,最后拼接并投影:
6.2.3.3 前馈神经网络层(Feed-Forward Network, FFN)
在自注意力层之后,每个位置的向量会独立且相同地通过一个两层的全连接网络: 通常中间隐藏层的维度扩展为输入维度的 4 倍(如 )。
6.2.3.4 残差连接与层归一化(Add & Norm)
每个子层输出后均执行 残差连接(Residual Connection) 与 层归一化(Layer Normalization),有效防止深层网络梯度消失:
6.2.3.5 位置编码(Positional Encoding, PE)
由于自注意力机制天然不包含时序先后概念(置换不变性),必须显式注入位置信息。标准 Transformer 采用正弦和余弦函数构建固定的绝对位置编码: 计算出的 矩阵直接与 Token Embedding 相加后输入编码器。
6.2.3.6 小结
Encoder 的单层数据流向可总结为: \text{Input} \rightarrow \text{Embedding + PE} \rightarrow \text{[Multi-Head Self-Attention + Add & Norm]} \rightarrow \text{[FFN + Add & Norm]} \rightarrow \text{Next Layer}
6.2.4 解码器(Decoder)
6.2.4.1 概述
解码器负责自回归生成目标序列。每个 Decoder Layer 由 三个核心子层 构成,相比 Encoder 额外增加了一个交叉注意力子层。
6.2.4.2 Masked 自注意力子层(Masked Multi-Head Attention)
- 作用:确保生成当前时刻词时,模型只能看见历史词,而不能提前窥探未来时刻的词。
- 实现原理(因果掩码 / 下三角掩码):在计算 后,将上三角矩阵(未来位置)的值替换为 。经过 Softmax 之后,未来位置的注意力权重被归零。
6.2.4.3 编码器-解码器注意力子层(Cross-Attention)
- 作用:实现目标端序列与源端序列的全局语义交互。
- Q, K, V 来源:
- (Query):来自 Decoder 前一个子层的输出;
- (Key)与 (Value):来自 Encoder 顶层的最终输出(Memory)。
6.2.4.4 小结
Decoder 的单层数据流向为: \text{Target} \rightarrow \text{[Masked Self-Attention + Add & Norm]} \rightarrow \text{[Cross-Attention + Add & Norm]} \rightarrow \text{[FFN + Add & Norm]} \rightarrow \text{Next Layer}
6.3 模型训练与推理机制
6.3.1 模型训练(全并行训练)
- 训练特性:得益于 Masked Attention,训练阶段解码器无需按时间步串行迭代。
- 机制:
- 将整个目标序列(Shifted Right,即添加
<BOS>并在末尾去除<EOS>)一次性传入 Decoder。 - 配合掩码矩阵,Decoder 可以同时计算所有时间步的损失。
- 采用交叉熵损失与 Label Smoothing(标签平滑) 技术,全面反向传播更新参数。
- 将整个目标序列(Shifted Right,即添加
6.3.2 模型推理(自回归生成)
- 推理特性:推理时无法预先得知未来的目标词,必须回归到串行自回归模式。
- 机制:
- Encoder 仅需执行一次前向计算,输出源端表征(Memory)。
- Decoder 以
<BOS>为起点,逐步预测下一个 Token; - 将新生成的 Token 拼接到 Decoder 输入中,重复迭代,直到生成
<EOS>或达到最大步长(结合 Greedy Search 或 Beam Search)。
6.4 API 使用(PyTorch 实战)
PyTorch 在 torch.nn 模块中提供了开箱即用的高优化 Transformer API。
6.4.1 概述
PyTorch 将 Transformer 拆解为高阶整体类(Transformer)和细粒度积木块(如 TransformerEncoderLayer、TransformerEncoder 等),兼具易用性与灵活定制能力。
6.4.2 核心类
nn.Transformer:包含完整 Encoder-Decoder 架构的最高阶模型类。nn.TransformerEncoderLayer:单层 Encoder 结构。nn.TransformerEncoder:由多个 EncoderLayer 堆叠而成的编码器栈。nn.TransformerDecoderLayer:单层 Decoder 结构。nn.TransformerDecoder:由多个 DecoderLayer 堆叠而成的解码器栈。
6.4.3 Transformer 构造参数
import torch.nn as nn
transformer = nn.Transformer(
d_model=512, # 特征嵌入维度 (默认: 512)
nhead=8, # 多头注意力的头数 (默认: 8)
num_encoder_layers=6, # Encoder 堆叠层数 (默认: 6)
num_decoder_layers=6, # Decoder 堆叠层数 (默认: 6)
dim_feedforward=2048, # FFN 隐藏层维度 (默认: 2048)
dropout=0.1, # Dropout 概率 (默认: 0.1)
activation='relu', # 激活函数,可选 'relu' 或 'gelu'
batch_first=True # 输入张量是否以 batch 为第一维度 (推荐 True)
)
6.4.4 Transformer.forward
- 调用形式:
output = transformer( src=src_emb, # [batch_size, src_len, d_model] tgt=tgt_emb, # [batch_size, tgt_len, d_model] tgt_mask=tgt_mask, # [tgt_len, tgt_len] 因果掩码 src_key_padding_mask=src_pad, # [batch_size, src_len] Padding 掩码 tgt_key_padding_mask=tgt_pad # [batch_size, tgt_len] Padding 掩码 )
6.4.5 Transformer.encoder
可单独调用编码器部分,获取源端 Memory:
memory = transformer.encoder(src_emb, src_key_padding_mask=src_pad)
6.4.6 Transformer.decoder
在推理自回归阶段,结合 Memory 单独调用解码器:
out = transformer.decoder(tgt_emb, memory, tgt_mask=tgt_mask)
6.5 案例实操(中英翻译 V3.0)
基于 PyTorch 原生 API 构建端到端的 Transformer 中英机器翻译模型。
6.5.1 需求说明
- 目标:实现中译英模型(V3.0),对比 RNN/Seq2Seq 版本,大幅提升长句翻译的自然度,并利用 GPU 并行加速训练。
- 技术栈:PyTorch + 正弦位置编码 + 自定义因果掩码生成。
6.5.2 需求分析
- 位置编码模块:通过数学公式计算可支持动态最大长度的
PositionalEncoding类。 - 掩码生成逻辑:
tgt_mask:防止解码器提前看到未来词的下三角因果矩阵;padding_mask:避免模型关注<PAD>占位符。
6.5.3 需求实现(完整核心模型代码)
import math
import torch
import torch.nn as nn
class PositionalEncoding(nn.Module):
"""正弦-余弦绝对位置编码"""
def __init__(self, d_model, max_len=5000):
super(PositionalEncoding, self).__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)
pe = pe.unsqueeze(0) # [1, max_len, d_model]
self.register_buffer('pe', pe)
def forward(self, x):
# x: [batch_size, seq_len, d_model]
x = x + self.pe[:, :x.size(1), :]
return x
class TransformerNMT(nn.Module):
"""中英机器翻译 Transformer V3.0 模型"""
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, dropout=0.1):
super(TransformerNMT, self).__init__()
self.d_model = d_model
# 词嵌入与位置编码
self.src_tok_emb = nn.Embedding(src_vocab_size, d_model)
self.tgt_tok_emb = nn.Embedding(tgt_vocab_size, d_model)
self.positional_encoding = PositionalEncoding(d_model)
# Transformer 主干网络
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,
dropout=dropout,
batch_first=True
)
# 输出词表映射层
self.generator = nn.Linear(d_model, tgt_vocab_size)
def generate_square_subsequent_mask(self, sz, device):
"""生成因果掩码 (下三角矩阵)"""
mask = (torch.triu(torch.ones((sz, sz), device=device)) == 1).transpose(0, 1)
mask = mask.float().masked_fill(mask == 0, float('-inf')).masked_fill(mask == 1, float(0.0))
return mask
def forward(self, src, tgt, src_pad_idx, tgt_pad_idx):
# 1. 构建掩码
tgt_seq_len = tgt.size(1)
tgt_mask = self.generate_square_subsequent_mask(tgt_seq_len, tgt.device)
src_key_padding_mask = (src == src_pad_idx)
tgt_key_padding_mask = (tgt == tgt_pad_idx)
# 2. 词嵌入并缩放 + 叠加位置编码
src_emb = self.positional_encoding(self.src_tok_emb(src) * math.sqrt(self.d_model))
tgt_emb = self.positional_encoding(self.tgt_tok_emb(tgt) * math.sqrt(self.d_model))
# 3. Transformer 前向计算
outs = self.transformer(
src=src_emb,
tgt=tgt_emb,
tgt_mask=tgt_mask,
src_key_padding_mask=src_key_padding_mask,
tgt_key_padding_mask=tgt_key_padding_mask
)
# 4. 投影到目标词表概率
return self.generator(outs)
💡 总结: Transformer 架构通过 Self-Attention + 多头设计 + 位置编码,成功摆脱了时序循环的算力束缚,实现了长程特征无损捕获与全并行训练。从这一章开始,现代深度学习正式步入了以 Transformer 为核心的预训练大模型时代。