Weight Initialization › Xavier/Glorot Initialization
Language AI HandbookAll chapters Weight Initialization › Xavier/Glorot InitializationOne section · Sections in this chapter6 / 19 ↓
Reading tools Definitions & inline links
Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.
Article links
Make inline references clickable
Our variance analysis derived the optimal weight variance for forward propagation. But training a neural network involves both forward and backward propagation, and gradients face the same variance amplification problem in reverse.
Xavier Glorot and Yoshua Bengio, in their 2010 paper "Understanding the Difficulty of Training Deep Feedforward Neural Networks," recognized that we must consider both signal directions simultaneously. If we optimize only for forward variance, gradients might explode or vanish during backpropagation. The key insight was that a good initialization must care about the health of the gradient signal just as much as the health of the forward activations, because training depends on both flowing cleanly through the entire network.
Forward and Backward Requirements
The forward pass constraint from our derivation above gives:
where is the fan-in (number of input connections to each neuron).
During backpropagation, gradients flow in the opposite direction. Each input neuron receives gradient contributions from all output neurons. By the same reasoning applied to the gradient equations, maintaining gradient variance during the backward pass requires:
where is the fan-out (number of output connections from each input neuron).
To see why the backward pass requirement involves , recall the chain rule during backpropagation. The gradient of the loss with respect to an input activation is:
This is a weighted sum of gradient terms, structurally identical to the forward pass equation but with fan-out replacing fan-in. The same variance analysis applies, giving the backward requirement .
The Glorot Compromise
We face a dilemma. The forward pass requires , but the backward pass requires . These two constraints conflict whenever , which is the common case for layers that change dimensionality.
Glorot and Bengio proposed taking the harmonic mean of the two fan values:
where:
- : fan-in (input dimension of the weight matrix)
- : fan-out (output dimension of the weight matrix)
- : a compromise variance that partially satisfies both the forward and backward variance preservation constraints
Notice that when , this formula reduces to , recovering the LeCun result. For layers where the input and output dimensions differ substantially, the formula takes a middle path between the two competing requirements. This is an elegant engineering compromise: it is not optimal for either direction alone, but it avoids catastrophically failing in either direction.
This is Xavier initialization (also called Glorot initialization). To sample weights, we convert this target variance to the parameters of either a normal or uniform distribution.
For a normal distribution , the variance is . Setting and taking the square root gives the standard deviation:
Weights are drawn from:
For a uniform distribution , the variance is . Setting and solving for :
Weights are drawn from:
A weight initialization scheme where weights are drawn from a distribution with variance . Designed for networks using symmetric activations like tanh or sigmoid, where the activation function is approximately linear near zero and does not systematically distort variance across layers.
In practice, the uniform variant is the more commonly referenced form, particularly in the original Glorot and Bengio paper. Both versions achieve similar results in practice because the variance formula is the same; only the shape of the distribution differs. The uniform variant is bounded, so it avoids the (very small) probability of drawing a very large outlier weight from the tails of a normal distribution.
Why This Works for Tanh and Sigmoid
The derivation assumes the activation function does not distort the variance of the signal. Tanh and sigmoid satisfy this assumption near zero, where they are both approximately linear. Specifically:
- for small
- for small , with derivative
For tanh, the derivative near zero is approximately 1, meaning the function barely affects variance. For sigmoid, the derivative near zero is about 0.25, which does systematically reduce variance. This is why PyTorch's implementation includes an empirical correction factor of for tanh (accounting for the actual saturation properties) and why some implementations of Xavier for sigmoid include additional adjustment. The original Glorot and Bengio paper noted that sigmoid is more problematic than tanh, because its non-zero mean output shifts the input distribution seen by subsequent layers.
Implementation
def xavier_uniform(shape):
"""Xavier initialization with uniform distribution."""
fan_in, fan_out = shape
limit = np.sqrt(6 / (fan_in + fan_out))
return np.random.uniform(-limit, limit, shape)
def xavier_normal(shape):
"""Xavier initialization with normal distribution."""
fan_in, fan_out = shape
std = np.sqrt(2 / (fan_in + fan_out))
return np.random.randn(*shape) * std
def compare_initializations(n_layers, layer_size, init_func, activation="tanh"):
"""Track activation standard deviation through network with given initialization."""
weights = [init_func((layer_size, layer_size)) for _ in range(n_layers)]
x = np.random.randn(1000, layer_size)
stds = [np.std(x)]
for W in weights:
x = x @ W
if activation == "tanh":
x = np.tanh(x)
elif activation == "relu":
x = np.maximum(0, x)
stds.append(np.std(x))
return stdsActivation standard deviations across layers (tanh network): ------------------------------------------------------------ Naive (std=1.0): Layer 0: std = 0.9999 Layer 2: std = 0.9740 Layer 4: std = 0.9738 Layer 6: std = 0.9740 Layer 8: std = 0.9740 Layer 10: std = 0.9738 Small (std=0.01): Layer 0: std = 1.0004 Layer 2: std = 0.0250 Layer 4: std = 0.0006 Layer 6: std = 0.0000 Layer 8: std = 0.0000 Layer 10: std = 0.0000 Xavier normal: Layer 0: std = 0.9991 Layer 2: std = 0.4858 Layer 4: std = 0.3593 Layer 6: std = 0.2948 Layer 8: std = 0.2531 Layer 10: std = 0.2255 Xavier uniform: Layer 0: std = 1.0009 Layer 2: std = 0.4855 Layer 4: std = 0.3560 Layer 6: std = 0.2921 Layer 8: std = 0.2546 Layer 10: std = 0.2241
Xavier initialization keeps activation standard deviation stable across layers, while naive (too large) and small (too small) initializations diverge in opposite directions.
