Deep Learning

RNN & backprop through time

This lecture processes ordered data with a recurrent network. It shares one set of weights across time steps and trains them with backprop through time. After this page you can run a two-step RNN forward pass by hand and trace one BPTT gradient.

Sequence learningSearch on YouTube

Feedforward networks and CNNs take fixed-size inputs. They treat every input as independent of the others. Sequence tasks break both rules. Length varies from sample to sample. Order changes the meaning.

The slides show auto word prediction. Feed d into the network and it predicts e. Feed that e back in and it predicts the next letter. Each prediction depends on the letters seen before.

Two more slide tasks work the same way. POS tagging assigns one tag to each word in order. Polarity scoring reads a whole review and outputs one label.

A sentence is a queue, not a bag of coins. Shuffle the words and the total stays the same, but the meaning breaks.

Sequence learning covers problems with ordered, variable-length input. Temporal dependence means the current input needs the past inputs for its meaning. Speech, text, sensor traces and video are natural examples.

Challenges in sequence learningSearch on YouTube

Three demands separate sequence learning from standard learning:

  • Variable-length inputs. Sentences and traces have different lengths. The model must accept any length.
  • Temporal dependencies. The meaning of the current input depends on previous elements. not flips the good that follows it.
  • Same function at each time step. The model must reuse one parameter set for every time step tt. Sharing cuts the parameter count and helps the model generalize across time.

Failed alternativesSearch on YouTube

Two naive designs fail before the RNN appears.

First, reuse one fixed network per element with no memory. It accepts any length. It keeps no dependency on previous inputs. Each step sees only the current element.

Second, train separate weights for each position. Position 1 gets one matrix, position 2 another, and so on. The parameter count grows with length. Computation grows with it. Long sentences become untrainable.

ApproachAny lengthKeeps historyParameter cost
Fixed net, no memoryyesnosmall
One net per positionnoyesgrows with length
RNN with shared weightsyesyesfixed

S0, S1 and S2 solutionSearch on YouTube

The slides build the fix from states. Keep a state SS that summarizes the past. Update it at each step. Read the output OO from it.

The chain runs S0→S1→S2S_0 \to S_1 \to S_2. Each new state combines the current input with the previous state. The output at each step reads the current state. This is the recurrent solution. The next section names the pieces.

Recurrent neural networkSearch on YouTube

An RNN processes a sequence one element at a time. It keeps a hidden state that carries past information forward. The hidden state (the slides also call it state StS_t) updates at every step with the same weights.

h1 h2 h3 x1 x2 x3 o1 o2 o3 W W U V V
Unrolled RNN over three steps. U feeds inputs in, W carries the state forward, V reads outputs out.
ht=σ(Uxt+Wht−1+b)h_t = \sigma(U x_t + W h_{t-1} + b)

hth_t is the hidden state at step tt. xtx_t is the input at step tt. UU maps inputs to the hidden state. WW maps the previous hidden state to the current one. bb is the bias. σ\sigma is the hidden activation function.

y^t=Ot(Vht+c)\hat{y}_t = O_t(V h_t + c)

y^t\hat{y}_t is the predicted value at step tt (yty_t is the label). VV maps the hidden state to the output. cc is the output bias. OtO_t is the output activation function: softmax, sigmoid or linear.

The same UU, WW, VV, bb and cc serve every step. Sharing is what keeps the model small. The hidden state is the only thing that changes with time.

Training a recurrent networkSearch on YouTube

Training follows three steps. They mirror feedforward training, with time added.

  1. Run the forward pass. Feed the sequence step by step. Update the hidden state and emit outputs.
  2. Compute the loss. Compare each prediction with its label. Add the per-step losses into one total.
  3. Run backprop through time. Send gradients back across steps. Add them and update the weights.

Outputs appear at each step or only at the final step. Tagging needs one output per step. Polarity needs only the last one.

L=∑t=1TLtL = \sum_{t=1}^{T} L_t

LL is the total loss over a sequence of length TT. LtL_t is the loss at step tt. All learnable parameters sit in θ={V,W,U}\theta = \{V, W, U\} plus biases.

Lt=12(yt−y^t)2Lt=−∑iyt,ilog⁡y^t,iL_t = \tfrac{1}{2}(y_t - \hat{y}_t)^2 \qquad L_t = -\sum_i y_{t,i}\log \hat{y}_{t,i}

