引言:1750亿参数从何而来?
当你看到"GPT-3有1750亿参数"、“LLaMA 7B”、“Claude 100K上下文"这样的描述时,你是否想过:这1750亿参数到底是怎么算出来的?它们分别存储在模型的哪些部分?
这个问题并非简单的好奇心。理解参数量的计算,是深入理解大模型架构的第一步。当你需要估算训练成本、规划显存需求、甚至设计新的模型架构时,这都成为必须掌握的基础知识。
让我们从一个简单的问题开始:假设一个Transformer模型有$d_{\text{model}}=4096$的隐藏维度,$n_{\text{layers}}=32$层,词表大小$V=32000$,它的总参数量是多少?读完这篇文章,你将能够徒手计算出答案。
mindmap
root((Transformer参数量))
Embedding层
词嵌入 V×d
位置嵌入 ctx×d
Transformer层×L
Attention
Q/K/V投影
输出投影
FFN
升维层 W₁
降维层 W₂
LayerNorm
γ参数
β参数
输出层
词表投影
为什么参数量如此重要?
在深入公式之前,先理解参数量的三个核心意义:
第一,参数量决定显存需求。 一个参数在FP16精度下占用2字节,FP32精度下占用4字节。1750亿参数的GPT-3,仅存储模型权重就需要350GB显存(FP16)。这就是为什么大模型训练需要数百张GPU。
第二,参数量与计算量直接相关。 模型每处理一个token,大约需要进行$2 \times P$次浮点运算,其中$P$是参数量。这个简单的公式可以帮助你估算推理速度和训练时间。
第三,参数量分布揭示模型设计哲学。 你可能以为Attention机制是Transformer的核心,参数量应该最多?事实恰恰相反——FFN(前馈网络)占据了约三分之二的参数量。这个发现会改变你对模型架构的理解。
graph LR
A[参数量 P] --> B[显存需求<br/>FP16: 2P bytes]
A --> C[计算量<br/>推理: 2P FLOPs]
A --> D[训练成本<br/>约 6P×tokens]
B --> E[GPU数量规划]
C --> F[推理速度预估]
D --> G[预算评估]
style A fill:#f9f,stroke:#333
style B fill:#bbf,stroke:#333
style C fill:#bfb,stroke:#333
style D fill:#fbf,stroke:#333
核心公式:参数量的快速估算
在逐层拆解之前,先给出一个快速估算公式:
$$P \approx 12 \times n_{\text{layers}} \times d_{\text{model}}^2$$这个公式来自一个关键的观察:在Transformer中,绝大多数参数来自于$d_{\text{model}} \times d_{\text{model}}$形状的矩阵乘法。
以LLaMA 7B为例:$n_{\text{layers}}=32$,$d_{\text{model}}=4096$。套用公式:
$$P \approx 12 \times 32 \times 4096^2 = 6.44 \times 10^9$$实际LLaMA 7B有约7B参数,误差来自FFN隐藏维度略大于$4d_{\text{model}}$以及词表嵌入层。这个估算公式虽然简化了细节,但足够用于快速评估。
接下来,我们将深入每个组件,理解这个公式背后的完整推导。
第一部分:Embedding层的参数
Embedding层是模型的入口,负责将离散的token索引转换为连续向量表示。
词嵌入(Token Embedding)
词嵌入矩阵的形状是$V \times d_{\text{model}}$,其中$V$是词表大小。每个token对应一个$d_{\text{model}}$维的向量。
$$P_{\text{token\_emb}} = V \times d_{\text{model}}$$以GPT-2为例,$V=50257$,$d_{\text{model}}=768$:
$$P_{\text{token\_emb}} = 50257 \times 768 = 38,597,376$$大约3860万参数,占GPT-2 124M总参数量的约31%。
位置嵌入(Position Embedding)
原始Transformer使用可学习的位置嵌入:
$$P_{\text{pos\_emb}} = n_{\text{ctx}} \times d_{\text{model}}$$其中$n_{\text{ctx}}$是最大序列长度。GPT-2支持$n_{\text{ctx}}=1024$:
$$P_{\text{pos\_emb}} = 1024 \times 768 = 786,432$$约78万参数,相对较小。
注意: 现代大模型(如LLaMA、GPT-3)使用旋转位置编码(RoPE)或ALiBi,这些方法不增加可学习参数。
Embedding层的参数占比之谜
有趣的是,Embedding层的参数占比会随模型规模急剧下降:
| 模型 | 词表大小 | 隐藏维度 | Embedding参数 | 总参数 | 占比 |
|---|---|---|---|---|---|
| GPT-2 Small | 50,257 | 768 | 38.6M | 124M | 31% |
| GPT-3 175B | 50,257 | 12,288 | 617M | 175B | 0.35% |
| LLaMA 7B | 32,000 | 4,096 | 131M | 7B | 1.9% |
原因很简单:Embedding参数量与$d_{\text{model}}$成线性关系,而其他组件的参数量与$d_{\text{model}}^2$成比例。当$d_{\text{model}}$增大时,Embedding的占比被迅速稀释。
graph TD
subgraph GPT2["GPT-2 Small (124M)"]
E1["Embedding: 31%"] --> A1["Attention: 22%"]
A1 --> F1["FFN: 45%"]
F1 --> O1["其他: 2%"]
end
subgraph GPT3["GPT-3 175B"]
E2["Embedding: 0.35%"] --> A2["Attention: 22%"]
A2 --> F2["FFN: 75%"]
F2 --> O2["其他: 2.65%"]
end
style E1 fill:#ff9
style E2 fill:#ff9
style F1 fill:#9f9
style F2 fill:#9f9
第二部分:Attention层的参数
Attention层是Transformer的核心创新,但它的参数量却出人意料地"轻量”。
单头注意力的参数结构
一个完整的Self-Attention需要四个投影矩阵:
- Query投影 $W_Q$:将输入投影到查询空间
- Key投影 $W_K$:将输入投影到键空间
- Value投影 $W_V$:将输入投影到值空间
- Output投影 $W_O$:将注意力输出投影回原空间
每个矩阵的形状都是$d_{\text{model}} \times d_{\text{model}}$(不考虑多头拆分时)。
flowchart LR
X[输入 X<br/>shape: n×d] --> Q[Q = XW_Q<br/>shape: n×d]
X --> K[K = XW_K<br/>shape: n×d]
X --> V[V = XW_V<br/>shape: n×d]
Q --> A[Attention<br/>QK^T/√d × V]
K --> A
V --> A
A --> O[Output = AW_O<br/>shape: n×d]
O --> Y[输出 Y]
style Q fill:#e1f5fe
style K fill:#e1f5fe
style V fill:#e1f5fe
style O fill:#e8f5e9
多头注意力的参数计算
在多头注意力中,总维度$d_{\text{model}}$被分配到$n_{\text{heads}}$个头上。每个头的维度为:
$$d_{\text{head}} = \frac{d_{\text{model}}}{n_{\text{heads}}}$$关键洞察:多头注意力不改变参数量。无论有多少个头,Q、K、V的总投影矩阵大小仍然是$d_{\text{model}} \times d_{\text{model}}$。
flowchart TB
subgraph 输入
X["输入向量 (d_model=768)"]
end
subgraph 投影矩阵
WQ["W_Q: 768×768"]
WK["W_K: 768×768"]
WV["W_V: 768×768"]
WO["W_O: 768×768"]
end
subgraph 多头拆分
H1["头1: Q₁,K₁,V₁<br/>各64维"]
H2["头2: Q₂,K₂,V₂<br/>各64维"]
HN["头12: Q₁₂,K₁₂,V₁₂<br/>各64维"]
end
X --> WQ
X --> WK
X --> WV
WQ --> H1
WQ --> H2
WQ --> HN
WK --> H1
WK --> H2
WK --> HN
WV --> H1
WV --> H2
WV --> HN
H1 --> WO
H2 --> WO
HN --> WO
style WQ fill:#bbf
style WK fill:#bfb
style WV fill:#fbf
style WO fill:#ffb
含偏置项的完整公式
实际实现中,每个线性层通常都有偏置项:
$$P_{\text{attn}} = 4 \times d_{\text{model}}^2 + 4 \times d_{\text{model}}$$其中:
- $4 \times d_{\text{model}}^2$:四个投影矩阵的权重
- $4 \times d_{\text{model}}$:四个投影矩阵的偏置
每层Attention参数量
$$P_{\text{attn\_layer}} = 4d_{\text{model}}^2 + 4d_{\text{model}}$$对于$d_{\text{model}}=4096$:
$$P_{\text{attn\_layer}} = 4 \times 4096^2 + 4 \times 4096 = 67,149,312$$约67M参数。但要注意,很多现代实现(如LLaMA)去掉了偏置项,此时:
$$P_{\text{attn\_layer}} = 4d_{\text{model}}^2 = 67,108,864$$第三部分:FFN层的参数——真正的参数大户
FFN(Feed-Forward Network)是一个两层全连接网络,在每层的Attention之后应用:
$$\text{FFN}(x) = \text{GELU}(xW_1 + b_1)W_2 + b_2$$FFN的维度设计
标准Transformer中,FFN的隐藏维度$d_{\text{ff}}$通常是$d_{\text{model}}$的4倍:
$$d_{\text{ff}} = 4 \times d_{\text{model}}$$这个4倍的比例来自原始论文的设计,在现代大模型中有所调整:
- GPT系列:保持4倍
- LLaMA系列:使用约2.7倍($d_{\text{ff}} = \frac{2}{3} \times 4d_{\text{model}}$)
FFN参数量计算
FFN包含两个线性变换:
- 升维层 $W_1$:$d_{\text{model}} \to d_{\text{ff}}$
- 降维层 $W_2$:$d_{\text{ff}} \to d_{\text{model}}$
当$d_{\text{ff}} = 4d_{\text{model}}$时:
$$P_{\text{ffn}} = 8d_{\text{model}}^2$$flowchart LR
subgraph FFN结构
IN["输入<br/>d_model=768"] --> W1["W₁升维<br/>768×3072"]
W1 --> ACT["GELU激活"]
ACT --> W2["W₂降维<br/>3072×768"]
W2 --> OUT["输出<br/>d_model=768"]
end
subgraph 参数量
P1["W₁: 2.4M参数"]
P2["W₂: 2.4M参数"]
PT["总计: 4.7M参数"]
end
W1 -.-> P1
W2 -.-> P2
P1 --> PT
P2 --> PT
style W1 fill:#fbb
style W2 fill:#fbb
style PT fill:#bfb
含偏置项的完整公式
$$P_{\text{ffn}} = 2d_{\text{model}}d_{\text{ff}} + d_{\text{ff}} + d_{\text{model}}$$代入$d_{\text{ff}} = 4d_{\text{model}}$:
$$P_{\text{ffn}} = 8d_{\text{model}}^2 + 5d_{\text{model}}$$为什么FFN参数这么多?
对比Attention和FFN的参数量:
| 组件 | 参数量(无偏置) | 参数量比例 |
|---|---|---|
| Attention | $4d_{\text{model}}^2$ | 33% |
| FFN | $8d_{\text{model}}^2$ | 67% |
FFN的参数量是Attention的两倍。这个比例在整个模型中保持一致,使得FFN占据了Transformer参数量的三分之二。
这背后的原理是:Attention负责"信息路由"——决定哪些位置的信息应该被聚合;FFN负责"知识存储"——在每层存储和处理丰富的语义信息。研究表明,FFN在某种程度上充当了模型的"知识库"。
第四部分:LayerNorm的参数
LayerNorm(层归一化)在每个子层前后各有一个,负责稳定训练。
每个LayerNorm有两个可学习参数:
- $\gamma$(scale):缩放系数
- $\beta$(shift):偏移系数
每层有两个LayerNorm(Attention前和FFN前,或采用Post-LN时在之后):
$$P_{\text{ln\_layer}} = 4d_{\text{model}}$$LayerNorm参数量很小,通常可以忽略不计。
第五部分:完整公式推导
将所有组件组合起来,得到单个Transformer层的参数量:
$$P_{\text{layer}} = P_{\text{attn}} + P_{\text{ffn}} + P_{\text{ln}}$$$$P_{\text{layer}} = (4d_{\text{model}}^2 + 4d_{\text{model}}) + (8d_{\text{model}}^2 + 5d_{\text{model}}) + 4d_{\text{model}}$$$$P_{\text{layer}} = 12d_{\text{model}}^2 + 13d_{\text{model}}$$graph TB
subgraph 单层参数分解
A["Attention: 4d² + 4d"]
F["FFN: 8d² + 5d"]
L["LayerNorm: 4d"]
end
A --> T["总计: 12d² + 13d"]
F --> T
L --> T
subgraph 占比分析
R1["Attention占比: 33%"]
R2["FFN占比: 67%"]
R3["LayerNorm占比: <1%"]
end
T --> R1
T --> R2
T --> R3
style A fill:#e1f5fe
style F fill:#fff3e0
style L fill:#e8f5e9
style T fill:#f3e5f5
全模型参数量
$$P_{\text{total}} = P_{\text{emb}} + n_{\text{layers}} \times P_{\text{layer}} + P_{\text{output}}$$展开:
$$P_{\text{total}} = V \times d_{\text{model}} + n_{\text{layers}} \times (12d_{\text{model}}^2 + 13d_{\text{model}}) + V \times d_{\text{model}}$$如果使用权重共享(Weight Tying),输出层和输入嵌入层共享参数,则:
$$P_{\text{total}} = V \times d_{\text{model}} + n_{\text{layers}} \times (12d_{\text{model}}^2 + 13d_{\text{model}})$$pie title 参数量分布(典型大模型)
"FFN层" : 66
"Attention层" : 22
"Embedding层" : 10
"LayerNorm" : 2
第六部分:实际模型验证
让我们用真实模型验证这些公式。
GPT-2 Small (124M)
官方配置:
- 词表大小:$V = 50,257$
- 隐藏维度:$d_{\text{model}} = 768$
- 层数:$n_{\text{layers}} = 12$
- 注意力头:$n_{\text{heads}} = 12$
- FFN隐藏维度:$d_{\text{ff}} = 3072$($4 \times 768$)
计算:
Embedding层:
$$P_{\text{emb}} = 50257 \times 768 + 1024 \times 768 = 39,383,808$$每层Transformer:
$$P_{\text{layer}} = 4 \times 768^2 + 8 \times 768^2 = 7,077,888$$(简化计算,忽略偏置)
总层数参数:
$$12 \times 7,077,888 = 84,934,656$$总计:
$$P_{\text{total}} \approx 39.4M + 84.9M = 124.3M$$与官方的124M参数完全吻合!
graph LR
subgraph GPT2参数计算
E["Embedding<br/>39.4M"] --> T["总计<br/>124.3M"]
L["12层Transformer<br/>84.9M"] --> T
end
subgraph 验证
V["官方数据<br/>124M ✓"]
end
T --> V
style T fill:#9f9
style V fill:#9f9
LLaMA 7B
官方配置:
- 词表大小:$V = 32,000$
- 隐藏维度:$d_{\text{model}} = 4096$
- 层数:$n_{\text{layers}} = 32$
- 注意力头:$n_{\text{heads}} = 32$
- FFN隐藏维度:$d_{\text{ff}} = 11,008$
LLaMA有几个特殊设计:
- 使用RoPE位置编码,无位置嵌入参数
- 使用RMSNorm,无偏置项
- 使用SwiGLU激活函数,FFN有三个矩阵而非两个
- 使用GQA(分组查询注意力),KV头数减少
考虑SwiGLU的FFN:
$$P_{\text{ffn}} = 3 \times d_{\text{model}} \times d_{\text{ff}} = 3 \times 4096 \times 11008 = 135,266,304$$每层参数:
$$P_{\text{layer}} = 4 \times 4096^2 + 135,266,304 = 202,377,216$$总层数参数:
$$32 \times 202,377,216 = 6,476,070,912$$加上词嵌入:
$$32,000 \times 4096 = 131,072,000$$总计:
$$6,476M + 131M \approx 6,607M \approx 6.6B$$实际LLaMA 7B约7B参数,差异来自GQA的具体实现和其他细节。估算已足够精确。
GPT-3 175B
官方配置:
- 词表大小:$V = 50,257$
- 隐藏维度:$d_{\text{model}} = 12,288$
- 层数:$n_{\text{layers}} = 96$
- 注意力头:$n_{\text{heads}} = 96$
使用快速估算公式:
$$P \approx 12 \times 96 \times 12288^2 = 174.6 \times 10^9$$约1746亿参数,与官方175B吻合!
graph TB
subgraph 模型参数对比
G2["GPT-2<br/>124M参数<br/>d=768, L=12"]
L7["LLaMA 7B<br/>7B参数<br/>d=4096, L=32"]
G3["GPT-3<br/>175B参数<br/>d=12288, L=96"]
end
G2 --> |"参数增长<br/>56倍"| L7
L7 --> |"参数增长<br/>25倍"| G3
style G2 fill:#e1f5fe
style L7 fill:#e8f5e9
style G3 fill:#fff3e0
第七部分:参数量与显存、计算量的关系
理解参数量后,我们可以推导显存需求和计算量。
显存占用估算
$$M = P \times b$$其中$b$是每个参数的字节数:
- FP32:$b = 4$ 字节
- FP16/BF16:$b = 2$ 字节
- INT8:$b = 1$ 字节
经验法则:在FP16精度下,1B参数约需2GB显存。
| 模型 | 参数量 | FP16显存(仅权重) |
|---|---|---|
| LLaMA 7B | 7B | ~14GB |
| LLaMA 70B | 70B | ~140GB |
| GPT-3 175B | 175B | ~350GB |
训练时还需存储梯度和优化器状态,显存需求约为推理的3-4倍。
graph LR
subgraph 显存需求
W["权重<br/>2P bytes (FP16)"]
G["梯度<br/>2P bytes"]
O["优化器状态<br/>4P bytes (Adam)"]
end
W --> T["总显存<br/>推理: 2P<br/>训练: 8P"]
G --> T
O --> T
subgraph 示例
E["LLaMA 7B训练<br/>约56GB显存"]
end
T --> E
style T fill:#fbb
style E fill:#bfb
计算量(FLOPs)估算
推理时,每处理一个token的计算量约为:
$$\text{FLOPs} \approx 2 \times P$$这个"2"来自矩阵乘法的乘加操作:一次乘法+一次加法=2次浮点运算。
训练时(前向+反向):
$$\text{FLOPs}_{\text{train}} \approx 6 \times P \times n_{\text{tokens}}$$其中$n_{\text{tokens}}$是训练的总token数。
第八部分:参数优化技术
了解参数来源后,我们可以有针对性地优化。
权重共享(Weight Tying)
让输入Embedding层和输出投影层共享参数:
$$W_{\text{output}} = W_{\text{embedding}}^T$$节省参数量:$V \times d_{\text{model}}$
对于GPT-2:节省$50,257 \times 768 = 38.6M$参数,约占总量31%。
这个技巧的理论依据是:词嵌入和输出投影本质上是同一语义空间的双向映射。
多查询注意力(MQA)与分组查询注意力(GQA)
传统多头注意力(MHA)中,每个Query头都有独立的Key和Value头。MQA让所有Query头共享一组Key-Value头:
flowchart TB
subgraph MHA["多头注意力 (MHA)"]
direction TB
Q1["Q头1"] --> A1["注意力计算"]
K1["K头1"] --> A1
V1["V头1"] --> A1
Q2["Q头2"] --> A2["注意力计算"]
K2["K头2"] --> A2
V2["V头2"] --> A2
Q3["Q头3"] --> A3["注意力计算"]
K3["K头3"] --> A3
V3["V头3"] --> A3
end
subgraph GQA["分组查询注意力 (GQA)"]
direction TB
Q4["Q头1"] --> A4["注意力计算"]
Q5["Q头2"] --> A4
Q6["Q头3"] --> A4
K4["共享K头"] --> A4
V4["共享V头"] --> A4
end
MHA --> |"参数节省"| GQA
style K4 fill:#fbb
style V4 fill:#fbb
GQA是MQA和MHA的折中:将Query头分成若干组,每组共享一组KV头。
参数节省(以LLaMA 2为例,32个Q头,8个KV头):
- 原始:$4d_{\text{model}}^2$参数用于KV投影
- GQA:$\frac{8}{32} \times 4d_{\text{model}}^2 = d_{\text{model}}^2$参数
节省75%的KV投影参数。更重要的是,GQA大幅减少了KV Cache的显存占用,显著提升推理速度。
低秩适应(LoRA)
LoRA不直接减少模型参数,而是通过低秩分解减少微调时需要训练的参数:
$$W = W_0 + \Delta W = W_0 + BA$$其中$B \in \mathbb{R}^{d \times r}$,$A \in \mathbb{R}^{r \times k}$,$r \ll \min(d, k)$。
训练参数从$dk$减少到$r(d+k)$,压缩比可达1000倍以上。
graph LR
subgraph 原始方法
W1["原始权重<br/>d×k参数<br/>全部训练"]
end
subgraph LoRA方法
W2["冻结权重 W₀<br/>不训练"]
A["矩阵A<br/>r×k参数"]
B["矩阵B<br/>d×r参数"]
A --> ADD["相加"]
B --> ADD
W2 --> ADD
end
W1 --> |"参数减少<br/>100倍+"| LoRA方法
style W1 fill:#fbb
style W2 fill:#bfb
style A fill:#bbf
style B fill:#bbf
第九部分:常见误区澄清
误区一:参数越多模型越强
参数量只是模型能力的一个维度。训练数据质量、架构设计、训练方法同样重要。LLaMA 7B在某些任务上超过GPT-3 175B就是明证。
误区二:Attention是参数量的大头
恰恰相反,FFN才是参数量的主要贡献者。Attention负责"路由",FFN负责"存储"。理解这一点对于模型优化和剪枝至关重要。
误区三:增加层数和增加宽度等效
虽然都增加参数量,但效果不同:
- 增加层数:增加模型深度,可能提升推理能力
- 增加宽度:增加表示容量,可能提升知识存储
现代研究表明,在相同参数预算下,“宽而浅"vs"窄而深"的选择取决于具体任务。
总结:参数量计算的思维框架
让我们回到开头的问题:一个$d_{\text{model}}=4096$、$n_{\text{layers}}=32$、$V=32000$的模型,参数量是多少?
应用公式:
$$P \approx 12 \times 32 \times 4096^2 + 32000 \times 4096$$$$P \approx 6.44 \times 10^9 + 131 \times 10^6 \approx 6.57B$$
约66亿参数。如果使用SwiGLU和GQA,大约是7B参数——这正是LLaMA 7B的设计。
掌握参数量计算,你就掌握了理解大模型的钥匙:
- 快速估算:$P \approx 12Ld^2$用于粗略评估
- 精确计算:逐组件计算用于架构设计
- 优化方向:知道参数在哪,才能优化在哪
当你下次看到"70B参数"时,你不再只会惊叹数字之大,而是能理解这70亿参数是如何分布的,需要多少显存,能进行多快的计算。这就是从"使用者"到"理解者"的跨越。
graph TB
subgraph 参数计算能力进阶
L1["Level 1: 知道模型有参数"]
L2["Level 2: 理解参数来源"]
L3["Level 3: 能徒手计算"]
L4["Level 4: 能优化设计"]
end
L1 --> L2 --> L3 --> L4
subgraph 应用场景
A1["评估硬件需求"]
A2["模型架构设计"]
A3["训练成本预估"]
A4["推理优化"]
end
L3 --> A1
L3 --> A2
L3 --> A3
L4 --> A4
style L4 fill:#9f9
style A4 fill:#bbf
参考文献
- Vaswani et al. (2017). “Attention Is All You Need”. NeurIPS.
- Brown et al. (2020). “Language Models are Few-Shot Learners”. NeurIPS.
- Touvron et al. (2023). “LLaMA: Open and Efficient Foundation Language Models”. arXiv.
- Press et al. (2023). “Train Short, Test Long: Attention with Linear Biases”. ICLR.
- Ainslie et al. (2023). “GQA: Training Generalized Multi-Query Transformer Models”. arXiv.
- Shazeer (2020). “GLU Variants Improve Transformer”. arXiv.
- Hu et al. (2021). “LoRA: Low-Rank Adaptation of Large Language Models”. ICLR.
- Kaplan et al. (2020). “Scaling Laws for Neural Language Models”. arXiv.
- Hoffmann et al. (2022). “Training Compute-Optimal Large Language Models”. arXiv.
- kipply. “Transformer Inference Arithmetic”. kipp.ly