Source code for mygrad.nnet.initializers.glorot_normal
import numpy as np
from mygrad.tensor_base import Tensor
[docs]def glorot_normal(*shape, gain=1, dtype=np.float32, constant=None):
r"""Initialize a :class:`mygrad.Tensor` according to the normal initialization procedure
described by Glorot and Bengio.
Parameters
----------
shape : Sequence[int]
The shape of the output Tensor. Note that ``shape`` must be at least two-dimensional.
gain : Real, optional (default=1)
The gain (scaling factor) to apply.
dtype : data-type, optional (default=float32)
The data type of the output tensor; must be a floating-point type.
constant : bool, optional (default=False)
If ``True``, the returned tensor is a constant (it
does not back-propagate a gradient).
Returns
-------
mygrad.Tensor, shape=``shape``
A Tensor, with values initialized according to the glorot normal initialization.
Notes
-----
Glorot and Bengio put forward this initialization in the paper
"Understanding the Difficulty of Training Deep Feedforward Neural Networks"
http://proceedings.mlr.press/v9/glorot10a/glorot10a.pdf
A Tensor :math:`W` initialized in this way should be drawn from a distribution about
.. math::
\mathcal{N}(0, \frac{\sqrt{2}}{\sqrt{n_j+n_{j+1}}})
"""
if not np.issubdtype(dtype, np.floating):
raise ValueError("Glorot Normal initialization requires a floating-point dtype")
if len(shape) == 1:
shape = shape[0]
if len(shape) < 2:
raise ValueError(
"Glorot Normal initialization requires at least two dimensions"
)
if isinstance(gain, Tensor):
gain = gain.item()
fan_in = shape[1] * (shape[-1] if len(shape) > 2 else 1)
fan_out = shape[0] * (shape[-1] if len(shape) > 2 else 1)
std = gain * np.sqrt(2 / (fan_in + fan_out))
return Tensor(
np.random.normal(0, std, shape),
dtype=dtype,
constant=constant,
copy=False,
)