The Math Behind the Machine/ Unit 7 · Backprop & Auto-diff Checks 0/16
Unit 7 of 16 · by Prof. Saurabh

Backpropagation & Automatic Differentiation

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 + play 7 interactive widgets · 3 in 3D · train a neuron live 16 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)f(x)=\sqrt{x^2+e^{x^2}}+\cos\!\big(x^2+e^{x^2}\big)

Differentiating by hand, the chain rule sprays copies of 2x+2xex22x+2xe^{x^2} everywhere:

dfdx=2x+2xex22x2+ex2sin ⁣(x2+ex2)(2x+2xex2)\begin{aligned}\frac{df}{dx}&=\frac{2x+2xe^{x^2}}{2\sqrt{x^2+e^{x^2}}}\\[.3em]&\quad-\sin\!\big(x^2+e^{x^2}\big)\big(2x+2xe^{x^2}\big)\end{aligned}

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+ea=x^2,\quad b=e^{a},\quad c=a+b,\quad d=\sqrt{c},\quad e=\cos(c),\quad 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 cc, where two pieces of blame add.

drag the graph to orbit it

1

Forward, every node computes one baby step and remembers its value. Backward, every node receives its blame vˉ=f/v\bar v = \partial f/\partial v — starting from fˉ=1\bar f = 1 — and passes blame to its parents by multiplying with a local derivative. Watch node cc: it feeds two children, so its blame arrives in two pieces that add. At the far left, xˉ\bar x is the answer df/dxdf/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=2x=2 reports e=cos(58.6)0.83e=\cos(58.6)\approx 0.83 and ends with df/dx2.224df/dx\approx-2.224. But 58.658.6 here is in radians: cos(58.6)0.46\cos(58.6)\approx-0.46 and sin(58.6)0.89\sin(58.6)\approx 0.89, so cˉ=12csin(c)0.0650.888=0.822\bar c=\tfrac{1}{2\sqrt c}-\sin(c)\approx 0.065-0.888=-0.822 (not 0.01-0.01), and the true answer is df/dxx=2182.87df/dx\big|_{x=2}\approx\mathbf{-182.87} — the ex2e^{x^2} 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=x2a=x^2 feeds both b=eab=e^a and c=a+bc=a+b. When blame flows backward, what does aa 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\bar v=\partial f/\partial 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 xx to ff, the sensitivities multiply — Unit 6's amplifiers in series. Rule 2 — where paths merge, add. If xx can reach ff 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=uvf=uv with u=x2+yu=x^2+y and v=xyv=x-y. The input xx reaches ff through uu and through vv; 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 xx to 00 to see one whole route switch off.

1
1

