fn

randn

Tensor
randn(size: _int | tuple[_int, ...] = (), dtype: DTypeLike = None, device: DeviceLike = None, requires_grad: _bool = False, generator: _C_engine.Generator | None = None)
source

Return a tensor of samples drawn from the standard normal distribution.

Each element is drawn independently from N(0,1)\mathcal{N}(0, 1), the standard Gaussian with zero mean and unit variance:

XiN(0,1),fX(x)=12πex2/2X_i \sim \mathcal{N}(0, 1), \quad f_X(x) = \frac{1}{\sqrt{2\pi}}\, e^{-x^2 / 2}

The distribution has mean E[X]=0\mathbb{E}[X] = 0, variance Var[X]=1\operatorname{Var}[X] = 1, and all odd central moments zero.

Parameters

*sizeint or tuple[int, ...]
Shape of the output tensor.
dtypelucid.dtype
Floating-point data type. Defaults to the global default.
devicestr or lucid.device
Target device — "cpu" or "metal".
requires_gradbool
Enable autograd tracking. Default: False.
generatorlucid._C.engine.Generator
Explicit generator. Defaults to the global default generator.

Returns

Tensor

Tensor of shape size with N(0,1)\mathcal{N}(0, 1) samples.

Notes

The engine uses the Box–Muller transform to convert pairs of uniform samples (u1,u2)U(0,1)2(u_1, u_2) \sim U(0,1)^2 into standard normals:

z1=2lnu1cos(2πu2),z2=2lnu1sin(2πu2)z_1 = \sqrt{-2\ln u_1}\,\cos(2\pi u_2), \quad z_2 = \sqrt{-2\ln u_1}\,\sin(2\pi u_2)

This is exact (not approximate) and is highly efficient on SIMD hardware because the two outputs z1,z2z_1, z_2 can be produced simultaneously from one pair of uniform draws.

Xavier / Glorot initialisation (Glorot & Bengio, 2010) uses N(0,σ2)\mathcal{N}(0, \sigma^2) with

σ=2nin+nout\sigma = \sqrt{\frac{2}{n_\text{in} + n_\text{out}}}

which can be obtained as randn(fan_in, fan_out) * sigma.

He / Kaiming initialisation (He et al., 2015) for ReLU networks uses σ=2/nin\sigma = \sqrt{2 / n_\text{in}}.

Examples

>>> import lucid
>>> lucid.manual_seed(0)
>>> x = lucid.randn(1000)
>>> abs(float(x.mean())) < 0.1       # ≈ 0
True
>>> abs(float(x.std()) - 1.0) < 0.1  # ≈ 1
True
Kaiming initialisation for a linear layer:
>>> fan_in = 256
>>> w = lucid.randn(fan_in, 512) * (2.0 / fan_in) ** 0.5