Backpropagation Intuition: The Chain Rule on a Thin Network

Use a network with one neuron per layer to see how the chain rule gives every gradient, why we work backwards, and why gradients fade.

Deep Learning- Fundamentals to Advanced Concepts

Before the general formulas, look at the smallest possible deep network. It has one neuron in every layer, so every weight is a single number and there are no matrices to confuse us.

The thin network

x  →  a1=w1x  →  h1=σ(a1)  →  a2=w2h1  →  h2=σ(a2)  →  a3=w3h2  →  y^=σ(a3)x \;\to\; a_1 = w_1 x \;\to\; h_1 = \sigma(a_1) \;\to\; a_2 = w_2 h_1 \;\to\; h_2 = \sigma(a_2) \;\to\; a_3 = w_3 h_2 \;\to\; \hat y = \sigma(a_3)

with squared-error loss L=12(y^−y)2L = \tfrac12(\hat y - y)^2.

A chain of eight nodes from x through a1, h1, a2, h2, a3, y-hat to the loss, with forward arrows on top and backward gradient arrows below
Forward: compute each value. Backward: each gradient is built from the one to its right.

We want ∂L/∂w1\partial L / \partial w_1, the effect of the very first weight on the loss.

A change in w1w_1 changes a1a_1, which changes h1h_1, then a2a_2, h2h_2, a3a_3, y^\hat y and finally LL. The chain rule multiplies the derivative of each link:

∂L∂w1=∂L∂y^⏟y^−y  ∂y^∂a3⏟y^(1−y^)  ∂a3∂h2⏟w3  ∂h2∂a2⏟h2(1−h2)  ∂a2∂h1⏟w2  ∂h1∂a1⏟h1(1−h1)  ∂a1∂w1⏟x\frac{\partial L}{\partial w_1} = \underbrace{\frac{\partial L}{\partial \hat y}}_{\hat y - y}\; \underbrace{\frac{\partial \hat y}{\partial a_3}}_{\hat y(1-\hat y)}\; \underbrace{\frac{\partial a_3}{\partial h_2}}_{w_3}\; \underbrace{\frac{\partial h_2}{\partial a_2}}_{h_2(1-h_2)}\; \underbrace{\frac{\partial a_2}{\partial h_1}}_{w_2}\; \underbrace{\frac{\partial h_1}{\partial a_1}}_{h_1(1-h_1)}\; \underbrace{\frac{\partial a_1}{\partial w_1}}_{x}

Every factor is easy: the derivative of a sigmoid is σ(1−σ)\sigma(1 - \sigma), the derivative of a product w hw\,h with respect to hh is ww, and with respect to ww it is hh.

Real numbers

Take x=1x = 1, y=1y = 1 and weights w1=0.5w_1 = 0.5, w2=−0.3w_2 = -0.3, w3=0.8w_3 = 0.8.

Forward pass: h1=0.6225h_1 = 0.6225, h2=0.4535h_2 = 0.4535, y^=0.5897\hat y = 0.5897, loss =0.0842= 0.0842.

The factors:

FactorValue
y^−y\hat y - y−0.4103-0.4103
y^(1−y^)\hat y(1 - \hat y)0.24200.2420
w3w_30.800.80
h2(1−h2)h_2(1 - h_2)0.24780.2478
w2w_2−0.30-0.30
h1(1−h1)h_1(1 - h_1)0.23500.2350
xx1.01.0

The gradients: multiplying the factors gives

∂L∂w3=−0.0450,∂L∂w2=−0.01225,∂L∂w1=0.00139\frac{\partial L}{\partial w_3} = -0.0450,\qquad \frac{\partial L}{\partial w_2} = -0.01225,\qquad \frac{\partial L}{\partial w_1} = 0.00139

To check the derivation, we nudge each weight by a tiny amount, recompute the loss and divide by the nudge. The numerical estimates are −0.04501-0.04501, −0.01225-0.01225 and 0.0013880.001388, which agree with the chain-rule values.

Observation 1: work backwards and reuse

Look at how the three gradients share pieces. The first part of the product for w1w_1, namely (y^−y) y^(1−y^) w3 h2(1−h2) w2 h1(1−h1)(\hat y - y)\,\hat y(1-\hat y)\,w_3\,h_2(1-h_2)\,w_2\,h_1(1-h_1), contains the first part of the product for w2w_2 as a prefix.

So instead of multiplying the whole chain again for every weight, we go backwards and keep a running product:

  1. Start with ∂L∂y^\dfrac{\partial L}{\partial \hat y}.
  2. Multiply by y^(1−y^)\hat y (1 - \hat y) to get ∂L∂a3\dfrac{\partial L}{\partial a_3}. Now ∂L∂w3=∂L∂a3 h2\dfrac{\partial L}{\partial w_3} = \dfrac{\partial L}{\partial a_3}\,h_2.
  3. Multiply by w3w_3 to get ∂L∂h2\dfrac{\partial L}{\partial h_2}, then by h2(1−h2)h_2(1-h_2) to get ∂L∂a2\dfrac{\partial L}{\partial a_2}. Now ∂L∂w2=∂L∂a2 h1\dfrac{\partial L}{\partial w_2} = \dfrac{\partial L}{\partial a_2}\,h_1.
  4. Multiply by w2w_2, then by h1(1−h1)h_1(1-h_1), to get ∂L∂a1\dfrac{\partial L}{\partial a_1}. Now ∂L∂w1=∂L∂a1 x\dfrac{\partial L}{\partial w_1} = \dfrac{\partial L}{\partial a_1}\,x.

Each layer's gradient is built from the next layer's, using a couple of multiplications. The total work is proportional to the number of layers. That is backpropagation: the error signal flows backwards and each weight reads off its own gradient on the way.

Try it yourself
Backpropagation flow simulator →

Follow the gradient as it moves back through the layers.

Observation 2: gradients shrink going backwards

Look at the three results: 0.0450.045, 0.0120.012, 0.00140.0014. The earlier the weight, the smaller its gradient, shrinking by a factor of about 4 to 9 at each step here.

The reason is in the factors. Every step back multiplies by a weight and by a sigmoid derivative σ(1−σ)\sigma(1-\sigma), which is never more than 0.250.25. Multiply enough numbers smaller than 1 and the product collapses toward zero. The early layers then learn very slowly.

This is the vanishing gradient problem, which you met in the history course when we asked why deep networks stayed hard to train. Now you can see it happen in numbers, and the later remedies (other activations, better initialisation) will make sense.

MediumBackpropagation

In the thin network, which quantities does dL/dw2 need, and which does it reuse from the gradient of w3?

MediumVanishing gradients

Why do gradients for early layers tend to be small when every activation is a sigmoid?

MediumBackpropagation

Why is computing gradients from the output backwards better than starting from each weight?