如果你已经看完 如何根据 config.json 核对 MoE 模型的激活参数:以 gpt-oss-120b 为例,也建议你把这篇当成“方法论版”配套阅读:一个负责“把例子讲透”,一个负责“把方法抽象出来”。

关键词: MoE、config.json、active parameters、模型选型、Transformer、专家模型、参数量估算、推理部署

每次有新开源模型出来,很多开发者都会先看两样东西:

  • 模型卡写了多少参数
  • 社区里有人说它“像不像某某模型”

但如果你真的想快速建立工程判断,只看这两样远远不够。

尤其是 MoE 模型,最容易让人产生错觉:

  • 总参数很大,不代表每个 token 都会走完这些参数
  • active params 很小,不代表它的真实推理延迟就一定很低
  • 同样叫 MoE,不同模型的 expert 结构、路由方式、共享模块可能差异很大

所以,比“看别人总结”更有价值的能力,是自己打开 config.json,在几分钟内判断出这个模型的核心结构。

这篇文章要解决的问题很简单:

拿到任意一个 MoE 模型的 config.json,开发者应该如何快速看懂它?

我建议你不要一上来就盯着所有字段,而是按下面这 5 个问题去读:

  1. 它到底是不是标准 MoE?
  2. 它每层有多少 experts,每个 token 会激活几个?
  3. 单个 expert 有多大?
  4. 除了 experts,还有哪些 dense 模块一直在参与计算?
  5. 它的 total paramsactive params、真实部署成本分别意味着什么?

只要这 5 个问题能答出来,这个模型你基本就看懂一半了。

一、先建立正确心智:看 MoE,不要只盯“总参数”

很多人看模型时,只盯着一个数字:

671B236B120B

但对 MoE 模型来说,这个数字只能说明:

模型总共持有多少参数。

它并不能直接说明:

  • 每个 token 计算时会实际走多少参数
  • 它和 dense 模型相比,吞吐会是什么量级
  • 为什么一个超大参数模型还能跑在看起来“不那么离谱”的硬件上

MoE 的核心思想,本质上就是:

参数池很大,但每次只激活其中一小部分。

所以你以后看 MoE,要至少同时建立三个概念:

  • total params:模型总共持有多少参数
  • active params:单个 token 前向时会动用多少参数
  • real serving cost:真实服务成本,包括显存、通信、吞吐、时延

这三者有关,但不能互相替代。

二、第一步:先确认它是不是真正的 MoE

很多模型虽然在宣传里会提到专家、路由、混合结构,但你拿到 config.json 时,最好先确认它是不是典型的 Transformer MoE。

你优先找这些字段:

  • num_local_experts
  • num_experts_per_tok
  • experts_per_token
  • moe_intermediate_size
  • shared_expert_intermediate_size
  • n_routed_experts
  • n_shared_experts

不同模型家族的命名不一定一样,但含义通常比较接近。

典型判断逻辑

如果你在配置里看到下面这种组合:

{
  "num_local_experts": 128,
  "num_experts_per_tok": 4
}

通常就可以判断:

  • 这是一个按层路由的专家模型
  • 每层有 128 个 experts
  • 每个 token 在该层只会选中 4 个 experts

如果你再看到:

  • router_aux_loss_coef
  • output_router_logits

那基本可以进一步确认:

这是一个显式 top-k 路由的标准 MoE 架构。

不要只看有没有 “expert” 这个词

有些模型虽然也有类似“专家”概念,但结构上并不完全等同于你熟悉的标准 MoE。

比如可能存在:

  • routed experts + shared expert
  • 只在部分层启用专家
  • 稀疏专家和 dense FFN 并存
  • 不同 block 的 expert 数量不完全一致

所以你要避免一个常见误区:

看到 expert 就觉得“我已经懂了”。

真正有用的是继续问:

  • expert 出现在哪些层?
  • 每层都启用吗?
  • 每层 top-k 一样吗?
  • 有没有共享专家?

三、第二步:先抓住最关键的 8 个字段

如果你只想在最短时间内建立对一个 MoE 模型的整体认识,我建议你优先看下面 8 个字段。

1. num_hidden_layers

它决定模型有多少层。

这是最基础的总量因子,因为无论你算总参数还是 active params,最后都要乘上层数。

2. hidden_size

