from d2l import mxnet as d2l
from mxnet import np, npx
npx.set_np()A recurrent neural network carries a hidden state \mathbf{h}_t across time steps, a learned summary of all input seen so far:
\mathbf{h}_t = \phi(\mathbf{W}_{xh}\mathbf{x}_t + \mathbf{W}_{hh}\mathbf{h}_{t-1} + \mathbf{b}).
Same weights at every step, so the parameter count is constant regardless of sequence length. Unbounded effective context (in principle), with no fixed-size window like an n-gram.
An RNN unrolled across three time steps; the same weights are reused at every step.
The naive form: two matrix multiplies, summed:
array([[ 0.9422816 , 0.01977926, -2.6496055 , -2.2366421 ],
[ 1.1883913 , 1.8222132 , -2.8613284 , -4.743068 ],
[-1.6715677 , -2.8657658 , 2.348141 , 3.5657983 ]])
Equivalently, concatenate input and hidden and multiply by the concatenated weight matrix. Same result, one matmul:
array([[ 0.94228166, 0.01977928, -2.6496055 , -2.2366421 ],
[ 1.1883914 , 1.8222132 , -2.8613286 , -4.743068 ],
[-1.6715677 , -2.8657656 , 2.348141 , 3.5657983 ]])
The concatenate-then-multiply form is what most framework RNN implementations actually do.
Targets are the inputs shifted forward by one token; each step predicts the next token.
Train on gold prefixes; generate on the model’s own outputs. That mismatch is the rollout-error problem again.