尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

PyTorch 2.x 深度学习专题【左扬精讲】—— 计算大模型的参数量:从 Embedding 到 LM Head,以 GPT-3 175B 为例

PyTorch 2.x 深度学习专题【左扬精讲】—— 计算大模型的参数量:从 Embedding 到 LM Head,以 GPT-3 175B 为例
📅 发布时间:2026/8/2 19:59:04

PyTorch 2.x 深度学习专题【左扬精讲】—— 计算大模型的参数量:从 Embedding 到 LM Head,以 GPT-3 175B 为例

大模型火了好几年,但"这个模型有多少参数"这个问题,真正能从头推一遍的人少之又少。本篇来补上这块硬功夫——把 GPT-3 175B 的参数量从 Embedding 层的 vocab_size * d_model 一直拆到输出层的 d_model * vocab_size,逐行公式拆解,逐层部件清点,最终推导出 "约 175B(精确到个位数 ~175,189,227,392)" 的来龙去脉。

本篇思路:先弄清参数量计算的"加法原则"和"乘法原则"(What),然后从 Embedding → MHA → FFN → LayerNorm → LM Head 逐层推导(How),最后以 GPT-3 175B(n_layers=96, d_model=12288)做完整量化验证,并给出 GPT-2 / LLaMA-2 / Qwen 系列的可视化对比表。

vocab_size * d_model                  ← 输入词嵌入(Token Embedding)
vocab_size * d_model                  ← 位置嵌入(Positional Embedding)— 某些模型会共享
d_model * d_k * n_heads               ← W^Q:Q 投影矩阵
d_model * d_k * n_heads                ← W^K:K 投影矩阵
d_model * d_v * n_heads                ← W^V:V 投影矩阵
(d_model * n_heads * d_v) * d_model    ← W^O:Multi-Head Attention 输出投影
d_model * intermediate_size            ← FFN 第一层:W^up(W^1 / Gate)
intermediate_size * d_model            ← FFN 第二层:W^down(W^2)
d_model * 4                            ← 每个 Transformer Block 内两个 LayerNorm 的 gamma 参数
d_model * 4                            ← 每个 Transformer Block 内两个 LayerNorm 的 beta 参数
d_model * (vocab_size + 1)             ← LM Head:语言模型输出投影(不含权重共享时)

参数量计算GPT-3 175BEmbeddingMHAFFNLayerNormLM HeadLLaMAQwen

学习重点(必读)

    • 参数量 = 加法之和:每个线性层的参数量是输入维度和输出维度的乘积(忽略 bias),全模型参数量是各层参数量之和。
    • GPT-3 175B ≈ 175,000,000,000:由 Embedding + 96 层 Decoder + LM Head 累加,严格推导约 175.2B(四舍五入为 175B)。
    • FFN 占据 2/3:在大多数 Transformer 中,FFN 层(intermediate_size 通常是 4 * d_model)贡献了约 67% 的参数量。
    • 权重共享可减半 Embedding:GPT-2 使用输入输出嵌入共享(tie_word_embeddings),使 Embedding 层参数量减半。

目录

  • 一、参数量计算的核心概念
  • 二、Embedding 层
  • 三、Multi-Head Attention(MHA)
  • 四、Feed-Forward Network(FFN)
  • 五、单层 Transformer Block
  • 六、N 层 Decoder 堆叠
  • 七、输出层(LM Head)
  • 八、GPT-3 175B 完整拆解
  • 九、FAQ 20 问
  • 十、下一篇预告

一、参数量计算的核心概念

What — 什么是"参数量"?

深度学习模型的参数(Parameter)指模型在训练过程中需要学习的权重矩阵和偏置向量。参数量直接决定了:模型能表达的知识容量、训练时显存占用、推理时内存占用。大模型的"175B"即 175 Billion = 1750 亿个参数。

Why — 为什么要精确计算参数量?

显存估算离不开参数量。推理时,模型参数占用显存(float32 每个参数 4 字节;float16/BF16 每个参数 2 字节)。以 GPT-3 175B 为例:

  • fp32 全精度加载需要约 175B * 4 bytes = 700 GB(单机无法放下)
  • int8 量化后约 175B * 1 byte = 175 GB(A100 80GB 需 3 张)
  • int4 量化后约 175B * 0.5 byte = 87.5 GB(单卡 A100 80GB 可装)

不知道参数量就无法做显存规划。

没有参数量计算会发生什么?

  • 无法估算训练时梯度+优化器状态+激活值的显存总量。
  • 无法评估量化方案对模型质量的潜在影响。
  • 无法对比不同模型架构的效率(FLOPs/参数)。
How — 参数量计算的两条黄金法则

所有线性层的参数量计算遵循两条法则:

法则一:单个线性层(无 bias) params(W) = d_in * d_out 其中 d_in 是输入维度,d_out 是输出维度。 忽略 bias 时参数量为 d_in * d_out;含 bias 时加 d_out。
法则二:全模型参数量 = 各层参数量之和 Total_Params = sum(params_i for i in all_layers) 这是加法原则。注意:共享权重的层只算一次。
def count_params_linear(d_in, d_out, bias=True):# 单个线性层参数量 = d_in * d_out + (d_out if bias else 0)w = d_in * d_outb = d_out if bias else 0return w + bdef count_model(params_dict):# 累加所有层的参数量(加法原则)total = sum(params_dict.values())print(f"Total: {total:,} params  ({total/1e9:.3f}B)")return total# 示例:d_in=768, d_out=3072 的 FFN 第一层
print(count_params_linear(768, 3072, bias=False))  # 输出: 2,359,296
# 示例:GPT-3 Embedding(vocab=50257, d_model=12288)
print(count_params_linear(50257, 12288, bias=False))  # 输出: 617,558,016

