Roadmap / Neural Network Layers

✓

Xavier & Kaiming Initialization

easylayersinitialization

The problem

Before training, every weight is set to a random number, and the size of those random numbers decides whether the network can train at all. A layer y=xWy = xW with ninn_{\text{in}} inputs adds up ninn_{\text{in}} products, and so it multiplies the variance of its input by

nin⋅Var(w)n_{\text{in}} \cdot \mathrm{Var}(w)

where Var(w)\mathrm{Var}(w) is the variance of each weight (the average squared distance from 0, for weights with mean 0). Stack many layers and the factor compounds: above 1 the numbers explode, below 1 they vanish (the theory page shows both, measured). Initialization picks Var(w)\mathrm{Var}(w) so that the factor is about 1.

Example. nin=512n_{\text{in}} = 512. Weights with variance 1 make the factor 512: after 3 layers the variance has grown 5123≈134512^3 \approx 134 million times. Weights with variance 1/5121/512 make the factor exactly 1.

The weights have shape (nin,nout)(n_{\text{in}}, n_{\text{out}}) and are used as x @ W. In the code, ninn_{\text{in}} is fan_in and noutn_{\text{out}} is fan_out.

Xavier (Glorot) uniform

Glorot and Bengio (2010) want both the forward activations and the backward gradients to keep their scale. The forward pass suggests Var(w)=1/nin\mathrm{Var}(w) = 1/n_{\text{in}}, the backward pass 1/nout1/n_{\text{out}}, and the compromise is:

Var(w)=2nin+nout\mathrm{Var}(w) = \frac{2}{n_{\text{in}} + n_{\text{out}}}

The weights are drawn uniformly between −a-a and aa. A uniform distribution on [−a,a][-a, a] has variance a2/3a^2 / 3, so to get the variance above:

a=6nin+nouta = \sqrt{\frac{6}{n_{\text{in}} + n_{\text{out}}}}

Example. nin=nout=512n_{\text{in}} = n_{\text{out}} = 512: a=6/1024≈0.0765a = \sqrt{6/1024} \approx 0.0765, and the variance is 0.07652/3≈0.00195=2/10240.0765^2 / 3 \approx 0.00195 = 2/1024.

Kaiming (He) normal

ReLU (rectified linear unit) sets about half of its inputs to 0, which halves the variance at every layer. He et al. (2015) make up for it with a factor 2, using only ninn_{\text{in}}:

Var(w)=2nin\mathrm{Var}(w) = \frac{2}{n_{\text{in}}}

The weights are drawn from a normal (bell-shaped) distribution with mean 0 and this variance, so the standard deviation is 2/nin\sqrt{2 / n_{\text{in}}}.

Example. nin=512n_{\text{in}} = 512: standard deviation 2/512=0.0625\sqrt{2/512} = 0.0625.

What to implement

  • xavier_uniform(fan_in, fan_out, rng): weights uniform on [−a,a][-a, a], with aa as above.
  • kaiming_normal(fan_in, fan_out, rng): weights normal with mean 0 and variance 2/nin2 / n_{\text{in}}.

Both return an array of shape (fan_in, fan_out). rng is a np.random.Generator: use rng.uniform and rng.normal.

Requirements

  • Shape (fan_in, fan_out).
  • Kaiming uses fan_in only.

Hint

rng.normal(mean, scale, size) takes the standard deviation as scale, not the variance: pass the square root.

solution.py
Python idle

Press Run (⌘/Ctrl + Enter) to test your code.