漫画DeepSeekMoE--借助Excel理解它:从原理到代码实现 精华

发布于 2025-7-30 07:00
浏览
0收藏

在深度学习的广阔天地里,我们时常追求模型的高效与精准。精兵简政,这一理念在专家混合架构MoE中得到了淋漓尽致的体现。MoE,即Mixture of Experts,专家混合架构,它的核心思想在于将复杂的任务拆解为多个子任务,每个子任务由专门的“专家”模型负责处理。

这种架构的优势在于,它可以根据输入数据的不同特点,动态地选择最合适的专家进行处理,从而在保证模型性能的同时,降低了计算复杂度和资源消耗。正如古人所言,“多兵不如善用兵”,MoE正是通过优化资源配置,实现了表达力的大幅增强。

在接下来的内容中,我们将深入探讨MoE的具体实现原理、应用场景以及未来的发展趋势,以期在这一领域有更深入的理解和探索。

原来这就是专家混合架构

让我们继续借助第2章中的案例,深入了解DeepSeek所带来的创新之处。

在春秋末年,吴国的杰出将领孙武先生负责训练和指挥军队。军营中搭建了一座名为“点将台”的高台。每天黎明时分,全军列队。随着号角的响起,数万名士兵整齐划一地排列,静候孙将军挑选将领,带领他们奔赴战场。

漫画DeepSeekMoE--借助Excel理解它:从原理到代码实现-AI.x社区

而这,正是后人口中的“稀疏点将制”——如今我们在人工智能中称之为MoE。这套制度背后,蕴含着孙武对兵力调度的极致智慧,也正好道出了MoE模型为何强大又高效的原理。

将多兵不如善用兵:表达力大幅增强

孙武的军营中,将领如云,人才济济。营外,是经历过百战的精兵强将——左侧有擅长夜袭的田将军,右侧有精通水战的吕都尉,更有深谙兵法、洞察敌情的钟谋士。每位将领都各自统领着万人的军队,他们都是能够独当一面的杰出人才。然而,孙武从不一次性派遣所有将领。他深知:兵力众多并不总是优势,战场上的关键在于“用人得当”。因此,每当敌情发生突变,他便登上点将台,从众多将军中挑选出最适合的两位来应对敌军。在出战之日,虽然看起来只有两支队伍奔赴前线,但实际上,这是整个将军团队智慧的体现。

漫画DeepSeekMoE--借助Excel理解它:从原理到代码实现-AI.x社区

这正体现了MoE模型的运作原理:尽管整个网络由众多“专家”组成,每个专家的参数数量可达到数亿,但在进行推理时,通常只激活其中两个或少数几个专家。以一个普通的 MLP 层为例,其参数量为100M;而在 MoE 层中,即便有10个专家,每个专家的参数量也是100M,总计参数量达到 1B;然而,在实际操作中,每次仅启用2个专家,因此实际的计算成本保持在200M,大大提高了用兵的效率。

孙武布兵如 MoE 布网:整军备战,局部出击,智取胜于力拼。

稀而不弱:高效稀疏调度,轻装上阵

孙武实施“点将制”,这不仅体现了他的智慧,更源于他需要迅速调配兵力、轻装上阵。他深知兵贵神速,多余的兵力只会拖慢进军的步伐。每当调动军队出征,他仅需向军令官轻声下令:“点将谋士、田将军。”军令如山,其他人员保持不动,唯独这两员大将迅速整顿部队。

漫画DeepSeekMoE--借助Excel理解它:从原理到代码实现-AI.x社区

这与在 MoE 模型中引入的稀疏前向传播极为相似:通过门控机制,仅激活 Top-k 个专家,而其他专家则保持静默状态。这样,每次只需计算一小部分子网络,从而节省了内存和计算资源;同时避免了重复学习,提升了专家的特化程度。这正是稀疏机制的核心所在:确保专家仅在必要时参与计算。

调兵无上限:专家可扩展,模型更灵活**

随着敌军战术的不断演变,孙武不再满足于现有的十位将领。他开始着手扩充军队,吸纳更多的专家型将军。然而,这位智者并未安排所有将领同时进行训练或出征。他深知,在战斗中每次只需两位最合适的将军出战(参见下图),即使军营中拥有百将千帅,其目的也是为了在面对各种不同的战场时,能够有更多的选择和更精确的调度。

漫画DeepSeekMoE--借助Excel理解它:从原理到代码实现-AI.x社区

