Optimization2018advanced13 min read

Shampoo: Preconditioned Stochastic Tensor Optimization

Shampoo: أمثَلة المُوتِّرات العشوائية بالتكييف المُسبَق

Gupta, V. · Koren, T. · Singer, Y. — ICML

The problem

Preconditioned methods like full- converge faster than simple because they adapt to the of the . But the is a matrix whose size is the square of the number of parameters — storing and inverting it is completely infeasible for modern neural networks with millions of parameters. Diagonal approximations like throw away all cross-parameter curvature information.

The contribution

Shampoo exploits the structure of parameters. Instead of one huge preconditioner, it maintains a separate, smaller preconditioner matrix for each dimension of the parameter tensor. For an m×n , this means an m×m left preconditioner and an n×n right preconditioner — storage of m²+n² instead of m²n². The of these matrices provably lower-bounds the full preconditioner, so Shampoo captures cross-parameter curvature that diagonal methods miss, with guarantees in the stochastic convex setting and O(√T) .

The impact

Shampoo demonstrated that structured is practical at scale. A variant of Shampoo won the inaugural AlgoPerf optimization benchmark. Its Kronecker factorization idea connects to K-FAC and directly inspired the Muon and SOAP. The theoretical framework linking tensor structure to efficient preconditioning also informed research on maximal update parameterization (muP) for scaling neural networks.

Imagine you manage a conference hall with a seating chart arranged in rows and columns. You need to adjust every seat's height to fit each guest perfectly.

SGD gives you one wrench and says "turn each bolt the same amount." Adam gives you a smarter wrench that remembers how much each individual bolt has been turned — but it treats each seat in isolation, ignoring that an entire row might be too low or an entire column too narrow.

Shampoo gives you two adjustment rods: one slides along the rows and one along the columns. The row rod knows the overall pattern of that row; the column rod knows its column. Together they capture the shape of the whole hall — not just individual seats — so every adjustment is informed by the structure around it. And because each rod is much shorter than the full seating chart, you can handle them easily.

The dilemma: powerful preconditioning vs. feasible computation

The loss landscapes of neural networks are far from isotropic: some directions have sharp curvature while others are nearly flat. A first-order optimizer like SGD uses the same for every direction, so it oscillates in the steep directions and crawls in the flat ones. This is the fundamental motivation for preconditioning — multiplying the gradient by a matrix that rescales each direction according to the local curvature.

Full-matrix AdaGrad does exactly this: it accumulates the outer products of past gradients into a single matrix Ht=∑s=1tgsgs⊤H_t = \sum_{s=1}^{t} g_s g_s^\top and uses Ht−1/2H_t^{-1/2} to precondition the gradient. The result is an adaptive step size for each direction in parameter space that provably achieves optimal regret. The problem? For a network with dd parameters, HtH_t is a d×dd \times d matrix. A modest layer with 1000 inputs and 1000 outputs has d=106d = 10^6 parameters, making HtH_t a 106×10610^{6} \times 10^{6} matrix — a trillion entries. Storing it, let alone inverting it, is completely impossible.

Practitioners therefore use diagonal approximations: Adam tracks only the element-wise of each parameter. This is cheap — O(d)O(d) memory — but it throws away all information about how parameters interact. The cross-parameter curvature that makes full preconditioning so powerful is entirely lost.

Open in Lab
Compare the memory cost of full-matrix, diagonal, and Shampoo preconditioning for different layer sizes.
The demo wakes as you arrive…

The insight: parameters are tensors, not flat vectors

The key observation behind Shampoo is deceptively simple: neural network parameters are naturally organized as matrices and tensors, not as flat vectors. A 's weights form an m×nm \times n matrix. A 's weights form a 4D tensor (input-depth × width × height × output-depth). Flattening these into a single vector, as full-matrix methods require, discards the structural information that could make preconditioning tractable.

Shampoo asks: what if we precondition each dimension of the tensor separately? For an m×nm \times n weight matrix WW, instead of one mn×mnmn \times mn preconditioner, maintain two smaller matrices — a left preconditioner Lt∈Rm×mL_t \in \mathbb{R}^{m \times m} that captures row-wise (output) curvature, and a right preconditioner Rt∈Rn×nR_t \in \mathbb{R}^{n \times n} that captures column-wise (input) curvature.