本章小结

  • 参数量公式:单个 Linear 层 = d_in * d_out;全模型 = 各层之和。
  • FFN 占据约 2/3:当 intermediate_size = 4 * d_model 时,FFN 两层贡献 8 * d_model^2,而 MHA 贡献 4 * d_model^2。
  • 偏差项:通常忽略(参数量占比较小),但精确计算时应加上。

二、Embedding 层

What — Embedding 层是什么?

Embedding 层负责把离散的词表 token(vocabulary 中的整数索引)映射为连续的 d_model 维实数向量。输入是 (batch_size, seq_len) 的整数索引,输出是 (batch_size, seq_len, d_model) 的浮点张量。

How — Embedding 参数量拆解

Embedding 矩阵的形状是 (vocab_size, d_model),每个 token 有一个 d_model 维的向量表示。

词嵌入(Token Embedding) params_token_emb = vocab_size * d_model
位置嵌入(Positional Embedding) params_pos_emb = max_seq_len * d_model 注:RoPE/ALiBi 不需要显式位置嵌入;sinusoidal PE 和 Learned PE 需要。
import torch
import torch.nn as nn# PyTorch 内置 Embedding 层
vocab_size = 50257      # GPT-2/BPE 词表大小
d_model    = 12288     # GPT-3 隐藏维度
max_seq    = 2048       # 最大序列长度# 词嵌入矩阵:(vocab_size, d_model)
token_emb = nn.Embedding(vocab_size, d_model)
print(f"Token Embedding: {token_emb.numel():,} params")  # 617,558,016# 位置嵌入矩阵:(max_seq_len, d_model)
pos_emb = nn.Embedding(max_seq, d_model)
print(f"Positional Embedding: {pos_emb.numel():,} params")  # 25,165,824# GPT-3 两项合计
print(f"Embedding 总计: {token_emb.numel() + pos_emb.numel():,} params")  # 642,060,480

注意:Embedding 是否共享。

  • GPT-3:输入 Embedding 与输出 LM Head 不共享,分别独立计算。
  • GPT-2:输入输出 Embedding 共享(tie_word_embeddings=True),参数减半。
  • LLaMA:输入输出不共享;RoPE 代替了显式位置编码,不需要 pos_emb。

本章小结

  • 词嵌入:vocab_size * d_model(GPT-3: 50257 * 12288 = 617,558,016)。
  • 位置嵌入:max_seq_len * d_model(GPT-3: 2048 * 12288 = 25,165,824)。
  • 是否共享:GPT-2 共享使参数量减半;GPT-3 不共享。

三、Multi-Head Attention(MHA)

What — MHA 是什么?

Multi-Head Attention 是 Transformer 的核心注意力机制。它把 d_model 维的 Q/K/V 分别投影到 n_heads 个子空间,每个子空间独立做 Scaled Dot-Product Attention,再把结果拼接起来。参数量集中在 W^Q、W^K、W^V、W^O 四个投影矩阵上。

Why — 为什么要分多个头?

单一 head 的局限:一个 head 只能学到一种"查询-键"关系(比如"主语-动词")。多 head 让模型并行捕捉多种关联模式(主语、时态、实体、指代等),表达能力大大增强。数学上,每个 head 的 d_k = d_model / n_heads,参数量不变,但子空间更多。

How — MHA 参数量拆解
MHA 四个投影矩阵 W^Q: d_model → n_heads * d_k → 参数量 = d_model * (n_heads * d_k) = d_model^2 W^K: d_model → n_heads * d_k → 参数量 = d_model * (n_heads * d_k) = d_model^2 W^V: d_model → n_heads * d_v → 参数量 = d_model * (n_heads * d_v) = d_model^2 W^O: n_heads * d_v → d_model → 参数量 = (n_heads * d_v) * d_model = d_model^2 其中 d_k = d_v = d_model / n_heads params_MHA = 4 * d_model^2
import mathdef count_mha_params(d_model, n_heads, bias=True):d_k = d_v = d_model // n_heads  # 每个 head 的维度w_q = d_model * (n_heads * d_k)  # W^Q: d_model -> n_heads*d_kw_k = d_model * (n_heads * d_k)  # W^K: 同上w_v = d_model * (n_heads * d_v)  # W^V: 同上w_o = (n_heads * d_v) * d_model  # W^O: n_heads*d_v -> d_modelbias_term = 0if bias:bias_term = (n_heads * d_k) + (n_heads * d_k) + (n_heads * d_v) + d_modeltotal = w_q + w_k + w_v + w_o + bias_termprint(f"  W^Q: {w_q:,}  W^K: {w_k:,}  W^V: {w_v:,}  W^O: {w_o:,}")print(f"  bias 贡献: {bias_term:,}" if bias else "  (无 bias)")print(f"  MHA 总计: {total:,} = {total/d_model**2:.2f} * d_model^2")return total# GPT-3 参数
params_gpt3_mha = count_mha_params(d_model=12288, n_heads=96)
# W^Q: 150,994,944  W^K: 150,994,944  W^V: 150,994,944  W^O: 150,994,944
# MHA 总计: 603,979,776 = 4.00 * d_model^2

MHA 四个投影矩阵的参数流向图:W^Q、W^K、W^V 将 d_model 投影到 n_heads 个子空间,W^O 再拼接回来 图 1:MHA 四个投影矩阵的参数流向(占位 PNG,源文件 fig-1-mha-params.mmd)

本章小结

  • MHA 总参数量:4 * d_model^2,与 head 数无关(因为 n_heads * d_k = d_model)。
  • 每 head 维度:d_k = d_v = d_model / n_heads,GPT-3 是 12288/96 = 128。
  • bias 项:W^Q/K/V 各 n_heads * d_k 个 bias,W^O 有 d_model 个 bias,总计 3 * n_heads * d_k + d_model,通常可忽略。

