Backpropagation Intuition
The chain rule as blame assignment: how every weight learns its share of the error.
12 min read · lesson 6 of 49
Backpropagation is how a neural network figures out which of its millions of weights to blame for a wrong answer. It is just the chain rule from calculus, applied backwards through the network, with clever reuse of work.
The analogy
A restaurant gets a one-star review: "the food arrived cold". The manager traces it backwards. The waiter took four minutes to pick it up from the pass; the kitchen plated it eight minutes after cooking; the order sat in the queue for two minutes. Each step gets a share of the blame proportional to how much it contributed. Next time, each person adjusts a little. Backprop is that post-mortem, done for every weight, on every batch.
The forward and backward passes
Training a network repeats two passes:
forward: x ──► layer1 ──► layer2 ──► layer3 ──► prediction ──► loss backward: ∂L/∂W1 ◄── ∂L/∂W2 ◄── ∂L/∂W3 ◄── ∂L/∂pred ◄──────────── 1- Forward: compute outputs layer by layer, saving the intermediate values.
- Backward: start from the loss and use the chain rule to compute how the loss changes with respect to each layer's output, then each layer's weights.
The chain rule says: if L depends on y and y depends on w, then ∂L/∂w = ∂L/∂y · ∂y/∂w. Backprop computes the "upstream gradient" ∂L/∂y once per layer and reuses it for everything beneath. That reuse is why computing gradients for a billion parameters costs only about two to three times a forward pass, not a billion times.
A tiny worked example
One neuron, one input, squared-error loss:
z = w·x + b a = relu(z) L = (a − y)²With x = 2, w = 0.5, b = 0, y = 3:
- forward:
z = 1,a = 1,L = 4 ∂L/∂a = 2(a − y) = −4∂a/∂z = 1(ReLU slope when z > 0)∂z/∂w = x = 2- so
∂L/∂w = −4 · 1 · 2 = −8→ increasewto reduce loss. Makes sense: we predicted 1, wanted 3.
Autograd does it for you
You never hand-write backprop in practice. Frameworks build a computation graph during the forward pass and walk it backwards automatically.
import torchx = torch.tensor([2.0])y = torch.tensor([3.0])w = torch.tensor([0.5], requires_grad=True)b = torch.tensor([0.0], requires_grad=True)a = torch.relu(w * x + b)loss = (a - y) ** 2loss.backward() # backprop through the graphprint(w.grad, b.grad) # tensor([-8.]) tensor([-4.])with torch.no_grad(): # one gradient-descent step w -= 0.05 * w.grad b -= 0.05 * b.grad w.grad.zero_(); b.grad.zero_()Why it matters for an AI engineer
- Memory: the forward pass must store activations for the backward pass. That's why training needs far more GPU memory than inference, and why tricks like gradient checkpointing (recompute instead of store) exist.
- Vanishing / exploding gradients: multiplying many small derivatives shrinks the signal toward zero; many large ones blow it up. This is why deep networks need residual connections, normalization, careful initialization, and gradient clipping.
- Fine-tuning cost: LoRA and other PEFT methods freeze most weights, so gradients only need to be stored for a tiny number of parameters — a big memory saving.
- Frozen vs trainable: "freezing" a layer just means not computing or applying its gradient.
Common mistakes
- Forgetting to zero gradients between steps, so they accumulate across batches by accident.
- Calling backward inside
no_grador on a tensor detached from the graph — gradients silently becomeNone. - Assuming backprop "finds the right answer". It only gives the local direction of steepest improvement.
- Running inference without disabling gradient tracking, wasting memory.
In the interview
Q: Explain backpropagation in one minute. After a forward pass computes the loss, we apply the chain rule from the loss back through each layer, computing the gradient of the loss with respect to every parameter. Each layer receives the gradient of its output, multiplies by its local derivative, and passes the result down. Then an optimizer updates the weights. Reusing upstream gradients makes this efficient.
Q: Why does training use more memory than inference? Training stores intermediate activations for the backward pass, plus gradients and optimizer state (Adam keeps two extra values per parameter). Inference needs only the weights and a small working set — plus the KV cache for LLMs.
Q: What are vanishing gradients and how are they mitigated? Gradients shrink exponentially as they flow back through many layers, so early layers stop learning. Mitigations: ReLU-family activations, residual connections, normalization layers, and good initialization.
Key takeaways
- Backprop = chain rule applied backwards, reusing upstream gradients.
- Forward pass computes and caches; backward pass assigns blame.
- Autograd frameworks automate it, but memory and stability consequences are yours to manage.
- Freezing weights and PEFT methods exist largely to cut backprop's memory cost.