Deep Learning Slides 📂 Introduction · 16 of 18 34 min read

LSTM Networks: From Cell State to Gates

Vanilla RNNs forget within a few steps. LSTMs add a protected cell-state "conveyor belt" and three learnable gates that decide what to forget, write, and reveal. This visual guide walks the forget, input, and output gates, the core cell-state update, why addition beats vanishing gradients, and PyTorch code.

LSTM Networks — From Cell State to Gates

Ordinary RNNs forget within a few steps. LSTMs add a protected memory highway and three learnable gates that decide what to remember, forget, and reveal — so context survives across hundreds of time steps.
The Cell-State Highway Three Gates Addition, Not Multiplication PyTorch

Press Next → or use ← → arrow keys

Section 01

What Are LSTM Networks?

An LSTM is a recurrent network built to hold information for a long time — remembering is its default behaviour, not a struggle. Where a vanilla RNN repeats a single squashing layer, an LSTM cell contains four interacting components: three gates plus a candidate, all wrapped around a protected memory line.
1997Introduced by Hochreiter & Schmidhuber
4Interacting parts inside each cell
100+Time steps of memory it can hold
🔑
Two memories, not one

An LSTM carries a cell state (long-term storage) alongside the hidden state (short-term working memory). Keeping them separate is the whole trick.

Section 02

Why We Need LSTMs

A vanilla RNN's memory fades fast. Each step multiplies the signal by a weight below 1, so information decays exponentially — often gone within seven steps:

how much of "clouds" survives, step by step → 100%70%44%25%12%6%≈0%
🌥️
"The clouds in the sky are very ___"

To fill the blank you must still remember "clouds" and "sky" — but a vanilla RNN has lost them by the time it reaches the gap. The LSTM was built to solve exactly this.

Section 03

The Cell State — A Conveyor Belt

Picture a conveyor belt running straight through the whole network. Packages of information ride along it, barely touched — this is the cell state, the LSTM's protected long-term memory.

cell state Cₜ clouds sky plural cell t−1 cell t cell t+1
📦
Gates load and unload the belt

The cell state itself changes very little from step to step. Small, learned gates decide which packages board, ride on, or get thrown off — leaving the rest untouched.

Section 04

Inside the LSTM Cell

The cell state runs across the top. Below it, the inputs [hₜ₋₁, xₜ] drive three gates that edit the belt and read from it:

Cₜ₋₁ Cₜ × + σforget σinput tanhcandidate σoutput [hₜ₋₁, xₜ] hₜ
🚪
Forget ✕, write ✚, read →

The forget gate multiplies the belt (erase), the input gate adds new values (write), and the output gate reads a filtered copy out as the hidden state hₜ.

Section 05

Gate 1 — The Forget Gate

First, decide what to erase from the old cell state. A sigmoid outputs a keep-fraction between 0 and 1 for every value on the belt:

fₜ = σ(W_f · [hₜ₋₁, xₜ] + b_f)
output range (0, 1) — a keep-fraction per value
Completely erase this piece of memory — throw the package off the belt.
Keep it fully — let the package ride on, untouched.
🌥️
In our sentence

While reading "are very", the forget gate stays near 1.0 for "clouds" and "sky" — protecting them — while letting irrelevant earlier words fade.

Section 06

Gate 2 — Input Gate & Candidate

Next, decide what new information to write. Two parts work together: a candidate proposes values, and the input gate controls how much of it gets through.

iₜ = σ(W_i · [hₜ₋₁, xₜ] + b_i)
input gate — the "volume knob", (0, 1)
C̃ₜ = tanh(W_c · [hₜ₋₁, xₜ] + b_c)
candidate values — proposed update, (−1, 1)
🎛️
Candidate × volume = what gets written

The product iₜ ⊙ C̃ₜ is the scaled new information. On "clouds" the gate opens wide (iₜ ≈ 0.9); on a filler word like "in" it nearly shuts (iₜ ≈ 0.05), so the belt barely changes.

Section 07

The Cell State Update — The Core

This one equation is the heart of the LSTM. Erase with the forget gate, add the new writing — then move on:

Cₜ = fₜ · Cₜ₋₁ + iₜ · C̃ₜ
keep the old (scaled by fₜ) · add the new (scaled by iₜ)
1
fₜ · Cₜ₋₁ — element-wise erase: scale down the parts of memory to forget.
2
iₜ · C̃ₜ — element-wise write: add the gated new candidate values.
+
Addition, not multiplication — the two pieces are summed onto the belt. That plus sign is why gradients survive.
The belt keeps moving

Nothing here squashes the whole memory through a dense layer. The cell state flows forward with only a scale-and-add — a nearly uninterrupted path from the distant past to now.

Section 08

Gate 3 — The Output Gate

Finally, decide what to reveal. The protected cell state is squashed by tanh, then filtered by the output gate to form this step's hidden state:

