Skip to content

RNNs, LSTM, and GRU

Processing sequences — from vanilla RNNs to gated architectures


The Sequential Data Problem

Many problems involve sequences: text, speech, time series, video. Standard neural networks fail because:

  1. Variable length: Sentences have different numbers of words
  2. Order matters: "dog bites man" ≠ "man bites dog"
  3. Long-range dependencies: "The cat, which sat on the mat, was..."

Why MLPs Fail

  • Fixed input size (can't handle variable length)
  • No parameter sharing across positions
  • No notion of temporal order

Vanilla RNN

RNNs maintain a hidden state that gets updated at each timestep, creating a "memory" of previous inputs.

Architecture

RNN Unrolled

At each timestep t:

ht=tanh(Whhht1+Wxhxt+bh)yt=Whyht+by

Where:

  • xt = input at time t
  • ht = hidden state at time t
  • yt = output at time t
  • Whh,Wxh,Why = weight matrices (shared across time)

Parameter Sharing

The same weights are used at every timestep — this is what enables handling variable-length sequences.

Backpropagation Through Time (BPTT)

Unroll the RNN and apply standard backpropagation:

x₁ → x₂ → x₃ → ... → xₜ
↓     ↓     ↓           ↓
h₁ → h₂ → h₃ → ... → hₜ
↓     ↓     ↓           ↓
y₁    y₂    y₃         yₜ

Gradient flows backward through all timesteps.


The Vanishing Gradient Problem in RNNs

RNNs struggle with long sequences because gradients vanish (or explode) over many timesteps.

Why Gradients Vanish

The gradient from timestep T to timestep 1:

LTh1=LThTt=2Ththt1

Each term htht1=WhhTdiag(tanh(zt))

  • If largest eigenvalue of Whh < 1: gradients shrink exponentially
  • If largest eigenvalue of Whh > 1: gradients explode

Gradient Vanishing in RNN

Consequence

Early timesteps receive near-zero gradients — the RNN can't learn long-range dependencies. "The cat [100 words later] was hungry" — RNN forgets about "cat."


LSTM: Long Short-Term Memory

LSTMs solve vanishing gradients with a cell state that acts as a highway for gradient flow, controlled by gates.

Architecture

LSTM Cell

Three gates + cell state:

  • Forget gate ft: What to discard from cell state
  • Input gate it: What new information to add
  • Output gate ot: What to expose to the next layer

LSTM Equations

Forget gate (what to forget):

ft=σ(Wf[ht1,xt]+bf)

Input gate (what to update):

it=σ(Wi[ht1,xt]+bi)

Candidate values (new information):

C~t=tanh(WC[ht1,xt]+bC)

Cell state update:

Ct=ftCt1+itC~t

Output gate (what to expose):

ot=σ(Wo[ht1,xt]+bo)

Hidden state:

ht=ottanh(Ct)

Why LSTM Solves Vanishing Gradients

The cell state update is additive:

Ct=ftCt1+itC~t

Gradient through cell state:

CtCt1=ft

If ft1 (forget gate open), gradients flow unchanged through many timesteps — the cell state acts as a gradient highway.


GRU: Gated Recurrent Unit

GRU simplifies LSTM with 2 gates instead of 3, and no separate cell state.

Architecture

GRU Cell

Reset gate (how much past to forget):

rt=σ(Wr[ht1,xt])

Update gate (how much to update):

zt=σ(Wz[ht1,xt])

Candidate hidden state:

h~t=tanh(W[rtht1,xt])

Final hidden state:

ht=(1zt)ht1+zth~t

LSTM vs GRU

AspectLSTMGRU
Gates3 (forget, input, output)2 (reset, update)
StatesCell state + hidden stateHidden state only
ParametersMore (~4x hidden²)Fewer (~3x hidden²)
PerformanceOften better for complex sequencesComparable, sometimes better
Training speedSlowerFaster

Rule of thumb: Start with GRU (faster), try LSTM if GRU underperforms.


Bidirectional RNNs

Process sequence in both directions to capture future context:

Forward:   h₁ → h₂ → h₃ → ... → hₜ
Backward:  h₁ ← h₂ ← h₃ ← ... ← hₜ
Output:    [h₁→;h₁←] [h₂→;h₂←] ...

When Bidirectional Helps

  • NLP: Understanding "bank" requires future context ("river bank" vs "bank account")
  • Speech: Pronunciation depends on following sounds
  • NOT for: Real-time prediction (can't see future)

RNNs vs Transformers

AspectRNNsTransformers
ProcessingSequential (can't parallelize)Parallel (all positions at once)
ComplexityO(T) sequential stepsO(T²) attention, but parallelizable
Long-rangeStruggles despite gatesDirect attention to any position
MemoryO(1) hidden state sizeO(T) keys/values
Inductive biasSequential, localNone (learns from data)

Where RNNs Still Matter

  1. Streaming/online: Process tokens one at a time
  2. Edge devices: Lower memory than storing all keys/values
  3. Very long sequences: Linear complexity vs O(T²) attention
  4. Causal modeling: Natural fit for sequential generation

Reality: Transformers have largely replaced RNNs for NLP, but RNNs remain relevant for specific use cases.


Implementation Tips

Gradient Clipping

Essential for RNN training:

python
torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)

Packed Sequences

Handle variable-length sequences efficiently:

python
packed = nn.utils.rnn.pack_padded_sequence(x, lengths, batch_first=True)
output, hidden = rnn(packed)
output, _ = nn.utils.rnn.pad_packed_sequence(output, batch_first=True)

Dropout for RNNs

Apply dropout to non-recurrent connections:

python
nn.LSTM(input_size, hidden_size, dropout=0.2)  # between layers

Interview Questions

Q1: "Explain why LSTMs solve the vanishing gradient problem."

The cell state acts as a gradient highway.

In vanilla RNNs, gradients multiply through Whh at each timestep. If eigenvalues < 1, gradients vanish exponentially.

In LSTMs, the cell state update is additive:

Ct=ftCt1+itC~t

The gradient through cell state:

CtCt1=ft

When ft1 (forget gate open), gradients pass through unchanged. Over many timesteps:

CTC1=t=2Tft1

Key insight: The forget gate learns which information to preserve, allowing gradients to flow to early timesteps. It's not that gradients can't vanish — but the network can learn to keep them flowing for important information.

Q2: "What's the difference between LSTM and GRU?"

LSTM has 3 gates and separate cell/hidden states:

  • Forget gate: What to discard from cell
  • Input gate: What new info to add
  • Output gate: What to expose as hidden state
  • Cell state: Long-term memory (gradient highway)

GRU has 2 gates and only hidden state:

  • Reset gate: How much past to forget for candidate
  • Update gate: Interpolate between old and new state
  • No separate cell state

Practical differences:

  • GRU has fewer parameters (3x vs 4x hidden²)
  • GRU trains faster
  • LSTM may capture more complex dependencies
  • Performance is often similar

When to choose:

  • Start with GRU (simpler, faster)
  • Try LSTM if GRU underperforms
  • For very complex sequences, LSTM may be better

Q3: "When would you still use RNNs over Transformers?"

Use RNNs when:

  1. Online/streaming processing: Need to process tokens one at a time as they arrive (real-time speech, live transcription). Transformers need all tokens to compute attention.

  2. Very long sequences: Transformer attention is O(T²). For sequences of 100K+ tokens, RNNs with O(T) complexity may be more practical. (Though efficient transformers like Longformer exist.)

  3. Edge deployment: RNN hidden state is fixed size. Transformers store O(T) keys/values, which grows with sequence length.

  4. Causal modeling: RNNs have natural sequential inductive bias, which may help with limited data.

Reality: Transformers dominate most NLP tasks. RNNs are still used in niche applications (streaming, embedded systems) and sometimes combined with transformers (transformer encoders + RNN decoders).


Key Takeaways

  1. RNNs process sequences with shared weights and hidden state memory.

  2. Vanilla RNNs suffer from vanishing gradients — can't learn long-range dependencies.

  3. LSTM's cell state is a gradient highway — forget gates control what gradients flow through.

  4. GRU is simpler than LSTM (2 gates vs 3) with comparable performance.

  5. Bidirectional RNNs capture both past and future context.

  6. Transformers have largely replaced RNNs but RNNs remain relevant for streaming and edge applications.