Skip to course content
Free PyTorch course

Advanced Deep Learning with PyTorch

Unit 08.03: Recurrent networks as historical context

Recurrent networks were the answer to word order for years. Understanding what they do — and what it cost — explains why attention replaced them.

Reading left to right, carrying state

An RNN processes one timestep at a time, maintaining a hidden state that summarises everything seen so far. That state is what lets it distinguish orderings.

The data here is built so order is the *only* signal: [1, 2] and [2, 1] contain identical values and opposite labels:

import torch
from torch import nn

torch.manual_seed(0)
# Sequences where only the ORDER differs: [1,2] vs [2,1].
X = torch.tensor([[[1.], [2.]], [[2.], [1.]], [[1.], [2.]], [[2.], [1.]]])
y = torch.tensor([[1.], [0.], [1.], [0.]])

# A bag-of-words style sum cannot tell them apart: both sum to 3.
print("summed inputs:", X.sum(dim=1).flatten().tolist(), "<- identical")

rnn = nn.RNN(input_size=1, hidden_size=8, batch_first=True)
head = nn.Linear(8, 1)
opt = torch.optim.Adam(list(rnn.parameters()) + list(head.parameters()), lr=0.05)

for _ in range(300):
    opt.zero_grad()
    output, hidden = rnn(X)
    nn.BCEWithLogitsLoss()(head(output[:, -1]), y).backward()
    opt.step()

with torch.no_grad():
    output, _ = rnn(X)
    acc = ((torch.sigmoid(head(output[:, -1])) > 0.5).float() == y).float().mean().item()
print("RNN accuracy on order-only data:", acc)
print("output shape:", tuple(output.shape), "= batch, timesteps, hidden")

# RNNs read left to right, carrying a hidden state. That sequential dependency
# is also their weakness: it cannot be parallelised, and long-range signal
# fades. Attention was the answer to both.

The summed inputs are identical for both classes, so any count-based approach is at chance. The RNN separates them, because its hidden state depends on the sequence.

The output shape — batch, timesteps, hidden — shows it produced a state at every position. Taking output[:, -1] uses the final state as a summary of the whole sequence.

The mistake this prevents

Assuming an RNN handles long sequences well. The hidden state is a fixed-size bottleneck, and signal from early positions fades as the sequence grows — the vanishing-gradient problem from Module 5, now along time.

Takeaway

RNNs read sequentially and carry state. That gives them order, and costs them parallelism and long-range memory.