Backpropagation Solved Step by Step
Press Next → or use ← → arrow keys
The Network — Read the Diagram
Two inputs, two hidden neurons, one output. Every arrow is a weight; both layers use the sigmoid activation.
Four weights feed the hidden layer, two feed the output. Our whole job is to nudge all six so the prediction moves closer to the target — and backprop tells us exactly how.
The Givens
Everything we start with — inputs, target, weights, and the two functions:
y = 1.0 (target)
σ(z) = 1 / (1 + e⁻ᶻ)
L = ½(ŷ − y)²
w₁₂ = 0.3, w₂₂ = 0.3
w₁₃ = 0.3 (h₁→o₃)
w₂₃ = 0.9 (h₂→o₃)
Run forward to get the prediction and loss, push the error backward for all six gradients, then update every weight with learning rate η = 0.5.
Forward Pass — Hidden Layer
Each hidden neuron takes its weighted sum, then squashes it with sigmoid:
ah1 = 0.5523 and ah2 = 0.5781 now become the inputs to the output neuron.
Forward Pass — Output & Loss
The output neuron combines the two hidden activations, squashes once more, and we score the result:
The network undershot. The loss of 0.0561 is the gap we now carry backward to fix — every weight will learn its share of the blame.
Backward — The Output Error δ
Backprop starts at the output. The error signal δ combines how the loss changes with the prediction and how the sigmoid bends there:
Every gradient in the output layer, and every δ further back, is built from this one number. Compute δ once, reuse it everywhere.
Backward — Output Weight Gradients
Each output-weight gradient is simply δo3 times the activation that fed into it:
A weight's gradient is always the error signal at its destination multiplied by the activation at its source. That single rule powers the entire backward pass.
Backward — Propagate to the Hidden Layer
Send δo3 back through the output weights, then multiply by each hidden neuron's sigmoid slope:
Because w₂₃ = 0.9 versus w₁₃ = 0.3, more of the output error flows into h₂ (δh2 is three times δh1). Blame is shared in proportion to influence.
Backward — Input Weight Gradients
The last four gradients follow the same rule: each hidden δ times the input feeding that weight.
| Weight | δ × input | Gradient |
|---|---|---|
| w₁₁ (x₁→h₁) | δh1 × 0.35 | −0.001938 |
| w₂₁ (x₂→h₁) | δh1 × 0.70 | −0.003875 |
| w₁₂ (x₁→h₂) | δh2 × 0.35 | −0.005733 |
| w₂₂ (x₂→h₂) | δh2 × 0.70 | −0.011466 |
Two at the output, four at the input — every weight in the network has been assigned its exact share of the error. Time to update.
The Whole Picture at a Glance
Forward values in green, the error signals δ that flowed backward in amber:
δ starts at −0.0746 at the output and dwindles to −0.0055 and −0.0164 at the hidden layer. Multiply many such shrinking steps and you get the vanishing-gradient problem.
Weight Update — Before & After
Apply w_new = w_old − η · gradient with η = 0.5. Every weight ticks upward:
| Weight | Old | Gradient | New | Δ |
|---|---|---|---|---|
| w₁₁ | 0.2000 | −0.001938 | 0.2010 | +0.0010 |
| w₂₁ | 0.2000 | −0.003875 | 0.2019 | +0.0019 |
| w₁₂ | 0.3000 | −0.005733 | 0.3029 | +0.0029 |
| w₂₂ | 0.3000 | −0.011466 | 0.3057 | +0.0057 |
| w₁₃ | 0.3000 | −0.041212 | 0.3206 | +0.0206 |
| w₂₃ | 0.9000 | −0.043140 | 0.9216 | +0.0216 |
The output weights (w₁₃, w₂₃) move most — they're closest to the error. Repeat this whole loop thousands of times and the loss steadily falls.
Why Every Weight Increased
If the prediction is too low, weights should rise; too high, they should fall. When the signs line up like this, your backprop is almost certainly correct.
Python — Every Number Confirmed
The same calculation in a dozen lines. Run it and the outputs match our hand-work to four decimals:
import numpy as np
x1, x2 = 0.35, 0.70; y = 1.0; lr = 0.5
w11, w21, w12, w22 = 0.2, 0.2, 0.3, 0.3
w13, w23 = 0.3, 0.9
sig = lambda z: 1/(1+np.exp(-z))
sigD = lambda z: sig(z)*(1-sig(z))
# forward
z_h1 = w11*x1 + w21*x2; a_h1 = sig(z_h1) # 0.2100 → 0.5523
z_h2 = w12*x1 + w22*x2; a_h2 = sig(z_h2) # 0.3150 → 0.5781
z_o3 = w13*a_h1 + w23*a_h2; a_o3 = sig(z_o3) # 0.6860 → 0.6651
# backward
d_o3 = (a_o3 - y) * sigD(z_o3) # -0.074617
d_h1 = (d_o3 * w13) * sigD(z_h1) # -0.005536
d_h2 = (d_o3 * w23) * sigD(z_h2) # -0.016380
# update every weight: w -= lr * (delta * input)
w13 -= lr * d_o3 * a_h1 # 0.3 → 0.3206
w23 -= lr * d_o3 * a_h2 # 0.9 → 0.9216
δo3 = −0.074617, the hidden deltas, and every updated weight land exactly on the numbers we derived. That's your gradient check.
The 8-Step Recipe
Every deep network — from this 2×2×1 toy to a giant transformer — runs exactly these eight steps. The only difference is scale.