← Master Index
Vol. 02 Module 2.2 Lecture

Gradient Descent

Calculus

How This Lesson Fits the Module

Derivatives told you how a function changes locally. Partial Derivatives extended that to functions of many variables. The Chain Rule explained how gradients flow through composed functions—the backbone of backpropagation. Gradient assembled those partial derivatives into a single vector: the direction of steepest ascent.

Gradient descent is where calculus becomes an algorithm. It takes that gradient and walks downhill on a loss surface, updating model parameters until predictions improve. Every neural network you train—from a small logistic regressor to a billion-parameter language model—relies on some variant of this loop.

If the gradient is the compass, gradient descent is the journey.

Learning Objectives

By the end of this lesson, students should be able to:

  • State the gradient descent update rule and explain each symbol: weights, learning rate, and loss gradient.
  • Describe why we subtract the gradient (not add it) when minimizing loss.
  • Explain the role of the learning rate α and diagnose symptoms of rates that are too large or too small.
  • Distinguish batch gradient descent, mini-batch gradient descent, and stochastic gradient descent (SGD).
  • Recognize local minima, saddle points, and plateaus as landscape challenges—and why deep networks often still train successfully.
  • Outline a standard ML training loop: forward pass, loss, backward pass, optimizer step.
  • Describe momentum at a high level as a technique that smooths and accelerates updates.
  • Read a high-level PyTorch training script and map each line to the mathematical update rule.

Introduction: From Gradient to Algorithm

In supervised learning, a model has parameters (weights) w that map inputs to predictions. Training means finding w that minimizes a loss function L(w)—a scalar measuring how wrong the model is on data. You cannot try every possible w in a high-dimensional space; you need an iterative procedure.

Gradient descent is that procedure. At each step, compute the gradient ∇wL—the vector of partial derivatives of the loss with respect to every parameter. The gradient points uphill (toward higher loss). To reduce loss, move in the opposite direction.

This lecture turns the gradient from a mathematical object into a training algorithm—the engine behind modern deep learning.

The Update Rule

Definition — Gradient Descent Update

Given current parameters w, loss L, and learning rate α > 0, one step of gradient descent is:

ww − α ∇wL

Read aloud: “w gets updated to w minus alpha times the gradient of L with respect to w.” The assignment arrow (←) emphasizes that we overwrite the old weights with new ones.

Unpacking the symbols:

Symbol Name Role in the Update
w Parameters (weights) The vector of all trainable values—weights and biases in a neural network. May live in millions of dimensions.
L Loss function A scalar objective to minimize (e.g., cross-entropy, mean squared error). Must be differentiable for gradient descent.
wL Gradient of L w.r.t. w Vector of partial derivatives. Points in the direction of steepest increase in L. Same dimension as w.
α Learning rate Positive scalar controlling step size. Also written η (eta) in many textbooks—same role, different symbol.
Descent direction Subtracting the gradient moves against the uphill direction—hence “descent.”

Component-wise view: If w = (w1, w2, …, wn), then each parameter updates independently:

wi ← wi − α · (∂L / ∂wi)

The gradient packages all these partial derivatives into one vector so we can write a single, compact update.

Worked Example — One Parameter

Suppose L(w) = (w − 3)2. Then dL/dw = 2(w − 3). Start at w = 0 with α = 0.1:

  • Step 1: w ← 0 − 0.1 × 2(0 − 3) = 0 + 0.6 = 0.6
  • Step 2: w ← 0.6 − 0.1 × 2(0.6 − 3) = 0.6 + 0.48 = 1.08
  • Step 3: w ← 1.08 − 0.1 × 2(1.08 − 3) = 1.08 + 0.384 = 1.464

Each step moves w toward the minimum at w = 3. The loss decreases monotonically for this simple convex function.

Why Subtract the Gradient?

The gradient ∇L points in the direction of steepest ascent—the direction that increases L fastest. Minimization requires the opposite direction: −∇L.

Geometric intuition: imagine standing on a hillside where height represents loss. The gradient points uphill. To reach the valley, walk downhill—opposite to the gradient. The learning rate α determines how far you stride in that downhill direction each step.