这正是 MoE 模型可扩展性的体现:在模型训练或性能不佳时,可以通过新增专家(子网络)来扩充“知识容量”;但每次计算仍然保持稀疏,仅激活最相关的 Top-k 专家,不增加实际计算负担;随着专家数量的增加,模型能适应更多任务场景,迁移性更强。孙武并非盲目扩军,而是精准备战;MoE 亦非盲目堆叠参数,而是理性稀疏计算的艺术。

点将有术:门控网络如统帅

尽管将军众多,但真正能够洞悉敌情、善于用人者,正是站在点将台上的孙武本人。

漫画DeepSeekMoE--借助Excel理解它:从原理到代码实现-AI.x社区

在 MoE 模型中,门控网络(Gating Network)扮演着至关重要的角色。每当输入一句话或一个样本,它便负责判断当前最适合处理该输入的专家是哪一位,并激活相应的子网络。例如:输入一句诗词 → 选择文学类专家;输入一段代码 → 激活程序专家;输入医学记录 → 调用医学专家进行处理。门控网络所学习的,不仅仅是“谁能完成任务”,更是“谁完成得最为出色”。这与孙武多年征战后练就的“点将直觉”如出一辙。

MoE(专家混合架构)就像孙武兵法中的用兵之道,是一种兼顾力量与智慧的策略工具:

  • 兵多将广:模型参数多,具备强大的表达能力;
  • 点将得当:通过稀疏激活,精准调度专家,降低计算成本;
  • 弹性扩军:可根据任务灵活扩展或裁剪专家,适应性强;
  • 门控统帅:由门控机制挑选最合适的专家,高效又精准。

MoE 的关键不在于“人多”,而在于“选对人、用对人”,让模型从“全员出动”进化为“精兵出击”,大幅提升了效率与智能表现。

从撒豆成兵到撒豆成精:DeepSeek MoE的数学推演

让我们通过结合Excel表格和DeepSeek MoE的公式,共同探索机器学习领域中一个非常重要的创新——DeepSeek MoE。下图是从传统的MoE架构,到Deepseek MoE架构的演变。

漫画DeepSeekMoE--借助Excel理解它:从原理到代码实现-AI.x社区

在人工智能领域,随着模型规模的不断膨胀和复杂性的增加,管理这些“知识专家”变得异常棘手。

若每次任务都激活所有专家,不仅会消耗大量电力,还会导致模型运行缓慢,造成资源的浪费。

幸运的是,一些智慧的科学家们创造了Mixture of Experts(MoE),它宛如一位指挥官,仅挑选出最适宜的少数专家参与每一次的任务。

然而,DeepSeek团队意识到,传统的MoE仍有提升空间。因此,他们提出了一个升级版——DeepSeekMoE。这个创新设计融合了两大核心策略:

  • 细粒度专家分割(图b)
  • 共享专家隔离(图c)

这两大策略,旨在实现一个共同目标:

使每位专家更加专业,整个系统运行更高效、更节约、更智能。

细粒度专家分割

想象一下,如果你要组建一个救援小组。传统方法是,每个人都是"全能战士":又要能开船、又要能攀岩、又要懂医疗……虽然厉害,但一旦出任务,总有人做得不好,因为术业有专攻。更聪明的方法是:把任务细分,组建小而专的队伍。 比如有人专攻救火,有人专攻山地搜救,有人专攻医疗急救。这样一来,每个人只专注在自己最擅长的领域,整体效率大大提高!

在 DeepSeekMoE 中,科学家们也采用了类似的办法。他们做了两件事:

一是把每个原本的大型FFN模块,切成_m_个更小的专家;二是为了保持整体运算量不变,每次选择的小专家数量也同步乘_m_。

举个具体例子:假设以前有16个大专家,每次从中选择2个来工作,组合方式只有120种。

现在每个专家被切成4个小专家,一共有64个小专家,每次选择8个,组合方式一下子飙升到惊人的44亿种(准确是4,426,165,368种)。

这种变化带来了巨大的好处:

  • 输入的信息可以被更细致地分配到最适合的小专家;
  • 每位小专家负责更窄、更专精的领域;
  • 整个模型变得更聪明、响应更快。

关键点提醒:虽然专家变小了,数量变多了,但总的参数量和计算量是一样的哦,不用担心模型负担加重!

共享专家隔离

还有一个问题:在现实任务中,有些基本知识是大家都会用的。比如,不管做什么任务,基本的沟通能力、常识判断都必不可少。如果让每个小专家都自己去重新学习这些基础知识,那就太浪费了。所以 DeepSeekMoE 引入了第二个绝招——共享专家隔离

