又有人来问MOE和Dense模型到底差哪了?

发布于 2025-9-29 07:29
浏览
0收藏

最近更新的比较少,因为一直在打街霸6的天梯,我已经冲到钻石了,离大师一步之遥。

又有人来问MOE和Dense模型到底差哪了?-AI.x社区

然而...今天又被人问了MOE和dense到底区别在哪,但是他说的很多理解是完全错的。其实我以前讲过,但是可能没那么细,所以我今天仔细澄清一下大家理解的误区。

如果随便答,其实什么推理省显存,简单的道理,因为activation 少了么,原来要激活整个MLP,现在激活的几个expert之类的云答案,这种很好找的。

那么问题来了,激活experts(一般需要*N)就比你dense模型激活少么?

首先MOE的experts和dense的 MLP是什么关系?

估计大部分兄弟随口一云,就会说per_expert_dim * expert_num= MLP

这对么?

看起来好像对的答案,其实是经不起推敲的。

我们知道transformer的layer的架构排布是下面这样的。

又有人来问MOE和Dense模型到底差哪了?-AI.x社区图片


因为我们为了简单就用标准的causal LLM也就是右边的这个来讲。

首先MH attention 层要经过qkv矩阵之后算注意力然后由liner o 也就是output会产生出来送给MLP层的tensor,这个东西对mlp层计算的dim(维度)是和mlp层的input layer是相同的。

那就变了MOE就能不同?

想象都知道不可能得事吗,维度不一样,你怎么矩阵计算呢?

所以这个在互联网上普及的看似正确的答案就是个纯扯淡的意淫流答案。

那实际是怎么样的呢?

我们分两个思路来看

第一,假设你原有一个模型,你就想给它升级MOE

那你升级哪呢?

升级MLP么,对吧,基于我刚才讲的,liner o出来的维度要和mlp维度等价,所以你如果有8个experts,就是相当于给你的整个MLP层扩大了8倍参数。

这么做的话呢,首先可以肯定的是,如果你会训练,知道怎么稳定MOE梯度之类的操作,那么效果自然是好的,因为扩参数,想都不用想。

但是,你省资源了吗?

那必然是没省,因为你整个参数扩大了,对于transformer模型来讲最大头的参数肯定是MLP,也就是你放大了几倍的参数,weight显存,你占定了,同样的激活,原来我激活一个mlp,哪怕你是最简单的8 experts only激活2个,那也是2倍一样的激活显存,这个不管训练还是推理,你都要投入对应的显存容量来fulfill。

所以这个和你初始的要求不太一样啊!

所以第二个思路,我重做一个,重头design。

我们以qwen的32b和qwen 30B A3B来做一个对比。

又有人来问MOE和Dense模型到底差哪了?-AI.x社区图片

这俩模型差不多大,对于weight显存的占用肯定是差不多了。

那么我们现在来分析左边的dense 32B 和右边的MOE 30B-A3B的区别。

