CadetX
CX Learn | Complete Neural Networks Guide
TensorFlow · Keras
CadetX logo CadetX CX Learn
NN-101 · Module 5 Intermediate about 45 minutes 9 Lessons Prereq: Modules 1 to 4

Backpropagation Algorithm

A network can have millions of weights. After each mistake, how does it know which ones to change, and by how much? The answer is backpropagation: an efficient way to send the error backwards through the network so every weight gets its fair share of the blame. It's the algorithm that makes deep learning possible.

  • Level: Intermediate
  • Time: about 45 minutes
  • Needs: Modules 1 to 4

By the end of this module you will be able to

  • Explain the problem backpropagation solves
  • Explain the chain rule using a simple everyday picture
  • Work through a forward pass and a backward pass by hand
  • Describe how the error signal flows back through layers
  • Explain how deep learning libraries automate backpropagation
  • Connect backpropagation to vanishing and exploding gradients
  • Train a network on XOR from scratch using backpropagation in NumPy

5.1The blame problem

In Module 4 you learned the rule for improving a weight: new weight = weight − learning rate × gradient. The gradient tells us how much the loss changes when that one weight changes. For a single neuron, that's easy to work out. But in a deep network, a weight in the first layer affects the output only indirectly, through every layer after it.

A football team loses 3–0

Whose fault was it? The striker who missed chances? The midfielder whose poor pass started the counter-attack? The defender who was out of position? A good coach traces the mistake backwards from the goal: who contributed, and how much. Backpropagation does exactly this for every weight in the network.

A slow way to find each gradient would be to nudge every weight one at a time and re-run the network to see what changes. With a million weights, that's a million extra runs per step. Backpropagation gets all the gradients in roughly the time of one extra run. That efficiency is why it transformed the field when it was popularised in 1986.

5.2The chain rule, without the scary maths

Backpropagation is built on one idea from calculus called the chain rule. Here it is with gears:

Three connected gears. When gear A turns once, gear B turns twice. When gear B turns once, gear C turns three times. So when A turns once, C turns 2 times 3, which is 6 times. This is the chain rule.Gear Aturns 1 timeGear Bturns 2 timesGear Cturns 6 timesA → B: × 2B → C: × 3A → C: 2 × 3 = 6
Figure 1. If turning A turns B twice as much, and turning B turns C three times as much, then turning A turns C 2 × 3 = 6 times as much. To find the effect along a chain, multiply the effects of each link.

A neural network is a chain too: weight → neuron → next layer → … → output → loss. To find how much a weight affects the loss, we multiply the effects of every link in its chain. And because the later links are shared by many weights, we can calculate them once and reuse them. That's the trick that makes backpropagation fast.

5.3A worked example

Let's follow the smallest possible network: 1 input, 1 hidden neuron and 1 output neuron, both using sigmoid. The input is x = 1, the correct answer is y = 1, and the weights start at w₁ = 0.5 and w₂ = 0.8 (biases are 0 to keep it simple). The loss is ½ × (y − prediction)².

Step 1: forward pass

CalculationValue
Hidden total: w₁ × x = 0.5 × 10.500
Hidden output: sigmoid(0.5)h = 0.622
Output total: w₂ × h = 0.8 × 0.6220.498
Prediction: sigmoid(0.498)ŷ = 0.622
Loss: ½ × (1 − 0.622)²0.0714

Step 2: backward pass

Now we go backwards, multiplying the effect of each link (the chain rule):

Link in the chainEffectRunning product
How the loss changes with the prediction: −(y − ŷ)−0.378−0.378
How the prediction changes with its total (sigmoid slope): ŷ × (1 − ŷ)0.235−0.0889 (the output's "blame")
Gradient for w₂: × h0.622−0.0553
Pass the blame back to the hidden neuron: × w₂0.8−0.0711
Hidden neuron's sigmoid slope: h × (1 − h)0.235−0.0167 (the hidden neuron's "blame")
Gradient for w₁: × x1−0.0167

Step 3: update the weights

