Forward.h1=tanh(1.0)=0.7616, h2=tanh(0.5⋅0.7616+0.5)=tanh(0.8808)=0.7068.
Why: apply the forward line twice; each memory feeds the next.
Backward, last step.δ2=h2−0.3=0.4068.
Why: the last step has no future, so δ2 is purely the local loss slope.
Backward, step 1.δ1=(h1−0.5)+0.5(1−h22)δ2=0.2616+0.5(0.5006)(0.4068)=0.3634.
Why: two sources — local loss 0.2616 plus the future loss squeezed by the tanh gate and the weight.
Weight gradient.δ^2=0.4068(1−0.70682)=0.2036, δ^1=0.3634(0.4200)=0.1526.
∂L/∂Whh=δ^1h0+δ^2h1=0+0.2036⋅0.7616=0.1551.
Why: multiply each pre-activation gradient by the memory that entered that step.
Verify:h0=0 deletes step 1's contribution, so only step 2 counts. 0.1551=0.310 — the wrong (no-tanh) answer would be 0.4068⋅0.7616=0.310, exactly double. ✓ (matches parent).
Forward.h1=tanh(1.5⋅0+1.0)=tanh(1.0)=0.7616. h2=tanh(1.5⋅0.7616+0.5)=tanh(1.6424)=0.9277.
Why: bigger Whh pushes the pre-activation higher, so h2 is closer to 1.
δ2.δ2=0.9277−0.3=0.6277.
δ1.(1−h22)=1−0.8607=0.1393. δ1=(0.7616−0.5)+1.5(0.1393)(0.6277)=0.2616+0.1312=0.3928.
Why: even though h2 is starting to saturate (small gate 0.1393), the large weight 1.5 partly compensates.
Verify: the un-gated future multiplier Whh=1.5>1 would explode the chain, but the tanh gate 0.1393 tames it here — this is exactly why LSTMs replace the gate. ✓
Forward.h1=tanh(1.0)=0.7616. h2=tanh(−0.5⋅0.7616+0.5)=tanh(0.1192)=0.1186.
Why: the negative recurrent term subtracts the past memory, so h2 lands near zero.
δ2.δ2=0.1186−0.3=−0.1814 (negative — the state is below target).
δ1.(1−h22)=0.9859. δ1=0.2616+(−0.5)(0.9859)(−0.1814)=0.2616+0.0894=0.3510.
Why: two negatives multiply to a positive, so the future term adds here — sign bookkeeping matters.
Verify: gradient is negative — gradient descent will increaseWhh (make it less negative), pulling h2 up toward 0.3. Direction makes physical sense. ✓
Verify: the gradient w.r.t. Whh is non-zero even though Whh=0 — that is correct! The gradient measures the effect of turning the link on, i.e. ht−1 still multiplies into the weight slot (h1=0.7616). A zero weight is not a zero derivative. ✓
Forward.h1=tanh(3.0)=0.9951. h2=tanh(1.0⋅0.9951+3.0)=tanh(3.9951)=0.99933.
Why: large pre-activations push tanh onto its flat tails.
δ2=0.99933−0.9=0.09933.
Gate at step 2:(1−h22)=1−0.99866=0.00134. δ1=(0.9951−0.9)+1.0(0.00134)(0.09933)=0.0951+0.000133=0.09523.
Why: the future term is crushed to ∼10−4 because the gate is nearly zero.
Verify: gradient ≈1.3×10−4, essentially zero despite a real loss — saturation ⇒ dead gradient. This is whyLSTMs and GRUs add un-squashed carry paths. ✓
Forward (same weights/inputs as Ex 1): h1=0.7616, h2=0.7068.
δ2=0.7068−(−0.2)=0.9068.
δ1=(0.7616−(−0.4))+0.5(1−0.70682)(0.9068)=1.1616+0.5(0.5006)(0.9068)=1.1616+0.2270=1.3886.Why: the mismatch is now huge (1.16 locally), and the future term adds more.
Verify: far larger than Ex 1's 0.1551 (bigger error ⇒ bigger gradient), and positive, so descent lowers Whh-driven output toward the negative targets. Consistent. ✓
δ1.(1−h22)=0.5006. δ1=(0.7616−0.5)+0.5(0.5006)(0.5573)=0.2616+0.1395=0.4011.
Why:δ2 already carries step-3's loss, so passing it back gives δ1 its share of all three losses.
Verify: with h0=0 only the last two terms survive; both positive and comparable, giving ≈0.425. Each backward hop shrank the future term (0.15,0.14) — a live preview of why very long sequences lose signal. ✓
Recall Self-test: predict before you compute
If Whh=0, is ∂L/∂Whh necessarily zero? ::: No — the incoming memory ht−1 still multiplies the weight slot; a zero weight has a non-zero derivative (Ex 4 gave 0.097).
Which factor turns a live loss into a nearly-dead gradient? ::: The saturation gate (1−ht2)→0 when ht→±1 (Ex 5).
When does the future term make δ1smaller than its local part? ::: When Whh or δt+1 is negative, so the future contribution subtracts (Ex 3, Ex 7).
Why must the weight gradient use δ^t and not δt? ::: Because Whh feeds the pre-activation; you must pass back through tanh, whose slope is (1−ht2) — skipping it doubled the answer in Ex 1.