Visual walkthrough — Recurrent neural networks — hidden state, BPTT
We keep everything scalar (single numbers, not matrices) so nothing hides behind linear algebra. Once you see it in scalars, the matrix version is the same story with and transposes bolted on.
Step 1 — The chain of memory (WHAT we are differentiating)
WHAT. A recurrent net reads a sequence one item at a time. At step it holds a memory number (the hidden state). It updates that memory using the new input and the old memory , always with the same three numbers :
WHY. We want the loss to go down, so we need to know how much each weight is to blame for the error. The blame is a derivative . Before we can chase that derivative we must see the road the signal travels — that road is the chain below.
PICTURE. Time runs left to right. Each box is a memory ; each black arrow is one use of the same weight ; each red arrow drops an output that gets compared to a target.
Step 2 — Name the pre-activation (WHY we introduce )
WHAT. The wraps a plain linear combination. Give that inside-part its own name:
WHY. The chain rule works one simple function at a time. If we lump the linear part and the squash together we have to differentiate a monster. Splitting at gives us two easy links:
WHY tanh at all? It squashes any number into , so the memory can recirculate forever without blowing up. It also passes through the origin, so a zero input gives a zero-ish memory (a fair starting point). Compare the alternatives in the picture.
PICTURE. Three curves. Only (red) is both bounded and centered at zero — the property we need for a memory that loops.
Recall Why not just drop tanh and stay linear?
Question: what breaks if (no squash)? ::: The whole unrolled net collapses to one big linear map ( becomes a constant times plus input terms), and the gradient becomes pure — guaranteed to vanish or explode with no nonlinearity to control it. See Vanishing and Exploding Gradients.
Step 3 — The single-link derivative: 's twin (WHAT is)
WHAT. To move blame through the squash we need the slope of . A beautiful fact:
So the slope is written using the output we already computed — no new evaluation needed.
WHY. During the backward pass we are standing at and want to step back to . The chain rule says multiply by this slope. Because it equals , and , this slope always lies in : each backward step through can only shrink the signal, never grow it. Hold that thought for Step 6.
PICTURE. The red curve is . It is tallest (=1) at the middle and squashed to 0 at the edges (). A memory that has saturated (pushed to ) passes almost no gradient — it has gone "deaf."
Step 4 — Blame arriving at a hidden state (the heart of BPTT)
WHAT. Define the blame on memory as : how much the total loss changes if we nudge . Because forked into two roads (Step 1), its blame is the sum of blame coming back along each road:
Term by term:
- — the local error this step made through its own output.
- — blame already computed for the next memory (we work right-to-left, so it's ready).
- — the bridge that carries future blame back one step. From Steps 2–3 it is : pass through 's twin, then through the weight.
WHY the sum? This is the multivariable chain rule: a quantity that influences the answer along several paths contributes the sum of the paths. has exactly two paths, so exactly two terms. This is the idea of "back-propagation through time": blame from step is handed to step , then step hands its total to step , and so on backward.
PICTURE. Red arrows flow right to left. At two red arrows merge: a short one from its own output, a long one arriving from . Their sum is .
Step 5 — Blaming the shared weight: sum over all its jobs
WHAT. Now the payoff. The weight was used at every step (every black arrow in Step 1's picture). Its total blame is the sum of what it did at each step. At step its job was to multiply inside , so its local contribution is (blame at , pushed back through the twin to ) times the number it multiplied, :
WHY sum again? Same weight-sharing logic as the sum in Step 4, but now over parameter uses instead of paths. One knob, many jobs add up the blame from every job. This single boxed line is the whole point of the BPTT derivation.
PICTURE. One knob labelled in the center; wires reach out to each time step; the total turn on the knob is the sum of the pulls coming back along every wire.
Step 6 — Edge case: many steps back = a product that dies or explodes
WHAT. How does blame from the final loss reach an early memory? Chain the bridges together. Going from step all the way to step multiplies one bridge per hop:
Each factor is roughly scaled by a number . Call the typical size of one factor . Then a gap of steps multiplies the blame by about .
WHY it matters — cover both signs of :
- (e.g. small , or saturated memories): . Blame from far away vanishes — the net cannot learn long-range dependencies. This is the common case, and why LSTM and GRU exist (they add a near-identity memory path where ).
- (large , unsaturated): . Blame explodes — training diverges. Fixed by gradient clipping.
- (the knife-edge): blame is preserved — exactly the regime gated cells try to engineer.
PICTURE. Three red curves of against the time-gap : one decaying to zero, one flat at 1, one shooting up. Only the flat one keeps memory alive.
Step 7 — Sanity check on real numbers (degenerate + normal case)
WHAT. Run the tiny scalar RNN end-to-end: , inputs , start , target at the last step with .
Forward:
Backward (right to left):
- .
- bridge .
- .
The degenerate first term. Because , the step-1 contribution to is multiplied by zero and vanishes — a clean illustration that the weight only earns blame where it actually multiplied a nonzero memory:
WHY. Every symbol here was defined in Steps 1–5. This number is the boxed formula of Step 5 in action, and it confirms the "sum over steps" structure with one term switched off by the zero initial state.
PICTURE. The two candles of the sum drawn side by side: a grey zero candle (step 1, killed by ) and a red live candle (step 2). Their heights sum to .
The one-picture summary
Everything on one canvas: forward chain across the top, red blame flowing backward along the bottom, and the shared weight collecting a sum of pulls from every step.
Recall Feynman: the whole walkthrough in plain words
You read a sequence one item at a time and keep a single memory number that you refresh with the same rule every step — that rule squashes with so the memory can loop forever without exploding. When the ending is wrong, you walk backward through the whole sequence handing blame from each step to the one before it. At each hand-off you pass the blame through "'s twin" (, always between 0 and 1) and then through the weight. Because that same weight was used at every step, you add up its blame from all of them — "same weight, sum the blame." The catch: walking back many steps multiplies many of those between-0-and-1 factors, so distant blame usually fades to nothing (vanishing gradient) — which is exactly the leak that LSTM and GRU plug. See also Time Series Forecasting and Sequence Modeling in Flight Data for where this memory earns its keep.