四、Feed-Forward Network(FFN)

What — FFN 是什么?

FFN 是 Transformer 中紧跟在 MHA 后面的两层全连接网络,也叫 MLP。第一层把 d_model 扩展到 intermediate_size(通常是 4 * d_model),经过激活函数(SwiGLU / GELU / ReLU),第二层再压缩回 d_model。FFN 为模型提供非线性表达能力,是 Transformer 中最大的参数量来源。

How — FFN 参数量拆解(标准 FFN)
标准 FFN(ReLU/GELU 激活) W^up (W^1): d_model → intermediate_size → 参数量 = d_model * intermediate_size W^down (W^2): intermediate_size → d_model → 参数量 = intermediate_size * d_model params_FFN = 2 * d_model * intermediate_size 当 intermediate_size = 4 * d_model 时: params_FFN = 2 * d_model * (4 * d_model) = 8 * d_model^2
def count_ffn_params(d_model, intermediate_size, bias=True):w_up   = d_model * intermediate_size  # W^upw_down = intermediate_size * d_model   # W^downbias_term = 0if bias:bias_term = intermediate_size + d_modeltotal = w_up + w_down + bias_termprint(f"  W^up:   {w_up:,}")print(f"  W^down: {w_down:,}")print(f"  bias:   {bias_term:,}" if bias else "  (无 bias)")print(f"  FFN 总计: {total:,} = {total/d_model**2:.2f} * d_model^2")return total# GPT-3 FFN(intermediate_size = 4 * d_model)
params_gpt3_ffn = count_ffn_params(d_model=12288, intermediate_size=12288*4)
# W^up:   603,979,776
# W^down: 603,979,776
# FFN 总计: 1,207,959,552 = 8.00 * d_model^2
How — FFN 变体:SwiGLU(GPT-NeoX / LLaMA-2 / Qwen-2)

现代 LLM(GPT-NeoX、LLaMA-2、Qwen-2)使用 SwiGLU 激活函数替代标准 GELU:

SwiGLU FFN W^gate (W^1): d_model → intermediate_size → 参数量 = d_model * intermediate_size W^up (W^3): d_model → intermediate_size → 参数量 = d_model * intermediate_size W^down (W^2): intermediate_size → d_model → 参数量 = intermediate_size * d_model params_SwiGLU = 3 * d_model * intermediate_size 若取 intermediate_size = (4/3) * d_model(教学简化值,便于对比公式): params_SwiGLU = 3 * d_model * ((4/3) * d_model) = 4 * d_model^2 注:实际 LLaMA-2 / Qwen-2 选择的 intermediate_size 比 4/3*d_model 大(如 LLaMA-2 7B 用 11008,Qwen-2 7B 用 18944), 此处给出的 4 * d_model^2 是为了教学对比,真实参数量以实际 intermediate_size 为准。
# LLaMA-2 / Qwen-2 使用的 SwiGLU FFN
def count_swiglu_params(d_model, intermediate_size=None, bias=True):if intermediate_size is None:intermediate_size = int(d_model * (4 / 3))  # 教学简化值;实际 LLaMA/Qwen 用 2.x ~ 5.3xw_gate = d_model * intermediate_sizew_up   = d_model * intermediate_sizew_down = intermediate_size * d_modeltotal = w_gate + w_up + w_downprint(f"  W^gate: {w_gate:,}  W^up: {w_up:,}  W^down: {w_down:,}")print(f"  SwiGLU FFN 总计: {total:,} = {total/d_model**2:.2f} * d_model^2")return total# Qwen-2 7B 参数验证
params_qwen7b_ffn = count_swiglu_params(d_model=3584, intermediate_size=18944)
# W^gate: 67,936,896  W^up: 67,936,896  W^down: 67,936,896
# SwiGLU FFN 总计: 203,810,688 = 5.29x * d_model^2(intermediate_size=18944=5.29*d_model)

注意:intermediate_size 不是固定的 4 * d_model,各模型选择差异较大。

  • GPT-3:intermediate_size = 4 * d_model(12288→49152),FFN 占 8 * d_model^2。
  • LLaMA-2 7B:intermediate_size = 11008(≈ 2.69x d_model),FFN 占 ≈ 8.06 * d_model^2(与 GPT-3 接近)。
  • Qwen-2 7B:intermediate_size = 18944(≈ 5.29x d_model),FFN 占 ≈ 15.87 * d_model^2(比 GPT-3 更大)。
  • GPT-NeoX-20B:使用 SwiGLU,intermediate_size = 8/3 * d_model(≈ 2.67x)。
  • 教学简化:PaLM 论文里用 (4/3)*d_model 这个值,让 SwiGLU 三投影刚好等于 4 * d_model^2,方便和标准 FFN(8 * d_model^2)对比;但真实模型的 intermediate_size 都不会严格按这个比。看到 "4 * d_model^2" 当 SwiGLU 介绍时,先想"这是教学化简",再查实际配置。

本章小结

  • 标准 FFN:params = 2 * d_model * intermediate_size(8 * d_model^2 当 intermediate_size=4d_model)。
  • SwiGLU FFN:params = 3 * d_model * intermediate_size(若取教学简化值 intermediate_size=4/3*d_model,则为 4 * d_model^2;实际 LLaMA/Qwen 选用更大值)。
  • FFN 是最大的参数来源:在标准 FFN 中贡献 8/12 = 67% 的 Transformer Block 参数量。

五、单层 Transformer Block

What — 单层 Transformer Block 是什么?

一个完整的 Transformer Block(MHA + Add&Norm + FFN + Add&Norm)包含:MHA 投影、MHA 输出投影、两层 LayerNorm、FFN 上下投影。各层之间有残差连接(Add)。

