LSTMs and GRUs
Imagine training a network to predict the next word in a paragraph. The crucial clue appeared a hundred words earlier. A plain Recurrent Neural Network trained with Backpropagation Through Time tries to carry that information forward. It does this through a hundred repeated multiplications. The signal either explodes or, far more often, decays into numerical silence. This is the vanishing gradient problem. It is not a minor nuisance. It is the reason vanilla RNNs are effectively short-memory systems. This holds no matter how large you make their hidden state. Long Short-Term Memory (LSTM) networks, introduced in 1997, and Gated Recurrent Units (GRUs), introduced in 2014, solve this by redesigning the recurrence itself. Instead of forcing information through a single nonlinear squashing function at every timestep, they introduce a separate memory pathway. This is a cell state or hidden state that gates can write to, read from, and protect. It is controlled by learned gates that decide what to remember, what to forget, and what to output. The gates are themselves small neural networks. They are trained end-to-end alongside everything else. So the model learns its own memory policy from data, rather than having one hand-engineered. This idea mattered enormously in practice. Before attention-based and transformer architectures dominated, LSTMs powered production systems. They ran machine translation, speech recognition, and handwriting recognition at Google, Apple, and Baidu. GRUs offered a lighter-weight alternative with comparable performance and fewer parameters. This was useful when compute or memory was tight. Even today, gated recurrent architectures remain a strong, simple baseline. This holds in domains with strict latency budgets, streaming requirements, or modest data. This article explains precisely how the gates are computed. It shows why the additive cell-state update is the mathematical key to preventing gradient vanishing. It walks through a full numerical trace of an LSTM cell. It compares LSTM against GRU design tradeoffs. Finally, it situates both historically, before they gave way to attention mechanisms in Encoder-Decoder Architectures.
- LSTMs and GRUs replace the single RNN recurrence with gated units that control information flow explicitly.
- The LSTM cell state is updated additively (via forget and input gates), which is the key fix for vanishing gradients.
- GRUs merge the cell and hidden state into one vector and use only two gates, trading some expressiveness for efficiency.
- Both process sequences in time and per-step memory beyond the hidden state, same asymptotic cost as vanilla RNNs.
- Gate values are learned functions of input and previous hidden state, giving data-driven, per-dimension memory control.
- They were the dominant sequence architecture for a decade before being displaced by attention-based transformers.
Gated recurrent units fix vanishing gradients by letting information flow through an additive, gate-controlled memory path instead of a single repeatedly-squashed nonlinear recurrence.
The idea
A vanilla RNN updates its hidden state as . During backpropagation through time, the gradient of the loss with respect to involves a product of Jacobians, each roughly . Since and is typically much smaller away from the origin, and since repeated multiplication by the same (or similarly-scaled) matrix tends to shrink or blow up singular values geometrically, the gradient magnitude scales roughly like for some effective factor . For this vanishes exponentially in ; for it explodes. This is the vanishing/exploding gradient problem, and it means vanilla RNNs cannot reliably learn dependencies spanning more than a few dozen steps. The LSTM (Long Short-Term Memory) fixes this by introducing a separate cell state that is updated by addition rather than repeated nonlinear transformation:
Here (the forget gate) and (the input gate) are vectors in , produced by sigmoid layers, and is a candidate update. Because this update is additive rather than a matrix-multiply-then-squash, the gradient (elementwise), with no forced contraction from a shared weight matrix. If the network learns for the dimensions that must persist, gradients flow through those dimensions almost unchanged across arbitrarily many steps — this is the mechanism, not a heuristic, that mitigates vanishing gradients. A separate hidden state (output) is derived from the cell state via an output gate : . All three gates and the candidate are computed from the same inputs via learned affine transforms followed by nonlinearities — sigmoids for gates (bounding them to act as soft switches in ), for the candidate content (bounding value magnitude to for stability). The GRU (Gated Recurrent Unit) simplifies this design by merging the cell state and hidden state into a single vector , and using only two gates: an update gate (playing a role similar to a combined forget/input gate) and a reset gate (controlling how much past information is used when computing the candidate). This yields comparable gradient-flow benefits with fewer parameters and one fewer state vector to carry, at the cost of slightly less fine-grained control over memory (no independent input/forget/output decisions).
How it works
LSTM cell. At each timestep , given input , previous hidden state , and previous cell state , compute:
GRU cell. Given and only (no separate cell state):
The GRU's update is structurally identical to the LSTM's update — a convex combination controlled by a gate — which is exactly what preserves the additive gradient path. The reset gate additionally lets the network "forget" past context specifically when forming the candidate, without discarding itself in the final blend. ``` function LSTM_STEP(x_t, h_prev, c_prev, params):
# params bundles W_, U_, b_ for f, i, o, c f_t = sigmoid(params.Wf @ x_t + params.Uf @ h_prev + params.bf) i_t = sigmoid(params.Wi @ x_t + params.Ui @ h_prev + params.bi) o_t = sigmoid(params.Wo @ x_t + params.Uo @ h_prev + params.bo) c_tilde = tanh(params.Wc @ x_t + params.Uc @ h_prev + params.bc) c_t = f_t c_prev + i_t c_tilde # elementwise; additive update h_t = o_t tanh(c_t) return h_t, c_t
function GRU_STEP(x_t, h_prev, params): z_t = sigmoid(params.Wz @ x_t + params.Uz @ h_prev + params.bz) r_t = sigmoid(params.Wr @ x_t + params.Ur @ h_prev + params.br) h_tilde = tanh(params.Wh @ x_t + params.Uh @ (r_t h_prev) + params.bh) h_t = (1 - z_t) h_prev + z_t * h_tilde return h_t
function RUN_SEQUENCE(inputs x_1..x_T, params, cell_type): h = zeros(d) c = zeros(d) # unused for GRU outputs = [] for t in 1..T: if cell_type == LSTM: h, c = LSTM_STEP(x_t, h, c, params) else: h = GRU_STEP(x_t, h, params) outputs.append(h) return outputs # feed into loss / next layer ``` Training proceeds exactly as with a vanilla RNN: unroll the recurrence across timesteps, compute a loss on the outputs, and run Backpropagation Through Time to get gradients with respect to all shared weight matrices . The only difference from a vanilla RNN is the richer local computational graph at each timestep — more nodes, but each still work and the chain rule still applies mechanically.
Complexity & correctness
Time complexity. At each timestep, an LSTM computes four affine transforms of size (each gate/candidate uses a recurrent matrix and a input matrix), where is hidden size and is input size. So each step costs , and a full sequence of length costs . A GRU has three affine transforms instead of four, so it is a constant factor () cheaper per step but the same asymptotic order. Both match vanilla RNNs in asymptotic time complexity — the constant factor (3× or 4× more matrix multiplies) is the real cost of gating, not a complexity-class change.
Space complexity. Per-step memory is for the hidden state (plus for the cell state in LSTM); storing all intermediate activations for backpropagation through time costs , since every gate/candidate value at every timestep must be cached for the backward pass. Parameter count is for GRU and times that for LSTM, independent of .
Correctness of the gradient-flow fix — the key argument. Consider the cell-state recurrence . The partial derivative of with respect to , holding gates fixed, is:
Compare this to the vanilla RNN's , which involves the same shared matrix at every step — its eigenvalues, raised to the -th power over steps, dictate exponential growth or decay independent of what the task needs. In contrast involves no matrix multiplication at all, just an elementwise gate that the network learns per-dimension, per-timestep. If the network sets (learned, e.g., by biasing to be large and positive at initialization — a well-known practical trick), then
so gradients backpropagate through the cell-state path across arbitrarily many steps without forced exponential decay. This is not a guarantee that gradients never vanish (if the task genuinely requires at some step, that path should attenuate), but it removes the structural obstruction that plagued vanilla RNNs: the network now has the freedom, via learnable gates, to choose long memory when the task demands it. The same reasoning applies to the GRU's , where has a term along the direct path.
Tradeoffs. Gating does not eliminate vanishing gradients in the output gate / hidden-state path (LSTM's still passes through and gate multiplications every step), and very long sequences (thousands of steps) can still be difficult. LSTMs have more parameters and compute than GRUs for the same hidden size, which matters at scale; GRUs sometimes underperform LSTMs on tasks needing finer memory control (e.g., counting tasks benefit from LSTM's independent output gate). Both remain strictly sequential across time — step needs — so they cannot be parallelized across the sequence dimension the way transformer self-attention can, which is the main reason they were later superseded in large-scale settings.
Worked example
Consider a toy LSTM with hidden size , scalar input , tracking whether a running total of a stream of numbers has ever exceeded a threshold (a task requiring long memory: the "exceeded" fact must persist regardless of later inputs). Suppose after training, the relevant gate weights approximately realize: forget gate saturates near once the flag dimension is set (protecting the memory), input gate opens briefly at the triggering timestep, then closes. Trace with hand-picked (simplified, illustrative) parameter values, hidden dimension 1 (the "flag" unit), input = the stream value, threshold behavior baked into weights:
| 0 | – | – | – | – | – | ||
| 1 | 0.2 | 0.95 | 0.10 | 0.30 | 0.5 | ||
| 2 | 0.9 | 0.90 | 0.85 | 0.95 | 0.6 | ||
| 3 | 0.1 | 0.98 | 0.05 | 0.10 | 0.9 | ||
| 4 | 0.0 | 0.99 | 0.02 | 0.00 | 0.95 |
Read the trace as a story: at the input crosses the threshold, the input gate opens () and lets a large candidate value () into the cell state, jumping from near to . From onward, even though the raw inputs drop back to small values, the forget gate stays close to 1 (), so the cell state is barely eroded () — the network has "remembered" that the threshold was crossed. The output gate grows over time, gradually exposing more of this memory into , which a downstream classifier reads to answer "has the threshold ever been exceeded?" A vanilla RNN attempting the same task would have to re-encode this fact through a -squashed matrix multiply at every single step, and — because always — that signal would erode multiplicatively rather than being protected by a near-1 gate. For a gradient-flow comparison, suppose over 20 further steps the forget gate averages per dimension. The surviving fraction of the gradient signal reaching back 20 steps along the pure cell-state path is approximately — a mild, controllable attenuation. Contrast this with a vanilla RNN where the effective per-step contraction factor is often empirically well below (products of terms near saturated regions and shrinking singular values), giving — six orders of magnitude smaller. That gap is the entire practical payoff of gating.
Common pitfalls & traps
| Pitfall | Why it happens | Fix |
|---|---|---|
| Forgetting to initialize forget-gate bias positively | Default zero-init biases make initially, causing early training to forget too aggressively | Initialize to a positive value (e.g., 1–2) so gates start near "remember" |
| Confusing cell state with hidden state | Only is typically fed to the output layer / next stacked layer, but both must be carried across timesteps | Always propagate the tuple for LSTM, not just |
| Assuming GRU is strictly better because it's "simpler" | GRU merges cell/hidden state, which is a genuine capacity reduction | Benchmark both; LSTM often wins for tasks needing separate read/write/forget control |
| Applying gradient clipping only to LSTM/GRU and skipping it | People assume gating eliminates the need for clipping entirely | Still clip gradients — exploding gradients through candidate paths and stacked layers remain possible |
| Truncating BPTT too aggressively | Truncation limits the very long-range dependencies gating was meant to enable | Choose truncation length relative to the actual dependency span in the task, not just for compute convenience |
| Treating gate outputs as interpretable "on/off" switches literally | Gates are continuous in and jointly learned; single dimensions rarely have clean semantics | Use ablations/probing rather than assuming a gate value alone explains model behavior |
Pioneers & history
The LSTM was invented to directly solve the vanishing gradient problem that had been formally analyzed for recurrent networks in the early 1990s. Its constant-error-carousel idea — a self-loop with weight 1 acting as an uninterrupted gradient highway — was the conceptual seed for the additive cell-state update used today. The GRU emerged nearly two decades later as a leaner alternative designed for the same purpose but with a smaller parameter budget, becoming popular during the era of encoder-decoder machine translation systems.
Origins · 1 minSepp Hochreiter and how this was discovered
Where this matters
Gated recurrent architectures powered production systems for roughly a decade: Google's neural machine translation system (pre-transformer) used stacked LSTMs; Apple's Siri and various speech-recognition pipelines used LSTM acoustic models; handwriting recognition, music generation, and time-series forecasting systems widely adopted LSTM/GRU cells. They remain a strong choice today for streaming or low-latency inference (constant per-step compute, no need to attend over a growing context window), for small-to-medium datasets where transformers' data hunger is a liability, and as building blocks inside larger systems such as Encoder-Decoder Architectures used in translation and summarization before attention mechanisms took over that role. Understanding gating is also essential background for appreciating why attention and transformers were adopted — attention solves the sequential-bottleneck and long-range-dependency problems that gating only partially addressed, without the sequential dependency chain that limits Recurrent Neural Networks parallelism.
Ask the tutor: Can you derive, step by step, how the LSTM's forget-gate gradient path compares numerically to a vanilla RNN's gradient decay over 50 timesteps?
Why do vanilla RNNs suffer from vanishing gradients but LSTMs mitigate it?
In a vanilla RNN, the gradient of the loss with respect to an early hidden state is a product of many Jacobians, each roughly . Since and repeated multiplication by the same matrix tends to shrink or grow singular values geometrically, the gradient magnitude scales like over steps, vanishing for . The LSTM instead updates its cell state additively, , so involves no matrix multiplication. If the network learns for dimensions it must remember, gradients pass through nearly unchanged across many steps, removing the structural cause of vanishing.
Is a GRU strictly simpler and worse than an LSTM, or just different?
A GRU is more parameter-efficient (three gates and one state vector versus four gates and two state vectors), which speeds up training and reduces overfitting risk on smaller datasets. It is not strictly worse: many empirical studies find GRUs match or slightly exceed LSTM performance on tasks like language modeling and machine translation, especially with limited data. LSTMs tend to have an edge on tasks needing very fine-grained memory control, such as counting or tracking multiple independent quantities, because the input, forget, and output decisions are decoupled rather than tied together through a single update gate. The right choice is empirical, not automatic.
What exactly does the cell state store, conceptually?
The cell state is a vector of "memory slots," each dimension independently protected or overwritten by the forget and input gates. Unlike the hidden state , which is squashed through and gated by before being exposed to the rest of the network, the cell state is only ever combined additively across timesteps and is never directly consumed by downstream layers. This separation lets the network preserve raw, unsquashed information across long spans while still producing a bounded, filtered output () at each step for use by the next layer or the loss function.
Do LSTMs and GRUs completely solve the vanishing gradient problem?
No — they substantially mitigate it along the additive memory path but do not eliminate it everywhere. The hidden-state path in an LSTM still passes through and gate multiplications at every step, so gradients along that path can still shrink. If a task genuinely requires forgetting (small ), the corresponding gradient path is correctly attenuated, which is desired behavior, not a bug. In practice, extremely long sequences (thousands of steps) can still pose difficulties, and techniques like gradient clipping, careful initialization, and truncated backpropagation through time remain standard companions to gated architectures.
How do LSTMs and GRUs relate to attention and transformers?
LSTMs and GRUs process sequences step by step, so the model at time can only access earlier information indirectly, compressed through the recurrent state, and computation cannot parallelize across the time dimension. Attention mechanisms, central to transformer architectures, let every position directly attend to every other position in a single parallelizable operation, sidestepping both the sequential bottleneck and much of the long-range decay issue. Historically, attention was first added on top of LSTM-based encoder-decoder models to help with long sequences, and only later did architectures drop the recurrence entirely in favor of pure attention, which is the lineage into Encoder-Decoder Architectures and transformers.
Why does the forget gate use a sigmoid instead of a tanh or ReLU?
Gates need to act as soft, per-dimension switches whose output represents "how much of this quantity to keep," which requires a bounded range of : a sigmoid naturally produces this range, with 0 meaning "fully forget" and 1 meaning "fully retain." A output in would allow sign flips that don't correspond to a sensible gating semantic, and ReLU is unbounded above and cannot represent "keep half" or "discard entirely" in a bounded, smooth, differentiable way. The candidate content , by contrast, uses precisely because it represents actual values to be blended in, not a gating decision.
What practical tricks improve LSTM/GRU training beyond the architecture itself?
Initialize the forget-gate bias to a positive value (commonly 1) so the network starts by retaining information rather than erasing it. Apply gradient clipping (by norm, typically to a threshold like 1–5) since exploding gradients remain possible through stacked layers or the candidate/output paths. Use orthogonal initialization for recurrent weight matrices to keep their spectral radius near 1 at the start of training. Consider layer normalization inside the cell for very deep stacks, and always monitor gate activations during training — gates saturating near 0 or 1 everywhere for all inputs is a sign of a training pathology, not learned structure.