NoisyLinear
ModuleNoisyLinear(in_features: int, out_features: int, bias: bool = True, sigma_zero: float = 0.5, device: DeviceLike = None, dtype: DTypeLike = None)A linear layer whose weights carry learnable exploration noise.
Parameters
in_featuresintLinear.out_featuresintLinear.biasbool= Truesigma_zerofloat= 0.5deviceoptional= Nonedtypeoptional= NoneAttributes
Raises
ValueErrorsigma_zero is not positive.Notes
Reference: Fortunato et al., "Noisy Networks for Exploration", ICLR, 2018 (arXiv:1706.10295).
with factorised noise, so the layer draws in_features + out_features random numbers rather than their product.
Initialised as the paper's factorised case specifies: "each element was initialised by a sample from an independent uniform distribution and each element was initialised to a constant ", with the input width.
The noise is a buffer, not a per-call draw. Redrawing inside
forward would make two calls on the same input two different
networks, which breaks both the Monte-Carlo gradient the paper
derives — one sample per optimisation step, its equation 13 — and
any agent that needs a fixed policy for an episode. Call
resample when a new sample is wanted. In eval() the
noise is not used at all, so a deterministic policy is just the mean
network.
Examples
>>> import lucid
>>> import lucid.nn as nn
>>> layer = nn.NoisyLinear(4, 3)
>>> layer(lucid.zeros((2, 4))).shape
(2, 3)Used by 1
Constructors
1Properties
2Instance methods
3Draw a fresh noise sample — one per optimisation step, or episode.
Notes
Writes the buffers in place with [:]. Assigning .data
writes to a copy and silently does nothing, which is the mistake
this codebase has made before.
The paper's factorised initialisation.
mu ~ U[-1/sqrt(p), 1/sqrt(p)] and sigma = sigma_zero / sqrt(p), with p the input width.