Gradient descent is three lines of code and a lifetime of behaviour. This lesson does what most treatments skip: it solves the algorithm’s dynamics exactly on the one problem where that is possible — the quadratic — and shows that everything you observe on real losses (divergence past a learning-rate threshold, zig-zagging across ravines, the slow crawl along flat directions) is already present, and provable, there.
The update, and where it comes from
Around the current iterate , first-order Taylor says . Among all steps of a fixed small length, the one that decreases this linear model fastest is : the negative gradient is the direction of steepest descent. Committing to it with a step size (learning rate) :
For an -smooth function, the smoothness upper bound from the previous lesson turns this from a heuristic into a guarantee. Plugging the step into the quadratic upper bound gives the descent lemma:
which is strictly decreasing whenever . There is the learning-rate ceiling, derived rather than tuned: step sizes are bounded by the sharpest curvature of the loss.
def gradient_descent(grad, x0, lr, steps):
x = x0.copy()
for _ in range(steps):
x -= lr * grad(x) # the entire algorithm
return x
Exact dynamics on a quadratic
Take with symmetric (any smooth loss looks like this near a minimum — this is not a toy, it is the local model of every basin). The gradient is , so the update is linear:
Diagonalize and write the error in the eigenbasis, . The coordinates decouple — each curvature direction evolves independently:
Every question about gradient descent on this problem reduces to the scalar factor :
- Convergence requires for all , i.e. . Exceed it and the stiffest direction oscillates with growing amplitude — the characteristic explode-in-one-axis divergence you can reproduce in the figure below.
- Speed is set by the slowest factor. With ranging over , the best constant step balances the two extremes:
For the rate is : each iteration removes 2% of the remaining error, and you need roughly iterations — iteration count scales linearly with the condition number. That sentence is why feature standardization, batch normalization and second-order-ish methods exist.
The zig-zag, explained. In a ravine (), any large enough to make progress along the flat direction is close to the stability limit of the steep one, so the steep coordinate’s factor is close to : it overshoots and flips sign every step. The trajectory bounces wall-to-wall across the ravine while creeping along it. You are watching the two eigenvalues disagree about the learning rate.
The contour map is the loss surface (darker = lower); dots mark the global minimum, local minimum and saddle. The side panel plots loss per iteration on a log scale — linear convergence appears as a straight line, and its slope is exactly the rate derived above.
Three experiments worth actually doing before reading on:
- Find the cliff. Quadratic, . The theory says stability ends at (here after scaling: watch for the readout’s DIVERGED). Sweep and locate the cliff — it is sharp, not gradual.
- Feel the κ tax. Fix slightly below the cliff and raise from 1 to 60. The loss line on the sparkline tilts toward horizontal: same algorithm, same code, 60× the iterations.
- Meet your first local minimum. Switch to the two-wells surface and drag the start around (the saddle). A few pixels left: the deep well. A few pixels right: the shallow one, and the loss curve flatlines at a higher value — gradient descent has converged, and it is not the answer. Which minimum you get is a property of the initialization, not the optimizer.
Beyond quadratics: what survives
On a general convex, -smooth with , telescoping the descent lemma against the first-order convexity bound yields
and with -strong convexity the geometric rate returns: . The quadratic analysis was not a special case after all — near any strict minimum it is the general case, with .
On non-convex , the descent lemma still guarantees — you always find an (approximately) stationary point. What kind of stationary point, the lemma cannot say; that question owns the non-convex landscapes lesson.
Continuous-time picture
As , gradient descent traces the ODE — water flowing downhill on the surface. This “gradient flow” view is more than a metaphor: finite discretizes the flow, and the divergence at is precisely a too-coarse Euler discretization of a stiff ODE going unstable. Optimization inherits 50 years of numerical-ODE intuition through this door, including momentum-as-damped-oscillator in the momentum lesson.
Exercises
Work these before the next lesson
- Derive : minimize over and show the optimum equalizes the two terms. Then verify the resulting rate is .
Solution
Worked solutions are part of Premium — unlock all of them for £5/month →
- 4 more exercises — each with a worked solution — are part of Premium. Unlock everything for £5/month →
References
- Y. Nesterov, Lectures on Convex Optimization, 2nd ed., 2018 — §2.1 for the rates quoted here.
- G. Goh, “Why Momentum Really Works”, Distill, 2017 — the eigenbasis decoupling used above, animated; also the bridge to the momentum lesson.
- S. Boyd & L. Vandenberghe, Convex Optimization, §9.2–9.3 — exact line search and the classical zig-zag analysis.