RNN
Understanding and investigating the rnn paper.
Standard architectures like cnn and mlp process independent inputs conveniently. There is an assumption that each input is quite independent of the other inputs, i.e. they are independent and indentically distributed (i.i.d). If you feed a picture of cat today and a picture of dog tomorrow, the model treats each as isolated events.
This does not hold well with sequential tasks like time series data or language. Here context dictates the output just as much as the immediate input. For example ‘bank’ has different meanings when used as in ‘river bank’ and ‘institutional bank’.
It is quite difficult to determine the meaning of the word for lack of context. one to many mappings could only made less ambiguous with context.
language, audio, timeseries all are context-dependent.
Beyond context incompatibility, traditional nns also happen to have a structural constraint which having fixed length inputs (X belongs to R of n). They usually take a fixed size vector X. A cnn takes a fixed size pixel grid and mlps require a fixed size feature vector. But a sequences (sentences, audio frames) come with variable lengths T.
How can we introduce memory in nn?
Instead of throwing away previous steps output, if we can pass it along the current input as a ‘state vector’. Here we’ve loosely come around the concept of rnns. Rnn is a network loop that passes a persistent memory vector ht down the timeline with the immediate input.
As quoted in Goodfellow et al; a rnn fundamentally is an unfolded computational graph across time.
To make ‘unfolding’ a lot clearer, we take the temporal loop and construct it into a standard Directed Acyclic Graph (DAG). The fundamental necessity for backpropagation to work is an explicit path from input to output.
The parameter is the model’s running summary of everything it has seen so far. Because is a function of the current input and the previous hidden state , expanding it recursively reveals that encodes , encodes , and encodes the entire sequence history .
In flight, at each time step, the rnn takes in an input and previous hidden state , combines them through their respective shared weights, and runs them through a non-linearity:
This new hidden state is passed forward to the next iteration step. If we want a prediction at step , we pass through an output layer:
One of these steps is considered as one time step.
Sometimes it is called a layer across time too though this is to be noted that it is not literally a separate layer as each iteration uses the same weights. This is one of the defining features of rnn, in standard textbooks it is also called parameter sharing or weight sharing.
Looking backward, without weight sharing, the parameter count would scale linearly with the input and generalization of seq length beyond what was seen during training is also missed out on.
Three questions:
- how do we compute total loss across a seq? To train an rnn, we must compute loss at each time step t (for example cross entropy loss between prediction y’t and gt yt). Total loss for an entire sequence of length T is simply the sum of losses that happened across all time steps.
- How do we compute the gradient for a weight matrix () that is shared across all time steps? And because is shared across all time steps, updating it requires it contribution to loss at each time step t:
- What happens when we backpropagate across long sequences over time? Chain rule across time: Look at a single loss term at step . Since depends on , which depends on , all the way back to , applying the chain rule to yields:
Focus on that middle term, . It represents the gradient flowing backward through hidden states from step down to step . By the chain rule, it expands into a product of Jacobians:
Hitting the Mathematical Wall
Differentiating with respect to gives:
When backpropagating across a long sequence (say ), you multiply by itself 50 times:Vanishing Gradient: If the largest singular value of is less than 1 (or because derivatives are ), multiplying these matrices repeatedly causes the gradient to decay exponentially toward zero. Steps far in the past receive zero gradient update. The model forgets long-term context.Exploding Gradient: If the singular values of are greater than 1, the product explodes exponentially toward infinity, producing NaN or wildly unstable training steps.
The Math behind Gradient Explosion
To see why the gradient vanishes or explodes, we examine the norm of a single term in the overall sum: .
Specifically, we bound the magnitude of the temporal gradient propagation term :
where .
Using the matrix norm inequality , we bound the norm of the Jacobian product by the product of the individual norms:
1. Bounding the Activation Derivative
The derivative of the hyperbolic tangent function is bounded:
Therefore, the spectral norm of the diagonal Jacobian matrix of the activation function is bounded by 1:
2. Bounding the Weight Matrix
Let be the largest singular value (spectral norm) of the weight matrix .
Substituting these bounds back into the inequality yields:
3. Bounding the Term Contributed to the Gradient
Multiplying by the explicit term (which evaluates the immediate derivative at step holding constant):
As the temporal distance grows large:
- Vanishing Gradient (): If :
The gradient decays exponentially to zero as it travels backward through time. Hidden state receives zero parameter updates from loss for large temporal gaps .
- Exploding Gradient (): If and activations remain un-saturated, the bound grows exponentially:
The gradient magnifies exponentially, causing numerical overflow (NaN values) or unstable gradient updates.
mitigation
- Gradient Clipping: exploding gradients don’t change the direction of the gradients, they just scale it to a very large number, causing parameter updates, that either blow up the weights.
Pascanu et al. introduced gradient clipping by norm as a fix here. Before taking the optimizer step, we calculate the l2 norm of the total gradient vector ||g||. if it exceeds a predef threshold , we rescale the entire gradient vector back down:
- Architectural Evolution Clipping fixes the exploding gradients but it can not fix vanishing gradients, you can not scale a gradient that has deacued to exact numerical zero.
In the following years Hochreiter and Schmidhuber redesigned the recurrent cell itself, introducing the LSTM (Long Short-Term Memory).