2. Transformer架构精讲
Transformer 这个架构,说白了就是大模型时代的「地基」。我刚开始接触它的时候,也觉得一堆公式挺唬人。但拆开来看,核心就那么几个模块。今天咱们就把 Attention、FFN、LayerNorm 这些零件一个个讲透。
核心观点:Transformer 的成功,在于用 Attention 机制彻底替代了 RNN 的时序依赖,让并行计算成为可能。没有它,就没有今天的 GPT 和 LLaMA。
1. Self-Attention:让每个词都「看见」全局
Self-Attention 要解决什么问题?简单说,就是让模型在处理某个词时,能知道句子中其他词跟它的关系。比如「他喜欢那本书,因为它很有趣」——「它」指代的是「书」,而不是「他」。传统 RNN 要一步步传递信息,容易忘;Self-Attention 一步到位。
它的计算分三步:
- 生成 Q、K、V:每个输入词向量分别乘以三个权重矩阵,得到 Query、Key、Value。
- 计算注意力分数:用 Q 和 K 做点积,再除以 √d_k(防止梯度爆炸),然后过 Softmax 归一化。
- 加权求和:用归一化后的分数对 V 做加权平均,得到最终输出。
公式长这样:
Attention(Q, K, V) = softmax(Q × K^T / √d_k) × V
嗯,这里要注意。除以 √d_k 这一步,我见过不少新手忽略。如果不除,当维度很大时,点积结果会非常大,Softmax 的梯度会趋近于 0,模型根本学不动。我在项目中踩过这个坑,后来养成了习惯——每次写 Attention 都先检查 scale 因子。
我的经验:实际部署时,Q 和 K 的维度 d_k 通常取 64 或 128。太小表达能力不够,太大计算量暴涨。你想想看,一个 7B 模型有几十层,每层省一点,整体推理速度能差好几倍。
2. Multi-Head Attention:多路并行,各看各的
一个 Attention 头只能学到一种关系模式。但语言中的关系是多样的——语法关系、语义关系、位置关系……所以 Transformer 用了多头机制:把 Q、K、V 拆成 h 份,每份独立做 Attention,最后拼起来。
公式:
MultiHead(Q, K, V) = Concat(head_1, ..., head_h) × W_O
其中 head_i = Attention(Q × W_Q_i, K × W_K_i, V × W_V_i)
我习惯把多头理解成「多个专家并行开会」。每个头关注不同的子空间,有的头关注主语-谓语关系,有的头关注修饰词-中心词关系。最后把大家的意见汇总,信息更丰富。
| 参数 | 典型值 | 说明 |
|---|---|---|
| 头数 h | 8 / 12 / 16 / 32 | GPT-3 用了 96 头,LLaMA 用 32 头 |
| 每头维度 d_k | 64 / 80 / 128 | 总维度 d_model = h × d_k |
| 总维度 d_model | 512 / 768 / 1024 / 4096 | 模型越大,d_model 越大 |
避坑指南:我曾经在优化推理时,试图减少头数来加速。结果发现模型质量掉得厉害。后来才明白——头数减少意味着并行子空间减少,模型对复杂关系的建模能力会断崖式下降。要加速,优先考虑 KV Cache 和 Flash Attention,而不是砍头数。
3. Feed-Forward Network:给模型加点「非线性」
Attention 层本质上是线性变换的加权组合,没有非线性。FFN 就是来补这个短板的。它通常是一个两层的 MLP:先升维,再降维。
FFN(x) = max(0, x × W_1 + b_1) × W_2 + b_2
中间维度 d_ff 通常是 d_model 的 4 倍。比如 d_model=768,d_ff=3072。为什么是 4 倍?我个人的理解是:升维让模型有更多「记忆空间」来存储中间特征,降维再压缩回原始维度。这个比例在实验中表现最稳定。
现在很多模型用 SwiGLU 或 GeLU 替代 ReLU,效果更好。LLaMA 用的就是 SwiGLU:
FFN_SwiGLU(x) = (x × W_gate) ⊙ SiLU(x × W_1) × W_2
这里多了个门控矩阵 W_gate,相当于给 FFN 加了个「开关」,让模型学会哪些信息该保留,哪些该丢弃。
4. Layer Normalization:稳住训练节奏
Transformer 层数一深,梯度就容易炸或消失。LayerNorm 就是来稳住局面的。它对每个样本的所有特征维度做归一化:
LayerNorm(x) = γ × (x - μ) / √(σ² + ε) + β
μ 和 σ 是每个样本的均值和标准差。γ 和 β 是可学习的缩放和平移参数。
我刚开始做训练时,发现 loss 震荡特别厉害。排查了半天,发现是 LayerNorm 的 ε 设得太小(1e-8),导致数值不稳定。后来改成 1e-5,训练立马稳了。这种细节,论文里不会写,但实战中特别重要。
注意:现在主流模型(如 GPT、LLaMA)用的是 Pre-LN 结构——先做 LayerNorm,再做 Attention/FFN。相比 Post-LN,Pre-LN 训练更稳定,收敛更快。如果你自己搭模型,建议直接用 Pre-LN。
5. Positional Encoding:给模型「指路」
Self-Attention 本身是位置无关的——它把输入当集合处理,不关心词序。但语言是顺序的,「我打你」和「你打我」意思完全不同。所以需要 Positional Encoding 来注入位置信息。
原始 Transformer 用正弦/余弦函数:
PE(pos, 2i) = sin(pos / 10000^(2i/d_model))
PE(pos, 2i+1) = cos(pos / 10000^(2i/d_model))
为什么用三角函数?因为这样不同位置的编码可以通过线性变换相互表示,模型能学到相对位置关系。不过现在很多模型改用 RoPE(旋转位置编码),效果更好,而且能处理更长的序列。
RoPE 的核心思想:把位置信息编码到 Q 和 K 的旋转矩阵里,而不是直接加到输入上。这样 Attention 分数天然就包含位置信息,而且支持外推——训练时序列长度 2048,推理时能用到 4096 甚至更长。
6. Decoder 与 Encoder-Decoder 架构
Transformer 有两种主流架构:
- Encoder-Decoder:原始 Transformer 的结构。Encoder 处理输入,Decoder 生成输出。适合翻译、摘要等任务。典型代表:T5、BART。
- Decoder-only:只有 Decoder 部分,自回归生成。适合文本生成、对话。典型代表:GPT 系列、LLaMA、ChatGLM。
Decoder 和 Encoder 最大的区别:Decoder 用了 Masked Self-Attention——每个 token 只能看到它自己和之前的 token,看不到未来的。这样才能保证生成时不会「作弊」。
我个人更偏爱 Decoder-only 架构。为什么?因为结构更简单,训练和推理都容易优化。而且实验证明,只要数据量和模型规模够大,Decoder-only 的效果完全不输 Encoder-Decoder。现在业界的主流方向也是 Decoder-only。
总结一下:Transformer 的核心就这六块——Self-Attention 让模型看全局,Multi-Head 让模型多角度理解,FFN 提供非线性,LayerNorm 稳定训练,Positional Encoding 注入顺序信息,Decoder 架构决定生成方式。把这些吃透了,后面讲推理优化、KV Cache、量化部署,你才能听得明白。