AdaGrad and RMSProp

Imagine training a network where one feature — say, a rare word in a vocabulary — appears in only a handful of mini-batches. Another feature, meanwhile, appears in nearly every batch. A single global learning rate forces an impossible compromise. Too large, and the frequent feature's weights oscillate wildly. Too small, and the rare feature's weights barely move at all. This happens since it gets scaled updates so infrequently. This tension between sparse and dense gradient signals is a real obstacle. It appears in language models, recommendation systems, and any task with heavy-tailed feature frequencies. AdaGrad and RMSProp solve this by giving each parameter its own effective learning rate. This rate shrinks according to how large that parameter's past gradients have been. Parameters that receive large, frequent gradients get their steps dampened. Parameters that receive small, rare gradients keep taking relatively large steps. This single idea — per-coordinate adaptive scaling — reshaped how practitioners think about optimizers. It moved thinking away from one global step size. Instead, practitioners now use a vector of step sizes that evolves with the optimization trajectory. The two methods share a mechanism: accumulate squared gradients, divide the step by their square root. But they differ in memory: AdaGrad sums forever, RMSProp forgets exponentially. That single design change — sum versus exponential moving average — has an enormous practical consequence. It determines whether the effective learning rate is monotonically decaying (AdaGrad). Or whether it can adapt continuously to a nonstationary loss landscape (RMSProp). Understanding this contrast is the essential bridge to modern optimizers like Adam. This article derives both algorithms from first principles and gives exact pseudocode. It analyzes their complexity and convergence behavior. It traces through a worked numerical example showing the divergence between the two methods. It also surveys the historical path from AdaGrad's regret-bound theory to RMSProp's practical fix for deep learning.

Key takeaways
  • AdaGrad and RMSProp give every parameter its own learning rate, scaled by the inverse square root of accumulated squared gradients.
  • AdaGrad accumulates squared gradients over all of training, causing the effective step size to shrink monotonically and eventually vanish.
  • RMSProp replaces the running sum with an exponential moving average, so the denominator "forgets" old gradients and the learning rate can stay useful indefinitely.
  • Both methods rescale each coordinate independently, which helps enormously with sparse features and differently-scaled parameters.
  • AdaGrad has a clean regret bound from online convex optimization; RMSProp trades that guarantee for practical performance on nonconvex, nonstationary deep learning objectives.
  • Both are direct ancestors of Adam, which adds momentum on top of RMSProp-style adaptive scaling.
The core insight

Divide each parameter's gradient step by the square root of that parameter's accumulated (or exponentially averaged) squared gradient history, so frequently and strongly updated parameters automatically get smaller steps.

The idea

In plain Stochastic and Mini-Batch Gradient Descent, every parameter θi\theta_i is updated by the same global learning rate η\eta:

θi←θi−η gi,\theta_i \leftarrow \theta_i - \eta \, g_i,

where gi=∂L/∂θig_i = \partial L / \partial \theta_i is the gradient of the loss with respect to that parameter on the current mini-batch. This treats all coordinates identically, which is wasteful when the loss surface is curved very differently along different directions — a common situation in deep networks, where some weights sit in flat regions and others in steep, narrow ravines.

AdaGrad (Adaptive Gradient algorithm) fixes this by maintaining, for each parameter, a running sum of squared gradients seen so far:

ri←ri+gi2,θi←θi−ηri+ϵ gi.r_i \leftarrow r_i + g_i^2, \qquad \theta_i \leftarrow \theta_i - \frac{\eta}{\sqrt{r_i} + \epsilon}\, g_i.

Here rir_i accumulates over the entire history of training, and ϵ\epsilon (typically 10−810^{-8} to 10−1010^{-10}) prevents division by zero. Because rir_i only grows, the effective learning rate η/(ri+ϵ)\eta / (\sqrt{r_i}+\epsilon) only shrinks — a feature that is provably optimal for the online convex setting AdaGrad was designed for, but becomes a liability in long-running deep network training.

RMSProp (Root Mean Square Propagation) keeps the same denominator idea but replaces the sum with an exponential moving average (EMA) of squared gradients, controlled by a decay rate ρ\rho (commonly 0.90.9 or 0.990.99):

