makemore, part 4
AI disclosure: I used ChatGPT to edit my original free-write and add technical context. Substantive AI additions are marked throughout.
Nice, so he does think it’s valuable to develop intuition for how gradients flow through the layers, which is what I was trying to do in the previous lectures.
He calls backprop a “leaky abstraction”, and yeah, that seems pretty obvious: you can’t separate the optimization technique from the architecture, lol. He motivates this from an engineer POV, but I think it’s even more important from a researcher POV.
From the overview, it seems he’s going to do much of what I already did in my detours over the last two lectures. He works through backprop at the level of individual operations in cross-entropy, and then derives the simplified expression analytically. I’m quite familiar with this now, so these notes are shorter.
Observations
Subtracting the maximum logit
We subtract the maximum logit for numerical stability, but this doesn’t change the final gradients with respect to logits. As discussed earlier, the downstream gradient is insensitive to constant shifts in logits.
ChatGPT addition (making the cancellation precise): For one example, , so . If , where , the extra chain-rule contribution from differentiating the maximum is proportional to , so it cancels. The shift depends on z, but that dependence does not change the final gradient in exact arithmetic.
Vector derivatives and intuition
Meta: pedagogy. He didn’t give the intuition for vector derivatives that I think is VERY important. He expanded the derivatives out, then collapsed them back into a matrix multiplication.
I think every time there’s a cleaner-than-expected result, it’s an opportunity to find a simpler or more intuitive explanation. This was what I was trying to do with the direction/coefficient interpretation in the part 2 addendum.
Bessel’s correction
Nice, he added Bessel’s correction to the variance estimate.
ChatGPT addition (a convention worth distinguishing): The notebook divides the centered sum of squares by :
This is an unbiased population-variance estimator under the usual i.i.d. sampling assumptions. It doesn’t follow that this convention is always better for normalization. PyTorch’s batch-norm training forward pass divides by B, while its running-variance update uses the unbiased estimate.1
Summing and broadcasting are dual
Another interesting observation is the duality between summing and broadcasting in the forward and backward passes. This is just a calculus thing, but it’s nice to notice: sum in the forward pass becomes broadcast in the backward pass, and broadcast in the forward pass becomes sum in the backward pass.
ChatGPT addition (the small example):
Conversely,
A shared input accumulates contributions from every place it is used. More generally, backward propagation applies the transpose of the forward operation’s Jacobian. Summation and replication are transposes of each other.
Analytical backprop as understanding
Meta: pedagogy. He also motivates “analytical backprop” through efficiency and simplicity rather than understanding :/ I think understanding is a very valuable pedagogical motivation here too.
But he did give intuition for the logit gradient: its total across output guesses is zero, so there’s a redistribution mechanism.
ChatGPT addition (the identity): For one example,
A gradient-descent step raises the target logit and lowers the others. For the batch-mean loss, each example’s logit gradient is additionally divided by B. The zero-sum identity is also the gradient-level expression of the constant-shift invariance above.
Batch norm: a missed opportunity for geometric intuition
Oh no! A big pedagogical mistake, imo: he does the full batch-norm gradient derivation very mechanically, without giving the geometric intuition for the result.
The result is also presented in a way that makes it harder to see what the variables mean. Vectorized notation would at least make the projection connection easier to see. He even says it’s nontrivial to convert his expression to vectorized form.
I also think the broadcasting details overcomplicate the conceptual task. I’d prefer to understand the transformation on one feature’s vector across a batch first, then handle the tensor shapes separately.
ChatGPT addition (the projection, using this lecture’s variance convention): For one feature, let contain its values across the batch. Define
If , the exact input gradient is
When and the variance is nonzero, and . The two subtracted terms are orthogonal projections onto the common-shift and centered-scale directions. The backward pass removes those components and rescales what remains.
With , the formula still holds, but the scale-direction component is not completely removed. The denominator matches the notebook; using the B-denominator variance convention changes that term to B.
This is the same geometry explored in the earlier notes. The longer expression is not just algebra to simplify: it describes which changes normalization makes ineffective.
References
Lecture materials: Karpathy’s makemore part 4 notebook. The equations above use its variance convention.
PyTorch, BatchNorm1d, on training-time and running-variance conventions. ↩︎