AI Knowledge Tree

Stochastic gradient descent

Replace the full gradient with a stochastic estimate and understand the noise versus step-size tradeoff.

⏱ 32 minPrerequisites:Gradient descent

Machine-learning objectives are averages over millions of examples, and computing the full gradient every step is prohibitive. Stochastic gradient descent replaces it with the gradient of a small random batch: a noisy but unbiased and cheap estimate. The noise changes the convergence story, and managing it through the step-size schedule is the central practical skill.

The finite-sum objective

Training minimizes an average loss over nn examples,

f(x)=1n∑i=1nfi(x),f(x) = \frac{1}{n}\sum_{i=1}^n f_i(x),

where fif_i is the loss on example ii and xx are the parameters. The full gradient ∇f(x)=1n∑i∇fi(x)\nabla f(x) = \frac{1}{n}\sum_i \nabla f_i(x) costs a pass over all nn examples.

The stochastic update

SGD samples an index iti_t (or a small minibatch) uniformly at random and steps along that single gradient:

xt+1=xt−ηt ∇fit(xt).x_{t+1} = x_t - \eta_t\, \nabla f_{i_t}(x_t).

The key property is unbiasedness: averaging over the random draw,

Eit[∇fit(xt)]=1n∑i=1n∇fi(xt)=∇f(xt).\mathbb{E}_{i_t}[\nabla f_{i_t}(x_t)] = \frac{1}{n}\sum_{i=1}^n \nabla f_i(x_t) = \nabla f(x_t). [1]

The stochastic gradient points in the right direction on average, but any single step is corrupted by variance σ2=E∥∇fit(x)−∇f(x)∥2\sigma^2 = \mathbb{E}\lVert \nabla f_{i_t}(x) - \nabla f(x)\rVert^2.

The noise floor with a constant step size

The variance changes convergence fundamentally. For μ\mu-strongly convex, LL-smooth ff with a constant step size η\eta, the expected suboptimality satisfies a recursion of the form

E[Δt+1]≤(1−ημ) E[Δt]+η2Lσ22.\mathbb{E}[\Delta_{t+1}] \le (1 - \eta\mu)\,\mathbb{E}[\Delta_t] + \frac{\eta^2 L \sigma^2}{2}.

The first term contracts as in deterministic GD; the second injects noise every step. At the fixed point, contraction balances injection and the iterates hover at a noise floor:

lim⁡t→∞E[Δt]≈ηLσ22μ.\lim_{t \to \infty}\mathbb{E}[\Delta_t] \approx \frac{\eta L \sigma^2}{2\mu}.

Constant-step SGD converges fast to a neighborhood of the optimum, then bounces around it. The floor height is proportional to η\eta: a smaller step gives a lower floor but slower approach.

Decaying step sizes

To reach the exact optimum, the step size must shrink so the noise term vanishes. The Robbins-Monro conditions are

∑tηt=∞(steps large enough to travel any distance),∑tηt2<∞(noise sums to finite).\sum_t \eta_t = \infty \quad (\text{steps large enough to travel any distance}), \qquad \sum_t \eta_t^2 < \infty \quad (\text{noise sums to finite}). [2]

A schedule like ηt=η0/t\eta_t = \eta_0 / t satisfies both and gives E[Δt]=O(1/t)\mathbb{E}[\Delta_t] = O(1/t). In practice, step decay or cosine schedules implement the same idea: large steps early to move fast, small steps late to settle.

Why minibatches

A minibatch of size BB averages BB independent gradient estimates, cutting the variance to σ2/B\sigma^2 / B. This lowers the noise floor and lets a larger step size be used, while exploiting vectorized hardware. The minibatch size trades gradient quality against per-step cost.

Stochastic gradient descent follows noisy mini-batch gradients, rattling around the optimum, where full-batch GD descends smoothly.
Stochastic gradient descent follows noisy mini-batch gradients, rattling around the optimum, where full-batch GD descends smoothly.

Check it on arrays

python · numpy
import numpy as np

rng = np.random.default_rng(0)

# Least squares as a finite sum: f_i(x) = 0.5 (a_i^T x - b_i)^2
n, d = 2000, 10
A = rng.normal(size=(n, d))
x_true = rng.normal(size=d)
b = A @ x_true + 0.1 * rng.normal(size=n)
x_star = np.linalg.lstsq(A, b, rcond=None)[0]

def full_loss(x):
    return 0.5 * np.mean((A @ x - b)**2)

def sgd(eta, batch=1, steps=20_000, decay=False):
    x = np.zeros(d)
    for t in range(steps):
        idx = rng.integers(0, n, size=batch)
        g = A[idx].T @ (A[idx] @ x - b[idx]) / batch
        lr = eta / (1 + 0.001 * t) if decay else eta
        x = x - lr * g
    return full_loss(x) - full_loss(x_star)

# Constant step: lower eta -> lower noise floor
print("const eta=0.05, B=1 :", round(sgd(0.05), 6))
print("const eta=0.01, B=1 :", round(sgd(0.01), 6))
# Bigger batch lowers the floor at the same step size
print("const eta=0.05, B=32:", round(sgd(0.05, batch=32), 6))
# Decaying step reaches lower suboptimality
print("decaying eta0=0.05  :", round(sgd(0.05, decay=True), 6))

