Chapter 5: Sequence Models
Master recurrent neural networks and their variants for processing sequential text data — from vanilla RNNs to LSTMs, GRUs, and the encoder-decoder paradigm.
- Topics
- 6
- Demos
- 3
- Videos
- 3
- Min read
- 45
Chapter Overview
Sequence models are the backbone of modern NLP systems that process text as ordered sequences of tokens. Unlike feedforward networks that treat each input independently, recurrent architectures maintain a hidden state that accumulates information as it reads through a sequence one token at a time. This memory mechanism allows the model to capture dependencies between words regardless of their distance in the sentence.
The vanilla RNN introduced the fundamental idea of recurrence but suffers from the vanishing gradient problem, which makes it difficult to learn long-range dependencies. The Long Short-Term Memory (LSTM) network and the Gated Recurrent Unit (GRU) solve this with gating mechanisms that control information flow through the network. These gated architectures became the dominant approach for tasks like language modeling, machine translation, and text classification throughout the 2010s.
This chapter traces the evolution from simple RNNs through gated variants, bidirectional processing, and the encoder-decoder framework that enabled sequence-to-sequence tasks like translation. Understanding these architectures is essential background for the attention mechanism (Chapter 6) and the Transformer (Chapter 7), which ultimately replaced recurrence with parallelizable self-attention.
Chapter Roadmap
Click any topic to jump in
Recurrent Neural Networks
The fundamental recurrence equation, BPTT, and why vanilla RNNs struggle with long-range dependencies.
Two gated architectures that preserve long-range gradients
LSTM
Gating mechanisms that solve the vanishing gradient problem via an additive cell state highway.
GRU
A streamlined alternative to LSTM that merges the cell and hidden state with fewer gates.
Bidirectional RNNs
Running two RNNs in opposite directions to capture both past and future context at every position.
Encoder compresses, decoder generates with search strategies
Sequence-to-Sequence
The encoder-decoder paradigm for mapping variable-length input sequences to variable-length outputs.
Encoder-Decoder Architecture
Context vector design, beam search decoding, and nucleus sampling for generation quality.
Topics
6 topics in this chapter
A Recurrent Neural Network (RNN) processes a sequence by applying the same function at each time step, taking the current input and the previous hidden state to produce a new hidden state . This recurrence is what gives the network its "memory" --- the hidden state is a compressed summary of everything the network has seen so far.
The hidden state update uses a simple formula: . The nonlinearity squashes the output to , and the two weight matrices (hidden-to-hidden) and (input-to-hidden) are shared across all time steps. This weight sharing means an RNN can process sequences of arbitrary length with a fixed number of parameters.
Training an RNN requires Backpropagation Through Time (BPTT), which unrolls the recurrence and applies the chain rule across time steps. Unfortunately, gradients that are multiplied through many time steps tend to either vanish (shrink to zero) or explode (grow unboundedly). The vanishing gradient problem means vanilla RNNs struggle to learn dependencies spanning more than about 10--20 time steps, motivating the gated architectures covered in the next topics.
Definition
A recurrent neural network is a sequence model that keeps a hidden state and updates it at every step with the same parameters, . Because the weights are shared across time, one network handles sequences of any length; it is trained by backpropagation through time.
In this topic
- 1Hidden State Recurrence
- 2Backpropagation Through Time (BPTT)
- 3Vanishing and Exploding Gradients
- 4RNN Output Modes
Hidden State Recurrence
The hidden state is a vector that encodes information about the entire sequence up to time . At each step, it combines the previous hidden state (what the network remembers) with the current input (what it sees now) through learned weight matrices. The tanh activation bounds the hidden state values, preventing unbounded growth. The same weights and are reused at every time step, which is what makes the architecture recurrent.
The recurrence is a nonlinear dynamical system where controls memory retention and controls input sensitivity. The tanh squashing to acts as a soft saturation — when the pre-activation magnitude exceeds ~2, the output barely changes, causing gradient attenuation. The eigenvalues of determine the system's stability: eigenvalues with magnitude < 1 cause exponential decay (forgetting), while magnitude > 1 causes exponential growth (exploding activations).
If , , , , and , compute .
Backpropagation Through Time (BPTT)
BPTT unrolls the RNN into a deep feedforward network with layers (one per time step) and applies standard backpropagation. The gradient of the loss with respect to the shared weights involves a product of Jacobian matrices across time steps. When the spectral norm of these Jacobians is consistently less than 1, the gradient product shrinks exponentially --- this is the vanishing gradient problem. When it exceeds 1, gradients explode.
The gradient involves a product of Jacobians across time steps. Each Jacobian has spectral norm bounded by . Over steps, this product scales as where is the largest singular value of modulated by tanh derivatives — explaining why gradients vanish () or explode () exponentially.
In a 50-step sequence, if the Jacobian norm at each step is 0.9, what fraction of the gradient from the last step reaches the first step?
Vanishing and Exploding Gradients
The vanishing gradient problem occurs when the product of Jacobian norms across time steps shrinks to near zero, making it impossible to learn long-range dependencies. The exploding gradient problem is the opposite: gradients grow exponentially, causing unstable weight updates. Gradient clipping (capping the gradient norm to a threshold) is a practical fix for exploding gradients. However, vanishing gradients require architectural changes --- specifically the gating mechanisms introduced by LSTMs and GRUs.
Gradient clipping rescales when , which projects the gradient onto a ball of radius . This preserves the direction of the gradient while bounding its magnitude, preventing catastrophic weight updates. Vanishing gradients cannot be fixed by scaling because the information about long-range dependencies is lost — the gradient signal is exponentially attenuated relative to short-range signals, so amplifying everything uniformly does not recover the lost structure.
Why does gradient clipping fix exploding gradients but not vanishing gradients?
RNN Output Modes
The same recurrent core can be wired to inputs and outputs in different ways, and the choice follows from the shape of the task's labels. Many-to-one reads the whole sequence and uses only the final hidden state , as in sentiment classification. Many-to-many emits an output at every step, as in part-of-speech tagging or named entity recognition. One-to-many starts from a single input and generates a sequence, as in image captioning. The failure mode of many-to-one is that every gradient must travel back from the last step, so early tokens learn slowly. Encoder-decoder models, later in this chapter, combine many-to-one with one-to-many.
In many-to-one mode, only contributes to the loss, so gradients must flow backward through all steps to update early representations. In many-to-many mode, each contributes to a local loss, providing gradient injection at every time step. This makes many-to-many training more stable because the effective backpropagation distance is shorter — each parameter receives gradient signal from the nearest output, not just the final one.
For a part-of-speech tagging task on a 10-word sentence, which output mode would you use, and how many predictions does the model make?
Theory Exercise
Problem:
Explain why weight sharing across time steps is essential for RNNs. What would happen if each time step had its own weight matrices?
Hints:
- Think about the number of parameters relative to sequence length
Coding Exercise
Problem:
Implement a vanilla RNN cell in PyTorch from scratch (without using nn.RNN). Create a class that takes an input and previous hidden state, applies the recurrence formula, and returns the new hidden state.
Hints:
- Define W_xh, W_hh, and b_h as nn.Parameter
Related Problems on PixelBank
The Long Short-Term Memory network, introduced by Hochreiter and Schmidhuber in 1997, solves the vanishing gradient problem by introducing a cell state that runs through the entire sequence with minimal modification. Information is added to or removed from the cell state through three gates: the forget gate, input gate, and output gate. Each gate is a sigmoid layer that outputs values between 0 and 1, controlling what fraction of information to let through.
The critical insight is that the cell state update is additive rather than multiplicative: . When the forget gate is close to 1 and the input gate is close to 0, the cell state passes through unchanged, creating a gradient highway that allows information (and gradients) to flow across hundreds of time steps without degradation.
LSTMs dominated sequence modeling for nearly two decades and are still used in production systems. They were the architecture behind breakthroughs in machine translation (Google Translate, 2016), speech recognition (Siri, Alexa), and text generation. Understanding the gating mechanism is also valuable because attention and Transformer architectures use similar sigmoid-gated information flow.
Definition
A Long Short-Term Memory network is a recurrent architecture that adds a cell state updated additively, , under the control of sigmoid forget, input, and output gates. The additive path lets information and gradients persist across many more time steps than a vanilla RNN.
In this topic
- 1Forget Gate
- 2Input Gate and Candidate Cell State
- 3Cell State Update
- 4Output Gate
Forget Gate
The forget gate decides what information to discard from the previous cell state . It concatenates the previous hidden state with the current input , passes them through a linear layer, and applies the sigmoid function to produce values in for each dimension of the cell state. A value of 0 means 'completely forget this information' and 1 means 'completely retain it'. This selective forgetting is what allows LSTMs to clear irrelevant context when processing long sequences.
Along the cell path, , so a gradient crossing steps is scaled by the product of the forget values. With at every step, 100 steps keep of the signal; with , ten steps keep only about 0.001. The gate is a soft value in , not a binary switch. A common practice from Gers et al. (2000), recommended again by Jozefowicz et al. (2015), initializes the forget bias to 1, so before training, which biases a new network toward remembering rather than forgetting.
In a language model processing the sentence 'The cats, which were very fluffy, were sleeping', when should the forget gate activate strongly?
Input Gate and Candidate Cell State
The input gate has two parts that work together. First, the sigmoid layer decides which dimensions of the cell state to update. Second, a tanh layer creates a candidate vector of new values in . The elementwise product gives the actual update: the sigmoid masks which candidate values get written. This two-part design separates the 'what to write' decision () from the 'where to write' decision ().
The input gate and candidate work as a write mechanism. The tanh produces candidate values in (what to write), while the sigmoid produces a gating mask in (how much to write). Their element-wise product means each cell dimension independently decides both the content and the strength of the update. This separation of content generation from write control is what makes LSTMs able to precisely accumulate information over long sequences.
If and , what is the actual update to the cell state?
Cell State Update
The cell state update combines forgetting old information and writing new information in a single additive step. The forget gate scales down the old cell state , and the input gate's filtered candidate values are added. This additive structure is the key to solving vanishing gradients: when and , the gradient flows through the cell state unimpeded. The cell state acts as a conveyor belt carrying information across arbitrarily long sequences.
The update is additive rather than multiplicative. This is the critical difference from vanilla RNNs where involves a matrix multiply through . Addition means the gradient is a diagonal matrix (just the forget gate values), not a full matrix multiply. Over steps, the gradient is — a product of values in , which can be kept near 1 by learning appropriate biases, unlike the uncontrolled spectral-norm products in vanilla RNNs.
If , , and , compute .
Output Gate
The output gate determines what part of the cell state to expose as the hidden state . The cell state is passed through tanh (squashing to ), then multiplied by the sigmoid output gate. This means the cell state can store information that is not immediately visible in the output --- the network can maintain a private memory that only surfaces when relevant. The hidden state is what gets passed to the next time step and used for predictions.
The output gate controls how much of the cell state is exposed to the rest of the network via . The tanh squashes the cell state (which can accumulate to large values) back to , and the sigmoid selectively reveals dimensions. This means the LSTM maintains two distinct representations: the cell state for long-term storage (unbounded, additive updates) and the hidden state for short-term computation (bounded, gated exposure).
If and , what is ?
Theory Exercise
Problem:
An LSTM has hidden_size=256 and input_size=128. How many learnable parameters does a single LSTM cell have? Show the calculation for each gate.
Hints:
- Each gate has a weight matrix for the concatenated [h, x] input and a bias
Coding Exercise
Problem:
Implement a single LSTM cell from scratch in PyTorch (without using nn.LSTM or nn.LSTMCell). Your class should maintain separate parameters for each gate and implement the full forward pass returning both h_t and C_t.
Hints:
- Concatenate h_{t-1} and x_t as the input to all gates
Related Problems on PixelBank
The Gated Recurrent Unit, proposed by Cho et al. in 2014, is a simplified alternative to the LSTM that merges the forget and input gates into a single update gate and combines the cell state and hidden state into one vector. Despite having fewer parameters, GRUs achieve comparable performance to LSTMs on most sequence modeling tasks.
A GRU has two gates: the update gate controls how much of the previous hidden state to retain versus replace with new content, and the reset gate controls how much of the previous hidden state to use when computing the candidate new state. When the reset gate is 0, the candidate ignores the previous hidden state entirely, allowing the network to "start fresh."
The update equation is a convex combination: values of near 0 keep the old state (like an LSTM forget gate near 1), while values near 1 replace it with the candidate (like an LSTM input gate near 1). This coupling means the GRU always "forgets" exactly as much as it "inputs," which reduces flexibility but also reduces overfitting risk.
Definition
A Gated Recurrent Unit is a recurrent cell with an update gate and a reset gate and no separate cell state. Its new state is the convex combination , where the candidate is computed from the input and the reset-gated previous state.
In this topic
- 1Update Gate
- 2Reset Gate
- 3Candidate Hidden State
Update Gate
The update gate plays the combined role of the LSTM's forget and input gates. When is close to 0, the hidden state passes through unchanged from the previous step (the model retains old information). When is close to 1, the hidden state is replaced with the new candidate . This complementary structure means the GRU cannot independently control forgetting and writing --- it always forgets exactly as much as it updates. Despite this constraint, GRUs match LSTM performance on most benchmarks.
The update gate interpolates between the previous hidden state and the candidate: . When , the hidden state is copied forward unchanged (), creating the same gradient highway as the LSTM forget gate. When , the state is fully replaced. This convex combination with learned coefficients subsumes the LSTM's separate forget and input gates into a single mechanism that enforces .
If , , and , compute .
Reset Gate
The reset gate controls how much of the previous hidden state is visible when computing the candidate new state. It is applied inside the candidate computation: . When is close to 0, the previous hidden state is ignored and the candidate is computed from the current input alone, effectively resetting the memory. This allows the GRU to make sharp transitions when the topic or context changes abruptly.
The reset gate controls how much of the previous hidden state contributes to the candidate: . When , the candidate ignores the past entirely and acts like a feedforward network on alone. This allows the GRU to make sharp transitions — completely resetting its memory when the context changes dramatically (e.g., a sentence boundary). The reset gate operates on before it enters the candidate computation, while the update gate operates on the output — a two-stage gating pipeline.
In a sentence boundary detection task, what should the reset gate do when processing the first word of a new sentence?
Candidate Hidden State
The candidate is the new content the GRU proposes at each step, before deciding how much of it to keep. It applies tanh to a linear map of the current input and the reset-gated previous state , so the reset gate chooses which parts of the old memory may influence the proposal. The tanh keeps every component in . The update gate then blends the candidate with to form . If the reset gate stays near 1 the candidate behaves like a vanilla RNN step, which is why the GRU reduces to the plain recurrence of the first topic when both gates are fixed open.
The candidate is the proposed new content, computed from a reset-gated version of the previous state. The tanh bounds the candidate to , and the final state is a convex combination . With hidden dimensions, the GRU has parameters (three gate/candidate matrices) versus the LSTM's (four gates). This 25% parameter reduction often yields comparable performance with faster training, especially on smaller datasets where the LSTM's extra capacity can overfit.
Compare the total parameters of a GRU cell versus an LSTM cell with the same hidden_size=256 and input_size=128.
Theory Exercise
Problem:
The GRU couples forgetting and updating through the update gate: what is retained is exactly (1 - z_t) and what is written is z_t. Explain a scenario where this coupling is a disadvantage compared to the LSTM, which has independent forget and input gates.
Hints:
- Think about situations where you want to keep all old information AND add new information
Coding Exercise
Problem:
Implement a GRU cell from scratch in PyTorch. Include the update gate, reset gate, and candidate computation, then test it on a short sequence.
Hints:
- Concatenate h_prev and x_t for the update and reset gates
Related Problems on PixelBank
A standard RNN processes sequences from left to right, so the hidden state at position only captures information from tokens . For many NLP tasks, the right context is equally important: the word "bank" in "river bank" versus "bank account" is disambiguated by what comes after it, not just before. A Bidirectional RNN solves this by running two independent RNNs --- one forward (left to right) and one backward (right to left) --- and concatenating their hidden states.
At each time step, the bidirectional representation is , where encodes the prefix and encodes the suffix . This doubled representation captures the full context around each token, which is crucial for tasks like named entity recognition, part-of-speech tagging, and extractive question answering.
The main limitation of bidirectional RNNs is that they require the entire sequence to be available before processing begins. This makes them unsuitable for autoregressive generation tasks (where you generate one token at a time) but excellent for encoding tasks where the full input is known upfront.
Definition
A bidirectional RNN runs two independent recurrent networks over the same sequence, one left to right and one right to left, and represents each position by concatenating their states, . Every position therefore sees the full sentence, but the whole input must be available first.
In this topic
- 1Forward and Backward Passes
- 2Concatenation of Hidden States
- 3Use Cases and Limitations
Forward and Backward Passes
A left-to-right RNN gives the state at position only the prefix , yet the word that settles a token's meaning often comes later. The bidirectional fix runs a forward RNN from to and a separate backward RNN from to . The forward state summarizes the left context and the backward state summarizes the right context, and each includes itself. The two networks have separate weights, so the parameter count doubles, and they can run in parallel. The cost is that the backward pass cannot start until the final token has arrived.
The forward RNN computes left-to-right and the backward RNN computes right-to-left. At position , the forward state summarizes and the backward state summarizes . Together they provide the complete sequence context at every position. The two RNNs have independent parameters — they do not share weights — so the model has exactly twice the parameters of a unidirectional RNN.
For the sentence 'I saw her duck', what information does each direction capture at the word 'duck'?
Concatenation of Hidden States
The standard approach is to concatenate the forward and backward hidden states, doubling the representation dimension. For a unidirectional RNN with hidden size , the bidirectional output at each position has size . Alternative combination methods include element-wise addition (), element-wise max, or a learned projection back to dimensions. Concatenation is most common because it preserves all information from both directions without imposing assumptions about how they should combine.
The concatenated representation has dimension where is the hidden size of each direction. This doubles the representation capacity at each position. When projecting to an output space of dimension , the projection matrix is , meaning the model can learn to weight forward and backward context differently for each output dimension. For tasks like NER where both left and right context are informative ("Dr. [PERSON] visited"), the bidirectional representation captures signals that a unidirectional model would miss from one direction.
If the forward hidden size is 128 and you use a bidirectional LSTM, what is the total hidden representation size per time step? How does this affect downstream layers?
Use Cases and Limitations
Bidirectional RNNs excel at encoding tasks where the full input is available: named entity recognition, POS tagging, sentiment classification, and extractive QA. They cannot be used for generation tasks (language modeling, machine translation decoding) because the backward pass requires future tokens that have not been generated yet. In practice, bidirectional LSTMs (BiLSTMs) were the dominant architecture for NLP encoding before Transformers, and models like ELMo used stacked BiLSTMs to produce contextualized word embeddings.
Bidirectional RNNs require the full input sequence to be available before computation — the backward pass starts from the last token. This makes them unsuitable for autoregressive generation where tokens are produced one at a time, because future tokens do not exist yet. However, for encoding tasks (classification, tagging, encoding in seq2seq), bidirectionality provides strictly more information at each position. The computational cost is exactly a unidirectional RNN, but the two directions can be computed in parallel on separate hardware.
Why can you use a BiLSTM encoder but not a BiLSTM decoder in machine translation?
Theory Exercise
Problem:
ELMo (Peters et al., 2018) trains forward and backward LSTMs independently and combines their representations. Why does ELMo NOT use a standard bidirectional LSTM where both directions are trained jointly with the same objective?
Hints:
- Think about what the training objective is for a language model
Coding Exercise
Problem:
Implement a BiLSTM-based named entity recognition (NER) tagger in PyTorch. Use nn.LSTM with bidirectional=True and a linear layer on top for per-token classification.
Hints:
- Set bidirectional=True in nn.LSTM
Related Problems on PixelBank
Sequence-to-sequence (seq2seq) models, introduced by Sutskever et al. in 2014, map a variable-length input sequence to a variable-length output sequence. The architecture uses two RNNs: an encoder that reads the input and compresses it into a fixed-length vector, and a decoder that generates the output sequence one token at a time conditioned on this vector.
The key challenge is the information bottleneck: the entire source sequence must be compressed into a single fixed-size context vector (typically the encoder's final hidden state). For short sequences this works well, but for long inputs, the fixed-size vector cannot retain all necessary details. This bottleneck motivated the development of attention mechanisms (Chapter 6), which allow the decoder to look back at all encoder states rather than relying on a single summary vector.
Seq2seq models brought neural approaches to tasks with different-length inputs and outputs: machine translation ("I love you" → "Je t'aime"), text summarization, dialogue systems, and even code generation. The teacher forcing training strategy --- feeding the ground-truth previous token rather than the model's own prediction --- accelerates convergence but creates a train-test mismatch called exposure bias.
Definition
A sequence-to-sequence model maps an input sequence to an output sequence of possibly different length with two networks: an encoder RNN that reads the source into a context vector , and a decoder RNN that generates the target one token at a time, modeling until it emits an end token.
In this topic
- 1Encoder
- 2Decoder and Autoregressive Generation
- 3Teacher Forcing
- 4Fixed-Length Bottleneck
Encoder
The encoder reads the source sequence token by token and produces a hidden state at each position. The final hidden state serves as the context vector that summarizes the entire input. For LSTM encoders, both the final hidden state and cell state are passed to the decoder. Using a bidirectional encoder is common because it captures both forward and backward context, though the doubled hidden states must be projected down to match the decoder's dimensionality.
The encoder maps a variable-length input to a fixed-size context . For a long input this is a lossy compression: the same numbers must summarize 5 tokens or 500, and the recurrent update overwrites early information as new tokens arrive. Real-valued vectors could in principle store a great deal, so the practical limit is what gradient descent can learn to pack into , not raw bit capacity. Sutskever et al. found that reversing the source sentence improved results, because it shortened the distance between the first source words and the first target words. Attention, in Chapter 6, removes the bottleneck.
For translating the French sentence 'Je suis etudiant' (3 tokens) using an LSTM encoder with hidden_size=256, what are the shapes of the context vectors passed to the decoder?
Decoder and Autoregressive Generation
The decoder generates the output sequence one token at a time. It is initialized with the encoder's final state and at each step takes the previously generated token as input (autoregressive property). A linear layer followed by softmax converts each decoder hidden state to a probability distribution over the target vocabulary. Generation starts with a special <SOS> token and continues until the model produces an <EOS> token or reaches a maximum length.
The decoder generates tokens autoregressively: where . At inference time, each predicted token is fed back as input to produce the next token. This creates a sequential dependency chain where errors compound — a wrong token at step shifts the entire conditional distribution for all subsequent tokens, a phenomenon known as exposure bias.
During training with teacher forcing, the decoder input at step 3 is the ground-truth . During inference, what is the input at step 3 instead?
Teacher Forcing
Teacher forcing feeds the ground-truth target token as the decoder input at each step during training, rather than the model's own previous prediction. This provides a stable training signal and dramatically speeds up convergence because the decoder never needs to recover from its own errors during training. However, it introduces exposure bias: at test time, the model must condition on its own (potentially incorrect) predictions, a distribution it never encountered during training. Scheduled sampling mitigates this by gradually transitioning from teacher forcing to model predictions during training.
During training, teacher forcing feeds the ground-truth token (not the model's prediction ) as input at each step. This means the loss at step is — conditioned on perfect history. The discrepancy is that at inference time, the model conditions on its own (possibly incorrect) predictions. This train-test mismatch means the model never learns to recover from its own errors. Scheduled sampling addresses this by randomly replacing ground-truth inputs with model predictions during training, with the replacement probability increasing over the course of training.
In scheduled sampling with a linear decay schedule starting at probability p=1.0 (always teacher force) and decaying by 0.01 per epoch, at epoch 60, what is the probability of using teacher forcing?
Fixed-Length Bottleneck
The most significant limitation of vanilla seq2seq is that the entire source sequence must be encoded into a single fixed-length vector . Regardless of whether the input is 5 words or 500 words, the context vector has the same dimensionality. Empirically, seq2seq performance degrades sharply on sentences longer than those in the training set. Cho et al. (2014) showed that BLEU scores drop significantly for source sentences beyond 20 tokens. This bottleneck is the direct motivation for the attention mechanism, which replaces the single context vector with a dynamic weighted combination of all encoder states.
The context vector must encode all source information regardless of sequence length. For a sentence of tokens each with embedding dimension , the input has dimensions of information compressed into dimensions. When , significant information loss is inevitable. Empirically, BLEU scores for seq2seq translation drop sharply for sentences longer than 20--30 words, precisely because the bottleneck cannot represent the fine-grained lexical and structural details needed for accurate translation of long sentences.
If the encoder hidden size is 512, how many bits of information can the context vector theoretically store? Is this sufficient for a 100-word sentence?
Theory Exercise
Problem:
Explain the difference between greedy decoding, beam search (beam size B=3), and sampling for seq2seq generation. When would you prefer each strategy?
Hints:
- Think about the trade-off between quality and diversity
Coding Exercise
Problem:
Implement a minimal seq2seq model in PyTorch with an LSTM encoder and LSTM decoder. Train it to reverse a short digit sequence (e.g., '1 2 3' → '3 2 1').
Hints:
- The encoder processes the input and returns its final hidden/cell state
Related Problems on PixelBank
The encoder-decoder architecture is the general framework underlying seq2seq models, and understanding its components --- the context vector, decoding strategies, and output generation --- is essential for all sequence transduction tasks. While Topic 5 introduced the architecture, this topic dives deeper into the practical aspects of building and deploying encoder-decoder systems.
The context vector is the bridge between encoder and decoder. In the basic seq2seq model, it is simply the encoder's final hidden state. More advanced variants use attention (Chapter 6) to create a different context vector at each decoder step. The choice of context vector mechanism is the single most impactful design decision in encoder-decoder models.
Decoding strategies determine how the model generates output sequences from the probability distributions it produces. Greedy decoding, beam search, top- sampling, and nucleus (top-) sampling each offer different trade-offs between output quality, diversity, and computational cost. The right strategy depends on the task: beam search for translation, nucleus sampling for dialogue, greedy for simple classification.
Definition
The encoder-decoder architecture is a general framework for sequence transduction: an encoder maps the input to representations , a context function summarizes them for the decoder, and a decoding strategy such as greedy search, beam search, or nucleus sampling turns the decoder's distributions into an output sequence.
In this topic
- 1Context Vector Design
- 2Beam Search Decoding
- 3Nucleus (Top-p) Sampling
Context Vector Design
The context vector summarizes the encoder output for the decoder. In vanilla seq2seq, (the last hidden state). Alternatives include: (1) averaging all encoder states: , (2) max-pooling across time, (3) using a learned weighted combination (attention). The choice of determines how much information from the source sequence is available to the decoder. Using only the final state creates the bottleneck problem; using all states with attention solves it.
The simplest context vector is , the encoder's final hidden state. A common improvement is , concatenating the final states of a bidirectional encoder, which captures information processed from both ends. Another option is or , pooling across all time steps. Each design trades off between compression (more lossy) and coverage (more complete). The attention mechanism (Chapter 6) eliminates this trade-off entirely by computing a different weighted combination of all encoder states at each decoding step.
Compare three context vector strategies for encoding 'The quick brown fox jumps over the lazy dog' (9 words) with hidden_size=256.
Beam Search Decoding
Beam search maintains candidate sequences (beams) at each decoding step. Each beam is extended by all vocabulary tokens, scored by cumulative log-probability, and the top candidates are kept. This explores a wider search space than greedy decoding without the exponential cost of exhaustive search. A beam size of or is standard for machine translation. Length normalization divides the score by (typically ) to prevent the algorithm from preferring shorter sequences, which naturally have higher log-probabilities.
Beam search maintains hypotheses (beams) at each decoding step, expanding each by the top- vocabulary tokens and keeping the highest-scoring partial sequences. The score of a hypothesis is . With beam width , the algorithm explores candidates per step, making it times more expensive than greedy decoding but dramatically improving output quality. Length normalization divides the log-probability by (typically ) to prevent the search from favoring shorter sequences, whose cumulative log-probabilities are less negative.
With beam size B=2 and vocabulary {a, b, c}, if the initial beam has sequences ['a'] (score -0.3) and ['b'] (score -0.5), and the next-step probabilities are P(a|'a')=0.6, P(b|'a')=0.3, P(c|'a')=0.1, P(a|'b')=0.2, P(b|'b')=0.7, P(c|'b')=0.1, what are the top-2 beams after this step?
Nucleus (Top-p) Sampling
Nucleus sampling (Holtzman et al., 2020) dynamically selects the smallest set of tokens whose cumulative probability exceeds a threshold (typically 0.9 or 0.95), then samples from this set after renormalization. Unlike top- which always considers exactly tokens regardless of the distribution shape, nucleus sampling adapts: when the model is confident (peaked distribution), the nucleus is small; when uncertain (flat distribution), it is large. This produces more coherent text than pure sampling while maintaining diversity.
Nucleus sampling selects from the smallest set of tokens whose cumulative probability exceeds a threshold : where is sorted by descending probability. Unlike top- sampling which always keeps exactly tokens, nucleus sampling adapts the candidate set size to the model's confidence. When the model is confident (one token has probability 0.9), the nucleus contains just 1--2 tokens. When uncertain (flat distribution), it may contain dozens. This adaptive behavior produces more natural and diverse text than fixed- sampling.
Given P = {the: 0.4, a: 0.25, my: 0.15, our: 0.1, her: 0.05, its: 0.03, his: 0.02} and p=0.9, what is the nucleus?
Theory Exercise
Problem:
Explain why reversing the source sentence before feeding it to the encoder improves translation quality in vanilla seq2seq models (as discovered by Sutskever et al., 2014). How does this relate to the vanishing gradient problem?
Hints:
- Think about the distance between corresponding source and target words
Coding Exercise
Problem:
Implement beam search decoding for a seq2seq model. Given a trained encoder-decoder, implement a beam_search function that maintains B candidate sequences and returns the highest-scoring complete sequence.
Hints:
- Track (sequence, score, decoder_state) tuples for each beam