Matrix optimizers: K-FAC, Shampoo and Muon
Before this lesson: lesson 06 (Adam; its first step is ), lesson 10 (Newton, the generalized Gauss–Newton matrix and the Fisher), linear algebra 08 (SVD, polar decomposition), linear algebra 11 (spectral and nuclear norms, dual norms), linear algebra 16 (Kronecker product and vec). Time: about 80 minutes, plus the notebook.
Why this matters #
Adam scales each coordinate separately: its preconditioner is diagonal. Full curvature (Newton) is far too expensive for a network. Matrix optimizers are the practical middle ground, and in 2024–2025 they moved into practice:
- Distributed Shampoo won the external-tuning track of the AlgoPerf training-speed benchmark;
- Muon set records in the NanoGPT speedrun, and Moonshot AI trained Kimi K2 (1 trillion parameters) with a Muon variant;
- K-FAC-type curvature is used for influence functions of large language models and for physics-informed networks.
The theory behind Muon is short and useful beyond it: an optimizer is a choice of norm, and the update is the steepest step in that norm.
1. Predict first #
2. The picture #
Optimizers as preconditioners #
Most optimizers have the form for some matrix :
| Method | Cost for parameters | |
|---|---|---|
| gradient descent | ||
| Adam (lesson 06) | a diagonal matrix (one scale per coordinate) | |
| Newton (lesson 10) | the full Hessian (or GGN, Fisher) | memory, time |
| K-FAC, Shampoo | per layer, a Kronecker product of two small matrices | memory for an weight |
For a weight matrix there are parameters, and a full has entries. A Kronecker product of an matrix and an matrix is also , but it is stored with only numbers, and it acts on the gradient matrix by multiplication from the left and the right: (linear algebra 16).
Convention for this lesson. stacks the columns of a matrix (as in Martens and Grosse). Then and . With row stacking, the two factors swap places.
Steepest descent depends on how you measure a step #
For a small step , the loss changes by about . The steepest step of size 1 is the with that makes most negative. The answer depends on the norm. Take :
- Euclidean norm : . This is gradient descent.
- Max norm (each coordinate may move by at most 1): . This is sign descent. Adam's first step is , and Adam with its moving averages switched off is sign descent.
- norm (the total movement is at most 1): . Move only the coordinate with the largest : coordinate descent.
Drag the tip of . The three shaded shapes are unit balls: the circle (), the square () and the diamond (). Each arrow is the point of its ball where is most negative. Choose one norm under "Show": the dashed line is the level line , and it touches the ball exactly at the steepest point. Its distance from the origin gives the dual norm . Try : the steepest step is no longer unique.
What is the steepest unit step for under the norm, and how much does it decrease the linear model ?
In the ball every coordinate can move by 1, so move each one fully against its gradient sign: , and . is the answer and the answer; is not in the unit ball.
For a matrix: the spectral norm and #
A weight matrix maps inputs to outputs. A natural size for a change is the spectral norm , the largest singular value. It bounds how far the change can move any output: .
Section 3 proves that the steepest step under this norm is , where is the SVD of the gradient: keep the singular vectors of , and set all its singular values to 1. Gradient descent moves along each singular direction in proportion to ; the orthogonalized step gives every direction the same size.
The simplest case: a diagonal gradient . Its SVD has , and . So : for a diagonal gradient, orthogonalization is sign descent. In general it is "sign descent on the singular values".
Move the sliders, then try the presets. The dashed circle is the set of unit inputs, with the input directions (grey arrows). The blue ellipse is its image under the gradient (drawn with ): the blue arrows have lengths and . The magenta circle is the image under : the same directions , both of length 1. With "" the blue ellipse is almost a line, but the orthogonalized step still moves the weak direction fully. "Muon (5 steps)" shows the dashed result of Muon's iteration: close to the circle, but not exactly on it.
A gradient matrix has singular values 100 and 1. What are the singular values of ?
keeps the singular vectors and replaces by , so both singular values become 1. The weak direction now gets the same step as the strong one. Dividing by (giving 1 and 0.01) only rescales the gradient; it is still a gradient step.
3. Definitions and main results #
K-FAC: Kronecker-factored curvature #
Take a linear layer with input and (a bias can be handled by appending a 1 to ). Backpropagation gives for the loss of one example, and the weight gradient is the outer product .
One example: an exact Kronecker product. With column stacking, , so
Many examples: the approximation. The Fisher block of the layer is the average of this matrix over examples, with the targets sampled from the model's own predictive distribution:
The mean of a product is replaced by the product of the means. This is exact when and are independent; in general it is an approximation. Martens and Grosse (2015), who introduced K-FAC (Kronecker-factored approximate curvature), call it a major approximation that still keeps the coarse structure of the Fisher. (They write for the second factor; we write , because is the gradient matrix in this lesson.) If you use the data labels instead of sampled targets, you get the "empirical Fisher", which loses the link to the Gauss–Newton matrix of lesson 10.
Why the step is cheap. Two Kronecker identities, and for symmetric , give
You invert an and an matrix, operations, instead of one matrix of size , which costs . In practice K-FAC uses one block per layer (it ignores the curvature between layers), moving averages of and , damping of each factor (, ), and recomputes the inverses only every few steps.
Move the slider from 1 example to 2, then to many. A tiny linear layer with 2 inputs and 2 outputs has 4 weights, so its Fisher block is . Left: the exact , the mean of over examples. Right: K-FAC's from the same examples. Blue entries are positive, orange ones negative; the thick lines show the blocks (block of is ). With one example the two maps are equal. With independent and the error shrinks as grows (with some noise). When depends on , the error stays at about 0.6 for every large .
For a linear layer, K-FAC approximates the Fisher block by with (inputs) and (output gradients). Which preconditioned step does it take for the gradient matrix ?
is (outputs × inputs), so the output factor must act from the left and the input factor from the right: . does not even have matching sizes unless . Forming the big inverse is exactly what K-FAC avoids.
Steepest descent under a norm #
Let be a norm. Its dual norm is
The dual of is ; the dual of is ; the dual of is (linear algebra 11). For matrices with , the dual of the Frobenius norm is the Frobenius norm, and the dual of the spectral norm is the nuclear norm (Theorem 2 below proves it).
Assume the loss satisfies a quadratic upper bound in this norm, , like the descent lemma of lesson 02 but with any norm. Minimizing the right side gives the step.
Proposition 1 (steepest descent; Bernstein and Newhouse, 2024). For ,
Proof.
- Write with a length and a direction . The objective is .
- For every fixed , the best direction maximizes ; the maximum value is .
- Minimize over : the derivative is zero at .
So the direction is the unit vector most aligned with , and the length is the dual norm divided by (Bernstein and Newhouse call the "sharpness"). Each norm gives an optimizer:
| Space | Norm | Dual norm | Steepest direction with | Optimizer |
|---|---|---|---|---|
| gradient descent | ||||
| sign descent (Adam without moving averages) | ||||
| Frobenius | Frobenius | gradient descent | ||
| spectral | nuclear | Muon; Shampoo without accumulation |
Theorem 2: the spectral steepest direction is the polar factor #
Theorem 2. Let have rank and reduced SVD . Then
and the steepest step is .
Why this is true (intuition). : each singular direction contributes times "how much sends to ". A matrix with spectral norm at most 1 can send each to at most a unit vector, so the best it can do is for every . That is .
Proof.
- (the trace of equals ).
- By Cauchy–Schwarz, , because and are unit vectors. So .
- has all nonzero singular values equal to 1, so . And for every , so it attains the bound. This also shows that the spectral and nuclear norms are dual.
- Proposition 1 with the spectral norm gives the step .
When has full rank the maximizer is unique. is the orthogonal factor of the polar decomposition , with and (linear algebra 08). It is also the closest semi-orthogonal matrix to in the Frobenius norm (Bernstein and Newhouse, Proposition 4). Muon uses the direction with a tuned learning rate in place of the length .
Why the spectral norm? Bernstein and Newhouse (Proposition 6) give the simplest case: a linear predictor with the square loss and inputs with satisfies
Minimizing this upper bound is exactly a spectral steepest-descent step. There is also an empirical reason (Jordan, 2024): the gradient and momentum matrices of transformer layers are almost low rank, with a few dominant directions. Orthogonalization raises the weak, "rare" directions, which may still matter for learning.
Newton–Schulz: with matrix products only #
An SVD is slow on GPUs. The Newton–Schulz iteration uses only matrix multiplications, which GPUs do very fast, also in low precision.
Lemma 3. Let with orthonormal columns in and and a diagonal . For coefficients , the step
equals with the odd polynomial applied to each singular value.
Proof.
- , because .
- , because . In the same way, .
- Add the three terms: .
So the singular vectors never change, and each singular value follows the scalar map . After steps, , where is applied times. If for every singular value that occurs, then . The algorithm:
- Normalize: . Since , all singular values are now in .
- Transpose tall matrices: if , work with , so that is the smaller Gram matrix.
- Iterate with the chosen coefficients.
The cubic (classical) iteration, , so :
- Fixed points: .
- , so . Near 1 the convergence is quadratic: .
- : a small singular value grows only by about 1.5 per step. From it needs 14 steps to pass 0.99.
- It converges to 1 for every ; the normalization guarantees this.
Muon's quintic (Jordan, 2024), :
- The slope at 0 is , so small singular values grow fast. From , five steps give .
- Jordan chose as large as possible while keeping the iterates in about .
- The price: 1 is not a fixed point, since . The iterates keep moving inside a band instead of converging. After 5 steps, normalized singular values that start in end in about .
So Muon's output is with , not exactly . Jordan reports that this does not hurt training. The 5 steps run in bfloat16.
Move and switch the polynomial. The large chart shows the map after steps (magenta; earlier faint), on a log scale of the starting singular value. The small chart follows five starting values over the steps. With the cubic, values near 1 converge very fast but needs many steps. With the quintic, every value from 0.001 to 1 enters the band between the yellow lines within about 6 steps, and then keeps moving inside it.
Cost. For , one step costs about operations. Jordan bounds Muon's extra cost in transformer training by ( Newton–Schulz steps, usually 5; model width ; batch size in tokens): about 0.7% of the training compute for the NanoGPT speedrun and 0.5% at the scale of Llama 3 405B.
Muon #
For each 2D weight of a hidden layer ( = fan-out rows, = fan-in columns),
with gradient , momentum coefficient (0.95 by default), learning rate and weight decay
, torch.optim.Muon does:
- momentum: (starting from );
- Nesterov: (without Nesterov, );
- : five quintic Newton–Schulz steps;
- , with a shape factor :
(Jordan's original choice, PyTorch's default) or
(Moonshot,
adjust_lr_fn="match_rms_adamw").
Some implementations write the momentum as a moving average, . This only changes the size of the buffer, and Newton–Schulz divides by the Frobenius norm, so is the same. Muon is "Shampoo without accumulation" (next subsection) applied to the momentum.
Update size. A full-rank semi-orthogonal matrix has , so its root-mean-square (RMS) entry is . AdamW's update RMS is usually about 0.2 to 0.4 (Liu et al., 2025). The factor makes Muon's update RMS equal to 0.2, so the learning rate and weight decay tuned for AdamW can be reused.
Which parameters. Muon is for the 2D weight matrices of hidden layers (a convolution kernel is flattened to 2D over its last three dimensions). Embeddings, the output layer, biases and normalization gains use AdamW. Jordan found AdamW better for the embedding and output layers even though they are 2D; biases and gains are vectors, so "orthogonalizing" them makes no sense (for a vector, is just ).
Shampoo #
Algorithm (Gupta, Koren and Singer, ICML 2018). For , start from , , and at each step
It stores numbers instead of the of full-matrix AdaGrad, and the inverse fourth roots cost (an eigendecomposition of each factor).
Why the power . Full-matrix AdaGrad preconditions with . Gupta et al. bound the sum inside by a multiple of a Kronecker product of and (their Lemma 8). Its square root has the factors and , one on each side of .
Proposition 4 (Shampoo without accumulation is ). With and , and the inverse roots taken on the range of (the limit ):
Proof.
- , so on the range of .
- In the same way, .
- The product is .
After identical gradients, and , so the update is : the step decay of AdaGrad. Practical versions (Distributed Shampoo; Shi et al., 2023) use moving averages for and , recompute the roots only every few steps, and use "grafting": Shampoo gives the direction, and a simpler method such as Adam gives the step size of each layer.
Shampoo and K-FAC. For one example , so and : K-FAC's factors, each weighted by the squared norm of the other side. Shampoo needs no extra backward pass with sampled targets, and it uses the power instead of .
Shampoo keeps only the current gradient: and (and ). What is ?
With , and , so the product is . This is the same direction as Muon. keeps the ratios of the singular values; sets them all to 1.
SOAP: Adam in Shampoo's eigenbasis #
Vyas et al. (2024) show that Shampoo with the power (that is, with averaged and ) is equivalent to Adafactor (an Adam variant whose second moment is factored into row and column statistics), run in the eigenbasis of and . SOAP ("ShampoO with Adam in the Preconditioner's eigenbasis") runs full Adam in that basis:
- Let and be the eigenvectors of and (moving averages of and ).
- Rotate the gradient, , and run Adam's moment updates on (the first moment is kept in the original space and rotated the same way).
- Rotate the Adam step back: . Refresh and every steps.
The preconditioning frequency is the only hyperparameter beyond Adam's. The intuition: Adam's diagonal scaling works best in a basis where the curvature is nearly diagonal, and Shampoo's eigenbasis is such a basis. For language models with 360M and 660M parameters at a large batch size, Vyas et al. report over 40% fewer iterations and over 35% less wall-clock time than AdamW, and about 20% better than Shampoo on both.
The evidence, as of 2025–2026 #
These are current results; they may change as methods and baselines improve.
- AlgoPerf (Kasimbeg et al., 2025): the winner of the external-tuning ruleset used Distributed Shampoo. Non-diagonal preconditioning beat Adam-type methods even in wall-clock time. (The self-tuning ruleset was won by Schedule-Free AdamW.)
- Speedruns (Jordan, 2024): Muon improved the NanoGPT speedrun record (3.28 validation loss on FineWeb) by a factor of 1.35, and the CIFAR-10 record (94% accuracy) from 3.3 to 2.6 A100-seconds.
- Moonlight (Liu et al., "Muon is Scalable for LLM Training", 2025): two changes were needed at scale, weight decay and the per-matrix update scale . Their scaling-law runs showed about the compute efficiency of AdamW under compute-optimal training. Moonlight is a mixture-of-experts model with 3B active and 16B total parameters, trained on 5.7T tokens.
- Kimi K2 (2025): a mixture-of-experts model with 1T total and 32B active parameters, trained on 15.5T tokens with MuonClip (Muon plus "QK-Clip", which rescales the query and key weights of an attention head when its largest attention logit grows too large), with zero loss spikes.
- A careful comparison (Wen, Hall, Ma and Liang, "Fantastic Pretraining Optimizers and Where to Find Them", 2025): with equally careful tuning of every optimizer, and comparison at the end of training, the fastest methods were matrix-based (Muon, SOAP), but their speedup over AdamW fell from about at 0.1B parameters to about at 1.2B. Many earlier claims compared against a weakly tuned AdamW.
Answers to section 1. (1) Both become about 1: exactly 1 for , and about 0.70 each for Muon's five quintic steps (the normalized values and end at and ). The weak direction now gets the same step as the strong one: this is the steepest step under the spectral norm, and for nearly low-rank updates it raises the rare directions. (2) The Fisher block of a layer with weights has entries. K-FAC's two factors have . (3) (Proposition 4): the same direction as Muon.
4. Worked example #
Take the gradient .
SVD. has eigenvalues and , so and (ratio 3). The right singular vectors are and . Then :
Polar factor.
This is a rotation by . With you can check .
Theorem 2 in numbers. , and . Two other matrices with spectral norm 1 do worse:
- gives ;
- , with and , gives .
Gradient descent keeps the ratio between the two singular directions; makes it .
Newton–Schulz. , so the normalized singular values are .
- Cubic: and ; then , , , . The largest error is after 6 steps and about after 7. The large value converges at once (quadratic convergence); the small one first grows by about 1.5 per step.
- Muon's quintic: , then . After 5 steps the update is . It is not orthogonal, and the strong direction now has the smaller value. But the ratio of the singular values went from 3 to 1.5.
Shampoo. also has eigenvalues 45 and 5, and exactly. After 4 identical gradients the update is .
Update RMS. For an MLP weight with rows and columns, has RMS . Jordan's factor gives ; Moonshot's factor gives .
K-FAC in one dimension. With one input and one output, the Fisher block is the number . For two examples and , the exact value is , but K-FAC gives . Here large comes with small , so and are negatively correlated, and the product of the means is too large.
A hidden weight of a transformer is . You use Muon with Moonshot's factor and learning rate . What is the RMS entry of the update if is exactly semi-orthogonal?
A full-rank semi-orthogonal matrix has RMS . The factor gives RMS , times . That is AdamW's typical update RMS, so AdamW's learning rate can be reused. is the RMS without any shape factor.
5. In code #
The notebook asks you to implement Newton–Schulz, Shampoo's inverse roots and K-FAC yourself. Here NumPy and
SciPy check the hand results: scipy.linalg.polar gives , and fractional_matrix_power gives the
inverse fourth roots of Shampoo.
import numpy as np
from scipy.linalg import polar, fractional_matrix_power
G = np.array([[3.0, 0.0], [4.0, 5.0]])
U, s, Vt = np.linalg.svd(G)
Q, P = polar(G) # G = Q P with Q = U Vᵀ, P = V Σ Vᵀ
print(s.round(4), np.allclose(Q, U @ Vt)) # [6.7082 2.2361] True
print(np.sqrt(5) * Q) # [[ 2. -1.] [ 1. 2.]]
# Theorem 2: among matrices with spectral norm 1, U Vᵀ has the largest <G, O> = ‖G‖_nuc
for name, O in [("UV^T", Q), ("G/sigma_max", G / s[0]),
("sign(G)", np.sign(G) / np.linalg.norm(np.sign(G), 2))]:
print(f"{name:12s} <G,O> = {np.sum(G * O):.4f}")
print(f"nuclear norm {s.sum():.4f}") # 8.9443; the three rows: 8.9443, 7.4536, 7.4164
def newton_schulz(G, coeffs, steps):
a, b, c = coeffs
X = G / np.linalg.norm(G) # Frobenius norm: all singular values ≤ 1
tall = X.shape[0] > X.shape[1]
if tall:
X = X.T # work with the smaller Gram matrix X Xᵀ
for _ in range(steps):
A = X @ X.T
X = a * X + (b * A + c * A @ A) @ X
return X.T if tall else X
cubic, quintic = (1.5, -0.5, 0.0), (3.4445, -4.7750, 2.0315)
print(np.abs(newton_schulz(G, cubic, 7) - Q).max()) # about 1e-10
print(np.linalg.svd(newton_schulz(G, quintic, 5), compute_uv=False).round(3)) # [1.134 0.753]
# Shampoo without accumulation gives U Vᵀ; after k equal gradients it gives U Vᵀ/√k
for k in [1, 4]:
S = fractional_matrix_power(k * G @ G.T, -0.25) @ G @ fractional_matrix_power(k * G.T @ G, -0.25)
print(k, np.allclose(S, Q / np.sqrt(k))) # 1 True, then 4 True
# K-FAC for one example: vec(δ aᵀ) = a ⊗ δ (columns stacked)
rng = np.random.default_rng(0)
a, delta = rng.standard_normal(3), rng.standard_normal(2)
v = np.outer(delta, a).flatten(order="F")
print(np.allclose(np.outer(v, v), np.kron(np.outer(a, a), np.outer(delta, delta)))) # True
# the cheap step: (A ⊗ D)^{-1} vec(M) = vec(D^{-1} M A^{-1})
A_f, D_f, M = np.diag([1.0, 2.0, 3.0]), np.array([[2.0, 1.0], [1.0, 2.0]]), rng.standard_normal((2, 3))
lhs = np.linalg.solve(np.kron(A_f, D_f), M.flatten(order="F"))
print(np.allclose(lhs, (np.linalg.inv(D_f) @ M @ np.linalg.inv(A_f)).flatten(order="F"))) # True
# two examples in 1D: mean of products vs product of means
a2, d2 = np.array([1.0, 2.0]), np.array([2.0, 1.0])
print(np.mean(a2**2 * d2**2), np.mean(a2**2) * np.mean(d2**2)) # 4.0 6.25
# a 64 x 256 gradient whose singular values span a factor of 100
U2, _ = np.linalg.qr(rng.standard_normal((64, 64)))
V2, _ = np.linalg.qr(rng.standard_normal((256, 64)))
G2 = U2 @ np.diag(np.geomspace(1.0, 0.01, 64)) @ V2.T
O2 = newton_schulz(G2, quintic, 5)
sv = np.linalg.svd(O2, compute_uv=False)
print(sv.min().round(2), sv.max().round(2)) # 0.68 1.2: a band around 1
update = 0.2 * np.sqrt(max(64, 256)) * O2 # Moonshot's shape factor
print(round(np.sqrt(np.mean(update**2)), 3)) # 0.184, close to AdamW's typical 0.2
The update RMS is 0.184 and not exactly 0.2, because the singular values are only near 1. Real Muon runs the iteration in bfloat16, which moves the last digits a little.
6. Where it shows up #
- Large-model pretraining. PyTorch ships
torch.optim.Muonwith three shape factors (adjust_lr_fn="original","match_rms_adamw"or"spectral_unclamped"). A typical setup has two optimizers: Muon for the hidden matrices and AdamW for everything else. When you compare it with AdamW, tune the AdamW baseline just as carefully (Wen et al., 2025). - Distributed training. Muon keeps one state matrix per weight (the momentum) instead of AdamW's two, so it needs half of AdamW's optimizer-state memory. With sharded optimizer states (ZeRO, FSDP), each matrix must be gathered before Newton–Schulz; Moonshot's distributed Muon does this.
- Curvature for analysis. Influence functions for large language models use K-FAC-type Hessian approximations (EK-FAC; Grosse et al., 2023). Laplace approximations of the posterior of a network often use K-FAC factors.
- ML for science. For physics-informed networks, Dangel, Müller and Zeinhofer (NeurIPS 2024) extend K-FAC to losses with differential operators. Transformer foundation models for weather or seismic data have the same parameter types as language models, so the same Muon rules apply. Small full-batch physics problems are still served better by curvature methods (L-BFGS, Gauss–Newton; lesson 10).
7. Common mistakes #
- Muon on every parameter. Embeddings, the output layer, biases and gains belong to AdamW.
- No normalization before Newton–Schulz. For a singular value above , the cubic iteration does not converge to 1, and the quintic is tuned for . Divide by the Frobenius norm first.
- Expecting an exact from Muon. Five quintic steps give singular values in a band around 1, on purpose.
- Reusing AdamW's learning rate with Jordan's shape factor. The update RMS is then (0.036 for a weight), far below AdamW's 0.2. Use the factor, or retune the learning rate.
- Mixing up the Kronecker order. With column stacking, and
the K-FAC step is . With row stacking, the factors swap. Fix one convention and test
it against
np.kronon a small case. - K-FAC with the data labels (the empirical Fisher) or without damping.
- Calling Shampoo "K-FAC". Both use two Kronecker factors, but with different statistics (gradient matrices vs activations and output gradients) and different powers ( vs ).
8. Check yourself #
- What is the steepest-descent step under the norm for and ?
Answer
The dual norm is : , and the unit direction is . By Proposition 1, . - . What are and the Shampoo update without accumulation?
Answer
Both are . For example, , so . - A single example passes through a linear layer, so with nonzero vectors and . What is , and what does Muon do here?
Answer
The reduced SVD has one singular value , with and . So . For a rank-1 gradient, orthogonalization is just normalized gradient descent. (Because is not full rank, the steepest direction is not unique; from the reduced SVD is one solution.) - Shampoo receives the same gradient at every step. What is the update after steps, and which older method has the same step decay?
Answer
and (ignoring ), so the update is . AdaGrad also gives steps that decay like for a constant gradient. - Why does the cubic iteration need many steps for a singular value of , how does Muon's quintic fix this, and what does it give up?
Answer
The cubic map has slope , so small values grow only 1.5 times per step (14 steps from 0.01 to 0.99). The quintic has slope 3.4445 at 0 and reaches the band around 1 in 5 steps. The price: , so 1 is not a fixed point, and the singular values stay in a band of about instead of converging to 1. - A linear layer has inputs and outputs. Compare the cost of inverting its exact Fisher block with K-FAC's two inversions.
Answer
The exact block has size , so about operations. K-FAC inverts a and a matrix: , about times less.
Define the dual norm of a norm .
. The dual of is ; the dual of the spectral norm is the nuclear norm.
What is the steepest-descent direction under the spectral norm for a gradient ?
: the singular vectors of with all singular values set to 1 (the polar factor).
What is the steepest unit step for under ?
: sign descent, which is Adam with its moving averages switched off.
What is the purpose of the Newton–Schulz iteration in Muon?
To compute (approximately) with matrix multiplications only, without an SVD; it applies an odd polynomial to each singular value.
Describe Muon in one sentence.
SGD with Nesterov momentum on each 2D hidden weight, where the momentum matrix is orthogonalized by five quintic Newton–Schulz steps before the step; other parameters use AdamW.
Write the Shampoo update.
with and (plus ).
What is Shampoo without accumulation equal to?
, the same direction as Muon.
Describe SOAP in one sentence.
Adam run in the eigenbasis of Shampoo's two factors, with the eigenbasis refreshed every few steps.
What is the K-FAC approximation of the Fisher block of a linear layer, and what is its step?
with (inputs) and (output gradients); the step is .
Why is K-FAC exact for a single example?
For one example , and exactly; only the average over examples needs the approximation.
9. Interview angle #
- "What is Muon, and why orthogonalize?" — Momentum SGD where the update of each 2D hidden matrix is orthogonalized (about ) by five Newton–Schulz steps; AdamW handles the rest. It is steepest descent under the spectral norm (Theorem 2), so the rare directions of a nearly low-rank update get a real step.
- "How are Muon and Shampoo related?" — Shampoo without accumulation is ; Muon applies this to the momentum and computes it with Newton–Schulz.
- "What does K-FAC approximate, and why is it cheap?" — The layer's Fisher block by ; the step needs two small inversions instead of one huge one.
- "How do you switch an AdamW recipe to Muon?" — Muon for 2D hidden weights only, the scale to reuse AdamW's learning rate and weight decay, keep the weight decay, watch the attention logits.
- "Does Muon beat AdamW?" — Speedruns, Moonlight (about compute efficiency) and Kimi K2 say yes; a careful benchmark with equally tuned baselines finds about at 0.1B parameters, shrinking to at 1.2B (as of 2025–2026).
10. Practice #
The notebook for this lesson runs in Colab. It has five exercises, each with a check cell and a folded solution:
- Check numerically that maximizes over spectral-norm-1 matrices (random search against the nuclear norm).
- Implement the Newton–Schulz iteration (cubic and quintic) and compare with the SVD polar factor.
- Compute matrix inverse fourth roots by eigendecomposition and check that Shampoo without accumulation gives .
- K-FAC for one linear layer: compute , and the exact Fisher block from samples, and the relative error of .
- Muon vs Adam vs gradient descent on a small matrix regression problem with an ill-conditioned input.
11. Watch and read #
- Bernstein and Newhouse, Old Optimizer, New Norm: An Anthology (2024): Proposition 1 (steepest descent), Propositions 4–6 (Shampoo and the spectral norm), Table 1.
- Jeremy Bernstein, Deriving Muon (blog).
- Keller Jordan, Muon: An optimizer for hidden layers in neural networks (2024): the Newton–Schulz coefficients, the cost analysis, the results.
- Martens and Grosse, Optimizing Neural Networks with Kronecker-factored Approximate Curvature (2015): §3 (the approximation), §5 (statistics with sampled targets), §6.3 (damping).
- Gupta, Koren and Singer, Shampoo: Preconditioned Stochastic Tensor Optimization (2018), and Shi et al., Distributed Shampoo (2023).
- Vyas et al., SOAP: Improving and Stabilizing Shampoo using Adam (2024).
- Liu et al., Muon is Scalable for LLM Training (2025), and Kimi Team, Kimi K2: Open Agentic Intelligence (2025).
- Kasimbeg et al., Accelerating Neural Network Training: An Analysis of the AlgoPerf Competition (2025), and Wen et al., Fantastic Pretraining Optimizers and Where to Find Them (2025).
- PyTorch,
torch.optim.Muon(the algorithm box and the three shape factors).
Runs in your browser with nothing to install. The notebook repeats the key demos and has exercises with checks; solutions are inside, folded.
No Google account needed: Python runs inside your browser. The first start downloads about 40 MB; your changes are saved in this browser only.