Optimizers

Optimizers are algorithms that improve gradient descent.

Error as a 2D curve

Consider two classes represented by two groups of dots on a line:

The error as a 2D curve

Adjusting the learning rate

Constant-sized updates

To update a weight using a constant learning rate (η, eta):

Step Explanation Image

Find the gradient

  • a weight w1 (not shown) was updated to value w2, and we want a better value w3
  • w2's error is point B
  • find the gradient g at point B and scale it by the fixed learning rate → ηg
  • ηg points in the same direction as g (smaller or same size) since 0 < η ≤ 1

Update the weight

  • add the scaled gradient ηg to w2
  • graphically, place the tail of the arrow ηg at B
  • the tip of the arrow gives w3
  • w3's error is point C

In this case, the step overshoots slightly and increases the error.

Instead of settling at the lowest point, the algorithm overshoots repeatedly:

The first 15 steps of learning with a constant learning rate

Missing a valley is a possible consequence of a large learning rate:

Gradient descent overshoot

Changing the learning rate over time

A better approach is to adapt the learning rate over time with:

This can be done by multiplying η by a decay parameter (slightly less than 1) at each update:

Visualization of the value of η across many steps with various multipliers:

Exponential decay

Writing this as an equation naturally involves exponents, so this kind of decreasing curve is called an exponential decay curve.

Compared to a constant learning rate, exponential decay efficiently settles the model into the lowest point of the error curve:

Constant learning rate vs. exponential decay

Decay schedules

Using a decay introduces two main challenges:

  1. choosing the right value for the decay parameter
  2. deciding when to apply decay (not necessarily after every update)

Strategies for adjusting the learning rate over time are called decay schedules, usually applied per epoch.

Common decay scheduling methods:

Name Description Image

Exponential decay

Reduce the learning rate after every epoch.

Exponential decay

Delayed exponential decay

Wait a few epochs before starting decay so weights can move away from random initialization.

Delayed exponential decay

Interval decay (or fixed-step decay)

Reduce the learning rate every fixed number of epochs (e.g., every 4 or 10) to avoid shrinking too fast.

Interval decay

Error-based decay

Keep the learning rate while error decreases; apply decay when the network stops improving.

Error-based decay

This raises natural questions:

Some gradient descent variations address these ideas.

Improving gradient descent

Different algorithms can improve gradient descent.

We compare the performance of three of them using the same setup:

Because each algorithm behaves differently, the number of epochs varies. Performance is compared after each epoch.

Feature Batch gradient descent (BGD) Stochastic gradient descent (SGD) Mini-batch gradient descent
Notes Also called epoch gradient descent "Stochastic" (roughly "random") reflects that the network sees samples in a random order The mini-batch is a fixed number of samples considerably smaller than the number of samples in the training set (usually a power of 2 between 32-256), chosen to fully utilize GPU parallelism
Gradient computation Average of gradients over entire dataset Gradient from one sample at a time (300 training samples = 300 updates per epoch) Average of gradients over mini-batch of samples
Weights and biases update frequency Once per epoch, after computing gradients for all samples in the dataset After computing the gradient of every single sample After each mini-batch, using the average gradient from that mini-batch
Performance
Error curve Very smooth (as it averages over all samples) Fluctuates a lot (because we update after every sample and each one pulls weights in a different direction) Moderately smooth, some noise
Epochs to converge ~20,000 ~400 ~5,000
Total weight updates 20,000 epochs × 1 update/epoch = 20,000 300 samples × 400 epochs = 120,000 300 samples, mini-batch size = 32
→ number of mini-batches per epoch ≈ 300 ÷ 32 ≈ 10
→ 10 * 5000 epochs = 50,000
Memory requirement High (all data must be stored in memory) Low (process samples one at a time) Medium (store only mini-batches)
Advantages Predictable, smooth learning; works offline (all data stored) Faster convergence; does not require all data to be stored in memory Compromise between BGD and SGD; efficient gains by using the GPU parallelism
Disadvantages Slow for large datasets; requires storing all samples Noisy error curve → hard to detect overfitting; can overshoot minima; more updates ≠ fewer epochs → total training time depends on number of updates (not just epochs) Slight noise; still requires multiple updates; mini-batch size affects performance
Usage Rare Sometimes Most common; often what is meant by "SGD" or "gradient descent" in literature

From this point forward, we'll refer to mini-batch gradient descent simply as SGD.

