from d2l import tensorflow as d2l
import tensorflow as tfA 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:
<tf.Tensor: shape=(3, 4), dtype=float32, numpy=
array([[ 0.7755375 , -1.208179 , -1.6591846 , -2.4052882 ],
[ 0.02714421, -1.4046688 , -2.6365745 , 0.47089213],
[ 1.5235438 , -0.9392809 , 2.6694849 , 2.1848555 ]],
dtype=float32)>
Equivalently, concatenate input and hidden and multiply by the concatenated weight matrix. Same result, one matmul:
<tf.Tensor: shape=(3, 4), dtype=float32, numpy=
array([[ 0.7755375 , -1.208179 , -1.6591846 , -2.4052885 ],
[ 0.02714423, -1.4046689 , -2.6365743 , 0.4708921 ],
[ 1.5235437 , -0.939281 , 2.6694846 , 2.1848555 ]],
dtype=float32)>
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.