SOAP: IMPROVING AND STABILIZING SHAMPOO USING ADAM
Introduction
The success of Shampoo has drawn increasing attention from the deep learning community. Several works have explored ways to scale Shampoo by improving its memory and compute efficiency (Wang et al., 2024; Anil et al., 2020; Shi et al., 2023). Other research (Morwani et al., 2024) has examined the theoretical foundations of Shampoo and proposed minor adjustments (such as using power rather than ) that align with prior empirical findings (Anil et al., 2020).
We study SOAP (ShampoO with Adam in the Preconditioner's eigenbasis) an algorithm that runs AdamW in the eigenbasis provided by Shampoo. Our main contributions are as follows:
- We make a formal connection between the Shampoo and the Adafactor algorithm. This insight leads us to consider the SOAP algorithm, which runs AdamW in the preconditioned space provided by Shampoo.
- SOAP outperforms both Shampoo and Adam in language model pre-training tasks with model sizes 360m and 660m, even after extensive hyperparameter tuning of Shampoo.
- SOAP reduces the number of hyperparameters compared to Shampoo, resulting in only one additional hyperparameter compared to AdamW: preconditioning frequency.
- SOAP demonstrates greater robustness to large preconditioning frequency compared to Shampoo on language model pre-training tasks.
Notation and background
We denote the weight matrix of a neural network layer by , and the corresponding gradient by . At a given time step , these are denoted as and , respectively. For a batch of inputs at time , denoted by , the loss and its gradient evaluated at are represented as and , respectively.
Adam (Kingma & Ba, 2015), a widely used first-order optimization algorithm in deep learning is a diagonal approximation of Adagrad. It maintains an exponential moving average of the gradients (denoted as ) and of element-wise squared gradients (denoted as ) for a given weight matrix . Its update rule with learning rate is given by
where the division is performed element-wise.
Adafactor (Shazeer & Stern, 2018; Zhai et al., 2022), a variant of Adam, replaces with its best rank-1 approximation to reduce memory usage. While the original Adafactor paper (Shazeer & Stern, 2018) proposed additional modifications, such as changes to the learning rate schedule, we focus on the version of Adafactor proposed in recent works (Zhai et al., 2022; Zhao et al., 2024c), whose update with learning rate is given by
Shampoo (Gupta et al., 2018b) is a second-order optimization algorithm that approximates Adagrad and maintains two preconditioners, and , for a given weight matrix . The updates for the preconditioners and the weights with learning rate are as follows:
Algorithms
We begin by describing an equivalence between Shampoo and running Adafactor in the eigenbasis of the Shampoo preconditioner. For simplicity we omit momentum but the equivalence also holds with momentum. For this equivalence we use Shampoo with the following modifications from the original Shampoo optimizer (Gupta et al., 2018b):
- We use power instead of power . This was already recommended in practical implementations (Anil et al., 2020; Shi et al., 2023) and a theoretical connection between optimal Kronecker approximation of Adagrad (Duchi et al., 2011b) preconditioner and Shampoo with power was established in Morwani et al. (2024).
- We also use the scalar correction to per layer learning rates described in Ren & Goldfarb (2021); Morwani et al. (2024).
- Instead of the running average of and across time steps, we use dataset averages.
Algorithm 1 Single step of idealized Shampoo with power
- Sample batch .
- (Where the expectation is over a random batch B.)
Algorithm 2 Single step of idealized Adafactor in Shampoo's eigenspace.
- Sample batch .
- (Idealized version of Adafactor taking to be the gradient)
- where
- (Elementwise division)
- (Elementwise division and square root)
Proposition: Algorithms 1 and 2 are equivalent.
Proof: Consider in the basis created after rotating by i.e. . Let the eigenvalues of and be given by and respectively. Algorithm 1 scales the coordinate by , while Algorithm 2 scales them by . We now show that , an analogous argument shows .
While these two algorithms are equivalent in their idealized forms, practical considerations reveal some differences. Firstly, the algorithms differ when using running averages instead of dataset averages. Secondly, and more significantly in practice, we do not invert or compute the eigenvector decomposition of and at every step. This means that the "adaptivity" of learning rates in Shampoo is limited to the updates of and . In contrast, with Adafactor in Shampoo's eigenspace, the second moment estimates (i.e., and in Algorithm 2) can be updated at every step as they are computationally inexpensive. Additionally, instead of using Adafactor, we can opt for Adam, which offers more generality. Combining these insights leads to Algorithm 3 which can be interpreted as running Adam in Shampoo's eigenspace.
Algorithm 3 Single step of SOAP for a layer. Per layer, we maintain four matrices: and . For simplicity we ignore the initialization and other boundary effects such as bias correction. Hyperparameters: Learning rate , betas , epsilon , and preconditioning frequency .
- Sample batch .
- {Now we "run" Adam on }
- (Elementwise multiplication)
- (Elementwise division and square root)
- {Now that we have preconditioned by Adam in the rotated space, we go back to the original space.}
- {End of gradient step, we now update and and possibly also and .}
- if then
- end if
We now describe some additional implementation details:
- Algorithm 3 describes the behavior of the algorithm for 2D layers. Following Zhao et al. (2024a), for 1D layers we run standard AdamW. This reduces the overhead as compared to standard implementations of Shampoo which solve an eigenvector problem for 1D layers too.
- Following Wang et al. (2024), we compute eigenvectors of (and ) using one step of power method (Algorithm 4). This requires doing one matrix multiplication followed by QR decomposition. QR decomposition is faster than standard eigenvector decomposition in PyTorch. For the first iteration, eigenvectors are initialized by doing a standard eigenvector decomposition.
- For layers with huge dimensions such as the first and last layer in language modeling transformers, maintaining the eigenvectors would be space and time prohibitive. For such dimensions we fix the rotation matrix ( or ) to be identity. Note that if we fix both and to be identity for a 2D layer, we would recover Adam.
- Algorithm 3 omits bias correction and weight decay for simplicity, but these are used in the actual implementation, identical to their use in AdamW.
Experimental Methodology
Hyperparameter tuning: We begin with hyperparameter values suggested by prior research for both AdamW and Distributed Shampoo (e.g., ). Initially, we conduct a learning rate sweep to determine the optimal learning rate for each optimizer. Once the optimal learning rate is identified, we perform two-dimensional sweeps for each of the remaining hyperparameters, where we vary the selected hyperparameter alongside the learning rate. The purpose of these sweeps is to demonstrate that our default hyperparameter settings are near-optimal, disregarding potential interactions between two non-learning-rate hyperparameters.
Throughput Measurement: We evaluate the throughput of each optimizer by measuring the number of tokens processed per second. At present, we perform these measurements on a single H100 GPU and utilize gradient accumulation to accommodate large batch sizes. While this approach may seem to disadvantage AdamW—as the overhead of Shampoo/SOAP is compared against multiple gradient accumulation steps—it is important to note that the overhead of Shampoo/SOAP can be amortized across layers by distributing the updates across multiple GPUs. This technique is employed in the distributed implementation of Shampoo (Shi et al., 2023).
Efficiency Benefits: Simply running SOAP for the same duration as Shampoo and AdamW cannot be directly used to calculate the efficiency benefit (in terms of training steps or wall-clock time) of using SOAP since we use a cosine schedule. Therefore, we run SOAP on .5, .625, .75 and .875 fraction of the training data and fit a scaling law of the form through the final losses obtained, where represents the number of training points and are the parameters of the fit. This scaling law is then used to calculate the efficiency benefit in terms of training steps and wallclock time. Here, the horizontal lines represent the final losses of AdamW and Shampoo.
Language Modeling Experiments
Further Efficiency Improvements
One Sided Eigenbasis
Doing this leads to a reduction in space usage as well as reduction of optimizer time overhead.
Space Usage of SOAP
For a matrix, we require
space usage.
The most direct way to reduce memory is using low precision to store the matrices. There are two algorithmic approaches to improving the space usage of SOAP:
- Using Adafactor instead of Adam as the diagonal preconditioner after rotating by and . This reduces the space usage by .
- Using one sided version of SOAP. This reduces space usage from to .
- Combining these approaches yields space usage of .
We try these approaches and observe that using Adafactor instead of AdamW yields very small reductions in performance while using one-sided preconditioner results in larger reductions. Nonetheless even after combining these two approaches the resulting optimizer outperforms AdamW while having a smaller space requirement than AdamW.
Time Overhead of SOAP
There are two types of overhead of Shampoo and SOAP over AdamW: the overhead per step and the overhead when changing the preconditioner (or for SOAP, the preconditioner's eigenbasis). Let us first analyze the first one. For SOAP per step for a layer of size we have an overhead of
Improving Time Overhead of SOAP
The per step overhead of SOAP can be reduced by using low precision to store the matrices. This approach cannot be used for reducing the overhead for the preconditioner update in popular deep learning frameworks such as PyTorch since torch.linalg.qr does not support precision lower than float32. Orthogonal to the low precision approach we can improve the per step time overhead of SOAP by the following algorithmic approaches:
- Using Adafactor instead of Adam as the diagonal preconditioner after rotating by and .
- Using one sided version of SOAP. This reduces overhead from to .
- Combining these approaches yields overhead of .