Open in Lab
How Shampoo decomposes a single huge preconditioner into per-dimension matrices. Click each dimension to see the corresponding preconditioner.
The demo wakes as you arrive…

The update rule accumulates gradient statistics separately for each dimension. On each step tt, given the gradient matrix GtG_t:

  • Update the left preconditioner: Lt=Lt−1+GtGt⊤L_t = L_{t-1} + G_t G_t^\top (captures row correlations)
  • Update the right preconditioner: Rt=Rt−1+Gt⊤GtR_t = R_{t-1} + G_t^\top G_t (captures column correlations)
  • Take the preconditioned step: Wt+1=Wt−η Lt−1/4 Gt Rt−1/4W_{t+1} = W_t - \eta \, L_t^{-1/4} \, G_t \, R_t^{-1/4}

Notice that GtGt⊤G_t G_t^\top is just an m×mm \times m matrix and Gt⊤GtG_t^\top G_t is n×nn \times n — both are easy to store and manipulate. The key is the −1/4-1/4 power (rather than −1/2-1/2 as in full AdaGrad): since there are two preconditioners contributing, each takes a square root of the square root, resulting in the familiar O(1/t)O(1/\sqrt{t}) effective step-size decay.

Wt+1=Wt−η Lt−1/4 Gt Rt−1/4W_{t+1} = W_t - \eta \, L_t^{-1/4} \, G_t \, R_t^{-1/4}
Shampoo update rule for matrices — the core equation — The gradient G is preconditioned from the left by L (row curvature) and from the right by R (column curvature). Each raised to the -1/4 power so the combined effect matches the -1/2 power of full-matrix preconditioning.

Why it works: the Kronecker product connection

The theoretical justification for Shampoo comes from a beautiful connection to the Kronecker product. When you flatten the weight matrix WW into a vector w=vec‾(W)w = \overline{\text{vec}}(W), the Shampoo update becomes a standard preconditioned gradient step with preconditioner Ht=Lt1/4⊗Rt1/4H_t = L_t^{1/4} \otimes R_t^{1/4}, where ⊗\otimes denotes the Kronecker product.

The critical insight is Lemma 8 from the paper: the Kronecker product of the per-dimension statistics lower-bounds the full statistics matrix. Formally, for gradients of at most rr:

ϵI+1r∑tgtgt⊤  ≤  LT1/2⊗RT1/2\epsilon I + \frac{1}{r} \sum_t g_t g_t^\top \;\leq\; L_T^{1/2} \otimes R_T^{1/2}

This means Shampoo's implicit preconditioner is at least as strong as the full-matrix preconditioner (up to a rank factor). The small eigenvalues — which are the most important for effective preconditioning because they correspond to poorly-conditioned directions — are preserved. Shampoo doesn't just approximate the full preconditioner; it provably dominates it in the operator sense.

Open in Lab
Drag the layer size sliders to see how the Kronecker factorization compresses the preconditioner while preserving its spectral structure.
The demo wakes as you arrive…

Beyond matrices: Shampoo for general tensors

The matrix case is clean and intuitive, but Shampoo's real power emerges with higher-order tensors. A convolutional layer's weights are 4-dimensional: input-channels × width × height × output-channels. Shampoo maintains a separate preconditioner for each of these four dimensions.

The algorithm generalizes cleanly. For an order-kk tensor of dimensions n1×⋯×nkn_1 \times \cdots \times n_k, Shampoo maintains kk preconditioner matrices Hti∈Rni×niH_t^i \in \mathbb{R}^{n_i \times n_i}. Each is updated using the contraction of the gradient with itself along all but the ii-th dimension: Hti=Ht−1i+Gt(i)H_t^i = H_{t-1}^i + G_t^{(i)}, where Gt(i)=mati(Gt)mati(Gt)⊤G_t^{(i)} = \text{mat}_i(G_t)\text{mat}_i(G_t)^\top. The preconditioned gradient is obtained by multiplying each dimension by (Hti)−1/2k(H_t^i)^{-1/2k} using the tensor-matrix product ×i\times_i.

This extension is non-trivial: the convergence analysis requires proving that the Kronecker product of kk dimension-wise preconditioners still lower-bounds the full preconditioner. The proof uses the operator monotonicity of geometric means of commuting positive semidefinite matrices — a deep result from matrix analysis.

