CASCenter for Advanced Studies · AI Engineering Program
◆ DEEP DIVE TUTORIAL · RNN · NUMERICAL WALKTHROUGH
RNN Forward Pass & Backprop by Hand
A complete numerical example: the sentence "was not bad" enters as one-hot vectors, and we compute every single value — forward and backward — with real numbers you can verify on a calculator.
Forward pass: 3 timesteps, every at and ht with 4-decimal precision
Softmax output & cross-entropy loss with exact numbers
Backprop: δt at every timestep with intermediate products shown
Total gradients for all 5 parameter tensors, summed across time
Gradient descent update with η = 0.1 — the new weights
No black boxes. Every number below was computed by a Python script — you can reproduce every step.
01 THE EXAMPLE
Sentence: "was not bad"
Three words. Target: POSITIVE (because "not bad" is good). The model must read one word at a time and build a hidden memory.
VOCABULARY · 3 WORDS
| Index | Word | One-hot |
|---|---|---|
| 0 | was | [1, 0, 0] |
| 1 | not | [0, 1, 0] |
| 2 | bad | [0, 0, 1] |
Vocab size |V| = 3. Hidden dim H = 2. Classes C = 2 (negative, positive).
Initial Parameters (the weights we will learn from)
Wxh (2 × 3)
[-0.1, 0.2, 0.1]]
Whh (2 × 2)
[-0.1, 0.3]]
Why (2 × 2)
[ 0.1, 0.3]]
Biases
by = [ 0.0, 0.0]
Parameters are set. Now we process each word — one timestep at a time, with every number shown.
02 FORWARD PASS
Every Number, Every Step
We initialize h−1 = [0, 0]. At each timestep: at = Wxh·xt + Whh·ht−1 + bh, then ht = tanh(at).
◈ LIVE DEMO
Watch the network think
Step through the forward pass one timestep at a time. See values flow through weights, hidden states update, and the final prediction emerge. Every number is real — from the example above.
Step 1 of 4 — Initialization
Press Next to begin the forward pass.
| 0.20 | 0.10 | −0.10 |
| −0.10 | 0.20 | 0.10 |
| 0.30 | 0.20 |
| −0.10 | 0.30 |
| 0.10 | −0.10 |
| 0.20 | −0.10 |
| 0.10 | 0.30 |
| 0.00 | 0.00 |
Word: "was" · x₀ = [1, 0, 0]
Start with the zero hidden state. The one-hot x₀ selects column 0 of Wxh.
Apply tanh to squash into (−1, 1):
Word: "not" · x₁ = [0, 1, 0]
Now the recurrence kicks in. We multiply Whh by the previous hidden state h₀.
Add the input contribution (column 1 of Wxh) and bias:
Apply tanh:
Word: "bad" · x₂ = [0, 0, 1]
Same computation — Whh·h₁, plus column 2 of Wxh, plus bias.
Softmax Prediction
Use the final hidden state h₂ to compute logits z, then softmax.
Softmax: exponentiate, sum, divide.
The model predicted negative but the true label is positive. Time to compute the loss and blame the right weights.
03 LOSS
Cross-Entropy with Real Numbers
How surprised is the model?
True label y = [0, 1] (positive). Model output ŷ = [0.5040, 0.4960].
Loss = 0.7011. Now we compute which weights are responsible — by propagating gradients backward through every timestep.
04 BACKPROPAGATION
Every Gradient, Every Product
We compute ∂L/∂Wxh, ∂L/∂Whh, ∂L/∂Why, and both biases. Starting from the output and walking back to t=0.
Output Error Signal
For softmax + cross-entropy, the gradient simplifies to ŷ − y.
Gradients for Why and by
Initial Hidden Gradient δ₂
Gradients at t = 2 (word "bad")
First compute the tanh derivative at a₂: (1 − tanh²).
Multiply δ₂ element-wise with the tanh derivative:
Now accumulate gradients. For Wxh, g₂ multiplies with x₂ᵀ = [0, 0, 1] — only column 2 survives:
Backprop to t = 1 (word "not")
Propagate the gradient backward through Whhᵀ:
Apply tanh derivative at a₁:
Backprop to t = 0 (word "was")
Sum Gradients Across All Timesteps
Add the contributions from t=0, t=1, and t=2 for each parameter.
Gradients computed. One final step: apply gradient descent and see the new weights.
05 PARAMETER UPDATE
Gradient Descent: New Weights
Learning rate η = 0.1. We subtract 10% of each gradient from its parameter.
Wxh BEFORE
[−0.1, 0.2, 0.1]]
Wxh AFTER (new)
[−0.0992, 0.2050, 0.1202]]
Whh BEFORE
[−0.1, 0.3]]
Whh AFTER (new)
[−0.0936, 0.2992]]
Why BEFORE
[ 0.1, 0.3]]
Why AFTER (new)
[0.1038, 0.2989]]
BIASES BEFORE
by = [ 0.0, 0.0]
BIASES AFTER (new)
by = [−0.0504, 0.0504]
Notice Why[1,0] increased from 0.1 → 0.1038, and Wxh[1,2] (the weight for "bad"→hidden[1]) increased from 0.1 → 0.1202. The model is learning to boost the positive signal. After many iterations, it would correctly predict POSITIVE.
The complete loop: forward → loss → backprop → update. Let us test your understanding with a quick quiz.
06 KNOWLEDGE CHECK
Verify Your Understanding
Instant feedback — no grades, just clarity. Every answer references the actual numbers above.