The previous three parts derived all twenty-six steps from the loss to every parameter, but that was opening the black box and walking through it. This one puts the box back together: cross-entropy's eight steps compressed into one line, BatchNorm's ten into one, both by the same method — count how many times a variable appears in the forward pass and the backward has that many terms. Then backward() is commented out and the model trains for 200,000 steps: val loss 2.1105, against PyTorch's 2.1106.
The previous part stopped at logits — the edge of the network, with not one parameter touched in eight steps. This one goes thirteen steps further in, and parameters appear for the first time. BatchNorm's nine steps are the worst stretch in the episode for the same reason softmax forks: a normalisation's numerator has to go build the denominator first. Along the way: the first sum-backward whose coefficient is not 1, and a mistake only 3% wide whose maxdiff looks like rounding error.
Initialisation only governs step 0; BatchNorm governs every step — vary σ_W by a factor of a thousand and the output after BN is identical. The price is that it becomes the one operation in the network where samples affect each other, which is why inference needs its own statistics, and why model.eval() exists.