Backpropagation: gradients by the chain rule
Read these first if they are new to you
- The chain rule: slopes of chained steps Basic
- The multilayer perceptron (MLP) Intermediate
- Loss: one number for how wrong Intermediate
The idea in one paragraph
Training needs the gradient of the loss with respect to every weight in a network. Backpropagation computes all of them in one backward pass. First, a forward pass runs the network and keeps every number it computes along the way. Then the backward pass starts at the loss and walks back through the same steps in reverse. At each step it multiplies by that step's own slope, which is the chain rule. The whole backward pass costs about as much as two forward passes, however many weights there are.
Nudging each weight in turn would be far too slow
Gradient descent needs, for every weight, how much the loss changes when that weight changes a little. One way to find out: nudge one weight, run the network again, and see how the loss moves. That costs one extra run of the network per weight. A network with a million weights would need a million runs for a single training step.
Backpropagation gets the same numbers from one forward run and one backward run.
A network is a chain of small steps, and slopes multiply along a chain
Take the smallest MLP: one input, one hidden unit with ReLU, one output, and a squared error. Written as a chain of steps:
z = w1x + b1 → h = ReLU(z) → y = w2h + b2 → L = (y − t)2
Here x is the input, t the target, and w1, b1, w2, b2 the four weights. Write ∂L/∂z for "how much L changes per unit change in z, with everything before z held fixed". The chain rule says that slopes along a chain multiply:
∂L/∂z = ∂L/∂y × ∂y/∂h × ∂h/∂z
Backpropagation evaluates this product from the left. It starts with ∂L/∂L = 1 at the loss. Each step back multiplies by one more local slope. So every gradient reuses the one computed just after it, and no work is repeated.
Try it. The figure shows the forward pass with x = 2, t = 2, w1 = 0.5, b1 = 0, w2 = 3 and b2 = 1. Before each press, predict the next orange number. Your goal is to reach ∂L/∂w1.
Forward pass: z = 0.5 × 2 + 0 = 1, h = ReLU(1) = 1, y = 3 × 1 + 1 = 4, L = (4 − 2)2 = 4.
Backward pass, from the loss back to the input:
- ∂L/∂y = 2(y − t) = 2 × 2 = 4.
- y = w2h + b2, so ∂L/∂w2 = 4 × h = 4, ∂L/∂b2 = 4 × 1 = 4, and ∂L/∂h = 4 × w2 = 12.
- ReLU has slope 1 where z > 0, and z = 1, so ∂L/∂z = 12 × 1 = 12.
- z = w1x + b1, so ∂L/∂w1 = 12 × x = 24 and ∂L/∂b1 = 12 × 1 = 12.
Check by nudging: raise w1 from 0.5 to 0.501. Then y = 4.006 and L = 2.0062 ≈ 4.0240. The loss rose by 0.0240 for a nudge of 0.001, a slope of about 24.
Your turn. Keep the weights but change the input to x = −1. Find ∂L/∂b2 and ∂L/∂w1.
Answer
Forward: z = −0.5, h = 0, y = 1, L = 1. Backward: ∂L/∂y = 2(1 − 2) = −2, so ∂L/∂b2 = −2. ReLU is switched off (z < 0), so its slope is 0, and ∂L/∂w1 = 0. The first layer learns nothing from this example.
Each kind of step has a short backward rule
Real networks are built from a few kinds of step. Each has a rule that turns the gradient arriving from the right into gradients for its inputs and its weights.
| Forward step | Backward rule, given ∂L/∂(output) = G |
|---|---|
| add a bias: y = u + b | pass G unchanged to both u and b |
| multiply: y = wh | to h: G × w; to w: G × h |
| ReLU: h = max(0, z) | pass G where z > 0; pass 0 elsewhere |
| squared error: L = (y − t)2 | start with 2(y − t) |
| one value used in several places | add up the gradients coming back from each place |
A whole linear layer applies the first two rules to every weight at once, as matrix arithmetic. The multiply rule also shows why the forward pass must keep its numbers: the gradient for w needs h. These stored values often take a large share of the memory that training uses, alongside the weights, their gradients and the optimizer's state.
The example has one number at each step. Real networks have tensors, so each rule becomes a matrix product, and a batch of examples adds up (or averages) each example's gradients. ReLU has no slope at exactly z = 0; software uses 0 there. You will rarely write these rules yourself: PyTorch records the forward steps and runs the backward rules for you.
backprop_torch.py
import torch
x, t = torch.tensor(2.0), torch.tensor(2.0) # input and target
w1 = torch.tensor(0.5, requires_grad=True)
b1 = torch.tensor(0.0, requires_grad=True)
w2 = torch.tensor(3.0, requires_grad=True)
b2 = torch.tensor(1.0, requires_grad=True)
h = torch.relu(w1 * x + b1) # forward pass
y = w2 * h + b2
loss = (y - t) ** 2
loss.backward() # backward pass
print(loss.item())
print(w1.grad.item(), b1.grad.item(), w2.grad.item(), b2.grad.item())
4.0
24.0 12.0 4.0 4.0
The slow way, nudging one weight, agrees:
nudge_check.py
def loss(w1, b1=0.0, w2=3.0, b2=1.0, x=2.0, t=2.0):
h = max(0.0, w1 * x + b1)
y = w2 * h + b2
return (y - t) ** 2
d = 0.001
print((loss(0.5 + d) - loss(0.5)) / d) # nudge w1 and watch the loss
24.036000000000612
The nudge gives 24.036 rather than 24 because a nudge of 0.001 is small but not zero.
Check yourself
-
In the tiny network with x = 2, change the target to t = 4. What are all four weight gradients, and why?
Answer
All are 0. The output y = 4 now equals the target, so ∂L/∂y = 2(4 − 4) = 0, and every gradient is that 0 times something.
-
A step computes y = wh with w = −2 and h = 1.5. The gradient arriving from the right is ∂L/∂y = 3. What are ∂L/∂w and ∂L/∂h?
Answer
∂L/∂w = 3 × 1.5 = 4.5 and ∂L/∂h = 3 × (−2) = −6.
-
A model has 10 million weights. About how many runs of the network does nudging each weight need for one training step? And backpropagation?
Answer
Nudging: one run per weight plus one, so about 10 million. Backpropagation: one forward run and one backward run, which together cost about as much as three forward runs.
-
A hidden unit's ReLU input is negative for every training example. What gradient do the weights feeding it get?
Answer
Zero, because ReLU passes 0 backward wherever its input is negative. Those weights never change. Such a unit is often called a "dead" ReLU.
Go further
Optional background, for readers who want more than this page.
-
The intuition first, without formulas. Its follow-up, Backpropagation calculus, works the chain rule on a tiny network like the one here.
-
Backpropagation, Intuitions: intuitive understanding Stanford CS231n notes Course notes Intermediate
Circuit diagrams with forward and backward numbers, and the "patterns in backward flow" for add, multiply and max.
-
The same backward pass for a full one-hidden-layer network, written with matrices.
Where this shows up
Units that build on this one
- Mixed precision: 16-bit numbers (bf16) Intermediate
- The training loop Intermediate