Smoothness (L-Lipschitz Gradient)#
A differentiable function is -smooth if its gradient is -Lipschitz continuous:
In plain terms: the gradient cannot change too fast. If you move a small distance, the gradient changes by at most times that distance.
This implies a powerful quadratic upper bound (sometimes called the descent lemma):
The convex first-order condition says . Smoothness adds the reverse: . Together, -smooth convex functions are sandwiched between two quadratics of curvature .
Worked example: Is with smooth?
The gradient is , and . So is -smooth with , the largest eigenvalue of .
For the 2D quadratic from Week 1, , so .
Descent Lemma#
Plugging the GD update into the quadratic upper bound:
For the decrease term to be meaningful (negative), we need , i.e. . The optimal choice minimises the coefficient: gives
This is the descent lemma: with step size , GD guarantees a decrease of at least per iteration. As long as the gradient is nonzero, we make progress.
Convergence for Convex Smooth Functions#
Starting from with distance to an optimum , after iterations of GD with on a convex -smooth function:
This is the sublinear rate. To halve the optimality gap, you need about twice as many iterations. To reach accuracy , you need iterations.
What this means in practice: GD on a convex problem is reliable but not fast. Early iterations reduce the loss quickly; later iterations are slow. If you need high accuracy (small ), GD alone is expensive.
Strong Convexity#
A function is -strongly convex if there exists such that:
This is the convex first-order condition plus a quadratic lower bound. The function must curve upward at rate at least everywhere.
For quadratics , strong convexity means , i.e. . The 2D quadratic from Week 1 has , so .
Adding regularisation to any convex objective makes it -strongly convex. This is why ridge regression (Week 4) has better convergence than plain least squares.
With -strong convexity, GD with achieves linear convergence:
where is the condition number. The gap shrinks by a constant factor every iteration, giving complexity.
Condition Number#
The condition number governs how fast GD converges:
- small (well-conditioned): GD converges quickly. The loss surface is roughly spherical.
- large (ill-conditioned): GD converges slowly. The loss surface has elongated valleys where GD zigzags.
- : The function is perfectly spherical; GD converges in one step with the right .
GD's complexity for strongly convex functions is why we later introduce momentum (Week 7 — reduces to ) and adaptive methods (Week 8).
Worked example: For the 2D quadratic :
- (largest eigenvalue)
- (smallest eigenvalue)
- — well-conditioned, GD converges quickly
- A less friendly case: with , where GD will creep along the narrow valley
If $L = 10$, the descent lemma guarantees a loss decrease when the step size $\\eta \\leq$ ___.
An L-smooth function satisfies which bound?
Browser lab#
Run GD on 1D quadratic with . Compare (safe, optimal) vs (near-divergence) vs (divergence).
import numpy as np
import matplotlib.pyplot as plt
a = 5.0
L = 2 * a
x0 = 4.0
K = 20
def run_gd(eta, x0, K):
x = x0
vals = [a * x**2]
xs = [x]
for _ in range(K):
g = 2 * a * x
x = x - eta * g
xs.append(x)
vals.append(a * x**2)
return np.array(xs), np.array(vals)
etas = [0.5/L, 1/L, 1.8/L, 2.1/L]
labels = ["η=0.5/L", "η=1/L (safe)", "η=1.8/L (osc)", "η=2.1/L (diverge)"]
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4.5))
ks = np.arange(K + 1)
for eta, lbl in zip(etas, labels):
xs, vals = run_gd(eta, x0, K)
ax1.plot(ks, vals, "o-", markersize=3, label=lbl)
ax2.plot(ks, np.abs(xs), "o-", markersize=3, label=lbl)
ax1.set_xlabel("Iteration k"); ax1.set_ylabel("f(x_k)")
ax1.set_title(f"Loss vs iteration (L={L})")
ax1.set_yscale("log"); ax1.legend()
ax2.set_xlabel("Iteration k"); ax2.set_ylabel("|x_k|")
ax2.set_title("Distance to optimum")
ax2.set_yscale("log"); ax2.legend()
plt.tight_layout()
plt.show()