Transformer拆解13:现代大模型改了什么,RoPE、RMSNorm、SwiGLU与GQA

我是老计。走到这里,经典Transformer的主要零件已经拆完。可你打开现代大模型配置,会看到一批原论文里没有的名字:RoPE、RMSNorm、SwiGLU、MQA、GQA。
容易出现两个极端。一种认为现代大模型和2017年Transformer完全一样,只是参数更多;另一种认为零件换了这么多,它已经不是Transformer。两种说法都过于简单。
现代大模型保留了Transformer的主干分工:注意力负责位置间信息交换,前馈网络逐位置加工,残差连接组织深层路径。变化主要发生在位置表示、归一化、激活门控和键值头共享方式上。
本篇不把这些缩写罗列成名词表,而是逐项回答:原来怎么做、现在改了什么、它试图解决什么、代价和边界是什么。
一,先立一条历史边界
2017年原始Transformer的代表性配置包括:
- Encoder-Decoder整体结构;
- 固定正弦位置编码与Embedding相加;
- 多头注意力中Q、K、V头数相同;
- Position-wise FFN使用ReLU;
- 子层后残差相加再LayerNorm,也就是Post-Norm。
许多现代Decoder-only大模型常见:
- RoPE作用于Q和K;
- Pre-Norm路径;
- RMSNorm;
- SwiGLU门控前馈网络;
- MQA或GQA减少KV头数量。
"常见"不等于"全部"。不同模型家族会选择不同组合,甚至同一家族不同代也会调整。写文章或读配置时,必须以具体模型技术报告和代码为准。

二,位置表示,从输入相加到QK旋转
经典正弦位置编码生成 [S,d_model] 的位置向量,与Token Embedding逐元素相加。位置和内容从模型入口就混在同一主干表示里。
RoPE不准备一张位置向量与输入相加。它把Q、K的维度两两配对,根据位置施加旋转。旋转后点积显式包含相对位置差。
RoPE试图带来什么
- 位置直接影响QK兼容度;
- 旋转保持每对向量的范数;
- 相同相对位移在理想二维推导中形成相同旋转差;
- 不需要可学习绝对位置表。
它没有自动解决什么
RoPE不自动保证模型能可靠处理任意长上下文。训练长度、频率基数、位置缩放、注意力分布和KV Cache容量都会限制有效长度。
现代模型还使用各种RoPE缩放和插值方案。它们不是原始RoPE定义的一部分,兼容预训练权重需要遵循模型配置。只把上下文长度字段改大,通常不能得到同等质量的长上下文能力。
三,归一化,从LayerNorm到RMSNorm
LayerNorm对每个Token隐藏向量减均值、按标准差缩放,再使用可训练增益和偏移。RMSNorm不减均值,只按均方根缩放,常见实现保留可训练增益而没有偏移。
RMSNorm改变了什么
它省去重新居中步骤,计算结构更简单。RMSNorm论文的核心观点是保留重新缩放不变性,而认为重新居中并非所有场景都必需。
不能怎样表述
- 不能说RMSNorm等于没有均值的LayerNorm后输出仍是零均值;
- 不能说RMSNorm在任何模型上都必然更快某个固定比例;
- 不能把已训练LayerNorm模型直接换成RMSNorm并期待无损;
- 不能忽略epsilon、可训练权重和低精度统计实现。
现代大模型常把RMSNorm放在注意力或FFN之前,形成Pre-Norm主干。但RMSNorm与Pre-Norm是两个维度:一个回答用什么归一化,一个回答归一化放在子层前还是后,不能混成同义词。
四,前馈网络,从ReLU到SwiGLU
经典FFN是两次线性投影,中间使用ReLU:
text
FFN(x) = ReLU(xW_1 + b_1)W_2 + b_2
SwiGLU使用两条输入投影,一条经过SiLU作为门,另一条提供内容,然后逐元素相乘,再投影回主干:
text
hidden = SiLU(xW_g) elementwise_multiply (xW_v)
output = hidden W_o
门控的直觉
内容分支回答"有哪些候选特征",门控分支回答"当前输入应让哪些特征通过多少"。两条分支都由输入动态计算,因此不是一个固定开关表。
公平比较为什么要调中间宽度
普通FFN主要有两组大矩阵,SwiGLU通常有三组。若保持相同中间宽度,SwiGLU参数和计算更多。现代模型常缩小门控FFN的中间宽度,使总参数预算接近。
所以比较ReLU与SwiGLU,至少要说明是否对齐:
- 主干隐藏维度;
- 中间维度;
- 总参数量;
- 训练Token和数据;
- 优化器与学习率;
- 推理内核与硬件。
把激活函数名字换掉不等于完成公平实验。SwiGLU的两条输入投影改变了参数结构,必须连同中间宽度一起比较。
五,注意力头,从MHA到MQA与GQA
标准MHA中,查询头数、键头数和值头数相同。假设有8个查询头,就有8组K和8组V。
MQA保留多个查询头,但所有查询头共享一组K和V。GQA位于两者之间,多个查询头被分成若干组,每组共享一组K/V。
例如8个查询头、2个KV头时,可以让前4个查询头使用KV头0,后4个使用KV头1。
严格定义三者
text
MHA:H_q = H_kv
GQA:1 < H_kv < H_q
MQA:H_kv = 1
常见高效实现要求 H_q 能被 H_kv 整除,以便每组拥有相同数量查询头。数学上也可以设计不等分映射,但不能直接套标准reshape和广播逻辑。
为什么减少KV头能帮助推理
自回归解码每一步都要读取历史K/V。KV头越少:
- 缓存元素数越少;
- 每步从显存读取历史K/V的数据量下降;
- 内存带宽压力可能减轻;
- 同样显存可能容纳更长上下文或更大批次。
它主要针对增量解码的缓存和带宽,不意味着训练算力、模型质量或端到端延迟一定按KV头比例变化。

