The idea
Every optimizer in common use is gradient descent with refinements. The ladder, one rung at a time:
SGD. , with the gradient on a random minibatch. Unbiased but noisy, and one global has to suit every parameter in the network at once.
Watch the learning rate itself decide the outcome on a single parameter — too small crawls, too large overshoots and oscillates, too large still and it diverges:
Each step scales distance-to-minimum by (1 − 2η) ≈ 0.40 — at η = 0.30 that is converging smoothly.
+ Momentum. Keep a velocity — an exponentially weighted average of recent gradients — and step along it:
With , a direction the gradients agree on compounds toward a terminal velocity of , while components that alternate sign cancel. Effect: faster along consistent directions, damped oscillation across steep narrow ravines, minibatch noise averaged out.
The ravine language is literal — here is a basin with exactly that kind of ridge running across it, and a ball spiraling down into it:
Loading the interactive 3D loss-surface visualization…
+ Per-parameter scale (RMSProp idea). Track a running average of the squared gradient and divide by its root, so each parameter gets a step size inversely proportional to its typical gradient magnitude. Parameters with rare, small gradients (embedding rows, early layers) stop being starved by a global chosen for the loudest layer.
Adam = both + bias correction.
Defaults: , , . The ratio is roughly gradient-scale-free, which is why Adam works out of the box across wildly different architectures.
AdamW fixes one subtlety: L2 regularization added into the gradient gets divided by like everything else, so exactly the weights with large gradient variance feel less decay. AdamW applies decay directly to the weights, , outside the adaptive machinery — the standard for transformers.
Worked example
Bias correction, with numbers. Single parameter, constant gradient , defaults above. At :
Uncorrected, the step would be — a 3x overshoot on step one, purely an artifact of the zero-initialized averages (and it gets worse for smaller /larger gaps). With correction:
Exactly the sensible thing: first step of size in the gradient direction.
Scale invariance, same setup. Repeat with everywhere: , , step . Identical. Adam takes -sized steps whether the raw gradients are of order or — with SGD, those two scenarios would need learning rates 1000x apart. That is the practical content of "adaptive".
Cheat sheet
| Optimizer | Update | Adds | State/param |
|---|---|---|---|
| SGD | — | 0 | |
| SGD + momentum | ; | direction smoothing | 1 |
| RMSProp | , EMA of | per-param scale | 1 |
| Adam | momentum + RMS scale + bias correction | both | 2 |
| AdamW | Adam + decoupled decay | correct weight decay | 2 |
- Defaults: (momentum); Adam , , ; AdamW -.
- LR starting points: SGD+momentum (vision) with batch 256 + decay; Adam generic ; transformer pretraining - with warmup; fine-tuning -.
- Terminal velocity: constant gradient → momentum amplifies steps by ; remember 10x at .
- Schedules: warmup (linear, first 1-5% of steps) then cosine or linear decay is the modern default recipe.
Symptoms → fixes
- Loss diverges / NaNs in first steps → LR too high or no warmup; add warmup, clip gradient norm to ~1.
- Loss plateaus early, gradients healthy → LR too low or decayed too soon.
- Adam trains, SGD stalls → heterogeneous gradient scales; keep Adam or fix normalization.
- Overfitting with Adam + L2 "not helping" → decay is being adaptively rescaled; switch to AdamW.
- Extra GPU memory 2-3x parameter count during training → optimizer state (, ) — expected, not a leak.