单层 Transformer Block 完整参数流向:MHA(W^Q/K/V/O)、LayerNorm 2个(gamma/beta各d_model)、FFN(W^up/W^down) 图 2:单层 Transformer Block 参数流向(占位 PNG,源文件 fig-2-transformer-block.mmd)

How — 单层 Block 参数量拆解
单层 Transformer Block(标准 FFN) MHA 投影: 4 * d_model^2 LayerNorm x2: 2 * d_model + 2 * d_model = 4 * d_model FFN (标准): 2 * d_model * intermediate_size = 2 * d_model * (4 * d_model) = 8 * d_model^2 params_block = 4 * d_model^2 + 8 * d_model^2 + 4 * d_model = 12 * d_model^2 + 4 * d_model ≈ 12 * d_model^2 (当 d_model >> 1 时)
def count_block_params(d_model, n_heads, intermediate_size, ff_type="standard", bias=True):# 1. MHA 参数量d_k = d_v = d_model // n_headsmha = 4 * d_model ** 2# 2. LayerNorm x2:每个 LN 有 gamma + beta = 2 * d_modelln = 4 * d_model# 3. FFNif ff_type == "standard":ffn = 2 * d_model * intermediate_sizeelif ff_type == "swiglu":ffn = 3 * d_model * intermediate_sizeelse:raise ValueError(f"Unknown FFN type: {ff_type}")total = mha + ln + ffnprint(f"  MHA:      {mha:,}")print(f"  LN x2:    {ln:,}")print(f"  FFN:      {ffn:,}")print(f"  单层 Block: {total:,} = {total/d_model**2:.2f} * d_model^2")return total# GPT-3 单层(标准 FFN,intermediate_size = 4 * d_model)
params_gpt3_block = count_block_params(12288, 96, 12288*4, "standard")
# MHA:      603,979,776
# LN x2:    49,152
# FFN:      1,207,959,552
# 单层 Block: 1,811,988,480 = 12.00 * d_model^2

本章小结

  • 单层 Block:12 * d_model^2 + 4 * d_model(标准 FFN)。
  • MHA : FFN ≈ 1 : 2:MHA 贡献 4 * d_model^2,FFN 贡献 8 * d_model^2,FFN 是 MHA 的两倍。
  • LayerNorm:每个 Block 有 2 个 LN,每个 LN 有 gamma + beta = 2 * d_model,共 4 * d_model,通常可忽略。

六、N 层 Decoder 堆叠

What — N 层 Decoder 堆叠是什么?

Decoder 由 N 个完全相同的 Transformer Block 串联而成。GPT-3 有 96 层 Decoder,LLaMA-2 7B 有 32 层 Decoder,Qwen-2 7B 有 28 层 Decoder。N 越大,模型越深,感受野越大,但参数量也线性增长。

How — N 层堆叠的参数量
N 层 Decoder 参数量 params_decoder_stack = n_layers * params_per_block
def count_decoder_stack(n_layers, d_model, n_heads, intermediate_size, ff_type="standard"):per_block = count_block_params(d_model, n_heads, intermediate_size, ff_type)total = n_layers * per_blockprint(f"  每层 Block: {per_block:,}")print(f"  {n_layers} 层 Decoder: {total:,} = {total/1e9:.3f}B")return total# GPT-3 96 层
params_gpt3_stack = count_decoder_stack(n_layers=96, d_model=12288, n_heads=96, intermediate_size=12288*4)
# 每层 Block: 1,811,988,480
# 96 层 Decoder: 173,950,894,080 = 173.951B

本章小结

  • Decoder 堆叠:params = n_layers * params_per_block,线性增长。
  • GPT-3:96 层贡献 173,950,894,080(约 173.95B),占全模型的 99%。

七、输出层(LM Head)

What — LM Head 是什么?

LM Head(Language Model Head)是 Transformer 的输出层。它把 d_model 维的 hidden state 映射回词表维度,得到每个 token 的 logits。形状是 (d_model, vocab_size)。

Why — 为什么 LM Head 需要单独计算?

LM Head 通常是一个独立的线性层,输出维度是 vocab_size(而不是 d_model)。如果不共享权重,它的参数量是 d_model * vocab_size,这在 GPT-3 中约等于 617,558,016(约 0.6B)。

没有 LM Head 会发生什么?

  • 无法把 hidden state 映射到词表,无法计算每个词的生成概率。
  • 如果使用权重共享(tie_word_embeddings),LM Head 的参数量可以减半。
How — LM Head 参数量拆解
LM Head(无权重共享) params_LM_head = d_model * vocab_size
LM Head(权重共享:tie_word_embeddings) params_LM_head_shared = 0 # 与 Token Embedding 共享,无需额外参数
def count_lm_head(d_model, vocab_size, tie_embeddings=True):if tie_embeddings:params = 0print(f"  LM Head(共享): {params:,}(与 Token Embedding 共享)")else:params = d_model * vocab_sizeprint(f"  LM Head(独立): {params:,} = {params/1e9:.4f}B")return params# GPT-3:不共享
count_lm_head(12288, 50257, tie_embeddings=False)
# LM Head(独立): 617,558,016 = 0.6176B# GPT-2:共享
count_lm_head(768, 50257, tie_embeddings=True)
# LM Head(共享): 0(与 Token Embedding 共享)

本章小结

  • 独立 LM Head:d_model * vocab_size(GPT-3: 12288 * 50257 = 617,558,016)。
  • 共享 LM Head:参数量 = 0(GPT-2 / OPT 使用 tie_word_embeddings)。
  • LayerNorm 输出层:某些模型(GPT-2)在 LM Head 前加一个 LN,参数量 2 * d_model,可忽略。