这是主干隐藏维度。

它会影响:

  • attention 投影规模
  • expert MLP 规模
  • embedding / lm_head 规模

可以说,这是绝大多数参数量公式里的核心变量。

3. intermediate_size

这是 FFN 或 expert MLP 的中间维度。

如果 expert 是标准三段 MLP 结构,那么它和 hidden_size 一起基本就决定了:

单个 expert 有多大。

4. num_local_experts

表示每层总共有多少个 experts。

这个数字越大,说明模型的“总专家池”越大,总参数通常也会更大。

5. num_experts_per_tok

表示每个 token 每层会命中的 expert 数量,也就是 top-k。

这是 active params 的关键字段。

一个最常见的直觉判断就是:

每层激活比例 = num_experts_per_tok / num_local_experts

6. num_attention_heads

决定 attention 的 query 头数。

7. num_key_value_heads

决定 KV 头数。

它非常关键,因为这能让你快速判断模型是:

  • 标准 MHA
  • GQA
  • MQA

如果 num_key_value_heads 明显小于 num_attention_heads,通常意味着采用了 GQA,这会明显影响 KV cache 规模和推理效率。

8. vocab_size

它会影响:

  • embedding 参数量
  • lm_head 参数量

很多人在核对 active params 时,容易忽略这两个大头。

四、第三步:先别急着算,先判断这是哪一类 MoE

不是所有 MoE 都应该用同一套公式硬套。

在实战里,你至少要先判断它属于下面哪一类。

第一类:标准路由型 MoE

特征通常是:

  • 每层固定数量 experts
  • 每个 token top-k 路由
  • expert 是标准 MLP
  • attention 仍然是 dense 的

这类模型最容易估算。

第二类:带 shared expert 的混合 MoE

特征通常是:

  • 除了 routed experts,还有 shared expert
  • shared expert 对所有 token 都参与
  • routed experts 只按 top-k 激活

这类模型在算 active params 时,要特别小心:

shared expert 不能按稀疏部分来算,它更像一个“始终开启的额外分支”。

第三类:部分层 MoE,部分层 dense

有些模型不是每一层都用 MoE。

这时你要特别注意:

  • 哪些层是 expert layers
  • 哪些层只是普通 dense FFN

如果只看 num_hidden_layers 直接乘,可能会高估或低估一大截。

第四类:实现上高度融合的 MoE

有些模型在 config.json 里字段看起来很标准,但实现里:

  • projection 被 fusion 了
  • bias 合并了
  • expert 结构并不是标准三段
  • 还有额外门控分支

这类模型就不适合只凭直觉公式估算,需要顺手看一下实现代码里的 tensor shape。

五、第四步:如何用 config.json 粗估单个 expert 的参数量

这一步是最核心的。

很多标准 MoE 模型里,单个 expert 本质上就是一个 gated MLP,大致可以理解成:

  • gate_proj
  • up_proj
  • down_proj

如果只做快速估算,可以用这个通用公式:

expert_params ≈ 3 * hidden_size * intermediate_size

这个公式为什么成立?

因为它本质上对应三块矩阵:

hidden_size * intermediate_size
+ hidden_size * intermediate_size
+ intermediate_size * hidden_size

如果你在意精确值,就再补上 bias。

一个快速心算法

如果你拿到一个模型,看到:

  • hidden_size = 4096
  • intermediate_size = 14336

那么单 expert 参数量可以先粗估为:

3 * 4096 * 14336
≈ 176M

这类心算能力非常有用,因为你很快就能得到:

  • 单个 expert 多大
  • 每层 active expert 大概多大
  • 总体 active params 会落在哪个量级

六、第五步:如何快速估算 active params

对标准路由型 MoE,最实用的一套粗估流程是下面这样。

1. 先算单个 expert

per_expert ≈ 3 * hidden_size * intermediate_size

2. 再算每层激活 expert

active_experts_per_layer
= num_experts_per_tok * per_expert

3. 再乘层数

active_expert_total
= num_hidden_layers * active_experts_per_layer

这时你得到的是:

全部稀疏专家部分,在每个 token 上被真正激活的参数规模。

但这通常还不是最终 active params。

因为你还没把这些 dense 模块加进去:

  • self-attention
  • router
  • norm
  • embedding
  • 有时还包括 shared expert