A smaller constant step and a larger batch both lower the noise floor, and the decaying schedule drives suboptimality further down.

Exercises

Exercise 1. A constant-step SGD run with step η\eta settles at a noise floor of height ηLσ22μ\frac{\eta L \sigma^2}{2\mu}. If halving the step is observed to halve the floor, explain why, and predict the floor after dividing the step by 1010 relative to the original.

Solution

Step 1. The floor formula ηLσ22μ\frac{\eta L \sigma^2}{2\mu} is linear in η\eta: the factors LL, σ2\sigma^2, and μ\mu are properties of the problem, fixed across runs, so only η\eta varies.

Step 2. Halving η\eta multiplies the whole expression by 12\tfrac12, which halves the floor. That linear dependence is exactly the observation.

Step 3. Dividing the step by 1010 multiplies the floor by 110\tfrac{1}{10}, so the new floor is one tenth of the original. The cost is a slower approach: the contraction factor (1−ημ)(1 - \eta\mu) moves closer to 11, so reaching the lower floor takes more steps.

Exercise 2. Show that the minibatch gradient is unbiased and that a batch of size BB drawn with replacement has variance σ2/B\sigma^2 / B. Let gB=1B∑j=1B∇fij(x)g_B = \frac{1}{B}\sum_{j=1}^B \nabla f_{i_j}(x) with the iji_j independent and uniform.

Solution

Step 1. Each draw is unbiased: E[∇fij(x)]=1n∑i∇fi(x)=∇f(x)\mathbb{E}[\nabla f_{i_j}(x)] = \frac{1}{n}\sum_i \nabla f_i(x) = \nabla f(x). By linearity of expectation, E[gB]=1B∑j=1B∇f(x)=∇f(x)\mathbb{E}[g_B] = \frac{1}{B}\sum_{j=1}^B \nabla f(x) = \nabla f(x), so the batch estimate is unbiased.

Step 2. Write the error of one draw as ej=∇fij(x)−∇f(x)e_j = \nabla f_{i_j}(x) - \nabla f(x), with E[ej]=0\mathbb{E}[e_j] = 0 and E∥ej∥2=σ2\mathbb{E}\lVert e_j\rVert^2 = \sigma^2. The batch error is gB−∇f(x)=1B∑jejg_B - \nabla f(x) = \frac{1}{B}\sum_j e_j.

Step 3. The draws are independent, so cross terms vanish in expectation, E[ej⊤ek]=0\mathbb{E}[e_j^\top e_k] = 0 for j≠kj \ne k:

E∥1B∑jej∥2=1B2∑j=1BE∥ej∥2=1B2⋅Bσ2=σ2B.\mathbb{E}\Big\lVert \tfrac{1}{B}\textstyle\sum_j e_j \Big\rVert^2 = \frac{1}{B^2}\sum_{j=1}^B \mathbb{E}\lVert e_j\rVert^2 = \frac{1}{B^2}\cdot B\sigma^2 = \frac{\sigma^2}{B}.

The variance drops as 1/B1/B: a batch of 3232 cuts gradient noise by a factor of 3232.

Exercise 3 (code). Estimate the noise floor empirically. Run constant-step SGD on a least-squares finite sum, and verify that halving the step size roughly halves the measured suboptimality floor, matching the linear η\eta dependence of Exercise 1.

Solution
python · numpy
import numpy as np

rng = np.random.default_rng(0)
n, d = 2000, 10
A = rng.normal(size=(n, d))
x_true = rng.normal(size=d)
b = A @ x_true + 0.1 * rng.normal(size=n)
x_star = np.linalg.lstsq(A, b, rcond=None)[0]

def full_loss(x):
    return 0.5 * np.mean((A @ x - b)**2)

def floor(eta, steps=40_000, tail=5_000):
    # average suboptimality over the last `tail` steps = noise-floor estimate
    x = np.zeros(d)
    acc = 0.0
    for t in range(steps):
        i = rng.integers(0, n)
        g = A[i] * (A[i] @ x - b[i])
        x = x - eta * g
        if t >= steps - tail:
            acc += full_loss(x) - full_loss(x_star)
    return acc / tail

f1 = floor(0.02)
f2 = floor(0.01)                                 # half the step
ratio = f2 / f1
print("floor(eta=0.02):", round(f1, 6))
print("floor(eta=0.01):", round(f2, 6))
print("ratio:", round(ratio, 3))

assert 0.35 < ratio < 0.75                       # near 0.5, the linear prediction

The measured floor at half the step is roughly half the original, the linear η\eta scaling predicted by the recursion's fixed point. Sampling noise keeps the ratio near but not exactly 0.50.5.

The next lesson speeds up the deterministic part with momentum.


References

  1. [1]Goodfellow, I., Bengio, Y., & Courville, A. (2016). Deep Learning, ch. 8. MIT Press. Minibatch stochastic gradient estimates and their unbiasedness.↩
  2. [2]Robbins, H., & Monro, S. (1951). "A stochastic approximation method". Annals of Mathematical Statistics, 22, 400-407. The step-size conditions for convergence (doi:10.1214/aoms/1177729586).↩