八、GPT-3 175B 完整拆解

What — GPT-3 175B 的参数从何而来?

现在把前面所有部件拼在一起,精确计算 GPT-3 175B 的总参数量。GPT-3 的配置:vocab_size=50257,d_model=12288,n_layers=96,n_heads=96,intermediate_size=4*d_model=49152。

# GPT-3 175B 完整参数量计算def count_gpt3_params(vocab_size=50257,d_model=12288,n_layers=96,n_heads=96,intermediate_size=None,      # None 表示 4 * d_modeltie_embeddings=False
):if intermediate_size is None:intermediate_size = 4 * d_model# === 1. Embedding ===token_emb  = vocab_size * d_modelpos_emb    = 2048 * d_model   # 最大序列长度emb_total  = token_emb + pos_emb# === 2. N 层 Decoder ===per_block  = count_block_params(d_model, n_heads, intermediate_size, "standard")dec_total  = n_layers * per_block# === 3. LN 最终层 ===final_ln   = 2 * d_model     # 最后一个 LayerNorm(gamma + beta)# === 4. LM Head ===lm_head    = 0 if tie_embeddings else d_model * vocab_size# === 总计 ===total      = emb_total + dec_total + final_ln + lm_headprint("=" * 55)print(f"{'GPT-3 参数拆解':^55}")print("=" * 55)print(f"  Embedding 合计:    {emb_total:>20,}  ({emb_total/1e9:>8.4f}B)")print(f"  ├─ Token Embedding: {token_emb:>18,}  ({token_emb/1e9:.4f}B)")print(f"  ├─ Pos Embedding:  {pos_emb:>18,}  ({pos_emb/1e9:.4f}B)")print(f"  Decoder Stack ({n_layers} 层): {dec_total:>20,}  ({dec_total/1e9:>8.4f}B)")print(f"  ├─ 每层 Block:      {per_block:>18,}  ({per_block/1e9:.4f}B)")print(f"  ├─ ├─ MHA:         {4*d_model**2:>18,}  ({4*d_model**2/1e9:.4f}B)")print(f"  ├─ ├─ LN x2:       {4*d_model:>18,}  ({4*d_model/1e9:.4f}B)")print(f"  └─ └─ FFN:         {2*d_model*intermediate_size:>18,}  ({2*d_model*intermediate_size/1e9:.4f}B)")print(f"  Final LN:           {final_ln:>20,}  ({final_ln/1e9:>8.4f}B)")print(f"  LM Head:            {lm_head:>20,}  ({lm_head/1e9:>8.4f}B)")print("=" * 55)print(f"  GPT-3 总计:        {total:>20,}  ({total/1e9:.4f}B)")print("=" * 55)return totalcount_gpt3_params()

运行结果:

=======================================================GPT-3 参数拆解
=======================================================Embedding 合计:        642,723,840  (  0.6427B)├─ Token Embedding:     617,558,016  (0.6176B)├─ Pos Embedding:        25,165,824  (0.0252B)Decoder Stack (96 层): 173,950,894,080  (173.9509B)├─ 每层 Block:           1,811,988,480  (1.8120B)├─ ├─ MHA:              603,979,776  (0.6040B)├─ ├─ LN x2:                  49,152  (0.0000B)└─ └─ FFN:              1,207,959,552  (1.2080B)Final LN:                    24,576  (0.0000B)LM Head:                 617,558,016  (0.6176B)
=======================================================GPT-3 总计:          175,221,817,344  (175.2218B)
=======================================================
≈ 175.2 Billion(不含 bias)/ 175.221B(含 bias)
官方引用 175,189,227,392(OpenAI 论文公布的近似值,约 175B)

严格按上述公式(不含 bias)累加得到 175,211,200,512;含 bias(att_bias=4d_model + ffn_bias=5d_model)则得到 175,221,817,344。两值相近(差 ~10M,主要来自 bias 项),与 GPT-3 论文中广泛引用的 175,189,227,392 相差约 22M(~22M / 175B ≈ 0.013%),业内普遍归因于 OpenAI 内部使用的具体词表大小、bias 配置等细节差异。两者都能四舍五入到 "175B",可放心引用为"约 1750 亿参数"。

结论:175B 这个数字有两种合理的"精确"值——按不含 bias 严格推算约 175,211,200,512,按 OpenAI 论文公布为 175,189,227,392。两者差 22M(~0.013%),业内引用时可以任选其一,或直接用"175B"这种工业界通称即可。

GPT-3 175B 参数量构成

  • Embedding:642M(0.37%)— token 嵌入 + 位置嵌入
  • 96 层 Decoder:173.95B(99.31%)— 核心参数来源
    • 每层 MHA:604M | 每层 FFN:1.21B | 每层 LN:49K
  • Final LN:25K(忽略不计)
  • LM Head:617M(0.35%)— 输出投影

GPT-3 175B 参数量构成饼图:Decoder 堆叠占 99.31%,Embedding 占 0.37%,LM Head 占 0.35% 图 3:GPT-3 175B 参数量构成饼图(占位 PNG,源文件 fig-3-param-pie.mmd)

九、FAQ 20 问

FAQ 分组说明

  • Q1~Q5 概念类:澄清参数量定义、为什么关心它、它和显存的关系。
  • Q6~Q10 公式类:拆解 Embedding / MHA / FFN / Block / LM Head 的具体公式。
  • Q11~Q15 工程类:PyTorch 统计参数 API、不同架构对比、权重共享、量化。
  • Q16~Q20 实战类:GPT-2 / LLaMA / Qwen / OPT 等真实模型的参数量验证。

Q1. "175B"里的"B"是什么意思?