具体来说:预留出_Ks_个专家,专门作为“公共知识库”;所有输入数据,不管走不走路由器,都必须经过这批共享专家;剩下的动态专家,才由路由器根据需要动态选择。

这样设计带来了双重好处:

  • 公共知识集中处理,每位小专家不用重复存储常识,大大减少了参数冗余;
  • 非共享专家可以专心做细分领域,比如有人专门研究生物学,有人专门研究物理学,各自深耕。

注意:因为共享专家是必选的,所以为了保持整体计算量稳定,动态选择的小专家数量会相应减少 _Ks_个。

它们的数学公式就如下所表示:

漫画DeepSeekMoE--借助Excel理解它:从原理到代码实现-AI.x社区

wpsoffice

我们可以把它们投影到我们的图中:

漫画DeepSeekMoE--借助Excel理解它:从原理到代码实现-AI.x社区

DeepSeekMOE

接下来尝试在Excel中实现它们,参见下图。

漫画DeepSeekMoE--借助Excel理解它:从原理到代码实现-AI.x社区

接下来再初始化一下路由权重,参见下图:

漫画DeepSeekMoE--借助Excel理解它:从原理到代码实现-AI.x社区

其中,_E_1 代表的是共享专家,_E_2~_E_4代表的是路由专家。

我们计算路由的公式是这样的:

漫画DeepSeekMoE--借助Excel理解它:从原理到代码实现-AI.x社区

/Users/i/Library/Containers/com.kingsoft.wpsoffice.mac/Data/tmp/wpsoffice.hBKTQpwpsoffice

想象一下,你经营着一个聪明的AI事务所,里面有许多聪明的“专家”——每位专家擅长不同的领域。每天,系统会接收到一些“任务”,每个任务由多个特征组成。你要做的,是判断哪些专家对哪个任务最感兴趣,从而派出最合适的人来处理问题。
我们首先有一组输入任务,它们由一个包含 6 个 Token(也可以理解为词或片段)的矩阵组成。每个 Token 拥有 5 个特征。换句话说,你眼前有一个 5 行 × 6 列的表格,每一列代表一个任务点,每一行是它的某个描述维度。
另一方面,AI事务所的专家团体(比如 E1、E2、E3 和 E4)每位都各有专长。他们的专长可以被表达成一个“兴趣向量”——也就是他们关注每种特征的程度。

这里用了 Excel 的一个函数来评估专家与任务的匹配度:

