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.
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 ):
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.
When computing gradients across ( T ) time steps, the chain rule requires repeatedly multiplying by the recurrent weight matrix ( mathbf{W}_{hh} ):
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 ). |
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.
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)")
Broaden your foundational and advanced AI knowledge across our curriculum:
How self-attention solved the sequential bottleneck of RNNs and LSTMs.
Preparing text sequences, tokens, and vocabulary for sequential models.
Embedding words into continuous vectors before feeding to LSTM cells.
LSTM cell architecture: forget gate, input gate, cell state, output gate.