一个非常重要的提醒

很多人会犯一个错误:

“top-k 是 2,专家总数是 16,所以 active params 就是总参数的八分之一。”

这通常是错的,原因有两个:

  • attention 主干不是稀疏的
  • embedding / lm_head / router / norm 等部分并不会按同样比例缩小

也就是说:

MoE 里稀疏的是专家层,不是整个模型。

七、第六步:别忘了 dense 主干,它往往比你想的更重要

一个完整的 Transformer MoE block,通常不会只有 experts。

它还有很多一直参与计算的 dense 模块,例如:

  • q_proj
  • k_proj
  • v_proj
  • o_proj
  • router
  • input / post-attention norm

这些模块的参数量虽然可能比全部 experts 小很多,但它们会决定两个很重要的事情:

  1. 你的 active params 不会小到只剩“被选中的 experts”
  2. 你的实际推理延迟也不会只由 experts 决定

如果你想更严谨地估算一个模型,建议把 dense 主干单独当成一项:

active_params
≈ active_expert_total
+ dense_trunk
+ embedding
+ shared_expert(如果有)

至于 lm_head 是否算进去,则取决于你采用哪种统计口径。

八、第七步:学会识别 4 个最容易踩的坑

这一部分非常重要,因为很多人不是不会算,而是误用了口径。

坑 1:把 total params 当成 active params

这是最常见的错误。

MoE 的价值恰恰在于:

  • 总参数很大
  • 单步激活参数远小于总参数

如果你看到一个模型 200B total,不要立刻联想到“它每 token 就是 200B 计算规模”。

坑 2:只算 experts,不算 dense 主干

这会导致你明显低估 active params。

坑 3:忽略 shared expert

如果模型有 shared expert,而你把它也当成 routed expert 一样按 top-k 处理,结果通常会偏小。

坑 4:把 active params 等同于真实推理成本

这是工程上最危险的误解之一。

真实成本还取决于:

  • expert parallel 通信
  • tokens 分布是否均匀
  • batch size
  • seq length
  • KV cache
  • kernel 优化
  • 量化
  • 部署框架

所以 active params 更像是:

一个结构级指标,而不是完整的部署结论。

九、第八步:如何通过 attention 字段快速判断部署侧含义

有些开发者看 MoE 只盯 experts,其实 attention 的配置同样非常值得看。

重点字段包括:

  • num_attention_heads
  • num_key_value_heads
  • head_dim
  • sliding_window
  • max_position_embeddings
  • rope_theta
  • rope_scaling

这些字段至少能让你快速判断三件事。

1. 它是不是 GQA / MQA

如果:

num_key_value_heads << num_attention_heads

通常说明模型用了 GQA。

这通常意味着:

  • KV cache 会更省
  • 长上下文推理更友好
  • 实际部署成本可能低于你对“头数很多”的直觉判断

2. 它对长上下文做了什么

如果你看到:

  • rope_scaling
  • max_position_embeddings
  • sliding_window

就要意识到:

这个模型不仅是 MoE,还是一个特定长上下文策略下的 MoE。

很多时候,真实部署瓶颈不在 experts,而在长上下文 attention。

3. 它的 attention 是不是全量密集

有些模型会混用:

  • full attention
  • sliding attention
  • local attention

这对真实延迟和上下文扩展策略都会有很大影响。

十、第九步:如何快速判断 embedding 和 lm_head 要不要纳入口径

这是核对模型卡时经常产生争议的一点。

通常你可以这样理解:

embedding

只要模型在前向时会把 token id 映射成向量,embedding 就是参与计算的。

因此很多团队在统计 active params 时,会把 embedding 算进去。

lm_head

是否纳入 active params,口径差异会更明显。

有些团队会认为:

  • 只要最终 logits 是通过 lm_head 投影出来的,就应该算

另一些团队则更偏向:

  • active params 主要描述主干 + 稀疏专家部分,不把 lm_head 单独计入

所以最稳妥的做法永远是:

当你自己给出 active params 数字时,顺手说明是否包含 embedding 和 lm_head。

这比单独报一个数字更专业,也更不容易引起误解。

十一、第十步:什么时候只看 config.json 就够,什么时候必须去看实现

这是一个非常实战的问题。

只看 config.json 就够的情况

