1. Deepseek MoE 的结构
DeepSeek-V3 的 MoE 架构延续并优化了其特有的 DeepSeekMoE 设计,并引入了 无辅助损失的负载均衡(Auxiliary-loss-free Load Balancing 策略。
1. 整体结构公式
对于 Token \(t\) 层的输入向量 \(\mathbf{u}_t\)(即 Attention 层的输出),MoE 层的输出 \(\mathbf{h}_t^{\prime}\) 定义为:
其中 \(\text{MoE}(\mathbf{u}_t)\) 由 共享专家(Shared Experts 和 路由专家(Routed Experts 两部分组成:
- \(N_s\):共享专家的数量。
- \(N_r\):路由专家的数量, \(=256\)。
- \(g_{i,t}\):第 \(i\) 个激活专家的门控增益(Gating Value)。只有\(K_r\)个激活专家。
- \(\text{FFN}(\cdot)\):标准的 Feed-Forward Network。
- \(K_r\):每个 token 激活的路由专家数量(Top-K)。
2. 专家内部结构 (FFN)
DeepSeek-V3 采用 SwiGLU 作为专家内部的激活函数。对于任意专家 \(i\),其计算公式为:
维度定义: * 输入向量 \(\mathbf{u} \in \mathbb{R}^{d}\),其中 \(d = 7168\)。 * \(\mathbf{W}_{up}, \mathbf{W}_{gate} \in \mathbb{R}^{d_{inter} \times d}\):升维矩阵。 * 对于路由专家,\(d_{inter} = 2048\) which is the moe_intermediate_size。 * 对于共享专家,\(d_{inter} = 2048\)(V3 中共享专家维度与路由专家一致,但始终激活)。 * \(\mathbf{W}_{down} \in \mathbb{R}^{d \times d_{inter}}\):降维矩阵。
这里 \(\odot\) 是两个维度为2048的向量的逐个元素相乘。
3. 路由与门控机制 (Routing & Gating)
DeepSeek-V3 采用了 无辅助损失(Aux-loss-free) 的负载均衡方案。
(1) 计算亲和力分数 (Affinity Score)
对于 token \(t\),计算其对第 \(i\) 个路由专家的亲和力:
其中,\(\mathbf{e}_i \in \mathbb{R}^{d}\) 是第 \(i\) 个专家的质心向量(Centroid)。
对所有的专家,他就等价于跟一个 \(\mathbf{u}_t\) 跟一个 Centroid 矩阵 \(\mathbf{W}_{route}\)相乘,\([\mathbf{s}_{1,t}; \mathbf{s}_{2,t}; \cdots ; \mathbf{s}_{N_r,t}] = \mathbf{u}_t \mathbf{W}_{route}\)。
这里 \(\mathbf{W}_{route} \in \mathbb{R}^{d \times N_r} = \mathbb{R}^{7168 \times 256}\).
(2) 引入偏置项 (Load Balancing Bias)
为了实现负载均衡而不损害性能,模型在推理和训练中维护一个动态偏置 \(b_i\):
* 如果专家 \(i\) 过载,算法会减小 \(b_i\); * 如果专家 \(i\) 空闲,算法会增大 \(b_i\)。
(3) Top-K 选择与归一化
选择 \(s'_{i,t}\) 最高的 \(K_r = 8\) 个专家。最终的门控值 \(g_{i,t}\) 是通过对原始 \(s_{i,t}\) 进行归一化得到的:
注意:计算 \(g_{i,t}\) 时使用的是不含偏置的 \(s_{i,t}\),以保证数学上的纯净性。
4. 关键维度与参数汇总
根据官方参数设置,DeepSeek-V3 的 MoE 维度如下:
| 参数项 | 符号 | 数值 | 备注 |
|---|---|---|---|
| 模型隐藏层维度 | \(d\) | 7168 | 输入/输出向量维度 |
| 路由专家总数 | \(N_r\) | 256 | 总共有 256 个可选专家 |
| 激活专家数 | \(K_r\) | 8 | 每个 token 选 8 个专家 |
| 共享专家数 | \(N_s\) | 1 | 始终激活的专家 |
| 专家中间层维度 | \(d_{inter}\) | 2048 | SwiGLU 升维后的维度 |
| 专家质心矩阵 | \(\mathbf{E}\) | \(256 \times 7168\) | 用于计算路由分数 |
| 激活参数量 | - | 37B | 每次推理实际调用的参数 |
| 总参数量 | - | 671B | 包含所有专家矩阵 |
5. 总结:DeepSeekMoE 的精髓
- 细粒度专家(Fine-Grained Experts): 将 \(d_{inter}\) 设为 2048(远小于传统 MoE 的 8192 或更高),通过增加专家数量 \(N_r\) 来提高知识的覆盖面和专业化程度。
- 共享专家(Shared Experts): 通过 \(N_s\) 捕获公共知识,减少路由专家之间的信息冗余。
- Aux-loss-free 策略: 传统的辅助损失(如 Switch Transformer 的 load balance loss)会约束路由分布,导致性能下降。DeepSeek-V3 通过调节偏置 \(b_i\) 来平衡流量,使得 Loss 专注于预测准确性,从而在 671B 规模下依然保持极高的性能。
2. DeepSeek MoE 的参数数量
1. FFN 变换矩阵的参数量 (单层)
对于每一个专家(无论是共享还是路由),它都包含三个主要的变换矩阵(基于 SwiGLU 结构): * \(\mathbf{W}_{up}\): \(d_{inter} \times d = 2048 \times 7168\) * \(\mathbf{W}_{gate}\): \(d_{inter} \times d = 2048 \times 7168\) * \(\mathbf{W}_{down}\): \(d \times d_{inter} = 7168 \times 2048\)
根据 DeepSeek-V3 的参数设置: * \(d = 7168\) * \(d_{inter} = 2048\) * 共享专家数 \(N_s = 1\) * 路由专家总数 \(N_r = 256\)
单个专家的 FFN 参数量为:
所有专家(1 个共享 + 256 个路由)的 FFN 总参数量为:
2. 路由中心(Router Centroids)(单层)
除了 FFN 矩阵,MoE 层还有一个关键组件:Router。 它需要一套参数来决定每个 token 该去哪个专家。DeepSeek 使用的是向量内积来计算亲和力,因此每个路由专家都有一个对应的“质心”向量 \(\mathbf{e}_i\)。对所有的256个路由专家,就是上面的 \(\mathbf{W}_{route}\)
- \(\mathbf{W}_{route}\): 路由参数量 = 专家数 \(\times\) 模型维度 = \(256 \times 7168 \approx 1.83 \text{ M (每层)}\)
虽然这部分参数相比 FFN 矩阵非常小,但在严谨的参数统计中是独立存在的。
3. 完整的 MoE 层参数公式(单层)
完整 MoE 层的总参数量(不含 Attention 部分),公式应该是:
代入数值:
4. MoE 总参数量
DeepSeek-V3 一共有 58 层 的MoE。简单相乘,得到 MoE的总参数为:\(58 \text{ 层} \times 11.32 \text{ B/层} \approx 656.6 \text{ B}\)
DeepSeek 官方公布的总参数量是 671B,可以看出模型的主要参数都是在MoE部分。 余下来的差别来自于: 1. MLA(注意力机制)层也会占用一部分参数。 2. Embedding 层(约 0.9B)和输出层。 3. 实际上,DeepSeek 在 \(671\)B 的总规模下,对某些维度进行了微调,以确保模型在 37B 激活参数的情况下达到最优性能平衡。