欢迎光临
我们一直在努力

Transformer 深度解析

一、什么是 Transformer?

Transformer 是一种基于**自注意力机制(Self-Attention)**的深度学习模型架构,彻底改变了自然语言处理(NLP)乃至计算机视觉(CV)、语音识别等多个领域。

在 Transformer 出现之前,序列建模的主流是 RNN(循环神经网络) 和 LSTM/GRU。这些模型存在根本性缺陷:

  • 串行计算:必须按时间步顺序处理,无法并行
  • 长距离依赖:信息随时间步传播会衰减,难以捕捉远距离 token 之间的关系
  • 梯度消失/爆炸:长序列训练困难

Transformer 的核心主张是:完全抛弃循环和卷积结构,仅依靠注意力机制来建模序列中任意两个位置之间的依赖关系。


二、核心创新点

1. 自注意力机制(Self-Attention)⭐

这是 Transformer 的灵魂。它允许模型在处理每个 token 时,同时关注输入序列中的所有位置,并自动学习不同位置之间的关联权重。

关键突破:

  • 任意两个 token 的距离都变为 O(1)(直接计算注意力权重)
  • 彻底解决了 RNN 的长距离依赖问题
  • 全局视野,每个位置都能"看到"整个序列

2. 完全并行化(Parallelization)⭐

RNN 必须按顺序计算:h_t = f(h_{t-1}, x_t)
Transformer 的 Self-Attention 可以同时计算所有位置的表示,训练速度大幅提升,且易于在 GPU/TPU 上扩展。

3. 多头注意力(Multi-Head Attention)

将注意力机制复制多份(heads),每份学习不同的"关注点"(子空间):

  • 有的 head 关注语法关系
  • 有的 head 关注语义关系
  • 有的 head 关注指代消解

最终拼接所有 head 的结果,获得更丰富的表示。

4. 位置编码(Positional Encoding)

由于 Self-Attention 本身没有位置概念(对输入顺序不敏感),Transformer 通过正弦/余弦函数将位置信息注入模型:

PE(pos, 2i) = sin(pos / 10000^(2i/d_model))
PE(pos, 2i+1) = cos(pos / 10000^(2i/d_model))

这种编码方式允许模型学习相对位置关系,且能外推到训练时未见过的更长序列。

5. 残差连接与层归一化(Residual Connection & Layer Normalization)

  • 残差连接:Output = LayerNorm(x + Sublayer(x)),缓解梯度消失,支持深层网络
  • 层归一化:对每个样本的所有特征做归一化,稳定训练

6. Encoder-Decoder 架构的解耦

  • Encoder:通过 Self-Attention 编码输入序列的上下文表示
  • Decoder:通过 Masked Self-Attention + Cross-Attention 自回归生成输出

三、Transformer 如何工作?(架构详解)

3.1 整体架构

┌─────────────────────────────────────────────────────────────┐
│ Transformer │
├─────────────────────────────┬───────────────────────────────┤
│ Encoder Stack │ Decoder Stack │
│ ┌───────────────────────┐ │ ┌─────────────────────────┐ │
│ │ Input Embedding │ │ │ Output Embedding │ │
│ │ + Positional Encoding│ │ │ + Positional Encoding │ │
│ └───────────┬───────────┘ │ └───────────┬─────────────┘ │
│ ▼ │ ▼ │
│ ┌───────────────────────┐ │ ┌─────────────────────────┐ │
│ │ Multi-Head Attention │ │ │ Masked Multi-Head Attn │ │
│ │ + Add & Norm │ │ │ + Add & Norm │ │
│ └───────────┬───────────┘ │ └───────────┬─────────────┘ │
│ ▼ │ ▼ │
│ ┌───────────────────────┐ │ ┌─────────────────────────┐ │
│ │ Feed Forward Network │ │ │ Multi-Head Cross-Attn │ │
│ │ + Add & Norm │ │ │ + Add & Norm │ │
│ └───────────┬───────────┘ │ └───────────┬─────────────┘ │
│ ▼ │ ▼ │
│ ┌───────────────────────┐ │ ┌─────────────────────────┐ │
│ │ … (N layers) │ │ │ Feed Forward Network │ │
│ └───────────┬───────────┘ │ │ + Add & Norm │ │
│ ▼ │ └───────────┬─────────────┘ │
│ ┌───────────────────────┐ │ ▼ │
│ │ Output to Decoder │──┼──▶│ … (N layers) │ │
│ └───────────────────────┘ │ └───────────┬─────────────┘ │
│ │ ▼ │
│ │ ┌─────────────────────────┐ │
│ │ │ Linear + Softmax │ │
│ │ │ → Probability Dist. │ │
│ │ └─────────────────────────┘ │
└─────────────────────────────┴───────────────────────────────┘

