☰
为什么 DeepSeek 又大又便宜?——MoE 混合专家,把“大模型“拆成一屋子“小专家“
2026/9/29 20:05:23 网站建设 项目流程

先说一个让很多人想不通的事实:DeepSeek-V3 有 671B 参数,是 GPT-4 那个量级的好几倍,可它一次推理实际"开火"的,只有 37B。

一个 6710 亿参数的庞然大物,跑起来却只用了不到二十分之一的算力。这听上去像营销话术,其实是 MoE(Mixture of Experts,混合专家)这个老架构在 2025 年被彻底盘活之后的结果。


一、全公司开会,还是叫几个人开小会

把大模型想象成一家公司。传统的大模型是"全公司开会"——每一个 token 进来,所有神经元都要算一遍,一个人都不能闲着。这种模型叫 **Dense(稠密)**模型,参数和计算是绑死的:671B 参数,就得 671B 全部参与一次前向。

MoE 的思路是:公司里养着一大屋子"专家",但每个问题进来,只叫最对口的那么两三个专家来开个小会,其余专家喝茶待命。

所以在 MoE 里要分清两个数:

  • 总参数:全公司有多少人(671B)。
  • 激活参数:每次开会叫了几个人(37B)。

推理成本由"叫了几个人"决定,而不是"养了多少人"。这就是"又大又便宜"的秘密:大体现在知识容量上,便宜体现在每次只激活一小撮上。


二、谁来当"前台"?——门控网络

谁来决定"这个 token 该找哪几个专家"?一个叫 **Router(路由/门控)**的小网络。

它本质是一个线性层 + softmax,把每个 token 的隐藏向量映射成"每个专家该分到多少权重":

g ( x ) = softmax ( W g ⋅ x ) g(x) = \text{softmax}(W_g \cdot x)g(x)=softmax(Wg​⋅x)

x xx是 token 的表示,W g W_gWg​是门控的权重矩阵。softmax 出来一串非负、和为 1 的分数,每个分数对应一个专家。

真正执行的时候,往往不是把 token 发给所有专家再加权,而是只取分数最高的 top-k 个专家(比如 top-2),其余专家直接跳过。这个"只挑 k 个"的动作,就是稀疏激活的由来:

y = ∑ i ∈ TopK ( g ( x ) ) g i ( x ) ⋅ E i ( x ) y = \sum_{i \in \text{TopK}(g(x))} g_i(x) \cdot E_i(x)y=i∈TopK(g(x))∑​gi​(x)⋅Ei​(x)

E i E_iEi​是第i ii个专家(通常就是一个小型的 FFN 前馈网络),g i ( x ) g_i(x)gi​(x)是它分到的权重。只有被选中的那几个专家被真正计算,其他专家的参数这次压根没被读进显存。


三、一段能跑的伪代码

别被"专家"两个字唬住,一个专家无非就是一层 MLP。用 PyTorch 写个最小可跑的 MoE 层,大概长这样:

importtorchimporttorch.nnasnnimporttorch.nn.functionalasFclassMoELayer(nn.Module):def__init__(self,dim,num_experts,top_k):super().__init__()self.top_k=top_k self.gate=nn.Linear(dim,num_experts)# 门控self.experts=nn.ModuleList([nn.Sequential(nn.Linear(dim,4*dim),nn.GELU(),nn.Linear(4*dim,dim))for_inrange(num_experts)# 每个专家一个 FFN])defforward(self,x):# x: [batch, seq, dim]logits=self.gate(x)# [batch, seq, num_experts]topk_weight,topk_idx=torch.topk(logits,self.top_k,dim=-1)topk_weight=F.softmax(topk_weight,dim=-1)# 只对被选中的专家做归一化out=torch.zeros_like(x)fori,expertinenumerate(self.experts):# 找出本次被分到第 i 个专家的 tokenmask=(topk_idx==i)# [batch, seq, top_k]ifmask.any():idx=mask.nonzero(as_tuple=False)weight=topk_weight[idx[:,0],idx[:,1],idx[:,2]].unsqueeze(-1)out[idx[:,0],idx[:,1]]+=weight*expert(x[idx[:,0],idx[:,1]])returnout

这段代码里最关键的,是那个if mask.any():不是所有专家都会被执行。一个 token 只流进 top-k 个专家,其他专家的forward根本没被调用。这就是稀疏激活落地的样子——省下来的,是真金白银的 FLOPs 和显存带宽。


四、为什么它以前火不起来

MoE 不是新东西,1991 年就有人提了。它真正难的地方不在数学,在工程:

  • 负载不均衡:如果门控"偏心",所有 token 都涌向同一个专家,那个专家就成瓶颈,其余专家闲置。于是要加负载均衡损失,逼门控雨露均沾。
  • 通信开销:在大规模分布式训练里,专家分布在不同 GPU 上,token 要跨卡"投递"给专家,这层 all-to-all 通信一度是噩梦。
  • 训练不稳定:门控收敛不好时,模型会"死专家"——某些专家永远没人用。

DeepSeek 那批工作的价值,很大程度上是把这些工程坑一个个填平了(辅助损失、共享专家、细粒度路由),让 MoE 从"论文里的玩具"变成了"真能上线、真能省钱"的东西。


五、一点顺带的感慨

我写这篇文章时总想起那句老话:不是力气大的人赢,是会用劲的人赢。

模型竞争走到今天,"堆参数"已经不够看了,比的越来越是怎么聪明地组织算力——该全量算的时候全量算,能偷懒的时候绝不多算一个专家。这套"按需激活"的朴素思想,其实跟操作系统按需调页、跟 CPU 的分支预测,是同一件事在不同层级的回声。

技术会变,但"把力气花在刀刃上"这件事,从 1991 年的 MoE 论文到今天的 DeepSeek,一直没变。


想补齐机器学习背后的数学底子(softmax、矩阵、概率分布这些 MoE 的门控都绕不开),推荐 B站【408实验室】的《机器学习数学基础》。

对模型"如何被压小、变便宜"感兴趣的,还可以看看我之前写的两篇:为什么大模型从 14G 缩到 4G,还能照样"聪明"?——量化,一次讲透 和 小模型为什么突然这么能打(端侧 AI)。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询