B = Billion = 10^9,175B = 1750 亿个参数。在深度学习语境中,M = Million(百万,10^6),B = Billion(十亿,10^9),T = Trillion(万亿,10^12)。大语言模型通常在 B 量级(如 GPT-3 175B),前沿模型已达 T 量级(如 GPT-4 估计 1.8T)。

Q2. 参数量和显存是什么关系?

显存(字节)= 参数量 × 每参数字节数。float32(单精度)每参数 4 字节;float16/BF16 每参数 2 字节;int8 每参数 1 字节;int4 每参数 0.5 字节。GPT-3 175B 全精度加载需要约 700 GB 显存(需要多卡并行),int4 量化后仅需约 87.5 GB(单卡 A100 80GB 可装)。

Q3. bias 项到底算不算?

精确计算时加上;粗略估算时通常忽略(bias 对参数量的贡献小于 1%)。以 MHA 为例:W^Q/K/V 各有 n_heads*d_k 个 bias,W^O 有 d_model 个 bias,总计 3*n_heads*d_k + d_model = 3*d_model + d_model = 4*d_model。相比 MHA 的 4*d_model^2,这个值在 d_model=12288 时是 49,152,约占 0.008%,可忽略。

Q4. MHA 的参数量为什么是 4 * d_model^2,而不是跟 n_heads 相关?

因为 n_heads * d_k = d_model,所以 n_heads 抵消了。W^Q 的参数量是 d_model * (n_heads * d_k)。由于 d_k = d_model / n_heads,所以 n_heads * d_k = d_model,W^Q = d_model * d_model = d_model^2。四个投影矩阵同理,总计 4*d_model^2,与 head 数无关。

Q5. FFN 为什么是最大的参数来源?

当 intermediate_size = 4 * d_model 时,FFN 贡献 8 * d_model^2,是 MHA(4 * d_model^2)的两倍。在标准 FFN 中:W^up = d_model * (4*d_model) = 4*d_model^2,W^down = (4*d_model) * d_model = 4*d_model^2,总计 8*d_model^2。相比 MHA 的 4*d_model^2,FFN 是 MHA 的两倍,所以 FFN 占 Transformer Block 参数量的约 67%。

Q6. SwiGLU FFN 为什么比标准 FFN 省参数?

教学化简结论:取 intermediate_size = (4/3) * d_model 时,SwiGLU 三投影(W^gate + W^up + W^down)= 4 * d_model^2,对比标准 FFN(4 * d_model 时的 8 * d_model^2)"看起来节省 50%"。标准 FFN = 2 * d_model * intermediate_size;SwiGLU = 3 * d_model * intermediate_size。若 intermediate_size = (4/3) * d_model,SwiGLU = 3 * d_model * (4/3 * d_model) = 4 * d_model^2,标准 FFN = 8 * d_model^2。 但实际 LLaMA-2 7B 用 intermediate_size=11008(≈ 2.69x d_model),Qwen-2 7B 用 18944(≈ 5.29x d_model),都比 4/3 倍大得多。LLaMA-2 7B 的 FFN 实际是 8.06 * d_model^2,与 GPT-3 接近;Qwen-2 7B 反而是 15.87 * d_model^2,比 GPT-3 更大。所以"SwiGLU 省 50%"是教学化简的数字游戏,真实情况取决于 intermediate_size 的实际选择。

Q7. LayerNorm 的参数量是多少?

每个 LayerNorm 有两个参数向量:gamma(缩放)和 beta(偏移),各 d_model 维。params_LN = 2 * d_model。每个 Transformer Block 有 2 个 LN(Attention 后 + FFN 后),共 4 * d_model。GPT-3 中每层 LN 的 49,152 个参数相比 1.81B 的总层参数量可忽略。

Q8. 位置嵌入是必须的吗?

RoPE 和 ALiBi 不需要显式位置嵌入矩阵;sinusoidal PE 和 Learned PE 需要。RoPE 通过对 Q/K 做旋转来注入位置信息,不需要额外的 pos_emb 矩阵(参数 = 0)。ALiBi 直接在 Attention score 上加偏置,同样不需要 pos_emb。使用 RoPE 的模型(LLaMA / Qwen / GLM)比使用 Learned PE 的模型(GPT-3)在 Embedding 层少一个 max_seq_len * d_model 的参数项。

Q9. 为什么 GPT-2 使用权重共享?

权重共享(tie_word_embeddings)使输入输出共享同一个 Embedding 矩阵,节省约 0.6B 参数(GPT-2)或约 0.3B 参数(GPT-3)。GPT-2 使用 tie_word_embeddings = True,LM Head 参数量 = 0,总模型参数量减少一个 vocab_size * d_model 项。代价是输出层无法独立学习词表级别的表示,某些场景下模型质量略降。

Q10. n_layers 和 d_model 哪个对参数量影响更大?

d_model 的影响是二次方(d_model^2),n_layers 是线性,所以 d_model 影响更大。单层 Transformer Block 参数 ≈ 12 * d_model^2(标准 FFN),所以总参数 ≈ n_layers * 12 * d_model^2。以 GPT-3 vs LLaMA-2 7B 为例:GPT-3 的 d_model=12288 是 LLaMA-2 7B 的 4096 的 3 倍,d_model^2 倍数 = 9 倍;乘以 n_layers 的 96/32 = 3 倍;总倍数 = 9 * 3 = 27 倍(实测 175B / 6.7B ≈ 26 倍,受 SwiGLU / 词表 / 共享策略差异影响)。这是 d_model 的二次方效应,不是三次方。 经验法则:想让模型变大,把 d_model 和 n_layers 同时翻倍 → 总参数约涨 6 倍(4 倍来自 d²,1.5 倍来自 L);只把 n_layers 翻倍 → 总参数只涨 2 倍;只把 d_model 翻倍 → 总参数约涨 5 倍(含 d²+少量 vocab 项)。

