Skip to content

feat: add preconditioning and coef presets to muon - #1602

Merged
copybara-service[bot] merged 2 commits into
google-deepmind:mainfrom
massena-t:feat/muon-preconditioning
Feb 23, 2026
Merged

copybara-service[bot] merged 2 commits into
google-deepmind:mainfrom
massena-t:feat/muon-preconditioning

Conversation

@massena-t

Copy link
Copy Markdown
Contributor

Add Preconditioning to the Muon Optimizer

In this commit, we implement different preconditioning methods for the Muon optimizer. Notably:

These options allow the user to tweak the trade-off between convergence speed of the Newton-Schulz iterative scheme and the computational budget associated to the preconditioning method.

We also add options to choose the coefficients used in the Newton-Schulz iterations. Further development could implement the PolarExpress (https://arxiv.org/abs/2505.16932) or CAN methods (https://arxiv.org/abs/2506.10935).

@google-cla

google-cla Bot commented Feb 11, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@massena-t
massena-t marked this pull request as draft February 11, 2026 15:38
Co-authored-by: Thibaut Boissin <thibaut.boissin@irt-saintexupery.com>
@massena-t
massena-t force-pushed the feat/muon-preconditioning branch from 669d7dd to cb97a46 Compare February 12, 2026 17:21
@massena-t
massena-t marked this pull request as ready for review February 13, 2026 15:58

@rdyro rdyro left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this is great! I left a few comments.

Comment thread optax/contrib/_muon_test.py
Comment thread optax/contrib/_muon.py Outdated
Comment thread optax/contrib/_muon.py
Comment thread optax/contrib/_muon.py
Comment thread optax/contrib/_muon.py Outdated
@massena-t

Copy link
Copy Markdown
Contributor Author

Thanks for the feedback! Just pushed the fixes to address the comments. Let me know if anything else needs tweaking.

@massena-t
massena-t requested a review from rdyro February 21, 2026 12:50

@rdyro rdyro left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

@copybara-service
copybara-service Bot merged commit 00a031a into google-deepmind:main Feb 23, 2026
16 checks passed
shoemoney added a commit to shoemoney/optax that referenced this pull request Sep 1, 2026
…ex inputs

The modified first Newton-Schulz step for 'schatten' preconditioning
computes the Gram matrix as a = x @ x.T, which for complex x is not the
Hermitian Gram matrix, so the iteration diverges and
orthogonalize_via_newton_schulz returns an all-NaN array for complex
parameters. Any muon(preconditioning='schatten') step on a complex model
NaN-poisons the parameters on the first update.

Same file, same function family: _aol_first_newton_schulz_iteration
(line 217, a = x @ x.T.conj()) and _base_newton_schulz_iteration
(line 247, a = x @ x.T.conj()) both take the conjugate; schatten, added
alongside aol in PR google-deepmind#1602, is the only one that omitted it.

.conj() is a no-op for real dtypes, so real-input behavior is unchanged.

test_newton_schulz is now parameterized over frobenius, aol, and
schatten so the existing real-orthogonality and complex-unitarity
assertions cover all three paths; the schatten complex case fails with
all-NaN output before this fix and passes after.
shoemoney added a commit to shoemoney/optax that referenced this pull request Sep 18, 2026
…ex inputs

The modified first Newton-Schulz step for 'schatten' preconditioning
computes the Gram matrix as a = x @ x.T, which for complex x is not the
Hermitian Gram matrix, so the iteration diverges and
orthogonalize_via_newton_schulz returns an all-NaN array for complex
parameters. Any muon(preconditioning='schatten') step on a complex model
NaN-poisons the parameters on the first update.

Same file, same function family: _aol_first_newton_schulz_iteration
(line 217, a = x @ x.T.conj()) and _base_newton_schulz_iteration
(line 247, a = x @ x.T.conj()) both take the conjugate; schatten, added
alongside aol in PR google-deepmind#1602, is the only one that omitted it.

.conj() is a no-op for real dtypes, so real-input behavior is unchanged.

test_newton_schulz is now parameterized over frobenius, aol, and
schatten so the existing real-orthogonality and complex-unitarity
assertions cover all three paths; the schatten complex case fails with
all-NaN output before this fix and passes after.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants