Skip to content

20. Weight Init

import math
import os

import plotly.graph_objects as go
import torch
from torch_judge import check

torch.set_default_device(os.environ.get("TORCH_DEVICE", "cpu"))


def kaiming_init(weight: torch.Tensor) -> None:
    # The Kaiming (He) initialization is designed to keep the variance of
    # the activations and gradients approximately the same across
    # every layer. It is obtained by drawing samples from a normal distribution with mean 0 and
    # standard deviation sqrt(2 / fan_in)
    fan_in = weight.shape[1]  # Number of input units in the weight tensor
    std = math.sqrt(2 / fan_in)
    with torch.no_grad():
        weight.normal_(mean=0.0, std=std)


def plot_weight_distributions(before: torch.Tensor, after: torch.Tensor):
    fig = go.Figure()
    fig.add_trace(
        go.Histogram(
            x=before.cpu().flatten().numpy(),
            nbinsx=50,
            name="Before (randn)",
            opacity=0.6,
        )
    )
    fig.add_trace(
        go.Histogram(
            x=after.cpu().flatten().numpy(),
            nbinsx=50,
            name="After (He init)",
            opacity=0.6,
        )
    )
    fig.update_layout(
        title="Weight Distribution: Before vs After He Initialization",
        xaxis_title="Weight value",
        yaxis_title="Count",
        barmode="overlay",
    )
    fig.show()


if __name__ == "__main__":
    w = torch.randn(256, 512)
    before = w.clone()
    kaiming_init(w)
    print(f"Mean: {w.mean():.4f} (expect ~0)")
    print(f"Std:  {w.std():.4f} (expect {math.sqrt(2 / 512):.4f})")

    plot_weight_distributions(before, w)
    check("weight_init")