This package provides a generic implementation of the Newton-Schulz method for computing various matrix functions such as the matrix sign and matrix square root.
This package provides iterative methods for computing various matrix functions, for example, the following computes the matrix sign of a rectangular matrix A using the PolarExpress coefficients.
O = msign(A, PolarExpress())All provided methods perform a default number of iterations, which can be over-riden as follows
O = msign(A, PolarExpress(), nsteps)All the matrix functions in this package follow this interface.
-
msign: Compute the matrix sign of a rectangular matrix -
mcsgn: Compute the matrix sign of a square matrix -
msqrt: Compute the arithmetic square root of a square positive semidefinite matrix -
mrsqrt: Compute the inverse square root of a square positive semidefinite matrix -
matmul_mrsqrt: Compute the product$A B^{-1/2}$ of a rectangular matrix$A$ and a square positive semidefinite matrix$B$ -
newton_schulzandnewton_schulz!: Perform a generic Newton-Schulz iteration -
newton_schulz_squareandnewton_schulz_square!: Perform a generic Newton-Schulz iteration on a square matrix.
All of the above functions use the iterative approach described below, with several choices of coefficients available.
ClassicalNewtonSchulz: The classical Newton-Schulz coefficients. This method converges slowly compared to other methods, do it is generally not recommended.NSJordan: The coefficients presented in https://kellerjordan.github.io/posts/muon/. These coefficients are designed to get a fast approximation ofmsignunder very low tolerances (O(0.1)), for use in the Muon optimizer.PolarExpressA set of coefficients designed for high tolerances (See https://arxiv.org/abs/2505.16932).NSJianlinSuA set of coefficients designed in https://kexue.fm/archives/10996 using the same principle asPolarExpress.
For general purposes, either PolarExpress or NSJianlinSu are suitable. The number of steps should in general be tuned to obtain the desired tolerance.
The matrix sign of a rectangular matrix
where
Using the SVD decomposition is the simplest method to compute
where
This package exports functions msign and newton_schulz to perform these computations.
A = randn(5, 10)
O_1 = msign(A, MSignSVD()) # compute using SVD
O_2 = msign(A, PolarExpress(), 10) # compute using Newton-SchulzConcretely, msign can be computed either via SVD using the MSignSVD method, or via Newton-Schulz with any of the coefficients outlined above.
For square matrices, we can define an alternative function,
This latter function is invariant under similarity transformation ($\text{mcsgn}(PAP^{-1}) = \text{mcsgn}(A)$), and if
This function can be approximated by a similar iteration as for msign, namely
The same coefficients used for msign can be used for this.
A = rand(10, 10)
O = mcsgn(A, PolarExpress())The mcsgn iteration can be adapted to compute the arithmetic matrix square root of a square positive semidefinite matrix msqrt function
A = randn(10,10)
A = A * A'
B = msqrt(A, PolarExpress(), 10) # More iterations neededA similar method makes it possible to compute the inverse square root, via the mrsqrt function
C = mrsqrt(A, PolarExpress(), 10)Beware that this method will perform poorly when matmul_mrsqrt function
A = randn(20,10)
B = randn(10,10)
B = B * B'
C = matmul_mrsqrt(A, B, PolarExpress(), 10)TODO
Much of the inspiration for this package came from Jianlin Su's excellent blog posts on the subject, and most of the applications implemented in this package are adapted from there.
- https://kexue.fm/archives/10996
- https://kexue.fm/archives/11025
- https://kexue.fm/archives/11056
- https://kexue.fm/archives/11158
AI generated english translations of these can be found here.
- Basic SVD version of
msign - Generic Newton-Schulz interface
-
msignimplementation -
mcsgnimplementation - AD Rules for
msign(following https://kexue.fm/archives/11025, https://kexue-tl.pages.dev/11025-The-Derivative-of-the-msign-Operator) - Matrix square root and inverse square root
- Matrix nth root
- Explicit GPU support