Transformer 模型

3 阅读5分钟

Transformer 模型

2017 年,Google 在论文《Attention Is All You Need》中提出了 Transformer 模型。该模型彻底摒弃了传统的循环神经网络(RNN/LSTM)和卷积神经网络(CNN)架构,完全依托自注意力机制(Self-Attention) 构建。这一突破不仅彻底解决了长距离依赖与训练无法并行化的痛点,更为后来的 BERT、GPT 系列等现代大语言模型(LLM)奠定了基石。


6.1 概述

  • 设计初衷:传统的 Seq2Seq+Attention 仍依赖 RNN 进行逐词编码与解码,存在计算无法高度并行化超长序列信息衰减的问题。
  • 核心变革:Transformer 提出了“注意力即一切”的理念,序列中任意两个词之间的交互距离直接缩短为 O(1)\mathcal{O}(1),且训练时能够在时间维度实现全矩阵并行计算
  • 历史地位:Transformer 已成为现代自然语言处理、多模态大模型乃至计算机视觉(Vision Transformer)领域的通用骨干网络架构。

6.2 模型结构详解

6.2.1 核心思想

  1. 全局直接交互:通过自注意力机制,序列中的每个词都可以直接与所有其他词进行相关度计算,消除距离障碍。
  2. 多头表征子空间(Multi-Head):利用多个独立的投影头,让模型同时在不同语义层面捕获丰富的上下文关联。
  3. 无时序计算结构的并行化:抛弃 RNN 的循环迭代,借助位置编码(Positional Encoding)注入时序信息,换取极高的训练并行效率。

6.2.2 整体结构

Transformer 整体依然遵循标准的 Encoder-Decoder(编码器-解码器) 框架:

       【输入序列】                     【目标序列 (右移)】
            │                                │
      [输入嵌入 + 位置编码]             [输出嵌入 + 位置编码]
            │                                │
  ┌─────────▼─────────┐            ┌─────────▼─────────┐
  │  N × Encoder 块   │ ──(Memory)─>│  N × Decoder 块   │
  └───────────────────┘            └─────────┬─────────┘
                                             │
                                     [线性映射 + Softmax]
                                             │
                                        【预测概率】
  • Encoder 栈:由 NN 个相同的编码器层(Encoder Layer)堆叠而成,提取输入序列的高阶语义表征。
  • Decoder 栈:由 NN 个相同的解码器层(Decoder Layer)堆叠而成,结合源端特征与目标端已生成信息自回归输出。

6.2.3 编码器(Encoder)

6.2.3.1 概述

编码器接收输入序列并生成对应的上下文矩阵。每个 Encoder Layer 内部包含两个核心子层:多头自注意力子层前馈神经网络子层,且每个子层周围均包裹了残差连接与层归一化

6.2.3.2 自注意力层(Self-Attention & Multi-Head Attention)
  1. 缩放点积注意力(Scaled Dot-Product Attention): 将输入矩阵 XX 分别乘以可学习权重矩阵 WQ,WK,WVW^Q, W^K, W^V 得到 Query (QQ)、Key (KK)、Value (VV): Attention(Q,K,V)=Softmax(QKTdk)V\text{Attention}(Q, K, V) = \text{Softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V 其中除以 dk\sqrt{d_k} 是为了防止向量维度较大时点积结果过大,导致 Softmax 梯度饱和进入极小区域。

  2. 多头注意力(Multi-Head Attention): 将 Q,K,VQ, K, V 投影到 hh 个不同的低维子空间分别计算注意力,最后拼接并投影: MultiHead(Q,K,V)=Concat(head1,,headh)WO\text{MultiHead}(Q, K, V) = \text{Concat}(\text{head}_1, \dots, \text{head}_h)W^O headi=Attention(QWiQ,KWiK,VWiV)\text{head}_i = \text{Attention}(Q W_i^Q, K W_i^K, V W_i^V)

6.2.3.3 前馈神经网络层(Feed-Forward Network, FFN)

在自注意力层之后,每个位置的向量会独立且相同地通过一个两层的全连接网络: FFN(x)=max(0,xW1+b1)W2+b2\text{FFN}(x) = \max(0, xW_1 + b_1)W_2 + b_2 通常中间隐藏层的维度扩展为输入维度的 4 倍(如 dmodel=512dff=2048512d_{\text{model}}=512 \rightarrow d_{\text{ff}}=2048 \rightarrow 512)。

6.2.3.4 残差连接与层归一化(Add & Norm)

每个子层输出后均执行 残差连接(Residual Connection)层归一化(Layer Normalization),有效防止深层网络梯度消失: Output=LayerNorm(x+Sublayer(x))\text{Output} = \text{LayerNorm}(x + \text{Sublayer}(x))

6.2.3.5 位置编码(Positional Encoding, PE)

由于自注意力机制天然不包含时序先后概念(置换不变性),必须显式注入位置信息。标准 Transformer 采用正弦和余弦函数构建固定的绝对位置编码: PE(pos,2i)=sin(pos100002i/dmodel)PE_{(pos, 2i)} = \sin\left(\frac{pos}{10000^{2i/d_{\text{model}}}}\right) PE(pos,2i+1)=cos(pos100002i/dmodel)PE_{(pos, 2i+1)} = \cos\left(\frac{pos}{10000^{2i/d_{\text{model}}}}\right) 计算出的 PEPE 矩阵直接与 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)
  • 作用:确保生成当前时刻词时,模型只能看见历史词,而不能提前窥探未来时刻的词
  • 实现原理(因果掩码 / 下三角掩码):在计算 QKT/dkQK^T / \sqrt{d_k} 后,将上三角矩阵(未来位置)的值替换为 -\infty。经过 Softmax 之后,未来位置的注意力权重被归零。
6.2.4.3 编码器-解码器注意力子层(Cross-Attention)
  • 作用:实现目标端序列与源端序列的全局语义交互。
  • Q, K, V 来源
    • QQ(Query):来自 Decoder 前一个子层的输出;
    • KK(Key)与 VV(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,训练阶段解码器无需按时间步串行迭代
  • 机制
    1. 将整个目标序列(Shifted Right,即添加 <BOS> 并在末尾去除 <EOS>)一次性传入 Decoder。
    2. 配合掩码矩阵,Decoder 可以同时计算所有时间步的损失。
    3. 采用交叉熵损失Label Smoothing(标签平滑) 技术,全面反向传播更新参数。

6.3.2 模型推理(自回归生成)

  • 推理特性:推理时无法预先得知未来的目标词,必须回归到串行自回归模式。
  • 机制
    1. Encoder 仅需执行一次前向计算,输出源端表征(Memory)。
    2. Decoder 以 <BOS> 为起点,逐步预测下一个 Token;
    3. 将新生成的 Token 拼接到 Decoder 输入中,重复迭代,直到生成 <EOS> 或达到最大步长(结合 Greedy Search 或 Beam Search)。

6.4 API 使用(PyTorch 实战)

PyTorch 在 torch.nn 模块中提供了开箱即用的高优化 Transformer API。

6.4.1 概述

PyTorch 将 Transformer 拆解为高阶整体类(Transformer)和细粒度积木块(如 TransformerEncoderLayerTransformerEncoder 等),兼具易用性与灵活定制能力。

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 需求分析

  1. 位置编码模块:通过数学公式计算可支持动态最大长度的 PositionalEncoding 类。
  2. 掩码生成逻辑
    • 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 为核心的预训练大模型时代。