Use squared error for real-valued targets. Use cross entropy for class targets. OtO_t pairs with the loss: linear with squared error, sigmoid with binary labels, softmax with cross entropy.

Worked example. Scalar toy RNN, two steps. Weights U=0.6U = 0.6, W=0.8W = 0.8, V=1.0V = 1.0, biases 00. Inputs x1=1x_1 = 1, x2=0.5x_2 = 0.5. Start state h0=0h_0 = 0. Hidden and output activations are sigmoid.

Step 1. a1=0.6⋅1+0.8⋅0=0.6a_1 = 0.6 \cdot 1 + 0.8 \cdot 0 = 0.6.

h1=σ(0.6)=1/(1+e−0.6)=1/1.5488=0.6457\begin{aligned} h_1 &= \sigma(0.6) = 1/(1+e^{-0.6}) = 1/1.5488 = \mathbf{0.6457} \end{aligned}

Step 2. a2=0.6⋅0.5+0.8⋅0.6457=0.3+0.5166=0.8166a_2 = 0.6 \cdot 0.5 + 0.8 \cdot 0.6457 = 0.3 + 0.5166 = 0.8166.

h2=σ(0.8166)=1/(1+e−0.8166)=1/1.4420=0.6935y^2=σ(1.0⋅0.6935)=1/(1+e−0.6935)=1/1.4998=0.6668\begin{aligned} h_2 &= \sigma(0.8166) = 1/(1+e^{-0.8166}) = 1/1.4420 = \mathbf{0.6935}\\ \hat{y}_2 &= \sigma(1.0 \cdot 0.6935) = 1/(1+e^{-0.6935}) = 1/1.4998 = \mathbf{0.6668} \end{aligned}

Check. e−0.6=0.5488e^{-0.6} = 0.5488, e−0.8166=0.4420e^{-0.8166} = 0.4420, e−0.6935=0.4998e^{-0.6935} = 0.4998. Recompute each quotient and the digits match.

Backprop through timeSearch on YouTube

BPTT is backprop unrolled over time. It computes one gradient per step and adds them. Shared weights collect their updates from all steps.

Time order controls the chain rule. hth_t depends on WW twice over. The direct path is the Wht−1W h_{t-1} term inside hth_t. The indirect path runs through ht−1h_{t-1}, which itself used WW. The same split holds for UU.

∂L∂W=∑t=1T∂Lt∂W∂L∂U=∑t=1T∂Lt∂U\frac{\partial L}{\partial W} = \sum_{t=1}^{T} \frac{\partial L_t}{\partial W} \qquad \frac{\partial L}{\partial U} = \sum_{t=1}^{T} \frac{\partial L_t}{\partial U}

Each step contributes its own gradient. Shared weights sum them. h0h_0 is a constant, so its derivative is 00.

∂Lt∂W=∂Lt∂y^t∂y^t∂ht∑r=1r≤t(∏k=r+1t∂hk∂hk−1)(∂hr∂W)explicit\frac{\partial L_t}{\partial W} = \frac{\partial L_t}{\partial \hat{y}_t}\frac{\partial \hat{y}_t}{\partial h_t} \sum_{r=1}^{r \le t}\left(\prod_{k=r+1}^{t}\frac{\partial h_k}{\partial h_{k-1}}\right)\left(\frac{\partial h_r}{\partial W}\right)_{\text{explicit}}

The explicit part is the direct use of WW at step rr. The implicit part is the product chain back through hr+1…hth_{r+1} \dots h_t. The UU gradient reuses the same chain with (∂hr/∂U)(\partial h_r / \partial U) in place of (∂hr/∂W)(\partial h_r / \partial W).

The r=tr = t term is the explicit component. Terms with r<tr \lt t are implicit components. They trace back to h1h_1. The r=0r = 0 term drops out because h0h_0 is constant.

Trace one LtL_t at a time in exams. Write the output path first. Then expand one explicit term plus one implicit chain. Examiners award marks for the split.

Worked example. BPTT trace for L2L_2 with the toy numbers above. Loss L2=12(y2−y^2)2L_2 = \tfrac{1}{2}(y_2 - \hat{y}_2)^2 with label y2=1y_2 = 1 and y^2=0.6668\hat{y}_2 = 0.6668.

