%matplotlib inline
from d2l import torch as d2l
import numpy as np
import torchDive into Deep Learning · §9.1
What makes deep-net optimization hard
risk vs. empirical risk · where gradients vanish · curvature and noise · the edge of stability
The chapter’s frame
Every method in this chapter, GD through Muon, is one way of making these three decisions.
Optimization minimizes the empirical risk (training loss). Learning wants low risk (expected loss on the population). The optimizer only ever sees the former:
The two minima sit in different places — and no optimizer can fix that:
def annotate(text, xy, xytext):
d2l.plt.gca().annotate(text, xy=xy, xytext=xytext,
arrowprops=dict(arrowstyle='->'))
x = d2l.arange(0.5, 1.5, 0.01)
d2l.set_figsize((4.5, 2.5))
d2l.plot(x, [f(x), g(x)], 'x', 'risk')
annotate('min of\nempirical risk', (1.0, -1.2), (0.5, -1.1))
annotate('min of risk', (1.1, -1.05), (0.95, -0.5))f(x) = x \cos(\pi x) has a local minimum that is not global. Near it, the gradient goes to zero — the signal cannot tell the two apart:
Noise can knock the iterate out of a shallow basin — minibatch variance supplies exactly that.
1D: f(x) = x^3 has f'(0) = 0, yet no minimum:
High-dim: a zero-gradient point is a minimum only if all Hessian eigenvalues are positive — with mixed signs it is a saddle. At 10^6 parameters, essentially every critical point is a saddle:
x, y = d2l.meshgrid(
d2l.linspace(-1.0, 1.0, 101), d2l.linspace(-1.0, 1.0, 101))
z = x**2 - y**2
ax = d2l.plt.figure().add_subplot(111, projection='3d')
ax.plot_wireframe(x, y, z, **{'rstride': 10, 'cstride': 10})
ax.plot([0], [0], [0], 'rx')
ticks = [-1, 0, 1]
d2l.plt.xticks(ticks)
d2l.plt.yticks(ticks)
ax.set_zticks(ticks)
d2l.plt.xlabel('x')
d2l.plt.ylabel('y');No critical point needed: f(x) = \tanh(x) at x = 4 has f'(4) \approx 0.0013. The surface is just flat where we stand:
ReLU and good initialization fixed this at the model level — not the optimizer’s job.
f(\mathbf{x}) = 0.1 x_1^2 + 2 x_2^2: curvatures 0.2 and 4, one learning rate. Steep direction caps \eta < 0.5; flat direction then keeps > 90\% of its value per step:
epoch 30, x1: -0.295265, x2: -0.002476
Zig-zag across, crawl along. Condition number \kappa = \lambda_{\max}/\lambda_{\min} = 20; iterations scale linearly with \kappa. Real networks: \kappa in the thousands.
Momentum → \sqrt{\kappa}. Adam → per-coordinate rescaling. Muon → per-matrix rescaling. Most of the chapter fights this picture.
Classical advice: measure sharpness \lambda_{\max}, pick \eta < 2/\lambda_{\max}.
Measured reality (Cohen et al., 2021): causality runs backwards — training raises sharpness (“progressive sharpening”) until it reaches \approx 2/\eta, then hovers there. Loss keeps falling, non-monotonically, in the “forbidden” regime.
The gradient is a minibatch estimate: unbiased, variance \propto 1/b (measured on a real network in the SGD section).
Deep losses are not convex — permutation symmetry alone gives every minimum d! separated copies; convex minima form one connected set.
What survives:
Full treatment: the convexity chapter of the math appendix.