)
如果你已经看完 如何根据 config.json 核对 MoE 模型的激活参数以 gpt-oss-120b 为例也建议你把这篇当成“方法论版”配套阅读一个负责“把例子讲透”一个负责“把方法抽象出来”。关键词MoE、config.json、active parameters、模型选型、Transformer、专家模型、参数量估算、推理部署每次有新开源模型出来很多开发者都会先看两样东西模型卡写了多少参数社区里有人说它“像不像某某模型”但如果你真的想快速建立工程判断只看这两样远远不够。尤其是 MoE 模型最容易让人产生错觉总参数很大不代表每个 token 都会走完这些参数active params 很小不代表它的真实推理延迟就一定很低同样叫 MoE不同模型的 expert 结构、路由方式、共享模块可能差异很大所以比“看别人总结”更有价值的能力是自己打开config.json在几分钟内判断出这个模型的核心结构。这篇文章要解决的问题很简单拿到任意一个 MoE 模型的config.json开发者应该如何快速看懂它我建议你不要一上来就盯着所有字段而是按下面这 5 个问题去读它到底是不是标准 MoE它每层有多少 experts每个 token 会激活几个单个 expert 有多大除了 experts还有哪些 dense 模块一直在参与计算它的total params、active params、真实部署成本分别意味着什么只要这 5 个问题能答出来这个模型你基本就看懂一半了。一、先建立正确心智看 MoE不要只盯“总参数”很多人看模型时只盯着一个数字671B、236B、120B但对 MoE 模型来说这个数字只能说明模型总共持有多少参数。它并不能直接说明每个 token 计算时会实际走多少参数它和 dense 模型相比吞吐会是什么量级为什么一个超大参数模型还能跑在看起来“不那么离谱”的硬件上MoE 的核心思想本质上就是参数池很大但每次只激活其中一小部分。所以你以后看 MoE要至少同时建立三个概念total params模型总共持有多少参数active params单个 token 前向时会动用多少参数real serving cost真实服务成本包括显存、通信、吞吐、时延这三者有关但不能互相替代。二、第一步先确认它是不是真正的 MoE很多模型虽然在宣传里会提到专家、路由、混合结构但你拿到config.json时最好先确认它是不是典型的 Transformer MoE。你优先找这些字段num_local_expertsnum_experts_per_tokexperts_per_tokenmoe_intermediate_sizeshared_expert_intermediate_sizen_routed_expertsn_shared_experts不同模型家族的命名不一定一样但含义通常比较接近。典型判断逻辑如果你在配置里看到下面这种组合{num_local_experts:128,num_experts_per_tok:4}通常就可以判断这是一个按层路由的专家模型每层有 128 个 experts每个 token 在该层只会选中 4 个 experts如果你再看到router_aux_loss_coefoutput_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_experts6.num_attention_heads决定 attention 的 query 头数。7.num_key_value_heads决定 KV 头数。它非常关键因为这能让你快速判断模型是标准 MHAGQAMQA如果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 是标准 MLPattention 仍然是 dense 的这类模型最容易估算。第二类带 shared expert 的混合 MoE特征通常是除了 routed experts还有 shared expertshared 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_projup_projdown_proj如果只做快速估算可以用这个通用公式expert_params ≈ 3 * hidden_size * intermediate_size这个公式为什么成立因为它本质上对应三块矩阵hidden_size * intermediate_size hidden_size * intermediate_size intermediate_size * hidden_size如果你在意精确值就再补上 bias。一个快速心算法如果你拿到一个模型看到hidden_size 4096intermediate_size 14336那么单 expert 参数量可以先粗估为3 * 4096 * 14336 ≈ 176M这类心算能力非常有用因为你很快就能得到单个 expert 多大每层 active expert 大概多大总体 active params 会落在哪个量级六、第五步如何快速估算 active params对标准路由型 MoE最实用的一套粗估流程是下面这样。1. 先算单个 expertper_expert ≈ 3 * hidden_size * intermediate_size2. 再算每层激活 expertactive_experts_per_layer num_experts_per_tok * per_expert3. 再乘层数active_expert_total num_hidden_layers * active_experts_per_layer这时你得到的是全部稀疏专家部分在每个 token 上被真正激活的参数规模。但这通常还不是最终 active params。因为你还没把这些 dense 模块加进去self-attentionrouternormembedding有时还包括 shared expert一个非常重要的提醒很多人会犯一个错误“top-k 是 2专家总数是 16所以 active params 就是总参数的八分之一。”这通常是错的原因有两个attention 主干不是稀疏的embedding / lm_head / router / norm 等部分并不会按同样比例缩小也就是说MoE 里稀疏的是专家层不是整个模型。七、第六步别忘了 dense 主干它往往比你想的更重要一个完整的 Transformer MoE block通常不会只有 experts。它还有很多一直参与计算的 dense 模块例如q_projk_projv_projo_projrouterinput / post-attention norm这些模块的参数量虽然可能比全部 experts 小很多但它们会决定两个很重要的事情你的 active params 不会小到只剩“被选中的 experts”你的实际推理延迟也不会只由 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 sizeseq lengthKV cachekernel 优化量化部署框架所以 active params 更像是一个结构级指标而不是完整的部署结论。九、第八步如何通过 attention 字段快速判断部署侧含义有些开发者看 MoE 只盯 experts其实 attention 的配置同样非常值得看。重点字段包括num_attention_headsnum_key_value_headshead_dimsliding_windowmax_position_embeddingsrope_thetarope_scaling这些字段至少能让你快速判断三件事。1. 它是不是 GQA / MQA如果num_key_value_heads num_attention_heads通常说明模型用了 GQA。这通常意味着KV cache 会更省长上下文推理更友好实际部署成本可能低于你对“头数很多”的直觉判断2. 它对长上下文做了什么如果你看到rope_scalingmax_position_embeddingssliding_window就要意识到这个模型不仅是 MoE还是一个特定长上下文策略下的 MoE。很多时候真实部署瓶颈不在 experts而在长上下文 attention。3. 它的 attention 是不是全量密集有些模型会混用full attentionsliding attentionlocal 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 的 shaperouter 输出的 top-k 逻辑是否所有层都调用同一种 MLP是否有额外 bias、shared branch、残差 branch十二、给开发者一套可复用的 5 分钟阅读流程如果以后你想快速看懂任意一个 MoE 模型我建议固定按下面流程走。第 1 分钟先看是不是标准 MoE重点扫num_local_expertsnum_experts_per_tokrouter_aux_loss_coefoutput_router_logits第 2 分钟看 expert 和层数规模重点扫num_hidden_layershidden_sizeintermediate_size这一步先把单 expert 和总层数的量级建立起来。第 3 分钟看 attention 结构重点扫num_attention_headsnum_key_value_headshead_dimsliding_window这一步是为了判断部署侧真实成本不只是参数量。第 4 分钟看 embedding / 输出头口径重点扫vocab_sizetie_word_embeddings这一步决定你后面核对 active params 时是否容易和官方数字差几亿。第 5 分钟判断要不要去看代码如果结构标准就可以直接做快速估算。如果结构复杂就不要死算直接去看实现 shape。十三、给团队做模型选型时我最建议记录的 8 个结论很多团队看完模型后没有沉淀成统一模板导致下一次又要重新理解一遍。我建议你每次看一个新 MoE 模型至少固定记录这 8 项总层数是多少每层总 expert 数是多少每个 token top-k 是多少单 expert 大小大概是多少是否存在 shared expert是否所有层都启用 MoEattention 是 MHA、GQA 还是 MQAactive params 的统计口径是否包含 embedding / lm_head你会发现只要这 8 项写下来模型结构已经非常透明了。十四、一个通用估算模板以后看任何标准 MoE 都能直接套下面给你一个通用模板适合快速估算标准 MoE。defestimate_standard_moe(hidden_size,intermediate_size,num_hidden_layers,num_local_experts,num_experts_per_tok,):per_expert3*hidden_size*intermediate_size active_per_layernum_experts_per_tok*per_expert total_active_expertsnum_hidden_layers*active_per_layer total_all_expertsnum_hidden_layers*num_local_experts*per_expertreturn{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你也能快速建立正确判断。所以这篇文章最想带走的不是某个具体结论而是一套稳定的阅读框架先确认是不是标准 MoE。再看 experts 的总量和 top-k。再估单 expert 的规模。再把 dense 主干补回来。最后明确统计口径不要把 active params 和真实部署成本混为一谈。只要你掌握了这套方法以后再看任何新出的专家模型基本都不会再被模型卡上的数字牵着走。