G~t=Gt×1(Ht1)−1/2k×2(Ht2)−1/2k⋯×k(Htk)−1/2k\widetilde{G}_t = G_t \times_1 (H_t^1)^{-1/2k} \times_2 (H_t^2)^{-1/2k} \cdots \times_k (H_t^k)^{-1/2k}
Shampoo update rule for general order-k tensors — Each dimension i gets its own preconditioner with power -1/2k. The tensor-matrix product ×_i applies the preconditioner along dimension i while leaving other dimensions untouched.

Convergence guarantees: O(√T) regret

Shampoo's analysis is set in the framework. The learner sees a sequence of convex loss functions f1,…,fTf_1, \ldots, f_T and wants to minimize regret — the difference between its cumulative loss and the loss of the best fixed point in hindsight.

The main theorem (Theorem 10) bounds the regret of the general tensor version:

RegretT≤2r D∏i=1kTr((HTi)1/2k)\text{Regret}_T \leq \sqrt{2r}\, D \prod_{i=1}^{k} \text{Tr}\big((H_T^i)^{1/2k}\big)

where rr is the geometric mean of the gradient ranks across dimensions, DD is the diameter of the iterates, and HTiH_T^i is the accumulated statistics for dimension ii. Under standard assumptions, each trace term scales as O(T1/2k)O(T^{1/2k}), so the product of kk such terms gives O(Tk⋅1/2k)=O(T)O(T^{k \cdot 1/2k}) = O(\sqrt{T}) — the optimal rate for stochastic convex optimization.

Making it practical: implementation tricks

The raw algorithm requires computing matrix powers (Hti)−1/2k(H_t^i)^{-1/2k} every step, which involves an or SVD. Three practical tricks make Shampoo competitive in wall-clock time:

  • Delayed preconditioner updates. Recompute the matrix roots every 20–100 steps instead of every step. Between updates, reuse the stale roots. The authors found almost no accuracy loss from this delay.
  • . Incorporate standard momentum: Gˉt=αGˉt−1+(1−α)Gt\bar{G}_t = \alpha \bar{G}_{t-1} + (1-\alpha) G_t with α=0.9\alpha = 0.9. The preconditioners are still updated with the raw gradient, but the step is taken with the momentum-averaged gradient.
  • Diagonal fallback for large dimensions. When a dimension exceeds roughly 1200, switch to a diagonal preconditioner for that dimension only. Other dimensions continue to use full matrices. This makes Shampoo applicable even when some tensors have one very large dimension.

Surprisingly, despite its richer computation, Shampoo's runtime per step is comparable to SGD, Adam, and AdaGrad in practice. The matrix operations are highly parallelizable on GPUs, and the preconditioner matrices are small enough for efficient eigendecomposition.

Open in Lab
Step through the Shampoo algorithm iteration by iteration to see how the preconditioners evolve and reshape the gradient.
The demo wakes as you arrive…

Experiments: faster convergence across domains

The paper evaluates Shampoo on (CIFAR-10/100 with ResNets and Inception networks) and language modeling (LM1B with models). Across all experiments, Shampoo converged significantly faster than SGD, Adam, and AdaGrad in terms of steps.

On CIFAR-10 with a 32-layer ResNet, Shampoo reached lower training loss in roughly half the iterations needed by Adam. On LM1B language modeling, Shampoo achieved the same test as Adam in a fraction of the steps. Crucially, the runtime per step was comparable — the extra computation for maintaining and applying preconditioners was negligible compared to the forward and backward passes of the network itself.

Perhaps the most striking result is the runtime comparison: despite performing SVD-based matrix operations, Shampoo processes roughly the same number of batches per second as SGD on a Tesla K40 . In some configurations (ResNet-55 on CIFAR-100), Shampoo was actually faster per step than the baselines.

Open in Lab
Watch SGD, Adam, and Shampoo optimize the same loss surface. Shampoo navigates the anisotropic curvature far more efficiently.
The demo wakes as you arrive…

Shampoo vs. K-FAC: two paths to Kronecker preconditioning