oₜ = σ(W_o · [hₜ₋₁, xₜ] + b_o)
output gate — how much cell state to expose, (0, 1)
hₜ = oₜ · tanh(Cₜ)
hidden state — the working memory passed onward
🎭
Know now, say later

An LSTM can hold information without exposing it. The output gate stays low until the moment it matters — in our sentence it opens fully (oₜ ≈ 1.0) only when predicting the final word.

Section 07

Why Addition Beats Multiplication

In a vanilla RNN the gradient is multiplied by a weight at every step, so it shrinks exponentially. The LSTM's cell state uses addition, and the gradient through it stays bounded:

hₜ = tanh(W·hₜ₋₁ + …)
Gradient = product of many weights < 1 → vanishes after a few steps.
∂Cₜ / ∂Cₜ₋₁ = fₜ
A single learned, bounded factor → gradient survives across 100+ steps.
🎠
The constant error carousel

Because the cell state carries the gradient by a scale-and-add rather than repeated matrix multiplication, the error signal rides all the way back to early steps — undamaged.

Section 09

The Complete Equations

Three gates, one candidate, and two state updates — the whole LSTM on one screen:

ComponentFormulaRange
Forget gatefₜ = σ(W_f·[hₜ₋₁, xₜ] + b_f)(0, 1)
Input gateiₜ = σ(W_i·[hₜ₋₁, xₜ] + b_i)(0, 1)
CandidateC̃ₜ = tanh(W_c·[hₜ₋₁, xₜ] + b_c)(−1, 1)
Cell updateCₜ = fₜ·Cₜ₋₁ + iₜ·C̃ₜ
Output gateoₜ = σ(W_o·[hₜ₋₁, xₜ] + b_o)(0, 1)
Hidden statehₜ = oₜ · tanh(Cₜ)(−1, 1)
🔁
Same weights, every step

W_f, W_i, W_c, W_o are shared across all time steps and learned by backpropagation through time — the parameter count never grows with sequence length.

Section 10

Worked Example — "The Clouds in the Sky Are Very ___"

Trace the gates as the sentence streams in, word by word:

1
"clouds" — input gate opens (≈ 0.9); the belt writes the weather subject into memory.
2
"in the" — filler; input gate nearly shuts (≈ 0.05), forget gate ≈ 1.0. "clouds" rides on unchanged.
3
"sky" — input gate reopens; adds outdoor/weather context. Memory now holds {clouds, sky}.
4
"___" — output gate opens fully (≈ 1.0), exposing the whole context → top predictions: "dark", "gray", "bright".
Memory survived five words

A vanilla RNN would have lost "clouds" by the blank. The LSTM's belt carried it through untouched — forget ≈ 1 for what mattered, input ≈ 0 for what didn't.

Section 11

Cell State vs Hidden State

The two memories play very different roles — decoupling them by design is what makes LSTMs work:

Cell state CₜHidden state hₜ
RoleLong-term memoryShort-term working memory
AccessPrivate, protectedPublic — passed to next layer
PathScale + add (the highway)Squashed & gated each step
Updated byForget + input gatesOutput gate · tanh(Cₜ)
🔐
Private storage, public read-out

The cell state hoards information safely; the hidden state exposes only the slice that's useful right now. Separating them is the design insight the whole architecture rests on.

Section 12

LSTM in PyTorch

The four equations map straight onto four linear layers — or you can just call the fused, GPU-optimised built-in:

# A single LSTM cell, by hand
combined = torch.cat([h_prev, x], dim=1)
f = torch.sigmoid(self.Wf(combined))     # forget gate
i = torch.sigmoid(self.Wi(combined))     # input gate
c_tilde = torch.tanh(self.Wc(combined))  # candidate
c = f * c_prev + i * c_tilde             # cell update
o = torch.sigmoid(self.Wo(combined))     # output gate
h = o * torch.tanh(c)                     # hidden state

# ...or the built-in (four matrices fused for speed)
model = nn.LSTM(input_size=10, hidden_size=128, num_layers=2,
                dropout=0.2, batch_first=True)
out, (hn, cn) = model(x)          # out: (batch, seq, 128)
Same maths, faster

nn.LSTM concatenates the four weight matrices into one fused operation — mathematically identical to the hand-written cell, but far quicker on a GPU.

Section 13

Where LSTMs Shine — & What to Remember

🌐
Language & translation
Encoder-decoder LSTMs powered early Google Translate and language models.
🎙️
Speech recognition
BiLSTMs read audio features forward and backward for low-latency voice assistants.
📈
Time series
Stock, weather, and sensor forecasting — learning seasonal cycles and trends.
  Five things to remember
1The cell state is long-term memory — a highway that bypasses per-step squashing.
2Three gates, four equations: forget (erase), input + candidate (write), output (read).
3Addition prevents vanishing gradients — Cₜ = fₜ·Cₜ₋₁ + iₜ·C̃ₜ carries the signal 100+ steps.
4Cell state ≠ hidden state — private storage vs public working memory.
5Weights are shared across time and learned end-to-end — no manual memory rules.