You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CHANGELOG.md
+6Lines changed: 6 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,6 +8,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8
8
## [Unreleased]
9
9
10
10
### Added
11
+
-**MoE router z-loss** (`moe_router_z_loss_weight`, ST-MoE style). An optional penalty on the router's pre-softmax logits — per MoE layer `mean_token(logsumexp(router_logits))²` — summed across layers and added to the training loss as `moe_router_z_loss_weight × z_loss`. It keeps router logits from growing without bound, targeting *logit-growth stability* (not load balance — that's the aux loss). Default `0.0` is off: the term is never added, so training, outputs, and gradients are unchanged. `z_loss` is a plain attribute like `aux_loss` (not a buffer/parameter), so it never enters `state_dict` — checkpoint-safe.
12
+
-`kempnerforge/config/model.py`: `moe_router_z_loss_weight: float = 0.0` (with a non-negativity check).
13
+
-`kempnerforge/model/router.py`: both `SoftmaxTopKRouter` and `SigmoidTopKRouter` set `self.z_loss = (logsumexp(logits, dim=-1) ** 2).mean()`.
14
+
-`kempnerforge/model/moe.py` / `transformer.py`: `MoEMLP.z_loss` exposes the per-layer value; `Transformer.get_moe_router_z_loss()` sums it across MoE layers (mirrors `get_moe_aux_loss()`).
15
+
-`scripts/train.py`: adds `moe_router_z_loss_weight × z_loss` to the loss on both forward paths (gated on `weight > 0`) and logs `moe/router_z_loss`.
16
+
- Tests: `tests/unit/test_config.py` (default, rejects negative) and `tests/unit/test_moe.py` (z-loss computed; scales with the coefficient).
11
17
-**Fine-grained MoE experts** (`moe_expert_ffn_multiplier`). Decouples each expert's FFN hidden width from the dense FFN: the per-expert hidden dim is `computed_ffn_hidden_dim × moe_expert_ffn_multiplier`, rounded to a multiple of 16. The default `1.0` is a no-op (each expert is a full dense FFN, zero behavior change); set `0.5` for fine-grained experts so top-2 routing matches the dense FFN's activated FLOPs (`2 × F/2 = F`) while adding total capacity — the DeepSeekMoE recipe. Applies to routed and shared experts wherever they are built (`build_moe` and MoMa's `ExpertChoiceMoE`).
12
18
-`kempnerforge/config/model.py`: `moe_expert_ffn_multiplier: float = 1.0` (with a positivity check) and a `computed_expert_ffn_hidden_dim` property; `num_params_estimate` accounts for the smaller experts.
13
19
-`kempnerforge/model/{moe,moma,mot,transformer}.py`: experts are built at `computed_expert_ffn_hidden_dim` instead of the dense FFN width.
|`moe_router_z_loss_weight`|`0.0`|`>0` adds the ST-MoE router z-loss `(logsumexp logits)²` to stabilize router logits (see [Aux loss and balancing](aux-loss-and-balancing.md)) |
0 commit comments