人工智能之语言领域 自然语言处理 第十二章 Transformer架构

人工智能之语言领域

第十二章 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.3.1 损失函数与优化器选择](#12.3.1 损失函数与优化器选择)
      • [12.3.2 训练技巧](#12.3.2 训练技巧)
        • [(1)学习率调度:Warmup + Decay](#(1)学习率调度:Warmup + Decay)
        • [(2)梯度裁剪(Gradient Clipping)](#(2)梯度裁剪(Gradient Clipping))
    • [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 层包含两个子层:

  1. 多头自注意力机制(Multi-Head Self-Attention)
  2. 前馈神经网络(Feed-Forward Network, FFN)

每层后接 残差连接 + 层归一化(LayerNorm)
输入 X
+
Multi-Head

Self-Attention
LayerNorm
输出 Y
+
Position-wise

FFN
LayerNorm

作用

  • 自注意力:捕获词间依赖
  • FFN:非线性变换,增强表达能力

12.1.2 解码器(Decoder)结构详解

每个 Decoder 层包含三个子层

  1. 掩码多头自注意力(Masked Multi-Head Self-Attention)
  2. 多头跨注意力(Multi-Head Cross-Attention)
  3. 前馈神经网络(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》

相关推荐
商业咨询信息2 小时前
中之网科技江苏有限公司:四核驱动数字营销,构筑GEO优化+短视频运营+宣传片拍摄+网站建设全链路服务生态
人工智能·新媒体运营
zzb15802 小时前
Agent学习-Reflection框架
java·人工智能·python·学习·ai
no_work2 小时前
python-深度学习快速入门实战-数据集和源码
开发语言·人工智能·python·深度学习·神经网络·cnn
火山引擎开发者社区2 小时前
数据中心冷却黑科技:负压液冷大揭秘
人工智能
Allnadyy2 小时前
【Transformer】神经网络,CNN,RNN
人工智能·深度学习·transformer
Flying pigs~~2 小时前
自然语言处理(NLP)开胃小菜
人工智能·算法·自然语言处理·大模型·文本分析处理
jay神2 小时前
基于深度学习的人脸检测与识别系统
人工智能·python·深度学习·可视化·计算机毕业设计
CoderJia程序员甲2 小时前
GitHub 热榜项目 - 日榜(2026-03-15)
人工智能·ai·大模型·github·ai教程