Goyalayus

Notes, essays, and fragments from the edge of understanding.

Mathematics behind Exploding and Vanishing Gradients

November 16, 2025

Original Substack post

Have you ever noticed that in a deep learning codebase, weights are rarely initialized as plain ?

You usually see something like this instead:

or sometimes:

In code this often looks like drawing normal random numbers and dividing by the square root of the input dimension.

Why do we do this?

Because if we initialize every weight with variance , then as signals move forward through many layers, and as gradients move backward through those same layers, their scale can multiply again and again. After enough multiplications, the numbers either become huge or almost zero.

That is the exploding and vanishing gradients problem.

This post is the mathematics behind it.

The short version is:

Deep learning is repeated multiplication. Repeated multiplication is controlled by variance, derivatives, Jacobians, and singular values.

Once that sentence becomes obvious, Xavier initialization, He initialization, residual connections, normalization, and gradient clipping all start feeling like the same family of fixes.


Start With One Neuron

Consider a single neuron in one layer. Ignore the bias for now.

or compactly:

Here is the number of input dimensions, usually called .

Let us make three simple assumptions:

  1. The inputs are normalized:
  1. The weights are initialized independently:
  1. The and are independent of each other.

We want to know the variance of .

Since each term is :

Because the weights and inputs are independent and both have mean zero:

and:

Since and :

Now is the sum of independent terms, so variances add:

This is the whole problem in one line.

If we initialize with , then:

So if the layer has 768 inputs, the output variance becomes about 768 after just one linear layer. That is already too large.

To keep the output variance around , we want:

so:

and therefore:

This is the basic statistical reason behind dividing by .


Why This Becomes Worse Across Layers

One layer is not the problem. Deep learning means stacking many layers.

Suppose a simple feed-forward network is:

where is an activation function like tanh, sigmoid, ReLU, or GELU.

If we temporarily ignore the activation, and each layer multiplies variance by some factor , then after layers:

If , activations explode.

If , activations vanish.

If , the network has a chance of preserving signal scale.

This is why tiny errors in scale become massive in deep networks. A factor of seems harmless for one layer, but over 100 layers:

A factor of seems harmless too, but:

So a deep network does not merely care whether a layer is mathematically valid. It cares whether repeated composition keeps signals in a usable numerical range.


Backpropagation Is The Same Problem In Reverse

Now let us look at gradients.

Suppose the loss is and we want gradients with respect to earlier layers.

Backpropagation repeatedly applies the chain rule.

For a network:

we get:

The object:

is the Jacobian of layer .

So the gradient at an early layer is:

Again, repeated multiplication.

This time we are multiplying Jacobian matrices instead of scalar variances.

If this product grows in norm, gradients explode. If this product shrinks in norm, gradients vanish.

That is the mathematical heart of the issue.


The Jacobian Of A Layer

For one layer:

The Jacobian is:

Using the chain rule:

where:

So each layer's Jacobian has two parts:

  1. , the weight matrix.
  2. , the diagonal matrix of activation derivatives.

This is important because gradients can vanish or explode because of either part.

Bad weight scale can break training.

Bad activation derivatives can also break training.

Usually both interact.


Singular Values: The Real Scale Of A Matrix

For scalars, repeated multiplication is easy to understand. If you multiply by many times, you explode. If you multiply by many times, you vanish.

For matrices, the closest idea is singular values.

A matrix stretches some directions and shrinks others. Its largest singular value tells us the maximum stretch:

If the Jacobians have singular values much larger than , gradients can explode.

If the Jacobians have singular values much smaller than , gradients vanish.

For many layers:

is controlled by the product of the singular values along the directions the gradient travels.

A rough bound is:

So even if every layer has maximum singular value only , after 100 layers the upper bound contains:

And if every layer has singular values around :

This is why people often talk about keeping Jacobian singular values near . The ideal is sometimes called dynamical isometry: signals and gradients pass through depth without being crushed or inflated too much.


