Sam Babichenko

Reading notes / NanoGPT speedrun

Refinements to Muon

Liu et al., 2025; Li et al., 2025; Chen et al., 2025; Srivastava, 2025

Context. Muon (see the Muon post in this section) replaces each hidden matrix's momentum by its polar factor, so every singular direction of the update gets the same step. Three refinements took it from a 124M speedrun win to a general optimizer and then reduced the speedrun time further: Moonshot matched AdamW's update size and added weight decay, NorMuon normalizes each neuron after the orthogonalization, and cautious weight decay decays only where the decay agrees with the step. An orthogonalized update has a fixed size set by the matrix's shape, which nothing in the gradient can shrink, and it makes all singular values equal while leaving the rows (one per output neuron) with unequal norms. So its size should be set to AdamW's, the weights need a decay that balances it (ideally one that never raises the loss), and each neuron needs its own scale.

Step 1

If Muon's updates match AdamW's update size, AdamW's tuning transfers. A rank-rr orthogonal factor O=UrVr⊤O=U_rV_r^\top has ∥O∥F2=r\|O\|_F^2=r spread over ABAB entries, so RMS(O)=rAB=1max⁡(A,B)at full rank,\mathrm{RMS}(O)=\sqrt{\frac{r}{AB}}=\frac1{\sqrt{\max(A,B)}}\quad\text{at full rank,} and a wide [H,4H][H,4H] MLP matrix takes per-entry steps half those of an H×HH\times H attention matrix. Moonshot multiplies each update by 0.2max⁡(A,B)0.2\sqrt{\max(A,B)}, so every matrix steps with RMS 0.2, where AdamW's update RMS sits in practice (0.2 to 0.4, below its nominal 1 because β1<β2\beta_1<\beta_2 and ϵ>0\epsilon>0); targets of 0.2 and 0.4 tie in a sweep, and the shape rule beats one global multiplier. In practice, the learning rate and decay tuned for AdamW serve Muon unchanged, and the AdamW-trained embeddings, head and norms share one schedule with the Muon matrices.

Step 2

On long runs Muon needs weight decay, because its steps never shrink. As gradients fade nothing slows the weights' growth, and Moonshot sees weight and layer-output RMS leave the range where bf16 is precise. Decoupled decay settles them where it balances the fixed step, inside a spectral ball of radius about 0.2max⁡(A,B)/λ0.2\sqrt{\max(A,B)}/\lambda (the spectral-constraint note in this section). At 800M parameters and 100B tokens, Muon without decay leads early and then falls behind Muon with decay, which also ends below AdamW; this rests on one pair of runs.

Step 3

With both fixes, Muon needs 44 to 49% of AdamW's compute over the tested range, untuned. Five compute-optimal dense models (399M to 1.5B parameters) are trained with AdamW at grid-searched hyperparameters, and Muon reuses exactly those. Solving the two fitted power laws for equal loss (my computation) gives a compute ratio of 0.44 at the smallest budget and 0.49 at the largest, so the quoted "about 52%" sits just past the tested range; the fits imply the ratio rises with compute, but their exponents (0.052 and 0.054) are printed to three decimals and a common 0.053 would give a constant 0.47, so the trend is uncertain. The comparison is conservative for Muon (AdamW tuned, Muon not) and rests on little data (five points per optimizer, no repeats, one data set).

Step 4

