先看稠密模型的浪费
Transformer 的参数大头不在注意力,而在 FFN(前馈网络,每层注意力之后的两层全连接,负责对信息做非线性加工)。按常见配置粗算,FFN 参数约占整个模型的三分之二。所谓稠密模型(dense),就是不管输入什么,每个 token 都要穿过全部参数:参数堆得越多,每个 token 的计算就越贵,能力与成本绑死在一起。
但直觉上这是浪费。一次回答里用到的知识高度局部化:一个问 SQL 优化的问题,用不着激活和分子生物学相关的参数。能不能让每个 token 只走一小部分参数?
MoE 的基本结构
MoE(Mixture of Experts,混合专家)的答案,是把每层的单个 FFN 换成 N 个并列的专家 FFN,再加一个路由器(router)——一个很小的网络,读入当前 token 的表示,给每个专家打分,选出得分最高的 top-k 个,token 只经过这几个专家的 FFN,输出按路由权重加权合并,其余专家对这个 token 零参与。
值得注意的是路由的粒度:路由决策逐 token 独立做出,同一段文本里不同的 token 会走不同的专家组合——谈 SQL 的词和谈历史的词,过了路由器就分道扬镳。专家也不是把训练好的多个模型拼在一起,而是与路由器一起从零训练;专家的「专长」由训练自发形成,公开分析显示分工常呈现可解释的倾向(比如语法与标点聚成一类),但不严格对应人类学科。
于是出现了两个必须分清的数字:总参数量(所有专家加起来)与激活参数量(每个 token 实际经过的部分)。读任何 MoE 模型的规格表,先找这两个数:显存需求看总参数,单 token 计算量看激活参数。这也是「变胖不变贵」的准确含义——总参数决定知识容量,激活参数决定推理成本,两者被解耦了。
训练难点:路由塌缩与负载均衡
MoE 训练有个著名陷阱:路由塌缩。训练初期若某个专家碰巧学得稍好,路由器就把更多 token 分给它,它因此变得更好,正反馈循环,最后几乎所有 token 涌向少数专家,其余专家得不到训练,MoE 退化成一个又贵又弱的残缺模型。
标准对策是辅助损失(auxiliary loss):在主任务损失之外加一项惩罚,激励各专家接收的 token 数尽量均匀,定性理解就是「不许有人闲死、有人忙死」。不同模型还有各自的补充手段,例如给每个专家设容量上限,满载后溢出的 token 直接跳过专家层。这些设计合起来保证专家「分工但不扎堆」——各学各的领域,同时没有谁被饿死。
负载均衡也不只是训练期的问题:推理时 token 若持续涌向同一批专家,对应的显卡被打满、其余算力闲置,服务吞吐随之受损。均衡既是训练技术,也是要长期盯的运维指标。
推理侧的真实成本
MoE 不是免费的午餐,账要分两头算。
显存一头不省。虽然每个 token 只激活少数专家,但任何 token 都可能路由到任何专家,全部专家的权重都必须随时可寻址。省的是计算,不省显存——这和稠密模型「想省显存就换小一号」的直觉正好相反。
计算一头真省。每 token 的计算量只跟激活参数挂钩:top-k 路由下,token 只流过 k/N 的专家 FFN。专家并行(expert parallelism)是部署大 MoE 的关键拼图:把不同专家的权重摊到不同显卡,token 按路由结果跨卡传递,与张量并行、流水线并行组合使用,超大 MoE 模型才跑得起来。
也正因如此,MoE 的吞吐优势要在成批请求下才充分体现:单个请求感受不到激活参数的便宜,大量 token 同时流动、分别路由到不同专家时,整体算力才被真正摊薄。离线批处理与高并发在线服务,是最能吃到红利的两类负载。
公开实践长什么样
Mixtral 8x7B 是最常被引用的参考:8 个专家、每 token 激活 top-2,总参数约 47B、激活参数约 13B——推理成本大致对标一个 13B 稠密模型,知识容量却大得多。DeepSeek 系列则走了另一条路:把专家切得更细(数量多、单个小),并配一组始终激活的共享专家承接通用知识,路由只管专业部分。定性上的收益是组合方式更灵活、专家分工更专职,细节以各自技术报告为准。
怎么选
MoE 适合的场景:显存充裕但算力或延迟紧张,比如自部署服务要扛高并发;或者想要大知识容量,又养不起同尺寸稠密模型的推理开销。稠密模型适合:显存本身就是第一约束的小卡场景;推理框架对 MoE 支持不完善时;或者业务规模根本吃不满 MoE 的吞吐优势。
一句话总结:MoE 用显存换算力,把「模型多大」和「每 token 多贵」拆成两个独立旋钮。看到模型规格,先找总参数和激活参数两个数——它们分别告诉你这个模型有多能装、有多省算。
读者留言
COMMENTS 暂无还没有留言,来说第一句?