Eigenvalues: The RNN Version

Eigenvalues become especially intuitive in recurrent neural networks.

A simple RNN has hidden state:

The same recurrent matrix is reused at every time step.

During backpropagation through time, the gradient from time back to time contains products like:

For the RNN:

where:

So:

If we ignore the changing activation derivative for a moment, the core repeated object is:

Now eigenvalues tell the story.

If has an eigenvector with eigenvalue , then:

and after repeated multiplication:

If , that direction explodes.

If , that direction vanishes.

If , that direction can preserve information over time.

This is why vanilla RNNs struggle with long-range dependencies. To remember something from 500 time steps ago, the gradient has to survive hundreds of repeated multiplications.

That is a brutal requirement.


Activation Functions Can Kill Gradients Too

Weights are only half the story. Activations matter because their derivatives appear inside every Jacobian.

Sigmoid

The sigmoid is:

Its derivative is:

The maximum value of this derivative is .

So every sigmoid layer contributes a derivative factor at most .

Across many layers, this is terrible:

This is why old deep networks with sigmoid activations were difficult to train.

Also, sigmoid saturates. For large positive or negative inputs, the output becomes close to or , and the derivative becomes almost zero.

So once a unit saturates, learning through it becomes tiny.

Tanh

Tanh is better than sigmoid because it is zero-centered:

Its derivative is:

The maximum derivative is , but for large , tanh also saturates and the derivative becomes close to zero.

So tanh can still vanish if activations drift into saturation.

ReLU

ReLU is:

Its derivative is:

ReLU helps because positive units pass gradient with derivative .

But roughly half the units may be inactive at initialization if pre-activations are symmetric around zero. Those inactive units have derivative .

So ReLU does not shrink every active path, but it drops many paths entirely.

This is why ReLU networks usually use He initialization instead of Xavier.


Xavier Initialization

Xavier initialization tries to keep variance stable through layers.

For activations that are roughly symmetric and not half-zeroed like ReLU, a common choice is:

or, balancing both forward and backward flow:

The second form is often called Glorot or Xavier initialization.

Why include ?

Forward propagation cares about because each output sums over input dimensions.

Backward propagation cares about because each input receives gradient contributions from output dimensions.

So Xavier balances both directions:

and:

It is not magic. It is variance bookkeeping.


He Initialization

For ReLU, about half the units are zeroed out at initialization.

So if we used:

then the variance after ReLU would roughly be cut in half.

To compensate, He initialization uses:

or:

This keeps the post-ReLU signal variance closer to stable.

In code, this is why you often see:

for ReLU-style networks.

For transformers using GELU, initialization is more architecture-specific, but the same principle remains: keep signal and gradient scales from drifting too fast with depth.


A Tiny Numerical Example

Suppose every layer accidentally multiplies gradient norm by .

After 10 layers:

After 50 layers:

After 100 layers:

That gradient is basically gone.

Now suppose every layer multiplies gradient norm by .

After 10 layers:

After 50 layers:

After 100 layers:

That gradient is unusably large.

So the problem is not that gradients are mysterious. The problem is that exponentials are unforgiving.


Why RNNs Were Especially Painful

Feed-forward networks multiply across depth.

RNNs multiply across time.

A sequence length of 1,000 means the model may need useful gradients across 1,000 recurrent steps.

For a vanilla RNN, the gradient from a late output to an early hidden state contains:

Even if the recurrent matrix is well-scaled at initialization, training changes it. And even if is fine, the activation derivatives can shrink gradients.

This is one reason LSTMs and GRUs were such a big deal. They create gated paths where information can flow additively, not only through repeated nonlinear matrix multiplication.

A simplified LSTM cell state update is:

The old memory is multiplied by a forget gate , but it also has a relatively direct path forward.

The derivative:

If is near , the gradient can pass through many time steps more easily.