一、谁变了、变到哪

  • 层数 L
    dense: num_hidden_layers=64
    MoE: num_hidden_layers=48
    MoE 版显著减少了层数。因为在总参受限了,就30B左右,所以FFN(MLP)大点,地方就那么大,那前面attention层就要受挤压,MoE 会让骨干深度变浅,把参数预算让给 experts。
  • 模型隐维 d_model 与注意力dense: hidden_size=5120, num_attention_heads=64, head_dim=128(由图左侧 head_dim=128 可见)MoE: hidden_size=2048, num_attention_heads=32, head_dim=128MoE 版把 d_model 从 5120 降到 2048;注意力头数也从 64 降到 32,但单头宽度 head_dim 仍是 128。这意味着注意力与残差主干被整体“瘦身”了,刚才把attention的层干浅了,这次把整个模型的dim宽度也干窄了,进一步为了维持30B左右的参数,继续砍
  • FFN/MLP 中间维(dense 的 intermediate_size)dense: intermediate_size=25600(≈5× d_model=5120)MoE: intermediate_size=6144(这是 MoE 层里每个 expert 的中间维度 d_ff_expert;≈3× d_model=2048)关键点:MoE 不是把 dense 的中间维切片,而是每个 expert 自己一套、但更“瘦”。这里清楚显示了业界常用策略:保持输入输出维为 d_model,降低专家的中间宽度来控参控算。当然有人也会杠,那为什么没有人在liner o,也就是proj o 后面加一个降为的liner来和mlp的expert对齐,这个问题我不回答,大家自己琢磨琢磨,留个彩蛋,当然你想明白这个问题就自然会心一笑。
  • MoE 相关字段"moe_intermediate_size": 768(图右存在该字段,通常用于门控/共享投影等 MoE 内部维度,具体实现依赖库)"num_experts": 128"num_experts_per_tok": 3(就是 top-k=3)还有 router/负载均衡的若干超参(如 router_aux_loss_coeff 等)这是一个较大 N 的 MoE(128 个专家),每个 token 激活 3 个。从训练的角度这个确实省激活,其实推理就还好。别看好像省了125个experts,但是对于推理来讲,它不是训练,不用考虑反向。这种没那么大的模型,activation的显存能省,但是省不了你们想那么多,除非你input的seq特别长,batch太大。
  • KV headsdense: num_key_value_heads=64(与总头数一致)
    MoE: num_key_value_heads=4(显著更少,采用 GQA:少量 KV 头共享给多查询头)
    这进一步压缩了注意力状态与推理缓存(KV cache),降低显存与带宽压力。

二、从这些变化得出的结论

  • MoE 版把“共享、每 token 必算”的主干(d_model、注意力头数、层数)都缩小了;把参数预算转移到“稀疏激活”的专家集合上。在总参固定下,MoE 也没有超能力,所以只能让注意力/层数变小或变浅。
  • 每个 expert 的中间维度被降了:dense 的 25600(≈5×5120)对比 MoE 每 expert 的 6144(≈3×2048),其实单个的mlp(一个expert)的表达能力是被降低了,我们知道mlp层的核心诉求就是需求隐空间的语义信息,那降低了怎么办?用多experts来承载多样性。
  • 同时引入 GQA(num_key_value_heads 远小于总头数)来进一步节约注意力侧的参数与 KV cache,适配大 N、top‑k 的 MoE 设计,保障吞吐和显存可行。

三、对训练/推理与效果的含义

  • 训练/推理 FLOPs
    每 token 的 MoE 计算量主要随 k=3 与 d_ff_expert=6144 走;N=128 对单 token FLOPs 影响不大(更多影响参数量与路由)。
    注意力侧因 d_model 变小、头数变少、GQA 化,计算与 KV cache 显著下降,有利于吞吐。
  • 表达力与路由
    虽然单个 expert 比 dense 的 FFN 更瘦,但有 128 个专家且 top‑3 激活,整体表达多样性提升;负载均衡和路由质量变得关键。
  • 长上下文与注意力质量
    d_model 与头数变小对注意力分辨率不利,但通过层数/专家多样性、训练策略与数据规模可以部分补偿。具体效果要看实际评测。这个也是moe的一个弱点(同等参数下),当然如果你能给upset做到671B又做到1T,那当我没说

四、可复制的设计要点(如果你要做同类改型)

  • 保持子层输入/输出维一致为 d_model(方便残差与实现),把“瘦身”放在 expert 的中间维 d_ff_expert。
  • 通过减少 L、d_model、注意力头数和使用 GQA 来为 MoE 挪参数预算。
  • 选择合适的 N 与 k,常见 k=1–2;这里采用 k=3,配合更强的路由/均衡与较瘦的 expert。
  • 关注 router 正则(如 router_aux_loss_coeff)与 capacity 设置,保证均衡与稳定训练。

好,那么我们总结一下!

看这两个模型config.json的配置,并对比,非常清晰地展示了标准业界的 MoE 的典型取舍:在总参相近时,MoE 模型显著缩小了主干(d_model、层数、注意力头/GQA),并把 FFN 从 dense 的单路大宽度,改成多专家的中等宽度;每个 expert 的维度被刻意降了,以换取“多专家 + 稀疏激活”的表达力与性价比。

本文转载自​熵减AI​,作者:周博洋

已于2025-9-29 10:11:56修改
收藏
回复
举报
回复
相关推荐