这两年大模型圈子里有个挺有意思的现象:同一个模型家族,标出来的参数版本越来越大,几百亿、上千亿的参数看着很唬人,但厂商对外宣传推理成本时,却说“和某个几十亿参数的模型差不多”。我第一次听到这种说法时,下意识觉得是营销话术。后来自己动手跑了一遍MoE(Mixture of Experts,专家混合)架构的开源模型,才意识到这句话在特定条件下居然是真的:总参数量翻了几倍,单次推理的计算量却基本没跟着涨。
这篇文章想把这笔账拆开讲清楚。适合两类人看:一类是被各种技术新闻里“MoE”“稀疏激活”“专家路由”这些词绕晕,想搞清楚它到底为什么省算力的小白;另一类是正在纠结选MoE架构还是稠密(Dense)架构做落地的工程开发者。我会尽量少堆公式,把机制、账本、代价三件事说透。
1. 先把“专家”这件事讲清楚:MoE治的是什么病
1.1 大模型的“通才病”:所有参数都得处理所有问题
要理解MoE,得先看传统Transformer模型的“笨办法”长什么样。标准的稠密模型里,每一层都只有一套权重,不管你给它的是“这是一句英文”“这是一道数学题”“这是一段代码”,还是“这是猫的图片描述”,同一层的所有参数都要完整参与计算。
这就好比一个医院里只有一个全科医生,不管你是头疼、骨折、拉肚子还是视力模糊,都得排队等这位医生一个人看。这位医生确实很博学,但他只有一双手、一个脑子,同时段只能处理一个病人,而且每个病人都要占用他全部的能力。
放到模型里,“全科医生”对应的是前馈网络FFN层。模型中的每个Token经过这一层时,都要把这一层的几亿、几十亿个参数全部乘一遍。模型越大,这个“全员出动”的计算量就越大。这是Dense模型推理成本居高不下的根本原因——没有偷懒的机制。
1.2 一个更贴近人类组织的分工逻辑
MoE的思路非常朴素:与其让一位全科医生看所有病,不如开一家综合医院,设很多专科,再配一个分诊台。病人来了,先由分诊台判断他大概属于哪个科,然后只把他送到对应的两三个专科医生那里。每个专科医生不需要掌握所有医学知识,只需要把自己领域看透。
在MoE模型里,原本那一个巨大的FFN层被拆成了若干个“专家”(Expert),每个专家都是一个独立的、规模较小的前馈网络。原来那层参数对每个Token全量计算,变成了一群专家先由门控网络打分,然后只把Token交给被选中的少数几位专家去处理。注意,整个过程中不是所有专家都在干活,每次只有一小部分被“点亮”。
这个逻辑放到现实生活里其实特别熟悉。上过大学的人都懂,一个学校有几百个老师,你的课程表不会让所有老师都来给你上课,而是由教务系统根据你的专业、选课,挑选出少数几位老师来教你这学期的课。MoE本质上就是把这种“按需调度”的思路引入到了神经网络的每一层。
1.3 专家分工不是大模型时代才有的思路
这里需要澄清一个误区:MoE并不是大模型火了之后才被发明出来的新概念。早在上世纪九十年代,统计机器学习领域就有过“专家混合”的探索,当时的想法是把多个模型组合起来,让门控网络根据输入样本分配给不同的子模型处理。后来在机器翻译领域,也有研究者验证过在循环神经网络里加入MoE结构的可行性。
真正让MoE进入大众视野的,是后来Transformer大模型面临计算瓶颈时,研究者发现把FFN层替换成专家混合结构,可以在不大幅增加单次推理计算量的前提下,把模型的总参数量拉上去好几个量级。这个“逻辑老早就有了,只是最近几年才被大规模商用验证”的节奏,和很多经典技术的翻红路径很像。它不是横空出世,而是因为算力贵、模型大的时代矛盾,终于轮到了它登场。
2. 门控网络、稀疏激活与路由机制:一次推理到底发生了什么
2.1 从“分诊台”到“专科医生”的完整流程
光说“把FFN拆成专家”还不够,你需要看到一个Token在MoE层里是怎么一步步走完的。我画个文字版的流程:
第一步,Token经过注意力层之后,得到当前时刻的隐藏表示。
第二步,这个隐藏表示会同时送给门控网络(Router)和所有专家。门控网络的本质是一个分类器,它的任务是计算这个Token和每个专家的匹配度得分,然后做个Softmax归一化。
第三步,由得分选出排名最高的K个专家(K通常取1~4,最常见的是2)。
第四步,Token被复制发送到这K个专家那里,各自独立完成一次FFN计算。
第五步,K个专家的输出结果按门控网络给出的权重做加权求和,合并成一个最终输出。
这个流程里最关键的设计就是:Token不需要访问所有专家。你只需要计算门控网络对所有专家的打分,但只对排名靠前的K个专家执行实际计算。这就像分诊台需要浏览全院科室名录来做判断,但最终只有被点名的一两个科室真的派出医生来看你。
2.2 Top-K激活:为什么只叫最靠谱的两位专家
这里的K值是MoE里最核心的超参数之一。如果你把K设置为1,那就意味着每次只派一位专家来干活,计算量最省,但风险是如果分诊台判断错了,完全没有纠错余地。如果K设置为2,相当于每次派两位医生会诊,即使其中一位判断不太准,另一位也能兜底,输出质量通常更稳。
从直觉上讲,K值越大,模型的表达能力越接近稠密模型,但计算量也越高。K值设置为全部专家数量的那种极端情况,其实就退化成了Dense模型,所有专家都参和一轮,等于没省任何算力。所以MoE的“稀疏”不是口头说说的,它是由K值硬性决定的。一个常见配置是16个专家选2个,32个专家选2个,这样每次只有12.5%甚至6.25%的专家参于实际计算,稀疏度非常可观。
有一个容易被忽略的点:路由决策是在Token级别做的。同一个句子里的不同Token,可能会被分到不同的专家。比如“我今天很开心,所以想去做运动”这句话,“开心”可能触发与情感语义相关的专家,而“运动”可能被路由到与动作、身体相关的专家。这种Token级动态路由,让模型能够在非常细的粒度上调度计算资源。
2.3 路由平衡:不能让一位专家忙死
如果你以为只要加一个门控网络就万事大吉,那就太天真了。实际训练中会遇到一个很麻烦的情况:门控网络可能很快学会“偷懒”,总是把大多数Token分配给某几个“明星专家”,而其他专家几乎接不到活。这会导致三个后果:明星专家过载,计算延迟变高;其他专家训练不足,能力退化;整体模型的表达能力下降。
为了解决这个问题,现代MoE普遍会加入负载均衡损失(Load Balancing Loss)。它的目标很直接——在训练时惩罚那些“分配极不均匀”的路由策略。如果一批Token里有90%都被分到了同一个专家,路由损失就会变得很高,模型训练时会尽量避免这种情况。这相当于医院给分诊台定了个制度:每名医生每个时段接待的病人数量要大致接近,不能说某个医生人气高就累死他。
负载均衡不是只影响训练稳定性的细节,它会直接作用到推理性能。因为部署MoE时,不同专家通常放在不同的计算设备上,如果某个专家被分配的Token远超其他专家,那么处理这位“明星专家”的设备就会变成瓶颈,其他设备都在空转等它。
2.4 共享专家与路由专家的拆分逻辑
如果你看过一些MoE模型的层结构,会发现除了若干个路由专家之外,往往还会额外放一个“共享专家”(Shared Expert)。每一个Token进来,不经过路由选择,一定会先经过这个共享专家,然后再进入被选中的稀疏专家。
为什么要单独开一个“必答题”?因为Token之间存在大量共通的基础模式——通用的语法结构、通用的逻辑框架、通用的常识知识。这些内容如果都交给路由专家去单独处理,会造成大量冗余计算,也有可能导致不同专家学到的通用知识不一致。共享专家的定位就是把这些公共底座接住,让路由专家可以更专注地学习“差异化”的那部分能力。
如果做个类比,你在一家互联网公司,共享专家相当于中台的基础服务,比如统一登录、统一权限;路由专家相当于各个业务线自己搭建的专用模块。基础能力放中台,不用每个业务线都重复造一遍,专用能力才按需动态调用。这种“共享+路由”的设计会让模型的参数效率更高,也是近两年很多主流MoE架构的共同选择。
3. 参数量翻倍但推理成本不涨:这笔账到底怎么算的
3.1 参数量与计算量:两个完全不同的指标
标题里那句“参数量翻倍却不增加推理成本”,问题就出在大家容易把“总参数量”和“单次推理计算量”混为一谈。实际上,对推理性能影响最直接的是后者,而不是前者。
参数量,就是模型文件里存储的权重总数。它决定的是这个模型占多少存储空间、加载进显存需要多大的容量。计算量,则是一次推理过程中实际执行的浮点运算次数,通常用FLOPs来估算。Dense模型里,总参数量几乎等于激活参数量——每个Token都会把所有参数都算一遍,所以两者成正比。但MoE模型里,总参数量很高,激活参数量却很低,因为每次只有少数专家被调用。
我举一个具体的例子。假设一个Dense模型的某一层FFN有8亿参数,那么每个Token经过这一层时,必须对这8亿参数做一次完整的矩阵乘加运算。现在把这个FFN拆成16个专家,每个专家的参数量设为0.6亿,那么16个专家的总参数是9.6亿,总参数反而更多了。但如果路由只选前2个专家,实际参与计算的只有1.2亿参数。你看,参数总量从8亿涨到9.6亿,但计算量从8亿降到1.2亿,大约只有原来的15%。这就是MoE真正的“魔法”——总量变大了,单次开销反而变小。
3.2 稀疏激活视角下的FLOPs估算
从FLOPs的角度来算可能更直观。忽略Attention部分,一个Token经过一层FFN的计算量大约等于2乘以该层的激活参数量。Dense模型激活参数就是全部参数,而MoE模型激活参数是“K乘以单个专家参数”再加上共享专家的参数。
所以决定推理速度的核心指标叫作“激活参数量”。两个模型,一个总参数1000亿的MoE模型和一个总参数100亿的Dense模型,如果MoE激活参数只有20亿,那MoE在计算速度上可能会比Dense模型更快,虽然它的总参数是后者的10倍。这个反直觉的结论,恰恰是MoE近年被大规模部署的核心原因。
但这里也要泼一盆冷水:FLOPs下降不等于墙钟时间等比例下降。计算量少了是理论上的,实际还要考虑内存带宽、路由开销、通信时延等等。特别要说明的是,现代模型的推理瓶颈往往不只是计算量,还有显存带宽——模型参数要从显存搬运到计算单元。如果参数总量很大,即使只有一小部分参与计算,加载这“一小部分”也仍然需要从显存里读数据。不过因为只读激活的那部分参数,带宽占用还是比Dense低。
3.3 显存占用、存储成本与推理成本:三笔账分开算
很多小白听到“参数量翻倍成本不涨”之后,天真地以为MoE模型的硬件要求也差不多,这是大错特错。我们需要把三笔账彻底分开:
第一笔,存储成本。所有专家的权重都要保存在硬盘上,总参数量大,模型文件就大,磁盘占用和下载流量都会明显增加。一个1000亿总参数的MoE模型,光模型权重就比100亿参数的Dense模型大一个量级。
第二笔,显存占用。部署推理时,所有专家的参数都要加载进显存(不管是否被激活),因为你这批次用到的Token可能被路由到任何专家。这也就意味着MoE模型的总显存需求非常高,通常需要在多张GPU上分布式部署,单卡基本跑不起来。
第三笔,推理算力成本。这才是MoE真正省钱的部分。因为单Token计算量由激活参数决定,如果激活参数控制得好,服务端每个Token的算力开销就跟一个小得多的Dense模型差不多。
3.4 “不增加推理成本”这句话应该怎么理解
所以最严谨的说法应该是:MoE在总参数量大幅增加的情况下,推理算力不会同比例增长,甚至可以在某些配置下低于同能力的Dense模型。但你不能说它完全“零成本增加”——门控网络要计算分数,Token要被复制和分发到多个专家,专家的输出要汇总,这些都引入了额外的开销。尤其在分布式部署时,Token从一台设备搬运到另一台设备的通信开销是实打实的,需要在工程上仔细优化。
另外有个问题常被忽略:MoE的训练成本一点都不低。推理时只用少数专家,但训练时所有专家的参数都要更新,优化器状态、梯度计算、通信同步的总量是和总参数成正比上升的。所以如果你因为“推理便宜”就想着从头训练一个MoE大模型,这个判断需要再掂量一下——省的是线上服务,贵的是炼金过程。
4. 从论文到大规模商用:现代MoE补上了哪些拼图
4.1 原理老早就有了,为什么近年才成为主流
前面提过MoE的学术渊源可以追溯到上世纪九十年代,但为什么到了近几年才成为大模型的主流架构之一?我认为核心原因是过去这几年同时凑齐了三块拼图:模型规模需求暴涨、算力成本越来越贵、分布式训练框架趋于成熟。
早期MoE的学术验证基本停留在小模型和特定任务上,一旦放大到生产级规模,问题就暴露了:路由不稳定、训练容易发散、负载严重不均衡、并行实现困难。这些问题让MoE长期停留在“很性感但没人敢跑”的阶段。
转折点出现在大模型竞赛开始之后。各家厂商发现,靠单纯堆算力扩大Dense模型容易撞上成本天花板,而MoE能在同样算力预算下把模型容量做得更大。随后出现的一系列开源MoE模型证明了其可行性,行业才真正开始跟进。
4.2 负载均衡策略的演进
现代MoE能稳定训练,很大程度上靠的是负载均衡策略的成熟。早期方案只是简单地对门控打分加噪声,鼓励探索,但效果不稳定。后来引入显式的辅助损失(Auxiliary Loss),让路由分布尽量接近均匀分布。
更进一步的改进是给路由打分加一个额外的Z-loss正则项。它的作用是防止路由得分的绝对值变得过大,从而让Softmax输出过于极端,比如90%的概率都集中在一个专家上。Z-loss会让路由决策变得更“平滑”,梯度传播也更稳定。这些细碎但重要的改进,是MoE从“论文里能跑”到“生产里能训”的关键跨越。
另外值得一提的还有专家容量(Expert Capacity)的概念。每个专家在一个批次内处理Token的数量是有上限的,如果超过上限,超出的Token会被丢弃或直接走残差连接跳过这层。这个机制看起来粗暴,实际非常有效。它解决了两个问题:一是防止个别专家过载导致训练崩溃;二是让训练和推理时的计算负载可预期。
4.3 跨设备专家并行与通信开销
MoE的部署和工程实现,与传统Dense模型有很大不同。Dense模型做并行时,会把整个模型切到多张GPU上,每张卡负责不同层或同一层的不同参数块,计算过程中每层通信模式相对规整。MoE则不同,专家分布在多张GPU上,Token经过路由之后可能需要从一张卡发送到另一张卡去“就诊”。
这个通信模式叫作All-to-All:任何一个设备都可能要向任意其他设备发送Token数据。如果路由均衡做得好,通信量相对均匀;如果路由失衡,通信热点的时延会直接拖垮整体性能。这也是为什么很多MoE框架都在拼了命优化通信调度,甚至会把专家复制多份放到不同节点,以减少跨节点通信。
在实际部署中,一个常见取舍是:专家数越多,单个专家参数量越小,通信频率越高;专家数越少,通信越少,但计算稀疏度越低。怎么取这个平衡,基本属于工程经验的范畴,业界没有统一答案。
4.4 训练稳定性的渐进优化
现代MoE在训练时还会采用一个非常重要的技巧:训练和推理的配置解耦。训练阶段,为了让梯度信息更充分地在专家之间传播,往往会让K值设得大一些,比如激活4个甚至更多专家;推理阶段则把K值调低,比如2个,来节省算力。这种做法相当于用训练时的“冗余”换取了推理时的“经济”。
另一个训练技巧是渐进式路由裁剪。训练初期路由决策会很不稳定,如果太早强制稀疏,模型可能学不到合理的路由策略。有些方案会在训练早期让更多专家参与,随着训练推进再逐步收敛到目标K值。这个步骤很细,但对最终的模型质量有明显影响。
对于刚接触MoE的同学,我建议不要一上来就基于开源代码改结构。先跑通一个现成的MoE模型,用固定随机种子做几组实验,观察路由分布的直方图,看看是否存在某个专家一直拿到超额Token。如果存在,就说明负载均衡的损失系数调得不对,需要调整。
5. MoE不是免费午餐:容易被忽略的成本与坑
5.1 显存占用没有减少,反而可能更高
前文提到,MoE总参数大,部署时所有专家必须常驻显存。无论当前批次是否用到某个专家,参数都必须待命。一个总参数1000亿的MoE模型,即使单Token激活只有20亿,服务器也得准备能装下1000亿参数的显存。
这就造成一个很尴尬的局面:MoE省下了算力成本,却把压力转移到了显存成本。很多MoE模型的商用部署,动不动就要几十张高端显卡,普通团队根本玩不起。如果对比同等“激活参数量”的Dense模型,MoE的显存开销可能是后者的五倍、十倍。所以在选购方案时,不能只看单Token成本,还要看整体的硬件投资。
5.2 路由波动与推理结果的不确定性
MoE还有一个在实践层面很容易被忽视的问题:推理结果存在一定程度的随机性。Dense模型在相同输入、相同权重下跑两次,结果几乎完全一致。MoE模型的输出则可能因为路由策略的微小波动而出现差异。
这个问题的根源是动态路由。Token在不同上下文、不同批次里可能被路由到不同的专家,而这种分配结果并不总是稳定的。尤其在低精度推理、批次大小动态变化的场景中,路由波动会更明显。对于对话、写作这类对结果一致性要求不高的应用,影响不大;但如果是做自动化测试、金融风控、内容审核这类依赖确定性输出的任务,就要特别小心。
有些团队会在推理时固定路由结果、不对门控打分做随机采样,来换取输出的确定性,但这个策略会牺牲一部分模型表达能力,属于取舍而非彻底解决。
5.3 微调与大改条件下的专家过拟合风险
MoE模型在微调阶段也让人头疼。因为路由本身是可学习的,一个模型在预训练任务上学到的路由偏好,在微调时可能被带偏,导致部分专家被大量使用,另一些专家逐渐被边缘化。如果不加约束,微调几次之后,模型可能沦为只会调用一两个专家的“半Dense模型”,MoE的优势名存实亡。
还有一个更实际的问题:微调时显存占用依然很高。优化器状态和梯度是按总参数量计算的,即使微调时只更新少数参数,也要把整个模型加载进显存。所以别以为MoE推理便宜,微调也一定便宜,这个坑不少人都踩过。
如果必须微调MoE,我建议保留较低的学习率,同时对路由部分的权重设置单独的学习率衰减策略。更稳定的是用LoRA这类参数高效微调方法,只训练注入的低秩矩阵,让预训练的路由决策保持稳定。
5.4 服务框架层面的动态调度复杂度
最后一个现实问题是服务化部署。Dense模型的推理batch可以很规整,所有请求按预定形状并行处理;MoE则不然,每个Token可能被分到不同的专家,同一个batch内不同专家的负载天然不均衡。服务框架要处理这种动态调度,难度比Dense大不少。
现代推理框架对MoE的支持还在持续完善中,但如果你用的是老旧的推理服务组件,很可能需要做不少定制开发才能跑起来。这里建议团队在立项前先做技术调研:你准备用的推理框架是否原生支持专家并行?是否支持动态路由的batch调度?如果不支持,自研的时间成本可能远远超过MoE带来的算力收益。
为了更直观,我把Dense和MoE几个关键维度的差异列个表:
| 维度 | Dense模型 | MoE模型 |
|---|---|---|
| 总参数量 | 较低 | 较高,甚至翻倍 |
| 单Token激活参数 | 全部 | 仅Top-K专家+共享专家 |
| 推理算力成本 | 与总参数线性相关 | 与激活参数线性相关 |
| 显存需求 | 中等 | 高,所有专家常驻显存 |
| 训练成本 | 与总参数成正比 | 更高,优化器状态和通信开销大 |
| 输出确定性 | 高 | 受路由波动影响 |
| 部署复杂度 | 较低 | 高,需专家并行与动态调度 |
6. 一些选型上的个人观察
做技术选型时,我的习惯是先问自己到底缺的是什么。如果瓶颈是“单Token推理成本太高、算力预算有限”,那MoE是很值得考虑的架构;如果瓶颈是“显存不够、只想用少量显卡部署”,那MoE大概率帮不上忙,甚至帮倒忙。
对小团队或者个人开发者,我的建议更直接:能用Dense就不折腾MoE。只有当你面对的用户规模足够大、推理成本在总支出里占比很高时,MoE的收益才值得你去承担它显存和工程复杂度上的额外负担。对普通用户来说,看厂商宣传时留个心眼:看清“总参数量”和“激活参数量”这两个数字,别看到千亿参数就以为一定要用超算才能跑,也别看到算力成本低就以为模型一定很轻。
如果你只是想理解MoE,最便宜的入门办法是找一个开源的MoE模型实际跑一次推理,打开路由日志看一眼每个Token被分到了哪几位专家。直觉建立起来之后,很多概念就通了。架构之争还会继续,但可以确定的是,在算力仍然昂贵的阶段,这种“让更多参数待命、让少数参数干活”的设计思路会越来越多地出现在各种规模的模型里。