跳转至

第三章 Transformer架构详解

导读

Transformer 是过去 8 年最重要的深度学习架构——所有主流 LLM(GPT、Claude、Llama、Qwen、DeepSeek)都基于它。本章解释它的核心机制:Self-Attention、Multi-Head、Positional Encoding、Encoder/Decoder。读完后,你应该能看懂 model.forward() 里发生的事。

3.1 为什么需要 Transformer

2017 年之前,自然语言处理的主流是 RNN/LSTM。RNN 的核心问题是:

  1. 顺序计算:必须从左到右逐 token 处理,无法并行;
  2. 长程依赖弱:信息要经过很多步传递,远端 token 的关联会衰减;
  3. 训练慢:上面两个问题导致 GPU 利用率低。

Transformer 用一个关键想法同时解决两者:让每个 token 直接"看"所有其他 token——通过 Self-Attention。

3.2 Self-Attention:核心公式

Self-Attention计算分解

公式:

\[\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V\]

直觉解释:

  • Q(Query):当前 token 在"问什么";
  • K(Key):所有 token 在"匹配什么";
  • V(Value):所有 token 在"提供什么内容";
  • \(QK^T\):得到每个 token 对当前 token 的重要性权重(一个 L×L 矩阵);
  • softmax:归一化为概率;
  • 乘 V:按权重加权聚合。

为什么除以 \(\sqrt{d_k}\)?当 \(d_k\) 大时,\(QK^T\) 数值方差变大,softmax 会进入梯度饱和区(接近 one-hot),导致梯度消失。除以 \(\sqrt{d_k}\) 让方差稳定在 1 附近。

伪代码:

def attention(Q, K, V):
    scores = Q @ K.transpose(-1, -2) / math.sqrt(d_k)   # [B, H, L, L]
    if causal:
        scores = scores + causal_mask                    # 下三角保留
    weights = softmax(scores)                            # [B, H, L, L]
    output  = weights @ V                                # [B, H, L, d_k]
    return output

3.3 Multi-Head Attention

把 Q、K、V 切成 h 份,分别做 attention,再拼接:

Multi-Head Attention

def multi_head_attention(x, W_q, W_k, W_v, W_o, num_heads):
    B, L, D = x.shape
    d_head = D // num_heads

    Q = x @ W_q          # [B, L, D]
    K = x @ W_k
    V = x @ W_v

    # 切头
    Q = Q.view(B, L, num_heads, d_head).transpose(1, 2)   # [B, H, L, d_head]
    K = K.view(B, L, num_heads, d_head).transpose(1, 2)
    V = V.view(B, L, num_heads, d_head).transpose(1, 2)

    out = attention(Q, K, V)                              # [B, H, L, d_head]
    out = out.transpose(1, 2).reshape(B, L, D)            # 合并头
    return out @ W_o

为什么多头?

  • 不同 head 学习不同子空间的关系(语法、共指、语义、位置);
  • 总参数量不变(h × d_head = d_model);
  • 计算量不变,但表达力提升。

变体(重要!)

  • MHA(标准):每 head 独立 Q/K/V,KV Cache 大;
  • MQA(Multi-Query):所有 head 共享 1 个 K/V,KV Cache 极小,质量略降;
  • GQA(Grouped-Query):折中——多 head 共享 K/V 组。Llama-3、Qwen 等现代模型标配

3.4 位置编码

Attention 本身是"集合操作"——没有顺序概念。但语言显然有顺序。所以需要额外注入位置信息。

绝对位置编码(原论文):用 sin/cos 函数生成不同位置的固定向量,加到 token embedding 上。

RoPE(Rotary Position Embedding,旋转位置编码)——现代 LLM 事实标准:

  • 不加在 input 上,而是**乘在 Q、K 上**——通过旋转矩阵 \(R(\theta_m)\)\(Q_m \cdot K_n\) 仅依赖相对位置 \(m - n\)
  • 优点:外推性好——训练 4K 可推到 32K+,无需重训;
  • 通过 YaRN、NTK-aware scaling 等技巧,可推到 1M。

3.5 Feed-Forward Network(FFN)

每个 Attention 之后接一个 FFN:

def ffn(x, W1, W2):
    return x @ W1 @ W2   # 经 ReLU/GELU 中间激活

现代变体:SwiGLU

def swiglu_ffn(x, W_gate, W_up, W_down):
    return (silu(x @ W_gate) * (x @ W_up)) @ W_down

引入"门控"机制,比 ReLU 表现更好但参数稍多。Llama、Qwen 都用 SwiGLU。

关键事实:FFN 占模型参数量的约 2/3。Attention 的计算随 L² 增长,FFN 随 L × d² 增长。

3.6 Layer Normalization 与残差连接

LayerNorm:对一个样本的所有特征做归一化(减均值、除标准差、再仿射变换)。让训练更稳定。

RMSNorm:LayerNorm 简化版——不算均值,只算 RMS(root mean square)。计算更快,效果接近。现代 LLM 标配

