Source code for mygrad.nnet.initializers.he_normal

import numpy as np

from mygrad.nnet.initializers.normal import normal


[docs]def he_normal(*shape, gain=1, dtype=np.float32, constant=None): r"""Initialize a :class:`mygrad.Tensor` according to the normal initialization procedure described by He et al. 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 He normal initialization. Notes ----- He, Zhang, Ren, and Sun put forward this initialization in the paper "Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification" https://arxiv.org/abs/1502.01852 A Tensor :math:`W` initialized in this way should be drawn from a distribution about .. math:: \mathcal{N}(0, \sqrt{\frac{2}{(1+a^2)n_l}}) where :math:`a` is the slope of the rectifier following this layer, which is incorporated using the `gain` variable above. The guidance put forward in that paper is that this initialization procedure should be preferred over the ``mygrad.nnet.initializers.glorot_*`` functions especially when rectifiers (e.g. ReLU, PReLU, leaky_relu) in very deep (> 1-20 or so layer) networks. Examples -------- >>> from mygrad.nnet.initializers import he_normal >>> he_normal(2, 3) Tensor([[-2.3194842 , 0.45956254, -0.28709933], [-0.15776408, 0.6777564 , -0.05587448]], dtype=float32) >>> he_normal(4, 2, gain=5/3, dtype="float64", constant=True) Tensor([[ 0.25962918, 1.1503933 ], [-0.13638746, 0.10581096], [ 1.44805926, 0.51367645], [-0.32018705, -0.80306442]]) >>> he_normal(2, 1, 2, dtype="float16") Tensor([[[ 0.8057 , -0.2922 ]], [[ 0.12213, -0.715 ]]], dtype=float16) """ if len(shape) == 1: shape = shape[0] if len(shape) < 2: raise ValueError("He Normal initialization requires at least two dimensions") std = gain / np.sqrt(shape[1] * (np.prod(shape[2:]) if len(shape) > 2 else 1)) return normal(shape, mean=0, std=std, dtype=dtype, constant=constant)