Recurrent Neural Networks (RNN), LSTMs, and GRUs for Sequence Modeling

Standard feedforward neural networks and CNNs assume that all inputs are independent of one another. However, many real-world modalities — natural language sentences, time-series stock prices, DNA sequences, and audio waveforms — are inherently sequential. In language, the meaning of a word depends entirely on the preceding context: "The bank was flooded with water" vs "The bank approved the loan".

Recurrent Neural Networks (RNNs) process sequences step-by-step, maintaining an internal Hidden State ( mathbf{h}_t ) that acts as a working memory of all past tokens processed so far.

Vanilla RNN Architecture: The Recurrent Loop

At each time step ( t ), a Vanilla RNN takes the current input token vector ( mathbf{x}_t ) and the previous hidden state ( mathbf{h}_{t-1} ), computing the new hidden state ( mathbf{h}_t ):

( mathbf{h}_t = anh(mathbf{W}_{hh} mathbf{h}_{t-1} + mathbf{W}_{xh} mathbf{x}_t + mathbf{b}_h) )

Backpropagation Through Time (BPTT): To train an RNN, the recurrent loop is unrolled across time steps ( t=1, dots, T ). Gradients flow backward across time steps via the chain rule.

The Fatal Flaw: The Vanishing & Exploding Gradient Problem

When computing gradients across ( T ) time steps, the chain rule requires repeatedly multiplying by the recurrent weight matrix ( mathbf{W}_{hh} ):

( rac{partial mathcal{L}_T}{partial mathbf{h}_1} propto prod_{k=2}^T mathbf{W}_{hh}^T ext{diag}(1 - anh^2(z_k)) )
  • If the largest eigenvalue of ( mathbf{W}_{hh} < 1 ), the gradient shrinks exponentially to zero (Vanishing Gradient). The network suffers from severe amnesia; it cannot learn dependencies spanning more than 8-10 words!
  • If the largest eigenvalue of ( mathbf{W}_{hh} > 1 ), gradients blow up to infinity (Exploding Gradient), causing numerical overflow and NaN parameters.

Long Short-Term Memory (LSTM) Networks (Hochreiter & Schmidhuber, 1997)

To overcome the vanishing gradient bottleneck, Sepp Hochreiter and Jürgen Schmidhuber invented the Long Short-Term Memory (LSTM) cell. The key innovation is the Cell State (( mathbf{c}_t )) — an internal highway that runs straight down the entire chain with only minor linear interactions, regulated by three non-linear Gating Mechanisms:

Gate Name Mathematical Formula Functional Role
1. Forget Gate (( mathbf{f}_t )) ( mathbf{f}_t = sigma(mathbf{W}_f [mathbf{h}_{t-1}, mathbf{x}_t] + mathbf{b}_f) ) Outputs values between 0 (completely erase) and 1 (completely keep). Decides what irrelevant past information to purge from cell memory.
2. Input Gate (( mathbf{i}_t ) & ( ilde{mathbf{c}}_t )) ( mathbf{i}_t = sigma(mathbf{W}_i [mathbf{h}_{t-1}, mathbf{x}_t] + mathbf{b}_i) )
( ilde{mathbf{c}}_t = anh(mathbf{W}_c [mathbf{h}_{t-1}, mathbf{x}_t] + mathbf{b}_c) )
Decides which new candidate values ( ilde{mathbf{c}}_t ) should be written into the cell state, scaled by importance factor ( mathbf{i}_t ).
Update Cell State ( mathbf{c}_t = mathbf{f}_t odot mathbf{c}_{t-1} + mathbf{i}_t odot ilde{mathbf{c}}_t ) Linear combination that updates cell state with zero gradient degradation!
3. Output Gate (( mathbf{o}_t )) ( mathbf{o}_t = sigma(mathbf{W}_o [mathbf{h}_{t-1}, mathbf{x}_t] + mathbf{b}_o) )
( mathbf{h}_t = mathbf{o}_t odot anh(mathbf{c}_t) )
Filters the internal cell state to produce the visible external hidden state ( mathbf{h}_t ).