ri←ρ ri+(1−ρ) gi2,θi←θi−ηri+ϵ gi.r_i \leftarrow \rho\, r_i + (1-\rho)\, g_i^2, \qquad \theta_i \leftarrow \theta_i - \frac{\eta}{\sqrt{r_i} + \epsilon}\, g_i.

Because old squared gradients are discounted geometrically, rir_i tracks the recent magnitude of gradients rather than their entire history. This lets the effective learning rate rise again if gradients shrink, and shrink again if gradients grow — exactly the adaptivity needed on the nonstationary, nonconvex loss surfaces of deep networks, where the local curvature along a given direction changes substantially as training progresses.

How it works

Both algorithms are drop-in replacements for the update rule inside a standard mini-batch training loop. The only state added is one accumulator vector rr, the same shape as the parameter vector θ\theta. ```

# Shared setup Initialize parameters θ Initialize accumulator r ← 0 (same shape as θ) Choose global learning rate η (e.g., 0.01 for AdaGrad, 0.001 for RMSProp) Choose ε (e.g., 1e-8) Choose decay ρ (RMSProp only, e.g., 0.9) for t = 1, 2, 3, ... until convergence: Sample mini-batch B_t g ← ∇_θ L(θ; B_t) # gradient on this mini-batch, elementwise vector

# --- AdaGrad update --- r ← r + g ⊙ g # elementwise square, accumulate forever Δθ ← -(η / (sqrt(r) + ε)) ⊙ g # elementwise divide θ ← θ + Δθ

# --- RMSProp update (replaces the two lines above) --- r ← ρ · r + (1 - ρ) · (g ⊙ g) # exponential moving average of squared gradient Δθ ← -(η / (sqrt(r) + ε)) ⊙ g θ ← θ + Δθ ``` Every operation above (`⊙`, `sqrt`, `/`) is elementwise — each coordinate ii of θ\theta gets its own scalar accumulator rir_i and its own effective step size. No cross-coordinate interaction occurs; this is what makes the method "per-parameter."

Why the square root? Squaring the gradient before accumulating makes rir_i track the magnitude of gradients regardless of sign (a large negative gradient should shrink the step just as much as a large positive one). Taking the square root before dividing restores the original units: gi/rig_i / \sqrt{r_i} has the same units as gi/∣gi∣g_i / |g_i|-scale, i.e., the division converts the raw gradient into something closer to a unit-scaled direction, similar in spirit to a per-coordinate Newton step using a diagonal curvature estimate.

Why ϵ\epsilon matters in practice. At t=1t=1 for AdaGrad, ri=gi2r_i = g_i^2, so the update is −η gi/(∣gi∣+ϵ)≈−η⋅sign(gi)-\eta \, g_i / (|g_i| + \epsilon) \approx -\eta \cdot \text{sign}(g_i) when ∣gi∣≫ϵ|g_i| \gg \epsilon — the very first step is already close to a fixed-magnitude step in the gradient's direction, not a large uncontrolled step. If ϵ\epsilon is too large relative to typical gradient magnitudes, it dominates the denominator and adaptivity is suppressed; if too small, numerical division by a near-zero rir_i for a parameter that has genuinely never received a gradient (e.g., an unused embedding row) can produce instability.

Figure
Two accumulators, one mechanism: AdaGrad sums forever, RMSProp forgets exponentially
gradient g_t g_t ⊙ g_t AdaGrad r ← r + g²  (sum, never decays) r grows unbounded → step → 0 RMSProp r ← ρ·r + (1−ρ)·g²  (EMA) r tracks recent magnitude, can rise or fall θ ← θ − (η / (√r + ε)) ⊙ g elementwise, per-parameter step size

Complexity & correctness

Time complexity. Each step requires computing the gradient gg (cost dominated by the forward/backward pass of the network, O(P)O(P) where PP is the number of parameters, same as plain SGD), then performing a constant number of elementwise operations on vectors of length PP: squaring, one multiply-add for the accumulator update, one square root, one division, one scaled subtraction. All of these are O(P)O(P) per step. So AdaGrad and RMSProp cost exactly the same asymptotic time per step as SGD, O(P)O(P) beyond the gradient computation itself — the adaptive scaling adds only a small constant-factor overhead (a handful of elementwise vector operations), which is negligible compared to the cost of the forward/backward pass in any real network.

