Skip to main content
© 2026 ePowerAI. All rights reserved.
CoursesContact
eAI
CoursesContact
Week 7: Momentum and Acceleration
Optimization
01Week 1: Optimization for Learning
02Week 2: Convex Sets and Functions
03Week 3: Gradient Descent Theory
04Week 4: Least Squares and Conditioning
05Week 5: Classification Losses
06Week 6: Stochastic Gradient Descent
07Week 7: Momentum and Acceleration
08Week 8: Adaptive First-Order Methods
09Week 9: Practical Training Dynamics
10Week 10: Nonsmooth and Composite Objectives
11Week 11: Constraints: Projections and Penalties
12Week 12: Duality for Practitioners
13Week 13: Nonconvex Deep Learning
14Week 14: Capstone — Theory Meets Training
Week 07· Optimization· First-order stack22 min read

Week 7: Momentum and Acceleration

✦Learning Outcomes
  • Write the heavy-ball momentum update and explain its effect: dampens oscillations, builds speed in consistent directions
  • Choose a momentum coefficient β\betaβ (common: 0.90.90.9)
  • Contrast Nesterov accelerated gradient (look-ahead gradient) with plain momentum
  • Explain why momentum reduces the O(κ)\mathcal{O}(\kappa)O(κ) iteration complexity to O(κ)\mathcal{O}(\sqrt{\kappa})O(κ​) for convex quadratics
◆Prerequisites

Background: Week 3 (GD convergence, condition number κ\kappaκ) and Week 6 (SGDStochastic Gradient Descent). The condition-number story from Week 3 directly motivates momentum.

Later weeks: Momentum is the "first moment" component inside AdamAdaptive Moment Estimation (optimizer) (Week 8), where it's combined with adaptive per-parameter step sizes.

Why Momentum?#

Recall Week 4's ill-conditioned problem: f(w)=12(w12+100w22)f(w) = \frac{1}{2}(w_1^2 + 100 w_2^2)f(w)=21​(w12​+100w22​) with κ=100\kappa = 100κ=100. GD with η=1/L\eta = 1/Lη=1/L makes rapid progress along w1w_1w1​ (steep direction) but crawls along w2w_2w2​ (shallow direction). The iterates zigzag down a narrow valley.

Momentum fixes this by adding inertia. Instead of the gradient alone determining the step, a fraction of the previous step's direction is retained:

vk+1=βvk−η∇f(wk)v_{k+1} = \beta v_k - \eta \nabla f(w_k)vk+1​=βvk​−η∇f(wk​) wk+1=wk+vk+1w_{k+1} = w_k + v_{k+1}wk+1​=wk​+vk+1​

where vkv_kvk​ is the velocity and β∈[0,1)\beta \in [0, 1)β∈[0,1) is the momentum coefficient.

The zigzag: oscillations in the steep direction cancel out when averaged over time, while progress in the shallow direction accumulates. The result is a smoother, faster trajectory.

Heavy-Ball Momentum#

The heavy-ball method (Polyak, 1964) is the classic momentum formulation:

vk+1=βvk−η∇f(wk)v_{k+1} = \beta v_k - \eta \nabla f(w_k)vk+1​=βvk​−η∇f(wk​) wk+1=wk+vk+1w_{k+1} = w_k + v_{k+1}wk+1​=wk​+vk+1​

Unrolling the velocity update reveals it as an exponential moving average:

vk+1=−η∑t=0kβk−t∇f(wt)v_{k+1} = -\eta \sum_{t=0}^k \beta^{k-t} \nabla f(w_t)vk+1​=−η∑t=0k​βk−t∇f(wt​)

Recent gradients have weight ≈1\approx 1≈1, while gradients mmm steps ago have weight βm\beta^mβm. The effective "memory" of momentum is roughly 1/(1−β)1/(1-\beta)1/(1−β) steps — with β=0.9\beta = 0.9β=0.9, about 10 steps; with β=0.99\beta = 0.99β=0.99, about 100 steps.

