Part VIII — Neural Network Fundamentals, Backpropagation & Optimizers · Chapter 6

Backpropagation, step by step

Hook

Last chapter chained two neurons along one path. A real network has many paths — every weight needs its own gradient. Is that a completely new problem, or the same one, more times?

Intuition
w11 = 0.50 — h1 = 0.50, y = 0.59, dL/dw11 = 0.0535

This is the loss of a real two-layer network — 2 inputs, 2 hidden neurons, 1 output — as a function of just one weight, w11w_{11}, holding everything else fixed. Drag it: the tangent line is backprop's answer for dL/dw11dL/dw_{11}, computed by chaining through both layers.

Formalize

Backpropagation is the chain rule, applied backward from the loss, one layer at a time:

Lw11=Lyyzoutzouth1h1z1z1w11\frac{\partial L}{\partial w_{11}} = \frac{\partial L}{\partial y}\cdot\frac{\partial y}{\partial z_{\text{out}}}\cdot\frac{\partial z_{\text{out}}}{\partial h_1}\cdot\frac{\partial h_1}{\partial z_1}\cdot\frac{\partial z_1}{\partial w_{11}}
  • LL — the loss, measuring how wrong the network's prediction is.
  • w11w_{11} — the weight connecting input 1 to hidden neuron 1, the one being differentiated.
  • yy — the network's final output.
  • zoutz_{\text{out}} — the output neuron's raw weighted sum, before its activation.
  • h1h_1 — hidden neuron 1's activation, feeding into the output.
  • z1z_1 — hidden neuron 1's raw weighted sum, before its activation.
  1. The loss adds a new starting term

    Five factors total, but only two are genuinely new beyond Chapter 4: the loss contributes its own local derivative, L/y\partial L/\partial y, at the very start of the chain.

  2. One factor is just a connecting weight

    zout/h1\partial z_{\text{out}}/\partial h_1 is nothing more than v1v_1 — the weight connecting h1h_1 to the output. Everything else in the five-factor product is the same local-slope idea from Chapter 4.

  3. Every weight reuses the same shared terms

    Every other weight in the network gets its gradient the same way, reusing the exact same L/zout\partial L/\partial z_{\text{out}} and L/z1\partial L/\partial z_1 terms computed once and shared.

Play
loss = 0.1109, dL/dw11 = 0.0263

Push w11w_{11} negative and watch the loss keep falling — this particular network, on this particular input, never stops preferring a more negative w11w_{11} within this range. The gradient still tells you the direction correctly at every point, even where it isn't near zero.

Worked example

At w11=0.5w_{11}=0.5:

  1. Forward pass

    z1=0.5(1)+(0.3)(2)+0.1=0z_1 = 0.5(1) + (-0.3)(2) + 0.1 = 0 exactly, so h1=σ(0)=0.5h_1=\sigma(0)=0.5. Forward through the rest:

    • z2=0.2(1)+0.4(2)+0.2=0.8z_2 = -0.2(1)+0.4(2)+0.2 = 0.8, so h2=σ(0.8)0.690h_2=\sigma(0.8)\approx0.690
    • zout=1.5(0.5)+(1.0)(0.690)+0.30.360z_{\text{out}} = 1.5(0.5)+(-1.0)(0.690)+0.3 \approx 0.360
    • y=σ(0.360)0.589y=\sigma(0.360)\approx0.589
    • loss =0.5(y0)20.173=0.5(y-0)^2 \approx 0.173
  2. Backward into the output neuron

    L/y=y=0.589\partial L/\partial y = y = 0.589 (target is 00), times σ(zout)=y(1y)0.242\sigma'(z_{\text{out}})=y(1-y)\approx0.242 gives L/zout0.143\partial L/\partial z_{\text{out}}\approx0.143. That one number is shared by every weight feeding the output:

    • L/v1=0.143h10.071\partial L/\partial v_1 = 0.143\cdot h_1 \approx 0.071
    • L/v2=0.143h20.098\partial L/\partial v_2 = 0.143\cdot h_2\approx0.098
    • L/c0.143\partial L/\partial c \approx0.143
  3. Push further back, into the hidden neurons

    For hidden neuron 1: L/h1=0.143v10.214\partial L/\partial h_1 = 0.143\cdot v_1\approx0.214, times σ(z1)=h1(1h1)=0.25\sigma'(z_1)=h_1(1-h_1)=0.25 gives L/z10.053\partial L/\partial z_1\approx0.053 — shared by every weight feeding h1h_1:

    • L/w110.053(1)=0.053\partial L/\partial w_{11}\approx0.053(1)=0.053
    • L/w120.053(2)=0.107\partial L/\partial w_{12}\approx0.053(2)=0.107
    • L/b10.053\partial L/\partial b_1\approx0.053

    The exact same mechanism, run on neuron 2: L/h2=0.143v20.143\partial L/\partial h_2 = 0.143\cdot v_2\approx-0.143, times σ(z2)=h2(1h2)0.214\sigma'(z_2)=h_2(1-h_2)\approx0.214 gives L/z20.030\partial L/\partial z_2\approx-0.030 — shared by every weight feeding h2h_2:

    • L/w210.030(1)=0.030\partial L/\partial w_{21}\approx-0.030(1)=-0.030
    • L/w220.030(2)=0.061\partial L/\partial w_{22}\approx-0.030(2)=-0.061
    • L/b20.030\partial L/\partial b_2\approx-0.030
  4. Tally the result

    All nine gradients, from two shared numbers (L/zout\partial L/\partial z_{\text{out}}, and per hidden neuron L/z1\partial L/\partial z_1 or L/z2\partial L/\partial z_2) and the inputs each weight multiplies.

Checkpoint

Drag w11 until dL/dw11 reaches 0.03 (within 0.005).

w11 = 0.50 — dL/dw11 = 0.0535
Drag the point to try it
Summary
Lw11=Lyyzoutzouth1h1z1z1w11\frac{\partial L}{\partial w_{11}} = \frac{\partial L}{\partial y}\cdot\frac{\partial y}{\partial z_{\text{out}}}\cdot\frac{\partial z_{\text{out}}}{\partial h_1}\cdot\frac{\partial h_1}{\partial z_1}\cdot\frac{\partial z_1}{\partial w_{11}}

Every gradient in this chapter was checked against a plain numerical derivative — nudge a weight by a tiny amount, remeasure the loss, compare. That's the whole promise of autograd (short for automatic differentiation): whatever backprop computes analytically, a numerical check should reproduce. The next chapters ask what starts to go wrong with this chain once a network gets deep enough that it's dozens of layers long, not two.