AI Grimoire
Sheet
statusstandard
difficultyintroductory
timeO(d)
memoryO(d)
described2017
revised3w ago

AdamW

Adam, with the one change that matters: weight decay applied to the parameter directly rather than smuggled in as an L2 term that the adaptive step then rescales.

Standing

Current standardPart of the default recipe. Present in most frontier models trained today, and the thing a new design departs from rather than argues for.

Decoupled weight decay is the default everywhere. The challengers are real but none has displaced it.

judged as of 2026-09 · what the labels mean

Theory

Adam keeps two exponential moving averages per parameter — of the gradient and of its square — and steps along the first divided by the root of the second.

mt=β1mt1+(1β1)gt,vt=β2vt1+(1β2)gt2m_t = \beta_1 m_{t-1} + (1-\beta_1) g_t, \qquad v_t = \beta_2 v_{t-1} + (1-\beta_2) g_t^2
eq. 1 — moments and their bias correction

Both are initialised at zero, so early estimates are biased toward it. Dividing by 1βt1 - \beta^t removes the bias exactly; with β2=0.999\beta_2 = 0.999 the correction is still a factor of two at step 700, which is why omitting it produces the famous need for a longer warmup.

m^t=mt1β1t,v^t=vt1β2t,θt=θt1η(m^tv^t+ε+λθt1)\hat{m}_t = \frac{m_t}{1-\beta_1^t}, \quad \hat{v}_t = \frac{v_t}{1-\beta_2^t}, \quad \theta_t = \theta_{t-1} - \eta \left( \frac{\hat{m}_t}{\sqrt{\hat{v}_t} + \varepsilon} + \lambda \theta_{t-1} \right)
eq. 2 — the update

The decoupling

Classic L2 adds λθ\lambda\theta to the gradient, so it enters mm and vv and is then divided by v^\sqrt{\hat v} along with everything else. The effective decay becomes per-parameter and inversely proportional to gradient history. AdamW applies λθ\lambda\theta outside the adaptive step, as in eq. 2, so every parameter decays at the same rate.

L2:    θ=ηm^(g+λθ)v^+εdecoupled:    θ=ηm^(g)v^+ε+ηλθ\text{L2:}\;\; \theta \mathrel{-}= \eta \frac{\hat{m}(g + \lambda\theta)}{\sqrt{\hat{v}} + \varepsilon} \qquad \text{decoupled:}\;\; \theta \mathrel{-}= \eta\frac{\hat{m}(g)}{\sqrt{\hat{v}} + \varepsilon} + \eta\lambda\theta
eq. 3 — what L2 actually does inside Adam

The consequence for tuning is that η\eta and λ\lambda decouple too: under L2 they interact, and a learning-rate sweep silently sweeps the regularisation strength with it.

Implementation

python · torch ≥ 2.1
import torch
from torch import Tensor


@torch.no_grad()
def adamw_step(
    p: Tensor, grad: Tensor, m: Tensor, v: Tensor, step: int,
    lr: float = 3e-4, betas: tuple[float, float] = (0.9, 0.95),
    eps: float = 1e-8, weight_decay: float = 0.1,
) -> None:
    b1, b2 = betas
    m.mul_(b1).add_(grad, alpha=1 - b1)
    v.mul_(b2).addcmul_(grad, grad, value=1 - b2)

    m_hat = m / (1 - b1**step)
    v_hat = v / (1 - b2**step)

    # decay the weight itself, untouched by the adaptive scale
    p.mul_(1 - lr * weight_decay)
    p.addcdiv_(m_hat, v_hat.sqrt().add_(eps), value=-lr)

β2=0.95\beta_2 = 0.95 rather than Adam’s default 0.9990.999 is near-universal for language models: the shorter window reacts faster to the variance spikes that precede a loss divergence. Keep the moments in fp32 whatever the compute dtype — vv in bf16 underflows to zero for small gradients, and the step then divides by ε\varepsilon.

fp32 master
4 B
momentum + variance
8 B
total state
12 B
per parameter, mixed-precision training

Related

References

[1]Loshchilov & Hutter — Decoupled Weight Decay Regularization (2017)arXiv:1711.05101
[2]Kingma & Ba — Adam: A Method for Stochastic Optimization (2014)arXiv:1412.6980
[3]Reddi et al. — On the Convergence of Adam and Beyond (2019)arXiv:1904.09237