Unit 6 gave you the chain rule. This unit turns it into the engine that trains every neural network: backpropagation. You will push a number forward through a chain of tiny steps, then send the blame back through the same steps. You will train one neuron with your own hands and watch its error drop. By the end, you will see how one backward sweep tells every knob in a network which way to turn, and why that costs almost nothing.
≈ 80 min read + play7 interactive widgets · 5 in 3D · train a neuron live16 inline checks🧾 13 proofs, step by step — tucked into drawers for when you want them✍ 11 solved practice problems
drag the graph to orbit
1
The million-knob problem
Imagine this
You make chai for twenty guests. You taste it: too sweet, and a little weak. What do you change?
You have four knobs: sugar, tea leaves, milk and boiling time. With four knobs you can reason it out. Less sugar, more tea leaves, done.
Now imagine a recipe with a million knobs, and no idea what each one does. That is a neural network. This unit answers one question: how does each knob find out which way to turn?
First, the names. The network makes a guess. The loss is one number that says how bad the guess was, like "too sweet, by this much". Training means turning every knob a little, so that the loss goes down.
From Unit 6 you know what each knob needs. It needs the slope of the loss with respect to that knob — mathematicians call it the partial derivative. It says: "turn me up a little, and the loss changes by this much". Gradient descent then turns each knob a little bit downhill.
So the whole job is this: find a million slopes, quickly, at every training step.
Try doing it by hand for one small function from the lecture:
f(x)=x2+ex2+cos(x2+ex2)
Its slope, worked out with the chain rule, is already a mouthful:
dxdf=2x2+ex22x+2xex2−sin(x2+ex2)(2x+2xex2)
That is for one input. A real network has millions of knobs, even billions. Writing a formula for each slope is hopeless.
The way out has two ideas. First, break the function into tiny steps. Second, send the blame backwards through those steps. That is backpropagation. The rest of this unit is these two ideas, slowly.
The realization
Training needs one slope per knob, at every step. So the real question is not "what is the slope?" but "how do we get a million slopes cheaply?"
Backpropagation is the answer: tiny steps, and blame sent backwards.
Pause & predict
A network has a million knobs. One way to find each knob's slope: nudge that knob, run the network again, and see how the loss moved. How much work is that per training step?
In one sentence: training needs the loss's slope for every knob at every step, and finding them one knob at a time would cost one run of the network per knob.
2
Baby steps — the computation graph
Imagine this
Your food order arrives 10 minutes late. The delivery app wants to know who caused the delay.
It looks at the chain: the kitchen cooked, the rider picked up, the rider drove to you. It starts at the end, "10 minutes late", and walks backwards along the chain. At each step it asks: how much of the delay came from you?
That backward walk is exactly what backpropagation does. First the order goes forward through the steps. Then the blame comes back through the same steps.
Let's do it with the scary function from Section 1. We will not differentiate it. We will just compute it, one tiny step at a time, and give each result a name:
a=x2,b=ea,c=a+b,d=c,e=cos(c),f=d+e
Each step is easy: a square, an exponential, an addition. Draw each step as a dot, with an arrow from each input to the step that uses it. This picture is a computation graph. Every deep-learning library builds one behind the scenes.
A tiny example with x=1: a=1, b=e≈2.718, c≈3.718, d≈1.928, e=cos(3.718)≈−0.838, so f≈1.090. That is the forward pass: values flow from left to right.
Now the backward pass. Every dot gets a blame: how much f would change if that dot changed by a tiny bit. We write it with a bar, vˉ (read it: "v-bar"), and it means ∂f/∂v. The last dot blames itself fully, so fˉ=1. Then each dot hands blame to the dots that fed it, multiplied by its own small, easy slope.
The graph machinevalues flow right, then blame flows back left
Try: press ▶ forward. Then press step once again and again to walk the blame home. Pause at c: two pieces of blame arrive there and add.
drag the graph to orbit it
—
Green: values going forward. Orange: blame coming back. The blame that reaches x is the answer df/dx, checked here against a nudge.
Errata — check this against your companion doc
The companion runs this graph at x=2 and reports e=cos(58.6)≈0.83 and df/dx≈−2.224. The slip: 58.6 is in radians. In radians, cos(58.6)≈−0.46 and sin(58.6)≈0.89.
So cˉ=2c1−sin(c)≈0.065−0.888=−0.822 (not −0.01), and the true answer is df/dxx=2≈−182.87. The ex2 term makes it huge. The companion's method is right; only the arithmetic slipped. Set the slider to x=2 and see for yourself.
The realization
Any function, however scary, is a chain of easy steps. Forward, each step computes a value. Backward, each step receives a blame vˉ=∂f/∂v, starting from fˉ=1.
The blame that reaches x at the far left is the answer df/dx.
Pause & predict
In the graph, a=x2 feeds two steps: b=ea and c=a+b. When the blame walks back, what does a receive?
In one sentence: write the function as a chain of easy steps; values flow forward, and blame vˉ=∂f/∂v flows backward from fˉ=1 to every step.
3
The whole algorithm is two rules
Imagine this
Petrol goes up by ₹1 a litre. How much does your monthly budget go up?
One route. Each ₹1 on petrol adds ₹0.50 per km to auto fares. You ride 40 km a month. So your fares rise by 0.5 × 40 = ₹20. Along a chain of effects, the rates multiply.
A second route. Petrol also makes vegetables costlier to bring to market: ₹15 more on your monthly vegetable bill. Your total: 20 + 15 = ₹35 for every ₹1 on petrol. When two routes reach the same place, their effects add.
That is all of backpropagation. Two rules:
×Rule 1 — along a path, multiply. Each arrow has a small slope: how much the next step moves when this one moves by 1. Along a path, these slopes multiply, like the petrol rates.
+Rule 2 — where paths meet, add. If x can reach f by several routes, work out each route's product, then add them up.
Backprop simply organises these two rules so that no path is ever walked twice.
Here is the smallest graph with two routes, from the practice set: f=uv, where u=x2+y and v=x−y. At (x,y)=(1,1) we get u=2, v=0 and f=0.
Route through u: the slope from x to u is 2x=2, and from u to f it is v=0. Product: 2×0=0.
Route through v: the slope from x to v is 1, and from v to f it is u=2. Product: 1×2=2. Now add the routes:
∂x∂f=via u0+via v2=2
Check it the long way. f=(x2+y)(x−y)=x3−x2y+xy−y2, so ∂f/∂x=3x2−2xy+y=3−2+1=2. Same answer. Two tiny products beat one messy expansion, and the gap grows with every layer.
Two roads, one destinationf = uv, u = x² + y, v = x − y · multiply along a road, add the roads
Try: press ▶ send a nudge and watch it travel both roads. Then pick one road at a time. Slide x to 0: one road now carries nothing.
drag the picture to orbit
—
A road's number is its slope; along a road they multiply. The glass column at f stacks what each road delivers, so its height is ∂f/∂x.
The realization
∂x∂f=routes∑arrows on the route∏(small slope)
Multiply along each route. Add the routes. Backprop does exactly this, and shares the work so that no route is walked twice.
Pause & predict
Still at (x,y)=(1,1). What is ∂f/∂y? (Route via u: ∂u/∂y=1. Route via v: ∂v/∂y=−1.)
In one sentence: backpropagation is two rules — multiply the small slopes along each path, add the paths — done so that no path is walked twice.
4
Why you can trust the two rules — the chain rule, proved
Imagine this
Open a map app and zoom into a winding mountain road. Zoom in more, and more. At some point, the road on your screen looks straight.
That is what a derivative really is. Zoom in close enough on a smooth curve, and it looks like a straight line. The slope of that line is the derivative. The small bend you can still see is the leftover, and it fades fast as you zoom in.
We have been leaning on "multiply along paths, add across paths". It had better be true. The proof needs just the zoom idea, written in symbols.
Take a function g and a point x0. Nudge the input by a small amount h. Saying "g has slope g′(x0)" means:
g(x0+h)=g(x0)+g′(x0)h+r(h),where hr(h)→0 as h→0
In words: new value = old value + slope × nudge + a leftover. And the leftover r(h) is tiny even compared with the tiny nudge h. That last part is the zoom: the bend fades faster than you zoom in.
A small example. Suppose the leftover is r(h)=0.35h2:
nudge h
leftover r(h)
r(h)/h
1
0.350
0.350
21
0.088
0.175
41
0.022
0.088
Halve h and the leftover drops to a quarter. So even r(h)/h halves each time, on its way to 0.
Line plus dying leftover. Near x0 the curve g (blue) and its tangent (orange) differ by the red gap r(h). Halve the nudge and the gap does not merely shrink — it shrinks faster than h (here r(h)=0.35h2), so r(h)/h itself goes to zero. That is the whole content of "has a derivative".
With this "line plus leftover" promise, both rules follow in a few lines each.
×Rule 1. Put two promises in a row, x→u→y. The slopes multiply, and the two leftovers stay tiny.
+Rule 2. Let x reach f through several middle steps at once. Each route brings its own product, and they add.
If you want the algebra · both rules proved, step by step
Prove it · Rule 1 — along a path, multiply
Claim. If u=g(x) and y=f(u), then at x0 (writing u0=g(x0)): dxdy=f′(u0)g′(x0) — the two slopes multiply.
1
Nudge the input by h and ask how much u moves. That is g's own promise:
Δu=g(x0+h)−g(x0)=g′(x0)h+rg(h)Line plus leftover, with rg(h)/h→0. Nothing new — just the definition, applied to g.
2
Feed that movement to f. That is f's promise, written at u0 with nudge Δu:
f(u0+Δu)=f(u0)+f′(u0)Δu+rf(Δu)Same definition, applied to f. Note the nudge f receives is Δu, not h.
3
Substitute step 1 into step 2 and multiply out:
f(g(x0+h))=f(u0)+the clean slopef′(u0)g′(x0)h+call it R(h)f′(u0)rg(h)+rf(Δu)One term proportional to h, and everything else swept into a single bracket R(h).
4
Check that R(h) is a legal leftover — that R(h)/h→0. Piece by piece:
hf′(u0)rg(h)→f′(u0)⋅0=0,hrf(Δu)=Δurf(Δu)⋅hΔu→0⋅g′(x0)=0The first piece is a constant times something dying. The second: Δu/h→g′(x0) by step 1, while rf(Δu)/Δu→0 because Δu→0. (Fine point: if Δu happens to be exactly 0, then rf(Δu)=rf(0)=0 and the term is already zero — no division needed.)
5
Read off the conclusion. We have shown
f(g(x0+h))=f(g(x0))+[f′(u0)g′(x0)]h+R(h),hR(h)→0
— one clean slope, one dying leftover. That is exactly the shape of a derivative's promise, so the number in the bracket is the derivative of the composite. ∎Two promises composed make a third promise, and slopes multiply while the leftovers stay harmless. "Multiply along a path" is now a theorem.
Now the second rule. Suppose f depends on several middle values u1,…,um at once, and each uk depends on x. That is the fork in the graph: one input, many routes.
Prove it · Rule 2 — across paths, add
Claim.dxdf=k=1∑m∂uk∂fdxduk — each route contributes its product, and the contributions add.
1
The many-input promise (Unit 6's total derivative): nudging all inputs at once,
f(u1+Δu1,…,um+Δum)=f(u)+k∑∂uk∂fΔuk+r,∥Δu∥r→0A multivariable derivative is a plane-promise: one slope per input, one shared leftover that dies faster than the total nudge. This is what "differentiable" means in several variables.
2
Each intermediate keeps its own one-variable promise:
Δuk=dxdukh+rk(h),hrk(h)→0Every route's first leg is an honest derivative — m copies of step 1 from Rule 1.
3
Substitute step 2 into step 1 and collect the terms proportional to h:
f(⋯)=f(u)+[k∑∂uk∂fdxduk]h+R(h),R(h)=k∑∂uk∂frk(h)+rThe bracket is the claimed slope. Everything not proportional to h — one leftover per route, plus the shared plane-leftover r — is swept into R(h). Nothing has been dropped yet.
4
The route leftovers die: for each k,
h1⋅∂uk∂frk(h)=∂uk∂f⋅hrk(h)→∂uk∂f⋅0=0A fixed number times something that dies — the same move as step 4 of Rule 1, once per route.
5
The shared leftover dies too. By step 2, ∥Δu∥/h→∥u′(x)∥, where u′=(du1/dx,…,dum/dx). So
hr=∥Δu∥r⋅h∥Δu∥→0⋅∥u′(x)∥=0The constant is ∥u′(x)∥, the size of the combined nudge per unit h. Fine point: if Δu is exactly 0 then r=r(0)=0 and the term is already gone — no division needed. Hence R(h)/h→0.
6
Same shape, same conclusion: the composite keeps a promise whose slope is the bracket — the sum over routes of (slope out) × (slope in). ∎"Add across paths" is not a new fact about graphs. It is what a multi-input derivative means, read one route at a time.
The bridge
The two rules are matrix multiplication in disguise. Suppose a list of inputs x makes a list of middle values u, which makes a list of outputs y. Each stage has a table of slopes, its Jacobian (Unit 6). The chain rule says: multiply the tables, JG∘F=JGJF.
Look at one entry of that product, using row-times-column:
(JGJF)ij=k∑(JG)ik(JF)kj
Each term is one route: input j moves middle value k, which moves output i. Multiply along the route (Rule 1). The sum adds one route per middle value (Rule 2). So row-times-column, which you have used since Unit 1, is the two rules of backprop.
One entry of a Jacobian product, drawn. The sensitivity of output y1 to input x2 is ∑k(JG)1k(JF)k2. Each orange route x2→uk→y1 is one term: multiply its two edge slopes (Rule 1); the three routes add (Rule 2). The row-times-column rule is those two rules at once.
The realization
A derivative is a promise: "near here, the function is a straight line plus a leftover that fades fast". Chain two promises, and the slopes multiply. Let several routes run side by side, and their products add.
And one entry of a matrix product, ∑k(JG)ik(JF)kj, is both rules written at once.
Pause & predict
The promise asks for r(h)/h→0, not just r(h)→0. What would go wrong if we only asked for r(h)→0?
Pause & predict
In (JGJF)ij=∑k(JG)ik(JF)kj, what is one single term (JG)ik(JF)kj, in graph language?
In one sentence: a derivative is a "straight line plus fading leftover" promise; chaining promises multiplies slopes, side-by-side routes add, and row-times-column is both rules at once.
5
The recipe, written once and for all
Imagine this
Think of a company. Staff report to team leads, team leads report to managers, and the managers' work adds up to one number: this year's result.
The result comes in low. The CEO sends each manager a note: "your share of the problem is this much". Each manager passes the note down to each team lead, scaled by how much that lead's work affected the manager. A team lead who works for two managers gets two notes, and adds them.
One sweep from the top down, and everyone knows their share. That is the backprop recipe.
Now in symbols. Number every value in the graph. x1,…,xd are the inputs, the middle steps come next, and the last one, xD, is the output f. Each value is made from its parents (the values that feed it) by one easy function gi:
xi=gi(xPa(xi))
Read Pa(xi) as "the parents of xi". Now walk backwards. The output blames itself fully. Every other value collects blame from its children — the values it feeds:
∂xD∂f=1,∂xi∂f=j:xi∈Pa(xj)∑∂xj∂f∂xi∂gj
Read the second formula like the company notes. Child j already knows its blame ∂f/∂xj. It sends each parent a copy, scaled by its own small slope ∂gj/∂xi. A parent with several children adds up its notes.
Why is this cheap? Two reasons. Each blame is worked out once, then shared by all the parents. And each small slope is easy, because each step is easy: the slope of ea or c, never of the whole scary function. So finding every slope costs about the same as computing the function once.
If you want the algebra · why the recipe always gives the right answer
Prove it · the recipe is correct
Claim. Process the nodes from right to left; then the recipe's xˉi equals the true ∂f/∂xi for every node in the graph.
1
Base case. The rightmost node: xˉD=1=∂f/∂f — the output's sensitivity to itself.
Nudge f by h and f changes by h. Slope 1, no leftover at all.
2
The order does the bookkeeping. Working right to left means: by the time we reach node xi, every child xj (every node that uses xi) has already been processed and — by induction — already holds its correct blame xˉj=∂f/∂xj.
Children sit to the right of their parents in the graph, so a right-to-left sweep always finds the mail ready before it must be sent.
3
Apply Rule 2 at node xi, with its children as the intermediates. Any nudge of xi can reach f only through the children, so §4's theorem says
∂xi∂f=j:xi∈Pa(xj)∑∂xj∂f∂xi∂gj
— and every factor on the right is one the recipe possesses: the child's (already correct) blame, times the local slope of the child's baby step. So the value the recipe writes into xˉi is the true derivative. Right-to-left induction covers the whole graph. ∎The recipe is not a new algorithm to take on trust — it is Rule 2, applied once per node, in an order that guarantees the mail is always ready.
The realization
Set fˉ=1. Walk from right to left. At each value, add up (child's blame × child's small slope) over all its children.
One sweep, and every value in the graph — every input, every weight — holds its slope.
Pause & predict
In the recipe, a value's blame is a sum over its children (the values it feeds). Why children, and not parents?
In one sentence: set fˉ=1, then let every value send each parent its own blame times a small slope — one right-to-left sweep prices every knob.
6
One neuron, trained by your own hands
Imagine this
You step into a hotel shower. You want the water just right. You turn the knob, feel the water, and notice: still too cold.
How far off you are tells you how much to turn. Which way you are off tells you the direction. Turn, feel, turn again. After a few goes, the water is perfect.
A neuron learns exactly like this. It has two knobs, a weight w and a bias b. Backprop "feels the water" and tells each knob how to turn.
The smallest network there is: one neuron. It takes an input x, and it should output a target y. Three easy steps lead from the knobs to the loss:
z=wx+b,a=tanh(z),L=21(a−y)2
In words: mix the input with the knobs (z). Squash it into the range −1 to 1 with tanh (that is a, the output). Measure the miss (L, the loss: half the squared gap).
Now send the blame back. The key stop is δ (the Greek letter "delta"): the blame that reaches z.
δ=∂z∂L=the miss(a−y)slope of tanh(1−a2)
Once you have δ, each knob reads its slope straight off it: ∂L/∂w=δx and ∂L/∂b=δ. Compute δ once, hand out copies.
With the practice set's numbers, w=0.5,b=0,x=1,y=1: z=0.5, a=tanh0.5≈0.462 and L≈0.145. The miss is a−y≈−0.538: too low. So δ≈(−0.538)(0.786)≈−0.423. Both slopes are negative, which says: make w and b bigger.
One training step then moves each knob a little downhill: w←w−η∂L/∂w. Here η (read "eta") is the step size; the widget uses η=0.5.
The learning neuronforward → blame back → step downhill, repeat. That is training.
Try: before each step, guess the sign of δ. Then set the target to y=−1 and watch the same machine push w the other way.
drag the landscape to orbit it
—
It starts at the practice set's numbers: L=0.1447 and δ=−0.4230. Both slopes are negative, so each step makes w and b bigger and the dot rolls downhill.
If you want the algebra · every number in the widget, from scratch
Prove it · every number in the widget, from scratch
Claim.δ=(a−y)(1−a2). Nothing to memorise — derive each local slope, then chain them with Rule 1.
1
The loss.L(a)=21(a−y)2. Nudge a by Δ and expand the square:
21(a+Δ−y)2=21(a−y)2+(a−y)Δ+21Δ2⇒∂a∂L=a−yThe 21Δ2 is the dying leftover. And now you can see why the 21 was planted in the loss: it exists purely to eat the 2 that squaring brings down.
2
The activation.a=tanhz=cs with s=ez−e−z, c=ez+e−z. Notice the pair swaps under differentiation: s′=c and c′=s. Quotient rule:
(cs)′=c2s′c−sc′=c2c2−s2=1−(cs)2=1−tanh2z=1−a2The derivative comes out written in terms of the outputa — which the forward pass already computed. So the backward pass buys 1−a2 for one multiplication, no new function calls.
3
The pre-activation.z=wx+b is linear, and a linear function's slopes are just its coefficients:
∂w∂z=x,∂b∂z=1,∂x∂z=wNudge w by Δ and z moves by xΔ exactly — not even a leftover this time.
4
Chain them (Rule 1, twice).δ=∂z∂L=∂a∂L⋅dzda=(a−y)(1−a2)
With the widget's starting numbers, a−y=0.4621−1=−0.5379 and 1−a2=0.7864:
δ=(−0.5379)(0.7864)=−0.4230
then ∂L/∂w=δx,∂L/∂b=δ,∂L/∂x=δw. ∎Every figure the widget displays is these four lines evaluated — press the buttons above and check any of them by hand.
The realization
δ=(a−y)(1−a2): the miss, times how steep the squash is. Every knob that feeds z then gets δ times one number: x for the weight, 1 for the bias.
Step each knob against its slope, repeat, and the loss really falls. That is training, complete.
Pause & predict
At the start, ∂L/∂w=δ⋅x and ∂L/∂b=δ⋅1, with δ=−0.423. What made them so cheap to get?
Pause & predict
Set the target to y=−1 instead. Before pressing anything: which way will the next step push w?
In one sentence: compute the blame δ=∂L/∂z once, and every knob feeding z reads its slope off it — then step downhill and the loss really falls.
7
A whole layer at once — backprop with matrices
Imagine this
A talent show has two judges and a few contestants. Every judge watches every contestant, but each judge cares about each one differently. Those "how much I care" numbers are the weights.
After the show, the producer says: "Judge 1 scored too low, judge 2 too high." Who should change what?
1A judge's weight on a contestant should change a lot only if that judge was badly offandthat contestant actually performed.
2Each contestant collects feedback from every judge who watched them.
Those two sentences are this whole section.
A real layer is many neurons side by side, all reading the same input list x. In symbols:
Z=Ax+b,a=σ(Z)
A is the table of weights: row i holds neuron i's weights. b holds the biases. The sigmoidσ(z)=1+e−z1 squashes each number into the range 0 to 1, one neuron at a time.
From the layer above, blame arrives: δ(a), one number per neuron. Each says how fast the loss would rise if that neuron's output rose a little. Passing it back through the layer takes four lines:
Step
In everyday words
In symbols
Through the squash
Each neuron's blame is scaled by how steep its own squash is. Neurons don't mix.
δ(Z)=δ(a)⊙a⊙(1−a)
A weight
Blame of its neuron × activity of its input. Big only when both are big.
∂A∂L=δ(Z)x⊤
A bias
Gets its neuron's blame, unchanged.
∂b∂L=δ(Z)
The input
Collects blame from every neuron it fed. This becomes the note for the layer below.
∂x∂L=A⊤δ(Z)
Two symbols to read aloud. ⊙ means "multiply entry by entry": first with first, second with second. And a⊙(1−a) is the sigmoid's slope. It needs only the output a, which the forward pass already has.
A tiny example with the widget's numbers. Neuron 1 outputs a1=0.622, so its slope is 0.622×0.378≈0.235. Blame 0.6 arrives, and 0.6×0.235≈0.141 gets through. Neuron 2 outputs a2=0.953: almost maxed out, like a volume knob already at 95%. Its slope is only 0.045. Blame −0.4 arrives, and just −0.018 gets through.
The weights' slope δ(Z)x⊤ is an outer product: a grid whose row i, column j holds δixj. And A⊤ (read "A transpose": the table flipped over its diagonal) sends the blame back along the columns. Forward, each neuron reads its row. Backward, each input collects its column.
Backprop through a layerthe four lines, with real numbers — watch the blame walk back
Try: press ▶ play to walk the four stages. Then slide δ1(a): row 1 of the weight grid changes, row 2 does not.
—
A tiny layer so every number fits: A=1−120, b=(0,1), x=(1,0.5). From above, δ(a)=(0.6,−0.4) arrives.
Why the transpose. Forward, neuron i reads along rowi — that is what Ax does. Backward, input j must collect blame from every neuron it fed, which means reading down columnj — and reading columns of A is reading rows of A⊤. Same numbers, opposite direction.If you want the algebra · the sigmoid's slope, the diagonal Jacobian, and the three matrix formulas
Prove it · where σ(1−σ) comes from
Claim.σ(z)=1+e−z1 satisfies σ′=σ(1−σ) — so the backward pass needs no new function evaluations.
1
Differentiate with Rule 1: σ=(1+e−z)−1, outer slope −(1+e−z)−2, inner slope −e−z:σ′=−(1+e−z)−2⋅(−e−z)=(1+e−z)2e−zThe two minus signs cancel — sigmoid always rises.
2
Split the fraction into two factors you can recognise:
(1+e−z)2e−z==σ1+e−z1⋅=1−σ1+e−ze−zsince1−σ=1+e−z(1+e−z)−1=1+e−ze−z
So σ′=σ(1−σ). ∎Output in, derivative out: a⊙(1−a) uses only the a the forward pass cached. This is why frameworks store activations — the way back is pure arithmetic.
Prove it · why the sigmoid step is entrywise — the Jacobian is diagonal
Claim.∂Z∂a=diag(a⊙(1−a)), and therefore δ(Z)=δ(a)⊙a⊙(1−a) — a multiplication per neuron, no matrix at all.
1
Who depends on whom.ai=σ(Zi) reads exactly one input, Zi. Nudge a differentZj and ai does not move:
∂Zj∂ai=0(i=j)Every off-diagonal entry of the Jacobian is zero because the activation never mixes neurons — it is applied one entry at a time.
2
The diagonal. On its own input, ai is the one-variable function σ, and the box above gives its slope:
∂Zi∂ai=σ′(Zi)=σ(Zi)(1−σ(Zi))=ai(1−ai)Steps 1 and 2 together: a matrix with ai(1−ai) down the diagonal and 0 everywhere else — diag(a⊙(1−a)).
3
Chain it (Rule 1 in matrix form). The blame on Z is the blame on a times this Jacobian; multiplying a row by a diagonal matrix scales each entry:
δi(Z)=j∑δj(a)∂Zi∂aj=δi(a)ai(1−ai)The sum over j is Rule 2, but only the j=i term survives (step 1) — so the "sum over routes" has one route per neuron. Written for all i at once, that is the ⊙ formula.
4
Check on the widget's numbers.a=(0.622,0.953) gives a⊙(1−a)=(0.235,0.045); with δ(a)=(0.6,−0.4),
δ(Z)=(0.6⋅0.235,−0.4⋅0.045)=(0.141,−0.018)
— exactly what stage 3 below displays. ∎Neuron 2 sits at a=0.953, nearly saturated, so its factor 0.045 throttles almost all of its blame. That is the vanishing-gradient mechanism, in one entry of a diagonal matrix.
Prove it · the three matrix formulas, entry by entry
Claim. The matrix formulas hide no new laws — they are Rule 1 and Rule 2 aimed at each entry, then reassembled into matrix shape. Write δ=δ(Z) for short.
1
A weight Aij. Scan the forward pass Zk=∑pAkpxp+bk: the entry Aij appears in exactly one place — the row k=i, multiplied by xj. One appearance means one path, so Rule 1 alone:
∂Aij∂L=δi⋅∂Aij∂Zi=δixj"Blame of my row, times activity of my column" — now proved, not just recited.
2
Assemble. The matrix whose (i,j) entry is δixj is, by definition, the outer product:
∂A∂L=δx⊤Same shape as A, one honest entry per weight, ready for A←A−η∂L/∂A.
3
A bias bi. It appears only in Zi, with slope 1: ∂L/∂bi=δi⋅1, so ∂L/∂b=δ.
The bias rides its own row and nothing else — blame arrives undiluted.
4
An input xj — the fork.xj appears in every row: Z1,…,Zm all use it. m appearances, m paths — Rule 2:
∂xj∂L=i=1∑mδi∂xj∂Zi=i=1∑mδiAij=(A⊤δ)jSumming δiAij over i walks down columnj of A — and reading columns is exactly what the transpose does. The mysterious A⊤ is Rule 2 wearing matrix clothes.
5
All three formulas recovered from two rules and one scan of where each variable appears. ∎This "find every appearance, add a term per appearance" habit is the entire skill of differentiating matrix expressions. The very next section runs on it.
The realization
Through the squash, scale each neuron's blame by its own slope. Then weights get δ(Z)x⊤, biases get δ(Z), and the layer below gets A⊤δ(Z).
Repeat, layer after layer. That is the inner loop of all of deep learning.
Pause & predict
A layer has a weight table A of size 100×300. What is the shape of ∂L/∂A=δ(Z)x⊤, and why must it be?
Pause & predict
Why does the blame go back through A⊤ (the flipped table) instead of A itself?
In one sentence: scale the blame by each neuron's slope, then weights get δ(Z)x⊤, biases get δ(Z), and the layer below gets A⊤δ(Z) — four lines, the inner loop of deep learning.
8
The gradient cookbook — five rules you'll use forever
Imagine this
A good cook does not work out how to make dal from scratch every evening. She knows a few basic recipes by heart, and combines them.
Slopes of matrix formulas work the same way. Five basic recipes cover almost everything a real model needs. Learn them as sentences, and the symbols follow.
One quick example first. Take a=(2,3) and the dot product x⊤a=2x1+3x2. Nudge x1 by 1: the value goes up by 2. Nudge x2 by 1: it goes up by 3. So the slope is the list (2,3) — just a itself. That is recipe 1.
Here are all five. (Slopes are written as rows, as in Unit 6.)
Recipe
In everyday words
∂x∂x⊤a=a⊤
The slope of a dot product is just the other vector.
∂x∂a⊤x=a⊤
Same thing: a dot product doesn't care about order.
∂X∂a⊤Xb=ab⊤
Each entry Xij is multiplied by aibj, so the slope is that grid: an outer product.
∂x∂x⊤Bx=x⊤(B+B⊤)
x appears twice, so you get two terms: B from one side, B⊤ from the other.
∂s∂(x−As)⊤W(x−As)=−2(x−As)⊤WA
For symmetric W: the least-squares slope. It is the chain rule through the leftover error x−As.
You have met two of these already. Recipe 3 is why the weights' slope in Section 7 came out as an outer product. Recipe 5 is the least-squares loss that trains linear models; it returns in Unit 9. The arena's Problem 7 checks two recipes with real numbers, and Problem 10 uses them on a real model.
One method proves them all: find every place the variable appears, and add one term per place.
If you want the algebra · the whole cookbook in four short derivations
Prove it · the whole cookbook, four short derivations
Claim. Every identity in the table is entry-wise differentiation, organised. The method is always the same: find every appearance of the variable, add one term per appearance.
1
Dot product.x⊤a=∑ixiai. Differentiate with respect to one coordinate xk: every term is constant except xkak, whose slope is ak. Collect the coordinates into a row:
∂x∂(x⊤a)=a⊤And a⊤x is the same scalar, so the table's second line comes free.
2
The sandwich.a⊤Xb=∑i,jaiXijbj. The entry Xij appears once, with coefficient aibj:∂Xij∂(a⊤Xb)=aibj⇒∂X∂(a⊤Xb)=ab⊤The same one-appearance argument that made ∂L/∂A an outer product in the layer proof — it is literally the same fact.
3
The quadratic — where B+B⊤ is born.x⊤Bx=∑i,jBijxixj, and x appears twice in each term. Product rule on xixj, with respect to xk: the left copy fires when i=k, contributing ∑jBkjxj=(Bx)k; the right copy fires when j=k, contributing ∑iBikxi=(B⊤x)k. Add the two:
∂xk∂(x⊤Bx)=(Bx)k+(B⊤x)k⇒∂x∂(x⊤Bx)=x⊤(B+B⊤)Two appearances of x, two donated terms — the "mysterious" +B⊤ is Rule 2's fork, hiding in plain algebra. For symmetric B it collapses to 2x⊤B.
4
Least squares — a chain of the previous lines. Set the residual r=x−As and E=r⊤Wr with W symmetric. Rule 1 with r as the intermediate:
∂s∂E=∂r∂E∂s∂r=line 3r⊤(W+W⊤)⋅r linear in s(−A)=2r⊤W⋅(−A)=−2(x−As)⊤WAThe 2 came from W+W⊤ under symmetry; the minus came from the −As inside the residual. Nothing to memorise once you can rebuild it in two lines. ∎
The realization
Dot product → the other vector. a⊤Xb → the outer product ab⊤. x⊤Bx → x⊤(B+B⊤), because x appears twice.
When in doubt, count where the variable appears, and add one term for each appearance.
Pause & predict
With B=1234 (not symmetric), what is the slope of x⊤Bx with respect to x=(x1,x2)?
Pause & predict
In the least-squares slope −2(x−As)⊤WA, where exactly did the 2 come from?
In one sentence: five recipes — dot product, outer product, the B+B⊤ doubling and least squares — give almost every small slope a real model needs.
9
Why it's so cheap — one sweep, everything reused
Imagine this
A metro line has ten stations. Every station wants to know its fare to the last stop.
The slow way: each station adds up every hop to the end, all by itself. Station 1 adds nine hops, station 2 adds eight, and so on. The same hops get added again and again.
The smart way: start at the end. The station next to the last stop is one hop away. The station before it asks its neighbour and adds one hop. Every hop is counted once.
Backprop is the smart way. (For slopes, the hops multiply instead of add, but the saving is the same.)
Stack K layers, fi=σi(Ai−1fi−1+bi−1), and put a loss at the end: L=∥y−fK∥2. Each layer's knobs θi={Ai,bi} need a slope. The chain rule writes each one as a long product, reaching from the loss back to that layer:
Look at the pattern. Each line is the line above, plus one more factor. The start of every product is shared. That shared start is the running blame δ that Section 7 passed down.
Count the work for K=4 layers. Building each product from scratch takes 2+3+4+5=14 factors. Reusing the shared start takes just 2 new factors per layer: 8 in all. For K=8 it is 44 against 16. The slow count grows like K2/2; the smart one grows like K.
The reuse staircaseeach layer's slope = the one before it + one new block
Try: press ▶ build the staircase. Then slide K up to 8 and compare the grey pile (the slow way) with the lit blocks (backprop).
drag the picture to orbit
—
One tower per layer, one block per chain-rule factor; the left tower sits next to the loss. Grey blocks are work the slow way repeats; lit blocks are all backprop does.
A second saving hides in the order. The loss is one number, so the first factor ∂L/∂fK is a thin row. A row times a matrix is cheap, and gives another thin row. Starting from the input end instead would multiply big square matrices: for layers m wide, about m times more work.
So the sweep must start at the loss. That choice of order is called reverse-mode automatic differentiation.
If you want the algebra · the stacked formula, and why the sweep must start at the loss
Prove it · the stacked formula is the recipe of §5, unrolled
Claim.∂θi∂L=∂fK∂L∂fK−1∂fK⋯∂fi+1∂fi+2∂θi∂fi+1 — no new chain rule, just the postal recipe on a graph that happens to be a line.
1
Draw the graph.fi+1=σi+1(Aifi+bi) means node fi+1 has exactly two parents, fi and θi={Ai,bi}, and node fi has exactly one child, fi+1. The loss L is the single child of fK.
A stack of layers is a chain: each activation feeds only the next. Forks exist only where a parameter joins in.
2
Recipe at an activation node. §5's rule sums over children; fj has one, so the sum has one term:
fˉK=∂fK∂L,fˉj=fˉj+1∂fj∂fj+1(j<K)One child, one piece of mail. Rule 2's sum collapses to a single Rule 1 product.
3
Unroll. Apply step 2 repeatedly, from K down to i+1:
fˉi+1=∂fK∂L∂fK−1∂fK⋯∂fi+1∂fi+2Each application appends one more Jacobian on the right. This running product is the δ(a) that §7 handed down to each layer.
4
Recipe at the parameter node.θi has one child, fi+1, so
∂θi∂L=θˉi=fˉi+1∂θi∂fi+1
and substituting step 3 gives the claim. ∎Every layer's gradient is the same prefix fˉi+1 times one local factor — which is exactly why computing the prefixes once, from the loss end, prices the whole stack.
Prove it · why the sweep must start at the loss
Claim. The chain ∂f1∂L=∂fK∂L∂fK−1∂fK⋯∂f1∂f2 can be multiplied in either order. One order is about m times cheaper — count it.
1
Shapes first (Unit 6's rule: outputs × inputs). L is a scalar, so ∂L/∂fK is a 1×mrow. Each layer-to-layer Jacobian ∂fi/∂fi−1 is a full m×m matrix, for layers of width m.
One skinny row at the loss end; big square blocks everywhere else. That asymmetry is the whole story.
2
Multiply from the loss end.(1×m)⋅(m×m) costs about m2 multiplications — and returns another 1×m row. Repeat through all K layers:
cost≈Km2,always carrying just a rowThat carried row is exactly the blame δ of the layer section — reverse mode never holds anything bigger than one layer's worth of numbers.
3
Multiply from the input end. The first product is (m×m)⋅(m×m): cost m3, and it returns another m×mmatrix that must be carried the whole way:
cost≈Km3For m=1000, that is a thousand times more work — from nothing but multiplying the same factors in the wrong order.
4
Same factors, same answer, wildly different bill. Keeping the scalar-loss end first means every step is a cheap row-times-matrix product. That choice of order is reverse-mode automatic differentiation. ∎And it explains the fine print to come: reverse mode wins because training has ONE output (the loss) and millions of inputs. Flip that ratio and the other order — forward mode — wins instead.
The realization
Every layer's slope is the same shared start, times one new factor. Carry that start — the blame δ — from the loss backwards, and each factor is used once.
So one backward sweep costs about as much as one forward pass, however many knobs there are.
Pause & predict
Rule of thumb: one backward pass costs about as much as one forward pass. What one fact makes that true?
In one sentence: all the layer slopes share one long start — carry it once, from the loss end, and the whole set costs a single sweep.
10
Linearization — the slope as a stand-in for the function
Imagine this
Stand in an open field. The ground looks flat. For walking to the gate, "the Earth is flat" is a perfect model.
For a flight from Delhi to London, it is badly wrong. The pilot must allow for the curve.
A slope gives you exactly this kind of "flat Earth" model of a function: excellent close by, worse and worse as you go further away.
Once you know the slopes at a point x0, you have the best straight-line guess for the function near x0:
f(x)≈f(x0)+∇f(x0)⊤(x−x0)
In words: value here + slope × how far you moved. This is Unit 6's tangent line, for many inputs at once. (∇f, read "grad f", is the list of all the slopes.)
A tiny example from the companion: f(x)=x2+9 at x0=−4. Here f(−4)=25=5 and the slope is f′(−4)=−4/5=−0.8. So the stand-in line is L(x)=5−0.8(x+4).
At x=−3.5, half a step away, the line guesses 5−0.8×0.5=4.6. The truth is 4.610: very close. Go far away and the guess drifts off. Gradient descent trusts this line for one small step at a time, which is why its steps must be small.
The stand-in linedrag the anchor and the probe · how far off is the straight-line guess?
Try: move the probe twice as far from the anchor. The error grows about four times.
✋ drag near the dot to move the anchor · elsewhere to move the probe
—
At anchor −4 the line is L(x)=5−0.8(x+4). Near the anchor it almost is the curve; far away the red error bar grows fast.
…and with two inputs: the stand-in planef(x, y) = eˣ cos y — the companion's second example; the glass sheet is the "flat Earth" at the anchor
drag the surface to orbit it
At the origin the slopes are (1,0), so the plane is L=1+x: tilted along x, flat along y. Shrink the probe circle and the red gap shrinks like its radius squared.
If you want the algebra · the stand-in is the first two Taylor terms
Prove it · the stand-in is the first two Taylor terms
Claim. The linearization L(x)=f(x0)+f′(x0)(x−x0) is what is left of the Taylor series when every term with (x−x0)2 or higher is dropped — and the first dropped term tells you the error.
1
Taylor at x0 (Unit 8's subject, used once here): with h=x−x0,
f(x0+h)=f(x0)+f′(x0)h+21f′′(x0)h2+61f′′′(x0)h3+⋯Keep the first two terms and you are holding L(x) exactly. Everything after them is §4's leftover r(h), now written out.
2
The error is led by the h2 term. For small h the h3 and later terms are smaller still, so
f(x)−L(x)≈21f′′(x0)(x−x0)2Twice the distance, four times the error — the same "leftover dies faster than h" you saw drawn in §4.
3
Check on the widget.f=x2+9, so f′′(x)=(x2+9)3/29 and f′′(−4)=1259=0.072. Probe at x=−3.5, i.e. h=0.5:
21⋅0.072⋅0.52=0.009vs. the widget’s4.6098−4.6=0.0098The prediction is off only by the h3 crumbs. So a gradient does more than point downhill — with f′′ it also prices how far the linear stand-in can be trusted. ∎
The realization
f(x0)+∇f(x0)⊤(x−x0) is the "flat Earth" version of f near x0.
Its error grows like the square of the distance: twice as far, about four times the error. Every gradient-descent step leans on this promise.
Pause & predict
The companion also linearizes f(x,y)=excosy at (0,0). There the value is 1 and the slopes are (1,0). What is the stand-in plane?
In one sentence:f(x0)+∇f(x0)⊤(x−x0) is the best straight-line stand-in near x0 — the promise every gradient-descent step relies on.
11
Fine print worth knowing
Imagine this
You want the weight of one ₹1 coin, but your kitchen scale only shows whole grams. So you weigh your purse, take the coin out, and weigh it again. The difference is the coin: about 4 grams. That works.
Now try the same trick to weigh a single hair. The difference is far smaller than the scale's own error. You get noise.
Computers hit the same wall when they estimate slopes by nudging. That is one more reason backprop was needed.
Three ways to get a slope.
Way
How it works
The catch
Symbolic
Work out the formula, like on paper.
Formulas blow up in size for deep functions.
Numerical
Nudge the input, see how far the output moves, divide.
One run per knob, plus rounding noise (the hair problem).
Automatic (this unit)
Follow the program step by step, and apply the chain rule to each step.
Exact, and about as cheap as one run.
The hair problem, in numbers. The nudge estimate is
2hf(x+h)−f(x−h)
It has two enemies. If h is big, the straight line between the two points misses the curve's true slope. If h is tiny, the computer subtracts two almost equal numbers, and the result drowns in rounding noise. Somewhere in between is a best h. Find it:
The gradient checkerthe nudge estimate vs. the exact slope — there is a best h, and it is not 0
Try: press ▶ shrink h, or slide it yourself. The error falls fast, then, near 10−6, it turns and climbs again.
—
The function is the one from Section 1, at x=1, where the exact slope is 5.98308. Too big an h bends the answer; too small drowns it in rounding noise.
If you want the algebra · the V-shape has a formula
Prove it · the V-shape has a formula
Claim. The checker's error falls like h2, rises like 1/h, and bottoms out at a best step h∗ of order 10−6–10−5 — all three facts derived, not observed.
1
Taylor both evaluations around x (Unit 6's tool, Unit 8's whole subject):
f(x±h)=f(x)±f′(x)h+2f′′(x)h2±6f′′′(x)h3+⋯Same expansion, two signs — writing them together is what makes the next line click.
2
Subtract — the even terms cancel.f(x+h)−f(x−h)=2f′(x)h+3f′′′(x)h3+⋯. Divide by 2h:
2hf(x+h)−f(x−h)=f′(x)+6f′′′(x)h2+⋯The h2 term is the left wall of the V — slope 2 on log–log axes. (The one-sided version hf(x+h)−f(x) keeps an 2f′′h term — slope only 1. That is why the checker uses the centred difference.)
3
Rounding. The computer stores f(x±h) only to relative precision u≈10−16, so the subtraction of two nearly equal numbers carries an absolute error of about u∣f(x)∣; dividing by 2h turns it into
rounding error≈2hu∣f(x)∣The 1/h is the right wall: shrink h and you divide the same noise by an ever smaller number.
4
Add the walls and set the slope to zero.E(h)≈6∣f′′′∣h2+2hu∣f∣. Differentiate in h:
E′(h)=3∣f′′′∣h−2h2u∣f∣=0⟺h3=2∣f′′′∣3u∣f∣A rising wall plus a falling wall has one lowest point, where the two slopes cancel. Multiplying through by h2 isolates h3.
5
Read off the best step.h∗=(2∣f′′′∣3u∣f∣)1/3∼u1/3≈5×10−6when ∣f′′′∣≈∣f∣
For the monster at x=1, ∣f∣=1.09 but ∣f′′′∣≈153, so h∗≈1×10−6 — the huge third derivative pushes the floor left, which is what the widget shows. ∎And the best possible error is only ∼u2/3≈10−11 (about 10−10 here) — while autodiff is exact to full precision. That is the entire case for automatic differentiation, compressed into one minimisation.
The realization
The nudge estimate's error is (curve error, shrinking like h2) + (rounding noise, growing like 1/h). So there is a best h — about 10−6 here — and even there the answer is off by about 10−10.
Autodiff has neither problem. Nudging survives only as a gradient checker: a quick test that a hand-written backward pass is right.
Pause & predict
In the gradient checker, why does making h smaller and smaller eventually make the estimate worse?
The squash's slope is free.σ′=σ(1−σ) needs only the output a, which the forward pass already has. The same trick works for tanh: its slope is 1−a2. That is why libraries store every layer's output on the way forward. That store is the "memory cost" of training.
Vanishing gradients. Remember the party game where a message is whispered down a line of people, and it gets fainter each time? Each sigmoid layer passes on at most a quarter of the blame it receives, because a(1−a)≤41. With ten layers, the blame reaching layer 1 is at most 4−9≈4×10−6 of what left the loss. The early layers hardly learn. This is why deep networks moved to ReLU, whose slope is 1 wherever it is switched on.
Vanishing gradients, drawn. The loss sits to the right of layer 10. Every sigmoid the blame crosses scales it by a(1−a)≤41, so by layer 1 the strongest possible signal is 4−9≈4×10−6 of what left the loss — and saturated neurons (a≈0.95, factor 0.045) make it far worse. The early layers barely learn. ReLU's slope of 1 where active is the fix.
Backwards or forwards? Backprop starts at one output (the loss) and finds the slope for every input in one sweep. There is a mirror image, forward mode: it starts at one input and finds the slope of every output. Training has one loss and millions of knobs, so every deep-learning library runs backwards.
Which sweep to run. A sweep costs about one pass either way; the question is what one sweep buys. Reverse mode starts at one output and prices every input — millions of weights for one loss. Forward mode starts at one input and prices every output. Training has one output and millions of inputs, so every framework runs reverse.
Forward mode you can do by hand — dual numbers. Carry every number as a pair: its value and its slope. Then teach ordinary arithmetic to update both at once. For f(x)=xex at x=1: start with the pair (1,1). Applying ex gives (e,e). Multiplying by x gives (e,2e). So f(1)=e and f′(1)=2e≈5.437, and nobody wrote down a slope formula.
If you want the algebra · arithmetic that differentiates itself
Prove it · arithmetic that differentiates itself
Claim. Write each pair (v,v˙) as v+v˙ε, where ε is a new symbol with one rule: ε2=0. Then ordinary algebra on these "dual numbers" performs exact differentiation.
1
Sums.(a+a˙ε)+(b+b˙ε)=(a+b)+(a˙+b˙)ε.
Values add, derivatives add — the sum rule, with no one enforcing it.
2
Products. Multiply out and apply the one rule:
(a+a˙ε)(b+b˙ε)=ab+(ab˙+a˙b)ε+a˙b˙ε2=ab+(ab˙+a˙b)εε2=0 killed the last term — it is the product of two tiny nudges, the very leftover that §4's promise says must die. What survives is exactly the product rule.
3
Any smooth function. Define g(a+a˙ε)=g(a)+g′(a)a˙ε — and this is forced, not chosen: Taylor gives g(a+t)=g(a)+g′(a)t+2g′′(a)t2+⋯, and with t=a˙ε every term from t2 onwards contains ε2 and vanishes.
The chain rule arrives baked in: whatever a˙ is carrying gets multiplied by the local slope g′(a).
4
Run the program on pairs, seeding the input as x=x0+1⋅ε (its derivative with respect to itself is 1). Example — f(x)=xex at x0=1:
x=(1,1)ex(e,e)×x(1⋅e,1⋅e+1⋅e)=(e,2e)
So f(1)=e and f′(1)=2e≈5.4366 — exact, and no derivative formula was ever written down. ∎Check: f′=ex(1+x) gives 2e. ✓ This is forward-mode autodiff: one sweep prices all outputs of one input — the mirror image of backprop, and the winner when inputs are few and outputs many.
Pause & predict
Dual numbers use a new symbol ε with one rule: ε2=0. That single rule makes the product rule appear by itself. What is ε2=0 really saying?
In one sentence: autodiff is exact like the paper method and cheap like one run of the program, which is why nudging survives only as a checker.
12
What to carry forward
Imagine this
In PyTorch, training a network needs one line: loss.backward(). It can feel like magic.
It isn't. It is everything in this unit, run by a simple loop.
One picture carried the whole unit: a function drawn as a graph of tiny steps, with values flowing right and blame flowing left. Everything else was careful bookkeeping on that picture.
Idea
The one-line version
Where it returns
Computation graph
Any function as tiny steps joined by arrows
every library's autograd
Backward pass
fˉ=1; multiply along paths, add at forks
every training step you'll ever run
δ (the blame)
Computed once at each step, reused by every knob feeding it
All of them, for about the price of one forward pass
why billion-knob training is possible
Linearization
f(x0)+∇f⊤(x−x0): the local "flat Earth"
Unit 8 · Taylor; Unit 9 · each descent step
The realization
Blame flows backwards through the same graph that computed the value. Multiply along paths, add at forks, and reuse every shared piece. Then a million slopes cost one sweep.
In one sentence:loss.backward() is this unit run by a for-loop — one backward sweep through the graph hands every knob its slope.
13
Practice arena — the unit's problem set, solved in full
Eleven problems. Three come from Part C of Prof. Saurabh's practice set (Parts A and B, on Taylor series and the Hessian, wait in Unit 8). Three come from his companion guide. Five are new: an identity drill (Problem 7), a full numeric backward pass (Problem 8), and three proof workouts (Problems 9–11). Every solution is machine-checked.
One habit does most of the work: draw the graph first, then walk it backwards. Multiply along paths, add at forks, and check every shape before trusting the algebra.
Problem 1medium
A one-layer network computes z=Wx and the loss g(z)=21∥z−t∥2 against a target t, with
W=10−1211,x=[11],t=102.(a) Compute ∇zg (with its dimension) and J=∂z/∂x (with its dimension). (b) Combine them to get ∇xg, and give the loss value.
What this tests. One honest backward step through a linear layer: the upstream gradient is the residual, and it returns to the input through W⊤.
Show the full solution
Step 1 — forward pass.z=Wx=(1+2,0+1,−1+1)⊤=(3,1,0)⊤. Residual r=z−t=(2,1,−2)⊤, and the loss is g=21(22+12+(−2)2)=29=4.5.
(a) Step 2 — gradient at the output. For g=21∥z−t∥2, ∇zg=z−t=r=(2,1,−2)⊤ — dimension 3×1, one entry per output. The Jacobian of a linear map is the matrix itself: J=∂(Wx)/∂x=W, dimension 3×2 (outputs × inputs).
(b) Step 3 — chain them.∇xg=J⊤∇zg=W⊤r=[1201−11]21−2=[1⋅2+0⋅1+(−1)(−2)2⋅2+1⋅1+1⋅(−2)]=[43]Dimension check:∇zg is 3×1, W⊤ is 2×3, product 2×1 — the shape of x, as a gradient must be. ✓
∇zg=(2,1,−2)⊤ (3×1), J=W (3×2), ∇xg=(4,3)⊤ (2×1), loss =4.5.
Remember
"Backprop through a linear layer" = "multiply the incoming gradient by W⊤". You can also check by substituting first: g(x)=21∥Wx−t∥2 has gradient W⊤(Wx−t)=W⊤r — same answer, one line.
Problem 2medium
A neuron computes z=wx+b,a=tanh(z), and the loss L=21(a−y)2. Using tanh′(z)=1−tanh2(z) and the values w=0.5,x=1,b=0,y=1: (a) do the forward pass (z,a,L); (b) backpropagate to obtain ∂L/∂w,∂L/∂b,∂L/∂x.
What this tests. The full forward–backward cycle on a single neuron, and the shared blame δ that Section 6 trains with.
δ is computed once and reused three times — the whole economy of backprop in miniature. Both parameter gradients are negative, so a descent step raises w and b, pushing a toward the target 1. Section 6's widget runs exactly these numbers.
Problem 3easy
A scalar function is built from two intermediates: f=uv, u=x2+y, v=x−y. (a) Write ∂f/∂u,∂f/∂v and the four partials of u,v with respect to x,y. (b) Using the chain rule, assemble ∂f/∂x and ∂f/∂y, and evaluate both at (x,y)=(1,1).
What this tests. Multiply along paths, add across paths — the two rules of Section 3, by hand.
Show the full solution
(a) The local derivatives. Outer: ∂f/∂u=v, ∂f/∂v=u. Inner: ∂u/∂x=2x, ∂u/∂y=1, ∂v/∂x=1, ∂v/∂y=−1.
(b) Step 1 — two paths from each input.∂x∂f=via u∂u∂f∂x∂u+via v∂v∂f∂x∂v=v(2x)+u(1)=2x(x−y)+(x2+y)∂y∂f=v(1)+u(−1)=(x−y)−(x2+y)
Step 2 — evaluate at (1,1) where u=2,v=0:
∂x∂f(1,1)=0⋅2+2⋅1=2,∂y∂f(1,1)=0⋅1+2⋅(−1)=−2
Step 3 — cross-check by expanding first.f=(x2+y)(x−y)=x3−x2y+xy−y2, so ∂f/∂x=3x2−2xy+y=3−2+1=2 ✓ and ∂f/∂y=−x2+x−2y=−1+1−2=−2 ✓.
∂f/∂x(1,1)=2, ∂f/∂y(1,1)=−2 — by paths and by expansion alike.
Problem 4hard
Define g(z,ν):=logp(x,z)−logq(z,ν) with z:=t(ϵ,ν), for differentiable functions p,q,t and x∈RD,z∈RE,ν∈RF,ϵ∈RG. Using the chain rule, compute the total derivative dνdg(z,ν).
What this tests. Direct and indirect paths of influence — the multivariate chain rule when a variable appears both explicitly and through an intermediate. (This is the gradient inside variational autoencoders.)
Show the full solution
Step 1 — draw the graph.ν reaches g two ways: directly (it sits inside logq(z,ν)) and indirectly (it builds z=t(ϵ,ν), and z feeds both logp and logq). Total derivative = sum over both routes.
Step 2 — the direct route. Hold z fixed and differentiate g in the ν-slot only. The logp term has no direct ν:
∂ν∂g=−∂ν∂logq(z,ν)(1×F)
Step 3 — the indirect route, two links. First how g feels z, then how z feels ν:
∂z∂g=∂z∂logp(x,z)−∂z∂logq(z,ν)(1×E),∂ν∂z=∂ν∂t(ϵ,ν)(E×F)
Step 4 — add the routes.dνdg=−∂ν∂logq+(∂z∂logp−∂z∂logq)∂ν∂tDimension check:(1×F)+(1×E)(E×F)=(1×F) ✓.
dνdg=−∂ν∂logq+(∂z∂logp−∂z∂logq)∂ν∂t.
Remember
Write d/dν (total) for "all routes", ∂/∂ν (partial) for "this slot only, everything else frozen". The whole problem is Section 3's fork rule wearing research-paper notation.
Problem 5medium
Compute dxdf for f(z)=log(1+z), z=x⊤x, x∈RD. State the dimension of every partial derivative involved.
What this tests. A two-step graph x→z→f where the middle is a scalar — plus the cookbook's dot-product identity applied to x⊤x.
Show the full solution
Step 1 — the outer link.dzdf=1+z1. Dimension 1×1.
Step 2 — the inner link.z=x⊤x=∑ixi2, so ∂z/∂xk=2xk, assembled as the row
∂x∂z=2x⊤(1×D)
(Or by the cookbook: x⊤Bx with B=I gives x⊤(I+I)=2x⊤.)
Step 3 — multiply the links.dxdf=dzdf∂x∂z=1+x⊤x2x⊤(1×1)(1×D)=(1×D)✓
Step 4 — sanity check with numbers. At x=(1,2)⊤: z=5, so the formula gives 62(1,2)=(31,32) — and differentiating log(1+x12+x22) directly gives (1+z2x1,1+z2x2)=(31,32) ✓.
dxdf=1+x⊤x2x⊤, a 1×D row.
Problem 6medium
Compute dxdf for f(z)=sin(z) applied entrywise, z=Ax+b, with A∈RE×D,x∈RD,b∈RE. State every dimension.
What this tests. The Jacobian chain rule with an entrywise nonlinearity — the exact structure of Section 7's layer, with sin in place of σ.
Show the full solution
Step 1 — the outer Jacobian.fi=sin(zi) touches only its own zi, so off-diagonal partials vanish and
∂z∂f=diag(cos(z1),…,cos(zE))=diag(cos(z))(E×E)
— the same diagonal shape as Section 7's diag(a⊙(1−a)), and for the same reason: entrywise functions have diagonal Jacobians.
Step 2 — the inner Jacobian.z=Ax+b is linear, so ∂z/∂x=A(E×D); the constant b contributes nothing.
Step 3 — multiply, order matters.dxdf=∂z∂f∂x∂z=diag(cos(Ax+b))A(E×E)(E×D)=(E×D)✓
Concretely: row i of A, scaled by cos(zi).
dxdf=diag(cos(Ax+b))A, an E×D Jacobian.
Problem 7medium
Verify two cookbook identities the honest way, entry by entry. (a) For B=[1324], expand x⊤Bx and confirm ∂(x⊤Bx)/∂x=x⊤(B+B⊤). (b) For a=(1,2)⊤,b=(3,1)⊤, expand a⊤Xb and confirm ∂(a⊤Xb)/∂X=ab⊤.
What this tests. That the identities are nothing but organised entry-wise differentiation — once verified by hand, you may use them forever with a clear conscience.
Show the full solution
(a) Step 1 — expand the scalar.x⊤Bx=x12+2x1x2+3x2x1+4x22=x12+5x1x2+4x22
Step 2 — differentiate like any polynomial.∂/∂x1=2x1+5x2, ∂/∂x2=5x1+8x2, so the gradient row is [2x1+5x2,5x1+8x2].
Step 3 — the identity's answer.B+B⊤=[2558], and x⊤(B+B⊤)=[2x1+5x2,5x1+8x2] — identical. ✓ (Note 2B would give [2x1+4x2,6x1+8x2] — wrong unless B is symmetric.)
(b) Step 1 — expand. With a=(1,2)⊤,b=(3,1)⊤:
a⊤Xb=i,j∑aiXijbj=3X11+X12+6X21+2X22
Step 2 — differentiate per entry.∂/∂Xij=aibj: the four coefficients 3,1,6,2 arranged in X's own shape are
∂X∂(a⊤Xb)=[3612]=ab⊤✓
Both identities check entry by entry — and (b) is exactly why Section 7's ∂Loss/∂A came out as the outer product δ(Z)x⊤.
Problem 8hard
Run the full backward pass on the lecture's function f(x)=x2+ex2+cos(x2+ex2) at x=1, using the graph a=x2,b=ea,c=a+b,d=c,e=cosc,f=d+e. (a) Forward pass: all six values to 4 decimals. (b) Backward pass: all the blames fˉ,dˉ,eˉ,cˉ,bˉ,aˉ,xˉ. (c) Confirm xˉ against the closed-form derivative.
What this tests. The complete algorithm of Sections 2–5, executed by hand with real numbers — including the fork at c and the fork at a.
Show the full solution
(a) Forward, left to right.a=12=1,b=e1=2.7183,c=1+2.7183=3.7183d=3.7183=1.9283,e=cos(3.7183)=−0.8383,f=1.9283−0.8383=1.0900
(Radians throughout — c is just a number, and cos of it lives on the unit circle, not a protractor.)
(b) Backward, right to left. Start fˉ=1. Node f=d+e mails both parents a copy scaled by 1: dˉ=1,eˉ=1.
The fork at c.c feeds d=c and e=cosc, so its mail arrives in two pieces that add:
cˉ=dˉ⋅2c1+eˉ⋅(−sinc)=2(1.9283)1+(−sin(3.7183))=0.2593+0.5452=0.8045
(sin(3.7183)=−0.5452 — third quadrant, so the minus signs stack to a plus.)
Through b, and the fork at a.bˉ=cˉ⋅1=0.8045. Then a feeds b=ea and c=a+b:
aˉ=bˉ⋅ea+cˉ⋅1=0.8045⋅2.7183+0.8045=2.1870+0.8045=2.9915
The last edge.xˉ=aˉ⋅2x=2.9915⋅2=5.9831.
(c) The closed form agrees.dxdf=(2x2+ex21−sin(x2+ex2))(2x+2xex2)x=1=0.8045×7.4366=5.9831✓
Notice the factor 0.8045iscˉ, and 2x+2xex2=7.4366 is what the graph assembled as aˉ⋅2x/cˉ — the closed form and the graph are the same computation, differently organised.
Run the same pass at x=2 and ex2=e4=54.6 dominates everything: cˉ=−0.8223 and df/dx=−182.87. The companion doc's printed run at x=2 uses cos(58.6)≈0.83, but the true value in radians is −0.46 — a calculator slip that flips the final answer completely (see the errata note in §2). The habit that catches such slips: always confirm a hand-computed derivative with a small numerical nudge.
Problem 9medium
The activation family, from first principles. (a) Show that the softpluss(z)=ln(1+ez) has derivative s′(z)=σ(z) — the sigmoid is softplus's slope. (b) Prove the bridge tanh(z)=2σ(2z)−1. (c) Using (b) and σ′=σ(1−σ), derive tanh′=1−tanh2without a quotient rule.
What this tests. That the activation identities frameworks hard-code are a small connected family — one proof engine (find the appearances, chain the slopes) generates them all.
Show the full solution
(a) Chain rule through the logarithm. Outer slope 1/(1+ez), inner slope ez:
s′(z)=1+ezez=e−z+11=σ(z)✓
(dividing top and bottom by ez in the middle step). So the smooth ramp softplus steepens exactly at the sigmoid's rate — which is why σ is also called the logistic function.
(b) Build 2σ(2z)−1 and simplify.2σ(2z)−1=1+e−2z2−1=1+e−2z2−(1+e−2z)=1+e−2z1−e−2z
Multiply top and bottom by ez:
ez+e−zez−e−z=tanh(z)✓
In words: tanh is a sigmoid, stretched to run twice as fast and re-centred to fill (−1,1).
(c) Differentiate the bridge with Rule 1. Write t=tanhz and note from (b) that σ(2z)=21+t, hence 1−σ(2z)=21−t. Then
tanh′(z)=2⋅σ′(2z)⋅2=4σ(2z)(1−σ(2z))=4⋅21+t⋅21−t=(1+t)(1−t)=1−t2✓
— the factor 2 outside is the bridge's scaling, the factor 2 inside is the chain rule through 2z.
s′=σ; tanhz=2σ(2z)−1; tanh′=1−tanh2, derived purely from σ′=σ(1−σ).
Remember
All three facts are one family portrait: softplus's slope is σ, tanh is a rescaled σ, and both backward-pass identities (σ(1−σ) and 1−a2) are the same identity seen through the bridge. Knowing one buys you the others.
Problem 10hard
The cookbook earns its keep: ridge regression solved by pure algebra. Consider the regularised least-squares loss
E(s)=∥x−As∥2+λ∥s∥2(a) Using the cookbook identities, derive ∇sE. (b) Set it to zero and show the minimiser solves (A⊤A+λI)s=A⊤x. (c) Solve numerically for
A=120013,x=120,λ=1.
What this tests. That the identities you proved are tools, not trivia: two of them combine into the closed-form solution of ridge regression — the first machine-learning model this course can now train end-to-end by algebra alone.
Show the full solution
(a) Differentiate each piece with the cookbook. The first piece is the least-squares identity with W=I:
∂s∂∥x−As∥2=−2(x−As)⊤A
The second is the quadratic identity with B=I (so B+B⊤=2I):
∂s∂λs⊤s=2λs⊤
Sum: ∇sE=−2(x−As)⊤A+2λs⊤.
(b) Set the gradient to zero (and transpose the row into a column to read it as an equation in s):
−2A⊤(x−As)+2λs=0⟹A⊤As+λs=A⊤x⟹(A⊤A+λI)s=A⊤x✓
This is a stationary point, and it is the minimum: E is a sum of squares whose quadratic part s⊤(A⊤A+λI)s is positive for every s=0 once λ>0 — the bowl opens upward in every direction, and adding λI even guarantees the system is invertible when A⊤A alone is not (Unit 5's nearly-singular warning, answered).
(c) Numbers.A⊤A=[1+4+00+2+00+2+00+1+9]=[52210],A⊤A+I=[62211],A⊤x=[1+4+00+2+0]=[52]
Solve [62211]s=[52]: determinant 66−4=62, so by Cramer (or elimination)
s1=625⋅11−2⋅2=6251≈0.8226,s2=626⋅2−2⋅5=622=311≈0.0323
Gradient → zero → linear system: for quadratic losses, "training" is one solve. Unit 9 begins exactly where this stops — with losses whose gradients cannot be set to zero in closed form, so we must walk downhill instead.
Problem 11medium
Differentiate a program with dual numbers (Section 11), seeding x=x0+1⋅ε. (a)f(x)=x2ex at x0=1. (b)f(x)=x2+9 at x0=−4 — then compare with Section 10's stand-in line. (c) In one sentence: why are these results exact, where the gradient checker's finite differences never are?
What this tests. Forward-mode autodiff executed by hand: the ε2=0 algebra runs the chain rule mechanically — you only ever do arithmetic on pairs.
Show the full solution
(a) Run the pairs. Seed x=(1,1).
x2=(1⋅1,1⋅1+1⋅1)=(1,2)ex=(e,e⋅1)=(e,e)x2⋅ex=(1⋅e,1⋅e+2⋅e)=(e,3e)
So f(1)=e≈2.7183 and f′(1)=3e≈8.1548. Check against the formula the program never used: f′=(2x+x2)ex1=3e ✓.
(b) A chain with a square root. Seed x=(−4,1).
x2=((−4)2,2⋅(−4)⋅1)=(16,−8)x2+9=(25,−8)⋅:(25,225−8)=(5,−0.8)
So f(−4)=5 and f′(−4)=−0.8=−54 — precisely the anchor value and slope of Section 10's stand-in line. The widget's tangent line and this pencil-and-paper pair computation are the same mathematics arriving by two roads.
(c) Why exact. No step ever subtracts two nearly equal numbers or divides by a small h — each rule (sum, product, g′(a)a˙) is the corresponding calculus rule, applied with ordinary arithmetic — so the only error anywhere is standard floating-point rounding of the values themselves.
(a) (e,3e): f′(1)=3e≈8.1548. (b) (5,−0.8): f′(−4)=−54. (c) The algebra rules are the calculus rules — nothing is approximated, so nothing needs a step size.
Remember
Reverse mode (this unit's hero) and dual numbers (its mirror) bracket the field: backward for one output and many inputs, forward for one input and many outputs. Both differentiate the program, both are exact — and neither ever writes a derivative formula.
Linearization kept one derivative and got a line. Unit 8 keeps them all — and proves, from a single flat spot on a hiking trail, exactly how far each cut of the series can be trusted. Then it takes the second-order term into two variables, where it becomes the Hessian: the judge that tells a bowl from a dome from a saddle at the bottom of every loss valley.