When you read “All the cats are cute,” you don't look at the whole sentence at once. You read one word at a time, and as you go you keep a running mental summary: all of something, the cats, they are something, cute. By the last word, that summary is your understanding of the sentence.
A recurrent neural network (RNN) processes text the same way. It keeps a vector called the hidden state, its memory, and updates it once per word: read the next word, update the memory. Because the same update rule is applied at every step, one small network can handle sentences of any length, and in principle the final memory can depend on every word that came before.
1The recurrent unit
Let $x_1,\dots,x_n$ be the word embeddings of a sentence. An RNN computes a sequence of hidden states $h_1,\dots,h_n$, starting from an initial state $h_0$ (usually the zero vector):
$$h_t=\sigma\!\left(W h_{t-1}+U x_t+b\right)$$- $U x_t$ reads the current word: $U$ maps the input embedding into the hidden space.
- $W h_{t-1}$ brings in the memory from the previous step.
- $b$ is a bias, and $\sigma$ is an elementwise activation function, usually $\tanh$ (sometimes the sigmoid), which keeps every entry of $h_t$ between −1 and 1.
The learnable parameters are $W$ (size $d_h\times d_h$), $U$ (size $d_h\times d_x$), and $b$ (size $d_h$), where $d_x$ is the embedding size and $d_h$ is the hidden size. The key point is that the same $W$, $U$, and $b$ are used at every time step. Whether a sentence has 5 words or 500, the RNN has the same number of parameters: it just applies the same update more times.
Step through the running example with a tiny RNN that has 2-dimensional embeddings and a 2-dimensional hidden state, so you can follow every number.
2Unrolling the RNN for classification
Drawing one copy of the recurrent unit per time step is called unrolling the RNN. The unrolled picture is a chain: $h_0\to h_1\to\dots\to h_n$, with word $x_t$ feeding into step $t$. It looks like a deep network with $n$ layers, except that every layer shares the same weights.
For text classification, the final hidden state $h_n$ has read the whole sentence, so it serves as the sentence representation. Feed it into a classifier (for example a feedforward network with a softmax) and train everything end to end with the cross-entropy loss over $C$ classes:
$$\mathcal L_{CE}(y,\tilde y)=-\sum_{c=1}^{C}y_c\log P(y=c\mid h_n)$$Using only $h_n$ puts the whole sentence through a single vector, and the last few words tend to dominate it. A common alternative is to pool over all hidden states, using the elementwise mean or max of $h_1,\dots,h_n$, so that every position contributes directly.
3RNN language models
An RNN can also be a language model: a model of the probability of the next word given all previous words. At every step, add an output layer that turns the hidden state into a distribution over the vocabulary $\mathcal V$:
$$\hat y_t=\text{softmax}(V h_t),\qquad \hat y_t[w]=P(x_{t+1}=w\mid x_1,\dots,x_t)$$Here $V$ is a $|\mathcal V|\times d_h$ output matrix (plus a bias, omitted). Unlike an n-gram model, which only sees a fixed window of the last few words, $h_t$ summarizes the entire prefix, so the prediction can in principle use words from far back. And the model has no counts to store: similar words have similar embeddings, so it can generalize to word sequences it never saw.
Training. Run the RNN over a training sentence. At each position, feed in the true current word (this is called teacher forcing) and score the probability assigned to the true next word. The loss is the sum of the per-step cross-entropies:
$$\mathcal L=-\sum_{t}\log P(x_{t+1}\mid x_1,\dots,x_t)$$| input so far | target | $P(\text{target})$ | $-\ln P$ |
|---|---|---|---|
| <s> | All | 0.05 | 2.996 |
| <s> All | the | 0.40 | 0.916 |
| <s> All the | cats | 0.10 | 2.303 |
| <s> All the cats | are | 0.50 | 0.693 |
| <s> All the cats are | cute | 0.20 | 1.609 |
| <s> All the cats are cute | </s> | 0.60 | 0.511 |
| total | 9.028 |
The average per-token cross-entropy is exactly the log of the perplexity, so minimizing this loss directly lowers perplexity. To generate text, run the same model one step at a time: pick the next word from $\hat y_t$, feed it back in as $x_{t+1}$, and repeat until </s>.
4Stacked and bidirectional RNNs
Stacked (multi-layer) RNNs
The hidden states $h_1^{(1)},\dots,h_n^{(1)}$ of one RNN form a new sequence, so a second RNN can read them:
$$h_t^{(2)}=\sigma\!\left(W^{(2)}h_{t-1}^{(2)}+U^{(2)}h_t^{(1)}+b^{(2)}\right)$$Each layer has its own parameters. As with stacked convolution layers, higher layers can build more abstract features. In practice, 2 to 4 layers are common.
Bidirectional RNNs
A left-to-right RNN's state $h_t$ only knows about words $1,\dots,t$. But for understanding a word, what comes after can matter as much as what comes before: in “the bank of the river,” the word river tells you which bank is meant. A bidirectional RNN runs two separate RNNs, one forward (left to right) and one backward (right to left), and concatenates their states at each position:
$$h_t=\big[\,\overrightarrow{h}_t\,;\,\overleftarrow{h}_t\,\big]$$Bidirectional RNNs are a natural choice when the whole input is available up front: classifying a sentence, or labeling each word in it. They can't be used as language models or for left-to-right generation, because the backward RNN would need to see the future words the model is supposed to predict.
5Strengths and weaknesses
| Advantages | Disadvantages |
|---|---|
| Can process input of any length | Recurrent computation is slow: $h_t$ needs $h_{t-1}$, so steps can't run in parallel |
| Model size doesn't grow with the input length (weights are shared) | In practice, information from many steps back is hard to use |
| Step $t$ can, in theory, use information from all earlier steps | Training suffers from vanishing (and exploding) gradients |
Compared with a CNN, which looks at local windows of words in parallel, an RNN reads sequentially and carries a memory forward. That makes long-range information available in principle, at the price of sequential computation.
6Training and the vanishing gradient problem
An unrolled RNN is just a deep network with shared weights, so it's trained with ordinary back-propagation, applied through the unrolled chain. This is called back-propagation through time (BPTT). Because $W$ is used at every step, its gradient collects one contribution from each step. For a loss computed at step 5, the chain rule gives
$$\frac{\partial\mathcal L}{\partial W}=\sum_{t=1}^{5}\frac{\partial\mathcal L}{\partial h_5}\left(\prod_{k=t+1}^{5}\frac{\partial h_k}{\partial h_{k-1}}\right)\frac{\partial h_t}{\partial W},$$where $\frac{\partial h_t}{\partial W}$ means the direct effect of $W$ on $h_t$ through step $t$'s own update, holding $h_{t-1}$ fixed. The term for step $t$ multiplies together $5-t$ step-to-step derivatives. For $h_k=\tanh(Wh_{k-1}+Ux_k+b)$, each one is
$$\frac{\partial h_k}{\partial h_{k-1}}=\text{diag}\!\left(1-h_k^2\right)W.$$The contribution from $t$ steps back is a product of many such factors. If they are typically smaller than 1 (the derivative of tanh is at most 1, and the sigmoid's is at most 0.25), the product shrinks exponentially. A factor of 0.5 over 20 steps gives $0.5^{20}\approx10^{-6}$. This is the vanishing gradient problem: the gradient signal from distant words fades away, so the weights are updated mostly according to short-term effects, and the RNN struggles to learn long-range dependencies. If the factors are larger than 1, the product instead grows exponentially: the exploding gradient problem.
7Check your understanding
Exercise 1: an RNN by hand
A 1-dimensional RNN has $h_t=\tanh(0.5\,h_{t-1}+x_t)$ and $h_0=0$. The inputs are $x_1=1$ and $x_2=-1$. Compute $h_1$ and $h_2$.
$h_2=\tanh(0.5\cdot0.762-1)=\tanh(-0.619)\approx-0.551$.
Exercise 2: counting parameters
An RNN classifier uses 300-dimensional embeddings and a 128-dimensional hidden state. (1) How many parameters are in $W$, $U$, and $b$? (2) How does this change for sentences that are twice as long? (3) If the same RNN becomes a language model with a vocabulary of 10,000 words, how many parameters does the output layer $V$ (with its bias) add?
(2) It doesn't change: the same weights are reused at every step.
(3) $10{,}000\times128+10{,}000=1{,}290{,}000$. The output layer is much larger than the recurrent part.
Exercise 3: vanishing gradients
Suppose every step-to-step derivative $\partial h_k/\partial h_{k-1}$ is about 0.5. Roughly how much weaker is the gradient signal from 20 steps back than from 1 step back? What if every factor were 1.5?
Quick quiz
8Further reading
- Karpathy (2015). The Unreasonable Effectiveness of Recurrent Neural Networks. Blog post. (Character-level RNN language models and what they learn.)
- Mikolov, Karafiát, Burget, Černocký & Khudanpur (2010). Recurrent Neural Network Based Language Model. Interspeech.
- Bengio, Simard & Frasconi (1994). Learning Long-Term Dependencies with Gradient Descent is Difficult. IEEE Transactions on Neural Networks. (The vanishing gradient problem.)
- Pascanu, Mikolov & Bengio (2013). On the Difficulty of Training Recurrent Neural Networks. ICML. (Vanishing and exploding gradients; gradient clipping.)
- Schuster & Paliwal (1997). Bidirectional Recurrent Neural Networks. IEEE Transactions on Signal Processing.