Gated Recurrent Unit (GRU) (Cho et al., 2014)

The GRU is a streamlined variation of the LSTM that merges the cell state and hidden state into a single vector, using only two gates: a Reset Gate (( mathbf{r}_t )) and an Update Gate (( mathbf{z}_t )). GRUs have ~25% fewer parameters than LSTMs, training faster while achieving comparable empirical performance.

PyTorch Implementation: Sequence Classification with an LSTM

The following script demonstrates building an LSTM sequence classifier in PyTorch:

import torch
import torch.nn as nn

class LSTMSequenceClassifier(nn.Module):
    def __init__(self, vocab_size, embedding_dim, hidden_dim, output_dim):
        super(LSTMSequenceClassifier, self).__init__()
        self.embedding = nn.Embedding(vocab_size, embedding_dim)
        # Bidirectional LSTM: processes sequences forward and backward
        self.lstm = nn.LSTM(embedding_dim, hidden_dim, batch_first=True, bidirectional=True)
        self.fc = nn.Linear(hidden_dim * 2, output_dim)

    def forward(self, text_seq):
        embedded = self.embedding(text_seq)  # [batch_size, seq_len, embed_dim]
        # output: all time steps, (hidden_state, cell_state)
        lstm_out, (hn, cn) = self.lstm(embedded)
        
        # Concatenate final forward and backward hidden states
        final_hidden = torch.cat((hn[-2, :, :], hn[-1, :, :]), dim=1)
        logits = self.fc(final_hidden)
        return logits

# Initialize Model
model = LSTMSequenceClassifier(vocab_size=1000, embedding_dim=64, hidden_dim=128, output_dim=2)
# Sample batch: 4 sequences of 10 word token IDs
sample_batch = torch.randint(0, 1000, (4, 10))
predictions = model(sample_batch)

print(f"Batch Input Shape  : {sample_batch.shape}")
print(f"Output Logits Shape: {predictions.shape} (4 samples classified into 2 classes)")

Frequently Asked Questions (FAQ) - Student & Interview Review

Q1. Why does the Cell State in an LSTM prevent vanishing gradients?

The cell state c_t is updated purely through linear addition: c_t = f_t * c_{t-1} + i_t * c_tilde. During backpropagation, the gradient flows directly through this additive highway without being repeatedly compressed by non-linear tanh activations, allowing gradients to persist across hundreds of time steps.

Q2. What is a Bidirectional LSTM (BiLSTM)?

A standard LSTM only knows past context (words from left to right). A Bidirectional LSTM runs two separate LSTM networks concurrently: one processing the sentence forward (left-to-right) and another backward (right-to-left), concatenating their hidden states. This provides the model with complete past and future context at every word.

Q3. What is the difference between an LSTM and a GRU?

An LSTM has three gates (Forget, Input, Output) and maintains two separate internal vectors: Cell State (c) and Hidden State (h). A GRU has only two gates (Reset and Update), merges the cell state and hidden state into a single representation, and has 25% fewer parameters, making it faster to train.

Q4. Why did Transformers replace LSTMs in modern Natural Language Processing?

LSTMs process tokens strictly sequentially step-by-step (token t cannot be computed until token t-1 finishes), making it impossible to parallelize training across massive GPU clusters. Transformers use Self-Attention, which processes all tokens in parallel simultaneously, unlocking internet-scale pretraining.

Explore Related Artificial Intelligence Tutorials & Next Steps

Broaden your foundational and advanced AI knowledge across our curriculum:

Transformers & Self-Attention

How self-attention solved the sequential bottleneck of RNNs and LSTMs.

NLP Preprocessing & Tokenization

Preparing text sequences, tokens, and vocabulary for sequential models.

Word2Vec, GloVe & Vector Spaces

Embedding words into continuous vectors before feeding to LSTM cells.

BCA & University Viva-Voce Guide

LSTM cell architecture: forget gate, input gate, cell state, output gate.

Share Share on Facebook Share on Twitter Share on LinkedIn Pin on Pinterest Share on Reddit

You may also like this!