Space complexity. Both methods store one extra vector rr of size PP, i.e., O(P)O(P) additional memory — doubling the optimizer's state footprint relative to vanilla SGD (which needs none), but this is standard and modest compared to the memory needed for activations during backpropagation.

Correctness / why it works — AdaGrad. AdaGrad was originally derived and analyzed in the framework of online convex optimization. For a sequence of convex loss functions ftf_t observed online, and true (not stochastic-noisy) subgradients gt=∇ft(θt)g_t = \nabla f_t(\theta_t), AdaGrad's diagonal preconditioning achieves a regret bound

RegretT=∑t=1Tft(θt)−min⁡θ∑t=1Tft(θ)  ≤  O ⁣(∑i=1P∥g1:T,i∥2),\text{Regret}_T = \sum_{t=1}^T f_t(\theta_t) - \min_\theta \sum_{t=1}^T f_t(\theta) \;\le\; O\!\left(\sum_{i=1}^P \|g_{1:T,i}\|_2 \right),

which is never worse, and can be much better, than the O(T)O(\sqrt{T}) bound of plain online gradient descent, especially when gradients are sparse — i.e., when most gt,ig_{t,i} are zero for most tt, so the per-coordinate norm ∥g1:T,i∥2\|g_{1:T,i}\|_2 stays small for rarely-updated coordinates. Intuitively: the bound rewards AdaGrad for adapting to geometry — it behaves like an adaptively-chosen diagonal Mahalanobis norm rather than the fixed Euclidean norm implicit in plain gradient descent. The tradeoff is that this same monotonic accumulation, which is what makes the regret bound provable, is exactly what causes the effective learning rate to decay towards zero over a long non-convex training run: since rir_i never decreases, η/(ri+ϵ)→0\eta/(\sqrt{r_i}+\epsilon) \to 0 as t→∞t \to \infty whenever gradients keep arriving, and training can stall long before reaching a good minimum.

Correctness / why it works — RMSProp. RMSProp abandons the clean online-regret guarantee in exchange for tracking a nonstationary signal. Because rir_i is an exponential moving average with a fixed decay ρ\rho, it has an effective "window" of roughly 1/(1−ρ)1/(1-\rho) recent steps (e.g., ρ=0.9⇒\rho = 0.9 \Rightarrow effective window ≈10\approx 10 steps): old gradient information is discounted geometrically and eventually forgotten. This means rir_i estimates E[gi2]\mathbb{E}[g_i^2] over a sliding recent window rather than over all of history, so if the gradient scale for a coordinate shrinks later in training (e.g., because the network has entered a flatter region), rir_i shrinks too and the effective step size grows back — unlike AdaGrad, whose accumulator can never shrink. This adaptivity to a moving target is essential in deep learning, where the loss landscape's local curvature changes continually as other parameters move (the gradient distribution for any one weight is nonstationary due to the other weights changing under it). RMSProp has no known regret bound of the AdaGrad type — it was introduced as an unpublished but widely validated empirical fix, and its justification is primarily the extensive empirical record of successful deep network training, together with the informal argument above about tracking a moving second-moment estimate. This is the honest tradeoff: AdaGrad's guarantee is provable but eventually self-defeating in non-convex deep learning; RMSProp's guarantee is empirical but far more useful in practice.

A shared invariant worth checking. In both algorithms ri≥0r_i \ge 0 always (sums and convex combinations of squares), so ri\sqrt{r_i} is always well-defined and the denominator ri+ϵ\sqrt{r_i}+\epsilon is always strictly positive — the update is always well-defined, never a division by exactly zero, which is the basic well-posedness property any implementation must preserve.

Worked example

Consider two parameters, θ1\theta_1 (a "dense" feature weight receiving a moderate gradient every step) and θ2\theta_2 (a "sparse" feature weight receiving a large gradient only occasionally, zero otherwise). Take η=1\eta = 1, ϵ=0\epsilon = 0 for clarity, ρ=0.9\rho = 0.9 for RMSProp. Suppose the gradient sequence over 4 steps is:

step ttg1g_1 (dense)g2g_2 (sparse)
11.05.0
21.00.0
31.00.0
41.05.0