If you accidentally add the gradient (w ← w + α∇L), you climb uphill and loss increases. This is gradient ascent—useful for maximization problems, but wrong for training classifiers and regressors.

The Learning Rate α

The learning rate is the single most important hyperparameter in gradient descent. It scales every component of the gradient equally.

α Too Large

Updates overshoot the minimum. Loss oscillates, spikes, or diverges to NaN.

Symptom: Training loss jumps wildly or explodes within the first few epochs.

α Too Small

Updates are timid. Convergence is correct but painfully slow; training may stall on flat regions.

Symptom: Loss decreases glacially; many epochs needed for acceptable accuracy.

α Well Tuned

Loss decreases smoothly and reaches a good minimum in reasonable time.

Practice: Start with a standard value (e.g., 1e-3 for Adam, 0.01–0.1 for SGD), then tune on a validation set.

Unlike parameters w, the learning rate is typically not learned by gradient descent itself (though learning rate schedules and adaptive optimizers like Adam adjust effective step sizes per parameter). Engineers set α or choose a schedule: constant, step decay, cosine annealing, warmup-then-decay.

Engineering Principle

There is no universal learning rate. It depends on model architecture, loss scale, batch size, and optimizer. A rate that works for a 2-layer MLP on MNIST may destroy training for a transformer on web text. Always monitor loss curves during the first epoch when trying a new α.

Estimating the Gradient: Batch, Mini-Batch, and SGD

The update rule assumes we can compute ∇L. But in ML, L is almost always an average loss over training data:

L(w) = (1/N) ∑i=1N Li(w)

where Li is the loss on the i-th training example. The true gradient is the average of per-example gradients. How we approximate that average defines three variants:

Variant Gradient Computed Over Update Frequency Trade-offs
Batch GD Entire dataset (all N examples) One update per epoch Accurate gradient direction; expensive for large N; slow updates
Mini-Batch GD A subset of B examples (batch size) One update per mini-batch Industry standard; balances noise and speed; GPU-friendly parallelism
SGD One example (B = 1) One update per example Noisy but fast per step; rarely used alone at B = 1 today; “SGD” often means mini-batch in practice

Mini-batch gradient descent is the workhorse of deep learning. A typical batch size ranges from 32 to 4096 depending on GPU memory and model size. The gradient estimate is:

∇L ≈ (1/B) ∑i ∈ batch ∇Li

This is an unbiased estimate of the true gradient when batches are sampled uniformly. The noise introduced by mini-batching can actually help escape poor regions—similar to shaking a ball out of a shallow dip.

Shuffle training data — Randomize example order each epoch Partition into mini-batches — Groups of B examples For each mini-batch: forward pass → compute loss → backward pass → update w End of epoch — Every example seen once (approximately, if N not divisible by B) Repeat for multiple epochs until convergence or early stopping

The Loss Landscape: Local Minima and Beyond

Gradient descent follows local slope information. It has no global map of the loss surface. That creates well-known challenges:

Definition — Local Minimum

A point w* is a local minimum if L(w*) ≤ L(w) for all w in some neighborhood around w*. The gradient is zero (or near zero) at such a point, so gradient descent stops updating.

For simple convex problems (linear regression with MSE, logistic regression), the loss has a single global minimum—gradient descent is guaranteed to find it (with an appropriate α). Neural networks are non-convex: millions of local minima and saddle points exist.

Why Deep Learning Still Works

Empirically, large neural networks often reach solutions that generalize well, even though we do not find the global minimum. Reasons include: (1) many local minima have similar loss in high dimensions; (2) mini-batch noise helps escape saddles; (3) overparameterized networks have wide, flat basins that generalize better than sharp minima; (4) early stopping prevents overfitting before wandering too far. Local minima are a concern in theory but less catastrophic in practice than early textbooks suggested.

Momentum: A Brief Preview

Plain gradient descent can zigzag in narrow valleys and crawl across flat regions. Momentum addresses this by accumulating a velocity vector that smooths updates over time.

v ← βv − α∇L,   ww + v

