Fix muon moe dimension numbers - #4843
Conversation
There was a problem hiding this comment.
Code Review
This pull request updates the Muon optimizer utilities to support additional Mixture of Experts (MoE) block variants, including 'routed_experts', 'moe_block', and 'GptOssMlp', as well as prefused 'wi' weights. It also refactors the bias exclusion logic to simplify the path check and adds comprehensive unit tests to verify these changes. There are no review comments, and I have no additional feedback to provide.
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
|
🤖 Hi @RissyRan, I've received your request, and I'm working on it now! You can track my progress in the logs for more details. |
There was a problem hiding this comment.
This pull request successfully resolves issue #4798 by ensuring correct Muon dimension numbers are assigned to Mixture-of-Experts (MoE) models and that all bias variants are correctly excluded from orthogonalization. The implementation is clean, robust, and accompanied by comprehensive unit test coverage verifying all proposed edge cases.
🔍 General Feedback
- Comprehensive Testing: Excellent job adding detailed unit tests covering all target architectures (Qwen3, Qwen3-next, GPT-OSS, and prefused/gate configurations).
- Robust Substring Matching: The group exclusion checks for bias variant substrings (
"bias" in segment) successfully prevents any bias variant from being wrongly subjected to Muon orthogonalization. - Pipeline Parallelism Alignment (Future Scope): In
src/maxtext/utils/pipeline_utils.py(around line 80),is_moe_block_0 = "MoeBlock_0" in path_keysis used to identify MoE blocks. Since you have introduced alternative MoE block names ("routed_experts","moe_block","GptOssMlp"), those names may also need to be recognized inpipeline_utils.pyin a separate follow-up PR to ensure they are handled correctly during scanned pipeline parallelism execution.
| if _is_path_contain_any(("MoeBlock_0", "routed_experts", "moe_block", "GptOssMlp"), path): | ||
| # exclude gate | ||
| if _is_path_contain_any(("wi_0", "wi_1", "wo"), path): | ||
| if _is_path_contain_any(("wi", "wi_0", "wi_1", "wo"), path): | ||
| return mdn((-2,), (-1,)) |
There was a problem hiding this comment.
🟢 Low: Extracting the MoE block names and expert kernel names into variables improves code readability and makes it easier to extend with other MoE architectures in the future.
| if _is_path_contain_any(("MoeBlock_0", "routed_experts", "moe_block", "GptOssMlp"), path): | |
| # exclude gate | |
| if _is_path_contain_any(("wi_0", "wi_1", "wo"), path): | |
| if _is_path_contain_any(("wi", "wi_0", "wi_1", "wo"), path): | |
| return mdn((-2,), (-1,)) | |
| moe_blocks = ("MoeBlock_0", "routed_experts", "moe_block", "GptOssMlp") | |
| if _is_path_contain_any(moe_blocks, path): | |
| # exclude gate | |
| expert_kernels = ("wi", "wi_0", "wi_1", "wo") | |
| if _is_path_contain_any(expert_kernels, path): | |
| return mdn((-2,), (-1,)) |
RissyRan
left a comment
There was a problem hiding this comment.
LGTM at high level, and trying to understand a little bit on tests.
FYI @shuningjin who may have most context of Muon conv
| def test_bias_is_excluded(self): | ||
| self.assertIsNone(muon_utils.transform_logic(("decoder", "dense", "bias"))) | ||
|
|
||
| def test_bias_variant_is_excluded(self): |
There was a problem hiding this comment.
Could you help explain a little bit why those bias to be excluded? or add a comment there?
Also, for a model/config, are you consider all bias? for instance, wondering why GptOss only excludes wo_bias?
Description
This PR updates
maxtext.utils.muon_utils.transform_logicto assignMuonDimensionNumbersto MoE expert weights across (Qwen 3, Qwen 3-next, and GPT-OSS) and ensures all bias variants are correctly excluded from Muon orthogonalization.Problem
transform_logicpreviously checkedif "MoeBlock_0" in path:to detect expert weights. However, newer MoE architectures use different module names:routed_experts(Qwen3-next inqwen3.py)moe_block(Qwen3 MoE inqwen3.py/qwen3_custom.py)GptOssMlp(GPT-OSS ingpt_oss.py)Because these module names did not contain
"MoeBlock_0", their expert weight tensors fell through to the default mappingmdn((0,), (-1,))instead ofmdn((-2,), (-1,)), leading to incorrect orthogonalization across the expert axis.prefuse_moe_weights=True, the fused gate+up kernel is namedwi, which was missing from the recognized expert weight kernels("wi_0", "wi_1", "wo").transform_logiccheckedsegment == "bias", which missed compound bias names such aswi_0_bias,wo_bias(used in GPT-OSS withmlp_bias=True), andmlp_bias.Solution
transform_logicto recognize("MoeBlock_0", "routed_experts", "moe_block", "GptOssMlp")."wi"to the expert weight kernel tuple("wi", "wi_0", "wi_1", "wo")returningmdn((-2,), (-1,))."bias"to the substring exclusion tuple so all bias variations (wi_0_bias,wo_bias, etc.) returnNoneand fall back to AdamW as intended.FIXES: #4798
Tests
Added unit test coverage in
tests/unit/muon_utils_test.py:test_bias_variant_is_excluded: Verifieswi_0_bias,wo_bias, andmlp_biasreturnNone.test_qwen3_next_moe_routed_experts: Verifiesrouted_expertsexpert kernels (wi_0,wi_1,wo) returnmdn((-2,), (-1,)).test_qwen3_moe_block: Verifiesmoe_blockexpert kernels returnmdn((-2,), (-1,)).test_gpt_oss_mlp_moe: VerifiesGptOssMlpexpert kernels returnmdn((-2,), (-1,)).test_moe_prefused_wi_uses_last_two_axes: Verifies prefusedwikernels returnmdn((-2,), (-1,)).test_moe_gate_falls_through_to_standard: Verifies gate routing kernels fall through to standard mapping.Ran test suite locally:
Checklist
Before submitting this PR, please make sure (put X in square brackets):
gemini-reviewlabel.