A 20-layer network sits there, loss stuck, weights barely moving. Four chapters back you learned four separate fixes for four separate failure modes. Which one is actually broken here -- and does fixing just one of them turn out to be enough?
This is the vanishing-gradients chapter's exact failure mode, just twenty layers deep instead of a handful: with weights initialized too small, the gradient reaching the input has almost nothing left of it. Flip on RMSNorm and watch every bar past the first few layers jump from invisible to a healthy, readable size -- the same rescue the RMSNorm chapter demonstrated on a single vector, now stacked twenty times in a row.
Four independent problems, four independent fixes -- each one exactly the function its own chapter built:
- -- layer 's output; RMSNorm (previous chapter) renormalizes it after every layer, so its scale can't compound across depth.
- , -- a raw gradient and the loss-scale factor; dynamic loss scaling (mixed-precision-training) multiplies by before casting to fp16, then divides back out, so a small survives storage instead of underflowing to exactly .
- , -- the learning rate at step and the warmup length; LR warmup (learning-rate-schedules) ramps up from instead of applying the full rate to the very first, least-trustworthy gradient.
- , -- a weight and the decay strength; decoupled weight decay (weight-decay-vs-l2) shrinks by a fixed fraction every step, independent of any optimizer's per-parameter gradient history.
- These four failure modes don't cure each other
Normalizing every layer fixes vanishing magnitude, but does nothing about:
- A raw fp16 cast underflowing to zero.
- An unbounded first update.
- Weights drifting upward over training.
Each fix repairs exactly one mechanism.
- Some of them only matter once another is in place
Loss scaling rescues a vanishing gradient from becoming exactly in storage -- but a gradient that's merely tiny, not zero, is still too small to be useful. RMSNorm is what actually lifts the magnitude; loss scaling only stops that magnitude from being destroyed a second time on the way into fp16.
- A healthy network needs all of its own separate fixes
Below, toggling on only one or two of the four almost never clears every failure mode at once -- the demo's health check is a logical AND across gradient magnitude, first-update size, and weight growth, exactly like a real training run failing for any one of several unrelated reasons.
step-0 update ≈ 0.000 (unsafe above 0.5) · weight after 50 steps ≈ 11.47 (bound 5)
✗ still unstable
With every fix off, the gradient reaching the input is stuck at essentially the same rounding-floor magnitude as the earlier vanishing-gradients chapter -- and the fp16 cast crushes it to exactly on top of that. Turn on RMSNorm and the gradient jumps to a healthy scale, but the very first update (still at the full base learning rate) blows past the safe threshold. Add warmup and that first step is safe -- but fifty steps in, an unchecked weight has drifted well past its bound. Only with all three of normalize, warmup, and weight decay on together does the readout turn green.
- Start from the broken network
With every fix off, the gradient reaching the input is about in full precision -- already far below the healthy floor. Cast to the toy fp16 format with no loss scaling, it stores as exactly : the update for that layer's weights is now not just tiny, but identically zero.
- Loss scaling alone doesn't fix the magnitude
Turn on loss scaling by itself: that same gradient now survives storage as instead of -- rescued from total information loss, but still nowhere near the floor. RMSNorm, not loss scaling, is the fix for magnitude.
- RMSNorm fixes the magnitude, but exposes the next problem
Turn on RMSNorm instead: the gradient reaching the input jumps to , comfortably healthy. But at the base learning rate (, unwarmed), step 's update is -- past the unsafe threshold before training has learned anything.
- Warmup and decoupled decay close the other two gaps
Warmup starts the learning rate at exactly , so step 's update is regardless of gradient size -- safe by construction.
For the weight bound, each step first grows the weight by , then -- with decay on -- shrinks that grown value back down by another : a net per-step factor of .
- Without decay, 50 steps compounds the raw growth alone:
- With decay, 50 steps compounds the net factor instead: , comfortably under the bound of
Flip fixes on until the gradient reaching the input clears 0.3, the first update stays under 0.5, and the weight after training stays under 5 -- all at once.
step-0 update ≈ 0.000 · weight after 50 steps ≈ 11.47
A 20-layer network that won't train rarely has one problem -- it has several, layered on top of each other. RMSNorm keeps the forward and backward signal from vanishing across depth; dynamic loss scaling keeps that signal from being destroyed a second time by low-precision storage; LR warmup keeps the first, least-trustworthy update from overshooting; and decoupled weight decay keeps every weight bounded over the long run. None of the four substitutes for another -- stabilizing a deep network means running all of them together, exactly as this part built them, one chapter at a time.