CS336 · 第 3 课

Transformer 架构与超参数

从 Vaswani et al. 2017 的"Attention Is All You Need"到今天的前沿模型,Transformer 架构经历了一系列关键演化。这一课拆解现代 Transformer 的每一个组件,理解每个设计选择背后的 trade-off。

授课:Tatsu Hashimoto 预计用时:80 分钟 难度:中等

Spring 2026 官方来源:Lecture 3 PDF · 课程日程

本页是中文学习导读;讲次主题、教师与材料版本以 Stanford 官方页面和讲义为准。

本讲问题:有了 token 之后,还需要决定一个 Transformer block 如何组织归一化、attention、FFN 和位置表示;这些选择会同时影响训练稳定性、参数量和计算成本。

30 秒知识地图

Transformer block 数据流 → normalization / activation / position choices → attention 与 FFN shape → 参数和 FLOPs 核算 → 超参数组合成完整模型。

问题与 prerequisite refresher

本课不是记组件名,而是回答:一个 token representation 怎样经过 attention、前馈网络(feed-forward network,FFN,也常称 MLP)与 residual path,为什么某些改动让梯度、位置表达或资源账本更合理?后文统一使用 FFN。先确认你会用最后一维做 linear projection,并知道 residual addition 要求两侧 shape 完全相同。

Transformer block 的对象关系

x:[B,T,d]
├─ norm → Q,K,V → causal attention → [B,T,d] ─┐
│                                             ├─ residual add
└─────────────────────────────────────────────┘
      ↓ norm → MLP d→d_ff→d → residual add → next block

architecture choice → tensor shape → parameters / FLOPs / memory
hyperparameter value → capacity / optimization / hardware efficiency

从 toy shape 到真实模型

令 \(B=2,T=4,d=8,h=2\),则每头 \(d_h=4\)。Q/K/V 均从 [2,4,8] 投影并 reshape 为 [2,2,4,4];每头 score 是 [4,4],合并 heads 后回到 [2,4,8],才能与 residual 相加。一般化后 score 元素随 \(B h T^2\) 增长,这是 Exact shape;写成 \(O(T^2)\) 是 Asymptotic,并不告诉你常数或真实 kernel 时间。

为什么不是“组件越新越好”

Pre-Norm 不是因为 LayerNorm “更准确”,而是给梯度保留更直接的 residual path;RMSNorm 少做 mean-centering 不代表对任何模型都更优;FlashAttention 改变 IO 顺序而不近似 attention 数学。反例:若把 attention 输出宽度改成 \(2d\) 却不加 output projection,residual addition 直接 shape 不合法。


架构演化的核心问题

原版 Transformer 提出了一个优雅的设计。但在实际训练大规模模型时,研究者发现了很多可以改进的地方。这一课围绕几个核心问题展开:

梯度流

Pre-norm vs Post-norm

非线性

ReLU → GELU → SwiGLU

位置信息

Sinusoidal → RoPE → ALiBi

效率

LayerNorm → RMSNorm


Transformer 回顾

Guided refresher

Transformer Refresher

用几分钟追踪 tokens 如何经过 attention、MLP 与两次 residual addition。

原版架构(Vaswani et al., 2017)

每个 Transformer block 包含:

Input: x  (batch, seq_len, d_model)

# 1. Multi-Head Self-Attention
attention_output = MultiHeadAttention(x, x, x)  # Q=K=V=x
x = LayerNorm(x + attention_output)              # Post-norm + residual

# 2. Feed-Forward Network
ffn_output = FFN(x)                              # Linear → ReLU → Linear
x = LayerNorm(x + ffn_output)                    # Post-norm + residual

# 3. 重复 L 层

# 4. 最终输出
output = Linear(x)  # d_model → vocab_size

关键维度

符号含义GPT-3 175BLlama 2 70B
d_model隐藏维度122888192
n_layers层数9680
n_heads注意力头数9664
d_head每头维度128128
d_ffFFN 中间维度4915228672
V词表大小5025732000

Pre-Norm vs Post-Norm

原版:Post-Norm

# Post-norm (Vaswani 2017)
x = LayerNorm(x + MultiHeadAttention(x))
x = LayerNorm(x + FFN(x))

现代:Pre-Norm