六,用NumPy计算KV头映射和缓存元素数
设批次2、历史长度128、查询头8、每头维64,只比较单层K/V元素数:
python
import numpy as np
B, L, H_q, head_dim = 2, 128, 8, 64
for name, H_kv in [("MHA", 8), ("GQA", 2), ("MQA", 1)]:
elements = 2 * B * L * H_kv * head_dim
q_to_kv = np.arange(H_q) // (H_q // H_kv)
print(
name,
"kv_heads=", H_kv,
"elements=", elements,
"q_to_kv=", q_to_kv.tolist(),
)
运行环境:Python 3,NumPy 1.26.4,CPU。实际输出:
text
MHA kv_heads= 8 elements= 262144 q_to_kv= [0, 1, 2, 3, 4, 5, 6, 7]
GQA kv_heads= 2 elements= 65536 q_to_kv= [0, 0, 0, 0, 1, 1, 1, 1]
MQA kv_heads= 1 elements= 32768 q_to_kv= [0, 0, 0, 0, 0, 0, 0, 0]
公式中的第一个2表示K和V两份,不是批次。总元素数为:
text
2乘B乘L乘H_kv乘head_dim
在这组配置中,GQA缓存元素数是MHA的四分之一,MQA是八分之一。这只是理想元素数量比例,不能直接写成推理速度提升4倍或8倍。真实速度还受Q投影、注意力计算、FFN、内核、批次、并行通信和调度影响。
完整模型还要乘层数和字节数
若有 N_layers 层、每元素 bytes 字节,总缓存近似:
text
KV bytes = 2乘B乘L乘N_layers乘H_kv乘head_dim乘bytes
有的系统按请求分别管理,有的做分页缓存、块共享或量化;内存分配还会有元数据和碎片。公式是核心张量体积,不是进程完整显存账单。
七,用代码验证RMSNorm和SwiGLU形状
下面把输入先做无仿射RMSNorm,再通过简化SwiGLU。这里不含注意力和残差,只验证两个零件的统计与形状。
python
import numpy as np
rng = np.random.default_rng(131)
x = rng.normal(size=(2, 3, 8))
epsilon = 1e-6
rms = x / np.sqrt(np.mean(x * x, axis=-1, keepdims=True) + epsilon)
wg = rng.normal(size=(8, 12))
wv = rng.normal(size=(8, 12))
wo = rng.normal(size=(12, 8))
def silu(z):
return z / (1 + np.exp(-z))
y = (silu(rms @ wg) * (rms @ wv)) @ wo
print("input:", x.shape, "rms:", rms.shape, "swiglu output:", y.shape)
print("rms values:", np.round(
np.sqrt(np.mean(rms * rms, axis=-1)), 6
))
实际输出:
text
input: (2, 3, 8) rms: (2, 3, 8) swiglu output: (2, 3, 8)
rms values: [[0.999999 1. 1. ]
[1. 0.999999 0.999999]]
RMSNorm不改变形状,SwiGLU先扩到12维再投影回8维。均方根接近1,因为epsilon让结果不是数学上绝对等于1。
八,这些改造不是一条因果链
RoPE、RMSNorm、SwiGLU和GQA解决的是不同问题:
- RoPE改变位置如何进入QK关系;
- RMSNorm简化归一化统计;
- SwiGLU改变逐Token非线性加工;
- GQA减少KV头共享以降低推理缓存和带宽。
它们可以组合,但不是"用了RoPE就必须用RMSNorm""用了SwiGLU就必须用GQA"。每项都要与训练配方和内核共同验证。
现代模型质量来自数据、规模、优化、架构和训练稳定性共同作用。不能把模型提升归因给某一个零件,也不能从不同论文的独立结果拼出一个保证更强的配方。
架构改造不是积木排行榜。每个零件改变一条计算路径,也引入新的参数、数值和部署约束,组合效果必须靠完整训练与评测证明。
九,工程选型怎样避免只看配置表
阅读模型配置时,建议按四层检查:
- 数学结构:位置、归一化、FFN、头共享分别是什么;
- 张量形状:查询头、KV头、每头维度和中间宽度是否匹配;
- 训练事实:模型权重是否按这套结构训练,不能随意替换;
- 运行实现:推理框架是否支持对应内核、量化、并行和缓存布局。
例如某模型使用GQA,但推理框架若把KV重复展开成查询头数量再计算,缓存或带宽优势可能被部分抵消。某模型使用SwiGLU,但硬件没有高效融合内核,延迟收益也不能只看公式预测。
十,GQA在张量上怎样广播
设查询头数 H_q=8、KV头数 H_kv=2、每组4个查询头。投影后形状可以是:
text
Q:[B,8,T,head_dim]
K、V:[B,2,S,head_dim]
计算注意力前,要建立查询头到KV头的映射。概念上,查询头0至3使用KV头0,查询头4至7使用KV头1。
一种简单实现会把每个KV头重复4次,临时得到8头K/V再调用MHA内核;这种做法计算正确,却可能物化重复数据,削弱内存优势。更高效内核可以在计算中按组广播,不真的复制缓存。
缓存减少与投影参数减少要分开
GQA不仅可能减少缓存,也会减少K/V投影输出宽度和相应参数。若Q投影仍输出 H_q×head_dim,K/V只输出 H_kv×head_dim:
text
W_Q:[d_model, H_q乘head_dim]
W_K:[d_model, H_kv乘head_dim]
W_V:[d_model, H_kv乘head_dim]
但具体模型可能让Q头维、KV头维或总隐藏宽度采用其他约定。计算参数量必须读配置,不能只看"用了GQA"四个字。
从MHA检查点转为GQA不是直接改数字
GQA论文给出了从已有MHA检查点上训练转换的方法。一般需要把多组K/V参数按策略聚合或初始化,再继续训练适配。直接把配置中的KV头数从8改成2,会导致权重形状不匹配;粗暴重复或平均虽然能构造参数,也不保证质量。
GQA是一种需要模型参数配套训练的架构,不是推理时随手打开的无损开关。
十一,以LLaMA为例怎样描述才准确
LLaMA技术报告是现代组合的代表之一:它在Transformer主干上使用Pre-Norm、RMSNorm、SwiGLU和RoPE。不过不同LLaMA代际和规模的注意力头组织并不应只靠家族名概括,具体是否使用GQA、头数和上下文策略要查对应版本配置。
这给写技术文章一个重要提醒:
- 可以用具体技术报告说明某代模型采用了哪些改造;
- 不要把整个模型家族所有版本写成完全相同;
- 不要从一个模型使用某组合,推导这套组合是现代大模型标准答案;
- 不要把训练数据、规模带来的能力提升全部归因于架构零件。
现代模型配置是多目标权衡:训练稳定、质量、参数预算、推理显存、硬件内核和分布式策略共同决定结果。
十二,为什么不能在现有权重上直接换零件
这些结构会改变前向计算,预训练权重已经与原结构共同适配:
- 正弦相加改RoPE,会改变位置进入注意力的方式;
- LayerNorm改RMSNorm,会改变每层激活统计;
- ReLU FFN改SwiGLU,会改变矩阵数量和权重形状;
- MHA改GQA,会改变K/V投影与缓存头映射。
因此"配置文件改一行"通常不够。至少需要权重转换、继续训练、蒸馏或从头训练,并在质量与性能上验证。某些近似初始化方法可以降低转换成本,但不能预先保证无损。
即使两个模型参数总量接近,也可能因为计算图不同无法直接互换权重。模型格式转换应比较固定输入下的逐层激活和最终Logits,而不是只看权重文件成功加载。
现代改造是训练架构的一部分,不是推理阶段随意替换的插件。权重与计算图必须配套。
十三,常见误区
误区一:现代大模型只是把Transformer做大
主干仍是Transformer,但位置、归一化、FFN和注意力头组织已有多种改造。
误区二:RoPE加在输入Embedding上
标准RoPE通常旋转Q和K,不是输入位置向量相加。
误区三:RMSNorm会把均值归一到0
它不减均值,只按均方根缩放。
误区四:SwiGLU只替换一个激活函数
它通常多一条输入投影和逐元素门控,参数结构发生变化。
误区五:GQA减少查询头
GQA通常保留多个查询头,减少并共享KV头。查询头与KV头数量不能混称。
误区六:KV缓存缩小几倍,速度就提升几倍
缓存体积和读取量只是端到端性能的一部分,实际收益要在真实硬件和请求上测量。
小结
现代大模型常在经典Transformer主干上采用RoPE、Pre-RMSNorm、SwiGLU和MQA/GQA。RoPE把位置注入QK旋转,RMSNorm不做均值居中,SwiGLU使用门控与内容两条投影,GQA让多个查询头分组共享更少KV头。
这些改造各解决不同问题,不是绑定套餐,也不保证简单拼装就更好。尤其GQA的KV缓存元素数下降,不能直接当作端到端加速比例。
下一篇收官,集中拆KV Cache与FlashAttention:一个减少重复计算和历史读取,一个减少注意力在内存层级间搬运,它们到底优化了什么、没有优化什么。
延伸阅读
- Touvron等,《LLaMA: Open and Efficient Foundation Language Models》:arxiv.org/abs/2302.13971
- Su等,《RoFormer》:arxiv.org/abs/2104.09864
- Shazeer,《GLU Variants Improve Transformer》:arxiv.org/abs/2002.05202
- Ainslie等,《GQA》:arxiv.org/abs/2305.13245
(本文为技术学习与经验分享,代码用于理解机制。框架与实现可能随版本变化,具体用法请以官方最新文档为准。)
版权声明:本文版权归作者老计个人所有。欢迎个人学习阅读,未经授权,禁止转载、摘编、搬运或用于任何商业用途,违者将追究责任。转载请联系作者Jich。