A loss is a landscape, and the derivative is the slope under your feet. Subtract a small multiple of it from every weight — w = w − lr · dL/dw — and the error falls. That loop is training.
Draw a line through two nearby points on a curve and shrink the gap. The secant pivots until it becomes the tangent at one point — and its slope is the derivative f'(x). For x², that slope is 2x: at x = 2 it is 4.
f'(2) = 4 nudge x by 0.001 → y moves ≈ 0.00402 / PARTIALS FREEZE THE REST
One knob at a time.
A loss depends on every weight at once. ∂L/∂w asks how the loss responds to one weight while all the others are held still. For f(x, y) = x² + 3xy + y², ∂f/∂x = 2x + 3y and ∂f/∂y = 3x + 2y.
Collect the partials into one vector and you get ∇L, the direction of steepest ascent. Training subtracts a multiple of it from every weight. Too large a step and the loss bounces; too small and it crawls.
w ← w − lr · ∂L/∂w
MENTAL MODEL IN ONE SENTENCE
Training is a loop: predict, measure the loss, read the slope of the loss with respect to every weight, step downhill, repeat — and calculus is the part that tells you which way downhill is.
By the end you will be able to read dL/dw and ∂L/∂w without fear, explain why the gradient points uphill, predict what a learning rate does before you run it, and check any gradient by hand with a finite difference.
01
THE SLOPE AT A POINT
How fast is it changing right now?
A derivative answers one question: nudge the input a hair — how much does the output move? The answer is the slope of the curve at that exact point.
Take two points on a curve and draw a line through them: that is a secant line, and its slope is the average rate of change over the gap. Shrink the gap and the secant pivots toward the tangent at a single point. The limit of that slope as the gap goes to zero is the derivative, written f’(x).
For f(x) = x², the derivative is f’(x) = 2x. At x = 2 the slope is 4: nudge x right by 0.001 and f rises by about 0.004. At x = 0 the slope is 0 — the curve is flat, and you are standing at the bottom of the bowl.
From secant to tangent
Drag the green point along the curve, then shrink h. The orange secant line through the two nearby points becomes the blue tangent line — and its slope becomes the derivative.
x = 1.200 f(x) = 1.440
secant slope = 2.40000
tangent slope = 2.40000
gap = 4.44e-16
as h → 0 the gap → 0: the secant IS the
tangent, and its slope is f'(x).
Numerically h never reaches zero — a tiny h loses precision to floating-point rounding. The best real-world h sits around 1e-5 to 1e-7. The next chapter shows exactly where it breaks.
Gradient descent steps are proportional to the slope, so the walk slows down by itself as it approaches the minimum. The steps change the input x; the height f(x) follows.
Derivation: the derivative of x² from the definition, then the rules you get for free
Definition: f’(x) = lim as h → 0 of [f(x + h) − f(x)] / h. That is the slope of a line through two points a gap h apart, as the gap shrinks to nothing.
Let h → 0: only 2x survives, so f’(x) = 2x. At x = 2 the slope is 4, exactly as the figure says.
The same expansion with xⁿ gives the power rule: d(xⁿ)/dx = n·xⁿ⁻¹. Two more facts you will use constantly: the derivative of a constant is 0, and derivatives add term by term.
d/dx (x³) = 3x² at x = 2: 12
d/dx (5x² + 3x + 7) = 10x + 3 the constant vanishes
d/dx (eˣ) = eˣ the defining property of e
d/dx (ln x) = 1/x because ln undoes exp
numeric nudge check for f(x) = x² at x = 2:
f(2.001) − f(2) 4.004001 − 4
--------------- = -------------- = 4.001 → f'(2) = 4 ✓
0.001 0.001
02
DERIVATIVES IN CODE
Exact, approximate, or automatic.
There are three ways to get a slope: derive it by hand, approximate it with nearby points, or let a framework differentiate the code itself. The middle one is the only one you can check with a calculator — and the one with a hidden failure mode.
The analytic derivative is a formula: for x², it is 2x. Exact and fast — but somebody has to derive it. The numerical derivative skips the algebra: evaluate the function at two nearby points and take the slope of the line between them. The central form (f(x + h) − f(x − h)) / 2h is more accurate than a one-sided version because the errors from the two sides cancel.
Frameworks take a third road: automatic differentiation (autodiff) applies the chain rule to the code itself, giving exact derivatives without writing any calculus by hand. Lesson 5 builds it. Everything in this chapter is how you verify that machinery: compare its answer against a finite difference and watch them agree.
Finite-difference check
Compare the analytic derivative with the central difference (f(x+h) − f(x−h)) / 2h as h shrinks from 10⁻¹ to 10⁻¹⁶. The error falls, then explodes — that explosion is floating-point cancellation.
f(x) = x² x = 2
analytic f'(x) = 4.0000e+0
central (f(x+h) − f(x−h)) / 2h
= 4.0000e+0 error 8.88e-16
forward (f(x+h) − f(x)) / h
= 4.1000e+0 error 1.00e-1
⚠ h is large: the secant is still far from
the tangent, so the approximation is biased.
Rule of thumb: h between 1e-5 and 1e-7 for float64. Frameworks never use this in production — they work out exact derivatives symbolically (autodiff), and use finite differences only to check them.
Subtracting the two expansions kills every even-power term, including the ½f″h² term that dominated the forward difference. With h = 0.001, an error “like h” is around 0.001 while “like h²” is around 0.000001 — a thousand times better from the same two function evaluations.
03
PARTIAL DERIVATIVES
Millions of knobs. One at a time.
A loss depends on every weight at once. A partial derivative freezes all of them except one and asks the only question training needs: how does the loss respond to this single knob?
For a function of one variable we write df/dx. For a function of many variables we write ∂f/∂x — the curly “d” means partial: differentiate with respect to x while pretending every other variable is a constant. In ML the loss depends on the weights, so ∂L/∂w is the loss’s sensitivity to one weight, with all the others held still.
Take f(x, y) = x² + 3xy + y². For ∂f/∂x, treat y as a fixed number: x² becomes 2x, 3xy becomes 3y (a constant times x), and y² becomes 0. So ∂f/∂x = 2x + 3y. Likewise ∂f/∂y = 3x + 2y. At the point (1, 2) that is [2 + 6, 3 + 4] = [8, 7].
The gradient console
Pick a function and a point. Each row shows one partial derivative: its formula, its exact value, a numerical check, and the update it would trigger.
f(x,y) = x² + 3xy + y²
f(1, 2) = 11.0000
gradient ∇f = [8.000, 7.000]
step with lr = 0.1:
x ← 1 − 0.1·8.00 = 0.200
y ← 2 − 0.1·7.00 = 1.300
each partial freezes the other variable and differentiates a one-variable function
partial
formula
exact
numeric (2h = 0.00002)
∂f/∂x
2x + 3y
8.0000
8.0000
∂f/∂y
3x + 2y
7.0000
7.0000
The exact and numeric columns agree to four decimals because the central difference is exact for quadratics. That is the check backpropagation implementations are verified against.
Derivation: partial derivatives, one variable at a time
The trick is to replace the frozen variable by a number and forget it is a variable at all.
For ∂f/∂x, pretend y = 5. Then f = x² + 15x + 25, a one-variable function of x.
Differentiate term by term: x² → 2x; 15x → 15 = 3y; 25 → 0. So ∂f/∂x = 2x + 3y.
For ∂f/∂y, pretend x = 1. Then f = 1 + 3y + y², so ∂f/∂y = 3x + 2y.
At (1, 2): ∂f/∂x = 2·1 + 3·2 = 8 and ∂f/∂y = 3·1 + 2·2 = 7.
numeric check with central differences, h = 1e-5:
∂f/∂x ≈ [f(1+h, 2) − f(1−h, 2)] / 2h
= (11.00008001 − 10.99991999) / 0.00002 = 8.0000 ✓
analytic: 2(1) + 3(2) = 8
∂f/∂y ≈ [f(1, 2+h) − f(1, 2−h)] / 2h
= (11.00007000 − 10.99993000) / 0.00002 = 7.0000 ✓
analytic: 3(1) + 2(2) = 7
the two partials answer different questions:
∂f/∂x: if x moves and y is pinned, f moves ~8 per unit
∂f/∂y: if y moves and x is pinned, f moves ~7 per unit
Notice that neither partial tells you what happens when both move at once. That is the job of the gradient, which collects them into one vector.
04
THE GRADIENT
Uphill is a direction. We want the other one.
Collect every partial derivative into one vector and you have the gradient. It points in the direction of steepest ascent — so training walks in the exactly opposite direction.
The gradient, written ∇f, is the list of all partial derivatives: ∇f = [∂f/∂x, ∂f/∂y, …]. For f(x, y) = x² + y², it is [2x, 2y]. At the point (1, 1) that is [2, 2]: moving away from the origin in any direction raises f, and the direction that raises it fastest is the diagonal. At the bottom of the bowl, (0, 0), the gradient is [0, 0] — flat in every direction.
Two facts make the whole training loop work. First, the gradient points uphill. Second, it is perpendicular to the contour lines of f, so it is the most efficient direction to move if you want to change f quickly. To decrease the loss, take the gradient and flip its sign.
The bowl, valley and saddle in the lab are teaching models — a real network’s loss lives in millions of dimensions and cannot be drawn. The rule being demonstrated is exactly the same: one partial derivative per parameter, collected into one vector.
A gradient field you can poke
Click anywhere to sample a point. Blue arrows show the downhill direction −∇f; the orange circle marks the function’s special point. The contour lines are level sets: the gradient is always perpendicular to them.
Each partial derivative is the slope along one axis with the other frozen. Together they form the gradient, which always points uphill — so training takes its step in the opposite direction.
Point
∇f for x² + y²
−∇f (descent)
What it means
(2, 1)
[4, 2]
[−4, −2]
steepest way up is right and slightly up; downhill is the reverse
(1, 1)
[2, 2]
[−2, −2]
the diagonal, straight back toward the bowl’s bottom
(0, 0)
[0, 0]
[0, 0]
flat everywhere: you are at the minimum
Derivation: why the gradient points in the steepest direction
Forget pictures for a second and do the arithmetic. Suppose you move a tiny step (dx, dy) away from the point (x, y). The change in f is, to first order:
df = (∂f/∂x)·dx + (∂f/∂y)·dy = ∇f · (dx, dy)
That is a dot product between the gradient and your step. A dot product is largest when the two vectors point the same way, so the step that increases f fastest is the one parallel to ∇f. The step that decreases f fastest is −∇f. Every optimization algorithm in deep learning is a variation on that one observation.
f(x, y) = x² + y², at (1, 1):
∇f = [2, 2]
step 1 in +x: df ≈ 2·1 + 2·0 = 2
step 1 in +y: df ≈ 2·0 + 2·1 = 2
step 1 along [1, 1]/√2 ≈ [0.707, 0.707]:
df ≈ 2·0.707 + 2·0.707 = 2.83 ← the biggest
so the direction of steepest ascent is ∇f's direction,
and the direction of steepest descent is −∇f.
05
WALK DOWNHILL
The update rule that trains everything.
Subtract a small multiple of each partial derivative from its weight. Repeat. That one line, run over every knob, is the whole of neural network training.
The rule is w ← w − lr · ∂L/∂w, applied to every weight at once. The learning ratelr scales the step. The partial derivative says which way increases the loss, so subtracting moves the weight the other way. Because the slope flattens near a minimum, the steps shrink on their own as the model approaches the answer — no schedule required.
Get lr wrong and the curve tells you. Too small: hundreds of tiny steps and still far away. Too large: each step overshoots the valley, the loss bounces between the walls, and past a certain point it grows without bound. The lab is the fastest way to build that intuition.
Gradient descent stepper
Pick a loss curve and a learning rate, then step. Each step subtracts lr × slope from x. Too small and it crawls; too large and it bounces or diverges.
step 0
x = 4.00000 f(x) = 16.00000
slope f'(x) = 8.00000
next x = x − lr·f'(x) = 3.20000
On x², lr = 0.1 converges smoothly, lr ≈ 1 oscillates forever (x alternates sign), and lr > 1 diverges. On the double well, the start point decides which of the two valleys you fall into.
Derivation: the gradient of linear regression — where dw = 2·err·x comes from
Model: prediction = w·x + b. Loss on one example: (w·x + b − y)². Call the bracket err.
The loss is err² — a composition. Apply the chain rule: d(err²)/dw = 2·err · d(err)/dw.
Differentiating w·x + b − y with respect to w treats x, b and y as constants, so d(err)/dw = x. Result: ∂L/∂w = 2·err·x.
For the bias, d(err)/db = 1, so ∂L/∂b = 2·err.
Over a batch the loss is the mean, and the derivative of a mean is the mean of derivatives: dw = (1/n) Σ 2·errᵢ·xᵢ.
sanity check: x = 3, y = 7, w = 1, b = 1
prediction = 1·3 + 1 = 4 err = 4 − 7 = −3 loss = 9
∂L/∂w = 2·(−3)·3 = −18 → subtract a negative: w increases ✓
∂L/∂b = 2·(−3) = −6 → b increases too ✓
we underpredicted, so both knobs should move up.
numeric check of ∂L/∂w at (w=1, b=1), h = 1e-5:
L(1+h) = (3(1+h) + 1 − 7)² = (−3 + 3h)² ≈ 8.999820
L(1−h) = (3(1−h) + 1 − 7)² = (−3 − 3h)² ≈ 9.000180
[L(1+h) − L(1−h)] / 2h = −18.0000 ✓
The same loop, by hand — Pythonpython
xs = [1.0, 2.0, 3.0, 4.0, 5.0]
ys = [3.0, 5.0, 7.0, 9.0, 11.0] # truth: y = 2x + 1
w, b, lr = 0.0, 0.0, 0.01for epoch in range(200):
dw = db = loss = 0.0for x, y in zip(xs, ys):
err = (w * x + b) - y # prediction minus target
loss += err ** 2
dw += 2 * err * x # d(err²)/dw = 2·err·x
db += 2 * err # d(err²)/db = 2·err
n = len(xs)
w -= lr * dw / n
b -= lr * db / n
# after 200 epochs: w ≈ 1.98, b ≈ 1.07 — converging on y = 2x + 1
Predict, measure the loss, compute the gradients, nudge the weights. Every training loop has this shape.
gradient descent on f(x) = x², start x = 5, lr = 0.1
x ← x − 0.1·2x, so each step multiplies the distance by 0.8
step 0: x = 5.0000 f = 25.0000
step 1: x = 4.0000 f = 16.0000
step 2: x = 3.2000 f = 10.2400
step 3: x = 2.5600 f = 6.5536
...
step 20: x = 0.0576 f = 0.0033
the slope shrinks with x, so the steps do too — automatic braking.
06
THE CHAIN RULE
Networks are chains. Derivatives multiply.
A network is a composition: linear, then activation, then linear, then loss. The chain rule says the derivative of a composition is the product of the local derivatives — link by link.
If y = f(g(x)), then dy/dx = f’(g(x)) · g’(x): the outer derivative evaluated at the inner value, times the inner derivative. For y = (3x + 1)², the outer function is u² with derivative 2u, and the inner is 3x + 1 with derivative 3, so dy/dx = 2(3x + 1) · 3 = 6(3x + 1).
This is the whole trick behind deep learning. The forward pass walks left to right through the chain; backpropagation (Lesson 5) walks right to left, multiplying one local derivative at each step. When a value is used in two places, its contributions add — which is why the gradient of a parameter sums over every path through the graph.
Logistic regression as a computation graph. Every backward arrow multiplies by one local derivative; a parameter’s gradient is the product of all local derivatives along the path from the loss to it.
Derivation: the sigmoid derivative σ(1 − σ)
σ(x) = 1 / (1 + e⁻ˣ) = (1 + e⁻ˣ)⁻¹. Use the chain rule with outer function u⁻¹ and inner u = 1 + e⁻ˣ.
Rewrite in terms of σ. Since 1 − σ = e⁻ˣ/(1 + e⁻ˣ), the product σ·(1 − σ) equals e⁻ˣ/(1 + e⁻ˣ)² — the same expression.
Hence σ’(x) = σ(x)·(1 − σ(x)), computed from the value the forward pass already produced.
numeric check at x = 2, h = 1e-5:
σ(2) = 0.880797
σ'(2) = σ(2)·(1 − σ(2)) = 0.880797 · 0.119203 = 0.104994
central difference = [σ(2+h) − σ(2−h)] / 2h = 0.104994 ✓
why this matters: σ(1 − σ) is at most 0.25 (at σ = 0.5),
so every sigmoid layer multiplies the gradient by at least ¼.
Ten layers deep: 0.25¹⁰ ≈ 9.5e-7 — the vanishing gradient.
That shrinkage is exactly why deep networks abandoned sigmoid for ReLU (Lesson 2): ReLU’s derivative is 1 wherever the unit is active, so the chain does not get quieter with depth.
07
CURVATURE & SMART STEPS
The slope says which way. Curvature says how far.
The first derivative gives the direction. The second derivative — the Hessian, in many dimensions — describes how the slope itself bends, and that is what makes better optimizers possible.
A gradient step assumes the function is a straight line in the direction you are walking. Near the minimum that is optimistic: the line keeps going down forever, but the curve flattens. Curvature measures how quickly the slope changes. A large learning rate works when curvature is gentle and misbehaves when it is sharp, because the step leaves the region where the linear approximation was trustworthy.
In many dimensions the second derivatives form the Hessian matrix: entry (i, j) is how the slope of parameter i changes when parameter j moves. At a point where the gradient is zero, the Hessian’s eigenvalues classify the point — all positive is a minimum, all negative a maximum, mixed signs a saddle.
The second derivative signs the curvature. At a flat point (gradient zero), positive curvature means a valley, negative means a peak, and mixed signs mean a saddle — downhill in one direction, uphill in another.
Method
Uses
Cost per step
Reality check
Gradient descent
first derivatives only
O(N)
slow but reliable
Newton's method
full Hessian H
O(N³)
fast, impractical for big N
L-BFGS
Hessian estimated from gradient history
O(N)
superlinear, medium models
Adam
per-parameter running moments of the gradient
O(N)
the deep learning default
Derivation: Newton's step from the Taylor series — and why small steps work
Taylor’s theorem says any smooth function is locally a polynomial. Write h for the step away from x:
f(x + h) = f(x) + f'(x)·h + ½·f''(x)·h² + ⅙·f'''(x)·h³ + …
keep 0 terms: f(x) → random search
keep 1 term: f(x) + f'(x)·h → a line; minimize it: h = −lr·f'(x)
keep 2 terms: f(x) + f'(x)h + ½f''(x)h² → a parabola; minimize it: h = −f'(x)/f''(x)
For the quadratic model q(h) = f(x) + f′(x)·h + ½f″(x)·h², differentiate with respect to h: q′(h) = f′(x) + f″(x)·h.
Set it to zero: h = −f′(x) / f″(x) — Newton’s step. In many dimensions f″ becomes the Hessian and division becomes H⁻¹, giving w ← w − H⁻¹·∇L.
Gradient descent is what you get by replacing the true curvature f″ with a guessed constant 1/lr. Every step trusts the linear model; a large lr takes a long step into a region where that model is no longer true.
numeric check on f(x) = sin x at x = 1:
f'(1) = cos(1) = 0.5403, f''(1) = −sin(1) = −0.8415
Newton step h = −0.5403 / (−0.8415) = +0.6421
f(1 + 0.6421) = sin(1.6421) = 0.9975 ← already at the peak
a gradient step with lr = 0.5 gives f(1.2701) = 0.9553 — slower.
curvature-aware steps are faster because they rescale the slope.
08
CHECK YOURSELF
Five questions. Then the terms worth keeping.
Answer before you look. The gradient, learning-rate and finite-difference questions are the ones that come up every time you debug a training run.
0 / 5 answered · 0 correct
01What does the derivative of a function at a point tell you?
02What is a gradient in ML?
03What does w = w − lr · dL/dw accomplish?
04Why can't Newton's method be applied directly to networks with millions of parameters?
05What is the central-difference approximation for f'(x)?
Key terms, demystified
Click a card to swap the lazy description for what it actually means.
Exercises from the lesson
Three short problems. Try first; a worked answer is one click away.
Write numerical_second_derivative(f, x) by calling the first-derivative function twice. Verify that the second derivative of x³ at x = 2 is 12.Show one worked answer
def numerical_derivative(f, x, h=1e-5):
return (f(x + h) - f(x - h)) / (2 * h)
def numerical_second_derivative(f, x, h=1e-3):
return (numerical_derivative(f, x + h) - numerical_derivative(f, x - h)) / (2 * h)
f = lambda x: x ** 3
print(numerical_second_derivative(f, 2)) # ≈ 12.0000
The calculus: f'(x) = 3x², so f''(x) = 6x, and 6·2 = 12. The nesting is itself a warning: the outer difference builds two inner differences, so rounding noise is amplified. Use a larger outer h (1e-3) than the inner one (1e-5), or use the direct central second difference (f(x+h) − 2f(x) + f(x−h))/h², which needs only one subtraction of nearby values.
Use gradient descent to find the minimum of f(x, y) = (x − 3)² + (y + 1)². Start from (0, 0). The answer should converge to (3, −1).Show one worked answer
The partials are ∂f/∂x = 2(x − 3) and ∂f/∂y = 2(y + 1), so with lr = 0.1 each coordinate follows x ← x − 0.2(x − 3), i.e. the distance to 3 is multiplied by 0.8 every step.
step 0: (0.000, 0.000)
step 1: (0.600, −0.200)
step 2: (1.080, −0.360)
step 3: (1.464, −0.488)
...
step 20: (2.965, −0.988)
step 30: (2.996, −0.999)
The two coordinates have their own slopes and are optimized independently. The steps shrink as the slope flattens, so gradient descent slows down automatically near the minimum. A quadratic bowl like this one has no local minima to get caught in.
Add momentum to the gradient descent loop: keep a velocity that accumulates past gradients. Compare convergence speed with and without momentum on f(x) = x⁴ − 3x².Show one worked answer
Momentum: v ← β·v + f'(x), then x ← x − lr·v, with β around 0.9. Plain descent: x ← x − lr·f'(x).
From x = 2.2, f'(x) = 4x³ − 6x. Plain descent with lr = 0.02 walks 2.200 → 1.612 → 1.470 → 1.393 → 1.344 → … toward the valley at x ≈ 1.2247 (f = −2.25).
Momentum with lr = 0.01 and β = 0.9:
v = 29.39, x = 1.906
v = 42.71, x = 1.479
v = 42.51, x = 1.054
Momentum reaches the valley region in three steps that plain descent needed five or six for — consistent directions accumulate, so it accelerates on the long slope. But it also overshoots: the third step lands left of the minimum, and the velocity has to bleed off before it settles. The lesson is that momentum makes the effective step size larger, so lr must be retuned (and it is exactly why Adam, in Lesson 8, tracks per-parameter moments instead of one global momentum).
Terms this lesson borrows from later lessons (or outside)
You do not need to master these here. Each one gets a proper treatment in its own lesson; the one-line meaning is enough to keep reading. Orange dotted underlines in the prose point back to this list.
backpropagation — The algorithm that computes the gradient of the loss for every weight by applying the chain rule backward through the layers. (Lesson 5)
cross-entropy — The classification loss: minus the log of the probability the model assigned to the correct answer. (Lesson 6)
softmax — Turns a list of raw scores into probabilities that are positive and sum to 1. (Lesson 6)
variance — How spread out a set of numbers is: the average squared distance from their mean. (Lesson 6)
expected value — The probability-weighted average of a random quantity; its long-run mean. (Lesson 6)
distribution — A complete description of which values a random quantity can take and how likely each one is. (Lesson 6)
prior / posterior — Bayesian inference: start with a belief (the prior), see evidence, and compute an updated belief (the posterior). (Lesson 7)
momentum — A gradient-descent variant that keeps a running velocity, so steps build up in directions that stay consistent and cancel in directions that flip. (Lesson 8)
mini-batch — A small random subset of the training data used for one gradient step, instead of the whole dataset. (Lesson 8)
attention — The mechanism inside transformers where each token scores every other token by a dot product (query · key) and reads more from the high-scoring ones.
normalization — Rescaling inputs to a common range (typically mean 0, spread 1) so no single feature dominates the others.
KEEP GOING
A picture is a start. Practice is the rest.
This lesson is a port of an open course. Everything here traces back to it — and the next step is running the code yourself.
Lesson text adapted from AI Engineering from Scratch (Phase 01, Lesson 04) and the Math Foundations Notebook reference build. Interactive figures, added AI visuals, worked exercise answers, and the four new calculus labs are original to this page. Every lab runs in your browser.