> Hard top-K 路由的未选中专家没有梯度——它永远学不会自己该被选中
MoE 用 topk + softmax(top_k_logits) 做 hard routing 时:
结论先行¶
MoE 用 topk + softmax(top_k_logits) 做 hard routing 时:
未被选中的专家收不到任何梯度信号,因此学不到"我什么时候该被选中"。 路由决策不可微,专家分化只能靠初始化的运气和负载均衡 loss 的推力。
如果你的 MoE"专家没有真正专业化"、"路由退化成固定分配"、 "换了 router 特征也没变化"——先查这条,而不是去调 router 的容量或特征维度。
为什么¶
三个互相纠缠的失效模式,在一个把频率统计当路由先验的 Trie-MoE 上同时出现:
1. 路由信号和任务目标解耦。 路由向量来自频率统计(freq / CTR / info bucket), 但 CTR 预测需要的是特征交互模式。设最优路由 \(r^*(x) = \arg\max_i P(y \mid x, \text{expert}_i)\), 而实现的是 \(r_{\text{trie}}(x) \approx f(\text{freq}(x))\)。 统计先验 ≠ 最优路由,两者的相关性可能本来就很弱—— 而由于第 0 条(没有梯度),router 也没有办法从数据里学着修正这个先验。
2. 负载均衡 loss 和主目标梯度冲突。
lb_loss = self.num_experts * (fraction_per_expert * router_probs).sum()
return bce_loss + lb_loss # 直接相加
当 \(\cos(\nabla\mathcal{L}_{\text{task}},\ \nabla\mathcal{L}_{\text{aux}}) < 0\) 时两者互斥, 表现为负载均衡度和任务指标的跷跷板。 Switch Transformer 的 aux loss 之所以有效,是因为它构成自校正反馈 (过载专家→路由概率下降压力增大);但全程施加它会阻止 router 收敛。
3. 专家没有结构性分化。 所有专家架构完全相同,只靠路由区分。 在没有梯度信号的前提下,"相同架构 + 学不动的 router" 等于"随机分组"。
怎么用¶
先做的诊断(都很便宜):
- 专家利用率直方图。 如果少数专家吃掉绝大部分 token,或者分布完全均匀但 任务指标没提升,说明分化没有发生。
- 梯度冲突量。 记录 \(\cos(\nabla\mathcal{L}_{\text{task}}, \nabla\mathcal{L}_{\text{aux}})\) 的滑动均值。长期为负就说明 aux loss 在拖后腿。
- 路由 ablation:把 router 换成随机固定分配。 指标不掉,说明路由本来就没起作用—— 省下所有调 router 的时间。这一步是整套里性价比最高的。
修法,按代价从低到高:
| 做法 | 解决什么 | 代价 |
|---|---|---|
| aux loss 加权衰减 / 训练后期关掉 | 梯度冲突、router 不收敛 | 一行 |
| top-K 改软路由(全专家加权,或 Gumbel-softmax) | 未选中专家无梯度 | 计算量上升 |
| Expert Choice:专家选 token,而非 token 选专家 | 无梯度 + 负载不均,一起解决 | 中等,要改 batch 组织 |
| 专家结构性异构(不同容量/不同归纳偏置) | 分化不足 | 大 |
Expert Choice 是这里的范式转换:每个专家挑固定数量的 token, 于是负载天然完美均衡(不需要 aux loss,第 2 条冲突消失), 每个 token 可以被多个专家处理,训练收敛速度报告有 2× 以上提升。 代价是需要拿到整个 batch 的偏好矩阵,在线/流式场景不适用。
出处¶
~/Projects/encRec/docs/theoretical_failure_analysis.md(含moe.py:236-247、:258-259、:291-294的代码定位)- 对照的理论来源:Switch Transformer 的 aux loss、PLE 的专家专业化要求、 Expert Choice routing