# Pre-norm (GPT-2 及以后主流)
x = x + MultiHeadAttention(LayerNorm(x))
x = x + FFN(LayerNorm(x))

为什么 Pre-Norm 更好?

梯度流的关键差异:

Post-norm 的恒等残差路径会经过归一化,深层网络往往更依赖 warmup、初始化和残差缩放。

Pre-norm 让残差主干保持恒等映射,梯度可以沿主干直接传播,因此通常更容易稳定训练很深的 Transformer。

这不是“Pre-norm 在所有指标上都更好”。Post-norm 或混合方案在合适初始化与缩放下也能稳定训练,并可能有不同的表示与收敛特性。架构选择应结合深度、初始化和训练 recipe 判断。

Norm 位置的现代变体

官方 Lecture 3 特别讨论了把额外的 norm 放在残差分支输出、但不放进恒等残差主干的做法;Grok、Gemma 2、OLMo 2 等模型采用了不同组合。它们不应笼统称为“DeepNet 的 Sandwich Norm”,也不是 DeepSeek-V3 的统一配置。

# 一类示意:保留干净的 residual stream,规范化分支输入/输出
x = x + PostNorm(Attention(PreNorm(x)))

激活函数的演化

ReLU → GELU

原版 Transformer 用 ReLU。GPT-2 开始用 GELU:

ReLU(x) = max(0, x)

GELU(x) = x × Φ(x)   (Φ 是标准正态的 CDF)
        ≈ 0.5 × x × (1 + tanh(√(2/π) × (x + 0.044715 × x³)))

为什么使用 GELU? GELU 是平滑的门控式非线性,按输入大小连续缩放信号,而 ReLU 对负值直接截断。它在 GPT/BERT 系列中表现良好,但不能仅凭“0 点不可导”解释优劣——深度学习可以正常优化 ReLU,最终选择主要来自经验结果与硬件代价。

SwiGLU:现代 LLM 的标准

Llama 系列和 Mistral 使用 SwiGLU:

# 标准 FFN
FFN(x) = W₂ × ReLU(W₁ × x)

# SwiGLU FFN(Noam Shazeer 2020 系统研究)
FFN(x) = W_down × (Swish(W_gate × x) ⊙ (W_up × x))

# 其中 Swish(x) = x × sigmoid(x)

SwiGLU 的优势:

注意:SwiGLU 把 FFN 的中间维度从 4×d_model 改为 ~2.67×d_model(为了保持参数量一致)。Llama 的 d_ff ≈ 8/3 × d_model ≈ 2.67 × d_model。

激活公式使用模型
ReLUmax(0, x)原版 Transformer, BERT
GELUx · Φ(x)GPT-2, GPT-3, BERT
SwiGLUSwish(W_g · x) ⊙ (W_u · x)Llama, Mistral, Qwen

位置编码的演化

Sinusoidal(原版 Transformer)

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

优势:可以外推到更长序列(理论上)。

劣势:实际表现不如可学习嵌入和 RoPE;推理时需要预先计算。

Learned Embedding

# GPT-2 风格
position_embedding = nn.Embedding(max_seq_len, d_model)

优势:简单,可学习。

劣势:不能外推到训练时未见过的位置;需要固定 max_seq_len。

RoPE(Rotary Position Embedding)—— 常见现代选择

RoPE 的核心思想:不直接编码位置,而是让 attention 分数自然包含相对位置信息。

RoPE 的直觉:

把 query 和 key 的每一对维度旋转一个与位置相关的角度。两个位置 p₁ 和 p₂ 的 attention score 只依赖 (p₁ - p₂)——即相对位置。

# RoPE 数学
对于维度 i (0, 2, 4, ...):
θ_i = 1 / (10000^(2i/d))

位置 m 的旋转:
R(m) = diag([e^{imθ_0}, e^{imθ_1}, ...])

# 应用到 query 和 key:
q_rotated = R(m) @ q
k_rotated = R(n) @ k

# attention score = q_rotated @ k_rotated^T
# 只依赖 (m - n) —— 相对位置!

RoPE 的优势:

ALiBi(Attention with Linear Biases)

# 不加位置编码,直接在 attention score 上加偏置
scores = Q @ K^T / √d
scores[i, j] -= |i - j| × slope_head_i  # 距离越远,惩罚越大