With a learning rate of 1: w₂ = 0.8 − 1 × (−0.0553) = 0.855 and w₁ = 0.5 − 1 × (−0.0167) = 0.517. Run the forward pass again and the prediction rises from 0.622 to 0.652, and the loss drops from 0.0714 to 0.0605. One step closer to the right answer.

Notice

The gradient for w₁ (−0.017) is much smaller than for w₂ (−0.055), because the blame was multiplied by another sigmoid slope (0.235) on its way back. That shrinking is the vanishing gradient problem from Module 3, happening right in front of you.

5.4Try it: step through backpropagation

Here's the same tiny network. Press the buttons in order to run the forward pass, the backward pass and the update, and watch the loss fall with every round.

Try it: one neuron at a time

5.5Backpropagation in a full network

In a real network, the same three steps happen for every layer at once:

A network with the forward pass flowing left to right, from inputs to a prediction, and the backward pass flowing right to left, carrying the error back from the loss to every weight.LossForward pass: inputs → predictionBackward pass: error → every weight gets its share of the blameInput layerHidden layerOutput layer
Figure 2. The forward pass carries inputs to a prediction. The backward pass carries the error from the loss back through each layer. At each layer, the blame is split between the weights and neurons that contributed, in proportion to how much they did.
StepWhat happensDirection
1. Forward passCompute every neuron's output and remember them allInput → output
2. Compute the lossCompare the prediction with the correct answerAt the end
3. Backward passStarting at the loss, work out each layer's blame and each weight's gradient, reusing the results from the layer after itOutput → input
4. UpdateEvery weight takes a gradient descent step (or an Adam step)Everywhere at once

A neuron that sends its output to several neurons in the next layer collects blame from all of them, added together. That's why, in the Python example, the hidden layer's blame is calculated with the whole weight matrix: d_out @ W2.T.

5.6You'll never do this by hand again

Working out gradients by hand is great for understanding, but impractical for real networks. Deep learning libraries do it automatically, using a technique called automatic differentiation (autodiff).

As your network runs forward, the library quietly records every calculation in a computational graph. It knows the slope of every simple operation (multiply, add, sigmoid, ReLU…), so it can run the chain rule backwards through the whole graph for you.

LibraryHow backpropagation is triggered
Keras (Module 6)Completely hidden inside model.fit()
TensorFlowtf.GradientTape() records the operations, then tape.gradient(loss, weights)
PyTorchloss.backward() fills in the gradient of every weight

So why learn it? Because understanding backpropagation explains why training sometimes fails: vanishing gradients, exploding gradients, dying ReLUs and learning rates that are too high all come from how blame flows backwards. You'll use that understanding in Module 7.

5.7Vanishing and exploding gradients, revisited

In the worked example, the blame was multiplied by a weight and an activation slope at every layer on its way back. In a deep network, that happens many times over:

If each layer multiplies the blame by…After 20 layersProblem
0.50.5²⁰ ≈ 0.000001Vanishing gradients: early layers barely learn
1.01Healthy: the signal arrives intact
1.51.5²⁰ ≈ 3,300Exploding gradients: huge, unstable updates

Fixes include ReLU activations (Module 3), careful starting weights, batch normalisation, gradient clipping and skip connections. You'll meet all of them in Module 7.

5.8Backpropagation from scratch in Python

In Module 2, a single perceptron could never learn XOR. Let's build a 2-4-1 network in NumPy, write the forward pass, backward pass and update ourselves, and watch it solve XOR.

backprop_xor.py
import numpy as np

# XOR: the problem a single perceptron could never solve (Module 2)
X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
y = np.array([[0], [1], [1], [0]])

sigmoid = lambda z: 1 / (1 + np.exp(-z))
rng = np.random.default_rng(1)

# A 2-4-1 network: 2 inputs, 4 hidden neurons, 1 output
W1, b1 = rng.normal(0, 1, (2, 4)), np.zeros((1, 4))
W2, b2 = rng.normal(0, 1, (4, 1)), np.zeros((1, 1))
lr = 1.0

