3.5.8 · D2Sequence Models

Visual walkthrough — Encoder-decoder architecture

2,717 words12 min readBack to topic

Step 1 — What a "sequence" even is, and why one vector can't hold it yet

WHAT. A sequence is just an ordered list of things read left to right. Our input is Let me name every piece:

  • ::: the item at position — for us, one word turned into numbers.
  • ::: the position counter, ticking
  • ::: the total number of input items (the length of the input). The little "" reminds us it is the input length.

WHY we care. The order matters. "Dog bites man" and "man bites dog" use identical words but mean opposite things. A machine that ignores order would confuse them. So we need something that reads the words in sequence and remembers what came before.

PICTURE. Look at the row of boxes: each box is one word . The red arrow shows the single direction we read — earlier words influence later understanding, never the reverse (for now).

Figure — Encoder-decoder architecture

Step 2 — The memory cell: how the encoder "reads and remembers"

WHAT. We introduce a running memory that updates once per word. Call it — the encoder's hidden state after reading word :

Term by term:

  • ::: the memory after seeing word (a list of numbers).
  • ::: the memory before word — everything understood up to now.
  • ::: the fresh word being added.
  • ::: the update rule (an LSTM or GRU cell). It blends old memory with the new word.

WHY this recursion and not a plain sum? A sum would forget order — . Feeding the previous memory back in makes each state depend on the path taken to reach it. That is exactly what an RNN gives us: order-sensitive memory. We choose recursion because the question "what did the whole prefix mean?" can only be answered by folding words in one at a time.

PICTURE. The red arrow is the feedback loop: yesterday's memory flows into today's cell. Every box hands its state rightward, so the last box has (in principle) touched every word.

Figure — Encoder-decoder architecture

Step 3 — Squeezing everything into one context vector

WHAT. After the last word , we freeze the final memory and call it the context vector:

  • ::: one fixed-size list of numbers meant to summarise the entire input.
  • ::: the memory after the last word — the end of the chain from Step 2.

WHY the last state? Because of the recursion, was built from , which was built from , and so on back to . So the last state is the only single point that "has heard" the whole sentence.

PICTURE. All arrows funnel into one red dot. That dot is — the bottleneck through which all meaning must pass.

Figure — Encoder-decoder architecture

Step 4 — The decoder starts: handing over the baton

WHAT. The decoder is a second memory chain. It begins its life as the context:

  • ::: the decoder's starting memory — copied from .
  • ::: a fake "word zero," the signal telling the decoder "begin producing now."

WHY start from ? The decoder has no other window into the input. Its only knowledge of "I love AI" is the summary handed over. Initialising its memory to literally injects that knowledge into the generation process.

PICTURE. The red dot from Step 3 flows across the divide and becomes the first block of the output chain. The baton is passed.

Figure — Encoder-decoder architecture

Step 5 — Generating one word at a time (autoregression)

WHAT. The decoder updates its memory using the word it just spoke. But careful: is a discrete word (like "J'aime") — and a cell only eats numbers. So, exactly as we did for the input in Step 1, we first turn that word into an embedding vector before feeding it in:

  • ::: the previously generated output word (a discrete token).
  • ::: that word mapped into a continuous vector — the decoder's analogue of from Step 1.
  • ::: the decoder's memory before this step.
  • ::: the decoder's update rule (another LSTM/GRU cell).

WHY embed it first? A word like "J'aime" is just an index into a dictionary; the cell cannot do arithmetic on an index. The embedding lookup gives it coordinates in meaning space — the same trick that let the encoder read words. Same problem, same fix, both ends of the machine.

WHY feed the previous word back at all? To stay coherent. If it just said "J'aime", the next word should follow that, not float free. This "use my own last output as next input" loop is called autoregression.

PICTURE. Each output box loops its word up and into the next box (red loop) — mirror image of the encoder, but now the arrows produce words instead of consuming them.

Figure — Encoder-decoder architecture

Step 6 — From memory to an actual word: the softmax

WHAT. A hidden state is numbers, not a word. We turn it into a probability for every word in the vocabulary : Term by term:

  • ::: a weight matrix and bias that map the memory to one raw score per word.
  • ::: the vector of raw scores ("logits"), one entry per candidate word .
  • ::: the raw score of word ; bigger = more favoured.
  • ::: exponential — makes every score positive and blows up gaps so the winner stands out.
  • the denominator ::: adds up all the exponentials so the result divides to .
  • ::: shorthand for "all words spoken before position ."