This does not make LSTMs perfect, but it explains why they helped long before transformers became dominant.


Residual Connections

Residual connections attack the same problem from another angle.

Instead of making a layer learn:

a residual block does:

Now the Jacobian is:

The identity matrix gives gradients a direct route backward.

So even if is small, the gradient is not forced to pass only through .

This is a major reason very deep ResNets and transformers train at all.

Residual connections do not remove the need for good initialization or normalization, but they make the optimization landscape much more forgiving.


Normalization

Normalization methods also fight scale drift.

BatchNorm normalizes using batch statistics. LayerNorm normalizes within each example across features.

A simplified LayerNorm is:

This keeps activations in a controlled range before the next transformation.

In transformers, LayerNorm is one of the quiet heroes. Without it, residual streams and attention/MLP blocks can drift in scale as depth increases.

There are two common layouts:

Post-norm:

Pre-norm:

Pre-norm transformers are usually easier to train at large depth because the residual path remains more direct.

Again, this is gradient-flow engineering.


Gradient Clipping

Gradient clipping is mostly a fix for exploding gradients.

If the gradient vector is and its norm is too large, we rescale it:

when:

Here is the clipping threshold.

So if the gradient norm becomes and the threshold is , clipping rescales the whole gradient to norm .

This does not solve vanishing gradients. It also does not fix the underlying reason the gradient exploded. But it prevents a single bad update from destroying the model parameters.

RNN training historically used gradient clipping a lot because exploding gradients were common during backpropagation through time.

Modern large-model training also often clips gradients because occasional spikes are normal at scale.


A Concrete Mental Model

Imagine a signal moving through a deep network.

At each layer, three things happen:

  1. The weight matrix stretches or shrinks the vector.
  2. The activation derivative keeps, shrinks, or kills gradient paths.
  3. The next layer repeats the process.

Forward pass:

Backward pass:

The forward pass can lose information if activations collapse or explode.

The backward pass can lose learning signal if Jacobian products shrink or explode.

Training works best when both stay in a reasonable range.

That is why initialization is not a small implementation detail. It determines the starting geometry of learning.


Why Plain Normal(0, 1) Is Bad

Let us return to the original question.

If:

and a layer has inputs, then:

For :

so the standard deviation is:

After one layer, activations are already much larger than the normalized input.

If you use tanh or sigmoid, this pushes units into saturation, where derivatives are near zero. So the forward activations become uninformative and the backward gradients vanish.

If you use ReLU, large activations can propagate and make later layers unstable. Gradients can become huge because matrix products keep stretching them.

So Normal$(0,1)$ is usually wrong not because randomness is bad, but because the randomness has the wrong scale for the number of summed inputs.


The Main Fixes, In One Place

Initialization controls the starting scale:

or for ReLU:

Activation choice controls derivative behavior. Sigmoid and tanh can saturate. ReLU and GELU usually preserve gradients better, but still need good scale.

Normalization keeps activations from drifting too far during training.

Residual connections create direct gradient paths:

Gradient clipping prevents occasional explosions from causing catastrophic updates.

Gated architectures like LSTMs create paths where memory and gradients can survive over time.

All of these are different ways of fighting the same mathematical enemy: bad products of many Jacobians.


Final Intuition

Exploding and vanishing gradients are not random bugs in neural networks.

They are what you should expect when you repeatedly multiply by matrices and activation derivatives.

In a deep feed-forward network, the multiplication happens across layers.

In an RNN, it happens across time.

The gradient is basically carried by a product like:

or for an RNN:

If the product's effective singular values are mostly above , gradients explode.

If they are mostly below , gradients vanish.

If they stay near , learning can flow.

That is why we divide by .

That is why Xavier and He initialization exist.

That is why residual connections, normalization, gates, and clipping are everywhere.

Deep learning works when the model is expressive enough to learn complicated functions, but numerically disciplined enough that the learning signal can actually travel through it.