AdaGrad trace (ri←ri+gi2r_i \leftarrow r_i + g_i^2, step =gi/ri= g_i/\sqrt{r_i}):

ttr1r_1step1=g1/r1_1 = g_1/\sqrt{r_1}r2r_2step2=g2/r2_2 = g_2/\sqrt{r_2}
1111/1=1.001/1 = 1.0025255/5=1.005/5 = 1.00
2221/1.414=0.711/1.414 = 0.7125250/5=0.000/5 = 0.00
3331/1.732=0.581/1.732 = 0.5825250/5=0.000/5 = 0.00
4441/2.000=0.501/2.000 = 0.5050505/7.07=0.715/7.07 = 0.71

Note the effect: θ1\theta_1's step size shrinks monotonically (1.00→0.71→0.58→0.501.00 \to 0.71 \to 0.58 \to 0.50) purely because it keeps receiving gradients — even though every g1g_1 has the same magnitude, 1.01.0, each step. Meanwhile θ2\theta_2's accumulator stays frozen at r2=25r_2=25 during the zero-gradient steps (t=2,3t=2,3), so when a gradient finally reappears at t=4t=4 its step (0.710.71) is comparable to the very first step (1.001.00) — AdaGrad preserved a usable step size for the rare feature.

RMSProp trace (ri←0.9 ri+0.1 gi2r_i \leftarrow 0.9\,r_i + 0.1\,g_i^2, r0=0r_0 = 0):

ttr1r_1step1_1r2r_2step2_2
10.10.11/0.316=3.161/0.316 = 3.162.52.55/1.581=3.165/1.581 = 3.16
20.190.191/0.436=2.291/0.436 = 2.292.252.250/1.5=0.000/1.5 = 0.00
30.2710.2711/0.521=1.921/0.521 = 1.922.0252.0250/1.423=0.000/1.423 = 0.00
40.3440.3441/0.586=1.711/0.586 = 1.714.324.325/2.078=2.415/2.078 = 2.41

RMSProp's step for θ1\theta_1 also decreases across these 4 steps (3.16→2.29→1.92→1.713.16 \to 2.29 \to 1.92 \to 1.71) — but it is converging toward a steady state, not decaying to zero. If the gradient sequence for θ1\theta_1 continued at g1=1.0g_1 = 1.0 forever, r1r_1 would converge to a fixed point r⋆r^\star solving r⋆=0.9r⋆+0.1(1)2⇒r⋆=1.0r^\star = 0.9 r^\star + 0.1(1)^2 \Rightarrow r^\star = 1.0, giving a constant long-run step size of 1/1.0=1.01/\sqrt{1.0} = 1.0 — it never vanishes, unlike AdaGrad's ever-shrinking 1/t1/\sqrt{t}-type decay. This is the crux of the practical difference: run both optimizers for 10,00010{,}000 more steps with the same constant gradient, and AdaGrad's step for θ1\theta_1 keeps shrinking toward zero while RMSProp's settles at a fixed, useful value.

Common pitfalls & traps

PitfallWhy it happensFix
Using AdaGrad for long deep-network trainingAccumulator rr only grows, so the effective learning rate decays to near zero and training stalls far from a good optimumPrefer RMSProp (or Adam) for non-convex, many-epoch training; reserve AdaGrad for convex or sparse, short-horizon problems
Setting ϵ\epsilon too small (e.g., 10−1210^{-12}) with float32For coordinates with genuinely zero or tiny historical gradient, ri+ϵ\sqrt{r_i}+\epsilon underflows or is dominated by float rounding, causing huge/unstable stepsUse a moderate ϵ\epsilon (e.g., 10−810^{-8}) and match precision to ϵ\epsilon's scale
Forgetting the accumulator is per-parameter, not globalSome learners mistakenly think rr is a single scalar shared across the whole network, which would just be a global rescaling, not adaptivityrr must be the same shape as θ\theta; every coordinate keeps its own scalar accumulator
Choosing the same global η\eta for AdaGrad and RMSPropAdaGrad's denominator grows unboundedly so it needs a larger nominal η\eta early on to compensate; RMSProp's denominator stabilizes so its η\eta behaves more like a constant-scale hyperparameterTune η\eta separately per method; typical RMSProp η≈10−3\eta \approx 10^{-3}, AdaGrad often needs η≈10−2\eta \approx 10^{-2}
Treating ρ\rho as unimportantρ\rho sets the effective memory window (≈1/(1−ρ)\approx 1/(1-\rho) steps); too small a ρ\rho makes rir_i noisy and step sizes jitter, too large makes RMSProp behave almost like AdaGrad within the training horizonDefault ρ=0.9\rho = 0.9 or 0.990.99 is a reasonable starting point; tune for the batch size and noise level