ALiBi 不需要位置 embedding 表,并在原论文设置中展示了长度外推能力;RoPE 与 ALiBi 的优劣取决于训练长度、缩放方法、架构和任务,不能概括为一个方法在“大多数任务”上必然更好。

方法编码方式外推能力使用模型
Sinusoidal绝对位置,三角函数理论好,实际差原版 Transformer
Learned绝对位置,可学习无GPT-2, BERT
RoPE相对位置,旋转好(可插值)Llama, Mistral, Qwen
ALiBi相对位置,线性偏置极好BLOOM, MPT

归一化:LayerNorm → RMSNorm

LayerNorm

# 原版 LayerNorm
mean = x.mean(dim=-1, keepdim=True)
var = x.var(dim=-1, keepdim=True, unbiased=False)
x_norm = (x - mean) / sqrt(var + ε)
output = γ × x_norm + β

参数量:2 × d_model(γ 和 β)

RMSNorm

Llama 系列使用 RMSNorm——去掉 mean centering:

# RMSNorm
rms = sqrt(mean(x²) + ε)
x_norm = x / rms
output = γ × x_norm  # 没有 β!

为什么去掉 mean centering?

归一化的位置

# 常见现代配置: Pre-RMSNorm
x = x + Attention(RMSNorm(x))
x = x + FFN(RMSNorm(x))

# 有些模型在 attention 内部也做 norm (QK-norm)
# 特别是长上下文模型,防止 attention logits 爆炸

FFN 架构选择

标准 FFN

FFN(x) = W₂ × activation(W₁ × x)
d_ff = 4 × d_model  (标准比例)

门控 FFN(Gated Linear Unit, GLU)

# 标准 GLU
GLU(x) = σ(W_gate × x) ⊙ (W_up × x)   # ⊙ 是逐元素乘
FFN(x) = W_down × GLU(x)

# SwiGLU(用 Swish 替代 sigmoid)
SwiGLU(x) = Swish(W_gate × x) ⊙ (W_up × x)

# GeGLU(用 GELU 替代 sigmoid)
GeGLU(x) = GELU(W_gate × x) ⊙ (W_up × x)

为什么门控更好?

维度调整:SwiGLU 把 d_ff 从 4×d_model 改为 ~2.67×d_model(8/3),因为现在有三个矩阵(W_gate, W_up, W_down)。参数量大致相同。


注意力机制的细节

Multi-Head Attention(MHA)

# 输入: Q, K, V  (batch, seq, d_model)
# 拆分成 h 个头
Q = rearrange(Q, 'b s (h d) -> b h s d', h=num_heads)
K = rearrange(K, 'b s (h d) -> b h s d', h=num_heads)
V = rearrange(V, 'b s (h d) -> b h s d', h=num_heads)

# Scaled dot-product attention
scores = Q @ K^T / √d_k
scores = causal_mask(scores)  # 因果掩码
attn = softmax(scores)
output = attn @ V

# 合并头
output = rearrange(output, 'b h s d -> b s (h d)')

Grouped-Query Attention(GQA)

下一课会详细讲,这里先预览:

MHA: num_heads 个 Q 头, num_heads 个 K 头, num_heads 个 V 头
MQA: num_heads 个 Q 头, 1 个 K 头, 1 个 V 头
GQA: num_heads 个 Q 头, num_kv_heads 个 K 头, num_kv_heads 个 V 头

例如: 32 个 Q 头, 8 个 KV 头(每 4 个 Q 头共享 1 个 KV 头)

FlashAttention

不是架构创新,而是计算方法的革命:

FlashAttention 的核心思想:不改变 attention 的数学定义,而是用 tiling 与 online softmax 避免把完整的 attention score/probability 矩阵物化到 HBM。

通过 tiling + online softmax,在 SRAM 中完成每个 block 的 attention,只把最终输出写回 HBM。

效果:attention 中间量的额外存储从 O(n²) 降到 O(n);加速比取决于序列长度、head dimension、GPU 与具体 kernel,不能固定写成 2-4×。


超参数选择

核心超参数