WHY exponentiate and divide? We need genuine probabilities: all non-negative, summing to , so the model can pick a word. Exponentials guarantee positivity; dividing by their total guarantees they sum to one. That is exactly what softmax does — it is the tool that answers "given these scores, how likely is each word?" One of the words competing for probability here is from Step 5 — that is how "stop now" competes fairly against every real word.

PICTURE. Tall red bar = the chosen word ("am"); the transform squashes a spiky score vector into a clean probability bar chart that sums to 1.

Figure — Encoder-decoder architecture

Step 7 — Why the training loss looks the way it does

WHAT. We want the model to make the true sentence likely. Its probability factorises by the chain rule of probability:

  • ::: multiply the per-word probabilities together (they chain: each word's chance depends on the ones before).
  • ::: the correct (ground-truth) word at position ; the star means "the target."
  • ::: length of the output sequence.

Multiplying many small numbers underflows to zero on a computer, so we take a logarithm — which turns products into sums and is easier and stabler: Maximising probability = minimising its negative, averaged over examples:

  • ::: every weight in encoder and decoder — what training adjusts.
  • the minus sign ::: converts "maximise likelihood" into "minimise loss."

WHY the log, concretely? Multiplying 30 times gives — the computer rounds it to and learning dies. Adding -values () never underflows. The gradients that update flow backward through time via BPTT.

PICTURE. Two arithmetic ladders side by side: the product ladder plunges toward ; the log-sum ladder walks steadily downhill — same information, safe numbers. The red line is the safe one.

Figure — Encoder-decoder architecture

Step 8 — The degenerate case: when one vector is too small

WHAT. Everything above squeezes an arbitrarily long input through the single fixed vector . What happens as grows?

WHY it must break. The key is not a precise bit-count (the slots of are real numbers, whose usable information is limited by noise and training, not by their 32-bit storage — so raw bit arithmetic would mislead us). The honest argument is about capacity that does not grow:

  • ::: the number of slots in the context vector — a constant chosen once (say 512).
  • ::: the input length — free to grow to 20, 50, 200 words.

Because has a fixed number of slots but the input it must summarise keeps growing, at some length the vector simply runs out of room. Details — especially early words, which have passed through the most update steps — get overwritten. This is the information bottleneck. Empirically, plain seq2seq accuracy falls off sharply once sentences pass roughly 20 words, exactly where a single vector starts to saturate.

PICTURE. A wide funnel (the long input) forced through a narrow red neck (the fixed-size ) — geometry that makes the loss inevitable. Short inputs pass; long ones spill over the sides.

Figure — Encoder-decoder architecture

The one-picture summary

Figure — Encoder-decoder architecture

Left half reads words into a chain of memories that funnel into the red context dot ; right half unfurls that dot back into words, each fed forward (after being re-embedded), each turned into a word by softmax, until is chosen. One drawing, the whole derivation.

Recall Feynman retelling — say it back in plain words

First I take a sentence and read it one word at a time, keeping a little scratchpad of "what I understand so far." Each new word updates the scratchpad. When I reach the end, I freeze the scratchpad into one fixed-size summary — the context vector . Then I start a second scratchpad set to that summary and begin speaking. Each word I say, I turn back into numbers (an embedding lookup) and feed to myself so my next word stays coherent. To choose a word I score every word in my vocabulary, exponentiate the scores so the best ones dominate, and normalise so they're real probabilities (softmax) — then pick. I keep going until I pick the special token, which means "the sentence is finished," or until I hit the length cap . To learn, I make the true sentence probable. Since a sentence's probability is a product of per-word probabilities, and products of tiny numbers vanish, I take logs and add instead — maximising that sum, which equals minimising the negative-log-likelihood loss. During training I feed myself the correct previous word (teacher forcing) so I learn fast. The catch: cramming an ever-longer sentence through one fixed-size vector must eventually lose information, because the vector's capacity never grows while the input does. That bottleneck is exactly why attention was born.

Recall Quick self-test

Why can't the encoder use a plain sum of word vectors? ::: A sum ignores order (); the recurrence makes memory depend on the path/order. What single quantity bridges variable-length input and output? ::: The fixed-size context vector . Before feeding back into the decoder, what must you do? ::: Map the discrete word into a continuous vector via an embedding lookup, — just like in the encoder. How does generation know when to stop? ::: When the chosen token is the special symbol, or when the length cap is reached. Why take the log of the likelihood? ::: Products of many small probabilities underflow to 0; logs turn products into stable sums. Why does softmax exponentiate? ::: To make scores positive and amplify the winner, then divide so they sum to 1 — a valid probability distribution. What breaks for long inputs and what fixes it? ::: The context vector's capacity is fixed while input length grows, so it saturates (information bottleneck); letting the decoder read all encoder hidden states (the attention mechanism) fixes it.