Cheat sheets

Calculus, Gradients and Convex Optimization

Derivatives, autodiff, GD, momentum, Adam, Newton and convexity tests. From-scratch Python and PyTorch.

  • Concepts and terms
  • Tasks and commands
  • Annotated code
  • Diagrams
  • Defaults and numbers
  • Troubleshooting
  • Questions and tips

Source

Forward and backward through one neuron#

*w+bbackwardx1xinputz1 = w*xmultiplyz2 = w*x + badd biasa = sigmoid(z2)activationdL/dwdL/dz2 * xdL/dbdL/dz2 * 1dL/dz2dL/da * a(1-a)Lcross-entropy loss*w+bbackwardx1xinputz1 = w*xmultiplyz2 = w*x + badd biasa = sigmoid(z2)activationdL/dwdL/dz2 * xdL/dbdL/dz2 * 1dL/dz2dL/da * a(1-a)Lcross-entropy loss

From Lesson 01.04

Reverse-mode autodiff in Value.backward#

1Recordeach operation makes a new Value with itschildren and a _backward closure.2Sortbuild_topo puts every node after the nodes itdepends on.3Seedset self.grad = 1.0 on the output. This is dy/dy= 1.4Walk backcall v._backward() for each node in reversedtopological order.5Accumulateeach closure adds to .grad with +=. A value usedtwice gets the sum.6Resetset p.grad = 0.0 for every parameter before thenext loss.backward().7Updatep.data -= lr * p.grad for each parameter.

From Lesson 01.05, 01.05 code/autodiff.py

Tasks in code#

TaskCode
Central differencenumerical_derivative(f, x, h=1e-7)
Gradient of many inputsnumerical_gradient(f, point, h=1e-7)
Hessian of f(x, y)hessian_2d(f, x, y, h=1e-5)
Check an autodiff gradientgradient_check(build_expr, x_val, h=1e-7)
XOR network, 4 hiddenmodel = MLP([2, 4, 1])
Run an optimizeroptimize(optimizer, func, grad_func, start)
Test convexity by samplingcheck_convexity(f, dim)
Newton steps in 2Dnewtons_method(grad_f, hessian_f, x0)

From 01.04 code/derivatives.py, 01.05 code/autodiff.py, Lesson 01.05, 01.08 code/optimizers.py, 01.18 code/convex.py

Optimizers from scratch#

GradientDescent(lr=0.001)w = w - lr * gradient
SGDMomentum(lr=0.001, momentum=0.9)v = beta * v + gradient
Adam(lr=0.001, beta1=0.9, beta2=0.999, epsilon=1e-8)two moments per weight
m_hat = [m / (1 - self.beta1 ** self.t) for m in self.m]bias correction
p - self.lr * mh / (vh ** 0.5 + self.epsilon)per-weight step size
adam_history = optimize(Adam(lr=0.01), rosenbrock, rosenbrock_gradient, start)

From Lesson 01.08, 01.08 code/optimizers.py

Autograd and optimizers in PyTorch#

x = torch.tensor(2.0, requires_grad=True)
y = x ** 2 + 3 * x + 1
y.backward()reverse mode through the recorded graph
print(x.grad)7.0 = 2*x + 3
sgd = torch.optim.SGD(model.parameters(), lr=0.01, momentum=0.9)
adam = torch.optim.Adam(model.parameters(), lr=0.001)
adamw = torch.optim.AdamW(model.parameters(), lr=0.001, weight_decay=0.01)
scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(adam, T_max=100)

From Lesson 01.05, Lesson 01.08

Derivatives to know#

CommandWhat it does
x^22x. MSE loss
wx + bx for w, 1 for b, w for x. Linear layer
e^xe^x. Softmax, attention
ln(x)1/x. Cross-entropy loss
sigmoidf(x)(1-f(x)). Sigmoid activation
tanh1 - tanh^2. Classic activation
x^nn x^(n-1). Used by __pow__
sin(x^2)cos(x^2) * 2x. Chain rule example

