Skip to content

Architectures Before Transformers

Encoder-decoder and the fixed-vector bottleneck

The problem attention was invented to solve

The whole point of attention, seen through the problem it was built to kill: every sentence - five words or fifty - forced through one fixed-length vector.

In 2014 the first neural machine translators worked in two moves. An encoder RNN read the source sentence one word at a time and boiled it down to a single fixed-length vector - its final hidden state. A decoder RNN then wrote the translation one word at a time, with nothing to go on but that one vector. It was elegant, it beat the phrase-based systems of its day - and it had a fatal flaw. Every sentence, however long, had to squeeze through the same fixed vector. That funnel is the bottleneck this lesson is about, and removing it is exactly what attention (Lesson 31) was invented to do.

The one-line idea

Imagine summarising a whole document on a single index card. Fine for a haiku; hopeless for a novel. A vanilla seq2seq model hands the decoder one index card - one fixed-size vector - no matter how long the input. The longer the sentence, the more meaning gets crushed onto the same small card, and the more the decoder has to guess.

The encoder-decoder pipeline

Two networks, one handoff. The encoder steps through the source tokens , updating a hidden state each step, . When it reaches the end it stops and keeps only the last state. That final vector - often called the context vector or thought vector - is the entire handoff:

The decoder is a second RNN that starts from and emits target words one at a time, each conditioned on and everything written so far, . It factorises the probability of the whole output sentence as a product of per-word predictions:

Notice that is the only thing carrying the source into every term of that product. During training we use teacher forcing: instead of feeding the decoder its own (possibly wrong) previous guess, we feed the true previous target word . That keeps early mistakes from snowballing while the model is still learning - at inference time it has to fall back on its own outputs.

# ENCODER: read the whole source, keep only the final hidden state.
h = zeros(d)                       # the "thought vector" - a FIXED size d
for x in source_tokens:            # x_1 ... x_n, any length
    h = rnn_step(h, embed(x))      # everything must fit inside this one h
context = h                        # <-- the entire sentence, squeezed into d numbers

# DECODER: write the target, conditioned ONLY on that one vector.
s = context                        # start from the squeezed summary
y_prev = "<START>"
for t in range(target_len):
    s = rnn_step(s, embed(y_prev))
    logits = W @ s                 # a distribution over the vocabulary
    guess  = argmax(logits)
    y_prev = target[t] if training else guess   # teacher forcing feeds the TRUE word
Seq2seq in pseudocode - one vector does all the carrying

The fixed-vector bottleneck

Here is the crack. The context vector has a fixed size chosen once, at build time. A five-word sentence and a fifty-word sentence both get exactly numbers. But the amount of meaning to carry grows with length, so a long sentence has to overwrite detail to fit - and because the encoder reads left to right, it is the start of the sentence that fades first. Sutskever, Vinyals & Le measured exactly this: translation quality (BLEU) held up on short inputs and slid on long ones. Their now-famous hack - reverse the source words before encoding - shortened the path from the first source words to and bought several points of BLEU. A hack that helps is a bottleneck confirmed.

Drag the slider below to grow the sentence. The fixed vector in the middle never changes size - watch more and more words get forced through its same handful of slots while the reconstruction fidelity meter falls.

Bottleneck squeeze drag n · watch it overload
source word (colored by position)fixed context vector - d slotsoutput: brighter = better recovered
reconstruction fidelity ≈ 100%

6 words squeezed into a fixed 7-slot vector, then re-expanded to 6 outputs. Short enough to fit the 7 slots - the decoder can rebuild it faithfully.

Why a fixed vector must lose information

The context vector lives in - a constant budget of numbers, and so a constant budget of storable detail. A source sentence of words carries information that grows with . Once you pass the vector's comfortable capacity, each word's share of the budget falls off like , so overall fidelity behaves like : flat and near-perfect while the sentence fits, then decaying as it grows. Past that knee the lost detail is simply gone - no decoder, however good, can recover what the encoder never stored.

The aha: delete the funnel

Attention's fix is almost embarrassingly direct: stop forcing everything through one vector. Keep all encoder states , and let the decoder, at each output step, look back and take a weighted blend of whichever ones it actually needs. There is no bottleneck because there is no single summary - the decoder reads the source directly. That one change (Lesson 31) is what turned seq2seq into the Transformer.

Check yourself

Without attention, a vanilla seq2seq decoder must produce the whole translation from:

Why does a vanilla seq2seq model degrade as the source sentence gets longer?

Recall: what is the single "context vector" in a vanilla seq2seq model, and why does it become a bottleneck on long inputs?

Try to state it, then check.

Lock it in

  • A vanilla seq2seq model encodes the whole source into one fixed-length context vector (the encoder's final hidden state), and the decoder writes every output word from that single vector alone.
  • The bottleneck: has a fixed size chosen at build time, so a long sentence overflows it and detail is lost - especially the start, which fades first - and no decoder can recover what was never stored.
  • Evidence it is real: reversing the source words shortens the path from the first words to and bought several BLEU points. A hack that helps is a bottleneck confirmed.
  • Teacher forcing feeds the true previous target word during training so early mistakes do not snowball; at inference the model falls back on its own outputs.
  • Attention deletes the funnel: keep all encoder states and let the decoder look back at whichever it needs - no single summary, which turned seq2seq into the Transformer.

Primary source

For the picture - the encoder squeezing a sentence into one vector and the decoder unrolling it - see Jay Alammar's The Illustrated Transformer and its seq2seq preamble. For the original result, including the surprising trick of reversing the source words to shorten the path from the first words to the vector, read Sutskever, Vinyals & Le, Sequence to Sequence Learning with Neural Networks (2014).

Ask your teacher

This lesson is the problem statement; Lesson 31 is the solution. Everything you just felt in the squeeze widget - meaning crushed through one fixed vector, the start of long sentences fading - is exactly what attention was designed to fix: instead of cramming a whole sentence into one vector, let the decoder look back at every input position directly. That one fix became the Transformer. Ask me why reversing the input helped, why LSTMs were needed to carry the vector this far without forgetting, or how attention turns this bottleneck into an grid of soft lookups.