Unit 6 ended with a promise: the chain rule becomes matrix multiplication, and that is backpropagation. This unit keeps the promise. You will watch a value flow forward through a graph and its error flow backward; train a single neuron with your own hands and see the loss actually drop; then do a whole layer at once, in matrix form — the exact four formulas inside every deep-learning framework. One backward sweep, and every knob in the network knows which way to turn. And nothing here is taken on faith: every rule the unit leans on is proved on the page, step by step, in plain language.
≈ 80 min read + play7 interactive widgets · 3 in 3D · train a neuron live16 inline checks🧾 13 proofs, step by step — chain rule, layer formulas, cookbook, checker✍ 11 solved practice problems
drag the graph to orbit
1
The million-knob problem
Imagine this
You are playing darts. Your first throw misses. Your brain notes how far off you were and in which direction — that is the error — and quietly adjusts your stance, grip, and force for the next throw. You learn from the miss. A neural network learns the same way: it makes a prediction (the throw), a loss function measures the miss (the error), and then every parameter gets adjusted to shrink that miss. The question this unit answers: with a million knobs, how does each one find out its own share of the blame — and how can that possibly be cheap?
From Unit 6 you already know what each knob needs: the partial derivative of the loss with respect to that knob. Gradient descent does the rest. So the whole problem is computing a million derivatives, fast.
Try the honest way first, on one small function from the lecture:
f(x)=x2+ex2+cos(x2+ex2)
Differentiating by hand, the chain rule sprays copies of 2x+2xex2 everywhere:
dxdf=2x2+ex22x+2xex2−sin(x2+ex2)(2x+2xex2)
One input, and the expression is already a mouthful — long to write, slow to evaluate, easy to get wrong. Now scale the ambition: a modern network has billions of parameters, and we need the derivative with respect to every one of them, at every training step. Writing formulas by hand is not just impractical — it is impossible.
Backpropagation is the way out, and its two ideas fit in one breath: break the function into baby steps, and send the error backwards through them. Everything else in this unit is those two ideas, carefully.
Pause & predict
A network has a million parameters. Estimating each gradient separately by nudging one parameter and re-running the network would cost about how much?
In one sentence: Training needs the derivative of the loss with respect to every knob, every step — and computing them one at a time would cost a forward pass per knob.
2
Baby steps — the computation graph
Here is the monster function again — but this time we refuse to differentiate it. Instead we just compute it, one baby step at a time, giving each intermediate result a name:
a=x2,b=ea,c=a+b,d=c,e=cos(c),f=d+e
Each step is trivial — a square, an exponential, an addition. Drawn with arrows showing who feeds whom, this is a computation graph, and it is the single most important picture in modern machine learning. Push a number through it, then watch the error walk home:
The graph machineforward: values flow right · backward: blame flows left — press both
Try: press ▶ forward, then use step once to walk the blame back one node at a time — and pause at c, where two pieces of blame add.
drag the graph to orbit it
—
Forward, every node computes one baby step and remembers its value. Backward, every node receives its blamevˉ=∂f/∂v — starting from fˉ=1 — and passes blame to its parents by multiplying with a local derivative. Watch node c: it feeds two children, so its blame arrives in two pieces that add. At the far left, xˉ is the answer df/dx — and the chip checks it against a numerical nudge.
Errata — check this against your companion doc
The companion's worked run of this graph at x=2 reports e=cos(58.6)≈0.83 and ends with df/dx≈−2.224. But 58.6 here is 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 method in the companion is exactly right; only the arithmetic slipped. Every number on this page is machine-verified.
Pause & predict
In the graph, node a=x2 feeds bothb=ea and c=a+b. When blame flows backward, what does a receive?
In one sentence: Rewrite any function as baby steps in a graph; then the forward pass computes values, and the backward pass hands every node its blame vˉ=∂f/∂v.
3
The whole algorithm is two rules
In plain words
Rule 1 — along a path, multiply. Each edge of the graph has a local derivative (how much the child moves per unit of parent). Following a path from x to f, the sensitivities multiply — Unit 6's amplifiers in series.
Rule 2 — where paths merge, add. If x can reach f by several routes, each route contributes its product, and the contributions add. That is all backpropagation is: multiply along paths, add across paths — organised so no path is ever walked twice.
See both rules in the smallest graph that has two paths — the practice set's own example: f=uv with u=x2+y and v=x−y. The input x reaches f through u and through v; click each path and watch its product, then their sum:
Paths multiply, forks addf = uv, u = x² + y, v = x − y — two routes from x to f
Try: click route via u, then route via v, then both — and slide x to 0 to see one whole route switch off.
—
At (1,1): via u: v⋅2x=0⋅2=0; via v: u⋅1=2. Sum: ∂f/∂x=2 — which matches expanding f=x3−x2y+xy−y2 and differentiating directly. Two tiny products beat one messy expansion, and the gap only grows with depth.
Pause & predict
Still at (x,y)=(1,1): what is ∂f/∂y? (Routes: y→u→f with ∂u/∂y=1, and y→v→f with ∂v/∂y=−1.)
In one sentence: Backpropagation is exactly two rules — multiply local derivatives along each path, add the paths — applied without ever walking a path twice.
4
Why you can trust the rules — the chain rule, proved
"Multiply along paths, add across paths" has been doing a lot of work, so it had better be true — a theorem, not a slogan. The proof needs exactly one idea, and it is the idea this course keeps returning to: a derivative is a promise about a straight line. Saying "g has slope g′(x0) at x0" means precisely this:
g(x0+h)=g(x0)+g′(x0)h+r(h),where hr(h)→0 as h→0.
In words: near x0 the function is a straight line plus a leftover r(h) so small that even after dividing by the tiny number h, it still shrinks to nothing. That last clause is the entire content of differentiability. Hold on to it — both rules fall out of it in a few lines each.
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".
Pause & predict
The promise demands r(h)/h→0, not merely r(h)→0. What would go wrong if we only asked for r(h)→0?
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 reaches the output through several intermediates at once — f is a function of u1,…,um, and each uk is a function of x. This is precisely the fork situation 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. For vector maps xFuGy, the chain rule reads JG∘F=JGJF — Jacobians multiply. Now look at one entry of that product, using the row-times-column rule:
(JGJF)ij=k∑(JG)ik(JF)kj
Each term is one path: input j nudges intermediate k (that is (JF)kj), which nudges output i (that is (JG)ik) — multiply along the path. The ∑k adds one product per intermediate stop — add across paths. The row-times-column rule you have used since Unit 1 is literally the two rules of backpropagation, written at once. Unit 6 promised "the chain rule becomes matrix multiplication"; you have now watched the promise come true, entry by entry.
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.
Pause & predict
In (JGJF)ij=∑k(JG)ik(JF)kj, what is one single term (JG)ik(JF)kj of the sum, in graph language?
In one sentence: A derivative is a "line plus dying leftover" promise; composing promises multiplies slopes (Rule 1), parallel routes add their products (Rule 2), and matrix multiplication's row-times-column formula is both rules written at once.
5
The recipe, written once and for all
The lecture states the two rules formally, and it is worth reading slowly because this half-line is automatic differentiation. Number every quantity in the graph: x1,…,xd are the inputs, xd+1,…,xD−1 the intermediate baby steps, xD the output. Each is computed from its parents by an elementary function:
xi=gi(xPa(xi))
Now walk backwards. The output blames itself fully, and every other node collects blame from the nodes it feeds — its children:
∂xD∂f=1,∂xi∂f=j:xi∈Pa(xj)∑∂xj∂f∂xi∂gj
Read it like a postal system: node j already knows its own blame ∂f/∂xj. It mails each parent i a copy, scaled by the local derivative∂gj/∂xi of its own baby step. A parent with several children just adds up its mail. One sweep from right to left and every node in the graph — every input, every weight — holds its derivative.
Two things make this cheap. Each blame ∂f/∂xj is computed once and reused by all of j's parents. And each local derivative ∂gj/∂xi is trivial, because each baby step is trivial — the derivative of ea or c or a+b, never of the whole monster. This is why the lecture can conclude: computing all the derivatives costs about the same as computing the function itself.
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.
Pause & predict
In the recipe, the sum for ∂f/∂xi runs over the children of xi — the nodes that use it. Why children, not parents?
In one sentence: Set fˉ=1, then let every node mail each parent its own blame times a local derivative — one right-to-left sweep prices every knob.
6
One neuron, trained by your own hands
Time to point this machinery at something that learns. The smallest possible network: one neuron with one weight w and one bias b, one input x, one target y:
z=wx+b,a=tanh(z),L=21(a−y)2
Forward: three baby steps to the loss. Backward: the blame walks home through the same three steps. The key arrival is δ=∂L/∂z — the blame reaching the pre-activation — because every parameter feeding z then reads its gradient straight off δ: ∂L/∂w=δx, ∂L/∂b=δ, ∂L/∂x=δw. Compute δ once, hand out copies. Then take an actual gradient step and watch the loss fall:
The learning neuronforward → backward → step, repeat — this is training, complete
Try: predict the sign of δ before each step; then set the target to y=−1 and watch the same machinery push w the other way.
drag the landscape to orbit it
—
Starting point is the practice set's own numbers: w=0.5,b=0,x=1,y=1, so z=0.5, a=tanh0.5=0.4621, L=0.1447, and the backward pass gives δ=(a−y)(1−a2)=−0.4230, hence ∂L/∂w=−0.4230, ∂L/∂b=−0.4230. Both gradients are negative — the loss wants w and bbigger. Press the step button and watch it happen; press train and watch the loss meter dive.
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.
Pause & predict
At the starting numbers, ∂L/∂w and ∂L/∂b are both exactly δ⋅x and δ⋅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 gradient step now push w?
In one sentence: Compute the blame δ=∂L/∂z once, and every parameter feeding z reads its gradient off it — then step downhill and the loss actually falls.
7
A whole layer at once — backprop in matrix form
A real layer is the same neuron, vectorised: m neurons share the input vector x∈Rn,
Z=Ax+b,a=σ(Z)
with A∈Rm×n the weights, b∈Rm the biases, and the sigmoid σ(z)=1+e−z1 applied entry by entry. The blame arriving from above is δ(a)=∂Loss/∂a, one entry per neuron.
Read the answer as people first, then as symbols. Passing blame back through the layer gives four lines. Through the sigmoid: each neuron's blame is scaled by its own slope — no mixing between neurons. A weight: gets the blame of its neuron times the activity of its input — big only when both are big. A bias: gets its neuron's blame straight. The input: gets blame collected back through the weights, and that becomes the mail for the layer below.
Now the symbols. Step one, through the sigmoid: ai=σ(Zi) touches only its own Zi, so the Jacobian ∂a/∂Z is diagonal — diag(a⊙(1−a)), using σ′=σ(1−σ) — and the blame is scaled entrywise (⊙ is the Hadamard, entrywise, product):
δ(Z)=δ(a)⊙a⊙(1−a)
Step two, through Z=Ax+b. Since Zi=∑jAijxj+bi, each weight sees ∂Zi/∂Aij=xj, and the chain rule assembles into three matrix formulas:
∂A∂Loss=δ(Z)x⊤,∂b∂Loss=δ(Z),∂x∂Loss=A⊤δ(Z)
The weights:δ(Z)x⊤ is an outer product — blame of my row, times activity of my column. The biases: the blame itself. The input:A⊤δ(Z) re-mixes the blame back through the transposed weights — and this vector is precisely the δ(a) the previous layer receives as its mail. Layer after layer, the same four lines: that is deep learning's inner loop.
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.
Backprop through a layerthe four formulas with real numbers — step through them
Try: reach stage 4, then slide δ1(a) — the top row of the outer product and the mail A⊤δ(Z) react; row 2 does not.
—
The layer is 2×2 so every number fits on screen: A=1−120, b=(0,1), x=(1,0.5), and the loss above sends down δ(a)=(0.6,−0.4). Watch stage 4: ∂L/∂A is literally the outer-product grid of δ(Z) against x — and A⊤δ(Z) leaves the widget as the mail for the layer below.
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.
Pause & predict
A layer has A∈R100×300. What is the shape of ∂Loss/∂A=δ(Z)x⊤, and why was that inevitable?
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.
Pause & predict
Why does the blame leave through A⊤ — the transpose — rather than through A itself?
In one sentence:δ(Z)=δ(a)⊙a⊙(1−a), then weights get δ(Z)x⊤, biases get δ(Z), and the layer below gets A⊤δ(Z) — four lines, all of deep learning's inner loop.
8
The gradient cookbook — five identities you'll use forever
Backprop needs local derivatives, and in matrix land a handful of them cover almost everything. The lecture lists five; learn them as sentences, not just symbols. (Gradients here are rows, Unit 6's convention.)
Identity
Say it in words
∂x∂x⊤a=a⊤
a dot product's sensitivity to x is just the other vector
∂x∂a⊤x=a⊤
same thing — a dot product doesn't care about the order
∂X∂a⊤Xb=ab⊤
each entry Xij is multiplied by aibj — so the gradient is that outer product
∂x∂x⊤Bx=x⊤(B+B⊤)
x appears twice, so you get two copies — B once from each side
∂s∂(x−As)⊤W(x−As)=−2(x−As)⊤WA
for symmetric W: least-squares' own gradient — chain rule through the residual
Notice the family resemblance to Section 7: the third identity is why ∂Loss/∂A came out as an outer product, and the last one is the loss ∥y−As∥2 that trains linear models — you will meet it again the moment optimisation starts in Unit 9. Below, every identity is derived in full — the whole cookbook takes four short arguments. The arena's Problem 7 re-checks two of them with concrete numbers, and Problem 10 puts the cookbook to work on a real model.
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. ∎
Pause & predict
With B=1234 (not symmetric), what is ∂x∂x⊤Bx at x=(x1,x2)?
Pause & predict
In the least-squares gradient −2(x−As)⊤WA, where exactly did the factor 2 come from?
In one sentence: Five identities — dot product, outer product, the B+B⊤ doubling, and least squares — supply nearly every local derivative a real model needs.
9
Why it's so cheap — one sweep, everything reused
Stack K layers, fi=σi(Ai−1fi−1+bi−1), and put a loss at the end: L=∥y−fK∥2. Every layer's parameters θi={Ai,bi} need a gradient, and the chain rule writes each one as a product that reaches from the loss back to that layer:
Look at the shape of those formulas: each one is the previous one's product, extended by one factor. Computed naively, left to right every time, you would rebuild the same long prefix over and over. Computed once from the loss end — keeping the running product as the δ that Section 7 handed backwards — every factor in the whole triangle is touched exactly once:
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.
The reuse triangleevery gradient shares its prefix with the next — slide the depth
Try: read one row left to right — it is the stacked formula above with real indices; then slide K to 8 and count grey versus blue.
—
Grey blocks: factors a naive left-to-right evaluation would recompute. Blue: the factors backprop actually computes — each row just extends the running blame δ by one new factor. Naive cost grows like K2/2; backprop stays at K. At depth 100 that is a 50× saving on top of the million-× saving over per-knob nudging.
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.
Pause & predict
Rule of thumb: one full backward pass costs about as much as the forward pass itself. What single fact makes that possible?
In one sentence: All the gradient formulas share their long prefix — carry it once, from the loss end, and the whole triangle of factors costs one sweep.
10
Linearization — the gradient as a stand-in for the function
The companion closes with the other reason gradients matter. Once you own ∇f(x0), you own the best linear stand-in for f near x0:
L(x)≈f(x0)+∇f(x0)⊤(x−x0)
This is Unit 6's tangent line in vector form — the first two terms of the Taylor series (derived below). It is accurate near x0, drifts as you leave, and it is the reason gradient descent works at all: each step trusts the linear stand-in for one small hop. Try the companion's own example — f(x)=x2+9 around x0=−4, where f(−4)=5 and f′(−4)=−54:
The stand-in linedrag the anchor, drag the probe — watch the honest error of the linear guess
Try: put the probe at twice the distance from the anchor and check that the error roughly quadruples.
✋ drag near the dot to move the anchor · elsewhere to move the probe
—
At anchor −4: L(x)=5−54(x+4), the companion's answer. Slide the probe to −3.5 and the stand-in guesses 4.6 against a true 4.61 — near the anchor the line is almost the function. Push the probe far away and watch the error column grow: a linearization is a local promise, exactly like Unit 6's Taylor windows.
…and in two variables: the stand-in planef(x, y) = eˣ cos y — the companion's second example, with its tangent plane at the anchor
drag the surface to orbit it
At the origin the gradient is (1,0), so the plane is L(x,y)=1+x — tilted along x, flat along y, exactly the check below. Drag the anchor away from the origin and the plane re-tilts to whatever the gradient says there. Shrink the probe radius and the red gap collapses like the radius squared.
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. ∎
Pause & predict
The companion also linearizes f(x,y)=excosy at (0,0): value 1, gradient (1,0). What is the stand-in plane?
In one sentence:f(x0)+∇f(x0)⊤(x−x0) is the best linear stand-in near x0 — the first two Taylor terms, and the promise each gradient-descent step relies on.
11
Fine print worth knowing
Three ways to differentiate, only one scales.Symbolic differentiation (what you do on paper, what algebra systems do) produces exact formulas — which explode in size for deep compositions. Numerical differentiation nudges the input and divides — one pass per parameter, plus a precision trap you can see below. Automatic differentiation — this unit — is a third thing: exact like symbolic, cheap like a function call, because it differentiates the program, step by step, instead of the formula.
The precision trap. A finite difference 2hf(x+h)−f(x−h) has two enemies. Big h: the secant misses the tangent (Unit 6's curvature gap). Tiny h: the computer subtracts two nearly equal numbers and the difference drowns in rounding error. Squeeze h yourself:
The gradient checkerfinite differences vs. the exact answer — there is a best h, and it is not 0
Try: slide h down one decade at a time and watch the error fall 100× per decade — until, near 10−6, it stops and turns.
—
The function is the monster from §1, at x=1, where autodiff says df/dx=5.98308 exactly. Slide h down the valley: the error falls like h2 (curvature fading), bottoms out near h≈10−6 for this f (nearer 10−5 for a tamer one), then rises again as rounding noise takes over. Frameworks still use this as a gradient checker — a sanity test for hand-written backward passes — but never for training.
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.
σ′ is free. The identity σ′=σ(1−σ) means the backward pass needs no new function calls — the forward pass already computed a, and a⊙(1−a) is two cheap operations. The same trick works for tanh (1−a2). Frameworks cache activations on the way forward precisely so the way back is arithmetic only — that cache is the "memory cost of training".
Vanishing gradients, revisited. Each sigmoid layer multiplies the blame by a⊙(1−a)≤41. Fifty layers deep, the blame arriving at layer one has passed fifty such factors — Unit 6's gears compounding — which is why early deep networks would not train, and why ReLU (slope 1 where active) took over.
Reverse is for losses; forward exists too. Everything here swept blame backwards, which prices all inputs of one output — perfect for a scalar loss. There is a mirror-image forward mode that prices all outputs of one input; it wins only when outputs vastly outnumber inputs, which training never is. That is why every deep-learning framework is a reverse-mode machine.
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.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.
Pause & predict
In the gradient checker, why does making h ever smaller eventually make the estimate worse?
Forward mode you can hold in your hand — dual numbers. Reverse mode swept blame backwards. Forward mode has an algebraic form so tidy you can run it with pencil and paper: carry every quantity as a pair — its value and its derivative — and teach ordinary arithmetic to update both at once.
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
The single rule ε2=0 makes the product rule appear on its own. What is ε2=0 really encoding?
In one sentence: Autodiff is exact like symbolic and cheap like numerical with neither one's flaw — and the finite-difference valley is why "just use tiny h" was never an option.
12
What to carry forward
One picture generated this entire unit: a function drawn as a graph of baby 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 baby steps with arrows
every framework's autograd tape
Backward pass
fˉ=1; multiply along paths, add at forks
every training step you'll ever run
δ (the blame)
Computed once at each node, reused by every parameter feeding it
Blame flows backwards through the same graph that computed the value. Multiply along paths, add at forks, reuse every partial product — and a million derivatives cost one sweep. When a framework call like loss.backward() feels like magic, it is exactly this unit, executed by a for-loop.
13
Practice arena — the unit's problem set, solved in full
Eleven problems: three from Part C of Prof. Saurabh's practice set (Parts A and B — Taylor series and the Hessian — belong to Unit 8's territory and wait there), three from his companion guide, and five written for this arena — the identity drill (Problem 7), the complete numeric backward pass (Problem 8), and three proof workouts (Problems 9–11) that derive from scratch the rules this unit leaned on. Every solution below is machine-verified.
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 any 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.