Skip to main content
© 2026 ePowerAI — free, open courseware. No login required.
CoursesContact
ePOWERAI
CoursesContact
Week 6: Stochastic Gradient Descent
Optimization

Foundations

  1. 01Week 1: Optimization for Learning
  2. 02Week 2: Convex Sets and Functions
  3. 03Week 3: Gradient Descent Theory

Model problems

  1. 04Week 4: Least Squares and Conditioning
  2. 05Week 5: Classification Losses

First-order stack

  1. 06Week 6: Stochastic Gradient Descent
  2. 07Week 7: Momentum and Acceleration
  3. 08Week 8: Adaptive First-Order Methods
  4. 09Week 9: Practical Training Dynamics

Structure

  1. 10Week 10: Nonsmooth and Composite Objectives
  2. 11Week 11: Constraints: Projections and Penalties
  3. 12Week 12: Duality for Practitioners

Nonconvex practice

  1. 13Week 13: Nonconvex Deep Learning
  2. 14Week 14: Capstone — Theory Meets Training
Week 06· Optimization· First-order stack6 min read

Week 6: Stochastic Gradient Descent

Learning Outcomes
  • Define mini-batch SGDStochastic Gradient Descent and explain why it is faster per-iteration than full-batch GD
  • Describe the bias–variance tension: mini-batch gradient is unbiased but noisy
  • Choose a decreasing learning rate schedule for convergence under noise
  • Contrast epoch (pass over full dataset) vs step (single mini-batch update)
Prerequisites

Background: Week 1 (GD algorithm), Week 3 (convergence rates, smoothness), Week 4 (least squares as a benchmark). The finite-sum ERM objective from Week 1 is the natural setting for SGD.

Later weeks: SGD is the base layer for momentum (Week 7) and Adam (Week 8). The noise characteristics introduced here determine how those advanced methods behave. The same mechanics drive deep RL training in Reinforcement Learning Week 8: Modern Deep Reinforcement Learning Algorithms.

Finite-sum objectives#

Nearly all supervised learning objectives have the form:

f(w)=1n∑i=1nfi(w)f(w) = \frac{1}{n} \sum_{i=1}^n f_i(w)f(w)=n1​∑i=1n​fi​(w)

where fi(w)=ℓ(fw(xi),yi)f_i(w) = \ell(f_w(x_i), y_i)fi​(w)=ℓ(fw​(xi​),yi​) is the loss on the iii-th training example. This is the ERMEmpirical Risk Minimization objective from Week 1.

The full gradient is ∇f(w)=1n∑i=1n∇fi(w)\nabla f(w) = \frac{1}{n} \sum_{i=1}^n \nabla f_i(w)∇f(w)=n1​∑i=1n​∇fi​(w), which requires scanning all nnn examples, one full pass through the dataset, for a single parameter update. When nnn is large (millions or billions), this is impossibly slow.

SGD replaces the full sum with an estimate computed from a small, randomly chosen mini-batch.

Mini-batch SGD#

At iteration kkk, sample a mini-batch Bk⊂{1,…,n}\mathcal{B}_k \subset \{1, \ldots, n\}Bk​⊂{1,…,n} of size BBB uniformly at random (without replacement). The mini-batch gradient estimate is:

gk=1B∑i∈Bk∇fi(wk)g_k = \frac{1}{B} \sum_{i \in \mathcal{B}_k} \nabla f_i(w_k)gk​=B1​∑i∈Bk​​∇fi​(wk​)

The SGD update is then wk+1=wk−ηk gkw_{k+1} = w_k - \eta_k \, g_kwk+1​=wk​−ηk​gk​.

Two key properties of gkg_kgk​:

  1. Unbiased: E[gk]=∇f(wk)\mathbb{E}[g_k] = \nabla f(w_k)E[gk​]=∇f(wk​). On average, the mini-batch gradient points in the right direction. The expectation is over the random choice of Bk\mathcal{B}_kBk​.

  2. Noisy: Var(gk)\mathrm{Var}(g_k)Var(gk​) is proportional to 1/B1/B1/B. A smaller batch has higher variance (noisier gradient estimate) but is cheaper to compute.

