Backpropagation
A network can contain many weights between an input and its prediction. Backpropagation works backwards through those calculations to find how each weight contributed to a change in the loss.
12 sections · 10 questions · 4 coding challenges
The arrow keys move between sections too.
Which Earlier Weight Helped Produce the Mistake?
BOTIE
Backpropagation draws on the chain rule and earlier work on reverse differentiation. The 1986 paper by Rumelhart, Hinton and Williams helped demonstrate its value for learning the hidden representations of neural networks. The central problem was assigning a useful adjustment signal to connections far from the output.
We record the calculations on the way forward. Starting from the loss, we then pass derivatives backward through those same operations, reusing intermediate results. Each derivative says how a small local change would affect the final loss. Backpropagation computes those sensitivities; an optimiser uses them to choose the actual weight updates.
Sources for this history
Which Weight Should Change?
A network makes a prediction through several layers, and we measure how far that prediction missed. To improve it, we need to know how a small change to each internal parameter would affect the final loss.
A hidden weight acts indirectly through later operations. Backpropagation works backward through that chain of effects.
Give the backward pass something to follow
First trace the forward calculation from input through hidden responses to prediction and loss. Keep the intermediate values because the later sensitivity calculation needs them.
Input
- Measurements
Hidden layer
- Scores
- Activations
Output
- Prediction
Compare with target
- Loss
Local sensitivities explain a distant parameter's effect
The detailed example now calculates the output gradient, follows one hidden path, and combines contributions where paths meet.
Numerical gradient checks compare this backward calculation with small parameter perturbations. They test the sensitivities, not a causal explanation of the training data.
Explore the full example
Follow the prediction forward and the gradients backward. Compare a gradient with the loss change produced by a small numerical nudge to that weight.
Inside each neuron, z is its score and a its output. Above it, the slope that arrived and the activation function’s slope g′ at the score; beneath it, their product δ. On each edge, w is the weight and ∂ the slope of the loss with respect to it. Click an edge to check that slope by nudging.
| x₁ | x₂ | bias | |
|---|---|---|---|
| h₁ | |||
| h₂ | |||
| h₃ |
| h₁ | h₂ | h₃ | bias | |
|---|---|---|---|---|
| y |
The chain rule says its slope is …. Nudging the weight up by a millionth and down by a millionth, remeasuring the loss each time and dividing the difference by the width of the nudge says …, a disagreement of ….
Part 1. What Training Needs
1. What the forward pass left behind
Backpropagation reverses something, so start with the thing it reverses. One row, (1, 2), goes into the 2-3-1 network. Each hidden neuron forms a score from the row, the rectifier applies ReLU to each score, the output neuron forms a score from the three activations, its activation function is the identity so that score is the prediction, and the prediction is measured against the target of 1 by half the squared miss.
…
Six kinds of intermediate value, and every one of them is kept. That is not tidiness. The backward pass is about to ask for each of them by name, and a forward pass that discarded its scores would have to be run again to recover them.
Keep in mind
2. What training needs to know
A gradient-descent step needs one number per weight, the slope of the loss with respect to that weight. In plain terms, if this weight went up a little, would the loss rise or fall, and how sharply?
∂L/∂w, for every w in the networkOn the logistic regression page that question had a short answer, because a single neuron’s weight sat one step from the loss. A hidden weight here does not. Its effect travels through its own neuron’s score and activation function, then through the output neuron’s score, then through the prediction, and only then into the loss. The widget draws that route for whichever hidden weight you choose, with the values the forward pass kept at every stop, and calculates nothing.
…
Keep in mind
3. Following one weight to the loss
Take one neuron rather than the whole layer, and take the output neuron because its route is shortest. Three separate questions can be asked about it. How much does the loss respond to the neuron’s output? How much does the neuron’s output respond to its score? How much does its score respond to one particular weight? Each has a small, local answer, and the chain rule multiplies them.
…
∂L/∂w = (∂L/∂a) · (∂a/∂z) · (∂z/∂w)›Why a product
A small change in w moves z by ∂z/∂w times as much, that change in z moves a by ∂a/∂z times as much, and that change in a moves L by ∂L/∂a times as much. Three magnifications in a row multiply, which is the calculus primer’s chain rule and nothing more.
Keep in mind
Part 2. Backward Through the Output Neuron
4. Beginning at the loss
The walk has to start somewhere, and it starts at the loss, which for this page is half the squared miss.
L = ½ (ŷ − y)² ∂L/∂ŷ = ŷ − yThe half is there so the derivative comes out as a clean subtraction. Two different numbers live at this point and the page will keep them apart. The loss is a value, how wrong the network is. The slope of the loss is a rate, how fast that wrongness changes when the prediction moves.
At a prediction of 5 the loss is 8 and its slope is 4. The 8 is how wrong the network is; the 4 is how fast that wrongness changes if the prediction moves, and it is the 4 that travels backward, not the 8.
At the worked row
The prediction is 5 and the target is 1. This example uses half the squared error as its loss. First calculate the miss, then the loss and its derivative with respect to the prediction.
miss = prediction − target = 5 − 1 = 4
loss = ½ × miss² = ½ × 4² = 8
∂loss/∂prediction = prediction − target = 4That derivative is the first gradient to arrive at the output neuron. It says that a sufficiently small increase in the prediction raises the loss by about four times that increase.
Keep in mind
5. Backward through the output neuron
The output neuron is a useful place to learn the backward calculation because its activation function is the identity: it returns its score unchanged.
output a = g(z) = z
activation derivative g′(z) = 1Call the gradient with respect to the score the delta. To obtain it, multiply the arriving output gradient by the activation derivative.
δ = (∂L/∂a) · g′(z)Then pick one edge, the weight from h₁ into the output. The score is a weighted sum, so its slope with respect to that weight is whatever the weight multiplied, and the weight’s gradient is the delta times that.
z = w₁h₁ + w₂h₂ + w₃h₃ + b
∂z/∂w₁ = h₁
∂L/∂w₁ = δ · h₁…
The four numbers
The output neuron received inputs 3, 0 and 1. Each weight gradient is the delta multiplied by the input attached to that weight. The bias is added directly, so its multiplier is one.
delta = 4 × 1 = 4
weight gradients = 4 × (3, 0, 1) = (12, 0, 4)
bias gradient = 4 × 1 = 4The first weight has the largest gradient because it multiplied the largest input. The second has a zero gradient on this example because its input was zero.
Keep in mind
6. Passing the gradient to the hidden layer
The output neuron can now update its own weights. The hidden layer still knows nothing, because nobody has told it how its outputs affected the loss. So ask one concrete question. How did changing h₁ affect the output score? By w₁ per unit, since h₁ appears in the score once, multiplied by w₁. The loss’s sensitivity to h₁ is therefore the output delta times w₁, and the same for the other two.
∂z_out/∂h₁ = w₁ ∂L/∂h₁ = δ_out · w₁…
The passed-down block
Multiply the output delta by the three output weights to pass the gradient back to the hidden outputs.
hidden output gradients = 4 × (1, −1, 2) = (4, −4, 8)These are the gradients arriving at h₁, h₂ and h₃. Each hidden neuron must still account for its own activation function.
Keep in mind
Part 3. The Hidden Layer
7. Backward through the rectifier
The hidden neurons have an activation function that is not the identity, and this is what changes. For each of them, take the arriving gradient, recall the score the forward pass kept, evaluate the rectifier’s derivative at that score, and multiply.
…
| neuron | arriving gradient | original score | rectifier slope | delta |
|---|---|---|---|---|
| h₁ | 4 | 3 | 1 | 4 |
| h₂ | −4 | −1 | 0 | 0 |
| h₃ | 8 | 1 | 1 | 8 |
The middle row is the one to look at. h₂ scored −1, the rectifier turned that into 0 going forward, and going backward its slope at −1 is 0, so an arriving −4 becomes a delta of 0. This neuron receives no update from this row. Nothing it does reaches the loss on this row, so nothing on this row can tell it what to do. Whether a neuron can get stuck that way for good belongs to the activation and regularisation material, not here.
Keep in mind
8. Calculating the hidden gradients
Once its delta is known, a hidden neuron follows the same rule as the output neuron. The first hidden neuron has delta 4 and received inputs 1 and 2.
weight gradients = 4 × (1, 2) = (4, 8)
bias gradient = 4 × 1 = 4…
Keep in mind
9. The four-line rule for a dense layer
Everything done by hand above is four lines, and now that each has been used they can be written as a summary rather than a rule to decode.
δ = arriving ⊙ g′(z)
∂L/∂W = δ xᵀ
∂L/∂b = δ
∂L/∂x = Wᵀ δ| line | its job |
|---|---|
| the delta | move the arriving gradient through the activation. Section 5 for the identity, section 7 for the rectifier. |
| the weight gradient | what the layer keeps to update its weights. Section 5, then section 8. |
| the bias gradient | what the layer keeps to update its biases. A weight on a constant input of one. |
| the input gradient | what the layer hands down, so the preceding layer has an arriving gradient of its own. Section 6. |
Two names are worth having now. The arriving block is the slope of the loss at a layer’s outputs, which came from the loss for the top layer and from the layer above for everyone else. The passed-down block is the slope at its inputs, which is the next layer down’s arriving block. One variable threads the whole walk.
Keep in mind
Check yourself
Questions on Parts 1 to 3
Question 1 of 5
A distant weight’s effect on the loss is found by multiplying the local effects along the path from the weight to the loss, so every layer only ever has to know its own local effects.
Part 4. Update and Check
10. Updating the parameters
Calculating gradients and applying them are two phases, and they must not overlap. In the first, backpropagation computes and stores every gradient while no parameter moves. Moving one early would change the scores and activations the remaining gradients are still being computed from. In the second, every parameter takes one step against its own gradient, scaled by the learning rate.
θ_new = θ_old − η · ∂L/∂θ…
One step at η = 0.05
The hidden neurons started at (1, 1), (1, −1) and (−1, 1) and the output neuron at (1, −1, 2), with every bias at zero. Every parameter moves by a twentieth of its slope, and h₁ is enough to see the rule at work, since section 8 found its weight gradients to be (4, 8) and its bias gradient 4.
h₁ weights: (1, 1) − 0.05 × (4, 8) = (0.8, 0.6)
h₁ bias: 0 − 0.05 × 4 = −0.2The same rule takes the output weights to (0.4, −1, 1.8) with a bias of −0.2 and h₃ to (−1.4, 0.2) with a bias of −0.4, and leaves h₂ exactly where it was, since every one of its gradients was zero. Then the row goes through again, because it must. The weights changed, so the scores and activations changed, and the old intermediate values and the old gradients describe a network that no longer exists.
h₁ score: 0.8 × 1 + 0.6 × 2 − 0.2 = 1.8
h₃ score: −1.4 × 1 + 0.2 × 2 − 0.4 = −1.4
prediction: 0.4 × 1.8 + (−1) × 0 + 1.8 × 0 − 0.2 = 0.52
loss: ½ × (0.52 − 1)² = 0.1152On the second pass h₃ scores −1.4 and goes dark beside h₂, so only h₁ reaches the output, the prediction is 0.52, and the loss falls from 8 to 0.1152.
Keep in mind
11. Checking a gradient numerically
The chain rule’s answer can be checked without the chain rule. Take one weight, nudge it up by a tiny ε and measure the loss, nudge it down by ε and measure again, and divide the difference by the width of the nudge.
[L(w + ε) − L(w − ε)] / 2ε ≈ ∂L/∂w…
On the weight from h₁ into the output
The chain rule says 12. The nudge, at ε of a millionth, says 11.999999998, a disagreement of 2.3e-9, which is the rounding in a difference of two losses near eight and not a disagreement about the slope. The same check on h₁’s weight from x₂ gives 8 against 8.000000001.
That is why the nudge is useful, and why it is a check rather than a method. It costs two forward passes per parameter, so it is the right tool for confirming that an implementation of the four lines is correct and the wrong tool for training anything, where one backward walk finds every slope at once for about the price of a second forward pass.
Keep in mind
Part 5. From Neurons to Layers
12. From one neuron to a layer
Every calculation so far was on scalars, one neuron and one weight at a time. A layer does the same thing for several neurons at once, and the scalars become vectors and matrices. The input x is a column of the layer’s inputs, W has a row per neuron and a column per input, z and a are columns with one entry per neuron, δ is a column of the same length, and the weight gradient has exactly W’s shape, because there is one slope per weight.
…
Read δ xᵀ back against section 5. A column of deltas times a row of inputs is an outer product, and its entry in row j and column i is δⱼ xᵢ, which is the scalar rule for the weight from input i into neuron j. Read Wᵀ δ back against section 6. Input i’s entry is Σⱼ w[j, i] δⱼ, the sum over every neuron of that neuron’s delta times the weight on the edge, which is section 6’s rule with the routes summed because in general an input feeds every neuron.
The stack then walks its layers from the top down, handing each one the block the layer above passed down.
Keep in mind
13. Layers without trainable parameters
With the mechanism settled, one question about the layer interface is worth settling too. Every layer must return a gradient with respect to its inputs, because the backward walk has to continue through it. Only layers with trainable parameters have parameter gradients. Dense and convolutional layers return both. Flattening, pooling and dropout return an input gradient and no parameter gradient, and they say so with None rather than a block of zeros.
The two meanings must stay distinct. None means this layer has no trainable parameters. A zero tensor would mean this layer has parameters and their gradients happen to be zero, which is what h₂ reported in section 8 and is a fact about this row, not about the layer. The rule cuts the other way as well.
A dense layer handed None when asked to step refuses, because it does have parameters and a missing gradient for them is a mistake in whoever built the backward pass. The stack’s report of the largest slope anywhere skips the parameterless layers rather than counting them as zero, so a network made of nothing but pooling reports no movement at all, which is the true answer.
Keep in mind
14. Formal derivation
Take one layer. Each row of its weight matrix belongs to one neuron. The matrix multiplication produces the scores, and the activation function acts on each score separately.
scores: z = Wx + b
outputs: a = g(z)Suppose the gradient of the loss with respect to every output is already known. Because this activation acts separately on each score, its backward calculation multiplies each arriving gradient by the corresponding activation derivative.
∂L/∂zⱼ = ∂L/∂aⱼ · g′(zⱼ) = δⱼScore j is the sum over i of w[j, i] x[i], plus b[j], so its derivative with respect to w[j, i] is x[i] and with respect to b[j] is 1, and the chain rule again gives the two lines the layer keeps. Input i appears in every score, so the loss reaches it through every neuron, and the chain rule sums the routes.
∂L/∂w[j, i] = δⱼ · xᵢ
∂L/∂bⱼ = δⱼ
∂L/∂xᵢ = Σⱼ δⱼ · w[j, i]That last line is the induction. The slope of the loss with respect to this layer’s inputs is, by definition, the slope of the loss with respect to the outputs of the layer beneath, which is exactly the arriving block that layer needs to run the same three lines. The base case is the loss itself, whose slope at the final output section 4 worked out, and the walk ends at the row, whose slope nobody needs but which costs nothing to report.
Every layer is visited once, every slope is computed once, and the arithmetic is a handful of matrix products against blocks the forward pass already built, which is why the forward responses keep their scores rather than only their outputs.
Keep in mind
Check yourself
Questions on Parts 4 and 5
Question 1 of 5
A parameter may be moved as soon as its own gradient is known, since the gradients still to come belong to other parameters.
Try it with Botie
Build with Botie
Write and run Python