def rmsnorm(x, weight, eps=1e-6):
    rms = x.pow(2).mean(-1, keepdim=True).add(eps).sqrt()
    return x / rms * weight

残差连接(Residual Connection)

x = x + sublayer(x)   # 而非 x = sublayer(x)

让梯度能"短路"回流,缓解深层网络梯度消失。Transformer 每个子层(attention / FFN)都包残差。

3.7 完整的 Transformer Block

Transformer Decoder Block

伪代码(一个 decoder block):

def transformer_block(x):
    # 子层1:Attention
    h = rmsnorm(x)
    x = x + attention(h, params_attn)

    # 子层2:FFN
    h = rmsnorm(x)
    x = x + ffn(h, params_ffn)

    return x

将这个 block 堆叠 N 层(Llama-3 8B 是 32 层,70B 是 80 层,GPT-4 估 120+层),就是 LLM 的主干。

3.8 Encoder vs Decoder vs Encoder-Decoder

原始 Transformer(2017)是 Encoder-Decoder 结构,用于翻译:

  • Encoder:双向注意力,看完整句,输出表示;
  • Decoder:单向(causal)注意力 + cross-attention 到 encoder 输出,自回归生成。

后续演化:

  • BERT:纯 Encoder,双向注意力,适合理解任务(分类、检索);
  • GPT 系列:纯 Decoder,单向注意力,自回归生成,当前 LLM 主流
  • T5、BART:Encoder-Decoder,适合翻译/摘要。

为什么 Decoder 主导了 LLM?因为:

  1. 自回归 + next-token 预测是**通用任务**——所有文本都可用;
  2. 可无监督训于海量原始文本,不需要标注;
  3. Scaling laws 友好(越大越好)。

3.9 Causal Mask:让 Decoder 看不见未来

Decoder 训练时,整个序列一次性前向,但要保证"预测第 i 个 token 时只能看前 i-1 个"。实现方式是**下三角 mask**:

mask = torch.triu(torch.full([L, L], float('-inf')), diagonal=1)
scores = scores + mask   # 上三角变 -inf,softmax 后变 0

这样每个位置只看到自己和之前的位置。生成时则逐 token 生成,每次新 token 的 K/V append 到 KV Cache(第 8 章详述)。

3.10 参数量估算

一个 Transformer 模型的参数大致分布在:

部分 参数量 占比
Embedding V × d 与词表正相关
Attention 每层 4d²(Q/K/V/O 各 d²) ~30%
FFN 每层 ~8d²(SwiGLU 三个矩阵) ~60%
LayerNorm 等 几个 d <1%

粗略公式:N_params ≈ 12 × L_layers × d_model²(含 FFN)。

例:Llama-3 8B:L=32, d=4096 → 12×32×4096² ≈ 6.4B,加上 embedding 与 head 约 8B。

3.11 计算量估算

每个 token 前向算力 ≈ 2 × N_params FLOPs(粗估,含 attention 与 FFN)。

  • 7B 模型,1 token ≈ 14 GFLOPS;
  • 一次推理 1K tokens ≈ 14 TFLOPS;
  • 训练 1T tokens ≈ 14 EFLOPS。

这就是为什么训练需要上万 GPU·月的算力——而推理成本相对便宜。

工程实战要点

  • 不要手写 attention——用 FlashAttention、sdpa 等优化实现;
  • GQA 是现代模型默认——评估开源模型时关注是否用 GQA,影响 KV Cache;
  • RoPE 外推——若要扩上下文,了解 YaRN、NTK;
  • Causal Mask 不能漏——训练数据中混入非 causal 实现会导致 loss 不降;
  • **参数量与计算量**估算能力是基础——估不出量级就无法判断硬件可行性。

小结

  • Transformer 用 Self-Attention 让每 token 直接看所有 token,解决 RNN 并行与长程依赖问题;
  • Attention 公式:softmax(QK^T/√d)·V;
  • Multi-Head 切分 Q/K/V 学习不同子空间;GQA 是现代主流折中;
  • RoPE 注入位置信息,外推性好;
  • FFN(SwiGLU)占 2/3 参数,是表达力主体;
  • 残差 + RMSNorm 让深层网络可训;
  • Decoder-only + Causal Mask 是当前 LLM 标准结构;
  • 参数量 ≈ 12 × L × d²,算力 ≈ 2 × N × tokens。

练习题

  1. 写出 Attention 的完整公式,解释每一项的含义。
  2. 为什么 Attention 要除以 √d_k?
  3. 解释 MHA、MQA、GQA 的区别。为什么 GQA 是折中?
  4. RoPE 与绝对位置编码相比,关键优势是什么?
  5. 为什么 FFN 占模型参数量大头(约 2/3)?
  6. 解释 Causal Mask 是如何让 Decoder "看不见未来"的。
  7. 估算 Llama-3 70B 的参数量(L=80, d=8192),并与真实值对比。
  8. 一个 7B 模型,前向处理 1 个 token 大约多少 FLOPs?处理 4096 tokens 呢?
  9. 残差连接在深层 Transformer 中起什么作用?

下一章:第四章 Tokenizer与Embedding