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.

Key takeaways
  • 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.
The core insight

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 fencf_{\text{enc}} consumes an input sequence x1,…,xTxx_1, \dots, x_{T_x} and produces a context representation cc, usually the final hidden state of a recurrent network (or a function of all hidden states, in attention-augmented variants). The decoder fdecf_{\text{dec}} is a separate recurrent network, initialized using cc, that generates an output sequence y1,…,yTyy_1, \dots, y_{T_y} autoregressively: each output token is sampled conditioned on cc and all previously generated tokens. Formally, the model defines a conditional probability distribution over output sequences given input sequences:

p(y1,…,yTy∣x1,…,xTx)=∏t=1Typ(yt∣y1,…,yt−1,c)p(y_1, \dots, y_{T_y} \mid x_1, \dots, x_{T_x}) = \prod_{t=1}^{T_y} p(y_t \mid y_1, \dots, y_{t-1}, c)

where c=fenc(x1,…,xTx)c = f_{\text{enc}}(x_1, \dots, x_{T_x}). Crucially, TxT_x and TyT_y need not be equal, and the model need not know TyT_y 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 cc 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 cc (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:

ht=RNNCell(xt,ht−1),h0=0⃗h_t = \text{RNNCell}(x_t, h_{t-1}), \qquad h_0 = \vec{0}

After consuming the last input token, the final hidden state hTxh_{T_x} (and cell state, for LSTMs) becomes the context vector cc. 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 h0dec=ch_0^{\text{dec}} = c. It is trained to predict each output token given the previous ground-truth output token, a technique called teacher forcing:

st=RNNCell(yt−1,st−1),y^t=softmax(Wst+b)s_t = \text{RNNCell}(y_{t-1}, s_{t-1}), \qquad \hat{y}_t = \text{softmax}(W s_t + b)

using yt−1y_{t-1} from the training data rather than the model's own (possibly wrong) previous prediction y^t−1\hat{y}_{t-1}. 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 y0y_0 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.

Figure
The encoder-decoder pipeline: input sequence compressed into one context vector, then expanded into an output sequence
Encoder–Decoder Architecture h₁ h₂ h₃ c x₁ "the" x₂ "cat" x₃ "sat" ENCODER context s₁ s₂ s₃ s₄ ŷ₁ "le" ŷ₂ "chat" ŷ₃ "s'est" ŷ₄ "assis" DECODER (autoregressive) All input information must pass through the single bottleneck vector c bottleneck: fixed size regardless of Tx

Complexity & correctness

Time complexity. Let TxT_x and TyT_y be input and output lengths, dd the hidden dimension, and assume the RNN cell (GRU/LSTM) does O(d2)O(d^2) work per step (matrix-vector products dominate). Encoding costs O(Txd2)O(T_x d^2); decoding costs O(Tyd2)O(T_y d^2); the total forward pass is O((Tx+Ty)d2)O((T_x + T_y) d^2), 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 O(Tx⋅Ty)O(T_x \cdot T_y) 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 O((Tx+Ty)d)O((T_x + T_y) d); the context vector itself is O(d)O(d) regardless of TxT_x — this fixed size is the architectural feature (and, as discussed below, the flaw). Parameter count is O(d2)O(d^2) for the recurrent weight matrices plus O(d⋅∣V∣)O(d \cdot |V|) for input/output embeddings and the softmax projection, where ∣V∣|V| is vocabulary size — independent of sequence length, since weights are shared across time steps.

Inference complexity. Greedy decoding is O(Tyd2)O(T_y d^2), same order as training. Beam search with beam width kk multiplies decoder cost by kk (each beam is a separate hypothesis carried forward), giving O(k⋅Ty⋅d2)O(k \cdot T_y \cdot d^2); this is still linear in TyT_y, just with a constant-factor overhead, and is the standard way to approximate the highest-probability output sequence without the intractable O(∣V∣Ty)O(|V|^{T_y}) 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 p(y∣x)p(y \mid x), and that teacher forcing does not bias this estimator. Because the chain rule factorizes any joint distribution over a sequence exactly,

p(y1,…,yTy∣x)=∏t=1Typ(yt∣y<t,x),p(y_1, \dots, y_{T_y} \mid x) = \prod_{t=1}^{T_y} p(y_t \mid y_{<t}, x),

training the decoder to predict yty_t from the true prefix y<ty_{<t} 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 y^<t\hat{y}_{<t}, 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 c∈Rdc \in \mathbb{R}^d has fixed dimension regardless of TxT_x, a sufficiently long input sequence must eventually lose information to compression, no matter how large dd is chosen — a pigeonhole-style argument, since the number of distinguishable input sequences the encoder could ever need to represent grows with TxT_x while the representational capacity of cc 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 d=2d=2 for illustration (real systems use dd in the hundreds to low thousands).

Step 1 — Encode. The encoder GRU processes tokens in order, updating its hidden state:

stepinput xtx_thidden state hth_t (illustrative values)
1"she"h1=(0.10,−0.05)h_1 = (0.10, -0.05)
2"likes"h2=(0.42,0.18)h_2 = (0.42, 0.18)
3"tea"h3=(0.55,0.30)h_3 = (0.55, 0.30)

The final state c=h3=(0.55,0.30)c = h_3 = (0.55, 0.30) is the context vector. Note that "she" no longer exists as a separately addressable quantity after step 3 — its influence is smeared into cc alongside "likes" and "tea".

Step 2 — Decode with teacher forcing (training). The decoder is seeded with `` and s0=c=(0.55,0.30)s_0 = c = (0.55, 0.30):

stepdecoder input yt−1y_{t-1} (ground truth)new state sts_tpredicted logits → softmaxtrue yty_tloss contribution
1``s1=(0.51,0.22)s_1=(0.51,0.22)peak on "elle" (p=0.71)"elle"−ln⁡0.71≈0.34-\ln 0.71 \approx 0.34
2"elle"s2=(0.60,0.10)s_2=(0.60,0.10)peak on "aime" (p=0.64)"aime"−ln⁡0.64≈0.45-\ln 0.64 \approx 0.45
3"aime"s3=(0.58,−0.02)s_3=(0.58,-0.02)peak on "thé" (p=0.58)"thé"−ln⁡0.58≈0.54-\ln 0.58 \approx 0.54
4"thé"s4=(0.40,−0.10)s_4=(0.40,-0.10)peak on `` (p=0.80)``−ln⁡0.80≈0.22-\ln 0.80 \approx 0.22

Total sequence loss ≈1.55\approx 1.55, backpropagated through both decoder and encoder (gradients flow from decoder loss all the way back through cc into h1,h2,h3h_1, h_2, h_3 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 y1y_1 for computing s2s_2. If the decoder was never trained on prefixes containing an erroneous "il", s2s_2 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

pitfallwhy it happensfix
Forgetting ``/`` tokensDecoder has no defined first input or stopping signalExplicitly add sentinel tokens to vocabulary and training data
No `max_len` cap at inferenceModel may never emit `` if poorly trained or on out-of-distribution inputHard cutoff on generation length, as in the pseudocode above
Using teacher forcing at inference tooMixing training-time convenience into deployment silently "cheats" using future ground truthAutoregressive feedback of `argmax` output only at inference
Assuming context vector scales to long inputsFixed-size cc has bounded capacity regardless of TxT_xUse attention, or at minimum a bidirectional encoder and larger dd as a partial mitigation
Reversing input order and forgetting whySutskever et al. found reversing source sentences helps optimization by shortening the average source–target dependency lengthUnderstand it as an optimization trick specific to plain seq2seq, not a universal requirement
Ignoring exposure biasCross-entropy loss never sees the model's own generation errors during trainingScheduled 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
IS
Ilya Sutskever
born 1986 · Co-author of the 2014 "Sequence to Sequence Learning with Neural Networks" paper that demonstrated LSTM-based encoder-decoder translation at scale, later a founding figure at OpenAI

History
2014
— Cho, Bahdanau, Bengio, and Manning-adjacent groups publish the RNN encoder-decoder with the GRU cell.
2014
— Sutskever, Vinyals, and Le publish "Sequence to Sequence Learning with Neural Networks" using stacked LSTMs.
2014
— Reversing source-sentence order is shown empirically to ease optimization in the Sutskever et al. system.
2015
— Bahdanau, Cho, and Bengio introduce the attention mechanism to remove the fixed context-vector bottleneck.
2017
— The Transformer replaces recurrence entirely, but retains the encoder-decoder split at the architectural level.

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 p(y∣x)=∏tp(yt∣y<t,x)p(y\mid x) = \prod_t p(y_t \mid y_{<t}, x) 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 dd chosen at model design time, but the amount of information in the input grows with sequence length TxT_x. Beyond some length, the encoder simply cannot fit all relevant details into cc 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 cc. 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 tt 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-kk partial sequences ("beams") at every step, expanding each and pruning back down to kk, approximating a search over the exponentially large space of full sequences at a cost of only a constant factor kk 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.

Before this

Where this leads