PythiloLesson 6 of 30 · progress kept in this browser

Weight initialisation

Every layer multiplies the spread of its input by some factor. Over twenty layers a factor of 2 becomes a million and a factor of 0.5 a millionth: the signal explodes or vanishes before training has started, and the gradients do the same on the way back.

import torch

torch.manual_seed(0)
for std in (1.0, 0.05, (2 / 256) ** 0.5):
    x = torch.randn(512, 256)
    for _ in range(20):
        w = torch.randn(256, 256) * std
        x = torch.relu(x @ w)
    print(f"{std:.3f} {x.std():.3g}")

He (or Kaiming) initialisation draws weights with standard deviation sqrt(2 / fan_in), where fan_in is the number of inputs each unit sums. A sum of fan_in products has fan_in times their variance, and ReLU zeroes half the signal, which the 2 makes up for.

nn.init.kaiming_normal_(w, nonlinearity="relu") applies it in place. PyTorch's default for nn.Linear is smaller, so in a deep ReLU stack set it yourself.

Your task

Write activation_stds(model, x): run x through the nn.Sequential model layer by layer without recording gradients, and return the standard deviation (a float) of the output of every nn.ReLU, in order. Write init_he(model): give every nn.Linear in model weights from nn.init.kaiming_normal_ with nonlinearity="relu" and zero biases, and return the model.

This lesson uses torch, which Python in this browser does not include. Read it here, and run and check it in the Pythilo app on iPhone or iPad.