At (1,1)(1,1): via uu:   v2x=02=0\;v\cdot 2x = 0\cdot 2 = 0; via vv:   u1=2\;u\cdot 1 = 2. Sum: f/x=2\partial f/\partial x = 2 — which matches expanding f=x3x2y+xyy2f=x^3-x^2y+xy-y^2 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)(x,y)=(1,1): what is f/y\partial f/\partial y? (Routes: yufy\to u\to f with u/y=1\partial u/\partial y=1, and yvfy\to v\to f with v/y=1\partial v/\partial 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 "gg has slope g(x0)g'(x_0) at x0x_0" means precisely this:

g(x0+h)=g(x0)+g(x0)h+r(h),where  r(h)h0  as h0.g(x_0+h)=g(x_0)+g'(x_0)\,h+r(h),\qquad\text{where }\ \frac{r(h)}{h}\to 0\ \text{ as }h\to 0.

In words: near x0x_0 the function is a straight line plus a leftover r(h)r(h) so small that even after dividing by the tiny number hh, 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.

Pause & predict

The promise demands r(h)/h0r(h)/h\to0, not merely r(h)0r(h)\to0. What would go wrong if we only asked for r(h)0r(h)\to0?

Prove it · Rule 1 — along a path, multiply

Claim. If u=g(x)u=g(x) and y=f(u)y=f(u), then at x0x_0 (writing u0=g(x0)u_0=g(x_0)):  dydx=f(u0)g(x0)\ \dfrac{dy}{dx}=f'(u_0)\,g'(x_0) — the two slopes multiply.

1
Nudge the input by hh and ask how much uu moves. That is gg's own promise: Δu  =  g(x0+h)g(x0)  =  g(x0)h+rg(h)\Delta u \;=\; g(x_0+h)-g(x_0)\;=\;g'(x_0)\,h+r_g(h) Line plus leftover, with rg(h)/h0r_g(h)/h\to0. Nothing new — just the definition, applied to gg.
2
Feed that movement to ff. That is ff's promise, written at u0u_0 with nudge Δu\Delta u: f(u0+Δu)  =  f(u0)+f(u0)Δu+rf(Δu)f(u_0+\Delta u)\;=\;f(u_0)+f'(u_0)\,\Delta u+r_f(\Delta u) Same definition, applied to ff. Note the nudge ff receives is Δu\Delta u, not hh.
3
Substitute step 1 into step 2 and multiply out: f(g(x0+h))=f(u0)+f(u0)g(x0)the clean slopeh  +  f(u0)rg(h)+rf(Δu)call it R(h)f\big(g(x_0+h)\big)=f(u_0)+\underbrace{f'(u_0)\,g'(x_0)}_{\text{the clean slope}}\,h\;+\;\underbrace{f'(u_0)\,r_g(h)+r_f(\Delta u)}_{\text{call it }R(h)} One term proportional to hh, and everything else swept into a single bracket R(h)R(h).
4
Check that R(h)R(h) is a legal leftover — that R(h)/h0R(h)/h\to0. Piece by piece: f(u0)rg(h)hf(u0)0=0,rf(Δu)h=rf(Δu)ΔuΔuh0g(x0)=0\frac{f'(u_0)\,r_g(h)}{h}\to f'(u_0)\cdot 0=0,\qquad \frac{r_f(\Delta u)}{h}=\frac{r_f(\Delta u)}{\Delta u}\cdot\frac{\Delta u}{h}\to 0\cdot g'(x_0)=0 The first piece is a constant times something dying. The second: Δu/hg(x0)\Delta u/h\to g'(x_0) by step 1, while rf(Δu)/Δu0r_f(\Delta u)/\Delta u\to0 because Δu0\Delta u\to0. (Fine point: if Δu\Delta u happens to be exactly 00, then rf(Δu)=rf(0)=0r_f(\Delta u)=r_f(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),R(h)h0f\big(g(x_0+h)\big)=f\big(g(x_0)\big)+\big[f'(u_0)\,g'(x_0)\big]\,h+R(h),\qquad \frac{R(h)}{h}\to0 — 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 ff reaches the output through several intermediates at once — ff is a function of u1,,umu_1,\dots,u_m, and each uku_k is a function of xx. This is precisely the fork situation in the graph: one input, many routes.

Prove it · Rule 2 — across paths, add

Claim.  dfdx=k=1mfukdukdx\ \dfrac{df}{dx}=\displaystyle\sum_{k=1}^{m}\frac{\partial f}{\partial u_k}\,\frac{du_k}{dx} — 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)+kfukΔuk+r,rΔu0f(u_1+\Delta u_1,\dots,u_m+\Delta u_m)=f(\mathbf u)+\sum_{k}\frac{\partial f}{\partial u_k}\,\Delta u_k+r,\qquad \frac{r}{\|\Delta \mathbf u\|}\to0 A 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=dukdxh+rk(h),rk(h)h0\Delta u_k=\frac{du_k}{dx}\,h+r_k(h),\qquad \frac{r_k(h)}{h}\to0 Every route's first leg is an honest derivative — mm copies of step 1 from Rule 1.
3
Substitute step 2 into step 1 and collect the terms proportional to hh: f()=f(u)+[kfukdukdx]h+R(h),R(h)=kfukrk(h)+rf(\cdots)=f(\mathbf u)+\Big[\sum_{k}\frac{\partial f}{\partial u_k}\frac{du_k}{dx}\Big]h+R(h),\qquad R(h)=\sum_k\frac{\partial f}{\partial u_k}\,r_k(h)+r The bracket is the claimed slope. Everything not proportional to hh — one leftover per route, plus the shared plane-leftover rr — is swept into R(h)R(h). Nothing has been dropped yet.
4
The route leftovers die: for each kk, 1hfukrk(h)=fukrk(h)hfuk0=0\frac{1}{h}\cdot\frac{\partial f}{\partial u_k}\,r_k(h)=\frac{\partial f}{\partial u_k}\cdot\frac{r_k(h)}{h}\to\frac{\partial f}{\partial u_k}\cdot 0=0 A 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/hu(x)\|\Delta\mathbf u\|/h\to\|\mathbf u'(x)\|, where u=(du1/dx,,dum/dx)\mathbf u'=(du_1/dx,\dots,du_m/dx). So rh=rΔuΔuh0u(x)=0\frac{r}{h}=\frac{r}{\|\Delta\mathbf u\|}\cdot\frac{\|\Delta\mathbf u\|}{h}\to 0\cdot\|\mathbf u'(x)\|=0 The constant is u(x)\|\mathbf u'(x)\|, the size of the combined nudge per unit hh. Fine point: if Δu\Delta\mathbf u is exactly 0\mathbf 0 then r=r(0)=0r=r(\mathbf 0)=0 and the term is already gone — no division needed. Hence R(h)/h0R(h)/h\to0.
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\mathbf x\xrightarrow{F}\mathbf u\xrightarrow{G}\mathbf y, the chain rule reads JGF=JGJFJ_{G\circ F}=J_G\,J_F — Jacobians multiply. Now look at one entry of that product, using the row-times-column rule:

(JGJF)ij=k(JG)ik(JF)kj\big(J_G J_F\big)_{ij}=\sum_{k}\big(J_G\big)_{ik}\big(J_F\big)_{kj}

Each term is one path: input jj nudges intermediate kk (that is (JF)kj(J_F)_{kj}), which nudges output ii (that is (JG)ik(J_G)_{ik}) — multiply along the path. The k\sum_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.

Pause & predict

In (JGJF)ij=k(JG)ik(JF)kj\big(J_G J_F\big)_{ij}=\sum_k (J_G)_{ik}(J_F)_{kj}, what is one single term (JG)ik(JF)kj(J_G)_{ik}(J_F)_{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,,xdx_1,\dots,x_d are the inputs, xd+1,,xD1x_{d+1},\dots,x_{D-1} the intermediate baby steps, xDx_D the output. Each is computed from its parents by an elementary function:

xi=gi(xPa(xi))x_i = g_i\big(x_{\mathrm{Pa}(x_i)}\big)

Now walk backwards. The output blames itself fully, and every other node collects blame from the nodes it feeds — its children:

fxD=1,fxi=j:xiPa(xj)fxjgjxi\frac{\partial f}{\partial x_D}=1,\qquad \frac{\partial f}{\partial x_i}=\sum_{j:\,x_i\in \mathrm{Pa}(x_j)}\frac{\partial f}{\partial x_j}\,\frac{\partial g_j}{\partial x_i}

Read it like a postal system: node jj already knows its own blame f/xj\partial f/\partial x_j. It mails each parent ii a copy, scaled by the local derivative gj/xi\partial g_j/\partial x_i 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\partial f/\partial x_j is computed once and reused by all of jj's parents. And each local derivative gj/xi\partial g_j/\partial x_i is trivial, because each baby step is trivial — the derivative of eae^a or c\sqrt c or a+ba+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\bar x_i equals the true f/xi\partial f/\partial x_i for every node in the graph.

1
Base case. The rightmost node: xˉD=1=f/f\bar x_D=1=\partial f/\partial f — the output's sensitivity to itself. Nudge ff by hh and ff changes by hh. Slope 1, no leftover at all.
2
The order does the bookkeeping. Working right to left means: by the time we reach node xix_i, every child xjx_j (every node that uses xix_i) has already been processed and — by induction — already holds its correct blame xˉj=f/xj\bar x_j=\partial f/\partial x_j. 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 xix_i, with its children as the intermediates. Any nudge of xix_i can reach ff only through the children, so §4's theorem says fxi=j:xiPa(xj)fxjgjxi\frac{\partial f}{\partial x_i}=\sum_{j:\,x_i\in\mathrm{Pa}(x_j)}\frac{\partial f}{\partial x_j}\,\frac{\partial g_j}{\partial x_i} — 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\bar 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\partial f/\partial x_i runs over the children of xix_i — the nodes that use it. Why children, not parents?

In one sentence: Set fˉ=1\bar 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 ww and one bias bb, one input xx, one target yy:

z=wx+b,a=tanh(z),L=12(ay)2z=wx+b,\qquad a=\tanh(z),\qquad L=\tfrac12\,(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\delta=\partial L/\partial z — the blame reaching the pre-activation — because every parameter feeding zz then reads its gradient straight off δ\delta: L/w=δx\partial L/\partial w=\delta\,x, L/b=δ\partial L/\partial b=\delta, L/x=δw\partial L/\partial x=\delta\,w. Compute δ\delta 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 δ\delta before each step; then set the target to y=1y=-1 and watch the same machinery push ww the other way.

drag the landscape to orbit it

1
1

Starting point is the practice set's own numbers: w=0.5, b=0, x=1, y=1w=0.5,\ b=0,\ x=1,\ y=1, so z=0.5z=0.5, a=tanh0.5=0.4621a=\tanh 0.5=0.4621, L=0.1447L=0.1447, and the backward pass gives δ=(ay)(1a2)=0.4230\delta=(a-y)(1-a^2)=-0.4230, hence L/w=0.4230\partial L/\partial w=-0.4230, L/b=0.4230\partial L/\partial b=-0.4230. Both gradients are negative — the loss wants ww and bb bigger. 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. δ=(ay)(1a2)\delta=(a-y)(1-a^2). Nothing to memorise — derive each local slope, then chain them with Rule 1.

1
The loss. L(a)=12(ay)2L(a)=\tfrac12(a-y)^2. Nudge aa by Δ\Delta and expand the square: 12(a+Δy)2=12(ay)2+(ay)Δ+12Δ2La=ay\tfrac12(a+\Delta-y)^2=\tfrac12(a-y)^2+(a-y)\,\Delta+\tfrac12\Delta^2\quad\Rightarrow\quad \frac{\partial L}{\partial a}=a-y The 12Δ2\tfrac12\Delta^2 is the dying leftover. And now you can see why the 12\tfrac12 was planted in the loss: it exists purely to eat the 2 that squaring brings down.
2
The activation. a=tanhz=sca=\tanh z=\dfrac{s}{c} with s=ezezs=e^z-e^{-z}, c=ez+ezc=e^z+e^{-z}. Notice the pair swaps under differentiation: s=cs'=c and c=sc'=s. Quotient rule: (sc)=scscc2=c2s2c2=1(sc)2=1tanh2z=1a2\Big(\frac{s}{c}\Big)'=\frac{s'c-sc'}{c^2}=\frac{c^2-s^2}{c^2}=1-\Big(\frac{s}{c}\Big)^2=1-\tanh^2 z=1-a^2 The derivative comes out written in terms of the output aa — which the forward pass already computed. So the backward pass buys 1a21-a^2 for one multiplication, no new function calls.
3
The pre-activation. z=wx+bz=wx+b is linear, and a linear function's slopes are just its coefficients: zw=x,zb=1,zx=w\frac{\partial z}{\partial w}=x,\qquad \frac{\partial z}{\partial b}=1,\qquad \frac{\partial z}{\partial x}=w Nudge ww by Δ\Delta and zz moves by xΔx\Delta exactly — not even a leftover this time.
4
Chain them (Rule 1, twice). δ=Lz=Ladadz=(ay)(1a2)\delta=\frac{\partial L}{\partial z}=\frac{\partial L}{\partial a}\cdot\frac{da}{dz}=(a-y)(1-a^2) With the widget's starting numbers, ay=0.46211=0.5379a-y=0.4621-1=-0.5379 and 1a2=0.78641-a^2=0.7864: δ=(0.5379)(0.7864)=0.4230\delta=(-0.5379)(0.7864)=-0.4230 then  L/w=δx,  L/b=δ,  L/x=δw\ \partial L/\partial w=\delta\,x,\ \ \partial L/\partial b=\delta,\ \ \partial L/\partial x=\delta\,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\partial L/\partial w and L/b\partial L/\partial b are both exactly δx\delta\cdot x and δ1\delta\cdot 1 with δ=0.423\delta=-0.423. What made them so cheap to get?

Pause & predict

Set the target to y=1y=-1 instead. Before pressing anything: which way will the gradient step now push ww?

In one sentence: Compute the blame δ=L/z\delta=\partial L/\partial z once, and every parameter feeding zz 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: mm neurons share the input vector xRn\mathbf{x}\in\mathbb{R}^n,

Z=Ax+b,a=σ(Z)Z=A\mathbf{x}+\mathbf{b},\qquad \mathbf{a}=\sigma(Z)

with ARm×nA\in\mathbb{R}^{m\times n} the weights, bRm\mathbf b\in\mathbb{R}^m the biases, and the sigmoid σ(z)=11+ez\sigma(z)=\tfrac{1}{1+e^{-z}} applied entry by entry. The blame arriving from above is δ(a)=Loss/a\boldsymbol\delta^{(a)}=\partial\mathrm{Loss}/\partial \mathbf 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)a_i=\sigma(Z_i) touches only its own ZiZ_i, so the Jacobian a/Z\partial\mathbf a/\partial Z is diagonal — diag ⁣(a(1a))\operatorname{diag}\!\big(\mathbf a\odot(1-\mathbf a)\big), using σ=σ(1σ)\sigma'=\sigma(1-\sigma) — and the blame is scaled entrywise (\odot is the Hadamard, entrywise, product):

δ(Z)=δ(a)a(1a)\boldsymbol\delta^{(Z)}=\boldsymbol\delta^{(a)}\odot \mathbf a\odot(1-\mathbf a)

Step two, through Z=Ax+bZ=A\mathbf x+\mathbf b. Since Zi=jAijxj+biZ_i=\sum_j A_{ij}x_j+b_i, each weight sees Zi/Aij=xj\partial Z_i/\partial A_{ij}=x_j, and the chain rule assembles into three matrix formulas:

LossA=δ(Z)x,Lossb=δ(Z),Lossx=Aδ(Z)\begin{gathered}\frac{\partial\mathrm{Loss}}{\partial A}=\boldsymbol\delta^{(Z)}\mathbf{x}^{\top},\qquad \frac{\partial\mathrm{Loss}}{\partial \mathbf b}=\boldsymbol\delta^{(Z)},\\[.4em] \frac{\partial\mathrm{Loss}}{\partial \mathbf x}=A^{\top}\boldsymbol\delta^{(Z)}\end{gathered}

The weights: δ(Z)x\boldsymbol\delta^{(Z)}\mathbf x^\top is an outer product — blame of my row, times activity of my column. The biases: the blame itself. The input: Aδ(Z)A^\top\boldsymbol\delta^{(Z)} re-mixes the blame back through the transposed weights — and this vector is precisely the δ(a)\boldsymbol\delta^{(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)=11+ez\sigma(z)=\dfrac{1}{1+e^{-z}} satisfies σ=σ(1σ)\sigma'=\sigma(1-\sigma) — so the backward pass needs no new function evaluations.

1
Differentiate with Rule 1: σ=(1+ez)1\sigma=(1+e^{-z})^{-1}, outer slope (1+ez)2-(1+e^{-z})^{-2}, inner slope ez ⁣:-e^{-z}\!: σ=(1+ez)2(ez)=ez(1+ez)2\sigma'=-(1+e^{-z})^{-2}\cdot(-e^{-z})=\frac{e^{-z}}{(1+e^{-z})^{2}} The two minus signs cancel — sigmoid always rises.
2
Split the fraction into two factors you can recognise: ez(1+ez)2=11+ez= σez1+ez= 1σsince1σ=(1+ez)11+ez=ez1+ez\frac{e^{-z}}{(1+e^{-z})^{2}}=\underbrace{\frac{1}{1+e^{-z}}}_{=\ \sigma}\cdot\underbrace{\frac{e^{-z}}{1+e^{-z}}}_{=\ 1-\sigma} \qquad\text{since}\quad 1-\sigma=\frac{(1+e^{-z})-1}{1+e^{-z}}=\frac{e^{-z}}{1+e^{-z}} So σ=σ(1σ)\sigma'=\sigma(1-\sigma). Output in, derivative out: a(1a)\mathbf a\odot(1-\mathbf a) uses only the a\mathbf 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. aZ=diag ⁣(a(1a))\dfrac{\partial\mathbf a}{\partial Z}=\operatorname{diag}\!\big(\mathbf a\odot(1-\mathbf a)\big), and therefore δ(Z)=δ(a)a(1a)\boldsymbol\delta^{(Z)}=\boldsymbol\delta^{(a)}\odot\mathbf a\odot(1-\mathbf a) — a multiplication per neuron, no matrix at all.

1
Who depends on whom. ai=σ(Zi)a_i=\sigma(Z_i) reads exactly one input, ZiZ_i. Nudge a different ZjZ_j and aia_i does not move: aiZj=0(ij)\frac{\partial a_i}{\partial Z_j}=0\quad(i\neq 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, aia_i is the one-variable function σ\sigma, and the box above gives its slope: aiZi=σ(Zi)=σ(Zi)(1σ(Zi))=ai(1ai)\frac{\partial a_i}{\partial Z_i}=\sigma'(Z_i)=\sigma(Z_i)\big(1-\sigma(Z_i)\big)=a_i(1-a_i) Steps 1 and 2 together: a matrix with ai(1ai)a_i(1-a_i) down the diagonal and 00 everywhere else — diag(a(1a))\operatorname{diag}(\mathbf a\odot(1-\mathbf a)).
3
Chain it (Rule 1 in matrix form). The blame on ZZ is the blame on a\mathbf a times this Jacobian; multiplying a row by a diagonal matrix scales each entry: δi(Z)=jδj(a)ajZi=δi(a)ai(1ai)\delta^{(Z)}_i=\sum_j \delta^{(a)}_j\,\frac{\partial a_j}{\partial Z_i}=\delta^{(a)}_i\,a_i(1-a_i) The sum over jj is Rule 2, but only the j=ij=i term survives (step 1) — so the "sum over routes" has one route per neuron. Written for all ii at once, that is the \odot formula.
4
Check on the widget's numbers. a=(0.622,0.953)\mathbf a=(0.622,\,0.953) gives a(1a)=(0.235,0.045)\mathbf a\odot(1-\mathbf a)=(0.235,\,0.045); with δ(a)=(0.6,0.4)\boldsymbol\delta^{(a)}=(0.6,\,-0.4), δ(Z)=(0.60.235,  0.40.045)=(0.141,0.018)\boldsymbol\delta^{(Z)}=(0.6\cdot0.235,\ \ -0.4\cdot0.045)=(0.141,\,-0.018) — exactly what stage 3 below displays. Neuron 2 sits at a=0.953a=0.953, nearly saturated, so its factor 0.0450.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)\delta^{(a)}_1 — the top row of the outer product and the mail Aδ(Z)A^{\top}\boldsymbol\delta^{(Z)} react; row 2 does not.

0.6

The layer is 2×22\times2 so every number fits on screen: A=A= 1−120, b=(0,1)\mathbf b=(0,\,1), x=(1,0.5)\mathbf x=(1,\,0.5), and the loss above sends down δ(a)=(0.6,0.4)\boldsymbol\delta^{(a)}=(0.6,\,-0.4). Watch stage 4: L/A\partial L/\partial A is literally the outer-product grid of δ(Z)\boldsymbol\delta^{(Z)} against x\mathbf x — and Aδ(Z)A^{\top}\boldsymbol\delta^{(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)\boldsymbol\delta=\boldsymbol\delta^{(Z)} for short.

1
A weight AijA_{ij}. Scan the forward pass Zk=pAkpxp+bkZ_k=\sum_p A_{kp}x_p+b_k: the entry AijA_{ij} appears in exactly one place — the row k=ik=i, multiplied by xjx_j. One appearance means one path, so Rule 1 alone: LAij=δiZiAij=δixj\frac{\partial L}{\partial A_{ij}}=\delta_i\cdot\frac{\partial Z_i}{\partial A_{ij}}=\delta_i\,x_j "Blame of my row, times activity of my column" — now proved, not just recited.
2
Assemble. The matrix whose (i,j)(i,j) entry is δixj\delta_i x_j is, by definition, the outer product: LA=δx\frac{\partial L}{\partial A}=\boldsymbol\delta\,\mathbf x^{\top} Same shape as AA, one honest entry per weight, ready for AAηL/AA\leftarrow A-\eta\,\partial L/\partial A.
3
A bias bib_i. It appears only in ZiZ_i, with slope 11:  L/bi=δi1\ \partial L/\partial b_i=\delta_i\cdot1, so L/b=δ\partial L/\partial\mathbf b=\boldsymbol\delta. The bias rides its own row and nothing else — blame arrives undiluted.
4
An input xjx_j — the fork. xjx_j appears in every row: Z1,,ZmZ_1,\dots,Z_m all use it. mm appearances, mm paths — Rule 2: Lxj=i=1mδiZixj=i=1mδiAij=(Aδ)j\frac{\partial L}{\partial x_j}=\sum_{i=1}^{m}\delta_i\,\frac{\partial Z_i}{\partial x_j}=\sum_{i=1}^{m}\delta_i\,A_{ij}=\big(A^{\top}\boldsymbol\delta\big)_j Summing δiAij\delta_i A_{ij} over ii walks down column jj of AA — and reading columns is exactly what the transpose does. The mysterious AA^{\top} 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 AR100×300A\in\mathbb{R}^{100\times 300}. What is the shape of Loss/A=δ(Z)x\partial\mathrm{Loss}/\partial A=\boldsymbol\delta^{(Z)}\mathbf{x}^{\top}, and why was that inevitable?

Pause & predict

Why does the blame leave through AA^{\top} — the transpose — rather than through AA itself?

In one sentence: δ(Z)=δ(a) ⁣a(1a)\boldsymbol\delta^{(Z)}=\boldsymbol\delta^{(a)}\!\odot\mathbf a\odot(1-\mathbf a), then weights get δ(Z)x\boldsymbol\delta^{(Z)}\mathbf x^{\top}, biases get δ(Z)\boldsymbol\delta^{(Z)}, and the layer below gets Aδ(Z)A^{\top}\boldsymbol\delta^{(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.)

IdentitySay it in words
xax=a\dfrac{\partial\, \mathbf{x}^{\top}\mathbf{a}}{\partial \mathbf{x}}=\mathbf{a}^{\top}a dot product's sensitivity to x\mathbf x is just the other vector
axx=a\dfrac{\partial\, \mathbf{a}^{\top}\mathbf{x}}{\partial \mathbf{x}}=\mathbf{a}^{\top}same thing — a dot product doesn't care about the order
aXbX=ab\dfrac{\partial\, \mathbf{a}^{\top}X\mathbf{b}}{\partial X}=\mathbf{a}\mathbf{b}^{\top}each entry XijX_{ij} is multiplied by aibja_i b_j — so the gradient is that outer product
xBxx=x ⁣(B+B)\dfrac{\partial\, \mathbf{x}^{\top}B\mathbf{x}}{\partial \mathbf{x}}=\mathbf{x}^{\top}\!\big(B+B^{\top}\big)x\mathbf x appears twice, so you get two copies — BB once from each side
s(xAs)W(xAs)=2(xAs)WA\dfrac{\partial}{\partial \mathbf{s}}(\mathbf x-A\mathbf s)^{\top}W(\mathbf x-A\mathbf s)=-2(\mathbf x-A\mathbf s)^{\top}WAfor symmetric WW: least-squares' own gradient — chain rule through the residual

Notice the family resemblance to Section 7: the third identity is why Loss/A\partial\mathrm{Loss}/\partial A came out as an outer product, and the last one is the loss yAs2\|\mathbf y-A\mathbf s\|^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. xa=ixiai\mathbf x^{\top}\mathbf a=\sum_i x_i a_i. Differentiate with respect to one coordinate xk ⁣:x_k\!: every term is constant except xkakx_k a_k, whose slope is aka_k. Collect the coordinates into a row: (xa)x=a\frac{\partial(\mathbf x^{\top}\mathbf a)}{\partial\mathbf x}=\mathbf a^{\top} And ax\mathbf a^{\top}\mathbf x is the same scalar, so the table's second line comes free.
2
The sandwich. aXb=i,jaiXijbj\mathbf a^{\top}X\mathbf b=\sum_{i,j}a_i X_{ij}b_j. The entry XijX_{ij} appears once, with coefficient aibj ⁣:a_ib_j\!: (aXb)Xij=aibj(aXb)X=ab\frac{\partial(\mathbf a^{\top}X\mathbf b)}{\partial X_{ij}}=a_ib_j\quad\Rightarrow\quad \frac{\partial(\mathbf a^{\top}X\mathbf b)}{\partial X}=\mathbf a\mathbf b^{\top} The same one-appearance argument that made L/A\partial L/\partial A an outer product in the layer proof — it is literally the same fact.
3
The quadratic — where B+BB+B^{\top} is born. xBx=i,jBijxixj\mathbf x^{\top}B\mathbf x=\sum_{i,j}B_{ij}\,x_i\,x_j, and x\mathbf x appears twice in each term. Product rule on xixjx_ix_j, with respect to xkx_k: the left copy fires when i=ki=k, contributing jBkjxj=(Bx)k\sum_j B_{kj}x_j=(B\mathbf x)_k; the right copy fires when j=kj=k, contributing iBikxi=(Bx)k\sum_i B_{ik}x_i=(B^{\top}\mathbf x)_k. Add the two: (xBx)xk=(Bx)k+(Bx)k(xBx)x=x(B+B)\frac{\partial(\mathbf x^{\top}B\mathbf x)}{\partial x_k}=(B\mathbf x)_k+(B^{\top}\mathbf x)_k\quad\Rightarrow\quad \frac{\partial(\mathbf x^{\top}B\mathbf x)}{\partial\mathbf x}=\mathbf x^{\top}\big(B+B^{\top}\big) Two appearances of x\mathbf x, two donated terms — the "mysterious" +B+B^{\top} is Rule 2's fork, hiding in plain algebra. For symmetric BB it collapses to 2xB2\mathbf x^{\top}B.
4
Least squares — a chain of the previous lines. Set the residual r=xAs\mathbf r=\mathbf x-A\mathbf s and E=rWrE=\mathbf r^{\top}W\mathbf r with WW symmetric. Rule 1 with r\mathbf r as the intermediate: Es=Errs=r(W+W)line 3(A)r linear in s=2rW(A)=2(xAs)WA\begin{aligned}\frac{\partial E}{\partial\mathbf s}&=\frac{\partial E}{\partial\mathbf r}\,\frac{\partial\mathbf r}{\partial\mathbf s} =\underbrace{\mathbf r^{\top}(W+W^{\top})}_{\text{line 3}}\cdot\underbrace{(-A)}_{\mathbf r\text{ linear in }\mathbf s}\\[.3em] &=2\,\mathbf r^{\top}W\cdot(-A)=-2(\mathbf x-A\mathbf s)^{\top}WA\end{aligned} The 22 came from W+WW+W^{\top} under symmetry; the minus came from the As-A\mathbf s inside the residual. Nothing to memorise once you can rebuild it in two lines.
Pause & predict

With B=B=1234 (not symmetric), what is xBxx\dfrac{\partial\,\mathbf x^{\top}B\mathbf x}{\partial \mathbf x} at x=(x1,x2)\mathbf x=(x_1,x_2)?

Pause & predict

In the least-squares gradient 2(xAs)WA-2(\mathbf x-A\mathbf s)^{\top}WA, where exactly did the factor 22 come from?

In one sentence: Five identities — dot product, outer product, the B+BB+B^\top doubling, and least squares — supply nearly every local derivative a real model needs.
9

Why it's so cheap — one sweep, everything reused

Stack KK layers, fi=σi(Ai1fi1+bi1)f_i=\sigma_i(A_{i-1}f_{i-1}+b_{i-1}), and put a loss at the end: L=yfK2L=\|\mathbf y-f_K\|^2. Every layer's parameters θi={Ai,bi}\theta_i=\{A_i,b_i\} need a gradient, and the chain rule writes each one as a product that reaches from the loss back to that layer:

LθK1=LfKfKθK1LθK2=LfKfKfK1fK1θK2Lθi=LfKfKfK1fi+2fi+1fi+1θi\begin{aligned}\frac{\partial L}{\partial\theta_{K-1}}&=\frac{\partial L}{\partial f_K}\frac{\partial f_K}{\partial\theta_{K-1}}\\[.35em] \frac{\partial L}{\partial\theta_{K-2}}&=\frac{\partial L}{\partial f_K}\frac{\partial f_K}{\partial f_{K-1}}\frac{\partial f_{K-1}}{\partial\theta_{K-2}}\\[.35em] \frac{\partial L}{\partial\theta_{i}}&=\frac{\partial L}{\partial f_K}\frac{\partial f_K}{\partial f_{K-1}}\cdots\frac{\partial f_{i+2}}{\partial f_{i+1}}\frac{\partial f_{i+1}}{\partial\theta_{i}}\end{aligned}

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 δ\boldsymbol\delta 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. Lθi=LfKfKfK1fi+2fi+1fi+1θi\dfrac{\partial L}{\partial\theta_i}=\dfrac{\partial L}{\partial f_K}\,\dfrac{\partial f_K}{\partial f_{K-1}}\cdots\dfrac{\partial f_{i+2}}{\partial f_{i+1}}\,\dfrac{\partial f_{i+1}}{\partial\theta_i} — 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)f_{i+1}=\sigma_{i+1}(A_if_i+b_i) means node fi+1f_{i+1} has exactly two parents, fif_i and θi={Ai,bi}\theta_i=\{A_i,b_i\}, and node fif_i has exactly one child, fi+1f_{i+1}. The loss LL is the single child of fKf_K. 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; fjf_j has one, so the sum has one term: fˉK=LfK,fˉj=fˉj+1fj+1fj(j<K)\bar f_K=\frac{\partial L}{\partial f_K},\qquad \bar f_j=\bar f_{j+1}\,\frac{\partial f_{j+1}}{\partial f_j}\quad(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 KK down to i+1i+1: fˉi+1=LfKfKfK1fi+2fi+1\bar f_{i+1}=\frac{\partial L}{\partial f_K}\,\frac{\partial f_K}{\partial f_{K-1}}\cdots\frac{\partial f_{i+2}}{\partial f_{i+1}} Each application appends one more Jacobian on the right. This running product is the δ(a)\boldsymbol\delta^{(a)} that §7 handed down to each layer.
4
Recipe at the parameter node. θi\theta_i has one child, fi+1f_{i+1}, so Lθi=θˉi=fˉi+1fi+1θi\frac{\partial L}{\partial\theta_i}=\bar\theta_i=\bar f_{i+1}\,\frac{\partial f_{i+1}}{\partial\theta_i} and substituting step 3 gives the claim. Every layer's gradient is the same prefix fˉi+1\bar 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.

4

Grey blocks: factors a naive left-to-right evaluation would recompute. Blue: the factors backprop actually computes — each row just extends the running blame δ\boldsymbol\delta by one new factor. Naive cost grows like K2/2K^2/2; backprop stays at KK. 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 Lf1=LfKfKfK1f2f1\dfrac{\partial L}{\partial f_1}=\dfrac{\partial L}{\partial f_K}\,\dfrac{\partial f_K}{\partial f_{K-1}}\cdots\dfrac{\partial f_2}{\partial f_1} can be multiplied in either order. One order is about mm times cheaper — count it.

1
Shapes first (Unit 6's rule: outputs × inputs). LL is a scalar, so L/fK\partial L/\partial f_K is a 1×m1\times m row. Each layer-to-layer Jacobian fi/fi1\partial f_{i}/\partial f_{i-1} is a full m×mm\times m matrix, for layers of width mm. 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)(1\times m)\cdot(m\times m) costs about m2m^2 multiplications — and returns another 1×m1\times m row. Repeat through all KK layers: costKm2,always carrying just a row\text{cost}\approx K\,m^{2},\qquad\text{always carrying just a row} That carried row is exactly the blame δ\boldsymbol\delta 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)(m\times m)\cdot(m\times m): cost m3m^3, and it returns another m×mm\times m matrix that must be carried the whole way: costKm3\text{cost}\approx K\,m^{3} For m=1000m=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)\nabla f(\mathbf x_0), you own the best linear stand-in for ff near x0\mathbf x_0:

L(x)    f(x0)+f(x0)(xx0)L(\mathbf x)\;\approx\;f(\mathbf x_0)+\nabla f(\mathbf x_0)^{\top}(\mathbf x-\mathbf x_0)

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\mathbf x_0, 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+9f(x)=\sqrt{x^2+9} around x0=4x_0=-4, where f(4)=5f(-4)=5 and f(4)=45f'(-4)=-\tfrac45:

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-4: L(x)=545(x+4)L(x)=5-\tfrac45(x+4), the companion's answer. Slide the probe to 3.5-3.5 and the stand-in guesses 4.64.6 against a true 4.614.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

0
0
0.5

At the origin the gradient is (1,0)(1,0), so the plane is L(x,y)=1+xL(x,y)=1+x — tilted along xx, flat along yy, 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)(xx0)L(x)=f(x_0)+f'(x_0)(x-x_0) is what is left of the Taylor series when every term with (xx0)2(x-x_0)^2 or higher is dropped — and the first dropped term tells you the error.

1
Taylor at x0x_0 (Unit 8's subject, used once here): with h=xx0h=x-x_0, f(x0+h)=f(x0)+f(x0)h+12f(x0)h2+16f(x0)h3+f(x_0+h)=f(x_0)+f'(x_0)\,h+\tfrac12 f''(x_0)\,h^2+\tfrac16 f'''(x_0)\,h^3+\cdots Keep the first two terms and you are holding L(x)L(x) exactly. Everything after them is §4's leftover r(h)r(h), now written out.
2
The error is led by the h2h^2 term. For small hh the h3h^3 and later terms are smaller still, so f(x)L(x)12f(x0)(xx0)2f(x)-L(x)\approx\tfrac12 f''(x_0)\,(x-x_0)^2 Twice the distance, four times the error — the same "leftover dies faster than hh" you saw drawn in §4.
3
Check on the widget. f=x2+9f=\sqrt{x^2+9}, so f(x)=9(x2+9)3/2f''(x)=\dfrac{9}{(x^2+9)^{3/2}} and f(4)=9125=0.072f''(-4)=\dfrac{9}{125}=0.072. Probe at x=3.5x=-3.5, i.e. h=0.5h=0.5: 120.0720.52=0.009vs. the widget’s4.60984.6=0.0098\tfrac12\cdot0.072\cdot0.5^2=0.009\qquad\text{vs. the widget's}\quad 4.6098-4.6=0.0098 The prediction is off only by the h3h^3 crumbs. So a gradient does more than point downhill — with ff'' it also prices how far the linear stand-in can be trusted.
Pause & predict

The companion also linearizes f(x,y)=excosyf(x,y)=e^x\cos y at (0,0)(0,0): value 11, gradient (1,0)(1,0). What is the stand-in plane?

In one sentence: f(x0)+f(x0)(xx0)f(\mathbf x_0)+\nabla f(\mathbf x_0)^{\top}(\mathbf x-\mathbf x_0) is the best linear stand-in near x0\mathbf x_0 — 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 f(x+h)f(xh)2h\tfrac{f(x+h)-f(x-h)}{2h} has two enemies. Big hh: the secant misses the tangent (Unit 6's curvature gap). Tiny hh: the computer subtracts two nearly equal numbers and the difference drowns in rounding error. Squeeze hh yourself:

The gradient checkerfinite differences vs. the exact answer — there is a best h, and it is not 0

Try: slide hh down one decade at a time and watch the error fall 100× per decade — until, near 10610^{-6}, it stops and turns.

−3

The function is the monster from §1, at x=1x=1, where autodiff says df/dx=5.98308df/dx=5.98308 exactly. Slide hh down the valley: the error falls like h2h^2 (curvature fading), bottoms out near h106h\approx10^{-6} for this ff (nearer 10510^{-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 h2h^2, rises like 1/h1/h, and bottoms out at a best step hh_* of order 10610^{-6}10510^{-5} — all three facts derived, not observed.

1
Taylor both evaluations around xx (Unit 6's tool, Unit 8's whole subject): f(x±h)=f(x)±f(x)h+f(x)2h2±f(x)6h3+f(x\pm h)=f(x)\pm f'(x)h+\tfrac{f''(x)}{2}h^{2}\pm\tfrac{f'''(x)}{6}h^{3}+\cdots Same expansion, two signs — writing them together is what makes the next line click.
2
Subtract — the even terms cancel. f(x+h)f(xh)=2f(x)h+f(x)3h3+f(x+h)-f(x-h)=2f'(x)h+\tfrac{f'''(x)}{3}h^{3}+\cdots. Divide by 2h2h: f(x+h)f(xh)2h=f(x)+f(x)6h2+\frac{f(x+h)-f(x-h)}{2h}=f'(x)+\frac{f'''(x)}{6}\,h^{2}+\cdots The h2h^2 term is the left wall of the V — slope 2 on log–log axes. (The one-sided version f(x+h)f(x)h\frac{f(x+h)-f(x)}{h} keeps an f2h\frac{f''}{2}h term — slope only 1. That is why the checker uses the centred difference.)
3
Rounding. The computer stores f(x±h)f(x\pm h) only to relative precision u1016u\approx10^{-16}, so the subtraction of two nearly equal numbers carries an absolute error of about uf(x)u|f(x)|; dividing by 2h2h turns it into rounding erroruf(x)2h\text{rounding error}\approx\frac{u\,|f(x)|}{2h} The 1/h1/h is the right wall: shrink hh and you divide the same noise by an ever smaller number.
4
Add the walls and set the slope to zero. E(h)f6h2+uf2hE(h)\approx\frac{|f'''|}{6}h^{2}+\frac{u|f|}{2h}. Differentiate in hh: E(h)=f3huf2h2=0h3=3uf2fE'(h)=\frac{|f'''|}{3}\,h-\frac{u\,|f|}{2h^{2}}=0\quad\Longleftrightarrow\quad h^{3}=\frac{3\,u\,|f|}{2\,|f'''|} A rising wall plus a falling wall has one lowest point, where the two slopes cancel. Multiplying through by h2h^2 isolates h3h^3.
5
Read off the best step. h=(3uf2f)1/3u1/35×106when ffh_{*}=\Big(\frac{3\,u\,|f|}{2\,|f'''|}\Big)^{1/3}\sim u^{1/3}\approx 5\times10^{-6}\quad\text{when }|f'''|\approx|f| For the monster at x=1x=1, f=1.09|f|=1.09 but f153|f'''|\approx153, so h1×106h_*\approx1\times10^{-6} — the huge third derivative pushes the floor left, which is what the widget shows. And the best possible error is only u2/31011\sim u^{2/3}\approx10^{-11} (about 101010^{-10} here) — while autodiff is exact to full precision. That is the entire case for automatic differentiation, compressed into one minimisation.

σ\sigma' is free. The identity σ=σ(1σ)\sigma'=\sigma(1-\sigma) means the backward pass needs no new function calls — the forward pass already computed a\mathbf a, and a(1a)\mathbf a\odot(1-\mathbf a) is two cheap operations. The same trick works for tanh\tanh (1a21-a^2). 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(1a)14\mathbf a\odot(1-\mathbf a)\le\tfrac14. 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.

Pause & predict

In the gradient checker, why does making hh 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˙)(v,\dot v) as v+v˙εv+\dot v\,\varepsilon, where ε\varepsilon is a new symbol with one rule: ε2=0\varepsilon^{2}=0. Then ordinary algebra on these "dual numbers" performs exact differentiation.

1
Sums. (a+a˙ε)+(b+b˙ε)=(a+b)+(a˙+b˙)ε(a+\dot a\varepsilon)+(b+\dot b\varepsilon)=(a+b)+(\dot a+\dot b)\varepsilon. 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)ε(a+\dot a\varepsilon)(b+\dot b\varepsilon)=ab+(a\dot b+\dot a b)\varepsilon+\dot a\dot b\,\varepsilon^{2}=ab+(a\dot b+\dot a b)\,\varepsilon ε2=0\varepsilon^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˙εg(a+\dot a\varepsilon)=g(a)+g'(a)\,\dot a\,\varepsilon — and this is forced, not chosen: Taylor gives g(a+t)=g(a)+g(a)t+g(a)2t2+g(a+t)=g(a)+g'(a)t+\tfrac{g''(a)}{2}t^2+\cdots, and with t=a˙εt=\dot a\varepsilon every term from t2t^2 onwards contains ε2\varepsilon^2 and vanishes. The chain rule arrives baked in: whatever a˙\dot a is carrying gets multiplied by the local slope g(a)g'(a).
4
Run the program on pairs, seeding the input as x=x0+1εx=x_0+1\cdot\varepsilon (its derivative with respect to itself is 1). Example — f(x)=xexf(x)=x\,e^{x} at x0=1x_0=1: x=(1,1)  ex  (e,e)  ×x  (1e,  1e+1e)=(e,2e)x=(1,\,1)\ \xrightarrow{\ e^{x}\ }\ (e,\,e)\ \xrightarrow{\ \times\, x\ }\ \big(1\cdot e,\ \ 1\cdot e+1\cdot e\big)=(e,\,2e) So f(1)=ef(1)=e and f(1)=2e5.4366f'(1)=2e\approx5.4366 — exact, and no derivative formula was ever written down. Check: f=ex(1+x)f'=e^{x}(1+x) gives 2e2e. ✓ 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\varepsilon^{2}=0 makes the product rule appear on its own. What is ε2=0\varepsilon^{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.

IdeaThe one-line versionWhere it returns
Computation graphAny function as baby steps with arrowsevery framework's autograd tape
Backward passfˉ=1\bar f=1; multiply along paths, add at forksevery training step you'll ever run
δ\delta (the blame)Computed once at each node, reused by every parameter feeding itUnit 9 · gradient descent at scale
The four layer formulasδ(Z)=δ(a) ⁣a(1a)\delta^{(Z)}=\delta^{(a)}\!\odot a\odot(1{-}a);  A=δ(Z)x\ \partial_A=\delta^{(Z)}x^{\top};  b=δ(Z)\ \partial_b=\delta^{(Z)};  x=Aδ(Z)\ \partial_x=A^{\top}\delta^{(Z)}the inner loop of deep learning
Gradient cookbookDot → a\mathbf a^\top;  aXbab\ \mathbf a^\top X\mathbf b\to \mathbf a\mathbf b^\top;  xBxx(B+B)\ \mathbf x^\top B\mathbf x\to \mathbf x^\top(B{+}B^\top)Units 9–15, constantly
Cost of a gradientAll of them, for the price of ≈ one forward passwhy billion-knob training is possible
Linearizationf(x0)+f(xx0)f(\mathbf x_0)+\nabla f^{\top}(\mathbf x-\mathbf x_0) — the local stand-inUnit 8 · Taylor; Unit 9 · each descent step
The one thing to remember

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\mathbf z=W\mathbf x and the loss g(z)=12zt2g(\mathbf z)=\tfrac12\|\mathbf z-\mathbf t\|^2 against a target t\mathbf t, with W=[120111],x=[11],t=[102].W=\begin{bmatrix}1&2\\0&1\\-1&1\end{bmatrix},\qquad \mathbf x=\begin{bmatrix}1\\1\end{bmatrix},\qquad \mathbf t=\begin{bmatrix}1\\0\\2\end{bmatrix}. (a) Compute zg\nabla_{\mathbf z}\,g (with its dimension) and J=z/xJ=\partial\mathbf z/\partial\mathbf x (with its dimension). (b) Combine them to get xg\nabla_{\mathbf x}\,g, 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 WW^{\top}.

Show the full solution
Step 1 — forward pass. z=Wx=(1+2, 0+1, 1+1)=(3,1,0)\mathbf z=W\mathbf x=(1{+}2,\ 0{+}1,\ -1{+}1)^{\top}=(3,1,0)^{\top}. Residual r=zt=(2,1,2)\mathbf r=\mathbf z-\mathbf t=(2,1,-2)^{\top}, and the loss is g=12(22+12+(2)2)=92=4.5g=\tfrac12(2^2+1^2+(-2)^2)=\tfrac92=4.5.
(a) Step 2 — gradient at the output. For g=12zt2g=\tfrac12\|\mathbf z-\mathbf t\|^2,  zg=zt=r=(2,1,2)\ \nabla_{\mathbf z}\,g=\mathbf z-\mathbf t=\mathbf r=(2,1,-2)^{\top} — dimension 3×13\times1, one entry per output. The Jacobian of a linear map is the matrix itself: J=(Wx)/x=WJ=\partial(W\mathbf x)/\partial\mathbf x=W, dimension 3×23\times2 (outputs × inputs).
(b) Step 3 — chain them. xg=Jzg=Wr=[101211][212]=[12+01+(1)(2)22+11+1(2)]=[43]\nabla_{\mathbf x}\,g=J^{\top}\nabla_{\mathbf z}\,g=W^{\top}\mathbf r=\begin{bmatrix}1&0&-1\\2&1&1\end{bmatrix}\begin{bmatrix}2\\1\\-2\end{bmatrix}=\begin{bmatrix}1\cdot2+0\cdot1+(-1)(-2)\\2\cdot2+1\cdot1+1\cdot(-2)\end{bmatrix}=\begin{bmatrix}4\\3\end{bmatrix} Dimension check: zg\nabla_{\mathbf z}g is 3×13\times1, WW^{\top} is 2×32\times3, product 2×12\times1 — the shape of x\mathbf x, as a gradient must be. ✓

zg=(2,1,2)\nabla_{\mathbf z}g=(2,1,-2)^{\top} (3×1), J=WJ=W (3×2), xg=(4,3)\nabla_{\mathbf x}g=(4,3)^{\top} (2×1), loss =4.5=4.5.

Remember

"Backprop through a linear layer" = "multiply the incoming gradient by WW^{\top}". You can also check by substituting first: g(x)=12Wxt2g(\mathbf x)=\tfrac12\|W\mathbf x-\mathbf t\|^2 has gradient W(Wxt)=WrW^{\top}(W\mathbf x-\mathbf t)=W^{\top}\mathbf r — same answer, one line.

Problem 2medium

A neuron computes z=wx+b, a=tanh(z)z=wx+b,\ a=\tanh(z), and the loss L=12(ay)2L=\tfrac12(a-y)^2. Using tanh(z)=1tanh2(z)\tanh'(z)=1-\tanh^2(z) and the values w=0.5, x=1, b=0, y=1w=0.5,\ x=1,\ b=0,\ y=1: (a) do the forward pass (z,a,L)(z,a,L); (b) backpropagate to obtain L/w, L/b, L/x\partial L/\partial w,\ \partial L/\partial b,\ \partial L/\partial x.

What this tests. The full forward–backward cycle on a single neuron, and the shared blame δ\delta that Section 6 trains with.

Show the full solution
(a) Forward. z=0.51+0=0.5z=0.5\cdot1+0=0.5;  a=tanh(0.5)=0.4621\ a=\tanh(0.5)=0.4621;  L=12(0.46211)2=12(0.5379)2=0.1447\ L=\tfrac12(0.4621-1)^2=\tfrac12(-0.5379)^2=0.1447.
(b) Step 1 — the shared blame. Walk zaLz\to a\to L backwards: La=ay=0.5379,dadz=1a2=10.2136=0.7864\frac{\partial L}{\partial a}=a-y=-0.5379,\qquad \frac{da}{dz}=1-a^2=1-0.2136=0.7864 δ  =  Lz=Ladadz=(0.5379)(0.7864)=0.4230\delta\;=\;\frac{\partial L}{\partial z}=\frac{\partial L}{\partial a}\,\frac{da}{dz}=(-0.5379)(0.7864)=-0.4230
Step 2 — hand out copies. z=wx+bz=wx+b gives z/w=x=1\partial z/\partial w=x=1, z/b=1\partial z/\partial b=1, z/x=w=0.5\partial z/\partial x=w=0.5: Lw=δx=0.4230,Lb=δ=0.4230,Lx=δw=0.2115\frac{\partial L}{\partial w}=\delta\cdot x=-0.4230,\qquad \frac{\partial L}{\partial b}=\delta=-0.4230,\qquad \frac{\partial L}{\partial x}=\delta\cdot w=-0.2115

z=0.5, a=0.4621, L=0.1447z=0.5,\ a=0.4621,\ L=0.1447;  L/w=0.4230, L/b=0.4230, L/x=0.2115\ \partial L/\partial w=-0.4230,\ \partial L/\partial b=-0.4230,\ \partial L/\partial x=-0.2115.

Remember

δ\delta is computed once and reused three times — the whole economy of backprop in miniature. Both parameter gradients are negative, so a descent step raises ww and bb, pushing aa toward the target 11. Section 6's widget runs exactly these numbers.

Problem 3easy

A scalar function is built from two intermediates: f=uvf=uv,  u=x2+y\ u=x^2+y,  v=xy\ v=x-y. (a) Write f/u, f/v\partial f/\partial u,\ \partial f/\partial v and the four partials of u,vu,v with respect to x,yx,y. (b) Using the chain rule, assemble f/x\partial f/\partial x and f/y\partial f/\partial y, and evaluate both at (x,y)=(1,1)(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\partial f/\partial u=v,  f/v=u\ \partial f/\partial v=u. Inner: u/x=2x\partial u/\partial x=2x,  u/y=1\ \partial u/\partial y=1,  v/x=1\ \partial v/\partial x=1,  v/y=1\ \partial v/\partial y=-1.
(b) Step 1 — two paths from each input. fx=fuuxvia u+fvvxvia v=v(2x)+u(1)=2x(xy)+(x2+y)\frac{\partial f}{\partial x}=\underbrace{\frac{\partial f}{\partial u}\frac{\partial u}{\partial x}}_{\text{via }u}+\underbrace{\frac{\partial f}{\partial v}\frac{\partial v}{\partial x}}_{\text{via }v}=v\,(2x)+u\,(1)=2x(x-y)+(x^2+y) fy=v(1)+u(1)=(xy)(x2+y)\frac{\partial f}{\partial y}=v\,(1)+u\,(-1)=(x-y)-(x^2+y)
Step 2 — evaluate at (1,1)(1,1) where u=2, v=0u=2,\ v=0: fx(1,1)=02+21=2,fy(1,1)=01+2(1)=2\frac{\partial f}{\partial x}\Big|_{(1,1)}=0\cdot2+2\cdot1=2,\qquad \frac{\partial f}{\partial y}\Big|_{(1,1)}=0\cdot1+2\cdot(-1)=-2
Step 3 — cross-check by expanding first. f=(x2+y)(xy)=x3x2y+xyy2f=(x^2+y)(x-y)=x^3-x^2y+xy-y^2, so f/x=3x22xy+y=32+1=2\partial f/\partial x=3x^2-2xy+y=3-2+1=2 ✓ and f/y=x2+x2y=1+12=2\partial f/\partial y=-x^2+x-2y=-1+1-2=-2 ✓.

f/x(1,1)=2\partial f/\partial x\,(1,1)=2,  f/y(1,1)=2\ \partial f/\partial y\,(1,1)=-2 — by paths and by expansion alike.

Problem 4hard

Define g(z,ν):=logp(x,z)logq(z,ν)g(\mathbf z,\boldsymbol\nu):=\log p(\mathbf x,\mathbf z)-\log q(\mathbf z,\boldsymbol\nu) with z:=t(ϵ,ν)\mathbf z:=t(\boldsymbol\epsilon,\boldsymbol\nu), for differentiable functions p,q,tp,q,t and xRD, zRE, νRF, ϵRG\mathbf x\in\mathbb{R}^D,\ \mathbf z\in\mathbb{R}^E,\ \boldsymbol\nu\in\mathbb{R}^F,\ \boldsymbol\epsilon\in\mathbb{R}^G. Using the chain rule, compute the total derivative ddνg(z,ν)\dfrac{d}{d\boldsymbol\nu}g(\mathbf z,\boldsymbol\nu).

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. ν\boldsymbol\nu reaches gg two ways: directly (it sits inside logq(z,ν)\log q(\mathbf z,\boldsymbol\nu)) and indirectly (it builds z=t(ϵ,ν)\mathbf z=t(\boldsymbol\epsilon,\boldsymbol\nu), and z\mathbf z feeds both logp\log p and logq\log q). Total derivative = sum over both routes.
Step 2 — the direct route. Hold z\mathbf z fixed and differentiate gg in the ν\boldsymbol\nu-slot only. The logp\log p term has no direct ν\boldsymbol\nu: gν=logq(z,ν)ν(1×F)\frac{\partial g}{\partial\boldsymbol\nu}=-\frac{\partial \log q(\mathbf z,\boldsymbol\nu)}{\partial\boldsymbol\nu}\qquad(1\times F)
Step 3 — the indirect route, two links. First how gg feels z\mathbf z, then how z\mathbf z feels ν\boldsymbol\nu: gz=logp(x,z)zlogq(z,ν)z(1×E),zν=t(ϵ,ν)ν(E×F)\frac{\partial g}{\partial\mathbf z}=\frac{\partial \log p(\mathbf x,\mathbf z)}{\partial\mathbf z}-\frac{\partial \log q(\mathbf z,\boldsymbol\nu)}{\partial\mathbf z}\quad(1\times E),\qquad \frac{\partial\mathbf z}{\partial\boldsymbol\nu}=\frac{\partial t(\boldsymbol\epsilon,\boldsymbol\nu)}{\partial\boldsymbol\nu}\quad(E\times F)
Step 4 — add the routes. dgdν=logqν  +  (logpzlogqz)tν\frac{d g}{d\boldsymbol\nu}=-\frac{\partial \log q}{\partial\boldsymbol\nu}\;+\;\left(\frac{\partial \log p}{\partial\mathbf z}-\frac{\partial \log q}{\partial\mathbf z}\right)\frac{\partial t}{\partial\boldsymbol\nu} Dimension check: (1×F)+(1×E)(E×F)=(1×F)(1\times F)+(1\times E)(E\times F)=(1\times F) ✓.

dgdν=logqν+(logpzlogqz)tν\dfrac{dg}{d\boldsymbol\nu}=-\dfrac{\partial\log q}{\partial\boldsymbol\nu}+\Big(\dfrac{\partial\log p}{\partial\mathbf z}-\dfrac{\partial\log q}{\partial\mathbf z}\Big)\dfrac{\partial t}{\partial\boldsymbol\nu}.

Remember

Write d/dνd/d\boldsymbol\nu (total) for "all routes", /ν\partial/\partial\boldsymbol\nu (partial) for "this slot only, everything else frozen". The whole problem is Section 3's fork rule wearing research-paper notation.

Problem 5medium

Compute dfdx\dfrac{df}{d\mathbf x} for f(z)=log(1+z)f(z)=\log(1+z),  z=xx\ z=\mathbf x^{\top}\mathbf x,  xRD\ \mathbf x\in\mathbb{R}^D. State the dimension of every partial derivative involved.

What this tests. A two-step graph xzf\mathbf x\to z\to f where the middle is a scalar — plus the cookbook's dot-product identity applied to xx\mathbf x^{\top}\mathbf x.

Show the full solution
Step 1 — the outer link. dfdz=11+z\dfrac{df}{dz}=\dfrac{1}{1+z}. Dimension 1×11\times1.
Step 2 — the inner link. z=xx=ixi2z=\mathbf x^{\top}\mathbf x=\sum_i x_i^2, so z/xk=2xk\partial z/\partial x_k=2x_k, assembled as the row zx=2x(1×D)\frac{\partial z}{\partial\mathbf x}=2\mathbf x^{\top}\qquad(1\times D) (Or by the cookbook: xBx\mathbf x^\top B\mathbf x with B=IB=I gives x(I+I)=2x\mathbf x^{\top}(I+I)=2\mathbf x^{\top}.)
Step 3 — multiply the links. dfdx=dfdzzx=2x1+xx(1×1)(1×D)=(1×D) \frac{df}{d\mathbf x}=\frac{df}{dz}\,\frac{\partial z}{\partial\mathbf x}=\frac{2\mathbf x^{\top}}{1+\mathbf x^{\top}\mathbf x}\qquad(1\times1)(1\times D)=(1\times D)\ \checkmark
Step 4 — sanity check with numbers. At x=(1,2)\mathbf x=(1,2)^{\top}: z=5z=5, so the formula gives 26(1,2)=(13,23)\tfrac{2}{6}(1,2)=(\tfrac13,\tfrac23) — and differentiating log(1+x12+x22)\log(1+x_1^2+x_2^2) directly gives (2x11+z,2x21+z)=(13,23)\big(\tfrac{2x_1}{1+z},\tfrac{2x_2}{1+z}\big)=(\tfrac13,\tfrac23) ✓.

dfdx=2x1+xx\dfrac{df}{d\mathbf x}=\dfrac{2\mathbf x^{\top}}{1+\mathbf x^{\top}\mathbf x}, a 1×D1\times D row.

Problem 6medium

Compute dfdx\dfrac{d\mathbf f}{d\mathbf x} for f(z)=sin(z)\mathbf f(\mathbf z)=\sin(\mathbf z) applied entrywise,  z=Ax+b\ \mathbf z=A\mathbf x+\mathbf b, with ARE×D, xRD, bREA\in\mathbb{R}^{E\times D},\ \mathbf x\in\mathbb{R}^{D},\ \mathbf b\in\mathbb{R}^{E}. State every dimension.

What this tests. The Jacobian chain rule with an entrywise nonlinearity — the exact structure of Section 7's layer, with sin\sin in place of σ\sigma.

Show the full solution
Step 1 — the outer Jacobian. fi=sin(zi)f_i=\sin(z_i) touches only its own ziz_i, so off-diagonal partials vanish and fz=diag ⁣(cos(z1),,cos(zE))=diag ⁣(cos(z))(E×E)\frac{\partial\mathbf f}{\partial\mathbf z}=\operatorname{diag}\!\big(\cos(z_1),\dots,\cos(z_E)\big)=\operatorname{diag}\!\big(\cos(\mathbf z)\big)\qquad(E\times E) — the same diagonal shape as Section 7's diag(a(1a))\operatorname{diag}(\mathbf a\odot(1-\mathbf a)), and for the same reason: entrywise functions have diagonal Jacobians.
Step 2 — the inner Jacobian. z=Ax+b\mathbf z=A\mathbf x+\mathbf b is linear, so  z/x=A\ \partial\mathbf z/\partial\mathbf x=A (E×D)(E\times D); the constant b\mathbf b contributes nothing.
Step 3 — multiply, order matters. dfdx=fzzx=diag ⁣(cos(Ax+b))A(E×E)(E×D)=(E×D) \frac{d\mathbf f}{d\mathbf x}=\frac{\partial\mathbf f}{\partial\mathbf z}\,\frac{\partial\mathbf z}{\partial\mathbf x}=\operatorname{diag}\!\big(\cos(A\mathbf x+\mathbf b)\big)\,A\qquad(E\times E)(E\times D)=(E\times D)\ \checkmark Concretely: row ii of AA, scaled by cos(zi)\cos(z_i).

dfdx=diag ⁣(cos(Ax+b))A\dfrac{d\mathbf f}{d\mathbf x}=\operatorname{diag}\!\big(\cos(A\mathbf x+\mathbf b)\big)A, an E×DE\times D Jacobian.

Problem 7medium

Verify two cookbook identities the honest way, entry by entry. (a) For B=[1234]B=\begin{bmatrix}1&2\\3&4\end{bmatrix}, expand xBx\mathbf x^{\top}B\mathbf x and confirm (xBx)/x=x(B+B)\partial(\mathbf x^{\top}B\mathbf x)/\partial\mathbf x=\mathbf x^{\top}(B+B^{\top}). (b) For a=(1,2), b=(3,1)\mathbf a=(1,2)^{\top},\ \mathbf b=(3,1)^{\top}, expand aXb\mathbf a^{\top}X\mathbf b and confirm (aXb)/X=ab\partial(\mathbf a^{\top}X\mathbf b)/\partial X=\mathbf a\mathbf b^{\top}.

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. xBx=x12+2x1x2+3x2x1+4x22=x12+5x1x2+4x22\mathbf x^{\top}B\mathbf x=x_1^2+2x_1x_2+3x_2x_1+4x_2^2=x_1^2+5x_1x_2+4x_2^2
Step 2 — differentiate like any polynomial. /x1=2x1+5x2\partial/\partial x_1=2x_1+5x_2,  /x2=5x1+8x2\ \partial/\partial x_2=5x_1+8x_2, so the gradient row is [2x1+5x2, 5x1+8x2][\,2x_1+5x_2,\ 5x_1+8x_2\,].
Step 3 — the identity's answer. B+B=[2558]B+B^{\top}=\begin{bmatrix}2&5\\5&8\end{bmatrix}, and x(B+B)=[2x1+5x2, 5x1+8x2]\mathbf x^{\top}(B+B^{\top})=[\,2x_1+5x_2,\ 5x_1+8x_2\,] — identical. ✓ (Note 2B2B would give [2x1+4x2, 6x1+8x2][2x_1{+}4x_2,\ 6x_1{+}8x_2] — wrong unless BB is symmetric.)
(b) Step 1 — expand. With a=(1,2), b=(3,1)\mathbf a=(1,2)^{\top},\ \mathbf b=(3,1)^{\top}: aXb=i,jaiXijbj=3X11+X12+6X21+2X22\mathbf a^{\top}X\mathbf b=\sum_{i,j}a_i X_{ij} b_j=3X_{11}+X_{12}+6X_{21}+2X_{22}
Step 2 — differentiate per entry. /Xij=aibj\partial/\partial X_{ij}=a_ib_j: the four coefficients 3,1,6,23,1,6,2 arranged in XX's own shape are (aXb)X=[3162]=ab \frac{\partial(\mathbf a^{\top}X\mathbf b)}{\partial X}=\begin{bmatrix}3&1\\6&2\end{bmatrix}=\mathbf a\mathbf b^{\top}\ \checkmark

Both identities check entry by entry — and (b) is exactly why Section 7's Loss/A\partial\mathrm{Loss}/\partial A came out as the outer product δ(Z)x\boldsymbol\delta^{(Z)}\mathbf x^{\top}.

Problem 8hard

Run the full backward pass on the lecture's function f(x)=x2+ex2+cos(x2+ex2)f(x)=\sqrt{x^2+e^{x^2}}+\cos(x^2+e^{x^2}) at x=1x=1, using the graph a=x2, b=ea, c=a+b, d=c, e=cosc, f=d+ea=x^2,\ b=e^a,\ c=a+b,\ d=\sqrt c,\ e=\cos c,\ 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ˉ\bar f,\bar d,\bar e,\bar c,\bar b,\bar a,\bar x. (c) Confirm xˉ\bar 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 cc and the fork at aa.

Show the full solution
(a) Forward, left to right. a=12=1,b=e1=2.7183,c=1+2.7183=3.7183a=1^2=1,\quad b=e^1=2.7183,\quad c=1+2.7183=3.7183 d=3.7183=1.9283,e=cos(3.7183)=0.8383,f=1.92830.8383=1.0900d=\sqrt{3.7183}=1.9283,\quad e=\cos(3.7183)=-0.8383,\quad f=1.9283-0.8383=1.0900 (Radians throughout — cc is just a number, and cos\cos of it lives on the unit circle, not a protractor.)
(b) Backward, right to left. Start fˉ=1\bar f=1. Node f=d+ef=d+e mails both parents a copy scaled by 11:  dˉ=1, eˉ=1\ \bar d=1,\ \bar e=1.
The fork at cc. cc feeds d=cd=\sqrt c and e=cosce=\cos c, so its mail arrives in two pieces that add: cˉ=dˉ12c+eˉ(sinc)=12(1.9283)+(sin(3.7183))=0.2593+0.5452=0.8045\bar c=\bar d\cdot\frac{1}{2\sqrt c}+\bar e\cdot(-\sin c)=\frac{1}{2(1.9283)}+\big(-\sin(3.7183)\big)=0.2593+0.5452=0.8045 (sin(3.7183)=0.5452\sin(3.7183)=-0.5452 — third quadrant, so the minus signs stack to a plus.)
Through bb, and the fork at aa. bˉ=cˉ1=0.8045\bar b=\bar c\cdot1=0.8045. Then aa feeds b=eab=e^a and c=a+bc=a+b: aˉ=bˉea+cˉ1=0.80452.7183+0.8045=2.1870+0.8045=2.9915\bar a=\bar b\cdot e^{a}+\bar c\cdot 1=0.8045\cdot2.7183+0.8045=2.1870+0.8045=2.9915
The last edge.  xˉ=aˉ2x=2.99152=5.9831\ \bar x=\bar a\cdot 2x=2.9915\cdot2=5.9831.
(c) The closed form agrees. dfdx=(12x2+ex2sin(x2+ex2))(2x+2xex2)x=1=0.8045×7.4366=5.9831 \frac{df}{dx}=\Big(\frac{1}{2\sqrt{x^2+e^{x^2}}}-\sin(x^2+e^{x^2})\Big)\big(2x+2xe^{x^2}\big)\Big|_{x=1}=0.8045\times7.4366=5.9831\ \checkmark Notice the factor 0.80450.8045 is cˉ\bar c, and 2x+2xex2=7.43662x+2xe^{x^2}=7.4366 is what the graph assembled as aˉ2x/cˉ\bar a\cdot2x/\bar c — the closed form and the graph are the same computation, differently organised.

Forward: 1, 2.7183, 3.7183, 1.9283, 0.8383, 1.09001,\ 2.7183,\ 3.7183,\ 1.9283,\ -0.8383,\ 1.0900. Backward: fˉ=1, dˉ=eˉ=1, cˉ=bˉ=0.8045, aˉ=2.9915, xˉ=5.9831=df/dx\bar f=1,\ \bar d=\bar e=1,\ \bar c=\bar b=0.8045,\ \bar a=2.9915,\ \bar x=5.9831=df/dx. ✓

Watch out

Run the same pass at x=2x=2 and ex2=e4=54.6e^{x^2}=e^4=54.6 dominates everything: cˉ=0.8223\bar c=-0.8223 and df/dx=182.87df/dx=-182.87. The companion doc's printed run at x=2x=2 uses cos(58.6)0.83\cos(58.6)\approx0.83, but the true value in radians is 0.46-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 softplus s(z)=ln(1+ez)s(z)=\ln(1+e^{z}) has derivative s(z)=σ(z)s'(z)=\sigma(z) — the sigmoid is softplus's slope. (b) Prove the bridge tanh(z)=2σ(2z)1\tanh(z)=2\,\sigma(2z)-1. (c) Using (b) and σ=σ(1σ)\sigma'=\sigma(1-\sigma), derive tanh=1tanh2\tanh'=1-\tanh^{2} without 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)1/(1+e^{z}), inner slope eze^{z}: s(z)=ez1+ez=1ez+1=σ(z) s'(z)=\frac{e^{z}}{1+e^{z}}=\frac{1}{e^{-z}+1}=\sigma(z)\ \checkmark (dividing top and bottom by eze^{z} in the middle step). So the smooth ramp softplus steepens exactly at the sigmoid's rate — which is why σ\sigma is also called the logistic function.
(b) Build 2σ(2z)12\sigma(2z)-1 and simplify. 2σ(2z)1=21+e2z1=2(1+e2z)1+e2z=1e2z1+e2z2\,\sigma(2z)-1=\frac{2}{1+e^{-2z}}-1=\frac{2-(1+e^{-2z})}{1+e^{-2z}}=\frac{1-e^{-2z}}{1+e^{-2z}} Multiply top and bottom by eze^{z}: ezezez+ez=tanh(z) \frac{e^{z}-e^{-z}}{e^{z}+e^{-z}}=\tanh(z)\ \checkmark In words: tanh is a sigmoid, stretched to run twice as fast and re-centred to fill (1,1)(-1,1).
(c) Differentiate the bridge with Rule 1. Write t=tanhzt=\tanh z and note from (b) that σ(2z)=1+t2\sigma(2z)=\tfrac{1+t}{2}, hence 1σ(2z)=1t21-\sigma(2z)=\tfrac{1-t}{2}. Then tanh(z)=2σ(2z)2=4σ(2z)(1σ(2z))=41+t21t2=(1+t)(1t)=1t2 \tanh'(z)=2\cdot\sigma'(2z)\cdot 2=4\,\sigma(2z)\big(1-\sigma(2z)\big)=4\cdot\frac{1+t}{2}\cdot\frac{1-t}{2}=(1+t)(1-t)=1-t^{2}\ \checkmark — the factor 22 outside is the bridge's scaling, the factor 22 inside is the chain rule through 2z2z.

s=σs'=\sigma;  tanhz=2σ(2z)1\ \tanh z=2\sigma(2z)-1;  tanh=1tanh2\ \tanh'=1-\tanh^{2}, derived purely from σ=σ(1σ)\sigma'=\sigma(1-\sigma).

Remember

All three facts are one family portrait: softplus's slope is σ\sigma, tanh\tanh is a rescaled σ\sigma, and both backward-pass identities (σ(1σ)\sigma(1-\sigma) and 1a21-a^2) 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)=xAs2+λs2E(\mathbf s)=\|\mathbf x-A\mathbf s\|^{2}+\lambda\|\mathbf s\|^{2} (a) Using the cookbook identities, derive sE\nabla_{\mathbf s}E. (b) Set it to zero and show the minimiser solves (AA+λI)s=Ax(A^{\top}A+\lambda I)\,\mathbf s=A^{\top}\mathbf x. (c) Solve numerically for A=[102103],x=[120],λ=1.A=\begin{bmatrix}1&0\\2&1\\0&3\end{bmatrix},\qquad \mathbf x=\begin{bmatrix}1\\2\\0\end{bmatrix},\qquad \lambda=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=IW=I: sxAs2=2(xAs)A\frac{\partial}{\partial\mathbf s}\|\mathbf x-A\mathbf s\|^{2}=-2(\mathbf x-A\mathbf s)^{\top}A The second is the quadratic identity with B=IB=I (so B+B=2IB+B^{\top}=2I): sλss=2λs\frac{\partial}{\partial\mathbf s}\lambda\,\mathbf s^{\top}\mathbf s=2\lambda\,\mathbf s^{\top} Sum:  sE=2(xAs)A+2λs\ \nabla_{\mathbf s}E=-2(\mathbf x-A\mathbf s)^{\top}A+2\lambda\,\mathbf s^{\top}.
(b) Set the gradient to zero (and transpose the row into a column to read it as an equation in s\mathbf s): 2A(xAs)+2λs=0        AAs+λs=Ax        (AA+λI)s=Ax -2A^{\top}(\mathbf x-A\mathbf s)+2\lambda\mathbf s=\mathbf 0 \;\;\Longrightarrow\;\; A^{\top}A\,\mathbf s+\lambda\mathbf s=A^{\top}\mathbf x \;\;\Longrightarrow\;\; \big(A^{\top}A+\lambda I\big)\mathbf s=A^{\top}\mathbf x\ \checkmark This is a stationary point, and it is the minimum: EE is a sum of squares whose quadratic part s(AA+λI)s\mathbf s^{\top}(A^{\top}A+\lambda I)\mathbf s is positive for every s0\mathbf s\neq\mathbf 0 once λ>0\lambda>0 — the bowl opens upward in every direction, and adding λI\lambda I even guarantees the system is invertible when AAA^{\top}A alone is not (Unit 5's nearly-singular warning, answered).
(c) Numbers. AA=[1+4+00+2+00+2+00+1+9]=[52210],AA+I=[62211],Ax=[1+4+00+2+0]=[52]A^{\top}A=\begin{bmatrix}1{+}4{+}0&0{+}2{+}0\\0{+}2{+}0&0{+}1{+}9\end{bmatrix}=\begin{bmatrix}5&2\\2&10\end{bmatrix},\qquad A^{\top}A+I=\begin{bmatrix}6&2\\2&11\end{bmatrix},\qquad A^{\top}\mathbf x=\begin{bmatrix}1{+}4{+}0\\0{+}2{+}0\end{bmatrix}=\begin{bmatrix}5\\2\end{bmatrix} Solve [62211]s=[52]\begin{bmatrix}6&2\\2&11\end{bmatrix}\mathbf s=\begin{bmatrix}5\\2\end{bmatrix}: determinant 664=6266-4=62, so by Cramer (or elimination) s1=5112262=51620.8226,s2=622562=262=1310.0323s_1=\frac{5\cdot11-2\cdot2}{62}=\frac{51}{62}\approx0.8226,\qquad s_2=\frac{6\cdot2-2\cdot5}{62}=\frac{2}{62}=\frac{1}{31}\approx0.0323

sE=2(xAs)A+2λs\nabla_{\mathbf s}E=-2(\mathbf x-A\mathbf s)^{\top}A+2\lambda\mathbf s^{\top}; minimiser (AA+λI)s=Ax(A^{\top}A+\lambda I)\mathbf s=A^{\top}\mathbf x; numerically s(0.8226, 0.0323)\mathbf s\approx(0.8226,\ 0.0323)^{\top}.

Remember

Gradient \to zero \to 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εx=x_0+1\cdot\varepsilon. (a) f(x)=x2exf(x)=x^{2}e^{x} at x0=1x_0=1. (b) f(x)=x2+9f(x)=\sqrt{x^{2}+9} at x0=4x_0=-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\varepsilon^{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)x=(1,\,1). x2=(11, 11+11)=(1,2)ex=(e, e1)=(e,e)x^{2}=(1\cdot1,\ 1\cdot1+1\cdot1)=(1,\,2)\qquad e^{x}=(e,\ e\cdot1)=(e,\,e) x2ex=(1e,  1e+2e)=(e, 3e)x^{2}\cdot e^{x}=(1\cdot e,\ \ 1\cdot e+2\cdot e)=(e,\ 3e) So f(1)=e2.7183f(1)=e\approx2.7183 and f(1)=3e8.1548f'(1)=3e\approx8.1548. Check against the formula the program never used: f=(2x+x2)ex1=3ef'=(2x+x^{2})e^{x}\big|_{1}=3e ✓.
(b) A chain with a square root. Seed x=(4,1)x=(-4,\,1). x2=((4)2, 2(4)1)=(16,8)x2+9=(25,8)x^{2}=\big((-4)^2,\ 2\cdot(-4)\cdot1\big)=(16,\,-8)\qquad x^{2}+9=(25,\,-8) : (25, 8225)=(5, 0.8)\sqrt{\,\cdot\,}:\ \big(\sqrt{25},\ \tfrac{-8}{2\sqrt{25}}\big)=(5,\ -0.8) So f(4)=5f(-4)=5 and f(4)=0.8=45f'(-4)=-0.8=-\tfrac45 — 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 hh — each rule (sum, product, g(a)a˙g'(a)\dot 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)(e,\,3e): f(1)=3e8.1548f'(1)=3e\approx8.1548. (b) (5,0.8)(5,\,-0.8): f(4)=45f'(-4)=-\tfrac45. (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.

Next up

Unit 8 · Taylor & MacLaurin Series →

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.

← All units