Both Shampoo and K-FAC use Kronecker-factored preconditioners, but they come from fundamentally different motivations:

  • K-FAC approximates the of a neural network by assuming statistical independence between the activations and the backpropagated gradients. It is deeply tied to the structure of in feed-forward networks and needs to sample from the model's predictive distribution.
  • Shampoo makes no assumptions about the model architecture. It simply observes that parameters live in tensor spaces and uses the gradient's own statistics to build per-dimension preconditioners. The theoretical guarantees hold for any convex loss, not just neural network losses.

This architectural agnosticism is Shampoo's key practical advantage: it works as a drop-in optimizer replacement. You don't need to modify the model or the training code — just swap the optimizer. K-FAC, by contrast, requires knowledge of each layer's type and structure, making it harder to implement as a general-purpose tool.

Legacy: from Shampoo to Muon and muP

Shampoo opened the door to a family of practical second-order optimizers for deep learning. Its influence radiates in several directions:

  • SOAP (2024) showed that Shampoo with the 1/2 power is equivalent to running Adafactor in the eigenbasis of the preconditioner, and stabilized Shampoo using Adam-like running averages instead of cumulative sums.
  • Muon (2024) simplifies Shampoo by dropping the temporal accumulation entirely: when you take just the current gradient's SVD and map it to its polar decomposition UV⊤UV^\top, you get an update that equalizes all singular values. Muon approximates this with Newton-Schulz iterations, which scale better than SVD, making it practical for very large models.
  • muP (Maximal Update Parameterization) research showed that Shampoo and K-FAC both connect to the deeper theoretical question of how to scale neural network parameterizations so that optimal hyperparameters transfer across model sizes. Proper scaling of Shampoo's terms enables width-invariant training.

A Shampoo variant won the inaugural AlgoPerf optimization competition in 2023, demonstrating that structured preconditioning can outperform Adam-family optimizers in a standardized benchmark setting.

  1. 2011

    AdaGrad: adaptive gradient accumulation

    Duchi, Hazan, and Singer introduce full-matrix and diagonal adaptive gradient methods with O(√T) regret. The full version is too expensive; the diagonal version becomes ubiquitous.

  2. 2015

    K-FAC: Kronecker-factored curvature

    Martens and Grosse approximate the Fisher matrix as a Kronecker product using the structure of backpropagation. Architecture-specific but very effective.

  3. 2018

    Shampoo: architecture-agnostic tensor preconditioning

    This paper. Kronecker-factored preconditioning from gradient statistics alone, with convergence guarantees and practical runtime comparable to first-order methods.

  4. 2023

    AlgoPerf: Shampoo variant wins optimization benchmark

    A refined version of Shampoo wins the inaugural MLCommons AlgoPerf benchmark, demonstrating practical superiority over Adam-family optimizers across diverse tasks.

  5. 2024

    SOAP and Muon: Shampoo simplified

    SOAP connects Shampoo to Adafactor via eigendecomposition; Muon drops temporal accumulation entirely and uses polar decomposition for an even simpler update. Both build directly on Shampoo's Kronecker insight.

Shampoo optimizer — simplified pseudocode for the matrix casepython

Simplified to show the idea — not the real implementation.

# Shampoo for a single m×n weight matrix W
import numpy as np

def shampoo_step(W, G, L, R, lr, epsilon=1e-6):
    """
    W:  current weights         (m × n)
    G:  gradient of loss w.r.t W (m × n)
    L:  left preconditioner      (m × m)
    R:  right preconditioner     (n × n)
    lr: learning rate
    """
    # 1. Accumulate second-moment statistics
    L = L + G @ G.T          # row (output) curvature
    R = R + G.T @ G          # column (input) curvature

    # 2. Compute matrix -1/4 power via eigendecomposition
    def mat_power_neg_quarter(M):
        eigvals, eigvecs = np.linalg.eigh(M)
        eigvals = np.maximum(eigvals, epsilon)
        return eigvecs @ np.diag(eigvals ** (-0.25)) @ eigvecs.T

    L_inv4 = mat_power_neg_quarter(L)
    R_inv4 = mat_power_neg_quarter(R)

    # 3. Preconditioned update: left × gradient × right
    W_new = W - lr * (L_inv4 @ G @ R_inv4)

    return W_new, L, R

CitationGupta, V., Koren, T., Singer, Y.. Shampoo: Preconditioned Stochastic Tensor Optimization. ICML, 2018.

Terms in this paper