3.2 Self-Attention 的数学原理

Step 1: 生成 Q, K, V

对每个输入 token 的嵌入向量 x,通过三个不同的权重矩阵映射为:

  • Query (Q): 当前 token "想要查询什么"
  • Key (K): 当前 token "包含什么信息"
  • Value (V): 当前 token "实际传递什么内容"

Q = X · W_Q
K = X · W_K
V = X · W_V

其中 W_Q, W_K, W_V ∈ R^(d_model × d_k) 是可学习的参数矩阵。

Step 2: 计算注意力分数

Attention(Q, K, V) = softmax(QK^T / √d_k) · V

分步拆解:

  • QK^T: 计算每对 token 之间的相似度(点积),得到注意力分数矩阵

    • 形状: (seq_len, seq_len) —— 每个位置关注所有位置的分数
  • / √d_k: 缩放因子(Scaling)

    • 当 d_k 很大时,点积的数值会非常大,导致 softmax 进入梯度极小的饱和区
    • 除以 √d_k 将方差控制在合理范围,保证梯度稳定
  • softmax: 将分数归一化为概率分布(每行之和为 1)

  • · V: 用注意力权重对 Value 做加权求和,得到输出表示

  • Step 3: 多头拼接

    MultiHead(Q, K, V) = Concat(head_1, …, head_h) · W_O
    where head_i = Attention(QW_i^Q, KW_i^K, VW_i^V)

    • 原始论文: h = 8 个头, d_k = d_v = d_model / h = 64
    • 每个 head 独立学习不同的注意力模式
    • 最终通过 W_O 投影回 d_model 维度

    3.3 Masked Self-Attention(Decoder 专用)

    Decoder 在训练时需要防止看到未来的 token(保持自回归特性)。

    实现方式:在 softmax 之前,将未来位置的注意力分数设为 -∞:

    Mask = [[0, -∞, -∞, …],
    [0, 0, -∞, …],
    [0, 0, 0, …],
    …]

    Attention_scores = QK^T / √d_k + Mask

    这样每个位置只能关注到它及之前的位置。

    3.4 Cross-Attention(Encoder-Decoder Attention)

    Decoder 中的第二层注意力:

    • Q 来自 Decoder 上一层的输出(当前已生成的序列)
    • K, V 来自 Encoder 的最终输出(源序列的编码表示)

    这实现了源语言 → 目标语言的信息传递,是机器翻译等任务的核心。

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

    每个 Encoder/Decoder 层都包含一个全连接前馈网络:

    FFN(x) = max(0, xW_1 + b_1)W_2 + b_2

    即:Linear → ReLU → Linear

    • 中间维度: d_ff = 2048(原始论文)
    • 对每个位置独立应用(不共享信息,信息交互由 Attention 完成)
    • 增加模型的非线性表达能力

    3.6 层归一化(Layer Normalization)

    LayerNorm(x) = γ ⊙ (x – μ) / √(σ² + ε) + β

    • 对单个样本的所有特征做归一化(区别于 BatchNorm)
    • 适用于序列长度变化的场景
    • Pre-Norm vs Post-Norm:原始论文用 Post-Norm,现代变体多用 Pre-Norm(更稳定)

    四、训练细节

    4.1 输入嵌入(Input Embedding)

    • 使用可学习的词嵌入矩阵将 token ID 映射为 d_model 维向量
    • 原始论文: d_model = 512
    • 嵌入权重与输出层 softmax 前的线性层共享权重(减少参数量,提升性能)

    4.2 输出层

    Decoder 最终输出经过:

  • Linear 层: 将 d_model 映射到词汇表大小 vocab_size
  • Softmax: 生成下一个 token 的概率分布
  • 4.3 损失函数

    标准交叉熵损失(Cross-Entropy Loss):

    L = -Σ log P(y_t | y_<t, x)

    4.4 优化器与正则化

    • Adam 优化器: β1=0.9, β2=0.98, ε=10⁻⁹
    • 学习率调度(Warmup + 衰减):

      lrate = d_model^(-0.5) · min(step^(-0.5), step · warmup_steps^(-1.5))

      • Warmup: 前 4000 步线性增长
      • 之后按 step^(-0.5) 衰减
    • Dropout: P_drop = 0.1(嵌入、注意力、FFN、残差连接后)
    • Label Smoothing: ε_ls = 0.1(防止模型过度自信)

    五、为什么 Transformer 如此强大?

    特性RNN/LSTMTransformer
    并行性 ❌ 串行 ✅ 完全并行
    长距离依赖 ❌ 随距离衰减 ✅ 直接连接
    计算复杂度(每步) O(1) O(1)(但总体 O(n²))
    训练速度 快(可大规模并行)
    位置感知 天然有序 需位置编码
    可解释性 高(注意力权重可视化)

    5.1 注意力可视化

    通过观察注意力权重矩阵,可以直观理解模型在关注什么:

    • 句法关系: 代词指向其指代的名词
    • 语义关系: 同义词/反义词之间的关联
    • 跨语言对齐: 翻译任务中源语言和目标语言的词对齐

    5.2 从 Transformer 到现代大模型

    Transformer 架构是以下所有模型的基础:

    模型架构特点
    BERT Encoder-only 双向编码,预训练 + 微调范式
    GPT 系列 Decoder-only 自回归生成,Scaling Law
    T5 Encoder-Decoder Text-to-Text 统一框架
    Vision Transformer (ViT) Encoder 将图像分块作为序列处理
    CLIP Dual Encoder 图文对齐,多模态理解
    LLaMA, ChatGPT, Claude Decoder-only 大规模预训练 + RLHF

    六、PyTorch 核心实现

    import math
    import torch
    import torch.nn as nn
    import torch.nn.functional as F

    class MultiHeadAttention(nn.Module):
    """多头自注意力机制"""
    def __init__(self, d_model=512, num_heads=8):
    super().__init__()
    assert d_model % num_heads == 0

    self.d_model = d_model
    self.num_heads = num_heads
    self.d_k = d_model // num_heads # 每个头的维度

    # 线性投影层
    self.W_q = nn.Linear(d_model, d_model)
    self.W_k = nn.Linear(d_model, d_model)
    self.W_v = nn.Linear(d_model, d_model)
    self.W_o = nn.Linear(d_model, d_model)

    def scaled_dot_product_attention(self, Q, K, V, mask=None):
    """计算缩放点积注意力"""
    scores = torch.matmul(Q, K.transpose(-2, -1)) / math.sqrt(self.d_k)

    if mask is not None:
    scores = scores.masked_fill(mask == 0, -1e9)

    attn_weights = F.softmax(scores, dim=-1)
    output = torch.matmul(attn_weights, V)
    return output, attn_weights

    def forward(self, query, key, value, mask=None):
    batch_size = query.size(0)

    # 1. 线性投影并分头
    # (batch, seq, d_model) -> (batch, seq, num_heads, d_k) -> (batch, num_heads, seq, d_k)
    Q = self.W_q(query).view(batch_size, -1, self.num_heads, self.d_k).transpose(1, 2)
    K = self.W_k(key).view(batch_size, -1, self.num_heads, self.d_k).transpose(1, 2)
    V = self.W_v(value).view(batch_size, -1, self.num_heads, self.d_k).transpose(1, 2)

    # 2. 计算注意力
    attn_output, attn_weights = self.scaled_dot_product_attention(Q, K, V, mask)

    # 3. 拼接多头并输出投影
    # (batch, num_heads, seq, d_k) -> (batch, seq, d_model)
    attn_output = attn_output.transpose(1, 2).contiguous().view(
    batch_size, -1, self.d_model
    )

    return self.W_o(attn_output)

    class PositionwiseFeedForward(nn.Module):
    """前馈神经网络"""
    def __init__(self, d_model=512, d_ff=2048, dropout=0.1):
    super().__init__()
    self.linear1 = nn.Linear(d_model, d_ff)
    self.linear2 = nn.Linear(d_ff, d_model)
    self.dropout = nn.Dropout(dropout)

    def forward(self, x):
    return self.linear2(self.dropout(F.relu(self.linear1(x))))

    class PositionalEncoding(nn.Module):
    """正弦位置编码"""
    def __init__(self, d_model=512, max_len=5000, dropout=0.1):
    super().__init__()
    self.dropout = nn.Dropout(dropout)

    # 预计算位置编码矩阵
    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 = x + self.pe[:, :x.size(1), :]
    return self.dropout(x)

    class EncoderLayer(nn.Module):
    """单个 Encoder 层"""
    def __init__(self, d_model=512, num_heads=8, d_ff=2048, dropout=0.1):
    super().__init__()
    self.self_attn = MultiHeadAttention(d_model, num_heads)
    self.feed_forward = PositionwiseFeedForward(d_model, d_ff, dropout)
    self.norm1 = nn.LayerNorm(d_model)
    self.norm2 = nn.LayerNorm(d_model)
    self.dropout = nn.Dropout(dropout)

    def forward(self, x, mask=None):
    # 子层1: Multi-Head Self-Attention + Add & Norm
    attn_output = self.self_attn(x, x, x, mask)
    x = self.norm1(x + self.dropout(attn_output))

    # 子层2: FFN + Add & Norm
    ff_output = self.feed_forward(x)
    x = self.norm2(x + self.dropout(ff_output))

    return x

    class TransformerEncoder(nn.Module):
    """Transformer Encoder 堆叠"""
    def __init__(self, vocab_size, d_model=512, num_heads=8,
    num_layers=6, d_ff=2048, dropout=0.1, max_len=5000):
    super().__init__()
    self.embedding = nn.Embedding(vocab_size, d_model)
    self.pos_encoding = PositionalEncoding(d_model, max_len, dropout)
    self.layers = nn.ModuleList([
    EncoderLayer(d_model, num_heads, d_ff, dropout)
    for _ in range(num_layers)
    ])
    self.dropout = nn.Dropout(dropout)
    self.scale = math.sqrt(d_model)

    def forward(self, x, mask=None):
    x = self.embedding(x) * self.scale
    x = self.pos_encoding(x)

    for layer in self.layers:
    x = layer(x, mask)

    return x


    七、总结

    核心公式回顾

    组件公式
    Scaled Dot-Product Attention softmax(QK^T / √d_k)V
    Multi-Head Attention Concat(head₁,…,headₕ)W^O
    FFN max(0, xW₁+b₁)W₂+b₂
    Positional Encoding sin/cos(pos/10000^(2i/d_model))
    Layer Normalization γ(x-μ)/√(σ²+ε) + β

    设计哲学

  • Attention Is All You Need: 用注意力替代循环/卷积,简化架构
  • 并行优于串行: 牺牲 O(n²) 的注意力计算,换取完全并行的训练
  • 深度 + 残差: 通过残差连接和层归一化堆叠深层网络
  • 表示学习: 通过多头机制学习丰富的多视角表示
  • 历史意义

    Transformer 不仅是 NLP 的里程碑,更是现代人工智能的基石。从 BERT 到 GPT-4,从 ChatGPT 到 Sora,几乎所有当前最先进的 AI 系统都建立在 Transformer 或其变体之上。它证明了:一个简洁而优雅的架构设计,可以引发整个领域的范式革命。

    赞(0)
    未经允许不得转载:171主机测评 » Transformer 深度解析
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址