Output path. Error signal times sigmoid slope.

∂L2/∂y^2=0.6668−1=−0.3332∂y^2/∂h2=0.6668⋅0.3332=0.2222∂L2/∂h2=−0.3332⋅0.2222=−0.0740\begin{aligned} \partial L_2/\partial \hat{y}_2 &= 0.6668 - 1 = -0.3332\\ \partial \hat{y}_2/\partial h_2 &= 0.6668 \cdot 0.3332 = 0.2222\\ \partial L_2/\partial h_2 &= -0.3332 \cdot 0.2222 = \mathbf{-0.0740} \end{aligned}

Hidden path. Sigmoid slopes: σ′(a2)=0.6935⋅0.3065=0.2126\sigma^\prime(a_2) = 0.6935 \cdot 0.3065 = 0.2126.

(∂h2/∂W)explicit=0.2126⋅h1=0.2126⋅0.6457=0.1373∂h2/∂h1=0.2126⋅0.8=0.1701(∂h1/∂W)explicit=σ′(a1)⋅h0=0    (h0=0)\begin{aligned} (\partial h_2/\partial W)_{\text{explicit}} &= 0.2126 \cdot h_1 = 0.2126 \cdot 0.6457 = \mathbf{0.1373}\\ \partial h_2/\partial h_1 &= 0.2126 \cdot 0.8 = \mathbf{0.1701}\\ (\partial h_1/\partial W)_{\text{explicit}} &= \sigma^\prime(a_1) \cdot h_0 = 0 \;\; (h_0 = 0) \end{aligned}

Combine. Implicit term dies on h0=0h_0 = 0. Only the explicit term at r=2r = 2 stays.

∂L2/∂W=−0.0740⋅(0.1373+0.1701⋅0)=−0.0102\begin{aligned} \partial L_2/\partial W &= -0.0740 \cdot (0.1373 + 0.1701 \cdot 0) = \mathbf{-0.0102} \end{aligned}

Check. 0.6935⋅0.3065=0.21260.6935 \cdot 0.3065 = 0.2126. Then 0.2126⋅0.6457=0.13730.2126 \cdot 0.6457 = 0.1373. Then 0.0740⋅0.1373=0.01020.0740 \cdot 0.1373 = 0.0102. Signs stay negative, so gradient descent raises WW.

The lab replays the two-step scalar RNN from the worked example. It then traces the BPTT chain and the clip plus truncate fixes.

h0=0h1=0.6457h2=0.6935x1=1x2=0.5y-hat=0.6668UUWWV

Unrolled toy RNN. U, W and V stay shared across steps.

a2 = 0.3 + 0.5166 = 0.8166. h2 = 0.6935. y-hat = 0.6668.

0.25^5 = 0.0010 (0.25^5 is about 0.001). Signal vanishes.

Norm is 12. Scale is 0.4167. Clipped norm is 5.0.

k = 2 keeps steps 6 to 7. Older links stay unlearned.

Vanishing and exploding gradientsSearch on YouTube

The implicit chain multiplies many derivatives. Each factor is a Jacobian ∂hk/∂hk−1=σ′(ak) W\partial h_k / \partial h_{k-1} = \sigma^\prime(a_k)\,W. Long products misbehave in two ways.

Vanishing means gradients shrink step by step. Early steps barely update. Learning stalls. Sigmoid slopes peak at 0.250.25. Tanh slopes peak at 1.01.0. Products of such factors decay fast.

Exploding means gradients grow step by step. Weights blow up. Training turns unstable. Factors above 11 compound the same way in reverse.

∂ht∂ht−k=∏j=0k−1σ′(at−j) W\frac{\partial h_t}{\partial h_{t-k}} = \prod_{j=0}^{k-1} \sigma^\prime(a_{t-j})\,W

One factor per step back. ∣σ′∣≤0.25|\sigma^\prime| \le 0.25 for sigmoid and ∣σ′∣≤1|\sigma^\prime| \le 1 for tanh. With ∣W∣<1|W| \lt 1 the product shrinks toward 00. With ∣W∣>1|W| \gt 1 it can grow fast.

