Take a microscopic look inside a single Long Short-Term Memory cell. Visualize the internal architecture, the conveyor belt, and the four gates that control memory.
A simple recurrent cell has one hidden state, and it is completely rewritten at every timestep. An LSTM has two:
The cell state is the important one. Because it is updated additively, information placed there at timestep 1 can reach timestep 500 essentially untouched — there is no repeated matrix multiplication to shrink it.
An LSTM adds a separate memory channel that information can travel along unchanged, plus three learned gates deciding what to erase, what to add, and what to reveal. That additive path is why it remembers hundreds of steps.
Each gate is a small sigmoid layer producing values in [0, 1], which then multiply a vector elementwise — 0 blocks completely, 1 passes completely, and everything between is a partial pass.
ft = σ(Wf·[ht−1, xt] + bf) forget
it = σ(Wi·[ht−1, xt] + bi) input
ot = σ(Wo·[ht−1, xt] + bo) output
The cell state update is then two operations — erase, then write:
Ct = ft ⊙ Ct−1 + it ⊙ C̃t
ht = ot ⊙ tanh(Ct)
In a language model the forget gate might drop the previous subject’s gender when a new subject appears, the input gate writes the new one, and the output gate exposes it only when a pronoun actually needs to agree.
The whole design rests on the additive update. Differentiating Ct with respect to Ct−1 gives ft — the forget gate itself, not a weight matrix.
So the gradient flowing back through the cell state is multiplied by the forget gate at each step. When the network learns to keep something, the forget gate sits near 1, and multiplying by roughly 1 many times preserves the gradient. Compare that with a simple RNN, where the same path is multiplied by Wh and a tanh derivative every step and decays geometrically.
This is the same principle as a residual connection: give the gradient an uninterrupted additive route, and depth stops destroying it.
A plain recurrent network overwrites its hidden state at every step. Whatever it knew about word one is repeatedly transformed, and after fifty steps almost nothing survives — gradients decay along the same path, so it cannot learn long-range dependencies either.
An LSTM adds a second, separately protected state: the cell state, which travels along the sequence with only additive updates and multiplicative gates deciding what enters and leaves.
Two states, two jobs:
c — long-term memory. Modified by addition, not by rewriting.h — the working output at each step, derived from the cell state.Three gates control the flow, each a small neural network with a sigmoid output between 0 and 1 — 0 meaning "block completely", 1 meaning "let everything through":
| Gate | Question it answers |
|---|---|
| Forget | What should I drop from memory? |
| Input | What new information should I store? |
| Output | What part of memory should I expose now? |
fᵗ = σ(Wᶠ·[hᵗ₋₁, xᵗ] + bᶠ) forget gate
iᵗ = σ(Wᵢ·[hᵗ₋₁, xᵗ] + bᵢ) input gate
gᵗ = tanh(Wᵕ·[hᵗ₋₁, xᵗ] + bᵕ) candidate memory
cᵗ = fᵗ ⊙ cᵗ₋₁ + iᵗ ⊙ gᵗ update the cell
oᵗ = σ(Wₒ·[hᵗ₋₁, xᵗ] + bₒ) output gate
hᵗ = oᵗ ⊙ tanh(cᵗ) produce the output
The line that matters most is the cell update. It is old memory scaled by the forget gate, plus new memory scaled by the input gate. Both operations are elementwise, so each dimension of the cell state is managed independently — one dimension can hold grammatical number while another tracks sentiment.
Note the two activations doing different jobs. Sigmoid produces gates, because a gate needs to be a fraction between 0 and 1. Tanh produces content, because content should be able to be negative.
In a plain RNN, the gradient flowing back through k steps is a product of k Jacobian factors. If those average below 1, the product decays exponentially.
The LSTM's cell state has a path where the derivative of cₜ with respect to cₜ₋₁ is simply the forget gate fₜ. If the forget gate is near 1 — the network has learned to keep this information — the gradient passes back essentially unchanged.
That is the same structural idea as a residual connection: an additive path with a derivative near 1, protecting the gradient from the multiplicative decay. It is why LSTMs handled sequences of hundreds of steps where plain RNNs managed ten.
It reduces the problem rather than eliminating it. Very long dependencies remain hard, and exploding gradients still occur, which is why gradient clipping is standard when training recurrent models.
An LSTM cell is four small networks and one running memory. All four are computed here on a real sequence, with the cell state printed at every step so you can see what it carries.
An LSTM separates long-term memory (the cell state) from working output (the hidden state) and controls the flow between them with three learned sigmoid gates. Because the cell state is updated by addition and gated multiplication rather than a matrix multiply, the gradient travels back through it multiplied only by the forget gate — so when the model chooses to remember, it genuinely can, for hundreds of steps. The cost is four times the parameters of a simple cell, and a GRU usually gets most of the benefit for less.
import torch.nn as nn
lstm = nn.LSTM(input_size=300, # embedding dimension
hidden_size=256,
num_layers=2,
batch_first=True,
bidirectional=False,
dropout=0.2) # applies between layers only
out, (h, c) = lstm(x) # x: (batch, seq, 300)
# out: (batch, seq, 256) -- the hidden state at every step
# h, c: (layers, batch, 256) -- the final statesWhich output you use depends on the task. For classification, take the final hidden state (or a pooled version of all steps). For tagging or sequence-to-sequence, use the full out tensor.
Parameter count is worth knowing, because it explains why LSTMs are heavier than they look: four gates each need a weight matrix over the concatenated input and hidden state, giving 4 × ((input + hidden) × hidden + hidden). For 300-dimensional input and 256 hidden units that is about 570,000 parameters per layer.
For variable-length batches, use pack_padded_sequence so the LSTM does not process padding — otherwise the final hidden state reflects the padding rather than the last real token.
| LSTM | GRU | Transformer | |
|---|---|---|---|
| Gates | 3 | 2 | None — attention instead |
| Parameters | Most | ~25% fewer | Most of all |
| Long-range dependencies | Good | Good | Best |
| Parallel across the sequence | No | No | Yes |
| Streaming / constant memory | Yes | Yes | No — KV cache grows |
| Small-data performance | Good | Good | Needs more data |
GRU merges the forget and input gates into a single update gate and drops the separate cell state. Fewer parameters, slightly faster, and empirically comparable on most tasks — the choice between them is usually not worth agonising over.
Transformers won for large-scale language work because they parallelise across the sequence and have constant path length between positions. But LSTMs remain a sensible choice for streaming inference with bounded memory, for small datasets, for on-device models, and for classical time-series work.
Are LSTMs obsolete? Superseded for large-scale language modelling; still practical for streaming, small data, embedded use and time series.
What is the difference between the cell state and the hidden state? The cell state is protected long-term memory updated additively; the hidden state is the filtered output exposed at each step.
How many layers? One or two for most tasks. Deep stacks of LSTMs are hard to train and rarely pay off.
Why tanh and sigmoid rather than ReLU? Sigmoid bounds gates to 0–1, which is what a gate requires. Tanh bounds content to −1–1, which keeps the repeatedly-applied recurrence stable.
Do I need gradient clipping? Yes — recurrent models are the classic case for it.
Should I use a bidirectional LSTM? For classification and tagging where the whole input is available, yes — it usually helps. Never for generation or streaming, where the future is not available.
∂cₜ/∂cₜ₋₁ is the forget gate — near 1 means the gradient survives.Say the answer out loud before you reveal it — recalling it is what makes it stick, and rereading it is not.
Without scrolling back — what is the one-line takeaway from this module?
An LSTM separates long-term memory (the cell state) from working output (the hidden state) and controls the flow between them with three learned sigmoid gates. Because the cell state is updated by addition and gated multiplication rather than a matrix multiply, the gradient travels back through it multiplied only by the forget gate — so when the model chooses to remember, it genuinely can, for hundreds of steps.
What does this module say about “Two states, not one”?
A simple recurrent cell has one hidden state, and it is completely rewritten at every timestep. An LSTM has two:
What does this module say about “The three gates”?
Each gate is a small sigmoid layer producing values in [0, 1], which then multiply a vector elementwise — 0 blocks completely, 1 passes completely, and everything between is a partial pass.
Take a microscopic look inside a single Long Short-Term Memory cell. Visualize the internal architecture, the conveyor belt, and the four gates that control memory.