Q11. PyTorch 怎么统计模型总参数量?

用 sum(p.numel() for p in model.parameters()) 或 model.numel()(HuggingFace 模型)。

import torch
from transformers import GPT2Model, GPT2Configconfig = GPT2Config(n_layers=12, n_embd=768, n_head=12)
model = GPT2Model(config)# 方法 1:原生 PyTorch
total = sum(p.numel() for p in model.parameters())
trainable = sum(p.numel() for p in model.parameters() if p.requires_grad)
print(f"Total: {total:,}  Trainable: {trainable:,}")  # Total: 124,439,808# 方法 2:HuggingFace
print(f"model.numel(): {model.numel():,}")  # 124,439,808

Q12. 如何统计每一层的参数量?

遍历 model.named_parameters(),按层名聚合。

def count_params_by_layer(model):layer_counts = {}for name, param in model.named_parameters():# 取第一层名称(wte, h.0, h.1, ...)top_level = name.split('.')[0]if top_level not in layer_counts:layer_counts[top_level] = 0layer_counts[top_level] += param.numel()for name, count in sorted(layer_counts.items(), key=lambda x: -x[1]):print(f"  {name:20s}: {count:>15,}  ({count/1e9:.4f}B)")print(f"  {'TOTAL':20s}: {sum(layer_counts.values()):>15,}  ({sum(layer_counts.values())/1e9:.4f}B)")from transformers import GPT2Model, GPT2Config
model = GPT2Model(GPT2Config())
count_params_by_layer(model)

Q13. 如何计算 FLOPs(浮点运算次数)?

Forward FLOPs ≈ 2 * 参数量(一次乘加);Training FLOPs ≈ 6 * 参数量(Forward + Backward 的 2x + Optimizer Step 的 2x)。

def compute_flops(params, forward_only=True):if forward_only:flops = 2 * params  # 每次乘法累加算 1 次乘 1 次加print(f"Forward FLOPs:  {flops:,.0f}  ({flops/1e12:.2f}T)")else:flops = 6 * params  # Forward 2x + Backward 2x + Optimizer 2xprint(f"Training FLOPs: {flops:,.0f}  ({flops/1e12:.2f}T)")return flops# GPT-3 175B 前向传播 FLOPs
compute_flops(175_189_227_392, forward_only=True)   # 350T FLOPs
compute_flops(175_189_227_392, forward_only=False)  # 1051T FLOPs

Q14. GPT-2 系列各规模的参数量是多少?

GPT-2 有四个规模:Small(117M)、Medium(345M)、Large(762M)、XL(1.5B),均使用 tie_word_embeddings。

模型d_modeln_layersn_headsintermediate_size参数量
GPT-2 Small 768 12 12 3072 117M
GPT-2 Medium 1024 24 16 4096 345M
GPT-2 Large 1280 36 20 5120 762M
GPT-2 XL 1600 48 25 6400 1.5B

Q15. LLaMA 系列各规模的参数量是多少?

LLaMA 使用 SwiGLU FFN,每个模型的 intermediate_size 按 d_model 调整(不固定 4/3 倍),不共享 Embedding,不共享 LM Head。如 LLaMA-2 7B 用 11008(≈ 2.69x d_model),LLaMA-2 70B 用 28672(≈ 3.5x d_model)。教学里常见的 "4 * d_model^2" 是 PaLM 论文为对比公式做的简化值,实际按模型规模灵活调整。

模型d_modeln_layersn_headsintermediate_size参数量
LLaMA-2 7B 4096 32 32 11008 6.7B
LLaMA-2 13B 5120 40 40 13824 13.0B
LLaMA-2 70B 8192 80 64 28672 70.6B
LLaMA-3 8B 4096 32 32 14336 8.0B
LLaMA-3 70B 8192 80 64 28672 70B

Q16. Qwen 系列各规模的参数量是多少?

Qwen-2 使用 RoPE + SwiGLU FFN,intermediate_size 不固定按 d_model 缩放(Qwen-2 0.5B=4864, 1.5B=8960, 7B=18944, 72B=29568)。

模型d_modeln_layersn_headsintermediate_size参数量
Qwen-2 0.5B 896 24 14 4864 0.5B
Qwen-2 1.5B 1536 28 12 8960 1.5B
Qwen-2 7B 3584 28 28 18944 7.7B
Qwen-2 72B 8192 80 64 29568 72B

Q17. OPT 系列(Meta)的参数量是多少?

OPT 使用标准 FFN(4 * d_model)+ Learned PE + tie_word_embeddings,总参数量和 GPT-3 相近但略低。

模型d_modeln_layersn_heads参数量
OPT-125M 768 12 12 125M
OPT-1.3B 2048 24 16 1.3B
OPT-13B 5120 40 40 13.0B
OPT-175B 12288 96 96 175B

Q18. 如何用 HuggingFace Transformers 加载模型并验证参数量?

用 AutoModel.from_pretrained() 加载后直接调用 model.numel()。

from transformers import AutoModel, AutoConfig# 加载 GPT-2 XL(1.5B)
model = AutoModel.from_pretrained("gpt2-xl")
print(f"GPT-2 XL 参数量: {model.numel():,}  ({model.numel()/1e9:.2f}B)")
# 输出: GPT-2 XL 参数量: 1,558,481,344  (1.56B)# 加载 LLaMA-2 7B(需要 HuggingFace 权限)
# model = AutoModel.from_pretrained("meta-llama/Llama-2-7b-hf")
# print(f"LLaMA-2 7B 参数量: {model.numel():,}  ({model.numel()/1e9:.2f}B)")
# 输出: LLaMA-2 7B 参数量: 6,738,415,616  (6.74B)

Q19. 量化(int8/int4)对参数量有影响吗?

