Repository navigation
feat(optim): DeepSeek-V4 Newton-Schulz schedule and update RMS for Muon (opt-in) - #4118
Closed
faresobeid wants to merge 1 commit into
Closed
faresobeid wants to merge 1 commit into
faresobeid wants to merge 1 commit into
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #4117.
Two opt-in Muon knobs, both from the DeepSeek-V4 report (section 2.4, Algorithm 1). Defaults are unchanged and keep dion's own Newton-Schulz function.
optim.newton_schulz_coefficients = "deepseek_v4": 8 Newton-Schulz steps with (3.4445, -4.7750, 2.0315), then 2 steps with (2, -1.5, 0.5). Default"muon"is dion's 5-step schedule.optim.update_rms(default 0.2; DeepSeek-V4 uses 0.18): the RMS of a Muon update per unit of learning rate.rms_normadjustment fixes this at 0.2 (Moonlight).update_rms / 0.2, so weight decay (1 - lr * wd) is unchanged.trainer/optim/newton_schulz.py, which is dion's bfloat16 iteration with the schedule as an argument. With"muon"and 0.2 it is bitwise equal to dion's function (checked on CPU). It is only installed when one of the knobs differs from its default.Measurements
Newton-Schulz alone on 1 H200, inputs with singular values spread over 1..1e-3:
The deepseek_v4 schedule roughly doubles Newton-Schulz time. On GLM-4.5-Air (2 nodes) all of Muon's step after the dion bump takes 0.63 s, so the cost is at most a few tenths of a second per step.
Loss A/B: Qwen3-0.6B SFT on
PrimeIntellect/Reverse-Text-SFT, 1 GPU, Muon lr 5e-5, batch 32, seed 0. Mean train loss per window:deepseek_v4update_rms = 0.18deepseek_v4+update_rms = 0.18deepseek_v4pushes small singular values up to 1, which gives a larger effective step. That is consistent with the lower early loss.Checks
deepseek_v4and 0.18 the output singular values are 0.896-0.903 (expected 0.9).tests/unit/orchestrator+tests/unit/test_configs.py -m "not gpu": 350 passed.ruff check,ruff format --check.Note
Low Risk
Training-path change is opt-in with unchanged defaults; only Muon’s orthogonalization step is affected when non-default config is set.
Overview
Adds opt-in Muon optimizer knobs aligned with DeepSeek-V4 while keeping defaults on dion’s built-in Newton-Schulz path.
MuonConfiggainsnewton_schulz_coefficients("muon"vs"deepseek_v4") andupdate_rms(default0.2). A newtrainer/optim/newton_schulz.pyimplements bfloat16 Newton-Schulz with selectable coefficient schedules and output scaling soupdate_rmscan differ from Moonlight’s fixed0.2without changing weight decay behavior.Muon construction only passes a custom
newton_schulz_funcinto dion when either knob differs from default; otherwise behavior stays on dion’s native function. Choosing"deepseek_v4"uses a longer 10-step schedule (roughly ~2× Newton-Schulz cost) aimed at singular values closer to 1.Reviewed by Cursor Bugbot for commit 4aaa0a8. Bugbot is set up for automated code reviews on this repo. Configure here.