for epoch in range(5001):
    # ---- Forward pass ----
    h = sigmoid(X @ W1 + b1)            # hidden layer
    y_hat = sigmoid(h @ W2 + b2)        # output layer
    loss = np.mean((y - y_hat) ** 2)

    # ---- Backward pass (backpropagation) ----
    d_out = (y_hat - y) * y_hat * (1 - y_hat)     # blame at the output
    d_hidden = (d_out @ W2.T) * h * (1 - h)       # blame passed back to hidden

    # ---- Update every weight (gradient descent) ----
    W2 -= lr * h.T @ d_out
    b2 -= lr * d_out.sum(axis=0, keepdims=True)
    W1 -= lr * X.T @ d_hidden
    b1 -= lr * d_hidden.sum(axis=0, keepdims=True)

    if epoch in (0, 500, 1000, 2000, 5000):
        print(f"Epoch {epoch:4}: loss = {loss:.4f}")

print("\nPredictions after training:")
for inputs, pred in zip(X, y_hat):
    print(f"  {inputs} -> {pred[0]:.3f}  (rounded: {round(pred[0])})")
Output
Epoch    0: loss = 0.2749
Epoch  500: loss = 0.0135
Epoch 1000: loss = 0.0023
Epoch 2000: loss = 0.0008
Epoch 5000: loss = 0.0002

Predictions after training:
  [0 0] -> 0.012  (rounded: 0)
  [0 1] -> 0.984  (rounded: 1)
  [1 0] -> 0.986  (rounded: 1)
  [1 1] -> 0.019  (rounded: 0)

What the output tells us

  • The loss falls from 0.275 to 0.0002 over 5,000 epochs, as backpropagation steadily improves all 17 weights and biases.
  • XOR is solved: the predictions are 0.012, 0.984, 0.986 and 0.019, which round to exactly 0, 1, 1, 0. A hidden layer, trained by backpropagation, did what the perceptron never could.
  • d_out is the output's blame, the same "loss slope × sigmoid slope" as in the worked example.
  • d_hidden passes that blame back through W2 and multiplies by the hidden sigmoid slope: the chain rule, for 4 neurons and 4 examples at once.

Try this yourself

Change the hidden layer from 4 neurons to 2 ((2, 2) and (2, 1)) and run it with a few different seeds. Sometimes it solves XOR and sometimes it gets stuck. That's a local minimum in action, and one reason bigger networks are often easier to train.

SummaryKey takeaways

  • Backpropagation works out every weight's share of the blame for the error, efficiently.
  • It uses the chain rule: the effect along a chain is the product of the effects of each link.
  • Training repeats: forward pass → loss → backward pass → update.
  • Blame flows backwards, layer by layer, reusing the results from the layer after.
  • Libraries do it automatically with autodiff: Keras inside fit(), PyTorch with loss.backward().
  • Repeated multiplying causes vanishing (too small) or exploding (too big) gradients.
  • A hidden layer trained with backpropagation solves XOR.

Check your understanding

Your neural networks roadmap

  1. 01
    Introduction to Neural NetworksWhat neural networks are and how they work
  2. 02
    The Perceptron and the Artificial NeuronBuild a single neuron from scratch
  3. 03
    Activation FunctionsSigmoid, tanh, ReLU and softmax
  4. 04
    Loss Functions and Gradient DescentHow networks measure and reduce error
  5. 05
    BackpropagationYou are here
  6. 06
    Building Networks with KerasYour first deep learning library
  7. 07
    Training Better NetworksOverfitting, dropout, batch normalisation, early stopping
  8. 08
    Convolutional Neural NetworksTeaching computers to see
  9. 09
    Recurrent Neural Networks and LSTMsWorking with sequences
  10. 10
    Transformers and AttentionThe architecture behind ChatGPT and Claude
  11. 11
    Transfer Learning and Pretrained ModelsStanding on the shoulders of giants
  12. 12
    Capstone ProjectBuild and present a deep learning project