03 Β· Calculus: change, direction, chain
Every training loop is the same sentence: look at how wrong you are, work out which way is less wrong, step that way. The middle part is calculus. This module builds the chain β derivative, gradient, curvature, Jacobian, chain rule β and spends its best section on the payoff: a full backpropagation worked with real numbers, so "autograd" becomes arithmetic you can do on paper.
By the end you can
- Read a derivative three ways β slope, sensitivity, local linear approximation β and say which one ML uses.
- Compute partials and the gradient, and explain why the gradient is the direction of steepest increase.
- Run gradient descent by hand and say exactly what the learning rate $\eta$ controls.
- Derive $\sigma'(x)=\sigma(x)(1-\sigma(x))$ in four steps, and say what it does to deep gradients.
- Do a backpropagation by hand on a 2-layer net, then verify it with a finite-difference check.
- Recall the gradients of MSE, sigmoid+BCE, softmax+CE and the $L_2$ penalty on sight.
Why this module exists
"Learning" in machine learning is a physical claim: parameters moved in a direction that made the error smaller. Without a derivative there is no direction β you would search the parameter space by random trial, and random search dies exponentially in dimension. Calculus converts one scalar (how wrong am I?) into a direction (which way is less wrong?), and that conversion is the entire content of every optimiser you will ever run.
The second reason is diagnostic: frameworks differentiate for you, so people skip this module and then cannot explain a loss that will not go down. Vanishing gradients, a saturated activation, a silently wrong loss β those are calculus bugs wearing a software costume. The third reason is that it is short. Almost all of what ML uses fits on one page, and probability, statistics and optimisation (Modules 04β07) all sit on top of it.
Remember β retrieve before you read
Six questions, cold, before any scrollingCold questions β answer from memory, in writing
- What is the derivative of $3x^2$?
- What is the derivative of $x^3 + 2x$?
- What is the derivative of $e^x$?
- A function has $f'(3) = 6$. In plain words: what does that promise near $x=3$, and what does it refuse to promise about $x = 100$?
- Expand $(f \circ g)'(x)$ β the derivative of $f(g(x))$ β from memory.
- What is the gradient of $g(x,y) = x^2 + y^2$ at $(1,2)$? Which way does it point?
Model answers
Only open these after your own answers are written down.
1β3. Derivatives of $3x^2$, $x^3+2x$, $e^x$
4. What does $f'(3) = 6$ mean in words?
5. Expand $(f\circ g)'(x)$
6. Gradient of $x^2+y^2$ at $(1,2)$?
What is a partial derivative, and how is it different from a gradient?
Why does the sigmoid have the derivative it has?
Name the four loss gradients you should not have to look up
Understand β the shape of the idea
Ten sections: what a derivative is, what a gradient buys, why backprop is the chain rule1 Β· Why change, and why now
A training step says: the parameters moved in a direction that made the error smaller. Three words do the work β "moved" (change), "direction" (a vector, not a number), "smaller" (a scalar to compare). Calculus was invented to talk about exactly those three words. ML did not borrow a tool from physics; it rediscovered the same problem with different nouns.
Newton and Leibniz built calculus in the 1600s to describe motion β position changes, velocity changes β because physics had become a question of rates. Two and a half centuries later the same machinery runs the same play: the loss is a function of the parameters, the gradient is its derivative, and the optimiser is a body rolling downhill under a force (the gradient) instead of gravity.
Leibniz gave us the notation we still use ($d$ for differentials, $\int$ for sums), and it survived because it is programmable: $\frac{dy}{dx}$ reads as a ratio of two tiny changes, and when you chain several, the $dx$'s cancel like units in physics. You will watch exactly that cancellation happen in Section 7 β it is not a trick, it is why the notation was chosen.
2 Β· The derivative, from the limit to the intuition
Start with what you can compute: a secant through two points on a curve, slope = rise/run. Then push the points together. The secant pivots toward the curve and becomes the tangent β the straight line that best touches the curve at that one point. That limit is the derivative.
Worked example, $f(x)=x^2$ at $x=3$. The quotient simplifies before the limit β the $h$ in the denominator cancels, which is why the limit exists:
One number, three readings. Keep all three β they get used in different places:
- Slope of the tangent. The geometric picture: draw the curve, draw the line grazing it at $x$, read its steepness. The sign is a statement about direction of increase β negative means downhill as $x$ grows.
- Sensitivity. Output per input, $\Delta\text{out}/\Delta\text{in}$. The engineer's reading: "how much does the loss react to a nudge in this parameter?" A parameter with derivative near $0$ is one the loss does not care about.
- Best local linear approximation. Near $x$ the function is almost the line $f(x_0) + f'(x_0)(x-x_0)$. Everything downstream β gradients, step sizes, convergence arguments β runs on this approximation, not on $f$ itself.
A neural loss is not a plane; it is a wildly curved surface in a million dimensions. So why does subtracting a gradient ever help? Because locally the surface is flat to first order: $f(\mathbf{x}+\Delta)\approx f(\mathbf{x}) + \nabla f^\top\Delta$, and that linear function has an obvious downhill direction, $-\nabla f$. The approximation only holds nearby β which explains two everyday behaviours: take small steps, and re-evaluate the gradient after each one. Momentum, Adam and Newton's method are refinements of "how far and how often to step", never a replacement for "the gradient is a local linear model".
3 Β· Rules, each with a reason
You memorised these once for an exam and lost them. This time attach each rule to the reason it exists.
Product rule β where the two terms come from. Nudge both factors and expand, exactly like $(a+b)^2$: each factor gets a turn to change while the other sits still.
Quotient rule (losses and normalisations divide), and the chain rule for composition β the two you will use most:
The table is limited to the functions ML actually differentiates:
| Function | Derivative | Where you meet it |
|---|---|---|
| $x^n$ | $n x^{n-1}$ | Power losses, $L_2$ penalties, polynomial features |
| $1/x$ | $-1/x^2$ | Every log-derivative, normalisation terms |
| $e^x$ | $e^x$ | Exponentials in softmax, natural parameterisations |
| $\ln x$ | $1/x$ | The most important row. Log-likelihoods: products become sums and derivatives become $1/x$ |
| $\log_b x$ | $1/(x \ln b)$ | Base-2 cross-entropy, bits (Module 06) |
| $\sigma(x) = \frac{1}{1+e^{-x}}$ | $\sigma(x)(1-\sigma(x))$ | Logistic regression, gates, attention masks |
The $\ln x$ row deserves one sentence: because $\frac{d}{dx}\ln x = \frac{1}{x}$, differentiating a log-likelihood replaces nasty products with sums and simple ratios. That is why we maximise log-likelihoods β the maths gets cheap exactly where it matters.
The sigmoid derivative, in four steps. Reproduce this without notes; it appears in every derivation of logistic regression:
- Write $\sigma(x) = (1+e^{-x})^{-1}$ β a power of something, so the chain rule applies.
- Differentiate: $\sigma'(x) = -(1+e^{-x})^{-2}\cdot(-e^{-x}) = \frac{e^{-x}}{(1+e^{-x})^2}$ (the minus signs cancel).
- Split the numerator with $e^{-x} = (1+e^{-x})-1$, giving $\frac{1}{1+e^{-x}} - \frac{1}{(1+e^{-x})^2}$.
- Both pieces are powers of $\sigma$: $\sigma'(x) = \sigma(x) - \sigma(x)^2 = \sigma(x)(1-\sigma(x))$.
$\sigma(1-\sigma)$ peaks at $0.25$ (when $\sigma=0.5$) and falls to nearly $0$ as $\sigma$ saturates at $0$ or $1$. Every saturated sigmoid kills up to 75% of the gradient passing through, and ten in a row leave $0.25^{10}\approx 0.000001$. Nothing is wrong with your code β that is the multiplication of sensitivities doing what Section 7 says it does. It is why ReLU took over deep nets, and why you should always ask "what is the derivative of this activation?" before stacking it.
4 Β· Partial derivatives and the gradient
Models have millions of parameters, so $f:\mathbb{R}^n \to \mathbb{R}$. A partial derivative freezes all but one coordinate and asks the single-variable question about that one:
The gradient collects all of them into one vector β a direction with one entry per parameter, the same shape as the weights, which is what makes subtraction legal:
Three geometric facts, each sketchable in ten seconds:
- Steepest increase. The gradient points where $f$ grows fastest at that point; descent goes against it.
- Perpendicular to level sets. Draw the contour where $f$ is constant β the gradient sticks straight out of it, because moving along a contour does not change $f$.
- Everything else is a projection. The rate of change along a unit direction $\mathbf{u}$ is $\nabla f\cdot\mathbf{u} = \|\nabla f\|\cos\theta$, largest when $\theta=0$ β that proof of "steepest", not a claim.
Worked example. $g(x,y)=x^2+y^2$ at $(1,2)$: differentiating $x^2$ with $y$ held fixed gives $2x$, and vice versa.
One gradient descent step subtracts a scaled version. $\eta$ (eta) is the learning rate: it converts a gradient (slope units) into a step (parameter units).
Two opposite errors. Using the raw gradient as the step ($\eta = 1$) overshoots: on $x^2+y^2$ each update multiplies the position by $(1-2\eta) = -1$, so you bounce between $(1,2)$ and $(-1,-2)$ forever. Choosing $\eta$ too large makes $|1-2\eta| \gt 1$ and the iterates run away β the loss you were minimising explodes, and the fix is a smaller learning rate, not a different loss. Pass 3 runs $\eta = 0.1$, $0.001$ and $1.1$ so you can watch convergence, crawling and divergence on one plot.
5 Β· Second derivatives: curvature, minima and saddles
The first derivative says which way is downhill right now; the second says whether downhill is getting steeper or flatter β the curvature, and with it the local shape:
With many variables there is a second derivative per pair of coordinates, so they organise into a symmetric matrix β the Hessian:
At a critical point ($\nabla f = 0$) the test generalises: $H$ positive definite β every direction curves upward β local minimum; negative definite β maximum; mixed signs β a saddle point, which looks like a minimum from one angle and a maximum from another. In high dimensions saddles are abundant and local minima are rare β one sentence now, developed in Module 07.
In plain English: the first term is where you are, the second is the tilt under your feet (zero at a critical point β which is why first-order methods stall there), the third is how the ground bends. Newton's method uses all three to jump to the bottom of a quadratic bowl; gradient descent uses only the second and inches downhill. And a large Hessian means the gradient changes fast over short distances β a narrow valley demanding small steps β while a flat plain tolerates big ones. That is the whole intuition behind Adam: rescale each coordinate's step by an estimate of its curvature.
6 Β· Jacobian: gradients of vector-valued functions
Gradients are for scalar outputs; layers return vectors. For $f:\mathbb{R}^d \to \mathbb{R}^k$, stack the $k$ output gradients as rows and you get the Jacobian, a $k \times d$ matrix:
Shapes, because shapes are 80% of the bugs: outputs along rows, inputs down columns. When $k=1$ the Jacobian collapses to one row β the gradient written as a $1\times d$ matrix. A gradient is a degenerate Jacobian, not a different species. And for a single linear layer $f(\mathbf{x}) = W\mathbf{x}$ with $W \in \mathbb{R}^{k\times d}$, the Jacobian is the weight matrix itself: $J = W$.
Why you should care: a whole layer's local behaviour is a matrix, so the vector chain rule is a product of these matrices (Section 7). But you never want to build them β a million-by-million layer has $10^{12}$ entries. Frameworks instead compute only $J$ times a vector (a Jacobianβvector product), in time proportional to the function itself. That trick is reverse-mode automatic differentiation, named in Section 10.
7 Β· The chain rule is backpropagation
Scalar case first β the formula from the warm-up, stated again on purpose:
Now the vector version, which is what backprop runs. If scalar $L$ is computed from an intermediate vector $\mathbf{y} = \mathbf{y}(\mathbf{x})$, the gradient w.r.t. $\mathbf{x}$ is the incoming gradient multiplied by the transposed Jacobian of the local step:
A full backpropagation, with numbers. The smallest network that still has a hidden non-linearity: one input $x$, one sigmoid, one output, squared loss.
Walk the chain backwards, symbols first, one factor per edge. For $w_2$: it reaches $L$ only through $z_2$, and $z_2 = w_2 a_1$ so $\partial z_2/\partial w_2 = a_1$:
For $w_1$ the path is longer β through $z_2$, then $a_1$, then $z_1$ β so four factors multiply:
Numbers: $x=1$, $w_1=0.5$, $w_2=1.2$, $y=1$. Forward first β these are the values the backward pass reuses:
Both gradients are negative: increasing either weight lowers $L$ here, which is exactly what a descent step will do. Pass 3 checks both numbers against finite differences.
The backward pass consumed $a_1$, $z_1$, $z_2$, $w_2$, $x$ β every value already computed on the way forward and merely reused. Each edge costs one multiplication, so the backward pass costs about one forward pass: training β 3Γ inference, not 3Γ per parameter. The counterweight: the same multiplications are how gradients vanish. Chain $\sigma' \le 0.25$ ten times and you are multiplying by $\approx 10^{-6}$; chain large derivatives and they explode. Same mechanism, opposite sign β residual connections (Module 10) are the architectural fix.
A gradient is local: it describes the surface within a step or two of where you stand. It does not say where the minimum is, what the loss will be after 100 updates, or whether a better basin exists elsewhere. That is why you recompute it every iteration, why an oversized learning rate "suddenly" diverges (you left the region where the local model held), and why "the gradient says this direction is bad" really means "bad from here". $f'(3)=6$, all over again, in $n$ dimensions.
8 Β· Gradients of the losses you will actually differentiate
These four are the payoff of the module. Learn to re-derive them, not just recite them β each is five lines of Section 3's rules plus a chain rule.
Derivation, shapes checked. Expand: $L = \frac{1}{n}\sum_{i=1}^{n}(x_i^\top w - y_i)^2$. Differentiating w.r.t. $w_j$, the chain rule brings down $2(x_i^\top w - y_i)$ and $\partial(x_i^\top w)/\partial w_j = x_{ij}$ (only $x_i$'s $j$-th coordinate touches $w_j$). So $\frac{\partial L}{\partial w_j} = \frac{2}{n}\sum_i (Xw-y)_i x_{ij}$ β column $j$ of $X$ times the residual vector, i.e. row $j$ of $X^\top(Xw-y)$. Shapes: $X$ is $n\times d$, $w$ is $d$, $y$ is $n$; so $Xw-y$ is $n$ and $X^\top$ ($d\times n$) times it is $d$ β a gradient the size of $w$, as it must be. In code: (2/n) * X.T @ (X @ w - y).
Sigmoid + binary cross-entropy. Differentiate with respect to $z$ (we stop at the pre-activation and let backprop carry it on), using $\frac{d}{dz}\ln\sigma = \frac{\sigma'}{\sigma}$ and $\frac{d}{dz}\ln(1-\sigma) = \frac{-\sigma'}{1-\sigma}$:
Those denominators are the cancellation to watch: $\sigma'/\sigma = 1-\sigma$ and $\sigma'/(1-\sigma) = \sigma$. Multiply out and two terms remain:
The beautiful cancellation: an activation whose derivative is built from its own output, paired with a loss containing that output inside logarithms, cancels to the simplest possible gradient. Not luck β maximum likelihood wearing a nice outfit β and the reason sigmoid and cross-entropy are never casually swapped for other pairings.
Sketch. The softmax Jacobian is $\frac{\partial p_c}{\partial z_j} = p_c(\mathbb{1}[c=j] - p_j)$. Substitute into $\frac{\partial L}{\partial z_j} = -\sum_c \frac{y_c}{p_c}\frac{\partial p_c}{\partial z_j}$: the $p_c$ in the denominator cancels the one in the Jacobian, leaving $-y_j + p_j\sum_c y_c = p_j - y_j$, since $\sum_c y_c = 1$. Same cancellation, one dimension up.
One line: $\|w\|^2 = \sum_j w_j^2$ and each coordinate gives $2w_j$. Practical consequence: the weight-decay step is $w \leftarrow w - \eta\,2\lambda w = (1-2\eta\lambda)w$ β a multiplicative shrink every iteration, which is what "decay" should mean.
$\tfrac{2}{n}X^\top(Xw-y)$, $\sigma(z)-y$, $\mathbf{p}-\mathbf{y}$, $2\lambda w$. Between them: linear regression, logistic regression, every neural classifier, $L_2$ regularisation. When a loss misbehaves, the fastest debug is re-deriving its gradient on paper and comparing with the code β exactly the finite-difference check in Pass 3.
9 Β· Integrals: the other half, used more rarely but needed
Differentiation splits a change into rates; integration rebuilds a whole from rates β addition in the limit. Geometrically $\int_a^b f(x)\,dx$ is the signed area under the curve, defined as the limit of summing ever-thinner rectangles: $\int_a^b f(x)\,dx = \lim_{k\to\infty}\sum_{i=1}^{k} f(x_i^*)\,\Delta x$.
No proof β this notebook does proofs only when they pay rent β but the paragraph worth remembering: if $F$ is an antiderivative of $f$, the accumulated area from $a$ to $x$ has derivative $f(x)$, because it grows exactly as fast as the curve is tall. Two functions with the same derivative differ by a constant; fixing it at one endpoint gives $F(b)-F(a)$. That is the whole theorem, and it is why "find the antiderivative" solves "find the area".
The most common integral in ML is the expectation β the continuous version of the probability-weighted average $\sum_x x\,P(X=x)$, with sums replaced by areas:
Where else ML meets integrals, in increasing order of frequency:
- Expectation of a function. $\mathbb{E}[g(X)] = \int g(x)\,p(x)\,dx$ β variance, risk, and every "average over the data distribution" statement you will meet.
- Probability is volume. $P(a \le X \le b) = \int_a^b p(x)\,dx$: a probability is the area under the density, so densities must integrate to $1$ β the constraint that produces every normalising constant in every distribution.
- The Gaussian integral, once. $\int_{-\infty}^{\infty} e^{-x^2}\,dx = \sqrt{\pi}$ β a beautiful fact about a boring-looking integrand, and the origin of the Gaussian's $\sqrt{2\pi\sigma^2}$.
So the "mysterious" $\sqrt{2\pi\sigma^2}$ is not decoration β it is exactly the number required to make the integral equal $1$. Module 04 completes the picture: expectation, variance, and where least squares comes from.
10 Β· Symbolic vs numeric vs automatic differentiation
You need derivatives in code. There are three ways to get them; knowing all three lets you choose, and lets you recognise which one your framework is running.
| Method | How | Failure mode |
|---|---|---|
| Numeric (finite differences) | Approximate the limit: $\frac{f(x+h)-f(x)}{h}$ | Subtractive cancellation: too small an $h$ and $f(x+h)-f(x)$ loses digits to float noise; too large and truncation error dominates. Ceiling β $10^{-8}$ |
| Symbolic (SymPy) | Apply algebra rules to the expression, like a person | Expression swell on real models; cannot differentiate arbitrary Python control flow |
| Automatic (PyTorch, JAX) | Apply the chain rule to a recorded computation graph | Needs differentiable ops; memory for saved intermediates |
Autodiff is what ML uses, and it is neither of the two things people assume. It is not numerical β no approximation, no cancellation, exact to floating-point precision. And it is not symbolic β it never builds a giant expression. It stores the operations you ran (the graph), then walks that graph backwards applying the chain rule one node at a time, exactly as you did in Section 7, at a small constant factor over the forward pass whatever the dimension. requires_grad=True starts the recording; loss.backward() runs the walk. The word you will see is autograd β now you know it means "the chain rule on a computation graph".
loss = criterion(model(x), y) builds the graph and computes $L$ (Section 7's forward pass). opt.zero_grad() clears old gradients, because they accumulate. loss.backward() fills param.grad with $\nabla_\theta L$. opt.step() applies $\theta \leftarrow \theta - \eta\nabla_\theta L$. Nothing else happens in training β everything else in deep learning is about making those four lines behave.
Implement β check the math against the machine
Type these; do not copy. Then change one number and predict the resultBlock 1 Β· The gradient check every engineer runs
Analytic gradient vs finite differences. If they disagree by more than about $10^{-8}$, one of them is wrong β in practice, your code.
import numpy as np
rng = np.random.default_rng(0)
# central difference: symmetric error is O(h^2), twice as good as the naive version
def fd_grad(fn, p, h=1e-5):
g = np.zeros_like(p)
for i in range(p.size):
e = np.zeros_like(p); e[i] = h
g[i] = (fn(p + e) - fn(p - e)) / (2 * h)
return g
# 1) a toy function you can differentiate by eye
f = lambda p: p[0]**2 + p[1]**2
grad_f = lambda p: np.array([2*p[0], 2*p[1]])
p = np.array([1.5, -2.0])
print("f analytic:", grad_f(p), " numeric:", fd_grad(f, p),
" err:", np.abs(grad_f(p) - fd_grad(f, p)).max()) # expect < 1e-8
# 2) the real thing: MSE on synthetic data
n, d = 20, 4
X = rng.normal(size=(n, d))
y = X @ rng.normal(size=d) + 0.1 * rng.normal(size=n)
w = rng.normal(size=d)
mse = lambda w: np.mean((X @ w - y)**2)
grad_mse = lambda w: (2/n) * X.T @ (X @ w - y)
print("MSE analytic:", np.round(grad_mse(w), 6))
print("MSE numeric :", np.round(fd_grad(mse, w), 6))
print("max error :", np.abs(grad_mse(w) - fd_grad(mse, w)).max()) # expect < 1e-8
Both errors land near $10^{-11}$. If you ever see $10^{-3}$, you have found a real bug β a missing factor of $2$, a forgotten $1/n$, a transposed matrix. This is a gradient check, and it is how any new custom layer gets validated before anyone trusts a training run to it.
Block 2 Β· Gradient descent from scratch, three learning rates
import numpy as np
import matplotlib.pyplot as plt
grad = lambda p: 2 * p # nabla f for f(x,y) = x^2 + y^2
def descend(eta, n_steps=30, start=(2.5, -2.0)):
p = np.array(start, float); path = [p.copy()]
for _ in range(n_steps):
p = p - eta * grad(p) # the update rule, nothing else
path.append(p.copy())
return np.array(path)
# contour map of the loss, with each trajectory drawn on top
xs = np.linspace(-3, 3, 200); X, Y = np.meshgrid(xs, xs)
plt.contour(X, Y, X**2 + Y**2, levels=12)
for eta, style in [(0.1, '-'), (0.001, '--'), (1.1, ':')]:
path = descend(eta)
plt.plot(path[:, 0], path[:, 1], style, marker='o', ms=3, label=f"eta={eta}")
print(f"eta={eta:<6} after 30 steps: {np.round(path[-1], 4)}")
# eta=0.1 -> [ 0.0031 -0.0025] converged: factor per step = 1-2*eta = 0.8
# eta=0.001 -> [ 2.3543 -1.8834] crawling: factor 0.998, barely moves
# eta=1.1 -> [ 593.44 -474.75] diverging: factor -1.2, |factor| > 1
plt.legend(); plt.axis('equal'); plt.show()
On this function each step multiplies the position by $(1-2\eta)$, so all three outcomes read off one number: $0.8$ converges, $0.998$ crawls, $-1.2$ diverges. Real losses are not quadratics, but the local picture is the same β and this plot is what to sketch when someone asks why their loss exploded after they raised the learning rate.
Block 3 Β· Backprop by hand, then verified
import numpy as np
sig = lambda z: 1 / (1 + np.exp(-z))
def loss_and_grad(w1, w2, x, y):
z1 = w1 * x
a1 = sig(z1) # save it: sigma'(z1) is built from a1
z2 = w2 * a1
L = (z2 - y)**2
# backward pass β one factor per edge, in reverse
dL_dz2 = 2 * (z2 - y)
dL_dw2 = dL_dz2 * a1
dL_dz1 = dL_dz2 * w2 * a1 * (1 - a1) # chain through the sigmoid
dL_dw1 = dL_dz1 * x
return L, np.array([dL_dw1, dL_dw2])
x, y, w = 1.0, 1.0, np.array([0.5, 1.2])
L, g = loss_and_grad(*w, x, y)
print(f"L = {L:.6f} grad = {np.round(g, 6)}")
# L = 0.064034 grad = [-0.142722 -0.315025] β matches the paper derivation
# now force the machine to agree
loss_only = lambda w1, w2: loss_and_grad(w1, w2, x, y)[0]
h = 1e-6
fd = np.array([(loss_only(*(w + h*np.eye(2)[i])) - loss_only(*(w - h*np.eye(2)[i]))) / (2*h)
for i in range(2)])
print("finite diff:", np.round(fd, 6), " max error:", np.abs(fd - g).max()) # ~1e-11
The two agree to twelve decimal places. That is the whole trust story of deep learning: the framework's backward() performs the same multiplications you just did, and you can audit it on any function you write.
- Implement $\frac{\partial L}{\partial z} = \sigma(z) - y$ for binary cross-entropy and verify it against a finite-difference check of the summed loss on $z = (-2.0,\, 0.0,\, 1.5)$, $y = (0, 1, 1)$. Expected agreement: $\approx 10^{-10}$.
- Then break it. Average the loss over the $n$ samples (
L.mean()) but keep the summed gradient $\sigma(z) - y$. Re-run the finite difference on the mean loss and divide your gradient by theirs: every ratio is exactly $n$ β here $3.0$. - Why this matters: mean-vs-sum mismatches are invisible in unit tests (the direction is still right, so the loss still falls) and surface weeks later as a run that only works at $\eta = 10^{-4}$. Your effective learning rate silently became $n\times\eta$. The fix is one line β divide by $n$ β if you know to look.
Prove it, then start Module 04
Answer first, then open the feedbackMultiple choice β instant feedback
1. You have computed $\nabla f$ at a point. Which statement is true?
2. Gradient descent on $g(x,y) = x^2 + y^2$ at $(1,2)$ with $\eta = 0.1$. Where do you land after one step?
3. What does backpropagation actually compute?
4. At a critical point of $f$, the Hessian $H$ is positive definite. What follows?
5. You find a point where $f'(x_0) = 0$ and $f''(x_0) = 0$. What can you conclude?
6. Which statement about plain gradient descent is true?
Open questions β answer aloud, without notes
- Explain $f'(3) = 6$ to a colleague: what does it promise about $x = 3.01$, and what does it refuse to promise about $x = 100$?
- Derive $\sigma'(x) = \sigma(x)(1-\sigma(x))$ from the definition, in four lines, without looking.
- Why does the product rule have two terms? Build them from $(f+df)(g+dg)$.
- For $g(x,y) = x^2+y^2$ at $(1,2)$: gradient, descent direction, and one step with $\eta = 0.05$.
- What is the Jacobian of a layer $f(\mathbf{x}) = W\mathbf{x}$? When does reverse-mode autodiff beat forward-mode, and why?
- Write $\partial L/\partial w_1$ for the 2-layer sigmoid net as a product of four factors, saying what each corresponds to in the graph.
- Why does sigmoid + cross-entropy give exactly $\sigma(z) - y$? Name the two factors that cancel.
- You set $h = 10^{-12}$ in a finite-difference check and the error got worse than with $h = 10^{-6}$. Explain why.
Re-answer these in 1 / 3 / 7 days β cold, no notes. The derivatives you cannot re-derive are the ones you have not learned yet.
This module is the "why"; the companion notebook is the "what it does". ML module 05 Β· Regression & gradient descent runs the update rule on a real dataset; ML module 06 Β· Logistic regression uses the $\sigma(z)-y$ gradient you derived in Section 8; and ML module 10 Β· Neural networks & deep learning is where backpropagation stops being a worked example and becomes the thing you train with.