From Lesson 01.04, Lesson 01.05

Key formulas#

Central difference
f'(x) \approx \frac{f(x + h) - f(x - h)}{2h}.
Chain rule
\frac{dy}{dx} = f'(g(x)) \cdot g'(x). Sum the paths where the graph branches.
Gradient descent
w = w - \text{lr} \cdot \text{gradient}.
Momentum
v = \beta \cdot v + \text{gradient}, then w = w - \text{lr} \cdot v.
Adam
w = w - \text{lr} \cdot \hat{m} / (\sqrt{\hat{v}} + \epsilon) with bias-corrected moments.
Newton
x_{\text{new}} = x - H^{-1} \cdot \text{gradient}.
Convex
f(tx + (1-t)y) \le t f(x) + (1-t) f(y) for t \in [0, 1].
Lagrangian
L(x, \lambda) = f(x) + \lambda g(x). Set its gradient to zero.

From Lesson 01.04, Lesson 01.05, Lesson 01.08, Lesson 01.18

Pick a method#

CommandWhat it does
Gradient descentFirst derivatives. O(n) memory. Baseline
SGD with momentumBest final accuracy with more tuning
AdamDiagonal curvature from gradient moments. Deep learning default
AdamWAdam with decoupled weight decay. Transformers
Newton's methodFull Hessian. O(n^3) per step. Small convex problems
L-BFGSLast m gradient differences. Medium convex problems
K-FACKronecker-factored Fisher. Large-batch training

From Lesson 01.04, Lesson 01.08, Lesson 01.18

Numbers and defaults#

SettingDefaultNote
Adam lr0.001Start here for most problems
Adam beta20.999beta1 is 0.9. Moment decay rates
Adam epsilon1e-8Stops division by zero
SGD momentum lr0.01With momentum 0.9
AdamW weight_decay0.01Decoupled from the gradient step
Mini-batch size32-256Good gradient estimate, moderate noise
Finite difference h1e-7In numerical_derivative
Gradient check difference< 1e-5Autodiff against numerical

From 01.04 code/derivatives.py, Lesson 01.05, Lesson 01.08, 01.08 code/optimizers.py

Troubleshooting#

SymptomCauseFix
Loss grows or becomes nanLearning rate too largeReduce the learning rate
Training is too slowLearning rate too smallIncrease it. Add a schedule
Zigzag in a narrow valleyHigh condition number of the HessianAdd momentum, or use Newton
Gradient near 0, no progressSaddle pointMomentum and mini-batch noise
Gradients grow each step.grad adds with +=Set p.grad = 0.0 before backward
Autodiff disagrees with numericBug in a _backward ruleRun gradient_check
Noisy second derivativeStep h too smallUse h=1e-4 for both calls
Newton too costly for a big modelO(n^2) memory, O(n^3) inverseUse L-BFGS or Adam

From Lesson 01.04, Lesson 01.05, Lesson 01.08, Lesson 01.18

Questions#

Why reverse mode for networks?
Many inputs and one loss. One backward pass gives all gradients.
How do I test convexity?
f'' >= 0 in 1D. Hessian positive semidefinite in many dimensions.
Why does SGD work on non-convex losses?
Most critical points are saddle points. Most minima are good.
Why does L1 give sparse weights?
The diamond has corners on the axes.
What is complementary slackness?
\lambda_i \, g_i(x) = 0. Support vectors have \lambda > 0.

From Lesson 01.05, Lesson 01.18

Tips#

  • Use a learning rate schedule for runs longer than a few epochs.
  • Cosine annealing and warmup suit transformers and large models.
  • Newton's method solves a quadratic in one step.
  • Gradient checks cost 2 forward passes per parameter. Do not run them in production training.
  • A Hessian with mixed eigenvalue signs at a critical point marks a saddle.
  • Flat minima generalize better than sharp minima.

From Lesson 01.04, Lesson 01.05, Lesson 01.08, Lesson 01.18