1. Gradient Explosion: Why Large Gradients Can Lead Training Astray?
First, let's look at vanilla SGD without momentum or weight decay:
is the parameter, is the learning rate, and is the gradient. Suppose and :
| Gradient | Updated Parameter | Update Magnitude |
|---|---|---|
At the time, I calculated that the two update magnitudes differed by , and I realized that in the second case, a single step went too far.
The gradient describes changes near the current position. Taking a sufficiently small step along the negative gradient direction usually decreases the differentiable loss; taking a large step offers no such guarantee. Therefore, a large gradient combined with a fixed learning rate may cause parameters to overstep the appropriate position, actually increasing the loss.
Why does this happen easily in RNNs? Consider a scalar example stripped of inputs and activation functions:
If the terminal gradient is and , backpropagating through three steps gives:
After ten steps, the same multiplicative factor is . This computes the gradient with respect to hidden state; when computing parameter gradients, these backpropagation signals are also used, so parameter gradients may correspondingly grow large.
"Increasing time steps" refers to the backpropagation path spanning more sequence positions, not that increased training epochs necessarily cause explosion. Real vector RNNs involve Jacobian multiplication, and not all paths continuously amplify. This scalar example demonstrates one mechanism.
2. Gradient Clipping: Limit the Length, Preserve the Direction
Initially, I understood clipping as "filtering outliers." More precisely: limit the impact of excessively large gradients, not discard them. Large gradients themselves don't necessarily indicate problematic data.
Organize the gradient to be clipped into a vector , and set the maximum length as . L2 norm clipping is:
For example, has length . With a threshold of :
All components are multiplied by the same positive number, so the direction remains unchanged and the length is scaled to . If we directly changed it to , the ratio would change from to , altering the direction; that is not norm clipping.
Lecture 5, page 44 of the course introduces this method. The referenced paper by Pascanu et al. proposes using gradient norm clipping to address gradient explosion.
Why Not Simply Lower the Learning Rate?
My initial thought was: "Lowering the learning rate only suppresses early updates; it will still explode later." This needs correction: a smaller learning rate shrinks every update, not just the first few. The real difference is that it also shrinks updates from normally-sized gradients.
| Approach | Update Magnitude When | Update Magnitude When |
|---|---|---|
| Learning rate | ||
| Learning rate , clip threshold |
The above still assumes vanilla SGD. Clipping only intervenes when a threshold is exceeded, while a small learning rate uniformly shrinks all updates. The two can also be used together.
Clipping occurs after gradient computation and does not cancel the chain multiplications in backpropagation. It also cannot solve gradient vanishing: is below the threshold , and after clipping remains .
3. LSTM: Retain Old Memories While Writing New Content
Gradient vanishing is not just about "small steps." When loss from later steps propagates to earlier positions, the signal becomes too weak, making it difficult for the model to learn to use information from the distant past.
LSTM maintains a cell state and updates memory through gates:
| Symbol | Meaning |
|---|---|
| Old memory | |
| Forget gate, how much old memory to retain | |
| Candidate memory, content to be written | |
| Input gate, how much candidate content to write |
denotes element-wise multiplication. In practice, these quantities are usually vectors, with each component having its own gate value; we'll compute one component by hand first.
Old memory is , forget gate is , retaining . Candidate memory is , input gate is :
Here can exceed ; the candidate memory component after tanh is within . This example with assumes memory has accumulated previously.
Are Gate Values Manually Fixed?
I then asked: "How are the input gate values defined? Is the forget gate a fixed value?"
They are computed from inputs, context, and trainable parameters:
is sigmoid, mapping finite input to as a passage ratio. For example, when sigmoid input is respectively, outputs are approximately .
Here we use column vector convention: if input dimension is and hidden dimension is , then , , , , ; similarly for other gates.
The same set of parameters is shared across all time steps, but since inputs and contexts differ, gate values can be different. Training updates these parameters; gate values are computed results from each forward pass.
4. Output Gate: Memory Retained Doesn't Mean It's Presented Now
LSTM also has an output gate:
I could compute , but then asked again: "What exactly does this represent?"
Now I've clarified it: is internal memory, is the current hidden state. can be sent to the output layer for predictions and participates in computing next step's gate values and candidate content; continues along the memory path. The standard LSTM's state relationships can be compared with PyTorch LSTM formula.
For example, a language model could compute , then apply Softmax to predict the next word. itself is neither a word nor a probability.
When the output gate is close to , the corresponding component is close to zero, but won't be directly cleared. To retain a memory, not present it for now, and not write new content, we can set the corresponding:
I also corrected a statement: "When the output gate opens, output follows the old memory." In reality, the output gate acts on the updated . The memory just changed to , so the ideal case with output gate corresponds to , not .
To preserve memory approximately unchanged, besides , the new addition term should be near zero, e.g., . Simply keeping the forget gate near could still allow continued writing of new content.
5. Why Can LSTM Alleviate Gradient Vanishing?
Along the path from old memory directly to new memory, the direct local derivative of each component is the corresponding component. Therefore, when five consecutive steps are , the gradient factor along this path is:
Compared to , the signal is preserved much better. My understanding is: " close to better preserves old information; multiplying by each step gradually causes forgetting." Plus backpropagation: gradients also more easily propagate back along this direct path to earlier positions.
This "direct" is important. The complete computation graph also includes dependencies through from gate values and candidate content; we can't reduce the complete derivative to just forget gate multiplication. LSTM provides more favorable propagation paths, but doesn't guarantee gradients never vanish or explode.
6. GRU: Blend Old and Candidate States Using an Update Gate
GRU doesn't maintain separately, but updates . This article adopts PyTorch GRU convention:
is the update gate, is the candidate state. Here, the closer is to , the more old state is retained; the closer to , the more candidate state is used.
Some materials have multiply the candidate state, with opposite notation. When reading, check the formula, not just the gate name.
For example, old state is , candidate state is , :
At the time, I summarized it as "either retain more old state or retain more new input." Here we need to change "new input" to "candidate state": it's not the original , but computed content that can itself contain historical information.
7. What's the Difference Between Reset Gate and Forget Gate?
The reset gate in GRU appears in the generation of candidate state. Continuing with PyTorch notation:
It is multiplied onto the contribution of the old state after transformation. When , the candidate content references history less; when , this portion of historical contribution is allowed to pass through. PyTorch's reset gate placement differs from some original implementations, and this article consistently uses the version above.
The name "reset" initially led me to guess backwards, thinking that wanting to start fresh should mean close to . Only by looking at the position did I realize that here the value represents the passage ratio.
I later asked: "Is its function similar to the LSTM forget gate?" Both control historical information, but at different positions:
| Gate | Position Controlled |
|---|---|
| LSTM | Path where old memory is directly retained to new memory |
| GRU | Contribution of old state when generating candidate state |
| GRU | Retention ratio of old state in final mixing |
So in terms of "directly retaining the old state," in this article's convention is more similar to .
Two combinations helped me truly distinguish them: when , the candidate content references history less, but the final state still mainly retains the old state; when , the final state mainly adopts the candidate state, but the candidate state may still contain processed historical information. Allowing reference to history does not guarantee preserving it unchanged.
8. BPTT: When to Multiply, When to Add?
Gate parameters are learned from task loss; no need to manually annotate correct values for each gate. But does BPTT update parameters at each step every time it backpropagates?
Usually not. Parameters are shared across time steps; BPTT collects and accumulates gradient contributions, which are then updated by the optimizer.
In the Q&A, two time steps' contributions to the same parameter were and , which I mistakenly computed as the product . The correct result should be:
The rule remains: along the same path, local derivatives multiply; when multiple paths converge to the same parameter, contributions add.
Even with loss only from the second step, the shared parameter has different paths:
One path affects loss through , another through . Compute derivatives along each path, then add them.
"Different time steps are different paths" is an introductory understanding. More precisely, parameter usages at different time steps form different paths, and each usage may affect multiple subsequent losses. The gradient contribution of a particular step must already include relevant subsequent propagation; it cannot be omitted or double-counted.
9. Optimizer: Actually Modifying Parameters After Receiving Gradients
BPTT is responsible for computing gradients; the Optimizer is responsible for using gradients to update parameters. The simplest example is still ordinary SGD:
Contributions from three time steps are ; total gradient is . If the parameter is and learning rate is :
In the next round, if the gradient is :
Negative gradient causes the parameter to increase. The updated parameters are used in the forward computation of all time steps in the next iteration. This computation corresponds to SGD without momentum, weight decay, or other extra terms.
Momentum and Adam further utilize historical information to determine updates, but here I've only established the optimizer's responsibility and basic SGD computation without expanding these algorithms.
10. The Training Loop Connected This Round
A typical training iteration can be read straight through: clear previous gradients → compute states, gate values, and predictions in forward pass → compute task loss → BPTT computes and accumulates gradients of shared parameters → clip if necessary → Optimizer updates parameters.
In practice there are also arrangements like gradient accumulation across batches and truncated BPTT, so "only update after the entire sequence ends" shouldn't be treated as the only approach. The core division of labor remains unchanged: computing derivatives and updating parameters are separate steps.
Three points I most want to remember from this round: clipping limits overly large gradients but cannot restore vanished signals; gating allows the model to learn how to retain and use history, but gate values are not parameters; during backpropagation, multiply along paths and add when summing contributions to shared parameters.
Next time I see a complex formula, I'll ask first: which path does this quantity control? Is it a state computed right now, or a parameter to be updated during training? This is more reliable than just memorizing gate names.