Deep Learning Slides 📂 Introduction · 17 of 18 35 min read

Long Short-Term Memory (LSTM) Networks

A complete tour of LSTM networks — the cell state and three gates, the four equations, why they beat vanilla RNNs at long-range memory, the whole variant family (BiLSTM, GRU, ConvLSTM), the hyperparameters you tune, and a real PyTorch stock-forecasting model built and trained end to end.

Long Short-Term Memory (LSTM) Networks

A gated memory cell that remembers what matters for hundreds of steps and forgets the rest. This is the full tour — the gates, the family of variants, the hyperparameters you tune, and a real forecasting model built end to end.
Gates & Cell State The Variant Family Hyperparameters PyTorch & Keras

Press Next → or use ← → arrow keys

Section 01

The Detective Who Never Forgets

One reader finishes a 200-page mystery still remembering that Marcus feared water back in chapter one — and cracks the ending. Another remembers only the last sentence, and is lost. A vanilla RNN is the forgetful reader; an LSTM is the detective who holds the key clue across the whole book.
🗄️
A filing room with three guards

Think of the cell state as a filing room. Three guards control it: an archivist who shreds outdated files, an intake officer who screens new documents, and a spokesperson who decides what to reveal. Those are the three gates.

Section 02

Why Vanilla RNNs Fail

During backpropagation through time, gradients are multiplied at every step. If the recurrent weights are small, that product collapses toward zero — distant clues become invisible to the optimiser.

gradient shrinks with every step back in time ← strongweakerfainttiny≈0
⚖️
Eigenvalues decide the fate

Recurrent-weight eigenvalues below 1 → gradients vanish; above 1 → gradients explode into NaNs. LSTM's cell state sidesteps both with a constant error carousel.

Section 03

LSTM Cell Anatomy

Each cell takes three things in and passes two things on. The cell state Cₜ is the long-term memory; the hidden state hₜ is the working output.

LSTM cell4 gates inside Cₜ₋₁ hₜ₋₁ xₜ (input) Cₜ hₜ
🔀
Two states in, two states out

Unlike a vanilla RNN (which carries only hₜ), the LSTM threads both Cₜ and hₜ from step to step. That extra memory line is the whole advantage.

Section 04

The Four Equations

Everything inside the cell is these six lines — three sigmoid gates, one tanh candidate, and two state updates:

StepFormulaRange
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 stateCₜ = fₜ ⊙ Cₜ₋₁ + iₜ ⊙ C̃ₜ
Output gateoₜ = σ(W_o·[hₜ₋₁, xₜ] + b_o)(0, 1)
Hidden statehₜ = oₜ ⊙ tanh(Cₜ)(−1, 1)
⊙ is element-wise, and the cell update adds

The cell state uses element-wise multiply (not matrix multiply) and an addition to combine old and new. That's precisely why gradients don't saturate away.

Section 05

Gate Intuition — The Three Guards

Each gate is a security guard controlling the filing room. Together they decide what the cell remembers:

🗑️
Forget — the archivist
Stamps "DESTROY" on outdated files. fₜ near 0 shreds a memory; near 1 keeps it on the shelf.
📥
Input — the intake officer
Screens new documents. iₜ decides how much of the candidate C̃ₜ is allowed to enter the room.
📢
Output — the spokesperson
Chooses which records to reveal. oₜ filters the cell state into the hidden state that leaves the cell.
🎓
All three are learned

No one hand-writes the rules. The gates' weights are trained by backpropagation, so the network discovers for itself what to keep, add, and expose at each step.

Section 06

LSTM Unrolled Through Time

Across time, each cell passes two lines forward — the cell state on top, the hidden state below — reusing the same weights at every step:

C h cell t−1 cell t cell t+1 x₁x₂x₃
🔑
Two highways, shared weights

The green cell-state line carries long-term memory; the violet hidden line carries the short-term output. Both flow through every step, and every cell uses the same learned weights.

Section 07

The LSTM Family Tree

The basic cell spawned a whole family, each tuned for a different job:

↔️
BiLSTM
Forward + backward passes, concatenated — sees future context. Great for tagging; not for live generation.
🥞
Stacked LSTM
2–4 layers vertically, learning hierarchical temporal patterns. The production default.
GRU
Only 2 gates (reset, update), merges cell & hidden state — fewer parameters, faster, similar accuracy.
🔭
Peephole
Gates also see the cell state directly, for precise timing — handy in music generation.
🌐
Seq2Seq + Attention
Encoder–decoder LSTMs with attention — the direct precursor to transformers.
🗺️
ConvLSTM
Convolutions instead of matrix multiplies — for spatiotemporal data like weather maps and video.
🌳
Same core, different wiring

Every variant keeps the gated-memory idea — they just rearrange the connections for direction, depth, efficiency, or spatial structure.

Section 08

Key Hyperparameters

These are the dials you actually turn when training an LSTM:

HyperparameterTypical rangeTip
hidden_size64–512Start 128; double if underfitting
num_layers1–42 is usually enough; 3+ needs regularisation
dropout0.1–0.50.2–0.3 between layers (not recurrent)
sequence_length≤ 200Truncated BPTT beyond that
learning_rate1e-4–1e-2Adam 1e-3 with a scheduler
gradient_clipping0.5–5.0Always on — 1.0 is a safe default
🎛️
Start small, then grow