Here v is a velocity buffer and β ∈ [0, 1) is a momentum coefficient (often 0.9). The update remembers past gradient directions—like a ball rolling downhill, gaining speed in consistent directions and dampening oscillations across ravines.

Momentum is one of many extensions to vanilla gradient descent. The next lecture, Optimization, covers Adam, RMSprop, learning rate schedules, and other optimizers used in production training.

The Training Loop

Gradient descent is not a single formula—it is a loop embedded in a larger training procedure. Every PyTorch, TensorFlow, or JAX training script follows this skeleton:

Initialize — Random weights w, choose optimizer and learning rate α Epoch loop — Repeat for a fixed number of passes over data (or until convergence) Batch loop — For each mini-batch of (input, label) pairs: Forward pass — Compute predictions: ŷ = f(w; x) Compute loss — L = loss(ŷ, y) Backward pass — Compute ∇wL via backpropagation (chain rule) Optimizer stepww − α∇L (or momentum / Adam variant) Zero gradients — Clear accumulated gradients before next batch Validate — Periodically evaluate on held-out data; log metrics; save checkpoints

Key engineering details often omitted from the formula but critical in practice:

PyTorch: Gradient Descent in Code

PyTorch hides the calculus behind two mechanisms: loss.backward() computes gradients via autograd, and optimizer.step() applies the update rule. Below is a high-level training loop for a simple classifier—not production code, but the structural template every engineer recognizes:

import torch
import torch.nn as nn
from torch.utils.data import DataLoader

# Model, loss, and optimizer (w is model.parameters(), alpha is lr)
model = nn.Linear(784, 10)                    # w: weights and biases
criterion = nn.CrossEntropyLoss()             # L: scalar loss
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)  # alpha = 0.01

train_loader = DataLoader(dataset, batch_size=64, shuffle=True)

for epoch in range(num_epochs):
    model.train()
    for inputs, labels in train_loader:     # mini-batch loop
        # Forward pass
        outputs = model(inputs)               # y_hat = f(w; x)
        loss = criterion(outputs, labels)     # L(w)

        # Backward pass: compute nabla_w L
        optimizer.zero_grad()                 # clear old gradients
        loss.backward()                       # autograd: chain rule

        # Update rule: w <- w - alpha * nabla_w L
        optimizer.step()

    # Validation (no gradient updates)
    model.eval()
    with torch.no_grad():
        val_loss = evaluate(model, val_loader)

Mapping code to math:

PyTorch Mathematical Meaning
model.parameters() The parameter vector w (tensors distributed across layers)
loss = criterion(outputs, labels) Compute scalar L(w)
loss.backward() Compute ∇wL via backpropagation
optimizer.step() Apply ww − α∇L (SGD) or extended rule (Adam, etc.)
lr=0.01 in optimizer constructor Learning rate α
batch_size=64 in DataLoader Mini-batch size B for gradient estimation

Switching from SGD to momentum is a one-line change: torch.optim.SGD(model.parameters(), lr=0.01, momentum=0.9). Switching to Adam: torch.optim.Adam(model.parameters(), lr=1e-3). The training loop structure stays identical—only the optimizer’s internal update rule changes.

Convergence and Stopping Criteria

When do you stop iterating? Common criteria:

In practice, engineers combine fixed epochs with early stopping and checkpointing: save the best validation model, then restore it after training ends.

Common Misconceptions

Misconception 1: “Gradient descent always finds the global minimum.”

Why people believe it: The algorithm “minimizes” the loss, so it sounds like it finds the best possible solution.

Reality: Gradient descent finds a local minimum (or stationary point) starting from initialization. For non-convex losses like neural networks, different random seeds can land in different basins with different test accuracy.

Misconception 2: “SGD always means batch size of 1.”

Why people believe it: The name “stochastic” suggests one random example at a time.

Reality: Historically, SGD used single examples. Today, when practitioners say “SGD,” they often mean mini-batch SGD with the torch.optim.SGD optimizer—batch sizes of 32, 64, or larger. True single-example SGD is rare in deep learning due to GPU inefficiency.