Orthogonalization leaves neurons with unequal update sizes. In a 1.1B model, Muon's update has flat singular values but row norms (one row per output neuron) that vary widely, while AdamW's are much more uniform. The paper only measures this; an explanation not in the paper follows. With M=UΣV⊤M=U\Sigma V^\top and φ\varphi the composed Newton-Schulz polynomial, ∥ei⊤NS5(M)∥2=∑kφ(σk)2 Uik2.\big\|e_i^\top\mathrm{NS5}(M)\big\|^2=\sum_k\varphi(\sigma_k)^2\,U_{ik}^2 . An exact polar factor of a full-rank wide matrix has unit rows. For tall matrices (m>nm>n, like the paper's headline MLP up-projection) the squared row norms are leverage scores summing to nn, uneven even when exact. For any shape, five fixed-coefficient steps leave the small singular values of a nearly low-rank momentum well below 1, so each row's norm is that neuron's leverage in the top few directions, and in a small check it tracked the neuron's gradient scale. The effect is largest exactly when the update is dominated by a few directions.

Step 5
Divide each row by its running RMS after Newton-Schulz, then restore AdamW's size. The extra state is one scalar per neuron (memory m(n+1)m(n+1) against Adam's 2mn2mn), and the rescale to Moonshot's 0.2 target keeps the step's size:
def normuon_step(W, G, M, v, lr, wd, beta1=0.95, beta2=0.95, eps=1e-8):
    M.lerp_(G, 1 - beta1)                    # momentum
    O = newton_schulz5(M)                    # Muon direction
    row_ms = (O * O).mean(dim=1)             # mean square of each row (neuron)
    v.lerp_(row_ms, 1 - beta2)               # EMA: one scalar per neuron
    O = O / (v.sqrt()[:, None] + eps)        # equalize neurons
    scale = 0.2 * lr * O.numel() ** 0.5 / O.norm()   # update RMS = 0.2 * lr
    W.mul_(1 - lr * wd)
    W.sub_(scale * O)
A row scaling moves each singular value by a factor between the smallest and largest row scale, so the update stays near-orthogonal. The order matters: for a full-rank wide matrix the polar factor of DMDM again has orthonormal rows, so a scaling applied before Newton-Schulz loses its row sizes, and that ablation trails NorMuon. A per-coordinate second moment after orthogonalization (Adam on top of Muon) also trails, at twice the memory. Under FSDP2's row sharding each device holds whole neurons, so the statistics need no communication.
Step 6

What the row normalization saves. At 1.1B and 5.4B parameters (50B tokens), NorMuon reaches AdamW's final loss in 21.74% and 13.91% fewer steps, against 10.43% and 6.08% for Muon, at 2.9% more step time than AdamW. In modded-nanogpt at 124M and 350M, with Muon's tuned hyperparameters reused, Muon needs 6% and 15% more iterations to match it. These are single runs at one learning rate per scale, and the margin over Muon shrinks with size.

Step 7

Cautious weight decay decays only where the step already shrinks the weight. Plain decay changes the problem (with Muon its fixed points are KKT points of min⁡f\min f subject to ∥X∥op≤1/λ\|X\|_{\rm op}\le1/\lambda); cautious decay masks it, for any base update utu_t, with no new hyperparameter: xt+1=xt−ηt(ut+λ 1{ut⊙xt≥0}⊙xt).x_{t+1}=x_t-\eta_t\big(u_t+\lambda\,\mathbb 1\{u_t\odot x_t\ge0\}\odot x_t\big). At the baseline's tuned λ\lambda it lowers final loss for AdamW, Lion and Muon from 338M to 2B parameters; on OLMo-1B, AdamW goes from 2.65 to 2.56 and Muon from 2.51 to 2.42, while a random mask of the same sparsity is worse than no decay at all, so the gain comes from which coordinates are decayed.

Step 8

The mask makes the loss a Lyapunov function, so the limit is unbiased. For the gradient flow with cautious decay, x˙=−∇f−λ 1{∇f⊙x≥0}⊙x\dot x=-\nabla f-\lambda\,\mathbb 1\{\nabla f\odot x\ge0\}\odot x, differentiate ff along the path: ddtf(xt)=−∥∇f∥22−λ∥(∇f⊙x)+∥1≤0.\frac{d}{dt}f(x_t)=-\|\nabla f\|_2^2-\lambda\big\|(\nabla f\odot x)^+\big\|_1\le0 . The mask turns the cross term into a positive part; with plain decay it is −λ⟨∇f,x⟩-\lambda\langle\nabla f,x\rangle, of either sign, so decay can raise the loss and the flow settles where ∇f=−λx\nabla f=-\lambda x. LaSalle then puts the limit set inside {∇f=0}\{\nabla f=0\}, the stationary points of ff itself (the momentum methods need a kinetic term and a mask-dependent correction). On the stationary set the decay acts as a tie-breaker, sliding along flat directions toward smaller magnitudes until it reaches a locally Pareto point (a stationary point with no nearby stationary point that is smaller or equal in every ∣xi∣|x_i|). The preference is mild: on the paper's circle of minimizers, f=((x−3)2+(y−3)2−1)2f=\big((x-3)^2+(y-3)^2-1\big)^2 (my check), cautious decay started at (4.2,4.2)(4.2,4.2) stays at the large-norm point (3.71,3.71)(3.71,3.71), since every tangent move there raises one coordinate.

