Encoder-Decoder Architectures
Imagine building a machine translation system. It converts "the cat sat on the mat" into French. The input and output are both sequences. But they have different lengths and word orders. There is also no fixed alignment between positions. A plain RNN emits one output per input step. This cannot handle the mismatch described above. French rarely has exactly six words matching the English original one-for-one. This mismatch between input length and output length is central. Encoder-decoder architectures solve this exact problem. The encoder-decoder framework is also called sequence-to-sequence (seq2seq) modeling. It splits the task into two cooperating networks. An encoder reads the entire input sequence. It compresses that sequence into a fixed-size summary called the context vector. A decoder then reads that context. It generates the output sequence, one token at a time. Each new token is conditioned on the context. It is also conditioned on the tokens already produced. This decoupling makes variable-length-in, variable-length-out mappings tractable. Such mappings become possible with neural networks built from LSTM and GRU cells. This idea is not a narrow trick for translation. It underlies text summarization, speech recognition, and image captioning. It also underlies dialogue systems, code generation, and time-series forecasting. It applies anywhere input and output are sequences of different, unknown lengths. Understanding the encoder-decoder pattern is a prerequisite for other topics. One is the attention mechanism, invented specifically to patch its main weakness. Another is Autoencoders, which reuse the encode-then-decode split. Autoencoders use this split for representation learning rather than sequence transduction. This article gives a precise definition of the encoder-decoder pattern. It walks through the training and inference algorithms step by step. It derives the complexity of both phases. It traces a full numeric example. Finally, it highlights the bottleneck problem that motivated everything that came after it.
- Encoder-decoder architectures map a variable-length input sequence to a variable-length output sequence via a fixed-size intermediate representation.
- The encoder is an RNN (or stack of RNNs) that compresses the whole input into a final hidden state, the context vector.
- The decoder is a separate RNN that generates output tokens one at a time, conditioned on the context and its own previous outputs.
- Training uses teacher forcing: the decoder sees the true previous token, not its own prediction, to stabilize and parallelize learning.
- Inference is autoregressive and typically uses greedy decoding or beam search since the true output is unknown.
- The single fixed-size context vector is a bottleneck for long sequences — this limitation directly motivates attention mechanisms.
Encoder-decoder models decouple "understanding a sequence" from "generating a sequence" by routing all information through one learned, fixed-size context vector.
The idea
An encoder-decoder architecture (sequence-to-sequence, seq2seq) is a composition of two neural networks trained jointly. The encoder consumes an input sequence and produces a context representation , usually the final hidden state of a recurrent network (or a function of all hidden states, in attention-augmented variants). The decoder is a separate recurrent network, initialized using , that generates an output sequence autoregressively: each output token is sampled conditioned on and all previously generated tokens. Formally, the model defines a conditional probability distribution over output sequences given input sequences:
where . Crucially, and need not be equal, and the model need not know in advance — generation stops when the decoder emits a special end-of-sequence token ``. The encoder and decoder are typically both LSTMs or GRUs (or stacks thereof), chosen because they resist vanishing gradients over the long sequences involved, but in principle any differentiable sequence model works, including the Transformer's attention-only encoder and decoder stacks that appear in later architectures. Two design choices define most of the variation among seq2seq systems: how the context is formed (a single final hidden state, a concatenation of forward/backward final states from a bidirectional encoder, or — in later architectures — a dynamically weighted combination of all encoder states), and how the decoder consumes (only at initialization, or re-injected at every decoding step). The version described here — a single fixed vector formed once and used to initialize the decoder — is the classical Sutskever–Cho formulation and is the version whose limitations set up the case for attention.
How it works
Encoding phase. The encoder RNN processes the input sequence left to right (optionally also right to left, if bidirectional), updating a hidden state at each step:
After consuming the last input token, the final hidden state (and cell state, for LSTMs) becomes the context vector . All information the decoder will ever have about the input is packed into this one fixed-size vector — this is the defining structural choice and, as later analysis shows, the defining structural weakness.
Decoding phase — training. The decoder is itself an RNN, initialized with . It is trained to predict each output token given the previous ground-truth output token, a technique called teacher forcing:
using from the training data rather than the model's own (possibly wrong) previous prediction . This decouples each decoding step from the correctness of earlier steps, letting the loss at every position be computed and backpropagated in parallel-ish fashion (still sequential within a sequence, but independent across the batch and not compounding errors sequence-internally during training).
Decoding phase — inference. At test time there is no ground truth to force, so decoding is genuinely autoregressive: the model feeds its own previous output back in. ``` function TRAIN_STEP(x_1..x_Tx, y_1..y_Ty, encoder, decoder):
# ---- Encode ---- h = zero_vector() for t in 1..Tx: h = encoder.step(x_t, h) c = h # context vector
# ---- Decode with teacher forcing ---- s = c loss = 0 y_0 = # beginning-of-sequence token for t in 1..Ty: s, logits = decoder.step(y_{t-1}, s) # y_{t-1} is GROUND TRUTH loss += cross_entropy(logits, y_t) backpropagate(loss) return loss function GENERATE(x_1..x_Tx, encoder, decoder, max_len): h = zero_vector() for t in 1..Tx: h = encoder.step(x_t, h) c = h s = c y_prev = output = [] for t in 1..max_len: s, logits = decoder.step(y_prev, s) y_t = argmax(softmax(logits)) # greedy; beam search generalizes this if y_t == : break output.append(y_t) y_prev = y_t # feed back OWN prediction return output ``` Two edge cases the pseudocode must handle correctly: (1) the decoder must be seeded with a `` (beginning-of-sequence) token before it has produced anything, since does not exist in the data; (2) generation must have a `max_len` cutoff, because a poorly trained model may never emit `` and would otherwise loop forever. Both are visible above as explicit guards, not afterthoughts.
Complexity & correctness
Time complexity. Let and be input and output lengths, the hidden dimension, and assume the RNN cell (GRU/LSTM) does work per step (matrix-vector products dominate). Encoding costs ; decoding costs ; the total forward pass is , and by symmetry of backpropagation-through-time, training has the same asymptotic cost per example. This is linear in sequence length, which is the main efficiency win over naive alternatives that would need explicit alignments (an issue attention mechanisms later reintroduce deliberately, in exchange for accuracy).
Space complexity. Storing all encoder and decoder hidden states for backpropagation-through-time costs ; the context vector itself is regardless of — this fixed size is the architectural feature (and, as discussed below, the flaw). Parameter count is for the recurrent weight matrices plus for input/output embeddings and the softmax projection, where is vocabulary size — independent of sequence length, since weights are shared across time steps.
Inference complexity. Greedy decoding is , same order as training. Beam search with beam width multiplies decoder cost by (each beam is a separate hypothesis carried forward), giving ; this is still linear in , just with a constant-factor overhead, and is the standard way to approximate the highest-probability output sequence without the intractable cost of exhaustive search.
Correctness argument. The claim to justify is not "the algorithm finds the exactly right answer" — there is no ground truth to check against structurally — but rather that the training procedure is a valid maximum-likelihood estimator for the conditional distribution , and that teacher forcing does not bias this estimator. Because the chain rule factorizes any joint distribution over a sequence exactly,
training the decoder to predict from the true prefix is training it to approximate exactly the factors of this exact factorization — no approximation is introduced by conditioning on ground truth at training time. The subtlety, and the honest caveat, is exposure bias: at test time the decoder conditions on its own generated prefix , which may lie outside the distribution of true prefixes it was trained on, so errors can compound during generation in a way the training loss does not penalize. This is a real, acknowledged mismatch between the training and inference distributions, not a proof failure — it is mitigated in practice by scheduled sampling, beam search, and (later) attention, but not eliminated by the basic architecture. The context-vector bottleneck is the other honest tradeoff: since has fixed dimension regardless of , a sufficiently long input sequence must eventually lose information to compression, no matter how large is chosen — a pigeonhole-style argument, since the number of distinguishable input sequences the encoder could ever need to represent grows with while the representational capacity of does not. Empirically, translation quality measured by BLEU degrades sharply for sentences longer than those seen in training, which is exactly the symptom this argument predicts.
Worked example
Consider translating the three-word English sentence "she likes tea" into a hypothetical three-word target "elle aime thé", with a toy hidden dimension for illustration (real systems use in the hundreds to low thousands).
Step 1 — Encode. The encoder GRU processes tokens in order, updating its hidden state:
| step | input | hidden state (illustrative values) |
|---|---|---|
| 1 | "she" | |
| 2 | "likes" | |
| 3 | "tea" |
The final state is the context vector. Note that "she" no longer exists as a separately addressable quantity after step 3 — its influence is smeared into alongside "likes" and "tea".
Step 2 — Decode with teacher forcing (training). The decoder is seeded with `` and :
| step | decoder input (ground truth) | new state | predicted logits → softmax | true | loss contribution |
|---|---|---|---|---|---|
| 1 | `` | peak on "elle" (p=0.71) | "elle" | ||
| 2 | "elle" | peak on "aime" (p=0.64) | "aime" | ||
| 3 | "aime" | peak on "thé" (p=0.58) | "thé" | ||
| 4 | "thé" | peak on `` (p=0.80) | `` |
Total sequence loss , backpropagated through both decoder and encoder (gradients flow from decoder loss all the way back through into and the encoder weights — this is exactly why the two networks are trained jointly, not independently).
Step 3 — Decode at inference (no ground truth available). Suppose at test time the decoder's own step-1 prediction is wrong — it emits "il" instead of "elle" (a plausible confusion, both mean "he/she" contextually). Under greedy autoregressive decoding, "il" (not "elle") is fed back as for computing . If the decoder was never trained on prefixes containing an erroneous "il", may drift into a region of state space the model handles poorly, potentially causing step 2 to also err — this is the exposure-bias phenomenon made concrete: one early mistake propagates because generation, unlike training, has no ground truth to fall back on.
Common pitfalls & traps
| pitfall | why it happens | fix |
|---|---|---|
| Forgetting ``/`` tokens | Decoder has no defined first input or stopping signal | Explicitly add sentinel tokens to vocabulary and training data |
| No `max_len` cap at inference | Model may never emit `` if poorly trained or on out-of-distribution input | Hard cutoff on generation length, as in the pseudocode above |
| Using teacher forcing at inference too | Mixing training-time convenience into deployment silently "cheats" using future ground truth | Autoregressive feedback of `argmax` output only at inference |
| Assuming context vector scales to long inputs | Fixed-size has bounded capacity regardless of | Use attention, or at minimum a bidirectional encoder and larger as a partial mitigation |
| Reversing input order and forgetting why | Sutskever et al. found reversing source sentences helps optimization by shortening the average source–target dependency length | Understand it as an optimization trick specific to plain seq2seq, not a universal requirement |
| Ignoring exposure bias | Cross-entropy loss never sees the model's own generation errors during training | Scheduled sampling, or move to attention/Transformer decoders trained with similar but improved regimes |
Pioneers & history
The encoder-decoder pattern for neural sequence transduction crystallized in 2014, when two groups independently proposed essentially the same architecture for machine translation: Cho, Bahdanau, and colleagues at Montreal introduced the RNN encoder-decoder framework alongside the GRU cell, while Sutskever, Vinyals, and Le at Google demonstrated it at scale with stacked LSTMs, showing for the first time that a purely neural system could rival phrase-based statistical machine translation. Both papers observed the same bottleneck — quality collapsing on long sentences — which within a year led Bahdanau, Cho, and Bengio to introduce attention, letting the decoder consult all encoder states rather than a single compressed vector.
Origins · 1 minIlya Sutskever and how this was discovered
Where this matters
Encoder-decoder architectures underpin production machine translation systems (early Google Translate's neural pivot, and the conceptual ancestor of today's Transformer-based translation services), automatic speech recognition pipelines that map audio frames to transcribed text, abstractive text summarization systems that compress documents into shorter summaries, image-captioning systems that pair a convolutional encoder with a recurrent (or Transformer) decoder, and sequence-based time-series forecasting where a variable-length history must produce a variable-length forecast. The pattern also generalizes structurally beyond sequences: any system that "reads everything, then generates" — including retrieval-augmented generation pipelines and code-generation assistants — inherits this two-stage read-then-write design, even where the internals have moved from RNN cells to attention-based Transformer blocks. Recognizing the encoder-decoder skeleton underneath a modern system, even a heavily modified one, is often the fastest way to reason about where its information bottlenecks and failure modes will show up.
Ask the tutor: How does adding attention mathematically change the decoder's conditioning from a single context vector to a weighted sum over all encoder states?
Why can't a standard RNN alone solve sequence-to-sequence tasks?
A standard RNN naturally produces one output per input time step, so its output length is tied to its input length. Translation, summarization, and similar tasks need output lengths that differ from — and are not known in advance relative to — input length. The encoder-decoder split fixes this by having the encoder consume the entire input before any output is produced, and having the decoder generate outputs autoregressively until it chooses to stop (by emitting ``), completely decoupling the two lengths. This is the essential structural innovation, independent of which specific recurrent cell (GRU, LSTM) is used inside each half.
What exactly is teacher forcing, and does it introduce bias into training?
Teacher forcing means feeding the decoder the ground-truth previous output token, rather than its own prediction, when computing the next output during training. It does not bias the maximum-likelihood objective, because the chain-rule factorization of the true conditional distribution is defined in terms of true prefixes, and training on true prefixes estimates exactly those factors correctly. The real cost is a train/test mismatch: at inference the decoder conditions on its own, possibly imperfect, generated prefix — a distribution the loss function never explicitly penalized errors within, known as exposure bias.
Why does the context vector become a bottleneck, and how does attention fix it?
The context vector has a fixed dimensionality chosen at model design time, but the amount of information in the input grows with sequence length . Beyond some length, the encoder simply cannot fit all relevant details into without lossy compression — a pigeonhole-style capacity limit, not a training failure. Attention mechanisms address this by letting the decoder look back at all encoder hidden states at every decoding step, computing a weighted combination whose weights depend on the current decoding context, effectively giving the model a dynamically-sized "working memory" instead of one static vector.
What role does the choice of RNN cell — LSTM vs GRU — play in encoder-decoder models?
Both LSTM and GRU cells were designed to combat vanishing gradients over long sequences, a prerequisite for the encoder to retain useful information across many time steps before producing . LSTMs use separate cell and hidden states with three gates; GRUs merge these into one state with two gates, giving fewer parameters and often comparable performance. The encoder-decoder pattern itself is agnostic to this choice — either cell type (or later, attention-only blocks) can fill the encoder and decoder roles, since the pattern is defined by the encode-then-decode information flow, not by the specific recurrent unit.
Why is greedy decoding often insufficient, and what does beam search do differently?
Greedy decoding picks the single highest-probability token at each step, but the locally-best token at step may lead to a globally worse full sequence than a slightly-lower-probability token would have. This happens because greedy search never reconsiders earlier choices once made. Beam search instead keeps the top- partial sequences ("beams") at every step, expanding each and pruning back down to , approximating a search over the exponentially large space of full sequences at a cost of only a constant factor over greedy decoding, at the price of never guaranteeing the true global optimum either.
How does an encoder-decoder architecture relate to an autoencoder?
Both split a model into an encoder that produces a compressed representation and a decoder that reconstructs or generates from it, but their goals differ. Autoencoders typically try to reconstruct the same input from a compressed code, usually for representation learning, denoising, or dimensionality reduction, and input/output lengths and domains match. Sequence-to-sequence encoder-decoders instead map an input sequence to a different output sequence, often in a different domain (English to French, audio to text) and different length, for a transduction task rather than reconstruction. The shared "encode-then-decode" skeleton is the same; the training objective and use case differ substantially.
Does the encoder-decoder pattern still matter now that Transformers dominate?
Yes — the Transformer, introduced in 2017, keeps the encoder-decoder split at the architectural level while replacing recurrence with self-attention and cross-attention inside each half. Many production systems (translation, summarization) are still conceptually "encode the input fully, then autoregressively decode the output," just with attention-based encoders and decoders instead of RNN cells. Understanding the RNN-based encoder-decoder first makes clear exactly what problem attention and Transformers were built to solve — the fixed-context bottleneck and long-range dependency issues — rather than treating those innovations as arbitrary architectural choices.