Computational cost per step:

  • Full-batch GD: O(nd)\mathcal{O}(n d)O(nd) to compute ∇f\nabla f∇f, then O(d)\mathcal{O}(d)O(d) to update
  • Mini-batch SGD (size BBB): O(Bd)\mathcal{O}(B d)O(Bd) to compute gkg_kgk​, then O(d)\mathcal{O}(d)O(d) to update

SGD makes roughly n/Bn/Bn/B times as many updates in the time it takes GD to do one update.

Noise and variance#

The variance of the mini-batch gradient estimate is:

Var(gk)≈σ2Bwhere σ2=1n∑i=1n∥∇fi(wk)−∇f(wk)∥2\mathrm{Var}(g_k) \approx \frac{\sigma^2}{B} \quad \text{where } \sigma^2 = \frac{1}{n} \sum_{i=1}^n \|\nabla f_i(w_k) - \nabla f(w_k)\|^2Var(gk​)≈Bσ2​where σ2=n1​∑i=1n​∥∇fi​(wk​)−∇f(wk​)∥2

The term σ2\sigma^2σ2 measures how different individual example gradients are from the average. When examples are "similar" (homogeneous data), σ2\sigma^2σ2 is small and SGD works well even with B=1B=1B=1. When examples are very different (heterogeneous data), you need larger batches to reduce variance.

The batch-size tradeoff:

  • Small BBB: cheap per iteration, many noisy updates per epoch → better exploration
  • Large BBB: expensive per iteration, fewer but more accurate updates → reliable descent
  • B=nB = nB=n: recovers full-batch GD (zero variance, maximum cost per step)

In practice, BBB is typically chosen as a power of 2 (32, 64, 128, 256) to fit well with GPU memory and vectorised computation.

Step sizes under noise#

With a fixed step size η\etaη, SGD does not converge to the exact optimum. It oscillates in a ball around w∗w^*w∗ whose radius is proportional to ησ2\eta \sigma^2ησ2. To converge exactly, we must decay the step size:

ηk=η01+γkorηk=η0k\eta_k = \frac{\eta_0}{1 + \gamma k} \quad \text{or} \quad \eta_k = \frac{\eta_0}{\sqrt{k}}ηk​=1+γkη0​​orηk​=k​η0​​

The O(1/k)\mathcal{O}(1/\sqrt{k})O(1/k​) schedule is common in theory; in practice, step-decay (halve η\etaη every TTT epochs) and cosine annealing (Week 9) are more popular.

A useful heuristic: for SGD with batch size BBB, a rule of thumb is η∝B\eta \propto Bη∝B. Doubling the batch size approximately allows doubling the learning rate (because the gradient estimate is twice as accurate).

Epoch vs step#

  • Step (or iteration): one mini-batch processed, one parameter update
  • Epoch: one full pass through the entire dataset (⌈n/B⌉\lceil n/B \rceil⌈n/B⌉ steps)

At the end of each epoch, the data is typically shuffled (random permutation) to avoid periodicity effects and to decorrelate consecutive mini-batches. Mini-batches drawn from a shuffled epoch are not independent — within an epoch they partition the data, so they are negatively correlated, but each is an unbiased estimate of the full gradient, which is what the convergence theory needs.

Tracking loss per epoch is more meaningful than loss per step, because epoch-level loss estimates the true objective while step-level loss is computed on a single mini-batch and is noisier.

Knowledge check#

Exercise · Multiple choice

If the mini-batch size B is doubled, the variance of the gradient estimate is approximately:

Halved
The same
Doubled
Quadrupled
Question 1 of 4

The mini-batch gradient g_k is an unbiased estimate of the full gradient ∇f(w) because:

E[g_k] = ∇f(w)
g_k has small variance
The data is shuffled
The batch size is large

Browser lab: GD vs SGD noise tradeoff#

Compare GD, SGD(B=1), and SGD(B=16) on a finite-sum quadratic objective. Plot loss vs epoch and observe the noise–convergence tradeoff.