Misconception 3: “A larger learning rate always speeds up training.”

Why people believe it: Bigger steps cover more ground per iteration.

Reality: Too large an α causes overshooting and divergence. There is a sweet spot—and adaptive optimizers adjust per-parameter step sizes because different weights need different effective rates.

Misconception 4: “You can skip zero_grad() to save time.”

Why people believe it: It seems like an optional cleanup step.

Reality: PyTorch accumulates gradients across calls to backward(). Without zeroing, gradients from multiple batches sum together and corrupt the update. This is one of the most common bugs in beginner training scripts.

Quick Knowledge Check

  1. Short Answer: Write the gradient descent update rule. Answer: w ← w − α∇wL.
  2. True/False: The gradient points in the direction of steepest loss decrease. Answer: False — it points in the direction of steepest increase; we subtract it to descend.
  3. Multiple Choice: Which variant uses the entire dataset for one gradient computation? (a) SGD, (b) Mini-batch GD, (c) Batch GD, (d) Momentum. Answer: (c) Batch GD.
  4. Short Answer: What happens if the learning rate is too large? Answer: Updates overshoot; loss may oscillate or diverge.
  5. Short Answer: What is a local minimum? Answer: A point where loss is lower than all nearby points but not necessarily the global lowest loss.
  6. True/False: In PyTorch, loss.backward() updates the model weights. Answer: False — it computes gradients; optimizer.step() updates weights.
  7. Short Answer: What does momentum add to plain gradient descent? Answer: A velocity term that accumulates past gradients, smoothing updates and accelerating consistent directions.
  8. Multiple Choice: Why do we call optimizer.zero_grad() before backward()? (a) To reset the model, (b) To clear accumulated gradients, (c) To set learning rate to zero, (d) To enable evaluation mode. Answer: (b).
  9. Short Answer: Name the four steps inside one mini-batch iteration. Answer: Forward pass, compute loss, backward pass, optimizer step (accept: zero grad before backward).
  10. True/False: Mini-batch noise is always harmful to training. Answer: False — noise can help escape saddle points and poor local regions.

Key Takeaways

  • Gradient descent iteratively minimizes loss: ww − α∇wL.
  • The gradient points uphill; subtracting it moves parameters downhill on the loss surface.
  • The learning rate α controls step size—the most critical hyperparameter to tune.
  • Batch GD (full data), mini-batch GD (subset), and SGD (one example) trade gradient accuracy for speed and noise.
  • Mini-batch training is the standard in deep learning; batch size affects memory, speed, and gradient noise.
  • Local minima, saddles, and plateaus complicate non-convex optimization, but large networks still train effectively in practice.
  • Momentum smooths updates by accumulating velocity—a preview of richer optimizers in the next lecture.
  • The training loop: forward → loss → backward → step; PyTorch’s autograd and optimizer handle the calculus.
  • Always zero gradients between batches; monitor loss curves when tuning α.

Further Reading & References

Books

Video & Visual

Official Documentation

Trainer’s Guide

Teaching strategy: Draw a bowl-shaped curve on the board. Mark a starting point, draw the tangent (gradient), and show that moving opposite to the tangent descends. Vary step size visually—small steps creep; large steps bounce out of the bowl.

Hands-on idea: Implement the scalar example L(w) = (w − 3)2 in a Jupyter notebook. Loop 20 steps with α = 0.1 and plot w and L over iterations. Then try α = 1.5 and show divergence.

PyTorch demo: Train nn.Linear(1, 1) on synthetic data (y = 2x + 1). Print loss.item() each epoch so students see the scalar decrease. Intentionally omit zero_grad() once and show broken training.

Discussion prompt: If two different random initializations reach different final losses on the same network, does that contradict gradient descent? What does it tell us about the loss landscape?

Bridge to next lecture: Preview that Adam and learning rate schedules are engineering upgrades to the same loop—the update rule changes, the training skeleton does not.

What’s Next Continue to Optimization for Adam, RMSprop, learning rate schedules, and the optimizer landscape beyond vanilla gradient descent. Review Gradient if the directional meaning of ∇L needs reinforcement.