Recurrent Neural Networks (RNNs, LSTMs, GRUs)
Trace state through time and compare a plain RNN with gated LSTM and GRU cells. Learn what gating helps, what it does not guarantee, and when recurrence is useful.
Jump to a section
Why this matters
A recurrent neural network applies a state update repeatedly across a sequence. At time , it reads input and the previous hidden state to produce . The shared weights let the same model process different sequence lengths. This is useful when order and carried state matter, such as a sensor stream or a sequence of events.
An RNN does not remember everything it has seen. The state has finite capacity, and learning what to retain is difficult when the relevant event lies many steps back. LSTM and GRU cells introduce gates that make retention and replacement learnable. They ease some long-dependency problems; they do not guarantee perfect memory.
Build the mental model
Imagine reading a log one record at a time. A plain RNN rewrites a compact note after each record. An LSTM keeps a separate cell state and learns three decisions: forget part of the old note, write a candidate update, and expose part of the result. A GRU combines retention and writing with fewer gate families and a single hidden state.
| Cell | Carried state | Main control | Practical consequence |
|---|---|---|---|
| Plain RNN | Hidden state | One nonlinear rewrite | Small and simple, but distant signals can be hard to train |
| LSTM | Hidden and cell | Input, forget, and output gates | Additive cell path can help preserve a learned signal |
| GRU | Hidden state | Update and reset gates | Compact gated alternative; accuracy and speed depend on workload |
The unrolled computation is still sequential across time. Batching many sequences can improve hardware use, but each step's state depends on the previous step. A Transformer uses attention to connect positions differently and is often easier to parallelize during training; this does not make recurrence obsolete for every streaming or stateful task.
Unroll the same state update through time
Each input and the previous hidden state enter the same recurrent function. U and W are shared across time.
Exact inputs and equations appear with the figure.
Preparing the scientific figure…
Exact forward states with W = [[0.6,0.2],[−0.1,0.5]], U = [1,0.5], and h₀ = [0,0]. Time, channel, and activation are separate axes. This is not a trained RNN or an LSTM/GRU gate simulation.
Elman · Finding Structure in TimeFigure 2, p. 184; hidden-state feedback described on p. 182
Authored unrolling of shared recurrent state. The unrolled tanh equation is a modern illustrative variant, not Elman’s original activation, initial context, or learned weights.
Work through the math
A plain RNN uses a shared transition:
Backpropagation through time sends a distant gradient through a product of state-transition Jacobians. The product can shrink or grow, depending on weights, activations, and the trajectory. A simple LSTM form instead computes gates and an additive cell update:
Holding near one and near zero can carry cell information forward. That is a possible learned behavior, not an unconditional gradient guarantee: gates, saturation, truncation, and finite state still matter. For one common GRU convention, ; here is the fraction of old state retained. Libraries may use different gate names or algebraic rearrangements, so check their equations before comparing parameters.
Read the implementation
PyTorch returns a sequence output and final state. LSTM's final state is a pair; GRU's is one tensor. These shapes are worth checking before adding a classifier or carrying state into another batch.
1import torch
2from torch import nn
3
4x = torch.randn(4, 7, 5) # batch, time, input features
5gru = nn.GRU(input_size=5, hidden_size=8, batch_first=True)
6lstm = nn.LSTM(input_size=5, hidden_size=8, batch_first=True)
7
8gru_steps, gru_final = gru(x)
9lstm_steps, (lstm_hidden, lstm_cell) = lstm(x)
10assert gru_steps.shape == lstm_steps.shape == (4, 7, 8)
11assert gru_final.shape == lstm_hidden.shape == lstm_cell.shape == (1, 4, 8)For independent examples, initialize state anew. For a continuous stream, carry state only across the intended sequence boundary; detach it when using truncated backpropagation through time. Otherwise, one user's history can leak into another example or a computation graph can grow without bound. Pad or pack variable-length batches so padding steps do not silently become data.
Questions and trade-offs
- Mechanism: Why does an RNN share weights across time? (The same transition processes each step while hidden state carries prior information; sharing also permits variable sequence length.)
- Gradient: Why can a plain RNN miss a distant dependency? (The backward signal contains products of time-step Jacobians that can shrink or grow.)
- Gates: What does the LSTM cell update buy? (An additive carry path with learned forget and input gates, which can ease retention without guaranteeing it.)
- Implementation: What differs in the returned state of PyTorch GRU and LSTM? (GRU returns a hidden tensor; LSTM returns hidden and cell tensors.)
- Systems: When would you still test recurrence against attention? (Streaming state, latency, context length, data scale, and hardware can change the tradeoff. Benchmark the actual task.)
Check your understanding
Without notes, write the plain RNN update and the LSTM cell update. Name one way gradients can fail across time and one way a stateful data loader can leak information. Then explain why a gate near one helps retention without promising unlimited memory.
Sources and further reading
- Elman, Finding Structure in Time (1990): recurrent context as dynamic memory.
- Bengio, Simard, and Frasconi, Learning Long-Term Dependencies with Gradient Descent is Difficult (1994): analysis of distant-gradient difficulty.
- Hochreiter and Schmidhuber, Long Short-Term Memory (1997): gated cell-state method.
- Cho et al., Learning Phrase Representations using RNN Encoder-Decoder (2014): GRU-style recurrent encoder-decoder.
- PyTorch recurrent layer documentation: current framework state shapes and gate conventions.
Oliver Perrin
Machine Learning Engineer · Founder, LiminalML
LiminalML brings together concept explanations, mathematical examples, and working visuals. Find more writing by Oliver on the LiminalML Substack.
Keep exploring the idea.
Ask a follow-up in a guided session, work through the self-check, or open the visual in Studio to build on it.
Related concepts
Deep Learning
Backpropagation
Trace local derivatives backward through a computation and connect the chain rule to a manual implementation.
Deep Learning
Transformer Architecture
Follow attention, feed-forward layers, normalization, and residual connections through a Transformer block.
Deep Learning
Attention Mechanisms
Turn compatibility scores into attention weights, then combine values. Explore the geometry, normalization, and limits of the mechanism.