3.5.6 · D2Sequence Models

Visual walkthrough — Bidirectional RNNs

2,462 words11 min readBack to topic

Step 1 — One word at a time: what "reading left to right" means

WHAT. Imagine a sentence laid out as beads on a string: . Each is one word turned into a little list of numbers (an embedding) — think of it as the word's "fingerprint." The subscript is just the position: is the first word, is the last ( = total number of words).

WHY. Before any mathematics, we must agree on what we are sliding our finger over. Everything later is "what does my finger know so far?" — so we first draw the finger.

PICTURE. The blue arrow is the finger. It sits on word . Everything to its left (lavender) it has already read; everything to its right (grey) it has not seen yet.

Figure — Bidirectional RNNs

Step 2 — Memory: the hidden state

WHAT. We want a running summary of everything the finger has read so far. Call it — the little right-pointing arrow on top means "this summary was built reading left→right." It is itself a short list of numbers; say it has dimension (we get to choose — a bigger means a roomier memory).

WHY tanh, and why this exact recipe? We need to fold the new word into the old summary. The natural recipe is:

Term by term, right where each lives:

  • = the summary one word ago (memory of the past); a list of numbers.
  • = a matrix (a grid of learned numbers) that reshapes that old memory — "how much of yesterday do I carry forward?" It must turn a -list into a -list, so its shape is .
  • = the new word's fingerprint; a list of numbers.
  • = a matrix that reshapes the new word — "how does this word change my summary?" It turns a -list into a -list, so its shape is .
  • = a constant bias vector of length , a small default push.
  • = the squash. It takes any number and gently bends it into the range .

Why and not just addition? Without a squash, adding word after word could let the numbers grow without bound (explode) or the model could only ever draw straight-line relationships. answers the question "how do I keep values bounded AND let the model bend, not just add?" Its S-shape saturates: huge inputs flatten out near .

PICTURE. Left: the S-curve of — see how big positive inputs flatten toward , big negatives toward . Right: the "fold" — old memory (lavender) and new word (coral) pour into the box, tanh squashes, out comes the new memory.

Figure — Bidirectional RNNs

Step 3 — The forward pass grows a summary, word by word

WHAT. Start the finger before the first word with an empty memory (all zeros — "I know nothing yet"). Then apply Step 2's recipe once per word.

WHY start at zero? At there is no previous word, so must be a neutral placeholder. Zero means "no prior belief."

Watch what each summary contains:

  • = knows only.
  • = knows (because it was built from ).
  • = knows the whole past .

PICTURE. A chain: each box passes its memory (lavender arrow) rightward while a new word (coral) drops in from below. The shaded region under each box shows how much of the sentence that summary has absorbed — it grows left to right.

Figure — Bidirectional RNNs
Recall

Why does "know" ? ::: Because it is computed from , which was computed from . Memory chains backward through the arrows.


Step 4 — The blind spot: the forward finger cannot see the future

WHAT. Consider tagging the first word of "Apple released iOS." At the forward summary has read only the word "Apple." Is it a fruit or a company? The word alone cannot say.

WHY this is the whole motivation. The forward RNN is causally blind: at position it has zero information about . For tasks where the answer depends on later words (as in Named Entity Recognition), this is fatal.

PICTURE. The forward finger on "Apple" — the words after it are behind a fog. The label bubble wavers between FRUIT and ORG.

Figure — Bidirectional RNNs

Step 5 — The backward pass: a second finger reading right to left

WHAT. A mirror RNN, with its own separate weights, starts at the last word and marches left. Its summaries wear a left-pointing arrow: , also of length .

The only change from Step 2 is the index: became . The "previous" summary is now the one to the right, because this finger walks the other way. The shapes match Step 2 exactly: is and is .

WHY separate weights ? Reading a language backward is a different skill from reading it forward. Forcing both fingers to share one set of weights would make each learn a blurry compromise. Independent parameters let each specialise.

Where does it start? — an empty memory just past the end of the sentence, the mirror of .

Now the summaries absorb the future:

  • = knows only.
  • = knows .
  • = knows the whole sentence from the right.

PICTURE. The lower chain (coral finger) walks right→left; its shaded region grows from the right edge inward — the mirror image of Step 3.

Figure — Bidirectional RNNs

Step 6 — The handshake: concatenation gives

WHAT. At every position we now have two summaries: (past) and (future). Glue them end to end:

The semicolon means concatenation — simply lay the second list right after the first. If each arrow-summary is a list of numbers, then is a list of numbers — the past block, then the future block.

WHY concatenate rather than add? Adding, , blends past and future into one soup — a big past value can cancel a big future value and you lose which was which. Concatenation keeps both blocks intact, so the next layer can decide, per feature, how much to trust past vs. future. It answers "how do I combine two summaries without losing either?"

PICTURE. At position 1 ("Apple"), the lavender past-block (, weak: "just saw Apple") and the mint future-block (, strong: "…released iOS in California") snap together into one long bar .

Figure — Bidirectional RNNs

Step 7 — Decide: softmax turns into a labelled guess

WHAT. Push through one more matrix and a softmax to get a probability for each possible label:

  • = a raw score for each class. If there are classes, has shape (it swallows the length- vector and produces one score per class), and has length .
  • = turns those raw scores into positive numbers that add up to 1 — a probability distribution.

WHY softmax? We are choosing one label out of several. We need the outputs to be non-negative and to sum to 1 so they read as probabilities. Softmax answers exactly "how do I turn arbitrary scores into a legal probability distribution?" by exponentiating (making everything positive) and dividing by the total (making it sum to 1).

PICTURE. For "Apple": raw scores (grey bars) → softmax → probabilities (coloured bars). B-ORG towers at ; the model commits.

Figure — Bidirectional RNNs

Step 8 — The edge and degenerate cases

Every reader must know what happens at the boundaries. The figure below has four mini-panels, top-left to bottom-right, matching Cases A, B, C, D in order.

Case A — the very first / very last word (top-left panel). At : uses , so it sees only . At : uses , so it sees only . But the combined and are still full-context, because the other direction supplies the rest — the top-left panel shows the mint future-arrow filling in behind the lone word . No position is ever context-starved — that is the payoff.

Case B — a one-word sentence, (top-right panel). Both fingers see the same single word. and are computed from alone (with different weights), then concatenated. The architecture still works; there is simply no future or past to add — the top-right panel shows the single shared word.

Case C — streaming / real-time input (bottom-left panel). The backward finger needs the last word to start. If words arrive one at a time (live speech, live typing), cannot be computed until the sentence ends. The bottom-left panel draws a clock with the backward arrow greyed out and blocked. Bidirectional RNNs are therefore unusable for strictly causal, streaming tasks — a genuine limitation, not a bug. This is one reason later models like the Attention Mechanism and Transformers were developed.

Case D — the empty sequence, (bottom-right panel). Nothing to read; both chains return their zero initial states and no is produced. A well-guarded implementation short-circuits here — the bottom-right panel is an empty, dashed box.

Figure — Bidirectional RNNs

The one-picture summary

Two fingers, opposite directions, meeting at every word to shake hands into one long summary that then votes on a label.

Figure — Bidirectional RNNs
Recall Feynman retelling — say it like a story

Picture a mystery novel and two friends. Friend One reads from page one forward, keeping a running "here's what I know so far" note — that note is , and it grows as she reads (Steps 2–3). But on any single page she has no idea how the story ends (Step 4 — the blind spot). So Friend Two reads the same book backwards from the last page, keeping his own note that captures "here's what's still to come" (Step 5). At every page the two friends staple their notes together side by side — that stapled pair is , and stapling (concatenation) rather than averaging means neither friend's insight is smudged out (Step 6). Finally a judge reads the stapled note and, using softmax, announces the most probable label for that page — like B-ORG, the beginning of a company name (Step 7). The only catch: Friend Two can't start until the book is finished — so this trick only works when you already have the whole sequence, not live word-by-word (Step 8, Case C). That single caveat is why streaming systems reach instead for Attention Mechanism and Transformers. See also how these summaries feed Sequence-to-Sequence Models and the Encoder-Decoder Architecture, and how gated cells like LSTM and GRU Cells can replace the plain box in each direction.