详细解释
Mixture of Depths(MoD,深度混合 / 深度稀疏路由) 一句话定义:MoE(混合专家)是「宽度方向做稀疏:每个 token 只挑几个专家 FFN 做计算、其余跳过」;MoD 是「深度方向做稀疏:每个 token 只挑几层 Transformer 层做计算、其余层直接跳过 copy 上一层输出」。MoE 让你能用很大的总参数量但只激活很少;MoD 让你能用很深的总层数(比如 128 层)但平均每个 token 只走其中 32-64 层,节省 30-50% 的训练和推理 FLOPs,最终达到「同样 FLOPs 预算下 MoD 稠密模型比普通稠密模型深 2 倍、效果好 5-10%」的效果。
Google DeepMind 2024 年 3 月的《Mixture of Depths: Dynamically Allocating Compute in Deep Transformers》是开山之作:他们训练了一个 8B 参数、64 层的 MoD 模型(每个 token 平均路由通过 32 层),在相同训练 FLOPs 下,效果显著优于 32 层同参数量普通稠密 Transformer,甚至追平了 FLOPs 是自己 2 倍的 64 层普通稠密模型。Gemini 2 系列已经内部大规模采用 MoD 架构,这也是为什么 Gemini 2 Flash 推理速度特别快的原因之一。
唯元智创 的推理引擎已经原生支持 MoD 架构模型的加速:自动把 MoD 路由器的跳过操作编译成零开销 branch-free 代码,在 A100 上路由判断延迟 <1µs,客户上线 MoD 模型后实际端到端延迟比同参数量普通模型低 40%。
MoD vs MoE:宽度稀疏 vs 深度稀疏对比表
| 维度 | MoE(Mixture of Experts,宽度稀疏) | MoD(Mixture of Depths,深度稀疏) | 推荐组合方式 |
|---|---|---|---|
| 稀疏发生在哪 | 每层内部 FFN 维度:N 个专家选 K 个(如 8 选 2) | 层与层之间:L 层选 C 层走、L-C 层跳过(如 64 层选 32) | 两者叠加:MoE 每层选专家 + MoD 选层,最大稀疏 |
| 每个 token 激活参数量 | 取决于 top_k 专家数,通常总参数的 1/N 到 2/N | 取决于 router_capacity(选几层),通常总层的 40-60% | Gemma 2、GPT-4o 推测双开 |
| 路由难度 | 高:路由器必须在每层给 token 挑专家,负载均衡难做 | 低:路由器只需要判断「重要 token 多走几层、不重要 token 少走几层」,负载均衡天然容易 | MoD 路由实现比 MoE 简单 |
| 节省 FLOPs 比例 | 训练/推理都省 50-85%(总参数量 8 专家,激活 2 个 = 省 75%) | 训练/推理都省 30-60%(64 层平均走 32 层 = 省 50%) | 两者叠加:8 专家 MoE + MoD = 省 90% FLOPs 以上 |
| 典型实现 | Mixtral 8x7B, Grok 1 8x70B, GPT-4 (推测) | Gemini 2 Flash, RecurrentGemma | 2024 年后新大模型几乎都至少有一个 |
| 最大的工程坑 | 专家负载均衡(Expert Dropout、Load Balancing Loss),否则 1 个专家干 80% 活 | 路由器容量约束(Capacity Constraint),否则某层 token 挤爆 | 两者都需要容量约束 + 辅助损失 |
MoD 架构的两个核心设计细节(看懂就等于懂了 MoD)
细节 1:路由器 Router 只输出「哪些 token 走这一层」的二值 mask,而不是「跳过多少层」。很多初学者误解 MoD 是「第 1 个 token 路由走 1-16 层、第 2 个走 17-32 层」——不对。正确做法是每一层都有一个独立的 tiny router(通常就一个线性层):对该层输入的所有 token 计算一个「重要度分数 s ∈ [0,1]」,然后取该层容量比例 capacity(比如 50%)的 token(s 分最高的那一半)在这一层正常走 Attention + FFN 计算;剩下 s 分低的一半 token 直接跳过 Attention+FFN,输出 = 输入 + 0(也可以加一个可学习的层缩放系数)。所以一个 64 层 MoD 模型有 64 个 router(每层一个),每个 token 平均被 32 层选中走计算、32 层跳过。容量参数 capacity 是 MoD 最关键的超参:0.5 = 省 50% FLOPs。
细节 2:Capacity Constraint + Auxiliary Loss 防止路由器「全选/全不选」。 MoD 路由器很容易学坏——如果某个 token 很模糊(比如一个停用词「的」),路由器倾向于「所有层都让它跳过」省计算,或者反过来所有层都让它走,导致容量波动。DeepMind 原文加了两个机制:(1) 硬容量约束:每层必须严格选 capacity 比例的 token,多了少了都不行,用 top-k(capacity*N) 硬截断;(2) 辅助损失 L_aux:对 router 的输出加一个「token 重要度分布尽量均匀」的正则损失 + 「每个层被选中的 token 数量方差尽量小」的正则损失。这两个加起来占总 Loss 的 1% 左右,防止路由器坍缩成全 0 或全 1。