Activations and initialization from variance propagation
Before this lesson: lesson 01 (the MLP), lesson 03 (the backward pass, and ). From other tracks: the variance of a sum of independent random variables and expectations under a normal distribution (probability-and-statistics track); singular values (linear-algebra lesson 08) for one advanced box. Time: about 65 minutes, plus the notebook.
Why this matters #
- Deep networks train or fail on these choices. Before 2010, deep networks with sigmoid units and badly scaled weights did not train well. ReLU activations and initialization derived from the variance argument (Glorot and Bengio 2010; He et al. 2015) were key steps towards very deep networks.
- The same variance argument appears everywhere. It explains the factor in attention (lesson 09), GPT-2's scaled residual weights, and the role of normalization (lesson 05).
- Modern architectures. GELU is the activation of BERT, GPT-2 and ViT. SwiGLU is the feed-forward layer of PaLM and the LLaMA family, and "why is its width ?" is a standard interview question.
- Hyperparameter transfer. μP (maximal update parametrization) extends the same reasoning to the size of the updates, so that a learning rate tuned on a small model works on a large one.
1. Predict first #
2. The picture #
One unit: variances add #
Take one unit with inputs: . Assume the weights are independent, with mean 0 and variance , and independent of the inputs . Then each term has mean 0 and variance , and the terms are uncorrelated. Variances of uncorrelated terms add:
So each layer multiplies the size of the signal by a factor. With factor 1 the signal keeps its size through any depth. With factor it halves in every layer. With factor 2 it doubles. Over layers the factor is raised to the power : the change is exponential in depth.
The activation enters this factor through . For ReLU, half of the inputs are set to 0, and . So with the factor is per layer, and with it is exactly 1. That is He initialization.
The backward pass has the same structure. The gradient goes through and is multiplied by , so its factor contains . A saturating activation has for large , so the gradient can vanish even when the forward signal is fine.
Choose an activation and an initialization. A 50-layer MLP of width 200 runs on 32 random inputs, and the figure updates after each change. The top chart shows the mean square of the pre-activations (forward, blue) and of the gradients (backward, orange) at each layer, on a log axis. The dashed aqua lines are the variance recursion of section 3. The bottom chart is the histogram of the activations at the layer you select. Try ReLU with Xavier, then with He. Then try tanh with a large gain and look at the histogram: most units are saturated.
A ReLU layer has fan-in . What is the standard deviation of He initialization?
He initialization sets the variance to , so the standard deviation is . The first option is the variance, not the standard deviation. The third is LeCun initialization, and the last is Xavier for a square layer; both shrink a ReLU signal by per layer.
3. Definitions and main results #
3.1 Activation functions #
The activation function is applied entry by entry after each linear layer. The table uses for the logistic sigmoid, and , for the CDF and the density of the standard normal distribution.
| Name | Notes | ||
|---|---|---|---|
| ReLU | PyTorch uses ; positively homogeneous | ||
| leaky ReLU | for , else | or | small slope, e.g. |
| sigmoid | maximum at 0; | ||
| tanh | |||
| GELU | minimum at | ||
| SiLU (Swish) | minimum at |
Pick an activation and move the input scale . The curve is (blue), its derivative is (orange), and the magenta band marks where : there the unit is saturated (or dead) and passes almost no gradient. The grey bell is the distribution of the input . The panel shows the two numbers that enter the variance recursion, (forward) and (backward). Compare tanh at and at .
- ReLU passes gradient 1 for , so it does not saturate for positive inputs. It gives sparse activations (many exact zeros). It is positively homogeneous: for . So the factor below holds at every scale of . For tanh the factor depends on .
- Saturation. For large the sigmoid and tanh are flat, so . Through sigmoid layers the gradient is multiplied by factors (times the weights), and . Sigmoid outputs are also not centered at zero. This vanishing gradient problem made early deep networks hard to train; recurrent networks have the same problem over time (lesson 08).
- Dead ReLU. A ReLU unit whose pre-activation is negative for every training input outputs 0 and gets zero gradient for its incoming weights and bias. So these weights stop changing, and the unit usually stays dead (it can come back only if the layers below change its inputs). Causes: a large update (a high learning rate, a loss spike) that pushes its weights or bias far negative, or a bad initialization. Fixes: a lower learning rate or a warmup, a leaky ReLU, GELU or SiLU, or normalization before the activation.
- GELU (Gaussian error linear unit; Hendrycks and Gimpel 2016) multiplies its input by the
probability that a standard normal variable is below it: . It is a smooth gate.
PyTorch also offers a tanh approximation,
approximate="tanh". - SiLU (sigmoid linear unit, also called Swish) is . GELU and SiLU are smooth and not monotone. They have a nonzero gradient for moderately negative inputs and are close to ReLU for large .
- Smoothness matters in ML for science. A ReLU network is piecewise linear, so its second derivative is zero almost everywhere. A physics-informed loss that contains then gets no useful signal. Use tanh, SiLU, GELU or sine activations there.
What is the derivative of the logistic sigmoid at ?
and , so . This is the largest value of . The value is itself, not its slope. So each sigmoid layer multiplies the backward signal by at most .
3.2 Gated linear units and SwiGLU #
A gated linear unit (GLU; Dauphin et al. 2017) multiplies a linear branch entry by entry by a gate: . Shazeer (2020) put variants of it into the transformer feed-forward network (FFN), without biases:
Here is the model width and the hidden width of the FFN.
- Why it may help. The product creates multiplicative (second-order) interactions between features, and the gate can switch features on and off for each input.
- The evidence is empirical. At equal parameters and compute, GEGLU and SwiGLU had the best held-out log-perplexity in Shazeer's T5 experiments (1.942 and 1.944 after 65,536 steps, against 1.997 for the ReLU FFN) and better fine-tuning scores. PaLM and LLaMA adopted SwiGLU. There is no accepted theory for why it works better.
- Parameter matching. A GELU FFN of width has weights. SwiGLU has three matrices, weights. Equal counts give , so . The FLOPs match too, because a matmul costs 2 FLOPs per weight per token. Implementations round up: LLaMA takes and rounds it up to a multiple of 256 (for : ).
Move the hidden width (in units of ) and pick a model width. The lines are the weight counts of a GELU FFN (two matrices) and of a SwiGLU FFN (three matrices); the dashed aqua line is the budget of a GELU FFN of width . The SwiGLU line meets the budget at (yellow point). Switch on rounding to see the widths that LLaMA models use.
A transformer has model width . Which SwiGLU hidden width has the same number of FFN weights as a GELU FFN of width ?
The GELU FFN has weights. SwiGLU has , so . With SwiGLU would have 1.5 times more weights, and the comparison would not be fair.
3.3 The variance recursion #
Setting. Use the row convention of this track: layer computes , with and , where is the width of layer (the fan-in of ; is its fan-out). Unit computes . Assume, at initialization:
- the are independent, with mean 0 and variance ;
- they are independent of (true at initialization, because depends only on earlier layers);
- the biases are 0;
- the units of layer have the same second moment for every (true for because the units are exchangeable; otherwise read it as the average over );
- is symmetric around 0, that is and have the same distribution (true when the weights are symmetric). Only the ReLU step below uses this.
Theorem (forward variance). .
Proof.
- , by independence (2) and (1).
- So, again by (2),
- For , by (1), so the cross terms vanish. For it is .
- Hence by (4).
Note that the formula has , not . ReLU outputs have a positive mean, and it counts.
He (Kaiming) initialization, for ReLU. Let . Since is symmetric (5), , and the two add up to . So
using (step 1 of the proof). Then , and the variance stays the same if and only if . Over depth,
Any constant factor per layer gives : exponential in depth.
LeCun initialization, for linear units (or tanh near 0). If , then , and the condition is : .
The backward pass has the same recursion
Let (one row of in lesson 03). The backward rule reads, for unit of layer ,
Assume also that is independent of and of . (This is the standard approximation; it is not exact, because depends on .) The four steps of the forward proof, now with a sum over the units above, give
For ReLU, , so the backward condition is (He initialization in "fan-out mode"). For linear units it is .
Xavier (Glorot) initialization. The forward condition wants and the backward condition wants (for linear or tanh units near 0). Both hold only if . Glorot and Bengio (2010) take the compromise
which is the harmonic mean of the two conditions. (The ReLU analogue would be .)
One condition is enough. With the forward condition (ReLU), the backward factor per layer is . Over the whole network the product telescopes:
a bounded change, not an exponential one (He et al. 2015, §2.2).
Uniform versions and library defaults. A uniform distribution has variance , so
. Xavier uniform: . He
uniform: . For a convolution, the fan-in is
(input channels times kernel size). PyTorch's default for nn.Linear and
nn.Conv* is , a variance of :
neither LeCun nor He.
3.4 What goes wrong #
Zero or constant initialization. Suppose all units of a hidden layer start with the same incoming weights and bias and the same outgoing weights. Then they compute the same function, so they get the same gradient: a unit's gradient depends on the unit only through these weights. After the update they are still equal. This is true after every step, so the layer acts like one unit. This is the symmetry problem, and random initialization is how we break the symmetry.
All-zero weights and biases in a ReLU or tanh MLP are even worse. Every hidden activation is . So , and because . Only the output bias gets a gradient, and the network stays in this state. Biases can start at 0, because random weights already make the units different.
Press Play with "identical" start, then with "identical + δ". A network with 2 inputs, 2 hidden tanh units and 1 output learns XOR by gradient descent. The plane shows, for each hidden unit, its bias and its outgoing weight during training: unit 1 (violet) and unit 2 (yellow). With an identical start the two paths lie on top of each other for ever and the loss stops near 0.67. A tiny difference δ grows until the units separate and the loss falls to 0. Smaller δ takes longer.
An MLP with ReLU hidden layers starts with all weights and biases equal to zero and is trained with SGD. What happens?
Every hidden activation is , so . The gradient that reaches the hidden layers is because . So no weight ever moves; only the output bias learns, and the network can only predict the class frequencies. (With a nonzero constant, the second option describes what happens.)
Xavier in a deep ReLU network. For square layers Xavier gives . The factor is per layer, forward and backward. After 50 layers the variance is about of its first value.
LeCun with tanh decays slowly. With and , the recursion is for . For small , , so (using ). Then falls like , not geometrically: after 50 layers it is about .
Second moments for : (ReLU), (GELU), (SiLU), (tanh). A weight variance keeps unit variance: for ReLU, about for GELU.
Beyond the average: the spread of the singular values
The variance recursion controls the average size of the signal. It does not control the shape of the input–output Jacobian . In a deep linear network with Gaussian weights of variance , the mean squared singular value of stays near 1, but the singular values spread out with depth: for width 200 and 50 layers, the largest is about 7 and the smallest about . Some directions explode and others vanish, and the condition number of is huge (linear-algebra lesson 08). With orthogonal initialization (, from the QR decomposition of a Gaussian matrix), the Jacobian of a deep linear network is a product of orthogonal matrices, so all its singular values are exactly 1. This is called dynamical isometry (Saxe et al. 2014). Pennington, Schoenholz and Ganguli (2017) showed that orthogonal weights with tanh near the critical scale can keep the singular values close to 1, while a ReLU network cannot reach isometry with any weight distribution.
μP: initialization is not enough
The standard parametrization (SP) initializes every layer with variance and uses one global learning rate. In SP the best learning rate shifts as the width grows, so a value tuned on a small model does not transfer to a large one (Yang et al. 2022).
Why, in the simplest case (Adam). An Adam update has entries of size about (the learning rate), whatever the scale of the gradient. For a hidden layer, the change of the output, , is a sum of terms. These terms are correlated with , because the gradient is an outer product of and the upstream gradient. So they add up coherently: , not . The initialization fixes only the size of at step 0; it says nothing about the size of the updates. Keeping of order 1 at every width needs .
μP (maximal update parametrization; Yang and Hu 2021; Yang et al. 2022, Table 3), for Adam:
| input weights, all biases | hidden weights | output weights | |
|---|---|---|---|
| init variance | (SP: ) | ||
| Adam learning rate | independent of width | (SP: independent) | (SP: independent) |
μP transformers also scale attention logits by instead of : after training, and are correlated, so grows like , not . The goal is that the features of every layer change by an amount of order 1 per step as the width goes to infinity: no layer blows up and none freezes. μTransfer: tune the hyperparameters on a narrow proxy model in μP and copy them to the wide model without tuning it. Yang et al. (2022) tuned a 40M-parameter proxy and transferred its hyperparameters to a 6.7B GPT-3 model. μP is about width; transfer across depth needs more (scaling of the residual branches) and is still an active research topic.
Answers to section 1. (1) About . The first layer gives , and then each ReLU layer multiplies by , so . (2) .
4. Worked example #
(a) Activations at . We need , and .
- GELU: value . Derivative . It is negative because GELU is not monotone there.
- SiLU: value . Derivative .
- ReLU: value 0 and derivative 0. At a ReLU unit passes no gradient; GELU and SiLU do.
(b) Initialization of a BERT-base FFN layer, fan-in 768, fan-out 3072.
- LeCun std: . He std: .
- Xavier normal std: . Xavier uniform bound: .
- PyTorch default: bound , so std .
(c) Depth. 50 square ReLU layers with Xavier: factor per layer, so . The gradients vanish in the same way. With He the factor is 1.
(d) SwiGLU at . The GELU FFN of width has weights. SwiGLU with has weights. ✓ This is exactly Shazeer's setup: for the two-matrix FFNs and for the GLU variants.
A convolution maps 64 input channels to 128 output channels and is followed by ReLU. What is the He standard deviation (fan-in mode)?
Each output value sums over inputs, so the fan-in is 576, not 64. The third option uses the fan-out (He fan-out mode), and the last one is Xavier, which is too small for ReLU.
5. In code #
NumPy and SciPy check the numbers of the worked example and the depth effect. The notebook has these cells and the exercises.
import numpy as np
from scipy.stats import norm
s = lambda x: 1 / (1 + np.exp(-x))
x = -1.0
print(round(x * norm.cdf(x), 4), round(norm.cdf(x) + x * norm.pdf(x), 4)) # GELU: -0.1587 -0.0833
print(round(x * s(x), 4), round(s(x) * (1 + x * (1 - s(x))), 4)) # SiLU: -0.2689 0.0723
rng = np.random.default_rng(0)
z = rng.standard_normal(10**6)
print(round(np.mean(np.maximum(z, 0) ** 2), 2)) # 0.5 = E[relu(z)^2] for z ~ N(0, 1)
# (b) standard deviations for fan-in 768, fan-out 3072
fi, fo = 768, 3072
print([round(float(v), 4) for v in (np.sqrt(1 / fi), np.sqrt(2 / fi), np.sqrt(2 / (fi + fo)), 1 / np.sqrt(3 * fi))])
# [0.0361, 0.051, 0.0228, 0.0208] LeCun, He, Xavier, PyTorch default
# (c) 50 ReLU layers of width 500: variance of the last pre-activation
for name, v in [("Xavier", 1 / 500), ("He", 2 / 500)]:
A = rng.standard_normal((200, 500))
for _ in range(50):
Z = A @ (rng.standard_normal((500, 500)) * np.sqrt(v))
A = np.maximum(Z, 0)
print(name, f"{np.mean(Z**2):.1e}") # Xavier 1.5e-15 (about 2^-49), He 1.8e+00 (about Var(z_1) = 2)
# (d) SwiGLU width at the parameter count of a 4d FFN
d = 768
print(2 * d * 4 * d, 3 * d * (8 * d // 3)) # 4718592 4718592
In PyTorch, nn.init.calculate_gain("relu") returns , the factor in He's standard deviation
, and a fresh nn.Linear(768, 3072) has weight standard deviation
about (the default, not He). The notebook checks both when PyTorch is installed.
6. Where it shows up #
- Language and vision models. GELU in BERT, GPT-2 and ViT; SwiGLU in PaLM and the LLaMA family.
- Transformer initialization. GPT-2 scales the weights of the residual output projections at initialization by for residual layers (nanoGPT uses standard deviation for them). So the variance of the residual stream does not grow with depth (lesson 05). DiT's adaLN-Zero starts each block as the identity map.
- Attention. The scores are sums of products, so their variance is when and have unit-variance entries. Dividing by brings it back to 1 (lesson 09).
- ML for science. Losses of physics-informed networks need second derivatives, hence tanh, SiLU or sine activations. SIREN (a network with sine activations) draws its weights from a uniform distribution scaled with , so that the input of each sine is close to : the same argument with a different .
- Porting code between frameworks. Defaults differ: PyTorch's
nn.Linearuses , Flax'snn.Denseuses LeCun normal. A model moved from one to the other starts from a different scale unless you set the initializer explicitly.
7. Common mistakes #
- instead of in the recursion. For ReLU the mean is not zero.
- Standard deviation vs variance. He std is ; is
the variance.
torch.randn(...) * stdneeds the standard deviation. - Xavier for deep ReLU networks. Xavier is derived for linear or tanh units; with ReLU it halves the variance in every layer.
- Assuming PyTorch's default is He.
nn.Linearuses , variance . - Conv fan-in . It is .
- "A good initialization is enough." The size of the updates also depends on the width: that is the point of μP.
- Comparing SwiGLU and GELU FFNs at the same . SwiGLU then has 1.5 times more parameters.
8. Check yourself #
- Why does a 10-layer sigmoid network train badly even with good weight scales?
Answer
Each layer multiplies the backpropagated gradient by , so the factor from the activations alone is at most . Saturated units give , which is even worse. - Which weight variance keeps unit pre-activation variance for GELU when ?
Answer
. - Why does need to be symmetric?
Answer
The proof splits into the parts with and and uses that they are equal. If has a positive mean or is skewed (for example with a large positive bias), more than half of the second moment lies on the positive side, and the factor is larger than . - All weights of an MLP with a softmax cross-entropy output are set to 0.5. At step 0 the first-layer gradient is exactly zero. Why?
Answer
All entries of are 0.5, so the entries of are , because both and sum to 1. Even after the output layer moves, the hidden units stay identical (symmetry). - He initialization (forward condition) is used in a network whose widths shrink from to . How does the gradient variance change over the whole network?
Answer
The backward factor per layer is , and the product telescopes to . A bounded change, not an exponential one. - You double the width of a hidden layer trained with Adam. In μP, how do its initialization variance and its learning rate change, and why?
Answer
The initialization variance halves, and the learning rate also halves (), because the change sums twice as many coherent terms.
Write the forward variance recursion of an MLP at initialization.
, with the fan-in and the weight variance.
What is He initialization, and for which activation is it derived?
Weight variance (std ), for ReLU.
What is Xavier (Glorot) initialization?
Weight variance : a compromise between the forward and the backward condition for linear or tanh units.
Why is ?
If is symmetric with mean 0, the positive half carries exactly half of , and ReLU keeps only that half.
What is the largest value of the sigmoid's derivative, and where?
, at , since .
What is a dead ReLU unit?
A unit whose pre-activation is negative for every training input. It outputs 0 and gets zero gradient, so it never recovers.
Write GELU and SiLU.
(standard normal CDF); (logistic sigmoid).
Why does a SwiGLU FFN use hidden width ?
It has three matrices; (the weights of a GELU FFN of width ) gives .
Why does a constant initialization fail?
Units with equal weights compute the same function and get the same gradient, so they stay equal after every update: the layer acts like one unit.
By what factor does Xavier initialization change the variance per layer in a square ReLU network?
(since ), so 50 layers give about .
9. Interview angle #
- "Why ReLU rather than sigmoid? What is GELU? What is a dead ReLU and how do you fix it?" Sigmoid saturates and its derivative is at most ; ReLU passes gradient 1 for positive inputs. GELU is , a smooth version. A dead ReLU is negative for all inputs; fix it with a lower learning rate, warmup, leaky ReLU, GELU or normalization.
- "Derive He initialization." Variances add: , and , so .
- "Why not initialize all weights to zero?" Symmetry: equal units stay equal. With zero weights the hidden activations and the hidden gradients are exactly zero.
- "Why is LLaMA-7B's FFN width 11008?" for is , rounded up to a multiple of 256.
- "How would you tune a model you can train only once?" μP and μTransfer from a narrow proxy model.
10. Practice #
The notebook for this lesson runs in Colab. Its exercises use NumPy; PyTorch is used as a reference when it is installed.
- Write ReLU, sigmoid, tanh, GELU and SiLU with their derivatives, and check the derivatives with central differences.
- Estimate and by Monte Carlo and compare with .
- Write
init_std(name, fan_in, fan_out)andpreactivation_variances(...), and plot the variance through 50 layers for LeCun, Xavier and He with ReLU and tanh. - Train a small network from a constant initialization and show that its hidden units stay identical; then break the symmetry.
- Write a SwiGLU FFN in NumPy with the parameter count of a GELU FFN of width .
11. Watch and read #
- Simon Prince, Understanding Deep Learning (free PDF): chapter 3 (activation functions) and chapter 7, §7.5 (parameter initialization, forward and backward).
- Zhang, Lipton, Li and Smola, Dive into Deep Learning, §5.4 Numerical stability and initialization.
- Glorot and Bengio, Understanding the difficulty of training deep feedforward neural networks (2010).
- He, Zhang, Ren and Sun, Delving deep into rectifiers (2015): He initialization, §2.2.
- Hendrycks and Gimpel, Gaussian error linear units (GELUs) (2016).
- Shazeer, GLU variants improve Transformer (2020), §2–3.
- Yang et al., Tensor Programs V: Tuning large neural networks via zero-shot hyperparameter transfer (2022), §2–4 and Table 3.
Runs in your browser with nothing to install. The notebook repeats the key demos and has exercises with checks; solutions are inside, folded.
No Google account needed: Python runs inside your browser. The first start downloads about 40 MB; your changes are saved in this browser only.