Home / Deep Learning

How LSTM Processes Text

By Updated

Visualize how Long Short-Term Memory networks pass both a Cell State (long-term memory) and a Hidden State (short-term memory) forward to process sequences.

Overview

The Vanishing Gradient Problem

Standard Recurrent Neural Networks (RNNs) pass a single "hidden state" forward through time. While great in theory, standard RNNs suffer from the vanishing gradient problem. During training, as the network looks back across many time steps (long sentences), the signals necessary to update the weights become microscopically small.

The result? A standard RNN essentially develops "amnesia." By the time it reads the 20th word in a sentence, it has mostly forgotten the 1st word. This makes it terrible at understanding long-range dependencies in text.

LSTM Analysis

Time Steps -
State Size -
Shared Parameters -
Cell State ($C_t$) - Long Term
Hidden State ($H_t$) - Short Term

LSTMs and Text: Mastering Long-Term Memory

Discover how Long Short-Term Memory networks use a dual-state architecture to overcome the limitations of standard RNNs.

The Dual State Solution: Cell and Hidden States

LSTMs solve this amnesia by introducing a more complex internal structure that passes two distinct states forward at every time step (as seen in the visualization):

  1. The Cell State ($C_t$): Often compared to a conveyor belt. It runs straight down the entire chain, with only minor linear interactions. It's very easy for information to flow along it unchanged. This is the LSTM's long-term memory.
  2. The Hidden State ($H_t$): This is the LSTM's short-term memory or its "focus" for the current time step. It is derived from the Cell State and is what gets passed up as the output ($Y_t$) for that specific step.

The Four Gates (Why so many parameters?)

To control what gets added to or removed from the Cell State conveyor belt, the LSTM uses neural network layers called gates. Inside every single LSTM cell block shown in the visual, there are actually four separate fully-connected layers operating simultaneously:

  • Forget Gate ($f_t$): Decides what information to throw away from the past cell state.
  • Input Gate ($i_t$): Decides which new values to update in the cell state.
  • Cell Candidate ($\tilde{C}_t$): Creates a vector of new candidate values that could be added to the state.
  • Output Gate ($o_t$): Decides what parts of the cell state to output as the new Hidden State ($H_t$).

Because there are 4 independent layers doing calculations on the inputs ($X_t$) and previous hidden state ($H_{t-1}$), an LSTM has roughly 4 times as many parameters as a standard RNN of the same size. Click the Parameters button to see the math.

Following a sentence through the cell

Take "the film was not very good" and watch what an LSTM does with it, one token at a time.

At each step the cell receives the current word's embedding and its own two states from the previous step, computes four things from them, and produces new states.

StepWordWhat the gates plausibly do
1theLittle to store; state stays near its initial value
2filmInput gate opens on subject dimensions; "film" is the topic
3wasTense recorded; subject retained (forget gate near 1)
4notA negation dimension is set; this is the important step
5veryIntensifier stored; negation retained
6goodCandidate is strongly positive — and the negation dimension is still set

The interesting step is 4. "Not" carries no sentiment on its own; its job is to invert what follows. A trained cell stores that in some dimension and keeps it (forget gate near 1) so that at step 6 the positive candidate for "good" is combined with an active negation signal.

That is what a bag-of-words model cannot do: to it, this sentence contains "good" and is therefore positive.

Four computations per step

fᵗ = σ(Wᶠ[hᵗ₋₁, xᵗ])   iᵗ = σ(Wᵢ[hᵗ₋₁, xᵗ])

gᵗ = tanh(Wᵕ[hᵗ₋₁, xᵗ])  oᵗ = σ(Wₒ[hᵗ₋₁, xᵗ])

cᵗ = fᵗ ⊙ cᵗ₋₁ + iᵗ ⊙ gᵗ    hᵗ = oᵗ ⊙ tanh(cᵗ)

All four transformations take the same input and are computed as a single fused matrix multiplication in practice, then split.

The two states do different jobs. The cell state is long-term memory, updated additively so information can persist for many steps. The hidden state is the working output — passed to the next layer, to the prediction head, and to the next step's gate computations.

What comes out, and what you use

For a 20-word sentence, a single-layer LSTM with 256 hidden units produces a 20×256 tensor: one hidden state per word.

Which part you use depends on the task:

Classification. The final hidden state summarises the whole sentence — or better, pool over all states with a mean or max, since the final state is biased towards the end of the input.

Tagging (named entities, part of speech). Use every hidden state, one prediction per word.

Generation. Feed each hidden state to an output layer over the vocabulary, and the predicted token becomes the next step's input.

