Type at least 2 letters. Enter opens the first result, Esc closes.

    Deep Learning · Lesson 4 · Making deep networks trainable

    Activations and initialization from variance propagation

    Intermediate 65 min 4 interactive figures 3 videos Colab notebook

    Before this lesson: lesson 01 (the MLP), lesson 03 (the backward pass, GlG_l and σ′\sigma'). 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 1/dk1/\sqrt{d_k} 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 8d/38d/3?" 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 nn inputs: z=∑i=1naiwiz = \sum_{i=1}^{n} a_i w_i. Assume the weights wiw_i are independent, with mean 0 and variance vv, and independent of the inputs aia_i. Then each term aiwia_i w_i has mean 0 and variance v E[ai2]v\,\mathbb{E}[a_i^2], and the terms are uncorrelated. Variances of uncorrelated terms add:

    Var⁡(z)=n v E[a2].\operatorname{Var}(z) = n\, v\, \mathbb{E}[a^2].

    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 1/21/2 it halves in every layer. With factor 2 it doubles. Over LL layers the factor is raised to the power LL: the change is exponential in depth.

    The activation enters this factor through E[σ(z)2]\mathbb{E}[\sigma(z)^2]. For ReLU, half of the inputs are set to 0, and E[relu⁡(z)2]=12Var⁡(z)\mathbb{E}[\operatorname{relu}(z)^2] = \tfrac12 \operatorname{Var}(z). So with v=1/nv = 1/n the factor is n⋅1n⋅12=12n \cdot \tfrac1n \cdot \tfrac12 = \tfrac12 per layer, and with v=2/nv = 2/n it is exactly 1. That is He initialization.

    The backward pass has the same structure. The gradient goes through W⊤W^\top and is multiplied by σ′(z)\sigma'(z), so its factor contains E[σ′(z)2]\mathbb{E}[\sigma'(z)^2]. A saturating activation has σ′(z)≈0\sigma'(z) \approx 0 for large ∣z∣|z|, so the gradient can vanish even when the forward signal is fine.

    Interactive figure: loading…

    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 ∂L/∂zl\partial\mathcal{L}/\partial z_l (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 σ(zl)\sigma(z_l) 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.

    Quick check

    A ReLU layer has fan-in n=512n = 512. What is the standard deviation of He initialization?

    3. Definitions and main results #

    3.1 Activation functions #

    The activation function σ\sigma is applied entry by entry after each linear layer. The table uses s(x)=1/(1+e−x)s(x) = 1/(1 + e^{-x}) for the logistic sigmoid, and Φ\Phi, φ\varphi for the CDF and the density of the standard normal distribution.

    Name σ(x)\sigma(x) σ′(x)\sigma'(x) Notes
    ReLU max⁡(0,x)\max(0, x) 1[x>0]\mathbf{1}[x > 0] PyTorch uses σ′(0)=0\sigma'(0) = 0; positively homogeneous
    leaky ReLU xx for x>0x > 0, αx\alpha x else 11 or α\alpha small slope, e.g. α=0.01\alpha = 0.01
    sigmoid s(x)s(x) s(x)(1−s(x))≤1/4s(x)(1 - s(x)) \le 1/4 maximum 1/41/4 at 0; s′(5)≈0.0066s'(5) \approx 0.0066
    tanh tanh⁡x\tanh x 1−tanh⁡2x≤11 - \tanh^2 x \le 1 tanh⁡′(3)≈0.0099\tanh'(3) \approx 0.0099
    GELU x Φ(x)x\,\Phi(x) Φ(x)+x φ(x)\Phi(x) + x\,\varphi(x) minimum ≈−0.170\approx -0.170 at x≈−0.752x \approx -0.752
    SiLU (Swish) x s(x)x\, s(x) s(x) (1+x(1−s(x)))s(x)\,(1 + x(1 - s(x))) minimum ≈−0.278\approx -0.278 at x≈−1.278x \approx -1.278
    Interactive figure: loading…

    Pick an activation and move the input scale ss. The curve is σ(x)\sigma(x) (blue), its derivative is σ′(x)\sigma'(x) (orange), and the magenta band marks where ∣σ′(x)∣<0.05|\sigma'(x)| < 0.05: there the unit is saturated (or dead) and passes almost no gradient. The grey bell is the distribution of the input z∼N(0,s2)z \sim N(0, s^2). The panel shows the two numbers that enter the variance recursion, E[σ(z)2]/s2\mathbb{E}[\sigma(z)^2]/s^2 (forward) and E[σ′(z)2]\mathbb{E}[\sigma'(z)^2] (backward). Compare tanh at s=0.5s = 0.5 and at s=3s = 3.

    • ReLU passes gradient 1 for x>0x > 0, so it does not saturate for positive inputs. It gives sparse activations (many exact zeros). It is positively homogeneous: relu⁡(cx)=crelu⁡(x)\operatorname{relu}(cx) = c\operatorname{relu}(x) for c>0c > 0. So the factor 12\tfrac12 below holds at every scale of zz. For tanh the factor depends on Var⁡(z)\operatorname{Var}(z).
    • Saturation. For large ∣x∣|x| the sigmoid and tanh are flat, so σ′(x)≈0\sigma'(x) \approx 0. Through LL sigmoid layers the gradient is multiplied by LL factors s′(zl)≤1/4s'(z_l) \le 1/4 (times the weights), and (1/4)10≈10−6(1/4)^{10} \approx 10^{-6}. 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: x⋅P(X≤x)x \cdot P(X \le x). It is a smooth gate. PyTorch also offers a tanh approximation, approximate="tanh".
    • SiLU (sigmoid linear unit, also called Swish) is x s(x)x\,s(x). GELU and SiLU are smooth and not monotone. They have a nonzero gradient for moderately negative inputs and are close to ReLU for large ∣x∣|x|.
    • 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 uxxu_{xx} then gets no useful signal. Use tanh, SiLU, GELU or sine activations there.
    Quick check

    What is the derivative of the logistic sigmoid s(x)s(x) at x=0x = 0?

    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: (xW+b)⊙s(xV+c)(xW + b) \odot s(xV + c). Shazeer (2020) put variants of it into the transformer feed-forward network (FFN), without biases:

    FFN⁡SwiGLU(x)=(SiLU⁡(xW)⊙xV) W2,W,V∈Rd×dff, W2∈Rdff×d.\operatorname{FFN}_{\text{SwiGLU}}(x) = \big(\operatorname{SiLU}(xW) \odot xV\big)\, W_2, \qquad W, V \in \mathbb{R}^{d \times d_{ff}},\ W_2 \in \mathbb{R}^{d_{ff} \times d}.

    Here dd is the model width and dffd_{ff} 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 4d4d has 2⋅d⋅4d=8d22 \cdot d \cdot 4d = 8d^2 weights. SwiGLU has three matrices, 3 d dff3\, d\, d_{ff} weights. Equal counts give 3d dff=8d23 d\, d_{ff} = 8 d^2, so dff=8d/3d_{ff} = 8d/3. The FLOPs match too, because a matmul costs 2 FLOPs per weight per token. Implementations round up: LLaMA takes ⌊8d/3⌋\lfloor 8d/3 \rfloor and rounds it up to a multiple of 256 (for d=4096d = 4096: 10922→1100810922 \to 11008).
    Interactive figure: loading…

    Move the hidden width dffd_{ff} (in units of dd) 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 8d28d^2 of a GELU FFN of width 4d4d. The SwiGLU line meets the budget at dff=8d/3d_{ff} = 8d/3 (yellow point). Switch on rounding to see the widths that LLaMA models use.

    Quick check

    A transformer has model width d=768d = 768. Which SwiGLU hidden width has the same number of FFN weights as a GELU FFN of width 30723072?

    3.3 The variance recursion #

    Setting. Use the row convention of this track: layer l+1l+1 computes zl+1=alWl+1z_{l+1} = a_l W_{l+1}, with Wl+1∈Rnl×nl+1W_{l+1} \in \mathbb{R}^{n_l \times n_{l+1}} and al=σ(zl)a_l = \sigma(z_l), where nln_l is the width of layer ll (the fan-in of Wl+1W_{l+1}; nl+1n_{l+1} is its fan-out). Unit jj computes zl+1,j=∑i=1nlal,i Wijz_{l+1,j} = \sum_{i=1}^{n_l} a_{l,i}\, W_{ij}. Assume, at initialization:

    1. the WijW_{ij} are independent, with mean 0 and variance vl+1v_{l+1};
    2. they are independent of ala_l (true at initialization, because ala_l depends only on earlier layers);
    3. the biases are 0;
    4. the units of layer ll have the same second moment E[al2]:=E[al,i2]\mathbb{E}[a_l^2] := \mathbb{E}[a_{l,i}^2] for every ii (true for l≥1l \ge 1 because the units are exchangeable; otherwise read it as the average over ii);
    5. zlz_l is symmetric around 0, that is zlz_l and −zl-z_l have the same distribution (true when the weights are symmetric). Only the ReLU step below uses this.

    Theorem (forward variance). Var⁡(zl+1,j)=nl vl+1 E[al2]\operatorname{Var}(z_{l+1,j}) = n_l\, v_{l+1}\, \mathbb{E}[a_l^2].

    Proof.

    1. E[zl+1,j]=∑iE[al,i] E[Wij]=0\mathbb{E}[z_{l+1,j}] = \sum_i \mathbb{E}[a_{l,i}]\,\mathbb{E}[W_{ij}] = 0, by independence (2) and E[W]=0\mathbb{E}[W] = 0 (1).
    2. So, again by (2),
    Var⁡(zl+1,j)=E[zl+1,j2]=∑i∑kE[WijWkj] E[al,i al,k].\operatorname{Var}(z_{l+1,j}) = \mathbb{E}[z_{l+1,j}^2] = \sum_i \sum_k \mathbb{E}[W_{ij} W_{kj}]\, \mathbb{E}[a_{l,i}\, a_{l,k}].
    1. For i≠ki \ne k, E[WijWkj]=E[Wij] E[Wkj]=0\mathbb{E}[W_{ij} W_{kj}] = \mathbb{E}[W_{ij}]\,\mathbb{E}[W_{kj}] = 0 by (1), so the cross terms vanish. For i=ki = k it is vl+1v_{l+1}.
    2. Hence Var⁡(zl+1,j)=vl+1∑iE[al,i2]=nl vl+1 E[al2]\operatorname{Var}(z_{l+1,j}) = v_{l+1} \sum_i \mathbb{E}[a_{l,i}^2] = n_l\, v_{l+1}\, \mathbb{E}[a_l^2] by (4). ■\blacksquare

    Note that the formula has E[a2]\mathbb{E}[a^2], not Var⁡(a)\operatorname{Var}(a). ReLU outputs have a positive mean, and it counts.

    He (Kaiming) initialization, for ReLU. Let z=zlz = z_l. Since zz is symmetric (5), E[z21{z>0}]=E[z21{z<0}]\mathbb{E}[z^2 \mathbf{1}\{z > 0\}] = \mathbb{E}[z^2 \mathbf{1}\{z < 0\}], and the two add up to E[z2]\mathbb{E}[z^2]. So

    E[relu⁡(z)2]=E[z21{z>0}]=12 E[z2]=12Var⁡(z),\mathbb{E}[\operatorname{relu}(z)^2] = \mathbb{E}[z^2 \mathbf{1}\{z > 0\}] = \tfrac12\, \mathbb{E}[z^2] = \tfrac12 \operatorname{Var}(z),

    using E[z]=0\mathbb{E}[z] = 0 (step 1 of the proof). Then Var⁡(zl+1)=12 nl vl+1Var⁡(zl)\operatorname{Var}(z_{l+1}) = \tfrac12\, n_l\, v_{l+1} \operatorname{Var}(z_l), and the variance stays the same if and only if vl+1=2/nlv_{l+1} = 2/n_l. Over depth,

    Var⁡(zL)=Var⁡(z1)∏l=1L−112 nl vl+1.\operatorname{Var}(z_L) = \operatorname{Var}(z_1) \prod_{l=1}^{L-1} \tfrac12\, n_l\, v_{l+1}.

    Any constant factor c≠1c \ne 1 per layer gives cL−1c^{L-1}: exponential in depth.

    LeCun initialization, for linear units (or tanh near 0). If σ(z)≈z\sigma(z) \approx z, then E[σ(z)2]≈Var⁡(z)\mathbb{E}[\sigma(z)^2] \approx \operatorname{Var}(z), and the condition is nlv=1n_l v = 1: v=1/faninv = 1/\mathrm{fan}_{\mathrm{in}}.

    The backward pass has the same recursion

    Let gl=∂L/∂zlg_l = \partial \mathcal{L}/\partial z_l (one row of GlG_l in lesson 03). The backward rule Gl=(Gl+1Wl+1⊤)⊙σ′(Zl)G_l = (G_{l+1}W_{l+1}^\top) \odot \sigma'(Z_l) reads, for unit ii of layer ll,

    gl,i=σ′(zl,i)∑j=1nl+1Wij gl+1,j.g_{l,i} = \sigma'(z_{l,i}) \sum_{j=1}^{n_{l+1}} W_{ij}\, g_{l+1,j}.

    Assume also that gl+1g_{l+1} is independent of Wl+1W_{l+1} and of σ′(zl)\sigma'(z_l). (This is the standard approximation; it is not exact, because gl+1g_{l+1} depends on zl+1=alWl+1z_{l+1} = a_l W_{l+1}.) The four steps of the forward proof, now with a sum over the nl+1n_{l+1} units above, give

    Var⁡(gl)=nl+1 vl+1 E[σ′(zl)2] Var⁡(gl+1).\operatorname{Var}(g_l) = n_{l+1}\, v_{l+1}\, \mathbb{E}[\sigma'(z_l)^2]\, \operatorname{Var}(g_{l+1}).

    For ReLU, E[σ′(z)2]=P(z>0)=12\mathbb{E}[\sigma'(z)^2] = P(z > 0) = \tfrac12, so the backward condition is vl+1=2/nl+1v_{l+1} = 2/n_{l+1} (He initialization in "fan-out mode"). For linear units it is v=1/nl+1v = 1/n_{l+1}.

    Xavier (Glorot) initialization. The forward condition wants v=1/faninv = 1/\mathrm{fan}_{\mathrm{in}} and the backward condition wants v=1/fanoutv = 1/\mathrm{fan}_{\mathrm{out}} (for linear or tanh units near 0). Both hold only if fanin=fanout\mathrm{fan}_{\mathrm{in}} = \mathrm{fan}_{\mathrm{out}}. Glorot and Bengio (2010) take the compromise

    v=2fanin+fanout,v = \frac{2}{\mathrm{fan}_{\mathrm{in}} + \mathrm{fan}_{\mathrm{out}}},

    which is the harmonic mean of the two conditions. (The ReLU analogue would be 4/(fanin+fanout)4/(\mathrm{fan}_{\mathrm{in}} + \mathrm{fan}_{\mathrm{out}}).)

    One condition is enough. With the forward condition vl+1=2/nlv_{l+1} = 2/n_l (ReLU), the backward factor per layer is nl+1⋅2nl⋅12=nl+1/nln_{l+1} \cdot \tfrac{2}{n_l} \cdot \tfrac12 = n_{l+1}/n_l. Over the whole network the product telescopes:

    ∏l=1L−1nl+1nl=nLn1,\prod_{l=1}^{L-1} \frac{n_{l+1}}{n_l} = \frac{n_L}{n_1},

    a bounded change, not an exponential one (He et al. 2015, §2.2).

    Uniform versions and library defaults. A uniform distribution U(−a,a)U(-a, a) has variance a2/3a^2/3, so a=3va = \sqrt{3v}. Xavier uniform: a=6/(fanin+fanout)a = \sqrt{6/(\mathrm{fan}_{\mathrm{in}} + \mathrm{fan}_{\mathrm{out}})}. He uniform: a=6/fanina = \sqrt{6/\mathrm{fan}_{\mathrm{in}}}. For a convolution, the fan-in is CinkhkwC_{\text{in}} k_h k_w (input channels times kernel size). PyTorch's default for nn.Linear and nn.Conv* is U(±1/fanin)U(\pm 1/\sqrt{\mathrm{fan}_{\mathrm{in}}}), a variance of 1/(3 fanin)1/(3\,\mathrm{fan}_{\mathrm{in}}): 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 σ(0)=0\sigma(0) = 0. So WˉL=AL−1⊤GL=0\bar W_L = A_{L-1}^\top G_L = 0, and GL−1=(GLWL⊤)⊙σ′=0G_{L-1} = (G_L W_L^\top) \odot \sigma' = 0 because WL=0W_L = 0. 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.

    Interactive figure: loading…

    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 bib_i and its outgoing weight viv_i 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.

    Quick check

    An MLP with ReLU hidden layers starts with all weights and biases equal to zero and is trained with SGD. What happens?

    Xavier in a deep ReLU network. For square layers Xavier gives v=1/nv = 1/n. The factor is 12⋅n⋅1n=12\tfrac12 \cdot n \cdot \tfrac1n = \tfrac12 per layer, forward and backward. After 50 layers the variance is about 2−49≈1.8⋅10−152^{-49} \approx 1.8 \cdot 10^{-15} of its first value.

    LeCun with tanh decays slowly. With ql=Var⁡(zl)q_l = \operatorname{Var}(z_l) and v=1/nv = 1/n, the recursion is ql+1=E[tanh⁡(zl)2]q_{l+1} = \mathbb{E}[\tanh(z_l)^2] for zl∼N(0,ql)z_l \sim N(0, q_l). For small qlq_l, tanh⁡(z)2≈z2−23z4\tanh(z)^2 \approx z^2 - \tfrac23 z^4, so ql+1≈ql−2ql2q_{l+1} \approx q_l - 2q_l^2 (using E[z4]=3ql2\mathbb{E}[z^4] = 3q_l^2). Then qlq_l falls like 1/(2l)1/(2l), not geometrically: after 50 layers it is about 0.010.01.

    Second moments for z∼N(0,1)z \sim N(0, 1): E[σ(z)2]=0.5\mathbb{E}[\sigma(z)^2] = 0.5 (ReLU), 0.4250.425 (GELU), 0.3560.356 (SiLU), 0.3940.394 (tanh). A weight variance v=1/(n E[σ(z)2])v = 1/(n\, \mathbb{E}[\sigma(z)^2]) keeps unit variance: 2/n2/n for ReLU, about 2.35/n2.35/n 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 J=∂zL/∂z0J = \partial z_L/\partial z_0. In a deep linear network with Gaussian weights of variance 1/n1/n, the mean squared singular value of JJ 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 10−1710^{-17}. Some directions explode and others vanish, and the condition number of JJ is huge (linear-algebra lesson 08). With orthogonal initialization (W⊤W=IW^\top W = I, 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 ∝1/fanin\propto 1/\mathrm{fan}_{\mathrm{in}} 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 η\eta (the learning rate), whatever the scale of the gradient. For a hidden layer, the change of the output, Δz=a ΔW\Delta z = a\,\Delta W, is a sum of nn terms. These terms are correlated with aa, because the gradient is an outer product of aa and the upstream gradient. So they add up coherently: Δz∝η n\Delta z \propto \eta\, n, not ηn\eta\sqrt{n}. The initialization fixes only the size of aWaW at step 0; it says nothing about the size of the updates. Keeping Δz\Delta z of order 1 at every width needs η∝1/fanin\eta \propto 1/\mathrm{fan}_{\mathrm{in}}.

    μ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 1/fanin1/\mathrm{fan}_{\mathrm{in}} 1/fanin1/\mathrm{fan}_{\mathrm{in}} 1/fanin21/\mathrm{fan}_{\mathrm{in}}^2 (SP: 1/fanin1/\mathrm{fan}_{\mathrm{in}})
    Adam learning rate independent of width ∝1/fanin\propto 1/\mathrm{fan}_{\mathrm{in}} (SP: independent) ∝1/fanin\propto 1/\mathrm{fan}_{\mathrm{in}} (SP: independent)

    μP transformers also scale attention logits by 1/d1/d instead of 1/d1/\sqrt{d}: after training, qq and kk are correlated, so q⊤kq^\top k grows like dd, not d\sqrt{d}. 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 10−1510^{-15}. The first layer gives Var⁡(z1)=1000⋅11000⋅1=1\operatorname{Var}(z_1) = 1000 \cdot \tfrac{1}{1000} \cdot 1 = 1, and then each ReLU layer multiplies by 12\tfrac12, so Var⁡(z50)=2−49≈1.8⋅10−15\operatorname{Var}(z_{50}) = 2^{-49} \approx 1.8 \cdot 10^{-15}. (2) 8d/38d/3.

    4. Worked example #

    (a) Activations at x=−1x = -1. We need Φ(−1)=0.1587\Phi(-1) = 0.1587, φ(−1)=0.2420\varphi(-1) = 0.2420 and s(−1)=0.2689s(-1) = 0.2689.

    • GELU: value −1⋅Φ(−1)=−0.1587-1 \cdot \Phi(-1) = -0.1587. Derivative Φ(−1)+(−1)φ(−1)\Phi(-1) + (-1)\varphi(-1) =0.1587−0.2420=−0.0833= 0.1587 - 0.2420 = -0.0833. It is negative because GELU is not monotone there.
    • SiLU: value −1⋅s(−1)=−0.2689-1 \cdot s(-1) = -0.2689. Derivative s(−1) (1+(−1)(1−s(−1)))s(-1)\,(1 + (-1)(1 - s(-1))) =s(−1)⋅s(−1)=0.26892=0.0723= s(-1) \cdot s(-1) = 0.2689^2 = 0.0723.
    • ReLU: value 0 and derivative 0. At x=−1x = -1 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: 1/768=0.0361\sqrt{1/768} = 0.0361. He std: 2/768=0.0510\sqrt{2/768} = 0.0510.
    • Xavier normal std: 2/(768+3072)=2/3840=0.0228\sqrt{2/(768 + 3072)} = \sqrt{2/3840} = 0.0228. Xavier uniform bound: 6/3840=0.0395\sqrt{6/3840} = 0.0395.
    • PyTorch default: bound 1/768=0.03611/\sqrt{768} = 0.0361, so std 0.0361/3=0.02080.0361/\sqrt{3} = 0.0208.

    (c) Depth. 50 square ReLU layers with Xavier: factor 12\tfrac12 per layer, so Var⁡(z50)/Var⁡(z1)=2−49≈1.8⋅10−15\operatorname{Var}(z_{50})/\operatorname{Var}(z_1) = 2^{-49} \approx 1.8 \cdot 10^{-15}. The gradients vanish in the same way. With He the factor is 1.

    (d) SwiGLU at d=768d = 768. The GELU FFN of width 4d=30724d = 3072 has 2⋅768⋅3072=8⋅7682=4,718,5922 \cdot 768 \cdot 3072 = 8 \cdot 768^2 = 4{,}718{,}592 weights. SwiGLU with dff=8⋅768/3=2048d_{ff} = 8 \cdot 768/3 = 2048 has 3⋅768⋅2048=4,718,5923 \cdot 768 \cdot 2048 = 4{,}718{,}592 weights. ✓ This is exactly Shazeer's setup: dff=3072d_{ff} = 3072 for the two-matrix FFNs and 20482048 for the GLU variants.

    Quick check

    A 3×33 \times 3 convolution maps 64 input channels to 128 output channels and is followed by ReLU. What is the He standard deviation (fan-in mode)?

    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 2\sqrt 2, the factor in He's standard deviation 2/fanin\sqrt 2/\sqrt{\mathrm{fan}_{\mathrm{in}}}, and a fresh nn.Linear(768, 3072) has weight standard deviation about 0.02080.0208 (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 1/N1/\sqrt{N} for NN residual layers (nanoGPT uses standard deviation 0.02/2nlayer0.02/\sqrt{2 n_{\text{layer}}} 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 q⊤kq^\top k are sums of dkd_k products, so their variance is dkd_k when qq and kk have unit-variance entries. Dividing by dk\sqrt{d_k} 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 6/n\sqrt{6/n}, so that the input of each sine is close to N(0,1)N(0, 1): the same argument with a different σ\sigma.
    • Porting code between frameworks. Defaults differ: PyTorch's nn.Linear uses U(±1/fanin)U(\pm 1/\sqrt{\mathrm{fan}_{\mathrm{in}}}), Flax's nn.Dense uses LeCun normal. A model moved from one to the other starts from a different scale unless you set the initializer explicitly.

    7. Common mistakes #

    • Var⁡(a)\operatorname{Var}(a) instead of E[a2]\mathbb{E}[a^2] in the recursion. For ReLU the mean is not zero.
    • Standard deviation vs variance. He std is 2/fanin\sqrt{2/\mathrm{fan}_{\mathrm{in}}}; 2/fanin2/\mathrm{fan}_{\mathrm{in}} is the variance. torch.randn(...) * std needs 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.Linear uses U(±1/fanin)U(\pm 1/\sqrt{\mathrm{fan}_{\mathrm{in}}}), variance 1/(3 fanin)1/(3\,\mathrm{fan}_{\mathrm{in}}).
    • Conv fan-in =Cin= C_{\text{in}}. It is CinkhkwC_{\text{in}} k_h k_w.
    • "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 dffd_{ff}. SwiGLU then has 1.5 times more parameters.

    8. Check yourself #

    1. Why does a 10-layer sigmoid network train badly even with good weight scales?
      AnswerEach layer multiplies the backpropagated gradient by s′(z)≤1/4s'(z) \le 1/4, so the factor from the activations alone is at most (1/4)10≈10−6(1/4)^{10} \approx 10^{-6}. Saturated units give s′≈0s' \approx 0, which is even worse.
    2. Which weight variance keeps unit pre-activation variance for GELU when Var⁡(z)=1\operatorname{Var}(z) = 1?
      Answerv=1/(n E[GELU⁡(z)2])=1/(0.425 n)≈2.35/nv = 1/(n\, \mathbb{E}[\operatorname{GELU}(z)^2]) = 1/(0.425\, n) \approx 2.35/n.
    3. Why does E[relu⁡(z)2]=12Var⁡(z)\mathbb{E}[\operatorname{relu}(z)^2] = \tfrac12\operatorname{Var}(z) need zz to be symmetric?
      AnswerThe proof splits E[z2]\mathbb{E}[z^2] into the parts with z>0z > 0 and z<0z < 0 and uses that they are equal. If zz 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 12\tfrac12.
    4. 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?
      AnswerAll entries of WLW_L are 0.5, so the entries of AˉL−1=GLWL⊤\bar A_{L-1} = G_L W_L^\top are 0.5∑cGbc=0.5∑c(pc−yc)/B=00.5 \sum_c G_{bc} = 0.5 \sum_c (p_c - y_c)/B = 0, because both pp and yy sum to 1. Even after the output layer moves, the hidden units stay identical (symmetry).
    5. He initialization (forward condition) is used in a network whose widths shrink from n1=4096n_1 = 4096 to nL=256n_L = 256. How does the gradient variance change over the whole network?
      AnswerThe backward factor per layer is nl+1/nln_{l+1}/n_l, and the product telescopes to nL/n1=1/16n_L/n_1 = 1/16. A bounded change, not an exponential one.
    6. 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?
      AnswerThe initialization variance 1/fanin1/\mathrm{fan}_{\mathrm{in}} halves, and the learning rate also halves (∝1/fanin\propto 1/\mathrm{fan}_{\mathrm{in}}), because the change a ΔWa\,\Delta W sums twice as many coherent terms.
    Recall cardsAnswer in your head first, then reveal. Add the cards to your review deck to see them again just before you would forget.
    1. Write the forward variance recursion of an MLP at initialization.

    2. What is He initialization, and for which activation is it derived?

    3. What is Xavier (Glorot) initialization?

    4. Why is E[relu⁡(z)2]=12Var⁡(z)\mathbb{E}[\operatorname{relu}(z)^2] = \tfrac12\operatorname{Var}(z)?

    5. What is the largest value of the sigmoid's derivative, and where?

    6. What is a dead ReLU unit?

    7. Write GELU and SiLU.

    8. Why does a SwiGLU FFN use hidden width 8d/38d/3?

    9. Why does a constant initialization fail?

    10. By what factor does Xavier initialization change the variance per layer in a square ReLU network?

    Open the review →

    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 1/41/4; ReLU passes gradient 1 for positive inputs. GELU is xΦ(x)x\Phi(x), 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: Var⁡(zl+1)=nl v E[a2]\operatorname{Var}(z_{l+1}) = n_l\, v\, \mathbb{E}[a^2], and E[relu⁡(z)2]=12Var⁡(z)\mathbb{E}[\operatorname{relu}(z)^2] = \tfrac12\operatorname{Var}(z), so v=2/nlv = 2/n_l.
    • "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?" 8d/38d/3 for d=4096d = 4096 is 10922.710922.7, 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.

    1. Write ReLU, sigmoid, tanh, GELU and SiLU with their derivatives, and check the derivatives with central differences.
    2. Estimate E[relu⁡(z)2]\mathbb{E}[\operatorname{relu}(z)^2] and E[relu⁡′(z)2]\mathbb{E}[\operatorname{relu}'(z)^2] by Monte Carlo and compare with 12\tfrac12.
    3. Write init_std(name, fan_in, fan_out) and preactivation_variances(...), and plot the variance through 50 layers for LeCun, Xavier and He with ReLU and tanh.
    4. Train a small network from a constant initialization and show that its hidden units stay identical; then break the symmetry.
    5. Write a SwiGLU FFN in NumPy with the parameter count of a GELU FFN of width 4d4d.

    11. Watch and read #

    The first hour: a bad initial loss, saturated tanh units, and fixing the weight scale with the Kaiming factor.
    Open on YouTube · the player loads from youtube-nocookie.com when you press play
    The variance argument in a few minutes: why the weight variance should be about 1/n or 2/n.
    Open on YouTube · the player loads from youtube-nocookie.com when you press play
    Activation functions (sigmoid, tanh, ReLU and their problems) and weight initialization with activation histograms.
    Open on YouTube · the player loads from youtube-nocookie.com when you press play