The Encoder-Decoder Architecture
Imagine building a machine translation system in 2014. Input and output are sequences of different, unaligned lengths. An English sentence of 9 words can become a French sentence of 12 words. Word order is scrambled between them. Classical statistical translation pipelines needed separate alignment models, phrase tables, and language models. These were glued together with hand-engineered features. The encoder-decoder architecture replaced this pipeline with a single differentiable model. It is trained end-to-end. One network reads the source sequence and compresses it into a vector. A second network reads that vector and generates the target sequence one token at a time. This architecture matters for an important reason. It is the first clean solution to a general problem. That problem is mapping a sequence to a sequence of different length. It does this without requiring the two sequences to be aligned position-by-position. That single idea underlies machine translation, abstractive summarization, speech recognition, and image captioning. It also underlies, in its modern Transformer incarnation, the encoder-decoder split. That split is still visible in models like T5 and the original machine-translation Transformer. Even decoder-only large language models inherit conceptual DNA from this design. The notion is this: first build a contextual representation, then autoregressively generate from it. The big picture is deceptively simple. An encoder network consumes the entire input sequence. It produces a fixed-size representation called the context. In attention-augmented variants, this representation can be variable-size instead. A decoder network is initialized from that context. It generates the output sequence token by token. Each new token is conditioned on both the context and everything generated so far. Training is done jointly by backpropagating a single loss. This loss is typically the negative log-likelihood of the target sequence. It passes through both networks simultaneously. This article develops the architecture precisely. It covers the encoder and decoder as separate recurrent networks. It covers the notorious information bottleneck, created by squeezing an entire sentence into one fixed-length vector. It also covers the mechanics of autoregressive decoding at inference time, including greedy search and beam search. We build the pseudocode and trace a full worked translation example. We also set up — without yet solving — the bottleneck problem. The Attention Mechanism in NLP was invented to fix that problem.
- Encoder-decoder maps variable-length input sequences to variable-length output sequences using two coupled networks.
- The encoder compresses the source into a fixed-size context vector (its final hidden state).
- The decoder is a conditional language model, generating one token at a time from that context.
- Training uses teacher forcing: the decoder sees the true previous token, not its own prediction, during learning.
- Inference is autoregressive: each generated token feeds back in as input to produce the next.
- The single fixed-size context vector is an information bottleneck, motivating the Attention Mechanism in NLP.
An encoder compresses an input sequence into a context vector, and a decoder autoregressively expands that context back into an output sequence, with the entire pipeline trained jointly as one probability model.
The idea
The encoder-decoder architecture — also called sequence-to-sequence (seq2seq) modeling — factors the task of transducing one sequence into another into two learned functions. Given a source sequence , the encoder processes it and produces a representation , called the context vector:
In the canonical Sequence-to-Sequence Models formulation, the encoder is a recurrent network (RNN, LSTM, or GRU) run over the input, and is simply its final hidden state . The decoder is a second recurrent network that is initialized with and generates the output sequence one symbol at a time, where each symbol's distribution is conditioned on the context and all previously generated symbols:
This factorization is exactly the chain rule of probability applied to the output sequence, with the entire source sequence summarized into the single conditioning variable . Two properties distinguish this from earlier sequence models. First, and need not match — this is precisely what makes translation, summarization, and other length-changing tasks tractable. Second, the decoder is itself an autoregressive model: a conditional language model over the target vocabulary, where generation of depends on , exactly like the Neural Machine Translation systems that popularized this design. The term information bottleneck refers to the fact that has fixed dimensionality (say, 512 or 1024 real numbers) regardless of how long the input sequence is. A 5-word sentence and a 50-word sentence are both compressed into a vector of the same size. This is the central structural weakness of the vanilla architecture: as grows, must encode proportionally more information in a space that does not grow with it, and empirically translation quality degrades sharply on long sentences. This weakness is precisely the motivation for the attention mechanism, which allows the decoder to look back at all encoder hidden states rather than relying on one compressed summary — but that solution is a separate development built on top of the architecture described here.
How it works
The system consists of two coupled recurrent components sharing a training objective but running under different regimes at train versus inference time.
Encoding. The encoder reads the source tokens one at a time, updating a hidden state:
with typically initialized to zero. After processing all tokens, the final hidden state becomes the context vector . (Some variants also use a summary of the cell state in LSTMs, or concatenate forward and backward hidden states from a bidirectional encoder — a detail worth noting but orthogonal to the core mechanism.)
Decoding at training time. The decoder is initialized with . At each step , it consumes the true previous target token (not its own prediction) — a technique called teacher forcing — updates its hidden state, and produces a probability distribution over the vocabulary via a softmax layer:
The first input to the decoder is a special `` (beginning-of-sequence) token, and generation is trained to stop by predicting a special `` (end-of-sequence) token. The whole network — encoder and decoder together — is trained by minimizing the cross-entropy loss between the predicted distributions and the true target tokens, summed over the sequence and averaged over a batch.
Decoding at inference time. At test time there is no ground truth to feed in, so the decoder must feed its own previous prediction back as the next input — this is the defining feature of autoregressive decoding. The simplest strategy, greedy decoding, picks the single highest-probability token at each step. Because greedy decoding can lock in an early suboptimal choice, beam search instead tracks the highest-scoring partial sequences ("beams") at each step, expanding all of them and keeping only the top overall. ``` function ENCODE(x[1..n]): h ← zero_vector() for t in 1..n: h ← RNN_enc(x[t], h) return h # this is the context vector c function GREEDY_DECODE(c, max_len): y ← [BOS] h ← c for t in 1..max_len: h ← RNN_dec(y[t-1], h) dist ← softmax(W · h + b) y_t ← argmax(dist) append y_t to y if y_t == EOS: break return y[2:] # drop the leading BOS function BEAM_SEARCH(c, k, max_len): beams ← [ (sequence=[BOS], score=0.0, hidden=c, done=false) ] for t in 1..max_len: candidates ← empty list for beam in beams: if beam.done: candidates.add(beam) # frozen: already emitted EOS continue h ← RNN_dec(beam.sequence[-1], beam.hidden) dist ← softmax(W · h + b) for token, prob in top_k_tokens(dist, k): new_score ← beam.score + log(prob) new_seq ← beam.sequence + [token] candidates.add( (new_seq, new_score, h, token == EOS) ) beams ← top_k_by_score(candidates, k) if all beams.done: break return highest_scoring(beams).sequence[1:] # drop BOS function TRAIN_STEP(x[1..n], y[1..m]): c ← ENCODE(x) h ← c loss ← 0 for t in 1..m: prev ← (y[t-1] if t > 1 else BOS) # teacher forcing h ← RNN_dec(prev, h) dist ← softmax(W · h + b) loss ← loss - log(dist[y[t]]) backpropagate(loss) # through decoder AND encoder update_parameters() ``` Three details deserve emphasis. First, `RNN_enc` and `RNN_dec` have separate parameters — they are two distinct networks, not one network reused twice. Second, teacher forcing means the training-time input sequence to the decoder is always the gold target shifted by one position, which decouples training from the model's own (possibly wrong) predictions and stabilizes learning, at the cost of a train/inference mismatch called exposure bias. Third, gradients from the decoder's loss flow backward not just through the decoder but all the way through the context vector into the encoder, so the encoder learns to produce representations useful for decoding, not representations useful in the abstract.
Complexity & correctness
Time complexity. Let be the source length, the target length, the hidden dimension, and the vocabulary size. Encoding requires sequential RNN steps, each costing for the recurrent matrix multiplications (for an LSTM, a small constant factor larger due to gates), giving . Decoding requires sequential steps, each costing for the recurrence plus for the softmax projection, giving . Training a single example thus costs
and inference under greedy decoding costs the same with replaced by the number of steps until `` is emitted (bounded by `max_len`). Beam search with beam width multiplies the decoding cost by , since hypotheses must be expanded at every step: . This is the honest tradeoff of beam search — a constant-factor slowdown in exchange for exploring a wider swath of the output space than a single greedy path.
Space complexity. Training must store all intermediate hidden states for backpropagation through time, giving activation memory per example (plus for the shared weight matrices, independent of sequence length). Beam search at inference needs memory to track the active hidden states, plus to store the candidate sequences.
Why the architecture computes what it claims to compute. The correctness argument is not "does the algorithm terminate correctly" in the classical sense, but "does the model define a valid, learnable probability distribution over target sequences." Three facts establish this: 1. Well-formed distribution. At every decoding step, softmax guarantees for all and . The chain-rule product of these per-step distributions is therefore itself a valid probability distribution over sequences (it sums to 1 over all sequences ending in ``, by induction on sequence length and the law of total probability). 2. The bottleneck is a real information constraint, not a training artifact. Because has fixed dimensionality, and the decoder's entire access to the source is through , the mutual information that the model can exploit is upper-bounded by — a fixed number of bits regardless of . As grows, the average bits of source information available per source token shrinks, which is precisely why empirical BLEU scores for vanilla encoder-decoder models degrade on long sentences: this is a provable capacity limit, not merely an optimization difficulty. This observation is exactly the gap that attention-augmented decoders close, since attention lets the decoder read from separate vectors instead of one. 3. Teacher forcing trains a consistent estimator of the true chain-rule factorization, since at training time the model literally sees samples of under the true , and cross-entropy minimization is the maximum-likelihood estimator for this factorized distribution. The mismatch appears only at inference, when true is replaced by the model's own generated prefix — this is exposure bias, a known and documented gap between training and test-time behavior, not a flaw in the probabilistic derivation itself.
Worked example
Consider translating the French sentence "Le chat dort" ("The cat sleeps") into English, with a toy vocabulary and for hand-traceable numbers (real systems use in the hundreds).
Encoding pass. Source tokens: `Le`, `chat`, `dort`, ``. The encoder RNN updates its hidden state after each token:
| step | input token | hidden state (illustrative) |
|---|---|---|
| 1 | Le | |
| 2 | chat | |
| 3 | dort | |
| 4 | `` |
The context vector is now the only channel through which the decoder learns anything about the source sentence.
Decoding pass (inference, greedy). The decoder is initialized with and fed ``:
| step | decoder input | hidden state | top softmax scores | chosen token |
|---|---|---|---|---|
| 1 | `` | The: 0.71, A: 0.15, … | The | |
| 2 | The | cat: 0.62, dog: 0.20, … | cat | |
| 3 | cat | sleeps: 0.58, runs: 0.25, … | sleeps | |
| 4 | sleeps | ``: 0.83, fast: 0.09, … | `<EOS>` |
Output: "The cat sleeps." — correct, and note each decoder input is the previous output, not the gold token, since this is inference-time autoregressive generation.
Contrast with beam search (). Suppose at step 1 the model actually assigns `The`: 0.55 and `A`: 0.40 (a closer call than above). Greedy commits irreversibly to `The`. Beam search keeps both `The` and `A` alive:
| beam | after step 1 | after step 2 (best continuation) | cumulative log-prob |
|---|---|---|---|
| 1 | "The" (0.55) | "The cat" (0.55 × 0.62) | |
| 2 | "A" (0.40) | "A cat" (0.40 × 0.30) |
Beam 1 remains ahead, and in this trace beam search would ultimately converge to the same "The cat sleeps," but the point is structural: beam search only discards the losing beam ("A cat …") after seeing how both continuations play out over multiple steps, whereas greedy decoding never sees the alternative at all. On sentences where the single best next word leads down a locally-promising but globally-worse path, beam search recovers superior full sequences that greedy decoding cannot.
Common pitfalls & traps
| Pitfall | Why it happens | Fix |
|---|---|---|
| Forgetting `` handling at inference | Model loops forever or produces a fixed `max_len` of garbage | Always cap decoding at `max_len` and explicitly check for `` per beam |
| Confusing training-time and inference-time decoder inputs | Teacher forcing feeds gold tokens; forgetting this at test time (or accidentally using gold tokens at test time) inflates apparent accuracy | Clearly separate `TRAIN_STEP` (teacher forcing) from `GREEDY_DECODE`/`BEAM_SEARCH` (self-feeding) |
| Treating the context vector as unbounded capacity | Assuming a bigger hidden dimension "fixes" long-sentence degradation indefinitely | Recognize the bottleneck is fundamental to fixed-size ; use attention for long sequences |
| Beam search with too-small beam width | reduces to greedy and inherits its myopia; beams that are all near-duplicates waste width | Add length normalization and diversity penalties; tune empirically (typically 4–10) |
| Exposure bias ignored during evaluation | Model trained only ever seeing gold prefixes performs worse when its own (possibly wrong) prefixes compound errors at test time | Techniques like scheduled sampling mix in model-generated prefixes during training |
| Off-by-one in sequence indexing | Feeding instead of as decoder input, or misplacing ``/`` boundaries | Write out index conventions explicitly and unit-test on a toy sequence before scaling up |
Pioneers & history
The architecture crystallized in 2014 through near-simultaneous work by two research groups tackling the same limitation of phrase-based statistical machine translation: its inability to learn end-to-end from data without hand-built alignment and feature engineering.
Origins · 1 minIlya Sutskever and how this was discovered
Where this matters
The encoder-decoder split remains one of the most widely deployed structural ideas in applied NLP and beyond. Neural machine translation systems — from the earliest production deployment of Google Translate's neural backend in 2016 to today's multilingual translation services — are built on this template, now almost universally paired with attention. Abstractive summarization systems encode a long document and decode a shorter summary, facing an even more acute version of the bottleneck problem that motivated attention and later hierarchical and sparse-attention variants. Speech recognition pipelines use an audio encoder (often convolutional or recurrent over spectrogram frames) paired with a text decoder, an architecture sometimes called "listen, attend and spell." Image captioning models replace the sequential encoder with a convolutional network that produces a spatial feature map, still handed to an autoregressive decoder that generates a caption word by word — a design in Show-and-Tell and its successors. Even architectures that appear to have moved past the vanilla design retain its logical skeleton. The Transformer, used in machine translation systems and in encoder-decoder large language models such as T5 and BART, still separates an encoder stack (bidirectional self-attention over the full input) from a decoder stack (causal self-attention plus cross-attention into the encoder), directly inheriting the two-network, context-mediated structure described here — with the fixed-size bottleneck replaced by the attention mechanism's ability to attend over the full set of encoder states. Understanding the vanilla encoder-decoder architecture, its bottleneck, and its autoregressive decoding loop is therefore the necessary foundation before studying Attention Mechanism in NLP and its role in modern Neural Machine Translation systems.
Ask the tutor: How exactly does adding an attention mechanism change the decoder's conditioning to bypass the fixed-size context vector bottleneck?
Why can't the encoder and decoder just share one RNN?
They are almost always separate networks with independent parameters, because they perform different jobs: the encoder builds a static, order-sensitive summary of a fixed input, while the decoder is a conditional generative model producing a variable-length output one token at a time. Sharing parameters would force one set of weights to specialize in two conflicting roles — reading versus writing — and empirically hurts performance. Some architectures do tie embedding matrices (input embeddings and output softmax weights) to save parameters, but the recurrent transition functions themselves remain distinct networks, each with weights learned to solve its half of the task.
Does the bottleneck problem disappear if I just increase the hidden dimension d?
Increasing helps somewhat but does not solve the underlying problem. The context vector's capacity grows linearly with , but the amount of information needed to represent a source sentence grows with sentence length, and in the worst case with the number of distinct concepts, entities, and dependencies present. For any fixed , sufficiently long or information-dense sentences will exceed that capacity, degrading translation quality. This is why the field moved to attention mechanisms, which give the decoder access to separate encoder states rather than forcing all of 's information through one vector of fixed width.
What exactly is exposure bias, and how serious a problem is it?
Exposure bias is the mismatch between training, where the decoder always conditions on the true previous token (teacher forcing), and inference, where it conditions on its own previously generated (possibly incorrect) tokens. If an early prediction is wrong, subsequent predictions are made in an out-of-distribution regime the model never saw during training, and errors can compound. In practice, well-regularized encoder-decoder models with attention are fairly robust to this at moderate sequence lengths, but it becomes more severe for very long generation, and mitigations like scheduled sampling (randomly substituting model predictions for gold tokens during training) were developed specifically to address it.
How is this different from a standard language model?
A standard (unconditional) language model estimates using only the previously generated tokens as context. The encoder-decoder's decoder is a conditional language model: it estimates , where the conditioning variable (via context vector ) comes from an entirely separate input sequence processed by the encoder. Architecturally, the decoder's recurrence and softmax output layer look identical to a language model's; the only addition is that its initial hidden state (and, in attention-augmented versions, its per-step inputs) are influenced by the encoded source.
Why is beam search not simply set to a very large k for best results?
Larger increases computational and memory cost linearly, since hidden states and candidate sequences must be tracked and expanded at every step. More subtly, very large beam widths do not monotonically improve output quality: past a certain point, wider beams tend to favor shorter, blander, higher-probability-but-lower-quality sequences (a well-documented phenomenon in neural sequence generation), because length normalization and model miscalibration interact poorly with an overly exhaustive search. Practical systems typically use between 4 and 10, often combined with a length penalty to counteract the model's bias toward short outputs.
Can encoder and decoder use different types of networks, e.g., a CNN encoder with an RNN decoder?
Yes — the architecture is defined by the division of labor (compress, then autoregressively generate), not by any specific network type. Image captioning models pair a convolutional encoder (which produces spatial features from pixels) with a recurrent or Transformer decoder that generates text. Speech recognition systems similarly pair convolutional or recurrent audio encoders with text decoders. The Transformer replaces both recurrent components with self-attention layers while preserving exactly this encode-then-autoregressively-decode structure, which is why the "encoder-decoder" label survives even in architectures with no RNN at all.
Is the vanilla (no-attention) encoder-decoder architecture still used today?
Rarely in isolation for tasks with long or information-dense inputs, since attention so reliably improves quality at modest extra cost. However, understanding the vanilla version remains essential: it isolates the core encode/decode/autoregressive-generation logic without the added complexity of attention weights, and every modern variant — attention-based RNN seq2seq, Transformer encoder-decoders, cross-attention in multimodal models — is best understood as "the vanilla architecture, plus a fix for the bottleneck." Some very short-sequence tasks (e.g., certain classification-as-generation setups) can still get away with a single fixed-size context vector.