Saturation adds to the damage. Large ∣w∣|w| makes the sigmoid switch too fast. Large ∣b∣|b| shifts it left or right into a flat end. Flat ends have near-zero slope, so gradients vanish there too.

VanishingExploding
Gradients shrink toward 0Gradients grow out of control
Early steps stop learningWeights blow up, loss jumps
Caused by slopes below 1, saturationCaused by factors above 1
Fix: truncate history, gate memoryFix: clip gradients

Fixes: clipping and truncated BPTTSearch on YouTube

The slides name three fixes. The first two belong here. The third is a later lecture.

Gradient clipping caps exploding steps. Pick a ceiling τ\tau such as 11 or 55. Rescale any gradient above it. Direction stays the same. Size stops at τ\tau.

Truncated BPTT caps the history length. Backpropagate only kk steps. A 100-word sequence might train on the last 20 steps. Long-range links beyond kk go unlearned. Cost per update stays flat.

LSTM adds a memory cell for long-range links. It is the topic of the next lecture.

g←g⋅min⁡(1, τ/∥g∥)g \leftarrow g \cdot \min\left(1,\, \tau / \Vert g \Vert\right)

gg is the gradient vector. ∥g∥\Vert g \Vert is its norm. τ\tau is the ceiling. Gradients below τ\tau pass through unchanged.

C-T-L: Clip, Truncate, LSTM

Clip caps gradient size · Truncate caps history length · LSTM (next lecture) carries long memory.

Truncate with care on exams. A small kk speeds training but erases links longer than kk. Name the trade-off when you recommend it.

Bag of words for text classificationSearch on YouTube

The classic pipeline ignores order. Tokenize the text. Build a vocabulary with one index per word. Count words per document into a design matrix. Feed the matrix to a plain classifier.

Each row is one document. Each column is one word. Cell values are counts or term frequencies. Labels sit in a vector YY.

Worked example. Three reviews. Vocabulary: movie (0), is (1), good (2), not (3). Labels: 11 for positive, 00 for negative.

DocTextmovieisgoodnotYY
d1movie is good11101
d2movie is not good11110
d3not good00110

Read it. The design matrix is 3×43 \times 4. YY is 3×13 \times 1. Row d3 equals the counts of good not. Order is lost: not good and good not share one row.

The slide pair proves the loss. The movie my friend has not seen is good is positive. The movie my friend has seen is not good is negative. Both use the same word multiset. Their count rows match. A BoW classifier cannot split them.

RNN text classificationSearch on YouTube

The RNN pipeline keeps order. Map words to integer ids. Pad short sentences to one length. Replace ids with vectors. Feed the vectors step by step.

Integers alone mislead. Id 77 is not larger than id 22. One-hot vectors remove the fake order. Each word becomes a sparse 1×V1 \times V row with one 11.

Dense embeddings replace the sparse rows. The embedding matrix EE has size V×DV \times D. VV is the vocabulary size. DD is the embedding size (feature count per word). Rows come from Word2Vec, GloVe, FastText or training from scratch.

The lookup trick skips the sparse multiply. (1×V)(1 \times V) times (V×D)(V \times D) gives (1×D)(1 \times D). That product copies one row of EE. So gather rows by index instead of multiplying.

e=xone-hot E(1×V) (V×D)=(1×D)e = x_{\text{one-hot}}\,E \qquad (1 \times V)\,(V \times D) = (1 \times D)

xone-hotx_{\text{one-hot}} is one 1×V1 \times V word vector. EE is the V×DV \times D embedding matrix. ee is the 1×D1 \times D dense word vector. Lookup copies row ii of EE when the 11 sits at index ii.

Worked example. Vocabulary size V=11V = 11 (ids 00 to 99, pad id 1010). Embedding size D=4D = 4. Sentence ids [7,5,2,4][7, 5, 2, 4] padded to length 77 with [10,10,10][10, 10, 10].

Lookup. Copy rows of EE in token order. Pad rows are zeros.

row 7=[1,0,2,0]row 5=[0,1,1,0]row 2=[2,2,0,1]row 4=[0,0,1,2]row 10=[0,0,0,0]\begin{aligned} \text{row } 7 &= [1, 0, 2, 0]\\ \text{row } 5 &= [0, 1, 1, 0]\\ \text{row } 2 &= [2, 2, 0, 1]\\ \text{row } 4 &= [0, 0, 1, 2]\\ \text{row } 10 &= [0, 0, 0, 0] \end{aligned}

