LLM + RoboticsModule 12 · Video 07

Optimisers from gradient descent to AdamW

Almost every large model in this course, and most robot policies, is trained with AdamW. This short video walks the family tree that leads there: plain gradient descent, momentum, RMSProp, Adam, and the one-line fix that turns Adam into AdamW. This guide explains each step from the original sources and gives you a 2D "optimiser race" to play with.

Video length7:19
Published11 October 2024
LevelIntroductory: gradients and a loss function are enough
Builds onModule 08 · Stage 01 (autograd), Module 08 · Stage 06 (optimiser-state memory)

Video by Jia-Bin Huang · Watch on YouTube

Start here (no maths needed)

Training a model means nudging millions of knobs, a tiny bit at a time, so its mistakes get smaller. An optimiser is the rule that decides how far to turn each knob on each step.

Think of it like this

You're lost on a foggy hillside and want to reach the lowest point of the valley. You can only feel the slope under your feet. The simplest rule is "step downhill". But the valley is long and narrow: the sides are steep and the floor slopes gently. If you only follow the slope, you zig-zag from wall to wall and crawl along the floor. A rolling ball does better, because it builds up speed along the floor and the side-to-side wobbles cancel out. A careful hiker does better too, by taking small steps where the ground is steep and bigger steps where it's flat. Adam does both. AdamW adds a gentle elastic band pulling you back towards home, so you don't wander off to some extreme spot.

How it works

  1. Measure the slope (the gradient) for every knob.
  2. Gradient descent: move every knob a little way downhill.
  3. Momentum: keep a running average of recent slopes, so steady directions speed up and wobbles cancel.
  4. RMSProp: keep a running average of how big each knob's slopes have been, and take smaller steps on knobs with big, jumpy slopes.
  5. Adam combines the two, and AdamW adds a separate, steady shrink of every knob towards zero (weight decay).

Why robots care

Robot policies, from small grasping networks to big vision-language-action models, are trained with these same rules. A good optimiser means fewer hours of GPU time and fewer failed training runs, and the weight-decay part helps a policy not over-fit to the few hundred demonstrations you recorded.

Try it

Words to know

Loss
One number saying how wrong the model is. Training tries to make it small.
Gradient
The slope of the loss for every parameter: which way is uphill, and how steep.
Learning rate
How big a step to take each time.
Momentum
A running average of past gradients that keeps you moving in steady directions.
Weight decay
Shrinking every weight a little each step, so the model prefers small weights.

Going deeper: everything below is the full version, with some maths. On a first read, skim the headings and the "Why it matters for robotics" box, and come back for the rest later.

1. Watch

Topic guide

The description for this video has no chapter timestamps. It names five topics, listed here in the order it gives them, so this table has no time links. The whole video is just over seven minutes, so watching straight through is easy.

Topic (from the description)What to look for
Gradient descentThe basic update, the role of the learning rate, and why a narrow valley (very different curvature in different directions) makes it slow.
MomentumHow averaging past gradients damps the side-to-side oscillation and speeds progress along the valley floor.
RMSPropDividing each parameter's step by a running root-mean-square of its gradients, so every direction gets a step of similar size.
AdamMomentum and RMSProp combined, plus bias correction for the zero-initialised averages.
AdamWThe difference between adding an L2 penalty to the loss and decaying the weights directly, and why that difference only appears for adaptive optimisers.

2. The ideas, explained

Gradient descent and the narrow-valley problem

Given a loss L(θ) and its gradient g = ∇L(θ), gradient descent repeats one update. In deep learning the gradient comes from a mini-batch rather than the whole dataset, which makes it stochastic gradient descent (SGD).

θ ← θ − η · g          η = learning rate

on a quadratic with curvature h along some direction:
  error_next = (1 − η·h) · error
  stable only if η < 2 / h_max

The last line is the whole problem. The steepest direction (largest curvature h_max) caps the learning rate, and with that small η the flattest direction (smallest curvature h_min) creeps along at a rate set by η·h_min. The ratio h_max/h_min, the condition number, says how badly a single learning rate fits. Neural-network losses are badly conditioned, so the two fixes below attack exactly this: momentum by accumulating speed along the flat direction, adaptive methods by giving each parameter its own step size.