Practical choices for β\betaβ:

  • β=0\beta = 0β=0: recovers plain GD/SGDStochastic Gradient Descent
  • β=0.9\beta = 0.9β=0.9: standard setting — good for most problems
  • β=0.99\beta = 0.99β=0.99: longer memory, useful when gradients are very noisy (SGD with small batch)
  • β=0.999\beta = 0.999β=0.999: very long memory — used in Adam's first-moment estimate

Physical analogy: A ball rolling down a hill. The gradient is the slope (instantaneous force), momentum keeps the ball rolling in the direction it's already going. If the slope direction changes slowly, the ball accelerates; if it oscillates (zigzag valley), the oscillations cancel.

Interpreting Momentum#

For a 1D quadratic f(w)=a2w2f(w) = \frac{a}{2} w^2f(w)=2a​w2, the momentum iteration becomes a second-order linear recurrence:

wk+1=(1+β−aη)wk−βwk−1w_{k+1} = (1 + \beta - a\eta) w_k - \beta w_{k-1}wk+1​=(1+β−aη)wk​−βwk−1​

The eigenvalues of this recurrence determine convergence. The optimal β\betaβ and η\etaη for a quadratic with curvature aaa are:

η∗=4(L+μ)2,β∗=(κ−1κ+1)2\eta^* = \frac{4}{(\sqrt{L} + \sqrt{\mu})^2}, \quad \beta^* = \left(\frac{\sqrt{\kappa} - 1}{\sqrt{\kappa} + 1}\right)^2η∗=(L​+μ​)24​,β∗=(κ​+1κ​−1​)2

The resulting convergence factor is κ−1κ+1\frac{\sqrt{\kappa} - 1}{\sqrt{\kappa} + 1}κ​+1κ​−1​, compared to κ−1κ+1\frac{\kappa - 1}{\kappa + 1}κ+1κ−1​ for plain GD. For κ=100\kappa = 100κ=100, GD needs ≈200\approx 200≈200 iterations for a constant-factor reduction; momentum needs ≈20\approx 20≈20 — a 10× speedup.

Nesterov Accelerated Gradient#

Nesterov (1983) proposed a subtle but important modification:

w~k=wk+βvk\tilde w_k = w_k + \beta v_kw~k​=wk​+βvk​ vk+1=βvk−η∇f(w~k)v_{k+1} = \beta v_k - \eta \nabla f(\tilde w_k)vk+1​=βvk​−η∇f(w~k​) wk+1=wk+vk+1w_{k+1} = w_k + v_{k+1}wk+1​=wk​+vk+1​

The difference: the gradient is evaluated at w~k=wk+βvk\tilde w_k = w_k + \beta v_kw~k​=wk​+βvk​ — the point we would reach if we continued with the current velocity — instead of at the current position wkw_kwk​. This "look-ahead" gradient provides a correction before we commit to the velocity direction.

