如果你把 Transformer 比作一辆法拉利,那这一章就是把它拆到只剩螺丝钉,然后一颗一颗告诉你:“这颗螺丝是干嘛的,拧紧了会怎样,拧松了又会怎样。”
系好安全带,我们要动刀了。
2.1 Self-Attention:一场精心策划的"相亲大会"
先忘掉公式,听个故事
想象你走进一个有 100 人的派对。你想知道"谁跟我关系最近"。怎么办?
你掏出三样东西:
- 名片(Query,Q):上面写着"我是谁,我想找什么"
- 胸牌(Key,K):上面写着"我是谁,我能提供什么"
- 礼物(Value,V):真正要传递的内容
你拿着自己的名片,跟每个人的胸牌碰一碰,算个"匹配度"。匹配度高的人,你就多拿点他的礼物;匹配度低的,意思意思就行。
最后你手里捧着一堆礼物,按匹配度加权混合——恭喜你,这就是 Self-Attention。
现在上公式(别跑!)
Attention(Q,K,V)=softmax(QKTdk)V\\text{Attention}(Q, K, V) = \\text{softmax}\\left(\\frac{QK^T}{\\sqrt{d_k}}\\right)VAttention(Q,K,V)=softmax(dkQKT)V
逐个拆解:
① QK^T——“名片碰胸牌”
Q 的形状是 [n,dk][n, d_k][n,dk],K 的形状也是 [n,dk][n, d_k][n,dk]。做矩阵乘法 QKTQK^TQKT,得到 [n,n][n, n][n,n] 的矩阵——每行每列代表"第 i 个人对第 j 个人的关注度"。
② 除以 √d_k——“防止音量炸麦”
dkd_kdk 是向量维度。维度越高,点积的数值越大。如果不除,softmax 的输入会变成一堆巨大的数,梯度直接"躺平"(趋近于零)。除以 dk\\sqrt{d_k}dk 相当于给音量旋钮拧到合理位置。
题库原话:sqrt(d) 的作用是防止内积值过大导致梯度消失。
③ Softmax——“把分数变成概率”
把一行的分数变成加起来等于 1 的概率分布。谁分高,谁权重就大。
④ 乘以 V——“按权重收礼物”
最终输出是每个位置的 Value 的加权和。
一句话总结
Self-Attention 的本质:让序列中的每个词,都能"看到"其他所有词,并决定该关注谁、关注多少。
批注:Transformer模型的核心机制是自注意力机制,能够直接建模任意距离的词元之间的交互关系。
2.2 Multi-Head Attention:一个人看不过来的,让八个人一起看
为什么一个头不够?
一个 Self-Attention 头,就像一个人同时当导演、摄影师、灯光师、剪辑师——忙不过来,视角单一。
Multi-Head 的做法:把 d 维空间切成 h 份,每份独立做注意力,最后拼起来。
MultiHead(Q,K,V)=Concat(head1,…,headh)WO\\text{MultiHead}(Q,K,V) = \\text{Concat}(\\text{head}_1, \\dots, \\text{head}_h) W^OMultiHead(Q,K,V)=Concat(head1,…,headh)WO
其中每个 headi=Attention(QWiQ,KWiK,VWiV)\\text{head}_i = \\text{Attention}(QW_i^Q, KW_i^K, VW_i^V)headi=Attention(QWiQ,KWiK,VWiV)
通俗比喻
把一部电影同时用 8 个机位拍:
- 机位 1 专拍主角表情(语法关系)
- 机位 2 专拍背景(语义上下文)
- 机位 3 专拍道具(指代关系)
- ……
最后剪辑师(WOW^OWO)把 8 个画面合成一部完整电影。
批注:多头注意力通过并行多个独立的注意力头,分别学习输入序列在不同子空间的特征表示,从而增强模型捕捉复杂语义的能力。
为什么不是"头越多越好"?
头太多 → 每个子空间维度太小 → 学不到有意义的模式。通常 8~128 个头,取决于模型规模。
2.3 位置编码三剑客:给词排座位
问题:Attention 是个"脸盲"
Self-Attention 只看"谁跟谁像",完全不管顺序。"狗咬人"和"人咬狗"在它眼里一模一样——这可不行。
所以我们需要位置编码,告诉模型:“这个词坐第几排第几座。”
第一代:正弦位置编码(绝对位置)
PE(pos,2i)=sin(pos/100002i/d)PE_{(pos, 2i)} = \\sin(pos / 10000^{2i/d})PE(pos,2i)=sin(pos/100002i/d)
PE(pos,2i+1)=cos(pos/100002i/d)PE_{(pos, 2i+1)} = \\cos(pos / 10000^{2i/d})PE(pos,2i+1)=cos(pos/100002i/d)
比喻:给每个座位刻一个固定编号。第 1 号座永远是 1 号,第 100 号座永远是 100 号。
- ✅ 简单,不需要学习
- ❌ 只能表达绝对位置,"第 5 个词和第 3 个词隔了 2 个位置"这种相对关系表达不好
- ❌ 训练时没见过的位置,推理时外推能力差
第二代:RoPE 旋转位置编码(相对位置)
批注:旋转位置编码通过复数域旋转矩阵对词向量进行空间变换,将相对位置关系融入注意力计算。
比喻:不刻座位号了,而是让每个人原地转一个角度。第 1 个词转 1°,第 2 个词转 2°,第 100 个词转 100°。
两个词做点积时,角度差自然体现了相对距离。就像两个时钟指针,你关心的不是各自指几点,而是它们之间的夹角。
- ✅ 天然编码相对位置
- ✅ 有长期衰减特性,适合长序列
- ✅ 外推能力比正弦编码强
- 代表用户:LLaMA、Qwen、DeepSeek
第三代:ALiBi(线性偏置)
比喻:不转了,直接在注意力分数上减一个跟距离成正比的惩罚。距离越远,扣分越多。
scoreij=qi⋅kj−m⋅∣i−j∣\\text{score}_{ij} = q_i \\cdot k_j – m \\cdot |i – j|scoreij=qi⋅kj−m⋅∣i−j∣
- ✅ 极其简单,不需要额外参数
- ✅ 天然鼓励关注近处
- ❌ 对非常长的依赖关系可能过于"短视"
三剑客对比表
| 正弦 | 绝对 | sin/cos 加到词向量 | 一般 | 原始 Transformer |
| RoPE | 相对 | 旋转矩阵乘 Q/K | 好 | LLaMA, Qwen |
| ALiBi | 相对 | 线性惩罚加到分数 | 中等 | BLOOM |
批注:旋转位置编码(RoPE)被广泛用于建模长序列数据,因其具有良好的性能和长期衰减特性。
2.4 Layer Normalization:给每个神经元"调音"
为什么需要归一化?
训练深层网络时,每层的输入分布会不断漂移(Internal Covariate Shift)。就像乐队演出,吉他手突然把音量拧到最大,鼓手被盖住了,整个乐队乱套。
LayerNorm 就是那个调音师:把每层的输入拉回到均值 0、方差 1 的"标准音量"。
LayerNorm(x)=x−μσ2+ϵ⋅γ+β\\text{LayerNorm}(x) = \\frac{x – \\mu}{\\sqrt{\\sigma^2 + \\epsilon}} \\cdot \\gamma + \\betaLayerNorm(x)=σ2+ϵx−μ⋅γ+β
Post-LN vs Pre-LN:调音师站哪儿?
Post-LN(原始 Transformer):
输入 → Attention → 残差相加 → LayerNorm → FFN → 残差相加 → LayerNorm
调音师站在残差连接之后。问题:深层网络训练不稳定,需要 warmup。
Pre-LN(GPT-2 之后主流):
输入 → LayerNorm → Attention → 残差相加 → LayerNorm → FFN → 残差相加
调音师站在子层之前。训练更稳定,但深层性能可能略弱。
批注:原始Transformer在残差连接前和FFN后均应用LayerNorm(Pre-LN结构)。
RMSNorm:调音师的精简版
LLaMA 用的方案。去掉"减均值"步骤,只做缩放:
RMSNorm(x)=xRMS(x)⋅γ\\text{RMSNorm}(x) = \\frac{x}{\\text{RMS}(x)} \\cdot \\gammaRMSNorm(x)=RMS(x)x⋅γ
少算一个均值,速度快 10%~15%,效果差不多。
DeepNorm:给深层网络加"保险丝"
微软提出的方案,在残差连接上加一个缩放系数 α\\alphaα,让 1000 层网络也能稳定训练。
2.5 激活函数:神经网络里的"门卫"
没有激活函数会怎样?
全是线性变换,100 层网络等价于 1 层。门卫全放假了,谁来都不拦,那还要大楼干嘛?
ReLU:最朴素的门卫
f(x)=max(0,x)f(x) = \\max(0, x)f(x)=max(0,x)
- 正数?放行。负数?滚。
- ✅ 计算快,求导简单
- ❌ 负区间梯度为 0 → “神经元死亡”(一旦输出负值,永远醒不过来)
批注:ReLU在正数区域内的梯度为1,可以保证梯度在传递过程中不会消失。
GeLU:温柔版门卫
f(x)=x⋅Φ(x)f(x) = x \\cdot \\Phi(x)f(x)=x⋅Φ(x)
不是硬邦邦地"负数全拒",而是用概率平滑过渡。Bert、GPT 系列都用它。
SwiGLU / GeGLU:当前顶流
LLaMA、Qwen 等新一代模型的标配。核心思想:把 FFN 拆成两个门控分支,一个走 Swish/GeLU 激活,另一个当"门"控制信息流量。
SwiGLU(x)=(Swish(xW1)⊙(xW3))W2\\text{SwiGLU}(x) = (\\text{Swish}(xW_1) \\odot (xW_3)) W_2SwiGLU(x)=(Swish(xW1)⊙(xW3))W2
比喻:以前厨房只有一个厨师做菜。现在一个厨师做菜,另一个厨师决定"这道菜上不上、上多少"。精细控制,效果更好。
2.6 FFN 隐藏维度演进:厨房越扩越大,又缩回去了
FFN(前馈网络)是 Transformer 里的"厨房"——注意力层负责"看菜单",FFN 负责"炒菜"。
经典配置:4d
原始 Transformer:输入维度 d=512,FFN 隐藏层 4d=2048。
比喻:厨房面积是餐厅的 4 倍。够用了。
大模型时代:8d → 3d
- GPT-3 用 4d
- PaLM 用 4d 但加了 SwiGLU,等效约 8d/3 ≈ 2.67d(因为 SwiGLU 多一个矩阵)
最新趋势:2.7d
LLaMA 的做法:用 SwiGLU,隐藏维度设为 8d3\\frac{8d}{3}38d(约 2.67d),但因为 SwiGLU 有 3 个权重矩阵,总参数量跟 4d 的普通 FFN 差不多。
翻译成人话:厨房没变大,但换了更高效的灶台,炒出更多菜。
2.7 残差连接:给梯度修一条"高速公路"
问题:信号传着传着就没了
100 层网络,梯度每层乘一个小数,传到第 1 层时已经接近 0。这叫梯度消失。
批注:ResNet通过残差连接构建H(x)=F(x)+x的恒等映射,确保深层网络至少能保留浅层特征。
解决方案:修一条直通的"电梯"
H(x)=F(x)+xH(x) = F(x) + xH(x)=F(x)+x
- F(x)F(x)F(x):走楼梯(经过卷积/注意力等变换)
- xxx:坐电梯(原封不动传过去)
反向传播时:
∂H∂x=∂F∂x+1\\frac{\\partial H}{\\partial x} = \\frac{\\partial F}{\\partial x} + 1∂x∂H=∂x∂F+1
那个 “+1” 就是电梯——不管楼梯多难走,梯度至少有一条直通路径。
批注:反向传播时,残差连接使得梯度可通过 ∂H/∂x = ∂F/∂x + 1 路径直接传递,避免连续卷积层的导数连乘导致梯度消失。
在 Transformer 中的位置
每个子层(Attention、FFN)后面都跟一个残差连接:
x → [Sub-Layer] → + x → LayerNorm → 输出
没有这条"电梯",Transformer 堆到 12 层以上基本就训不动了。
2.8 长上下文优化:从"只能看一页"到"看完整本书"
痛点:O(n²) 的诅咒
标准 Self-Attention 的计算量和显存都是 O(n2)O(n^2)O(n2)。序列长度从 512 涨到 128K,计算量涨了 62500 倍。
这就像你每读一个新字,都要把之前所有字重新看一遍——书越厚,越读越慢。
第一代:稀疏注意力(Longformer / BigBird)
思路:别每个词都看所有词了,只看附近的 + 几个关键的。
- Longformer:滑动窗口(局部)+ 全局 token
- BigBird:局部 + 全局 + 随机连接
比喻:以前每页都要跟其他所有页握手。现在只跟前后 3 页握手,再跟目录页和附录页握个手。
复杂度:O(n2)O(n^2)O(n2) → O(n)O(n)O(n)
第二代:Flash Attention(1/2/3)
思路:不改变数学公式,而是优化 GPU 内存访问模式。
传统实现:把 n×nn \\times nn×n 的注意力矩阵完整写进 GPU 显存(HBM),再读出来算 softmax。来回搬运数据是瓶颈。
Flash Attention:把计算拆成小块,在 GPU 的 SRAM(超快缓存)里完成,从不把完整的 n×n 矩阵写进 HBM。
- Flash Attention 1(2022):速度提升 2~4 倍
- Flash Attention 2(2023):优化并行,再快 2 倍
- Flash Attention 3(2024):利用 H100 的异步特性,接近硬件理论峰值
比喻:以前做菜要把所有食材从仓库搬到厨房,做完再搬回去。现在直接在仓库门口支个灶,现拿现炒,省了搬运时间。
第三代:Paged Attention(vLLM)
批注:PagedAttention借鉴了操作系统虚拟内存分页管理思想,将显存划分为固定大小的块(Page),通过分页表记录KV缓存的物理地址映射关系,有效解决显存碎片化问题。
问题:推理时,KV Cache 需要为每个序列预分配连续显存。序列长短不一 → 显存碎片化 → 利用率不到 60%。
解决:学操作系统的虚拟内存分页。
- 把 KV Cache 切成固定大小的"页"(如 16 个 token 一页)
- 用"页表"记录逻辑地址 → 物理地址的映射
- 不同序列可以共享相同的页(比如系统提示词)
效果:显存利用率从 <60% 提升到 >90%,吞吐量提升 14~24 倍。
比喻:以前图书馆给每个读者预留一整排连续书架,有人只看 3 本书也占一排。现在把书拆成标准大小的"书箱",按需分配,不同读者还能共享同一箱参考书。
长上下文技术演进总结
| 1.0 | Longformer/BigBird | 稀疏化注意力模式 | O(n) |
| 2.0 | Flash Attention | 优化硬件内存访问 | O(n²) 但常数极小 |
| 3.0 | Paged Attention | 分页管理 KV Cache | 解决显存碎片 |
批注:KV缓存通过存储注意力机制中的键值对,避免重复计算历史token的注意力,从而加速推理。
本章小结:一张图看懂 Transformer 一层
输入 x
│
├─→ LayerNorm (RMSNorm)
│ │
│ ▼
│ Multi-Head Self-Attention (带 RoPE)
│ │
│ ▼
└──→ (+) ← 残差连接(电梯)
│
▼
LayerNorm
│
▼
FFN (SwiGLU, 隐藏维度 ≈ 8d/3)
│
▼
(+) ← 残差连接(电梯)
│
▼
输出 → 送入下一层
堆 N 层(12 / 32 / 80 / 128……),加上 Embedding 和输出头,就是一个完整的 Transformer。
下一章预告:第 3 章我们将进入"炼丹房"——预训练、指令微调、RLHF、LoRA……看看一个大模型是怎么从"白纸"变成"全能选手"的。剧透:LoRA 就是给法拉利换个尾翼,而不是重新造一辆车。
本章完。如果你读到这里还没晕,恭喜你,你已经比 80% 的"AI 从业者"更懂 Transformer 了。 🎉