超参数含义典型范围影响
d_model隐藏维度512 - 12288模型容量
n_layers层数12 - 120模型深度
n_heads注意力头数8 - 96并行注意力
d_head每头维度64 - 128注意力表达力
d_ffFFN 中间维度4×d_model 或 2.67×d_modelFFN 容量
V词表大小32K - 256K序列效率

d_model vs n_layers 的权衡

对于固定的参数量预算,应该选宽模型(大 d_model, 少层)还是深模型(小 d_model, 多层)?

参数量估算

# Transformer 参数量(忽略 embedding 和 final head)
# Attention(MHA 假设): 4 × d_model²
# GQA/MQA 的 K、V 投影更小,不能直接套 4d²
# FFN (SwiGLU): 3 × d_model × d_ff  (W_gate, W_up, W_down)
# RMSNorm: 2 × d_model  (每层两个 norm)

# 使用 SwiGLU (d_ff = 8/3 × d_model):
per_layer = 4d² + 3d × (8/3)d + 2d = 4d² + 8d² + 2d = 12d² + 2d
total_params ≈ n_layers × 12 × d_model²

Chinchilla 比例

Hoffmann et al. (2022) 的实验常被概括为下面这个经验预算:

D ≈ 20 × N

其中:
D = 训练 token 数
N = 模型参数量

例如: 70B 模型 → ~1.4T tokens (compute-optimal)

边界:20 tokens/parameter 是 Chinchilla 70B 配置及其量级的常用速记,不是跨架构、数据质量和推理成本都不变的物理常数。现代模型常为了摊薄推理成本而显著 overtrain。


现代模型配置对比

模型d_modeln_layersn_headsd_headd_ff激活PositionNorm
GPT-3 175B12288969612849152GELULearnedPre-LN
Llama 2 70B8192806412828672SwiGLURoPEPre-RMS
Mistral 7B4096323212814336SwiGLURoPEPre-RMS
Gemma 2 27B46084632 Q / 16 KV12836864(8×d_model)GeGLURoPEPre/Post RMSNorm

趋势:


参数初始化策略

Xavier/Glorot 初始化

# 目标: 让输出的方差 ≈ 输入的方差
# 对于 (input_dim, output_dim) 的权重矩阵:
std = sqrt(2 / (input_dim + output_dim))  # Xavier uniform
std = sqrt(1 / input_dim)                  # 简化版本(前向)

w = torch.randn(input_dim, output_dim) * std

Transformer 特定的初始化

很多现代模型对残差分支做特殊初始化:

# GPT-2 风格
# 残差投影初始化为 0.02(很小),让训练初期接近 identity
w = torch.randn(d_model, d_model) * 0.02

# T5 / PaLM 风格
# 按层深度缩放: std = base_std / sqrt(2 * n_layers)
# 深层层的残差贡献更小,保持梯度稳定

In-Context-Learning 友好的初始化

PaLM 和后续模型使用特殊的初始化来增强 ICL 能力:


知识检查

问题 1:为什么现代 Transformer 用 pre-norm 而不是 post-norm?

问题 2:RoPE 的核心优势是什么?

问题 3:RMSNorm 和 LayerNorm 的区别是什么?

问题 4:使用 SwiGLU 时,d_ff 应该怎么调整?

问题 5:FlashAttention 为什么比普通 attention 更快?


Concept Check · residual shape 迁移题

输入 \(x:[3,128,512]\),attention 输出若为 [3,128,1024],能否直接 residual add?

答案:不能;逐元素加法要求 shape 可广播且这里应保持 model width。需先用 output projection 映射回 512。

若答“能,因为 token 数相同”,说明你只检查了 sequence 轴,漏掉 residual 的 feature-axis invariant。

你现在应该能够解释

通往第 4 课

标准 attention 与 dense MLP 的对象和成本已经明确;下一课才有资格问:共享 KV、限制 attention 范围或只激活部分 experts 时,究竟省了哪项成本、又新增了什么误差与通信。

如果只能记住 5 件事

Pre-Norm

残差绕过 LayerNorm,训练更稳定

SwiGLU + RoPE

现代 LLM 中很常见,但仍存在 GeGLU、ALiBi、NoPE 等替代方案

RMSNorm

去掉 mean centering,更快更省

FlashAttention

不改数学,改计算顺序,O(n) 内存


延伸阅读

Reference · 延伸阅读与一手资料