Pioneers & history

AdaGrad emerged from the online convex optimization community, where the goal was not deep learning specifically but robust, theoretically-grounded online learning with per-coordinate adaptivity for sparse, high-dimensional data such as text and click-through logs. RMSProp, in contrast, was a pragmatic fix proposed within the neural network community once it became clear that AdaGrad's ever-shrinking learning rate was unsuitable for the long, nonconvex training runs required by deep networks.

Origins · 1 minJohn C. Duchi and how this was discovered
JC
John C. Duchi
1980s birth (contemporary) · Statistics and online learning theorist who co-developed AdaGrad while working on adaptive subgradient methods for online and stochastic optimization

GE
Geoffrey E. Hinton
born 1947 · Cognitive scientist and machine learning researcher whose Coursera lecture "Neural Networks for Machine Learning" introduced RMSProp, and whose broader work on backpropagation and deep learning underlies the training methods this article builds on

History
2011
— Duchi, Hazan, and Singer publish AdaGrad, with a regret bound for online convex optimization with per-coordinate adaptive step sizes.
2012
— Tieleman and Hinton introduce RMSProp in an online course lecture, as an unpublished fix to AdaGrad's vanishing learning-rate problem for neural networks.
2012–2014
— RMSProp becomes widely adopted for training deep convolutional and recurrent networks, especially where AdaGrad had stalled.
2014
— Kingma and Ba combine RMSProp-style adaptive scaling with momentum to produce Adam, rapidly becoming the default optimizer for deep learning.
2016
–present — Adaptive methods and their variants remain standard in large-scale training, alongside continued research into their generalization behavior relative to plain SGD.

Where this matters

Adaptive per-parameter learning rates are indispensable whenever a model has features or parameters with wildly different update frequencies or gradient scales. Natural language processing systems with huge, sparse word-embedding tables rely on exactly this property: common words get frequent, well-damped updates while rare words retain large enough steps to actually learn something from their few appearances — a scenario close to the sparse-gradient setting AdaGrad was designed for. RMSProp and its descendants are used extensively in recurrent network training, where gradient magnitudes can vary enormously across time steps and layers, and where the loss surface changes character continuously as training proceeds — exactly the nonstationary regime RMSProp targets. In production deep learning frameworks, both algorithms are available as standard optimizer classes, but RMSProp is more often chosen for practical training given its resistance to premature learning-rate collapse, while AdaGrad persists in linear/convex online-learning systems such as click-through-rate prediction, contextual bandits, and other settings closer to its original theoretical home. Both are also the direct conceptual ancestors of Adam, which layers first-moment (momentum) estimation on top of RMSProp's second-moment adaptive scaling, becoming the default optimizer choice across most of modern deep learning — a connection the study of Adam and Its Variants develops fully.

Ask the tutor: How does adding momentum to RMSProp's adaptive scaling produce the Adam optimizer's update rule?

Why do we square the gradient before accumulating instead of just accumulating the gradient directly?

Squaring removes the sign, so both large positive and large negative gradients contribute equally to shrinking the step size — what matters for adaptivity is the magnitude of past updates, not their direction. If we accumulated raw signed gradients, oscillating gradients (alternating positive and negative) would cancel out and the accumulator would stay near zero even though the parameter has actually been receiving large, noisy updates — exactly the situation where we'd want damping. Squaring guarantees the accumulator is a nonnegative, monotonically-informative measure of "how much has this coordinate been pushed around," which is the correct quantity to divide by when trying to equalize effective step sizes across coordinates with very different gradient magnitudes.

Is RMSProp strictly better than AdaGrad, so should AdaGrad ever be used?