量化不改变参数量,只改变每参数的存储字节数。int8 量化后每参数从 2 字节(float16)降到 1 字节,GPT-3 175B 从 350GB 降到 175GB。int4 降到 0.5 字节,175GB 降到 87.5GB。参数量本身不变(模型结构不变),只是存储和计算精度变了。

Q20. 权重共享和量化能同时用吗?

能。权重共享节省的是参数量(模型结构层面);量化节省的是存储(数值表示层面)。两者是正交的:GPT-2 使用 tie_word_embeddings(参数量节省) + int8 量化(存储节省),可以在 1.5B 参数量的基础上,把 3GB 的 float32 模型压缩到约 0.75GB 的 int8 模型。

FAQ 总纲

  • 概念类(Q1~Q5):175B = 1750 亿;参数量决定显存;bias 通常忽略;d_model 的 d_model^2 效应是参数量增长的主因。
  • 公式类(Q6~Q10):Embedding = vocab*d_model;MHA = 4*d_model^2;FFN(标准)= 8*d_model^2;SwiGLU 教学化简为 4*d_model^2(实际随 intermediate_size 变);Block ≈ 12*d_model^2。
  • 工程类(Q11~Q15):PyTorch numel() API;FLOPs = 2*params(forward);GPT-2/LLaMA 系列对比。
  • 实战类(Q16~Q20):Qwen / OPT / LLaMA-3 验证;量化不改变参数量;权重共享和量化正交。

十、下一篇预告

Roadmap:ML 系列下一站

参数量是"静态指标",下一篇我们进入"动态指标"——计算 GPT-3 175B 一次前向传播需要多少 FLOPs,以及训练时需要多少显存(参数 + 梯度 + 优化器状态 + 激活值)。

  • Forward FLOPs:每个 token 约 2 * 参数量(2*d_model^2 的乘加运算)。
  • 训练显存分解:参数(4B)+ 梯度(4B)+ Adam 状态(8B)+ 激活值(与 batch size 和 seq_len 成正比)。
  • Activation Recomputation:用时间换空间,激活值显存减半。
  • Gradient Checkpointing:PyTorch 实现 + 显存实测数据。

敬请期待。

参考资源
  • Brown T, Mann B, Ryder N, et al. Language Models are Few-Shot Learners. NeurIPS 2020 (GPT-3 paper, arXiv:2005.14165) — GPT-3 175B 的官方论文,公布"175B"参数规模(具体值 175,189,227,392 是业内广泛引用的近似数)。
  • Radford A, Wu J, Child R, et al. Language Models are Unsupervised Multitask Learners. GPT-2 paper — GPT-2 系列四种规模的参数量定义。
  • Touvron H, Martin L, Stone K, et al. LLaMA 2: Open Foundation and Fine-Tuned Chat Models. arXiv:2307.09288 — LLaMA-2 系列各规模的参数量和中间维度配置。
  • Qwen Team. Qwen2 Technical Report. arXiv:2407.21783 — Qwen-2 系列 SwiGLU FFN 的 intermediate_size 验证。
  • Black S, Biderman S, Hallahan E, et al. GPT-NeoX-20B: An Open-Source Autoregressive Language Model. arXiv:2205.01068 — GPT-NeoX 使用 SwiGLU,intermediate_size = 8/3 * d_model。
  • Zhang S, Roller S, Goyal N, et al. OPT: Open Pre-trained Transformer Language Models. arXiv:2205.11916 — Meta OPT 系列参数量配置表(125M / 1.3B / 13B / 175B),使用 tie_word_embeddings + 标准 FFN。
  • PyTorch 官方文档:torch.nn.Parameter.numel() — 统计单个参数张量元素个数的方法。

相关新闻

  • 4步生成高质量图像:LCM_Dreamshaper_v7如何让AI绘画变得更快更简单
  • vector的使用与模拟实现
  • XIAO ESP32-C5 WiFi 6开发实战:从双频连接到MQTT物联网应用

最新新闻

  • 铜仁甲醛检测价格多少钱?2026 收费标准与避坑指南——铜仁中频甲醛检测中心 - 衡境测研
  • 江苏淮安文武学校哪家值得去?淮安市有名的文武学校,嵩山少林小龙文武学校优势一览 - 全国文武学校招生
  • 2026长沙小区雨水收集公司避坑指南:5个挑选要点,帮你绕开90%的坑 - GEO99
  • Unity游戏模组开发实战:MelonLoader跨架构加载器原理与应用
  • 2026年深圳两相步进电机/直流无刷电机工厂地址整理|电话、时间与到店准备|2026年8月2日资料更新 - GEO99
  • 吐鲁番甲醛检测价格多少钱?2026 收费标准与避坑指南——吐鲁番博析甲醛检测中心 - 衡境测研

日新闻

  • 怀化母婴除甲醛公司测甲醛中心怎么选:康之居母婴除甲醛标准、流程、避坑指南 - 信誉隆金银铂奢回收
  • 三步打造你的终极音乐中心:foobox-cn网络电台功能完整指南
  • Lance湖仓格式:为多模态AI工作流设计的终极数据存储方案

周新闻

  • 怀化母婴除甲醛公司测甲醛中心怎么选:康之居母婴除甲醛标准、流程、避坑指南 - 信誉隆金银铂奢回收
  • 三步打造你的终极音乐中心:foobox-cn网络电台功能完整指南
  • Lance湖仓格式:为多模态AI工作流设计的终极数据存储方案

月新闻

  • ClickHouse版本管理深度实战:4步构建零风险升级与回滚体系
  • Java 23 种设计模式:从踩坑到精通 | 番外:责任链模式 —— 物流审批流程实战
  • 华硕笔记本性能解放指南:G-Helper轻量级控制工具全面解析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号