Momentum

Heavy-ball momentum goes back to Polyak (1964). Sutskever, Martens, Dahl and Hinton (2013) showed that momentum with a well-chosen schedule matters a lot for training deep networks. The common form keeps a velocity:

v ← μ · v + g          μ ≈ 0.9
θ ← θ − η · v

Along a direction where the gradient keeps the same sign, v grows towards g/(1 − μ), so the effective step is up to 10× larger at μ = 0.9. Along a direction where the gradient flips sign each step (the valley walls), the terms partly cancel. Nesterov's variant evaluates the gradient at the look-ahead point θ − ημv and is often a little more stable.

RMSProp

RMSProp was never published as a paper. Geoffrey Hinton introduced it in lecture 6 of his 2012 Coursera course, Neural Networks for Machine Learning, and the slides (the video's first reference) are the usual citation. The idea is to divide each parameter's gradient by a running estimate of its typical size:

s ← ρ · s + (1 − ρ) · g²      (elementwise; the slides suggest ρ = 0.9)
θ ← θ − η · g / (√s + ε)

A parameter with consistently large gradients gets its step shrunk; one with tiny gradients gets it enlarged. In the narrow valley, both directions end up moving at a similar speed of roughly η per step, regardless of curvature. RMSProp descends from Rprop, which used only the sign of the gradient; dividing by the root mean square is a mini-batch-friendly way to get sign-like steps. AdaGrad (Duchi, Hazan and Singer, 2011) had divided by the root of the sum of all past squared gradients, which shrinks the step forever; RMSProp's moving average forgets old gradients and keeps going.

Adam

Adam (Kingma and Ba, ICLR 2015) keeps both a momentum-like first moment and an RMSProp-like second moment, and corrects both for starting at zero:

m ← β₁ · m + (1 − β₁) · g          first moment  (β₁ = 0.9)
v ← β₂ · v + (1 − β₂) · g²         second moment (β₂ = 0.999)
m̂ = m / (1 − β₁ᵗ),  v̂ = v / (1 − β₂ᵗ)    bias correction at step t
θ ← θ − α · m̂ / (√v̂ + ε)          α = 0.001, ε = 1e-8 (paper defaults)

Why bias correction: m and v start at zero, so early on they underestimate the true averages. At step 1, m = 0.1·g, and dividing by 1 − 0.9 = 0.1 recovers g. Without the correction for v, which uses β₂ = 0.999 and so warms up over about a thousand steps, the first steps would divide by a tiny √v and be far too large. The paper also notes that the step size is roughly bounded by α, which makes α easy to reason about: it is about how far each parameter can move per step.

Adam has a cost that matters at scale: two extra numbers per parameter, usually stored in fp32. With mixed precision that's 8 of the roughly 16 bytes per parameter that ZeRO shards across GPUs. Module 08 · Stage 06 does the accounting and has the ZeRO memory calculator.

AdamW: decoupled weight decay

Loshchilov and Hutter's "Decoupled Weight Decay Regularization" (ICLR 2019) starts from an observation. For plain SGD, adding an L2 penalty (λ/2)‖θ‖² to the loss and shrinking the weights directly by a factor each step are the same thing, up to rescaling λ by the learning rate. For adaptive methods like Adam they are not, and most libraries at the time implemented "weight decay" in Adam as the L2 version.

Adam + L2 (what libraries did):
  g ← ∇L(θ) + λ·θ                    decay enters the gradient …
  θ ← θ − α · m̂ / (√v̂ + ε)           … and is then divided by √v̂

AdamW (decoupled):
  g ← ∇L(θ)
  θ ← θ − α · ( m̂ / (√v̂ + ε) + λ·θ )   decay applied directly, not rescaled

With L2, the decay term passes through the adaptive scaling. Parameters with a history of large gradients have a large √v̂, so they are decayed less, which is the opposite of what a regulariser should do uniformly. AdamW applies the same relative shrink to every weight. The paper reports two effects: the best weight decay becomes much less dependent on the learning rate, so the two can be tuned separately, and Adam's generalisation improves enough to compete with SGD with momentum on image classification, where it had usually lost before. (In the paper the whole update is also multiplied by a schedule multiplier η_t; PyTorch's torch.optim.AdamW applies θ ← θ − lr·λ·θ before the Adam step.)