Not strictly better — they suit different regimes. AdaGrad comes with a provable regret bound in online convex optimization, particularly strong when gradients are sparse, since rarely-active coordinates accumulate very little in their denominator and keep near-full step sizes. RMSProp sacrifices that guarantee for practical robustness in long, nonconvex, nonstationary deep learning training, where AdaGrad's monotonically shrinking rate would eventually stall progress. For genuinely convex, single-pass, or short-horizon sparse-feature problems (some online advertising or bandit settings), AdaGrad's theoretical guarantees and simplicity remain attractive; for deep networks trained over many epochs, RMSProp (or its descendant Adam) is almost always preferred.

Does adaptive scaling replace the need to tune the learning rate η at all?

No — η is still a critical hyperparameter, but its role changes. In plain SGD, η alone sets the entire step size for every coordinate. In AdaGrad/RMSProp, η sets the overall scale of the adaptive step, while the accumulator r reshapes that scale per-coordinate. A poorly chosen η can still cause divergence (too large) or painfully slow training (too small); adaptivity only fixes the relative imbalance between coordinates, not the absolute magnitude of the step. In practice, RMSProp's typical default η (around 0.001) is smaller than a typical plain-SGD learning rate, precisely because the per-coordinate division already amplifies small-gradient directions.

How does RMSProp avoid the "vanishing learning rate" problem that AdaGrad suffers from?

The exponential moving average ri←ρri+(1−ρ)gi2r_i \leftarrow \rho r_i + (1-\rho) g_i^2 has a fixed-point behavior: if gradients for coordinate ii settle into a roughly constant magnitude gˉi\bar g_i, then rir_i converges to gˉi2\bar g_i^2 rather than growing without bound — the "memory" of old, possibly larger, gradients is discounted geometrically at rate ρ\rho per step, so contributions from steps far in the past shrink to negligible weight. This means the effective learning rate η/(ri+ϵ)\eta/(\sqrt{r_i}+\epsilon) settles to a stable, nonzero value in a stationary regime, and can rise again if gradients later shrink, since rir_i itself is free to decrease. AdaGrad's plain sum has no such forgetting mechanism, so it can only ever grow.

Can adaptive methods like RMSProp generalize worse than plain SGD despite training faster?

There is empirical and some theoretical evidence that adaptive methods can converge to solutions with somewhat worse test-time generalization than well-tuned SGD with momentum, particularly on certain image classification benchmarks, even though they often train faster and are easier to tune out of the box. The precise mechanism is still debated, but one informal argument is that adaptive per-coordinate rescaling can bias the optimization trajectory toward regions of parameter space that differ systematically from those reached by isotropic SGD updates, potentially affecting the implicit regularization SGD is believed to provide. In practice, many practitioners still choose adaptive methods for the reliability and speed of training, especially on transformers and recurrent networks, while using SGD with momentum for some vision tasks where the generalization gap is more pronounced.

Why is the update elementwise rather than using a full matrix of second-moment information?

A full second-moment matrix (a dense preconditioner analogous to Newton's method with the Hessian or a full outer-product covariance of gradients) would require O(P2)O(P^2) storage and O(P3)O(P^3) or O(P2)O(P^2) operations to invert or apply — utterly infeasible for networks with millions or billions of parameters. AdaGrad's original theoretical formulation does include a full-matrix variant with provably tighter regret bounds, but essentially all practical use restricts to the diagonal approximation, storing and updating only PP scalars. This diagonal restriction sacrifices the ability to capture correlations between parameters' gradients but keeps memory and compute at O(P)O(P), matching the cost of a single gradient step and making the method usable at deep-learning scale.

What is the natural next step beyond RMSProp, and why does it matter?

RMSProp adapts the step size per coordinate but does not smooth the direction of the gradient itself — each update still uses the raw current-batch gradient gtg_t, which can be noisy. The natural next step, explored in Adam and Its Variants, is to also maintain an exponential moving average of the gradient itself (a momentum-like first-moment estimate), then divide that smoothed gradient by the RMSProp-style square-root-of-second-moment denominator, with bias-correction terms to account for the moving averages starting at zero. This combination — momentum in the numerator, adaptive scaling in the denominator — became one of the most widely used optimizers in deep learning practice.

Before this

Where this leads