This site is version 0.0.1. Most of the code on this site is drafted by an agent and needs review. I apologize for the AI-speak, we are working on rewriting it!
viv-lang.org

Notebooks · lib/polar

Orthogonalizing a matrix by Newton-Schulz, which is what Muon does

Every real matrix factors as A = U H with U orthonormal and H symmetric positive semidefinite. U is the polar factor, and it is the closest orthonormal matrix to A in the Frobenius norm. Robotics wants it because a rotation matrix integrated forward stops being a rotation, and the polar factor is how you put it back. Training a transformer wants it because the Muon optimizer orthogonalizes the momentum matrix before taking a step, which is what makes it more sample-efficient than Adam at the same memory. The two use the same iteration and neither one computes an SVD.

What they run instead is a matrix polynomial:

X <- a X + b X X^T X + c (X X^T)^2 X

starting from A divided by its Frobenius norm, which puts every singular value in (0, 1]. The iteration does nothing to the singular vectors and acts on each singular value independently, by the scalar polynomial p(s) = a s + b s^3 + c s^5. So the whole question is what that polynomial does to the interval (0, 1].

The classical coefficients are (15/8, -10/8, 3/8). They fix p(1) = 1, and the iteration converges to the true polar factor. Muon uses (3.4445, -4.7750, 2.0315) instead, where p(1) = 0.70, and it does not converge to anything. Iterate the scalar map from anywhere in (0, 1] and after ten steps it is bouncing around inside [0.682, 1.134] and it keeps bouncing; there is no fixed point it is heading for. What it buys is speed off the mark: p'(0) = 3.4445 against the classical 1.875, so a singular value that starts near zero grows nearly twice as fast per step.

That trade is the whole design, and here is what it is worth. Starting from singular values spanning a factor of a thousand, the ratio of largest to smallest after k steps:

k       Muon        classical
1       267         557
3       30.7        159
5       2.60        45.1
7       1.52        12.9
9       1.59        3.72

At the five steps Muon runs, it is seventeen times tighter than the classical polynomial, and tighter at five steps than the classical one manages at nine. It also stops improving after that, around 1.5, because by then it is just moving around inside the band. An optimizer does not need an orthonormal matrix. It needs a direction whose singular values are all about the same size, and it needs it before the next step.

Used with import polar.

Look inside this program

  • Atlas

    The program’s map: every function and which calls which.

  • There’s no recorded run of this program yet.

Shift+Enter in a cell runs it and moves to the next. Running a cell runs every cell above it too, as one program.

[1]lines 53–265