Part IX — Deep Learning Regularization, Normalization & Training Dynamics · Chapter 10

Train and stabilize a 20-layer neural network

Hook

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?

Intuition

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.

Formalize

Four independent problems, four independent fixes -- each one exactly the function its own chapter built:

hl=RMSNorm(Wlhl1)stored=fp16(gs)/sη(t)=ηmaxttwarmupw=ηλwh_l = \text{RMSNorm}(W_l\,h_{l-1}) \qquad \text{stored} = \text{fp16}(g\cdot s)/s \qquad \eta(t) = \frac{\eta_{\max}\cdot t}{t_{\text{warmup}}} \qquad w \mathrel{-}= \eta\lambda w
  • hlh_l -- layer ll's output; RMSNorm (previous chapter) renormalizes it after every layer, so its scale can't compound across depth.
  • gg, ss -- a raw gradient and the loss-scale factor; dynamic loss scaling (mixed-precision-training) multiplies by ss before casting to fp16, then divides back out, so a small gg survives storage instead of underflowing to exactly 00.
  • η(t)\eta(t), twarmupt_{\text{warmup}} -- the learning rate at step tt and the warmup length; LR warmup (learning-rate-schedules) ramps η\eta up from 00 instead of applying the full rate to the very first, least-trustworthy gradient.
  • ww, λ\lambda -- a weight and the decay strength; decoupled weight decay (weight-decay-vs-l2) shrinks ww by a fixed fraction every step, independent of any optimizer's per-parameter gradient history.
  1. 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.

  2. Some of them only matter once another is in place

    Loss scaling rescues a vanishing gradient from becoming exactly 00 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.

  3. 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.

Play

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 00 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.

Worked example
  1. Start from the broken network

    With every fix off, the gradient reaching the input is about 1.05×1071.05\times10^{-7} in full precision -- already far below the 0.30.3 healthy floor. Cast to the toy fp16 format with no loss scaling, it stores as exactly 00: the update for that layer's weights is now not just tiny, but identically zero.

  2. Loss scaling alone doesn't fix the magnitude

    Turn on loss scaling by itself: that same gradient now survives storage as 1.05×107\approx1.05\times10^{-7} instead of 00 -- rescued from total information loss, but still nowhere near the 0.30.3 floor. RMSNorm, not loss scaling, is the fix for magnitude.

  3. RMSNorm fixes the magnitude, but exposes the next problem

    Turn on RMSNorm instead: the gradient reaching the input jumps to 0.738\approx0.738, comfortably healthy. But at the base learning rate (1.21.2, unwarmed), step 00's update is 1.2×0.7380.8861.2\times0.738\approx0.886 -- past the 0.50.5 unsafe threshold before training has learned anything.

  4. Warmup and decoupled decay close the other two gaps

    Warmup starts the learning rate at exactly 00, so step 00's update is 00 regardless of gradient size -- safe by construction.

    For the weight bound, each step first grows the weight by 5%5\%, then -- with decay on -- shrinks that grown value back down by another 5%5\%: a net per-step factor of 1.05×0.95=0.99751.05\times0.95=0.9975.

    • Without decay, 50 steps compounds the raw 5%5\% growth alone: 1×1.055011.471\times1.05^{50}\approx11.47
    • With decay, 50 steps compounds the net 0.99750.9975 factor instead: 1×0.9975500.881\times0.9975^{50}\approx0.88, comfortably under the bound of 55
Checkpoint

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

Toggle a fix to try it
Summary
hl=RMSNorm(Wlhl1),w=ηλw,η(0)=0 under warmuph_l = \text{RMSNorm}(W_l\,h_{l-1}), \qquad w \mathrel{-}= \eta\lambda w, \qquad \eta(0)=0 \text{ under warmup}

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.