python · runs in browser
import numpy as np
import matplotlib.pyplot as plt

rng = np.random.default_rng(42)
d, n = 3, 200

w_true = np.array([1.5, -0.8, 0.6])
X = rng.normal(size=(n, d))
y = X @ w_true + rng.normal(scale=0.3, size=n)

def loss(w, X, y):
    return 0.5 * np.mean((X @ w - y)**2)

def run_method(X, y, w0, n_epochs, method, B=None, eta=None):
    w = w0.copy()
    n = len(X)
    epoch_losses = []
    for ep in range(n_epochs):
        perm = rng.permutation(n)
        for start in range(0, n, B or n):
            idx = perm[start:start + (B or n)]
            g = X[idx].T @ (X[idx] @ w - y[idx]) / len(idx)
            w -= eta * g
        epoch_losses.append(loss(w, X, y))
    return epoch_losses

w0 = np.zeros(d)
n_epochs = 40
L = np.linalg.eigvalsh(X.T @ X / n).max()
eta = 1.0 / L

losses_gd = run_method(X, y, w0, n_epochs, "GD", B=n, eta=eta)
losses_sgd1 = run_method(X, y, w0, n_epochs, "SGD1", B=1, eta=eta*0.05)
losses_sgd16 = run_method(X, y, w0, n_epochs, "SGD16", B=16, eta=eta*0.5)

plt.figure(figsize=(8, 5))
plt.plot(losses_gd, label="GD (full batch)", linewidth=2)
plt.plot(losses_sgd1, alpha=0.8, label="SGD B=1 (noisy)", linewidth=1)
plt.plot(losses_sgd16, alpha=0.8, label="SGD B=16", linewidth=1.5)
plt.yscale("log")
plt.xlabel("Epoch"); plt.ylabel("Loss")
plt.title("GD vs SGD: Loss per Epoch")
plt.legend(); plt.grid(True, alpha=0.3)
plt.show()

print("Notice: full-batch GD is smooth but makes one update per epoch; SGD B=1 is noisy yet far cheaper per step.")

Key takeaways#

  • SGD replaces the full gradient with a mini-batch average that is unbiased but noisy, with variance scaling as 1/B1/B1/B.
  • Cost per update falls from O(nd)\mathcal{O}(nd)O(nd) to O(Bd)\mathcal{O}(Bd)O(Bd), so SGD takes roughly n/Bn/Bn/B updates in the time full-batch GD takes one.
  • A fixed step size leaves SGD oscillating in a ball of radius proportional to η\etaη; decaying η\etaη is what buys convergence to the optimum.
  • Batch size and learning rate trade off multiplicatively: the linear scaling rule lets you roughly double η\etaη when you double BBB.
  • Epoch-level loss is the meaningful curve; step-level loss is a noisy estimate from a single batch.
  • The noise structure introduced here is the input to momentum (Week 7) and Adam (Week 8).

Further reading#

  • Léon Bottou, Frank E. Curtis & Jorge Nocedal, Optimization Methods for Large-Scale Machine Learning (SIAM Review, 2018). Section 5 is the standard analysis of SGD, mini-batching, and step-size schedules.
  • Ian Goodfellow, Yoshua Bengio & Aaron Courville, Deep Learning (MIT Press, 2016). §8.3 covers mini-batch and stochastic gradient methods.
  • Herbert Robbins & Sutton Monro, "A Stochastic Approximation Method" (Annals of Mathematical Statistics, 1951). The original stochastic-approximation result behind SGD.

Reading is free. PDF and ePub unlock with the newsletter. Join once and every lesson opens in this browser.

← Previous
Week 5: Classification Losses
Next →
Week 7: Momentum and Acceleration
On this page
  • Finite-sum objectives
  • Mini-batch SGD
  • Noise and variance
  • Step sizes under noise
  • Epoch vs step
  • Knowledge check
  • Browser lab: GD vs SGD noise tradeoff
  • Key takeaways
  • Further reading