=MMULT(P152:T154, V141#)

这行公式的含义是:让系统把每一位专家的兴趣向量,与每个任务的特征做一次点积运算,得出一个“匹配打分表”。它就像是每位专家在看每个任务时会说:“这个任务我多感兴趣。”
在数学上,它可以被写成:

S = E · X

其中:
E 表示专家矩阵,每一行是一位专家对五个特征的偏好;
X 表示输入矩阵,每一列是一项任务的五个特征;
S 就是输出结果,也就是专家对每个任务的打分表。
接下来再用SoftMax对它们进行进一步的计算,参见下图:

漫画DeepSeekMoE--借助Excel理解它:从原理到代码实现-AI.x社区

Softmax 是深度学习和 AI 模型中非常常用的一个“变魔法”的函数,它的主要作用可以用一句话概括:

把一堆“分数”变成“比例”,让它们代表“谁说话声音更大”。

用简单例子说:

假设你有三个专家对一个任务的打分是:

专家 A:5

专家 B:2

专家 C:1

这只是相对的“分数”,不能直接用作权重(因为它们可能太大、太小、甚至为负数)。

这时候,Softmax 会这样做:

把所有分数指数化(变正、放大差距)

再除以总和,让它们变成 0~1 之间的比例

且所有比例加起来刚好等于 1(像概率)

比如,softmax 后结果可能是:

A:0.84

B:0.11

C:0.05

接下来对专家得分进行排序,也就是对我们上面的值按列进行排序,选择Top 3的专家。下图呈现了通过排序(SORT(...,,-1))得到的每列专家打分的降序排列结果,这一过程常用于混合专家模型(MoE)中进行Top-K路由选择。

漫画DeepSeekMoE--借助Excel理解它:从原理到代码实现-AI.x社区

其中Excle的公式如下:

=SORT(AC151:AC154,,-1)

图表内容揭示了一个4行×6列的打分矩阵,其中每列代表一个Token,每行代表一个专家。该矩阵列出了每个Token对应所有专家的亲和力得分,并且每列得分均按从高到低排序。

为何要进行此类排序?在MoE模型中,我们并非让所有专家同时“发言”,而是让每个Token仅选择得分最高的前K个专家参与处理。这一过程被称为:

Top-K Routing:每个Token路由至最匹配的K个专家。

此排序矩阵的作用是什么?你使用的是Excel的函数:=SORT(...,,-1),意味着对每列进行降序排列。

排序后的矩阵便于快速判断哪些专家进入了Top-K。

举个例子:Token5(第 5 列),原始打分(排序前)可能是:

专家 分数

E1 1.000000000

E2 0.867739153

E3 0.521375896

E4 0.407783590

排序结果是:

1.000000

0.867739

0.521376

0.407784

所以 Top-3 专家就是:E1、E2、E3

这里,我们同时对得分用 Softmax 做归一化,然后才进行的排序。接下来再对选出来的专家,进行运算:

得到最终的 Gate 权重

漫画DeepSeekMoE--借助Excel理解它:从原理到代码实现-AI.x社区

wpsoffice

对应的Excel公式:

=IF(AC151:AH154 >= AK153:AP153, AC151:AH154, 0)

下图是……

漫画DeepSeekMoE--借助Excel理解它:从原理到代码实现-AI.x社区

这张图非常清晰地展示了 Mixture of Experts 中的 Top-K 路由过程,并通过 Excel 函数 =IF(...) 实现了“打分保留 / 剔除”的门控逻辑。下面我来解释这段公式和操作背后的含义。

这段公式的意思是:

“对于每个专家对每个 Token 的打分,如果它进入了 Top-3(即分数 ≥ 该 Token 第 3 高的分数),那么保留原始值;否则设为 0。”

对应的数学表达形式,这是我们之前讲过的 “门控函数” 的选择形式:

漫画DeepSeekMoE--借助Excel理解它:从原理到代码实现-AI.x社区

wpsoffice

其中:

s:原始亲和力得分(专家打分)

g:门控值(控制专家输出权重)

红色区域(AK153:AP153):每列 Top-3 分数底线 每个 Token 的第三高分,用于筛选

黄色门控区域,满足条件的得分保留,否则为 0。

为什么这么做?这个过程实现了 Top-K 路由的门控过滤机制:

它不是直接根据“谁排第几名”来选专家,而是对每列找出 Top-K 的最小分数,然后保留所有大于等于这个分数的专家,这样做的好处是便于向下使用 Softmax(因为保留的是原始 score)。下图是……

漫画DeepSeekMoE--借助Excel理解它:从原理到代码实现-AI.x社区

这里我们可以看到因为专家1是共享专家,所以所有Token都参与了运算。

漫画DeepSeekMoE--借助Excel理解它:从原理到代码实现-AI.x社区

漫画DeepSeekMoE--借助Excel理解它:从原理到代码实现-AI.x社区

漫画DeepSeekMoE--借助Excel理解它:从原理到代码实现-AI.x社区

其他专家灰色的区域都没有参加计算,这样就大大节约了计算资源。

混沌初开,众神归位:DeepSeek MoE架构的代码实现

DeepSeek MoE架构的代码实现基于上述的逻辑和机制,将复杂的模型运算高效地组织起来。代码的核心在于如何精准地控制专家的选择和计算资源的分配。在DeepSeek中,专家们被组织成一个多层的结构,每一层都负责不同的任务,但都遵循着Top-K路由的门控过滤原则。

代码实现的关键步骤包括:首先,定义每个专家的计算函数和参数;其次,通过矩阵运算确定每个Token对应的专家得分;然后,根据Top-K路由机制,筛选出得分高于或等于每列Top-K最小分数的专家;最后,对这些筛选出的专家进行Softmax运算,以确定每个专家在最终决策中的权重。

DeepSeek MoE架构的代码实现不仅优化了模型的性能,还大大提高了计算效率。通过精准地控制专家的选择和计算资源的分配,DeepSeek能够在保证模型精度的同时,显著降低计算成本和时间。这使得DeepSeek在处理大规模数据和复杂任务时具有显著的优势。

下面来看看笔者的实现代码:

引入需要的库,示例代码如下:

import torch

import torch.nn as nn

import torch.nn.functional as F

定义单个前馈专家,实现代码如下:

class FeedForwardExpert(nn.Module):

def __init__(self, d_model):

super().__init__()

self.net = nn.Sequential(

nn.Linear(d_model, d_model),

nn.ReLU(),

nn.Linear(d_model, d_model),

) # 简单两层 MLP,含 ReLU

def forward(self, x):

return self.net(x) # 前向传播

定义 DeepSeekGroupedMoE 模块

class DeepSeekGroupedMoE(nn.Module):

def __init__(self, d_model, num_groups, experts_per_group, top_k):

super().__init__()

self.d_model = d_model

self.num_groups = num_groups # 分几组

self.experts_per_group = experts_per_group # 每组几个专家

self.total_experts = num_groups * experts_per_group

self.top_k = top_k # 每个 Token 在组内选几个专家

# 所有专家(按组摊平)

self.experts = nn.ModuleList([

FeedForwardExpert(d_model) for _ in range(self.total_experts)

])

# 一个共享专家(所有 Token 都经过)

self.shared_expert = FeedForwardExpert(d_model)

# 路由器部分

self.group_router = nn.Linear(d_model, num_groups) # 负责选择组

self.intra_router = nn.ModuleList([

nn.Linear(d_model, experts_per_group) for _ in range(num_groups) # 每组内部的路由器

])

前向传播逻辑

def forward(self, x): # 输入 x: [B, T, D]

B, T, D = x.shape

x_flat = x.view(-1, D) # [B*T, D] 扁平化为 Token 维度

# 步骤1: 分组路由(决定每个 Token 属于哪个 group)

group_logits = self.group_router(x_flat) # [B*T, num_groups]

group_idx = group_logits.argmax(dim=-1) # 每个 Token 属于哪个组 [B*T]

# 步骤2: 在组内选择 top-K 个专家

output = torch.zeros_like(x_flat) # 初始化输出 [B*T, D]

for g in range(self.num_groups): # 遍历每个组

mask = (group_idx == g) # 选择属于第 g 组的 Token

if mask.sum() == 0:

continue # 当前组没有 Token,跳过

x_g = x_flat[mask] # 提取该组 Token,形状 [N_g, D]

intra_scores = self.intra_router[g](x_g) # 对每个 Token 给组内专家打分 [N_g, experts_per_group]

# 选择 top-k 个专家

topk_vals, topk_idx = torch.topk(intra_scores, self.top_k, dim=-1)

out_g = torch.zeros_like(x_g) # 初始化当前组输出

for i in range(self.top_k): # 遍历每个 top-k 专家

expert_ids = g * self.experts_per_group + topk_idx[:, i] # 计算全局 expert ID

gate = topk_vals[:, i].unsqueeze(-1) # 获得门控分数 [N_g, 1]

# 对每个 Token 单独调用对应专家

expert_out = torch.stack([

self.experts[expert_id](x_g[j]) # 每个 Token 分别走自己的专家

for j, expert_id in enumerate(expert_ids)

])

out_g += gate * expert_out # 按照 gate 加权相加

output[mask] = out_g # 将该组 Token 的输出插回原位置

#步骤 3: 共享专家输出(所有 Token 都过一遍)

shared_out = self.shared_expert(x_flat) # 所有 Token 共享专家 [B*T, D]

final = output + shared_out # 最终输出为两者相加 [B*T, D]

return final.view(B, T, D) # reshape 回原始形状

在上面的代码清单中,我们对代码进行了尽量详细的注释,相信大家应该可以看得懂。

不过,为了更深入地理解这个模块,我们还是简单总结一下它的工作流程:

首先,输入的序列 x 会被展平成二维的形式 x_flat,这样可以对每个 Token 进行独立的处理。然后,这些 Token 会根据一定的规则(例如通过路由网络)被分配到不同的专家组中。每个专家组会对分配给自己的 Token 进行处理,并输出一个专家输出 expert_out。

接着,这些专家输出会根据 gate(门控机制)进行加权相加,得到加权后的输出 out_g。这个加权的过程实际上是在选择性地融合不同专家的知识,让模型能够更好地处理输入序列。

然后,我们将加权后的输出 out_g 插回到原始序列的对应位置上,得到完整的输出 output。这个步骤确保了即使某些 Token 被分配到了不同的专家组,它们的输出仍然能够按照原始序列的顺序进行组合。

此外,为了让所有 Token 都能够从专家网络中获益,我们还设计了一个共享的专家网络 self.shared_expert。这个网络会对所有 Token 进行处理,并输出一个共享的专家输出 shared_out。这个输出会与前面的 output 相加,得到最终的输出 final。

因此,DeepSeekMoE 模块实际上是一个结合了条件计算和知识蒸馏思想的混合专家系统。它通过对输入序列进行细粒度的分组和处理,以及通过门控机制和共享专家网络进行知识的融合和提炼,从而实现了对复杂任务的高效和准确的建模。

本文转载自 ​AI大模型世界​​​,作者:roclv

收藏
回复
举报
回复
相关推荐