Gradient descent variations

SGD works well, but it has two key challenges:

  1. choosing the right learning rate
  2. dealing with flat or tricky regions of the loss surface (like saddles and plateaus)
    • research has shown that deep networks commonly have many saddles in their error landscapes:
    • systems need strategies to avoid or escape these regions

Gradient descent variations that address these issues:

Momentum

Imagine the error surface as a 3D landscape:

A real rolling ball has inertia, which describes its resistance to a change in its motion.

A related idea is the ball's momentum or what keeps the ball moving across a plateau:

Momentum gradient descent adds inertia to gradient descent, combining the previous motion with the current gradient.

Finding the step for gradient descent with momentum:

Step Explanation Image

Find the previous motion

  • a weight w1 (not shown) with error A was updated to value w2 with error B, and we want a better value w3 with error C
  • the previous motion (from A to B) is the momentum vector m
  • scale it by the momentum scaling factor γ (gamma, 0 < γ ≤ 1), giving us γm

Gradient step

  • compute the gradient at B
  • scale it by the learning rate η, giving us ηg

Combined update

  • add γm + ηg to B
  • this gives the final direction and size of the next update
  • graphically, place the tail of γm at the head of ηg

Momentum accelerates learning and helps escape plateaus and shallow minima.

Choosing the right momentum factor γ requires experience, intuition, and often trial and error. A common choice is γ ≈ 0.9.

Nesterov momentum

Instead of only calculating the gradient at the current position, Nesterov momentum:

If the estimated future step:

Step Explanation Image

Start

  • the weight at position A is updated and ends up at B
  • the motion from A to B becomes the momentum vector (the arrow m)
  • it is scaled by γ (gamma) to get γm

Look ahead

  • instead of calculating the gradient at B
  • add the scaled momentum to B to get the "predicted" error P
  • this is where we think we're heading next on the error surface

Find the gradient g at point P

  • compute the gradient g at point P
  • scale it by the learning rate η (eta) → gives us ηg

Update the position

  • add the scaled momentum γm and the scaled gradient ηg
  • add both to B to get the next position C

Notice that:

  • we're not using the gradient at point B
  • point C is closer to the bottom of the bowl than point P

Compared to regular momentum, Nesterov momentum:

AdaGrad

Adagrad (adaptive gradient learning) adapts the learning rate η on a per-weight basis.

For each weight, Adagrad:

  1. takes the gradient from the current weight to update
  2. squares it and adds it to a running sum for that weight
  3. divides the original gradient by a value derived from this sum
  4. uses that result to update the weight

A small initial learning rate, such as η = 0.01, often works well, with AdaGrad automatically handling adjustments over time.

Since gradients are squared, the sum is always positive and always grows.

To keep it from growing out of control:

Adadelta and RMSprop

These improved methods fix Adagrad's issue of endlessly shrinking updates.

Instead of summing all the squared gradients, Adadelta (adaptive delta) uses a decaying average of squared gradients (not full history), giving more weight to recent gradients and less to older ones:

This creates a weighted average that is most heavily determined by recent gradients but also influenced to a lesser degree by the older gradients.

Adadelta requires additional hyperparameters:

RMSprop is similar to Adadelta, but uses slightly different math:

So the name literally describes: backpropagated gradients, scaled by the RMS of recent gradients.

Adam

For each weight, Adam (Adaptive Moment Estimation) keeps track of two running averages:

  1. a moving average of the raw gradients
  2. a moving average of the squared gradients

Previous algorithms used only squared gradients, which lost the sign information of the gradient.

Adam uses both lists to compute a more effective scaling factor.

Adam requires additional hyperparameters:

Common default values: β1 = 0.9 and β2 = 0.999 (as per the original Adam paper).

Choosing an optimizer

Summary of the two-moon results for different algorithms:

Summary of the two-moon results for different algorithms

Across many models and datasets:

Why are there so many optimizers?

Regularization

Even with the best optimizer, neural networks can overfit.

Regularization methods delay the onset of overfitting during training by:

Dropout

Dropout is a regularization technique used during training:

It is implemented as a dropout layer for conceptual clarity in network diagrams, but it's not a true layer:

Batchnorm

Batch normalization (or batchnorm) normalizes the outputs of the previous layer to a small range centered around 0:

It is implemented as a batchnorm layer:

Previous Backpropagation All ⏎ Next Convolutional neural networks

A Kemar Joint