Empirical validation of the PolarGrad optimizer (Lau et al., 2025) across matrix optimization and language model pretraining benchmarks. PolarGrad applies polar decomposition (via QDWH or ZOLO-PD) as a gradient preconditioner, extending Muon with nuclear-norm scaling and without the need to tune Newton-Schulz polynomial coefficients.
| Requirement | Minimum | Recommended |
|---|---|---|
| GPU | A100 80GB (Ampere) | H100 SXM |
| GPU count | 1 (matrix experiments) | 1 (Qwen pretraining) |
| CUDA | 12.1+ | 12.6 |
bfloat16 |
Required (Ampere+) | β |
Note: V100 and earlier do not support native
bfloat16hardware arithmetic.torch.linalg.qr(used in QDWH) does not supportbfloat16on CUDA β PolarGrad upcasts gradients tofloat32internally at the top of each optimizer step and casts back before the weight update. The matrix optimization experiments run on CPU or single GPU.
This project uses pixi for reproducible environment management.
Install pixi:
curl -fsSL https://pixi.sh/install.sh | bashClone the repository (including the polargrad submodule):
git clone --recurse-submodules https://github.com/ethanmarq/polar-decomposition.gitIf you already cloned without --recurse-submodules, initialize the submodule manually:
git submodule update --init --recursiveBootstrap the environment (run once from the project root):
pixi installAll subsequent commands are run via pixi run β no manual conda activate or pip install needed.
polar-decomposition/
βββ polargrad/ # Core optimizer library
β βββ polar_grad.py # PolarGrad optimizer (single-device)
β βββ polar_grad_ddp.py # PolarGrad with torch.distributed (DDP)
β βββ polar.py # Polar decomposition dispatcher
β βββ qdwh.py # QDWH algorithm
β βββ zolopd.py # ZOLO-PD algorithm
β βββ newton_schulz.py # NS iteration (Muon-compatible)
β βββ polar_express.py # Polar Express (matrix-multiply only, bf16-safe)
β βββ muon.py # Muon baseline
βββ qwen/ # Qwen2.5 pretraining
βββ nonnegative_matrix_factorization/ # NMF (two constraint implementations)
βββ multi_response_linear_regression/ # Multi-response linear regression
βββ multinomial_logistic_regression/ # Softmax / multinomial logistic regression
βββ pixi.toml
All commands are run from the project root (polar-decomposition/).
(Except qwen, as it uses a batch script to run)
Scripts: qwen/train_qwen.py
PolarGrad or Muon is applied to 2D weight matrices; 1D parameters (biases, LayerNorm) are routed to AdamW.
(Note: Update submit_qwen.sh to use your palemtto username, .out, .err saved to scratch)
# Full Qwen2.5 pretraining (A100/H100 required)
cd qwen/
sbatch submit_qwen.sh adamw
sbatch submit_qwen.sh muon_adamw
sbatch submit_qwen.sh muon_polarsgdm
# Plot results
python plot_qwen_6_4.py \
--adamw results/qwen_adamw_lr0.001.json \
--muon_adamw results/qwen_muon_adamw_lr0.001.json \
--muon_polar results/qwen_muon_polarsgdm_lr0.001.json \
--outdir figures/Scripts: nonnegative_matrix_factorization/nmf_s.py Β· nonnegative_matrix_factorization/nmf_np.py
Given a nonnegative target matrix
The two scripts enforce the nonnegativity constraint differently:
Nonnegativity is enforced via a smooth reparameterization. The raw parameters self.X, self.Y are unconstrained; the forward pass applies softplus before computing the loss:
def forward(self, target):
X = torch.nn.functional.softplus(self.X)
Y = torch.nn.functional.softplus(self.Y)
return torch.sum((X @ Y.T - target) ** 2) / target.numel()The optimizer updates unconstrained variables, making the problem fully differentiable everywhere.
pixi run python -m nonnegative_matrix_factorization.nmf_sNonnegativity is enforced by projecting parameters onto the nonnegative orthant after each optimizer step. The forward pass computes the loss directly on self.X, self.Y, and the constraint is applied post-update:
def forward(self, target):
return torch.sum((self.X @ self.Y.T - target) ** 2) / target.numel()
# After optimizer.step():
model.X.data.clamp_(min=0)
model.Y.data.clamp_(min=0)pixi run python -m nonnegative_matrix_factorization.nmf_np main
# LR Sweep
# pixi run python nmf_np tune_lr --steps=1000 --n_seeds=3Script: multi_response_linear_regression/multi_response_linear_reg.py
Objective: Strongly convex matrix regression with deterministic gradients. Given fixed
The closed-form gradient is
pixi run python -m multi_response_linear_regression.multi_response_linear_regScript: multinomial_logistic_regression/softmax_log_reg.py
Objective: Strongly convex softmax regression with stochastic gradients. Given data
A zero column is prepended to the scores before logsumexp for numerical stability (reference class convention). Mini-batches of size 1000 are drawn each step. Plots track training loss, gradient condition number
pixi run python -m multinomial_logistic_regression.softmax_log_reg@article{lau2025polargrad,
title={\textsc{PolarGrad}: A Class of Matrix-Gradient Optimizers from a Unifying Preconditioning Perspective},
author={Lau, Tim Tsz-Kit and Qi Long and Weijie Su},
year={2025},
journal={arXiv preprint arXiv:2505.21799}
}