For convex quadratics, Nesterov achieves the provably optimal convergence rate: O(1/k2)\mathcal{O}(1/k^2)O(1/k2) for smooth convex (vs GD's O(1/k)\mathcal{O}(1/k)O(1/k)) and O(κlog⁡(1/ε))\mathcal{O}(\sqrt{\kappa} \log(1/\varepsilon))O(κ​log(1/ε)) for strongly convex.

In deep learning practice, the distinction between heavy-ball and Nesterov momentum is often minor — both work well, and the choice is usually dictated by framework defaults.

Convergence Benefit#

For a convex LLL-smooth function, Nesterov's accelerated gradient achieves:

f(xK)−f(x∗)≤2L∥x0−x∗∥2K2f(x_K) - f(x^*) \leq \frac{2L \|x_0 - x^*\|^2}{K^2}f(xK​)−f(x∗)≤K22L∥x0​−x∗∥2​

Compare to GD: 2L∥x0−x∗∥2K\frac{2L\|x_0 - x^*\|^2}{K}K2L∥x0​−x∗∥2​. The acceleration improves the denominator from KKK to K2K^2K2 — a quadratic improvement in the number of iterations. To reach accuracy ε\varepsilonε, GD needs O(1/ε)\mathcal{O}(1/\varepsilon)O(1/ε) iterations; Nesterov needs O(1/ε)\mathcal{O}(1/\sqrt{\varepsilon})O(1/ε​).

When does momentum actually help?

  • Ill-conditioned convex problems: large speedup
  • Well-conditioned problems: little benefit (GD is already fast)
  • Nonconvex problems (deep nets): empirical benefit from dampening oscillations and escaping shallow regions — though theoretical guarantees are weaker
  • SGD with momentum: reduces variance in the update direction, acting as a variance-reduction technique alongside the adaptive step-size role
Exercise · Fill in the blank

If $\\beta = 0$, momentum SGD reduces to plain ___.

Question 1 of 4

The heavy-ball momentum update v_{k+1} = β v_k − η ∇f(w_k) can be seen as:

An exponential moving average of past gradients
A simple scaling of the current gradient
A random perturbation of the gradient
A second-derivative approximation

Browser lab#

Compare GD, momentum, and Nesterov on an ill-conditioned 2D quadratic (κ≈100\kappa \approx 100κ≈100). Plot iterate trajectories and loss vs iteration.

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

Q = np.diag([100.0, 1.0])

def f(w): return 0.5 * (w @ Q @ w)
def grad(w): return Q @ w

L = 100.0; mu = 1.0
eta_gd = 1.0 / L
eta_mom = 4.0 / (np.sqrt(L) + np.sqrt(mu))**2
beta_mom = ((np.sqrt(L/mu) - 1) / (np.sqrt(L/mu) + 1))**2

w0 = np.array([0.5, 10.0])
K = 200

def run_gd(w0, K, eta):
    w = w0.copy(); path = [w.copy()]; losses = [f(w)]
    for _ in range(K):
        w = w - eta * grad(w)
        path.append(w.copy()); losses.append(f(w))
    return np.array(path), np.array(losses)

def run_momentum(w0, K, eta, beta, nesterov=False):
    w = w0.copy(); v = np.zeros(2)
    path = [w.copy()]; losses = [f(w)]
    for _ in range(K):
        if nesterov:
            g = grad(w + beta * v)
        else:
            g = grad(w)
        v = beta * v - eta * g
        w = w + v
        path.append(w.copy()); losses.append(f(w))
    return np.array(path), np.array(losses)

path_gd, loss_gd = run_gd(w0, K, eta_gd)
path_mom, loss_mom = run_momentum(w0, K, eta_mom, beta_mom, nesterov=False)
path_nes, loss_nes = run_momentum(w0, K, eta_mom, beta_mom, nesterov=True)

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))
ax1.plot(path_gd[:, 0], path_gd[:, 1], alpha=0.6, label="GD")
ax1.plot(path_mom[:, 0], path_mom[:, 1], alpha=0.6, label="Momentum")
ax1.plot(path_nes[:, 0], path_nes[:, 1], alpha=0.6, label="Nesterov")
ax1.plot(0, 0, "kx", markersize=8)
ax1.set_xlabel("w1"); ax1.set_ylabel("w2")
ax1.set_title("Iterate Paths"); ax1.legend()
ax2.semilogy(loss_gd, label="GD"); ax2.semilogy(loss_mom, label="Momentum")
ax2.semilogy(loss_nes, label="Nesterov")
ax2.set_xlabel("Iteration"); ax2.set_ylabel("Loss")
ax2.set_title("Loss vs Iteration"); ax2.legend(); ax2.grid(True, alpha=0.3)
plt.tight_layout(); plt.show()
← Previous
Week 6: Stochastic Gradient Descent
Next →
Week 8: Adaptive First-Order Methods
On this page
  • Why Momentum?
  • Heavy-Ball Momentum
  • Interpreting Momentum
  • Nesterov Accelerated Gradient
  • Convergence Benefit
  • Browser lab