1 Why MLPs fail on sequences
- Text, audio, stock prices, video, DNA all have a temporal/order dimension β shuffling destroys meaning. CNNs assume spatial locality; sequences are temporal.
- Three fatal MLP problems:
- Fixed input size β MLP needs a predetermined number of input neurons.
- No notion of order β position 1 and position 100 are treated as unrelated features.
- Parameter explosion β 500 words Γ 300-dim = 150,000 input neurons.
- Flattening a sentence into one long vector loses all temporal structure.
- What makes sequences special: variable length, order matters ("dog bites man" β "man bites dog"), and long-range dependencies (e.g. "The students who came from France ___ French" β answer "speak" depends on "students" 6 words back).
- Key insight β weight sharing across time: apply the same function at every timestep. Same weights handle word 1 and word 1000 β handles any length with constant parameters.
2 The vanilla RNN & recurrence
- An RNN is a network with memory: it takes the previous hidden state
h_t-1plus inputx_tand produces a new hidden stateh_t.
h_t = tanh(W_xh Β· x_t + W_hh Β· h_t-1 + b_h)Start from
h_0 = 0 (no prior memory). Each step combines the current input with accumulated context.
- Unrolling: the folded loop = compact notation; the unrolled chain = what actually happens. It is the same network copied across time with identical weights at every step.
- Three weight matrices (the only learned params, shared across all timesteps):
| Matrix | Connection | Role |
|---|---|---|
W_xh | input β hidden | how to process new input |
W_hh | hidden β hidden | how to update memory |
W_hy | hidden β output | how to produce predictions |
- Parameter count for length T: MLP is
O(TΒ·dΒ²)(grows with length); RNN isO(dΒ²)β constant regardless of length. - PyTorch:
nn.RNN(input_size, hidden_size, batch_first=True); input shape(batch, seq_len, features). Forward returnsoutput(hidden states at all timesteps) andh_n(final hidden state only).
4 Backpropagation Through Time (BPTT)
- The big idea (3 steps): (1) unroll the RNN across all T timesteps; (2) the unrolled RNN looks like a very deep feedforward network (a 100-token sequence β a 100-layer net); (3) apply standard backprop on this unrolled graph. Gradients flow backward through time.
- The chain rule through time β gradient of loss w.r.t.
W_hhis a product of Jacobians across timesteps:
βL/βW_hh β β (t=k..T) βh_t / βh_t-1 each factor: βh_t/βh_t-1 = W_hh^T Β· diag(tanh'(Β·))
- Truncated BPTT: full BPTT on 10,000 tokens = backprop through 10,000 layers β impractical. Instead, only unroll
Ksteps (common K = 20β100, e.g. 35): process the sequence in chunks, carryhforward, backprop only within each chunk. Trade-off: can't learn dependencies longer than K steps.
5 Vanishing & exploding gradients
W_hh:
- singular value < 1 β product β 0 β vanishing
- singular value > 1 β product β β β exploding
tanh' β€ 1 always, which compounds the decay.
- Vanishing intuition: multiply a number < 1 by itself repeatedly β 0. e.g. 0.9ΒΉβ° β 0.349, 0.9β΅β° β 0.005, 0.9ΒΉβ°β° β 0.00003. The gradient from the loss barely reaches early timesteps.
- Consequence: the network cannot learn that an input 50 steps ago matters. In practice vanilla RNNs fail on dependencies beyond ~20 tokens.
- Exploding: symptoms are loss β NaN, params β β. Fix = gradient clipping: if
βββ > threshold, scale it down.torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=5.0). - Clipping fixes exploding, NOT vanishing. Vanishing needs a new architecture β LSTMs/GRUs (gates create "gradient highways" through time).
6 RNN task patterns
| Pattern | Input β Output | Example tasks |
|---|---|---|
| Many-to-one | sequence β label | sentiment, document classification, spam detection |
| Many-to-many | sequence β sequence | POS tagging, NER, machine translation |
| One-to-many | single β sequence | image captioning, music generation |
β Likely exam questions
Q1. Write the vanilla RNN recurrence equation and name the three weight matrices.
A. h_t = tanh(W_xhΒ·x_t + W_hhΒ·h_t-1 + b). W_xh: inputβhidden; W_hh: hiddenβhidden (memory update); W_hy: hiddenβoutput. All three are shared across every timestep.
Q2. Why can't a standard MLP handle variable-length sequences?
A. An MLP needs a fixed-size input vector. To use one you'd pad every sequence to the max length β wasting parameters and destroying the notion of temporal order. RNNs sidestep this via weight sharing across time.
Q3. Why does the unrolled RNN resemble a very deep feedforward network?
A. Each timestep acts like one layer, so a 100-step sequence becomes equivalent to a 100-layer net during backprop (BPTT).
Q4. Why do gradients vanish in RNNs?
A. The gradient w.r.t. W_hh is a product of Jacobians across timesteps. When the largest singular value of W_hh is < 1 (and tanh' β€ 1), repeated multiplication decays exponentially, so gradients barely reach early timesteps.
Q5. If the largest singular value of W_hh is 0.9 and the sequence is 50 steps, how much gradient reaches step 1?
A. β 0.9β΅β° β 0.005 β only about 0.5%. The network effectively cannot learn from that early input.
Q6. What is truncated BPTT, and what does gradient clipping fix?
A. Truncated BPTT only backpropagates through K timesteps (carrying h forward between chunks), trading long-range learning for feasibility. Gradient clipping rescales gradients above a threshold β it fixes exploding gradients but does nothing for vanishing (that needs LSTMs/GRUs).