Stack. Four word rows plus three pad rows give a 7×47 \times 4 input matrix.

1020
0110
2201
0012
0000
0000
0000

Check. Full one-hot math would multiply (7×11)(7 \times 11) by (11×4)(11 \times 4) to get (7×4)(7 \times 4). Lookup copies the same 77 rows. Dims and values agree.

Out-of-vocabulary words need a plan. Map unseen words to one unknown vector. Or build their vectors from sub-word pieces. A fresh Word2Vec trained only on new words may land in a different space, so avoid that shortcut.

Character prediction with vocab E S TSearch on YouTube

Character RNNs use a tiny vocabulary. Here it is {E,S,T}\{E, S, T\} with size 33. Inputs are one-hot: E=[1,0,0]E = [1,0,0], S=[0,1,0]S = [0,1,0], T=[0,0,1]T = [0,0,1]. Possible words include SET, SEE, SETS, SEES and TEST. A full capital-letter vocabulary would need size 2626.

The model reads one character per step. It predicts the next character. Softmax over 33 logits gives the probabilities.

P(y=i∣z)=ezi/∑jezjLt=−log⁡P(y=label∣z)P(y = i \vert z) = e^{z_i}/\sum_j e^{z_j} \qquad L_t = -\log P(y = \text{label} \vert z)

zz holds the 33 logits. PP is the predicted probability per character. LtL_t is the cross entropy loss at step tt for the true next character.

Worked example. Input so far: S E E. True next character: S (spells SEES). Logits for [E,S,T][E, S, T] are z=[1.2, 2.0, 0.5]z = [1.2,\, 2.0,\, 0.5].

Softmax. Exponentiate and normalize.

e1.2=3.3201e2.0=7.3891e0.5=1.6487sum=3.3201+7.3891+1.6487=12.3579P(E)=3.3201/12.3579=0.2687P(S)=7.3891/12.3579=0.5979P(T)=1.6487/12.3579=0.1334\begin{aligned} e^{1.2} &= 3.3201 \qquad e^{2.0} = 7.3891 \qquad e^{0.5} = 1.6487\\ \text{sum} &= 3.3201 + 7.3891 + 1.6487 = 12.3579\\ P(E) &= 3.3201/12.3579 = \mathbf{0.2687}\\ P(S) &= 7.3891/12.3579 = \mathbf{0.5979}\\ P(T) &= 1.6487/12.3579 = \mathbf{0.1334} \end{aligned}

Decide and score. Max probability is SS, so the model emits S. Loss is −log⁡(0.5979)=0.5144-\log(0.5979) = \mathbf{0.5144}. Probabilities sum to 1.00001.0000.

RNN variantsSearch on YouTube

One recurrence serves many layouts. The layout follows the task.

Sentiment and document classification is many-to-one. The RNN reads one word vector xtx_t per step. It updates hth_t from xtx_t and ht−1h_{t-1}. After the last word, one vector yy passes through softmax into positive, negative or neutral.

Image captioning is one-to-many. A CNN encoder (such as ResNet) turns the image into a vector vv. vv seeds the initial hidden state h0h_0. The RNN then emits words. Step 1 takes a start token and outputs y1y_1. Step 2 takes y1y_1 and outputs y2y_2. Decoding stops at an end token or a max length.

POS tagging is many-to-many and aligned. Each word maps to its tag at the same step. Input count equals output count. No delay.

Translation and question answering is many-to-many with delay. The RNN reads the full input first. Outputs start only after encoding ends. Alignment across languages is not one-to-one.

VariantLayoutOutputs start
Sentiment scoringmany-to-oneafter last word
Image captioningone-to-manyafter image vector seeds h0h_0
POS taggingmany-to-many, alignedat same step
Translationmany-to-many, delayedafter full input

Quick self-testSearch on YouTube

1. Why do feedforward nets fail on The movie my friend has not seen is good vs ... has seen is not good?

Both sentences share one word multiset, so fixed-size count inputs match. Order carries the flip from not. Sequence models read order, so they split the pair.