Step 9

How the speedrun used each (records #41 to #50). The record-holder's essay (Varun Srivastava, who set #38, #42, #43 and #46) and the READMEs give the sequence at 124M on 8xH100. Record #41 swapped in NorMuon with hyperparameters unchanged and removed 15 steps (0.7 s); #42 found Muon's learning rate about twice too high, halved it and reshaped the attention weights so the normalization runs along the output dimension, for 30 steps and 3.3 s, about 2% for the pair by the essay's count. Record #43 replaced plain decay, which stabilized training but raised the final loss at this training length, with cautious decay on the NorMuon matrices, its strength tied to the learning-rate schedule: 40 fewer steps and 2.2 s, with validation loss above the baseline until the learning rate starts to decay, and much smaller final weights. Record #48 fixed which axis counts as a neuron: on the smear gate, a single weight vector, the wrong orientation normalized each entry by its own history, which is sign descent. Record #50 extended cautious decay to the Adam-trained parameters except scalars (20 steps, 1.1 s). The essay's explanations are the author's reasoning; the ANVIL optimizer of record #92 still combines a NorMuon-style row rescale with cautious decay.

Consequences. Muon became a general optimizer once its update size was tied to AdamW's and its weights were held by decay (Kimi K2 and GLM-4.5 later trained with it); the speedrun refinements then remove what orthogonalization leaves behind, unequal neuron update sizes and a decay that can raise the loss. The evidence is empirical, mostly single runs without error bars.

Terms

RMS(UrVr⊤)\mathrm{RMS}(U_rV_r^\top)
r/(AB)\sqrt{r/(AB)}; 1/max⁡(A,B)1/\sqrt{\max(A,B)} at full rank
0.2max⁡(A,B)0.2\sqrt{\max(A,B)}
per-matrix multiplier: update RMS 0.2, like AdamW's, so AdamW's η,λ\eta,\lambda are reused
decoupled decay with Muon
W←W−η(sO+λW)W\leftarrow W-\eta(sO+\lambda W); weights settle within ∥W∥op≲s/λ\|W\|_{\rm op}\lesssim s/\lambda
compute ratio
0.44 to 0.49 of AdamW's over the tested range; about 52% quoted
∑kφ(σk)2Uik2\sum_k\varphi(\sigma_k)^2U_{ik}^2
squared row norm of NS5 output; leverage of neuron ii in the dominant subspace
vt∈Rmv_t\in\mathbb R^m
EMA of each row's mean squared update; NorMuon's only extra state
NorMuon (Front) / Muon+Adam
ablations: normalize before orthogonalizing, or per coordinate after; both worse
1{u⊙x≥0}\mathbb 1\{u\odot x\ge0\}
cautious decay mask: coordinates where the step already shrinks ∣xi∣|x_i|
local Pareto set P\mathcal P
stationary points with no nearby stationary point smaller or equal in every ∣xi∣|x_i|
records
#41/#42 NorMuon (0.7 s, 3.3 s); #43 cautious decay (-40 steps, 2.2 s); #48 gate axis; #50 Adam params (1.1 s)

Quiz

  1. What does scaling each update by 0.2max⁡(A,B)0.2\sqrt{\max(A,B)} achieve in practice?
  2. Solving the two printed fits for equal loss, how does the Muon-to-AdamW compute ratio behave across budgets?
  3. The 'Front' ablation normalizes rows before Newton-Schulz and does worse. What explains this most directly?
  4. A Bernoulli mask with the same sparsity as cautious decay does worse than no decay on OLMo-1B. What does that rule out?

Sources