当专家数量比较多时,不是通过一次 gate + topk 就选出来 K 个专家,而是通过一种【两阶段专家】的方式:先组内竞争,再组间竞争。

比如说对于 deepseek v3,其配置中包含以下专家配置:

组内筛选与打分

  1. 输入:Token 表示 X
    • 形状:[num_tokens, num_experts]
    • 每个 token 对每个专家有一个初始的“兴趣度”分数。
  2. 分数归一化与校正
    • S = sigmoid(X):将原始分数映射到 (0, 1) 区间,作为基础专家权重。
    • S_corrected = S + correction_bias:引入一个可学习的偏置项,用于调整专家选择的倾向性(例如,缓解专家负载不均衡)。
  3. 分组与组内竞争
    • 将 num_experts 个专家均匀分为 n_group 组。
    • 形状变换:S_corrected 从 [num_tokens, num_experts] 变为 [num_tokens, n_group, num_experts_per_group]。
    • 组内打分:在每个组内,为每个 token 选取 Top-2 的专家,并将它们的分数求和,作为该组的“组得分”。
    • 输出:组得分矩阵,形状为 [num_tokens, n_group, 1]。这代表了每个 token 对每个组的“兴趣度”。

组间竞争与专家选择

  1. 选择候选组
    • 基于组得分,为每个 token 选择得分最高的 Top-4 个组。
    • 输出形状:[num_tokens, 4](存储选中的组索引)。
  2. 生成组掩码并映射到专家
    • 创建一个组掩码 group_mask,形状为 [num_tokens, n_groups, 1]。对于每个 token,被选中的组对应位置为 1,否则为 0。
    • 将组掩码扩展(expand)到专家维度,得到初始的专家候选掩码 expert_candidate_mask,形状为 [num_tokens, num_experts, 1]。其逻辑是:一个专家所属的组若被选中,则该专家进入候选池。
  3. 最终专家筛选
    • 在候选专家池(由掩码定义)内,为每个 token 进行全局 Top-8 筛选。这确保了最终从所有被选中的组里挑出最优秀的 8 个专家。
    • 权重计算:最终这 8 个专家的融合权重,使用第一阶段计算的原始 sigmoid 分数 S(而非校正后的分数或组得分),以确保权重的直接性与可解释性。