As an encoder. The final state (or all states, with attention) is passed to a decoder.

lstm = nn.LSTM(300, 256, batch_first=True)
out, (h, c) = lstm(embedded)      # out: (batch, seq, 256)

pooled = out.mean(dim=1)          # better than h[-1] for classification

Interactive Exploration

  • Run the Simulation: Watch the blue data ($X_t$) enter the cell, merge with the past states, and then split into the Cyan conveyor belt ($C_t$) and the Green focus state ($H_t$).
  • Check Many-to-One vs Many-to-Many: In Many-to-One (like Sentiment Analysis), only the final $H_t$ is pushed up to the classifier to make the final $Y$ decision. In Many-to-Many (like Language Translation or Text Generation), an output is generated at every step.

Details that matter with real text

Pack variable-length sequences. Sentences in a batch have different lengths, so short ones are padded. Without pack_padded_sequence, the LSTM processes the padding, and the final hidden state describes the padding rather than the last real word.

from torch.nn.utils.rnn import pack_padded_sequence, pad_packed_sequence

packed = pack_padded_sequence(embedded, lengths, batch_first=True,
                              enforce_sorted=False)
out, (h, c) = lstm(packed)
out, _ = pad_packed_sequence(out, batch_first=True)

Consider bidirectionality. For classification and tagging, where the whole sentence is available, running one LSTM forward and another backward and concatenating gives each position both left and right context. It typically helps materially. Never use it for generation or streaming, where the future does not exist.

Clip gradients. clip_grad_norm_ with a threshold of 1–5. Recurrent models are the classic case for it, and omitting it eventually produces a NaN run.

Keep it shallow. One or two layers. Deep recurrent stacks are hard to train and rarely repay the cost.

Where it beats and loses to a transformer

An LSTM wins when memory must be bounded — streaming inference carries one fixed-size state regardless of how much text has passed, while a transformer's KV cache grows with every token. It also wins on small datasets, where its inductive bias helps and a transformer trained from scratch overfits, and on-device, where it is small and needs no attention kernels.

A transformer wins on long-range dependencies (any two positions are one step apart), on parallelism (all positions computed at once, so training scales), and consequently on anything requiring scale.

TaskReasonable choice
Sentiment on a few thousand labelled reviewsLSTM, or a fine-tuned small transformer
Streaming transcription with bounded memoryLSTM
Document-level question answeringTransformer
On-device text classificationLSTM or a distilled transformer
Anything generative at qualityTransformer

One sentence, one token at a time, gates shown

An LSTM reading a real sentence, with all four gates printed at every token and the cell state tracked alongside. The interesting part is which tokens make the gates move.

example_01.pyNumPy
Output

Questions people ask

Does an LSTM read left to right? Yes, unless bidirectional, in which case a second pass reads right to left and the outputs are concatenated.

Should I use the last hidden state or pool? Pool, for classification — the last state over-weights the end of the sequence.

How long a text can it handle? Hundreds of tokens reliably. Beyond that, information from the start is largely gone.

Do I need embeddings before the LSTM? Yes — token ids must become vectors first, either from a learned embedding layer or pretrained vectors.

Why is my final hidden state meaningless? Almost certainly unpacked padding: the state describes the pad tokens.

One layer or two? Two at most for most tasks; the second sometimes helps and often does not.

Recap in one screen

  • At each token the cell computes four transformations, updates the cell state additively, and emits a gated hidden state.
  • The cell state carries long-term memory; the hidden state is the working output at each step.
  • "Not ... good" is the canonical demonstration: the negation is stored and applied several steps later.
  • Pool over hidden states for classification; use all of them for tagging.
  • Pack variable-length batches, clip gradients, keep it shallow, and consider bidirectionality when the whole input is available.

Recall check

0 of 3

Say the answer out loud before you reveal it — recalling it is what makes it stick, and rereading it is not.

  1. What does this module say about “The Vanishing Gradient Problem”?

  2. What does this module say about “The Dual State Solution: Cell and Hidden States”?

  3. What does this module say about “The Four Gates (Why so many parameters?)”?

Cheat sheet

How LSTM Processes Text

Visualize how Long Short-Term Memory networks pass both a Cell State (long-term memory) and a Hidden State (short-term memory) forward to process sequences.

NLP · vizlearn.in/natural_language_processing/how_lstm_processes_text.html

About the author

Ashish Jangra builds and maintains VizLearn. Every module here is written and the visualisation behind it hand-built, so the numbers in a readout come from the same code that draws the picture. Corrections are genuinely welcome and get priority over everything else — if a page states something wrong, or an animation misrepresents what the algorithm does, get in touch.