2. Scalar RNN with U=0.5U = 0.5, W=0.5W = 0.5, b=0b = 0, h0=0h_0 = 0. Input x1=2x_1 = 2. Find h1h_1 with sigmoid.

a1=0.5⋅2+0.5⋅0=1.0a_1 = 0.5 \cdot 2 + 0.5 \cdot 0 = 1.0. h1=σ(1.0)=1/(1+e−1)=1/1.3679=0.7311h_1 = \sigma(1.0) = 1/(1 + e^{-1}) = 1/1.3679 = 0.7311.

3. Per-step losses are L1=0.2L_1 = 0.2, L2=0.5L_2 = 0.5, L3=0.1L_3 = 0.1. What total does BPTT differentiate?

L=0.2+0.5+0.1=0.8L = 0.2 + 0.5 + 0.1 = 0.8. BPTT sums per-step gradients of this total.

4. Differentiate the explicit and implicit parts of ∂Lt/∂W\partial L_t / \partial W.

Explicit is the direct WW use at step rr. Implicit is the chain back through hr+1…hth_{r+1} \dots h_t. The r=tr = t term is purely explicit.

5. Each step multiplies the gradient by 0.250.25. How much survives after 55 steps back?

0.255=0.00098≈0.0010.25^5 = 0.00098 \approx 0.001. Only about a thousandth survives. That is vanishing in numbers.

6. Gradient norm is 1212 and the ceiling is τ=5\tau = 5. What scale factor applies?

Factor =5/12=0.4167= 5/12 = 0.4167. New norm is 55. Direction is unchanged.

7. Vocabulary order: movie, is, good, not. Write the BoW row for movie not good. What label breaks BoW here?

Row is [1,0,1,1][1, 0, 1, 1]. good not gives the same row with opposite sense. Counts cannot split them.

8. Vocab size 99, embedding size 66, 55 tokens in. What tensor feeds the RNN?

Each token gives 1×61 \times 6. Five tokens stack to 5×65 \times 6. Lookup skips the (5×9)(9×6)(5 \times 9)(9 \times 6) multiply.

9. Logits [E,S,T]=[0.5,1.5,0.0][E, S, T] = [0.5, 1.5, 0.0]. Which character wins, with what probability?

Exponentials: 1.64871.6487, 4.48174.4817, 1.01.0. Sum =7.1304= 7.1304. P=[0.2312,0.6285,0.1403]P = [0.2312, 0.6285, 0.1403]. SS wins at 0.62850.6285.

10. POS tagging vs translation: which emits outputs with a delay, and why?

Translation waits for the full input first. Its outputs align with encoded meaning, not with input positions. POS tagging emits at the same step instead.

  • Sequence tasks have variable length and order-dependent meaning. Fixed independent inputs fail them.
  • Failed options are memory-free reuse (no history) and per-position weights (too many parameters).
  • The RNN updates ht=σ(Uxt+Wht−1+b)h_t = \sigma(Ux_t + Wh_{t-1} + b) and predicts y^t=Ot(Vht+c)\hat{y}_t = O_t(Vh_t + c) with shared weights.
  • Training runs forward pass, total loss L=∑LtL = \sum L_t, then BPTT sums per-step gradients.
  • BPTT splits each gradient into explicit (direct WW use) and implicit (chain through past states) parts.
  • Long chains vanish (factors below 1, saturation) or explode (factors above 1).
  • Fixes are gradient clipping (g⋅min⁡(1,τ/∥g∥)g \cdot \min(1, \tau/\Vert g\Vert)), truncated BPTT (last kk steps) and LSTM memory (next lecture).
  • BoW counts words into a design matrix but loses order (not good equals good not).
  • RNN text input runs integers to padding to one-hot to embedding lookup (1×V)(V×D)=(1×D)(1 \times V)(V \times D) = (1 \times D).
  • Char prediction over {E,S,T}\{E,S,T\} uses softmax ezi/∑jezje^{z_i}/\sum_j e^{z_j}; the SEES example gives P(S)=0.5979P(S) = 0.5979 and loss 0.51440.5144.
  • Variants: sentiment (many-to-one), captioning (one-to-many from h0=vh_0 = v), POS (aligned), translation (delayed).