外观
Transformer 架构详解
Transformer 是一类完全基于注意力机制(attention)的序列模型架构:它让序列中任意两个位置的 token 直接"互相看见",从而并行地建模全局依赖。 2017 年 Google 团队在 Attention Is All You Need 中提出它时,目标还是机器翻译;到今天,它是 GPT、Llama、Qwen、DeepSeek 等一切主流大语言模型的骨架。理解 Transformer 的每个部件,是理解全部 LLM 技术的前提。
一句话定位:Transformer = 自注意力(建模位置间关系)+ 前馈网络(逐位非线性变换)+ 残差与归一化(稳定训练)三者交替堆叠的深度网络。 它与语言建模的组合构成了"大模型"的引擎。
一、为什么是注意力:从 RNN 到 Transformer
RNN/LSTM 需要把历史压缩进一个隐藏状态向量,序列化逐时间步计算,无法并行,长距离信息易被稀释。自注意力(self-attention)让每个位置直接计算与所有其他位置的关联权重,两个问题同时解决:
| 维度 | RNN/LSTM | Transformer |
|---|---|---|
| 并行性 | 逐时间步串行 | 全序列并行 |
| 长程依赖 | 依赖隐状态压缩,易丢失 | 任意两位置直接连接 |
| 复杂度(单层) | O(n·d²) 串行 | O(n²·d) 并行 |
| 序列长度扩展 | 理论无限,实际有限 | 受 O(n²) 注意力约束(见上下文与长文本) |
二、Self-Attention 与 QKV:逐步拆解
1. Q、K、V 从哪来
对输入序列的每个 token 向量 $$x_i$$,分别乘三个权重矩阵得到**查询(Query)、键(Key)、值(Value)**三个向量:
text
对每个输入 token x ∈ R^{d_model}:
Q = x · W_q (查询:我在找什么)
K = x · W_k (键:我是什么/我提供什么线索)
V = x · W_v (值:真正要聚合的内容)
W_q, W_k ∈ R^{d_model × d_k},W_v ∈ R^{d_model × d_v}
(d_k = d_v = d_model / num_heads,如 4096/32 = 128)直觉:Q 代表"这个位置想从别处找什么",K 代表"这个位置对外展示什么标签",V 代表"这个位置真正的内容"。 注意力权重 = 用 Q 与所有 K 算相似度;输出 = 按权重对 V 做加权求和。
2. 缩放点积注意力
text
Attention(Q, K, V) = softmax( Q·K^T / √d_k ) · V
矩阵形状:Q[n, d_k],K^T[d_k, n] → 分数矩阵 [n, n]
第 i 行第 j 列 = q_i 与 k_j 的点积(相似度),
softmax 后为"位置 i 对位置 j 的注意力权重",
最后乘以 V 得到位置 i 的加权输出 [n, d_v]为什么除以 √d_k? 当 q、k 的各分量近似独立零均值、方差 1 时,点积的方差正比于 d_k。维度越大,点积数值越大,softmax 越容易进入饱和区(梯度趋近于零)。除以 √d_k 把方差归一,让注意力分数保持"温和"的分布,训练更稳定。
走一遍 2 个 token 的完整计算(直观感受):设两个 token 的向量为 x₁、x₂,d_k = 2。算出 Q = [q₁, q₂]、K = [k₁, k₂] 后,先做点积得分数矩阵 [q₁·k₁, q₁·k₂; q₂·k₁, q₂·k₂](2×2),除以 √2 缩放,再对每一行做 softmax——行 i 的两个权重之和为 1,表示"位置 i 从位置 1 和位置 2 各取多少信息"。最后把这两行权重分别作用于 V 的行并加权求和,得到两个输出向量。整个过程没有循环,完全由矩阵乘法表达——这正是它可以被 GPU 高度并行化的原因。
python
# 单头自注意力的实现(PyTorch 风格,示意)
import torch, torch.nn.functional as F
def scaled_dot_product_attention(q, k, v, mask=None):
# q: [n, d_k], k: [n, d_k], v: [n, d_v], mask: [n, n](可选)
d_k = q.size(-1)
scores = q @ k.transpose(-2, -1) / (d_k ** 0.5) # [n, n] 点积 + 缩放
if mask is not None:
scores = scores.masked_fill(mask == 0, float("-inf")) # 因果掩码
attn = F.softmax(scores, dim=-1) # 按行归一化
out = attn @ v # [n, d_v]
return out, attn一张图记住
Self-attention 就是三步:Q 问、K 答(算权重)、V 加权求和(取内容)。所有注意力变体(多头、因果、FlashAttention)都是在这三步上做工程化修改。
三、多头注意力:让"关系"分头看
把 d_model 维空间切成 h 个头,每个头在独立的低维子空间里做注意力(d_k = d_model/h),最后拼接再投影:
text
MultiHead(Q, K, V) = Concat(head_1, ..., head_h) · W_o
head_i = Attention(x·W_q^i, x·W_k^i, x·W_v^i)
h = 8 或 32(如 GPT-2 12 头、GPT-3 96 头、Llama 2 70B 64 头)为什么需要多头? 单头注意力只能学"一种相似度关系",而语言中的关系是多样的:有的头负责句法邻近,有的头负责指代回指,有的头负责位置信息。多头 = 多个"视角"并行观察同一序列,各管一类关系,再用 W_o 融合。 此外,低维子空间也让单头计算更轻、矩阵可并行,训练更高效。这也是 attention 得以并行的关键。
几代模型的典型超参可以直观地说明"深度、宽度、头数"如何协同变化(表中数值以官方发布为准):
| 模型 | 参数量 | 层数 | 隐藏维 d_model | 头数 | d_k |
|---|---|---|---|---|---|
| GPT-2 XL(2019) | 1.5B | 48 | 1600 | 25 | 64 |
| GPT-3(2020) | 175B | 96 | 12288 | 96 | 128 |
| Llama 2 7B(2023) | 7B | 32 | 4096 | 32 | 128 |
| Llama 2 70B(2023) | 70B | 80 | 8192 | 64 | 128 |
| Qwen2.5 72B(2024) | 72B | 80 | 8192 | 64 | 128 |
注意 d_k 高度一致(多取 64 或 128)——缩放因子 √d_k 与维度设计的经验值在业界相当稳定。
四、位置编码:让模型知道"谁在前谁在后"
自注意力本身置换等变——交换任意两个 token,输出也随之交换,完全丢失顺序信息。必须显式注入位置。三大类方案:
| 方案 | 机制 | 外推性 | 代表 |
|---|---|---|---|
| 绝对位置编码 | 每个位置加一个可学习/正弦向量 | 差(训练窗口外没有编码) | 原始 Transformer、BERT |
| 相对位置编码 | 在分数里加入"位置差 j−i"的偏置 | 较好 | T5、Transformer-XL |
| 旋转位置编码 RoPE | 把 Q/K 向量按位置旋转角度,分数含 j−i 的相对信息 | 中(训练窗口内效果好,外推有退化) | Llama、Qwen、DeepSeek |
| 线性偏置 ALiBi | 分数直接减一个随距离线性增大的惩罚 | 好(长度外推强) | MPT、早期长上下文模型 |
三种思路的区别一句话:绝对编码把位置"写进输入向量"(加法),模型必须自己学会利用;相对编码把位置"写进注意力分数"(显式偏置),更贴合"注意力看的是相对距离"这一直觉;RoPE 把位置"写进 Q/K 的旋转"(乘法),既保留了相对语义,又不增加显存与参数。
1. RoPE:现代主流
旋转位置编码(Rotary Position Embedding, RoPE) 由 Su et al. 2021 提出:把 q、k 向量中每个维度对按位置角度旋转,使注意力分数只依赖两位置的相对距离 j−i,且天然带有"距离越远权重越低"的归纳偏置:
text
对位置 m 的 q/k 的每个 2 维分块 (x1, x2):
旋转角度 θ_m = m · base^{-2i/d_k}(i 为维度下标,base 常取 10000)
(x1', x2') = (x1·cos θ_m − x2·sin θ_m, x1·sin θ_m + x2·cos θ_m)
效果:<q_m, k_n> = <R_m q, R_n k> = f(m − n),即相对位置RoPE 成为主流是因为:实现便宜(只动 Q/K)、相对位置语义好、配合插值可扩展到长上下文(详见上下文与长文本)。
直觉上可以把 RoPE 理解为"给每个位置的 Q/K 装了一个旋钮":旋钮的角度随位置线性增长,不同维度的旋转频率不同(低频维负责长距离信息,高频维负责局部细节)。两个位置的向量做内积时,旋转角之差恰好等于位置差——于是"相对距离"被数学上干净地编码进了注意力分数,且无需任何额外的位置参数表。
2. 位置编码的外推问题
训练时模型只见过窗口内的位置(如 4096),超出后 RoPE 的角度范围剧增、注意力分数分布崩坏——这是"模型写不到 4096 token 就胡言乱语"的结构根源。ALiBi 因惩罚是线性的而天然外推良好;RoPE 则需要插值/扩展技巧。这是长上下文研究的中心课题。
五、残差连接与 LayerNorm:Pre-Norm vs Post-Norm
每个子层(注意力、FFN)都套"残差 + 归一化"结构,保证深网络梯度通畅、数值稳定:
text
Post-Norm(原始 Transformer):
x' = LayerNorm( x + Sublayer(x) )
Pre-Norm(GPT-2 起的主流):
x' = x + Sublayer( LayerNorm(x) )| 对比 | Post-Norm | Pre-Norm |
|---|---|---|
| 归一化位置 | 残差相加后归一化 | 先归一化再进子层 |
| 训练稳定性 | 差(深网络易发散) | 好(残差路径干净,梯度易传) |
| 主流地位 | 历史方案 | 现代大模型事实标准(GPT/Llama/Qwen) |
为什么 Pre-Norm 赢了
Pre-Norm 让每个残差分支都直接通往输出,等效于"恒等路径"更干净,梯度不回穿归一化层,因此可以不降低学习率直接加深网络。代价是某些实现中深层效果略逊于调好的 Post-Norm,但稳定性收益远大于此。
六、前馈网络 FFN:逐 token 的非线性变换
注意力负责"位置之间"的混合;FFN 对每个 token 独立做非线性变换,是模型容量与知识存储的主力(Transformer 约 2/3 参数在 FFN)。现代实现:
text
经典 FFN(带 GELU 激活):
FFN(x) = W2 · GELU( W1·x + b1 ) + b2
(中间维度 4×d_model,如 d=4096 → 中间 11008/14336)
SwiGLU 变体(Llama、Qwen、Mixtral 用):
FFN(x) = (W1·x ⊙ σ( W3·x )) · W2
(σ 为 sigmoid;门控保留"该激活多少"的信息,常用 2/3·4d 中间维 + 少量提升)- GELU:平滑化的 ReLU,保留非线性、梯度更顺,是 GPT-2 起的默认。
- SwiGLU:门控线性单元,实证在相同参数预算下质量优于 GELU FFN,代价是多一个权重矩阵(总参数量约多 1/3),现代大模型普遍采用。
七、Decoder-only 与因果掩码:为什么 GPT 只剩一半
原始 Transformer 是 encoder-decoder(编码器双向看全序列 → 解码器从左到右生成)。GPT 系列做了决定性简化:只保留 decoder 的自回归分支,并用因果掩码(causal mask)屏蔽未来信息——预测位置 t 时只能看 1..t−1。
python
# 因果掩码:上三角置 -inf,softmax 后未来位置的权重为 0
n = seq_len
mask = torch.triu(torch.ones(n, n), diagonal=1).bool() # 上三角为 True
# scores[i, j] 在 j > i 时被掩码 → 位置 i 看不到它之后的任何 token为什么大模型几乎都走 decoder-only? 三方面:一是生成天然——自回归目标与"续写"完全一致,无需再训练一个编码器;二是训练目标统一——所有 token 都参与损失,无掩码位置的"浪费";三是少样本学习——GPT-3 证明纯 decoder 的自回归预训练足以涌现上下文学习。完整的路线对照见 GPT 系列 与 BERT 与编码器家族。
因果掩码还有一个常被忽视的好处:训练与推理行为一致。训练时模型本来就要逐步预测每个位置,掩码让"位置 t 只看前文"这一约束贯穿全程;推理时天然就是"已生成的前缀 + 新 token"——不存在 encoder 路线那种"训练时双向、推理时单向"的错位。这让 decoder-only 在工程上最简单、最不容易出现"训练/部署不一致"的隐性 bug。
八、复杂度与 KV Cache
1. 复杂度分析
text
自注意力:对序列长度 n 与隐藏维度 d:
计算 Q·K^T:O(n²·d) ← 时间与显存都随 n 平方增长
softmax 与加权求和:O(n²·d)
FFN:O(n·d²),随 n 线性
结论:长序列的成本由 O(n²) 的自注意力主导,
这是长上下文工程(FlashAttention、稀疏注意力)要攻克的墙。更精确地拆解:注意力计算中,矩阵乘法部分可用低精度与分块大幅加速,但 O(n²) 的"每对位置都要互动"是结构性的——只要注意力是全连接的,n 增大一倍的相互作用数量就翻四倍。缓解路径有三条:常数优化(FlashAttention)、结构稀疏(局部窗口/全局锚点)、或彻底换机制(线性注意力、状态空间模型),详见上下文与长文本。
2. KV Cache:推理时的复用
自回归解码时,每个新 token 都要算一次注意力,但历史位置的 K、V 与之前完全相同——没必要重算。KV Cache 把它们缓存复用:
text
无 KV Cache:生成第 t 个 token 时,把 1..t 全部重新前向 → O(t²) 总成本
有 KV Cache:只算新 token 的 Q,K/V 直接查缓存 → 每步 O(t),总成本 O(t)
代价:缓存显存随序列长度线性增长(≈ 2 × 层数 × 头数 × d_head × 长度 × 字节数)
伪代码(生成循环,示意):
for t in 1..max_len:
q_t = last_hidden_t @ W_q
k_t = last_hidden_t @ W_k; v_t = last_hidden_t @ W_v
k_cache = cat(k_cache, k_t); v_cache = cat(v_cache, v_t)
out_t = attention(q_t, k_cache, v_cache) # 只对全缓存做加权
...KV Cache 是推理系统吞吐与显存的头号变量,其管理与优化(PagedAttention、量化、共享)在推理基础:自回归与采样与部署与服务化中展开。
一个显存数字示例(感受量级):以 7B 量级模型(32 层、32 头、d_head 128、bf16 每值 2 字节)为例,单条 4096 token 序列的 KV Cache ≈ 2 × 32 × 32 × 128 × 4096 × 2 字节 ≈ 2.1 GB;换成 128K 上下文则约 66 GB——超过多数单卡显存。这就是为什么长上下文必然伴随 KV Cache 压缩(量化、共享、分页)与多卡部署。
九、为什么 Transformer 适合大规模并行
Transformer 统治大模型不只是因为效果好,还因为计算形状对分布式训练极其友好:
| 特性 | 对并行的意义 |
|---|---|
| 层内无序列依赖 | 张量并行(切分注意力/FFN 的权重)无通信热点 |
| 逐 token 独立计算 | 数据并行(batch 切分)天然成立 |
| 层间仅残差连接 | 流水线并行(按层切分)可高效重叠计算与通信 |
| 矩阵运算密集 | GPU 利用率高,可混用 bf16 等低精度 |
这让 数千 GPU 规模的预训练(见预训练:数据与目标)成为可能,也直接支撑了规模法则的兑现。
十、三种架构形态对比
| 形态 | 结构 | 双向/单向 | 代表模型 | 擅长 |
|---|---|---|---|---|
| Encoder-only | 仅编码器 | 双向 | BERT、RoBERTa | 理解、检索、分类 |
| Decoder-only | 仅解码器(因果) | 单向 | GPT、Llama、Qwen、DeepSeek | 生成、少样本、对话 |
| Encoder-decoder | 编码+解码 | 混合 | 原始 Transformer、T5、BART | 翻译、摘要、转换类任务 |
一句话选型:要生成与对话 → decoder-only;要表示与检索 → encoder-only;要输入理解 + 输出生成且可接受两阶段 → encoder-decoder。 大模型时代 decoder-only 是默认,另外两种形态在特定任务上仍有不可替代的位置。
一句话收束
Transformer 的每一块都有明确分工:注意力负责"谁和谁相关",位置编码负责"顺序",FFN 负责"容量",残差+Norm 负责"稳",因果掩码负责"生成",KV Cache 负责"推理快"。理解到这个颗粒度,才算真正读懂了模型。
十一、权衡与边界
- O(n²) 是长上下文的墙:注意力对序列长度平方级扩张,长文本需特殊工程(见上下文与长文本)。
- 位置编码外推是天然短板:训练窗口之外的输出质量快速退化,是评测模型时必须知道的局限。
- 容量靠 FFN 堆、关系靠注意力学:增大模型时两者的分配比例会直接影响下游表现。
- 训练稳定 > 单点技巧:Pre-Norm、缩放 √d_k、残差的设计都是"为大规模稳定训练服务"的。
注意力可视化与调试
"模型到底在看哪里"是理解与排错的关键入口:把注意力权重画成热力图,常见模式包括对角强权重(每个位置主要看自己和邻近位置)、名词-修饰语连边(句法依赖)、句首汇聚([CLS] 式位置吸收全局信息)。调试经验:生成错乱时先看注意力是否"摊平"(所有位置权重接近均匀,通常是训练不足或长度超限);某类 token 总被忽略时检查位置编码与 tokenizer 是否匹配。这些工具(如 attention rollout、可视化库)与经典论文精读中的注意力机制研究一脉相承。
延伸阅读
- 语言建模:下一词预测范式——Transformer 在训练什么目标
- 预训练:数据与目标——架构在万亿 token 上如何被训练
- 上下文与长文本——O(n²) 与位置编码外推的工程化解
- 推理基础:自回归与采样——KV Cache 与解码策略
- 规模法则——架构确定后,规模如何决定能力
- 经典论文精读——Attention Is All You Need 的深度导读
参考资料
- Vaswani et al. Attention Is All You Need(2017) —— Transformer 原始论文
- Su et al. RoFormer: Enhanced Transformer with Rotary Position Embedding(2021) —— RoPE 原始论文
- Press et al. Train Short, Test Long: Attention with Linear Biases Enables Input Length Extrapolation(ALiBi, 2021) —— ALiBi 位置编码
- Shazeer. GLU Variants Improve Transformer(2020) —— SwiGLU 的来源
- Hendrycks & Gimpel. Gaussian Error Linear Units(GELU, 2016) —— GELU 激活函数
- Touvron et al. LLaMA: Open and Efficient Foundation Language Models(2023) —— 现代 Pre-Norm + RoPE + SwiGLU 配置的公开范本
- Karpathy. nanoGPT —— 从零实现 GPT 的最佳代码参考