如果一个 MoE 模型满足这些条件:

  • 字段命名比较清晰
  • expert 结构比较标准
  • 没有 shared expert
  • 没有层间异构设计
  • 你的目标只是估算量级

那么只看 config.json 通常就够了。

最好去看实现代码的情况

如果你遇到这些情况,就建议直接看实现:

  • 有 shared expert
  • 有 routed expert 和 dense FFN 并存
  • 某些层是专家层,某些层不是
  • projection 进行了 fusion
  • 配置里没有直接告诉你 expert 的真实矩阵 shape
  • 你想把 active params 算到接近模型卡的精度

这时候你重点看:

  • expert 权重 tensor 的 shape
  • router 输出的 top-k 逻辑
  • 是否所有层都调用同一种 MLP
  • 是否有额外 bias、shared branch、残差 branch

十二、给开发者一套可复用的 5 分钟阅读流程

如果以后你想快速看懂任意一个 MoE 模型,我建议固定按下面流程走。

第 1 分钟:先看是不是标准 MoE

重点扫:

  • num_local_experts
  • num_experts_per_tok
  • router_aux_loss_coef
  • output_router_logits

第 2 分钟:看 expert 和层数规模

重点扫:

  • num_hidden_layers
  • hidden_size
  • intermediate_size

这一步先把单 expert 和总层数的量级建立起来。

第 3 分钟:看 attention 结构

重点扫:

  • num_attention_heads
  • num_key_value_heads
  • head_dim
  • sliding_window

这一步是为了判断部署侧真实成本,不只是参数量。

第 4 分钟:看 embedding / 输出头口径

重点扫:

  • vocab_size
  • tie_word_embeddings

这一步决定你后面核对 active params 时,是否容易和官方数字差几亿。

第 5 分钟:判断要不要去看代码

如果结构标准,就可以直接做快速估算。

如果结构复杂,就不要死算,直接去看实现 shape。

十三、给团队做模型选型时,我最建议记录的 8 个结论

很多团队看完模型后,没有沉淀成统一模板,导致下一次又要重新理解一遍。

我建议你每次看一个新 MoE 模型,至少固定记录这 8 项:

  1. 总层数是多少
  2. 每层总 expert 数是多少
  3. 每个 token top-k 是多少
  4. 单 expert 大小大概是多少
  5. 是否存在 shared expert
  6. 是否所有层都启用 MoE
  7. attention 是 MHA、GQA 还是 MQA
  8. active params 的统计口径是否包含 embedding / lm_head

你会发现,只要这 8 项写下来,模型结构已经非常透明了。

十四、一个通用估算模板:以后看任何标准 MoE 都能直接套

下面给你一个通用模板,适合快速估算标准 MoE。

def estimate_standard_moe(
    hidden_size,
    intermediate_size,
    num_hidden_layers,
    num_local_experts,
    num_experts_per_tok,
):
    per_expert = 3 * hidden_size * intermediate_size
    active_per_layer = num_experts_per_tok * per_expert
    total_active_experts = num_hidden_layers * active_per_layer
    total_all_experts = num_hidden_layers * num_local_experts * per_expert

    return {
        "per_expert": per_expert,
        "active_per_layer": active_per_layer,
        "total_active_experts": total_active_experts,
        "total_all_experts": total_all_experts,
        "activation_ratio_per_layer": num_experts_per_tok / num_local_experts,
    }

这个模板不能替代精确计算,但非常适合做第一轮判断。

你可以把它当成:

MoE 模型阅读时的计算器。

十五、最后总结:真正有用的不是记住某个模型,而是掌握阅读方法

很多人看模型文章时,容易陷入一个误区:

记住了一个具体模型的数字,就以为自己理解了 MoE。

但真正有价值的能力,其实是:

下次看到任何一个新模型,只凭 config.json,你也能快速建立正确判断。

所以这篇文章最想带走的,不是某个具体结论,而是一套稳定的阅读框架:

  1. 先确认是不是标准 MoE。
  2. 再看 experts 的总量和 top-k。
  3. 再估单 expert 的规模。
  4. 再把 dense 主干补回来。
  5. 最后明确统计口径,不要把 active params 和真实部署成本混为一谈。

只要你掌握了这套方法,以后再看任何新出的专家模型,基本都不会再被模型卡上的数字牵着走。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