Begin with 1–2 layers of 128 units and Adam at 1e-3. Only add depth or width once you've confirmed the model is underfitting — deeper LSTMs overfit small datasets fast.

Section 09

PyTorch — A Stock Forecaster

The task: predict tomorrow's closing price from the last 60 days. Two stacked LSTM layers feed a small dense head:

class LSTMForecaster(nn.Module):
    def __init__(self):
        super().__init__()
        self.lstm = nn.LSTM(input_size=1, hidden_size=128,
                            num_layers=2, dropout=0.2, batch_first=True)
        self.fc = nn.Sequential(
            nn.Dropout(0.2), nn.Linear(128, 64),
            nn.ReLU(), nn.Linear(64, 1))
    def forward(self, x):
        out, _ = self.lstm(x)          # x: (batch, 60, 1)
        return self.fc(out[:, -1, :])   # last step → price
60Day sliding window
199kTrainable parameters
2×128Stacked LSTM layers
Section 09

Training & Results

MSE loss, Adam at 1e-3, gradient clipping at 1.0, and a plateau scheduler over 50 epochs. The validation loss falls steadily:

1
Normalise prices to [0, 1] with MinMaxScaler; split 80/20 by time — never shuffle.
2
Clip gradients: nn.utils.clip_grad_norm_(model.parameters(), 1.0) before each step.
3
Val MSE: 0.00210 → 0.00124 → 0.00088 → 0.00069 across epochs 10 → 50.
$3.47Test MAE
$5.12Test RMSE
50Epochs
Section 10

The Same Model in Keras

Keras makes the stack even terser — just mind one rule about return_sequences:

import keras
from keras import layers

inputs  = keras.Input(shape=(60, 1))
x = layers.LSTM(128, return_sequences=True,  dropout=0.2)(inputs)
x = layers.LSTM(64,  return_sequences=False, dropout=0.2)(x)
x = layers.Dense(32, activation='relu')(x)
outputs = layers.Dense(1)(x)

model = keras.Model(inputs, outputs)
model.compile(optimizer=keras.optimizers.Adam(1e-3, clipnorm=1.0),
              loss='mse', metrics=['mae'])
⚠️
return_sequences=True for every layer but the last

Stacked LSTMs must pass the full sequence forward; only the final LSTM returns just its last hidden state to feed the Dense head. Forget this and you get shape-mismatch errors.

Section 11

LSTM vs Transformer

PropertyLSTMTransformer
MemoryRecurrent cell stateSelf-attention over all tokens
Long rangeGood (60–200 steps)Excellent (1000s)
Parallel trainingSequentialFully parallel
Real-time inferenceO(1) per stepNeeds full context
Edge deploymentLightweightOften too large
🎯
LSTMs still own real-time

Transformers rule large-scale NLP, but for streaming ECG, financial ticks, sensor fusion, and on-device speech — where O(1) per-step inference and a small footprint matter — the LSTM is still the go-to.

Section 12

Where LSTMs Live in Production

💹
Financial forecasting
Prices, forex, volatility from OHLCV sequences — with walk-forward validation.
🎙️
Speech recognition
BiLSTM + CTC turns spectrograms into characters, as in DeepSpeech.
🩺
Medical monitoring
ECG/EEG/ICU vitals streamed at 250 Hz+, flagging anomalies on embedded hardware.
🌍
Machine translation
Encoder–decoder LSTMs with attention generate the target word by word.
🎼
Music generation
Trained on MIDI, generates note by note with temperature sampling.
🌦️
Weather
ConvLSTM learns how pressure and temperature grids evolve over time.
⚙️
The common thread: streaming, real time, edge

Wherever data arrives as an ongoing stream and decisions must be fast and local, the LSTM's constant-time step and small size make it the practical choice.

Section 13

8 Golden Rules — Non-Negotiable

  Production LSTM practices
1Always clip gradients (norm 1.0) — exploding gradients produce NaN losses.
2Never shuffle time-series data — split by time only, or you leak the future.
3Normalise inputs — raw values saturate the sigmoid/tanh gates and stall learning.
4return_sequences=True on every stacked layer but the last (Keras).
5Reset hidden/cell state between unrelated sequences — stale state is catastrophic.
6Use eval() + no_grad() at inference — dropout must switch off.
7Start with 1–2 layers, 64–128 units — add depth only after confirming underfit.
8Truncated BPTT beyond ~200 steps — detach the hidden state between chunks.
🛡️
Most LSTM bugs are on this list

Clip, don't shuffle, normalise, reset state. Get these four right and you've avoided the vast majority of real-world LSTM failures.

Section 14

The LSTM Cheat Sheet

fₜ = σ(W_f·[h,x]+b_f)
iₜ = σ(W_i·[h,x]+b_i)
C̃ₜ = tanh(W_c·[h,x]+b_c)
Cₜ = fₜ⊙Cₜ₋₁ + iₜ⊙C̃ₜ
oₜ = σ(W_o·[h,x]+b_o)
hₜ = oₜ⊙tanh(Cₜ)
Regression → Dense(1), MSE, linear
Binary → Dense(1), BCE, sigmoid
Multi-class → Dense(k), CE, softmax
Generation → Dense(vocab), CE, softmax
🚀
You now know LSTMs end to end

Gated memory, a family of variants, the hyperparameters that matter, and the code to ship — from a 60-day forecaster to a streaming medical monitor.