In LLM practice, AdamW with β₂ around 0.95, a warmup followed by cosine or linear decay, gradient clipping, and weight decay around 0.1 has been the standard recipe for years. Weight decay is usually not applied to biases, normalisation gains or sometimes embeddings. The next video, on Muon, is about the first optimiser to seriously challenge this default for the hidden-layer matrices.

Interactive: an optimiser race in a narrow valley

Contours of f(x, y) = 0.05·(x − 2)² + (y − 1)²: curvature 0.1 along x, 2 along y, condition number 20. All five optimisers start at the ringed dot (−4, −0.5); the cross marks the minimum (2, 1). Grey: SGD. Orange: momentum (μ = 0.9). Red: RMSProp (ρ = 0.9). Blue: Adam (0.9, 0.999). Green dashed: AdamW, the same Adam with decoupled weight decay. SGD and momentum use the SGD learning rate; the other three use the adaptive one. Gradient noise is Gaussian, from a fixed seed, so runs are repeatable.

SGD loss
–
Momentum loss
–
RMSProp loss
–
Adam loss
–
AdamW loss
–

Try this: at the defaults (SGD rate 0.5, adaptive rate 0.1, 100 steps) SGD still hasn't quite reached the minimum along the flat x direction (loss about 6×10⁻⁵), while RMSProp is essentially there. Push the SGD rate to 1.05: the y curvature is 2, so the stability limit is 2/2 = 1, and SGD blows up along y while momentum survives. Set weight decay to 0.1: AdamW ends near (1.59, 0.96) instead of (2, 1), because decay pulls the weights towards zero. That is the regulariser doing its job, not a bug. With noise 0.5, nobody settles exactly; the adaptive methods hover with steps of roughly the learning rate. This is a toy with two parameters and axis-aligned curvature, which flatters per-parameter methods; don't read real-model rankings from it.

3. Where the course goes deeper

TopicCourse page
Autograd, where the gradients come fromModule 08 · Stage 01 · Tensor maths and autograd
Adam's memory cost and sharding optimiser state (ZeRO calculator)Module 08 · Stage 06 · Distributed training; Video 01 · ZeRO & FSDP
Adam with warmup in the original Transformer30u30 Day 13 · Attention is all you need
Adam in reinforcement learning (PPO settings)30u30 Day 29 · PPO
Training recipes and learning-rate schedules at scaleModule 08 · Stage 02 · Scaling and data mixing
The next optimiser: orthogonalised updatesVideo 08 · Muon and MuonClip

Why it matters for robotics

Self-check

Along one direction the loss has curvature 4. What is the largest learning rate plain gradient descent can use without diverging?

η must be below 2/h = 2/4 = 0.5. Above that, each step overshoots by more than it corrects, and the error grows.

Why does momentum help in a long, narrow valley?

Along the valley floor the gradient keeps the same sign, so the velocity builds up (towards g/(1 − μ)). Across the valley the gradient flips sign, so successive contributions cancel and the oscillation is damped.

What problem does RMSProp fix that AdaGrad has?

AdaGrad divides by the root of the sum of all past squared gradients, so its effective step size only ever shrinks and can stall. RMSProp uses an exponential moving average, which forgets old gradients.

Why does Adam need bias correction?

Its moving averages start at zero, so early estimates are biased towards zero. Dividing by 1 − βᵗ removes the bias. It matters most for the second moment with β₂ = 0.999, where an uncorrected √v would be tiny for the first few hundred steps and the steps far too large.

Adam + L2 and AdamW both "use weight decay". What's actually different?

With L2, λθ is added to the gradient and then divided by √v̂, so weights with large historical gradients are decayed less. AdamW subtracts αλθ directly, outside the adaptive scaling, so every weight shrinks by the same fraction. Loshchilov and Hutter showed this decouples the best λ from the learning rate and improves generalisation.

Roughly how many bytes per parameter does mixed-precision AdamW need for model states?

About 16: 2 for bf16 weights, 2 for gradients, 4 for an fp32 master copy, and 4 + 4 for the two Adam moments. Module 08 · Stage 06 walks through it.

References

From the video's description:

Also cited on this page: