Chapter 11 fixed one blindness and left the other in plain sight. The feed-forward language model concatenates embeddings into a single vector, that vector is its whole memory, and its length is decided before training begins. So the model reads a sentence through a slot of fixed width, and everything outside falls away exactly as it did for the counter.
Consider “the book that the committee rejected was short”, where the verb agrees with book eight words back and a window of three cannot see it. Widening the window is not a fix, because the hidden matrix has shape and its size grows with every word you admit. And no fixed width is ever wide enough, since sentences have no maximum length.
What we want is a model that reads left to right, keeping a running summary of everything so far and updating it at each word. The summary is a state and the update rule is a recurrence.
A recurrent neural network keeps a hidden state and rewrites it at every time step:
Here is the embedding of the word read at step , while is conventionally the zero vector.
Three matrices carry the whole model, where maps the current word into the state, maps the previous state into the new one, and maps the state to a score for every vocabulary word.
The important word is same, because the same , and are used at every step however long the sentence, and that reuse is what recurrent means.
Equation (12.8) therefore does something the feed-forward model could not, since was itself computed from and so on back to the first word. The state at step depends on every word read so far, so there is no window and no cliff.
Take a model small enough to print, with two hidden units, embeddings of size two and a vocabulary of three words.
Read the sentence the dog ran, starting from .
| word | ||||
|---|---|---|---|---|
| 1 | the | |||
| 2 | dog | |||
| 3 | ran |
Follow the third row, whose input column depends only on ran while its depends on , which depended on , which depended on the. So is a summary of the whole prefix, nothing was thrown away, and no parameter was added to make room for it.
The lectures ask why rather than the sigmoid, and the answer is worth keeping. is symmetric about the origin so its output is zero-centred, and states that average to zero train faster than states that average to . Its derivative is also steeper, since the sigmoid’s lies in while ’s lies in .
A derivative capped at shrinks the gradient by at least a factor of four at every step, and Section 12.5 shows why that is fatal, with merely delaying the problem rather than removing it.
Modern architectures mostly use ReLU and its variants, which pass gradient unchanged on the positive side, though ReLU has its own failure in that a unit whose input is always negative stops passing any gradient at all and never recovers. Leaky ReLU, with small , exists to prevent that.
Equation (12.9) already produces one distribution over the vocabulary per time step, which is exactly what a language model needs. Train it by predicting the next word at every position, where the loss at step is the cross-entropy of Chapter 11 and the loss for a sentence is their sum:
Everything from Chapter 10 carries over, since the task, the maximum likelihood objective and the perplexity of Section that section are all untouched. Only the machinery producing has changed again.
The clearest argument for the recurrence is a table of shapes. Take , embeddings of size and hidden units, which are the lecture’s numbers.
| matrix | shape | parameters |
|---|---|---|
| 1,000,000 | ||
| 50,000 | ||
| 250,000 | ||
| 5,000,000 | ||
| biases | 10,500 | |
| total | 6,310,500 |
Not one of those shapes mentions the length of the sentence. Compare the feed-forward model, whose has shape and therefore grows with every word of context admitted.
| context words | feed-forward | recurrent |
|---|---|---|
| 3 | 150,000 | 250,000 |
| 5 | 250,000 | 250,000 |
| 10 | 500,000 | 250,000 |
| 50 | 2,500,000 | 250,000 |
| 500 | 25,000,000 | 250,000 |
At a context of three the feed-forward model is actually smaller, the two cross over at five, and after that the comparison is not close. The left column grows without limit while the right column is a constant, and that one fact is what lets a recurrent network read a paragraph.
Training needs gradients, and the loop has to be flattened before the chain rule can be applied. Unroll the network and a sentence of words becomes a feed-forward network layers deep, in which every layer shares the same weights.
This is backpropagation through time, and the algorithm is ordinary backpropagation on the unrolled graph, with the lectures working the three derivatives out in full. The output matrix is the easy one, because with a softmax and cross-entropy the error signal is again prediction minus target:
The recurrent matrix needs one more link, through the :
where is elementwise multiplication and is the derivative of . The input matrix is identical in form, with in place of :
Because the weights are shared, the gradient for one matrix is the sum of its contributions from every time step, and that sum is where the trouble starts.
Take an error at step and ask what it says about the state at step , where the chain rule gives one factor per step in between:
Each factor is a Jacobian, and Equation (12.8) says what one contains:
So the product in Equation (12.5) behaves like raised to the power , with the derivative damping it at each step.
Repeated multiplication by a matrix is governed by its eigenvalues, and the outcome is binary. If every eigenvalue of satisfies then the product shrinks towards zero and gradients vanish, while if any eigenvalue satisfies then the product grows without bound and gradients explode. Only survives, and nothing in training holds it there.
Treat the per-step factor as a single number and raise it to the distance travelled.
| distance | |||||
|---|---|---|---|---|---|
| 1 | 1.00 | 1.10 | 1.20 | ||
| 5 | 1.00 | 1.61 | 2.49 | ||
| 10 | 1.00 | 2.59 | 6.19 | ||
| 20 | 1.00 | 6.73 | |||
| 47 | 1.00 | ||||
| 100 | 1.00 |
Notice how mild the failing factor is, because a per-step multiplier of looks harmless and yet after fifty steps it has removed more than per cent of the signal.
The lectures make it concrete, so take this passage.
Raj entered CoffeeDay to meet his partner Dru. Raj said “Hi Dru”. In the next few hours they discussed their start-up and devised a plan to develop a product on knowledge management. After a long and fruitful discussion, Raj said goodbye to his .
The answer is partner. The passage runs to words, so the evidence is words behind the gap, and once the punctuation is counted as tokens, which is what the model actually steps over, the distance is . Call it some steps and here is what reaches back that far.
A gradient of is no update at all, so the weights that would have captured the link never move and the network cannot learn the dependency however reliably it holds.
One point deserves emphasis because it is easy to misread. The forward pass is fine and information does flow from the first step to the last. It is the backward pass that fails, since the network cannot assign blame across that distance and so never learns to use the information it is already carrying.
The two failures are not equally hard, and it is worth being clear about which one has a cheap fix.
Exploding gradients have a one line remedy, which is that if the gradient is longer than a threshold you rescale it while keeping its direction:
| step | before | after | direction kept |
|---|---|---|---|
| 1 | 0.3735 | 0.3735 | 1.0000 |
| 2 | 2.7058 | 2.7058 | 1.0000 |
| 3 | 8.4526 | 5.0000 | 1.0000 |
| 4 | 77.0045 | 5.0000 | 1.0000 |
| 5 | 1418.8820 | 5.0000 | 1.0000 |
The last column is every time, because clipping changes how far the step goes and never which way it points, which is why it costs nothing in quality.
It does nothing whatever for vanishing gradients, where the problem is that the number is already too small and scaling it up would amplify noise along with signal.
Unrolling a sequence of thousands of steps is expensive in memory and slow, so truncated backpropagation through time splits the sequence into fixed segments and backpropagates within each, turning a sequence of samples into segments of .
The cost is honest and worth stating, because any dependency spanning a segment boundary is invisible to training, and choosing the boundaries at sentence ends reduces the damage without removing it.
Truncation is therefore a concession rather than a cure. It makes long sequences trainable by giving up on long dependencies, which were the reason for the recurrence in the first place.
One more variant is worth naming, because it answers a limitation that has nothing to do with gradients. An RNN reads left to right, so summarises the past and knows nothing of the future, and for tagging a word that is often the wrong half of the sentence.
A bidirectional RNN (Schuster and Paliwal 1997) runs two independent recurrences, one forward and one backward, then concatenates their states at each position so that every output sees the whole sentence.
The restriction is obvious once stated. A bidirectional model cannot generate text, because the backward pass would need words that have not been produced yet, so it is for labelling rather than prediction. That distinction returns in Chapter 18, where BERT reads both ways and GPT reads one way, for exactly this reason.
Try it yourself.
code/worked_examples/rnn.pyproduces every table in this chapter.--unrollprints the three step trace,--paramsthe two parameter tables,--vanishthe decay table and the forty-seven word arithmetic, and--clipthe clipping demonstration with its unchanged directions.
The window is gone. State carries an unbounded prefix, the parameter count no longer depends on sentence length, and the same three matrices serve a sentence of any size.
In exchange we inherited a new failure, and it is specific rather than vague, since gradients decay geometrically with distance. The network therefore cannot be trained to use information from far back, even though it is perfectly capable of carrying it. Clipping handles one half and truncation manages the cost, while neither touches the vanishing case.
The repair has to be architectural. Multiplying by at every step is what destroys the gradient, so the state needs a path that does not pass through that multiplication. That path is a gate, and building one is the subject of Chapter 13.
Elman (1990) is the original recurrent network for language and
remains the clearest short introduction. Rumelhart et al. (1986)
introduced backpropagation, which backpropagation through time simply
applies to an unrolled graph. Bengio et al. (1994) first proved that
gradient descent cannot learn long-term dependencies in this
architecture, and Pascanu et al. (2013) analyse both failures and
propose clipping. Karpathy et al. (2015) inspect what a trained
recurrent network actually stores in its state, and it is unusually
readable. In a framework the recurrence of this chapter is
torch.nn.RNN, which runs the same three lines over a whole
batch of sequences at once. Graves (2014) shows what these models could
already do with sequences.
Unroll by hand. Using the two by two matrices of this chapter, compute , and for the sentence the dog ran and confirm the table. Then recompute with set to the zero matrix. What has the model become, and which chapter was it?
Count the parameters. For , and , confirm the total of . Which matrix dominates, and what would you change first to shrink the model? Now find the context length at which a feed-forward overtakes the recurrent .
Derive the third gradient. Equations (12.3) and (12.4) differ in exactly one factor. Derive Equation (12.4) from Equation (12.8) and say why that one factor is the only difference.
Measure the decay. For per-step factors of and , compute the gradient magnitude after , and steps. At which distance does the case fall below single precision, roughly ? State what that means for a model trying to learn a dependency at that range.
Why and not sigmoid. The sigmoid derivative is bounded by and the derivative by . Compute the gradient surviving steps under each bound. Then explain why delays the vanishing problem without solving it.
Clipping preserves direction. Show from Equation (12.7) that the clipped gradient is a positive multiple of the original, so the cosine between them is exactly . Then explain in one sentence why the same trick cannot rescue a vanishing gradient.
The cost of truncation. A corpus is split into segments of tokens for truncated backpropagation. Describe a linguistic dependency that this makes unlearnable, and propose a segmentation rule that reduces the damage. What does your rule cost?
Hand your weights to the library. Load this
chapter’s
,
and
into a torch.nn.RNN with two inputs, two hidden units and
tanh, feed it the three word sequence, and confirm that it
returns
,
and
.
You will not get them on the first attempt, because the module holds two
bias vectors where the equation above holds one. Find the second bias,
say what it is for, and explain why leaving it at its initial value
changes every state.
Each one reproduces the tables above. Open it in Colab, change an input and watch which numbers move.
rnn.pyUnrolling, and the vanishing gradient
What unrolling does to the parameter count, and what it does to the gradient.
pip install numpy Run it in Colab Notebook SourceFrom Natural Language Processing: From Corpus Statistics to Grounded LLMs, by Ramaseshan Ramachandran.