The goal of machine learning is to use data to minimize some particular objective (loss) function. The most widespread way to do this is through gradient descent, which essentially takes small steps in the direction of steepest descent for a particular objective function to find the “minimum”.

  • = learning rate

In practice, we use stochastic gradient descent (SGD), which uses one data point at a time for a single step and uses a much smaller subset of data points at any given step.

MethodData Used per UpdateUpdate RuleSpeedStabilityNoiseBest Used When
Vanilla GD / Batch GDAll training data SlowVery stableNo noiseSmall datasets
Stochastic GD (SGD)One sample FastHigh varianceHigh noiseLarge datasets or online learning
Mini-batch GDA small batch of samplesMediumGood tradeoffMedium noiseDeep learning (standard default)

Learning Rate

The step size is the single most important hyperparameter. Too small and convergence crawls; too large and the iterates oscillate or diverge. For a smooth loss with -Lipschitz gradient, stability requires . In practice a schedule (warmup then decay, cosine, or step decay) beats a fixed rate.

Momentum

Plain SGD zig-zags across narrow valleys. Momentum accumulates an exponentially weighted average of past gradients to damp oscillation and accelerate along consistent directions:

with typically 0.9. Nesterov momentum evaluates the gradient at the look-ahead point for a sharper correction.

Convergence Intuition

  • Convex, smooth: batch GD converges at rate , and with acceleration.
  • Strongly convex: linear (geometric) convergence.
  • Non-convex (deep nets): no global guarantee, but SGD reliably reaches good local minima; the gradient noise itself acts as a regularizer and helps escape saddle points, which are far more common than bad local minima in high dimensions.

Code

import numpy as np
 
def sgd_momentum(grad_fn, x0, lr=0.1, beta=0.9, steps=100):
    x = x0.copy()
    v = np.zeros_like(x)
    for _ in range(steps):
        g = grad_fn(x)                 # gradient on current mini-batch
        v = beta * v + g
        x -= lr * v
    return x
import torch
opt = torch.optim.SGD(model.parameters(), lr=0.1, momentum=0.9)
for xb, yb in loader:
    opt.zero_grad()
    loss = loss_fn(model(xb), yb)
    loss.backward()                    # backprop fills .grad
    opt.step()                         # apply the update rule

Pitfalls

  • Unscaled features stretch the loss surface into ellipses, slowing descent; standardize inputs or use normalization layers.
  • A diverging loss almost always means the learning rate is too high.
  • Momentum can overshoot near the minimum; anneal toward the end.
  • Adam combines momentum with per-parameter adaptive step sizes.
  • Part of the broader family of First-Order Methods.