| import torch |
| from .module import Module |
| from torch.nn.parameter import Parameter |
| from .. import functional as F |
| |
| |
| # TODO: check contiguous in THNN |
| # TODO: use separate backend functions? |
| class _BatchNorm(Module): |
| |
| def __init__(self, num_features, eps=1e-5, momentum=0.1, affine=True): |
| super(_BatchNorm, self).__init__() |
| self.num_features = num_features |
| self.affine = affine |
| self.eps = eps |
| self.momentum = momentum |
| if self.affine: |
| self.weight = Parameter(torch.Tensor(num_features)) |
| self.bias = Parameter(torch.Tensor(num_features)) |
| else: |
| self.register_parameter('weight', None) |
| self.register_parameter('bias', None) |
| self.register_buffer('running_mean', torch.zeros(num_features)) |
| self.register_buffer('running_var', torch.ones(num_features)) |
| self.reset_parameters() |
| |
| def reset_parameters(self): |
| self.running_mean.zero_() |
| self.running_var.fill_(1) |
| if self.affine: |
| self.weight.data.uniform_() |
| self.bias.data.zero_() |
| |
| def _check_input_dim(self, input): |
| if input.size(1) != self.running_mean.nelement(): |
| raise ValueError('got {}-feature tensor, expected {}' |
| .format(input.size(1), self.num_features)) |
| |
| def forward(self, input): |
| self._check_input_dim(input) |
| return F.batch_norm( |
| input, self.running_mean, self.running_var, self.weight, self.bias, |
| self.training, self.momentum, self.eps) |
| |
| def __repr__(self): |
| return ('{name}({num_features}, eps={eps}, momentum={momentum},' |
| ' affine={affine})' |
| .format(name=self.__class__.__name__, **self.__dict__)) |
| |
| |
| class BatchNorm1d(_BatchNorm): |
| r"""Applies Batch Normalization over a 2d or 3d input that is seen as a mini-batch. |
| |
| .. math:: |
| |
| y = \frac{x - mean[x]}{ \sqrt{Var[x] + \epsilon}} * gamma + beta |
| |
| The mean and standard-deviation are calculated per-dimension over |
| the mini-batches and gamma and beta are learnable parameter vectors |
| of size C (where C is the input size). |
| |
| During training, this layer keeps a running estimate of its computed mean |
| and variance. The running sum is kept with a default momentum of 0.1. |
| |
| During evaluation, this running mean/variance is used for normalization. |
| |
| Args: |
| num_features: num_features from an expected input of size `batch_size x num_features [x width]` |
| eps: a value added to the denominator for numerical stability. Default: 1e-5 |
| momentum: the value used for the running_mean and running_var computation. Default: 0.1 |
| affine: a boolean value that when set to true, gives the layer learnable affine parameters. |
| |
| Shape: |
| - Input: :math:`(N, C)` or :math:`(N, C, L)` |
| - Output: :math:`(N, C)` or :math:`(N, C, L)` (same shape as input) |
| |
| Examples: |
| >>> # With Learnable Parameters |
| >>> m = nn.BatchNorm1d(100) |
| >>> # Without Learnable Parameters |
| >>> m = nn.BatchNorm1d(100, affine=False) |
| >>> input = autograd.Variable(torch.randn(20, 100)) |
| >>> output = m(input) |
| """ |
| |
| def _check_input_dim(self, input): |
| if input.dim() != 2 and input.dim() != 3: |
| raise ValueError('expected 2D or 3D input (got {}D input)' |
| .format(input.dim())) |
| super(BatchNorm1d, self)._check_input_dim(input) |
| |
| |
| class BatchNorm2d(_BatchNorm): |
| r"""Applies Batch Normalization over a 4d input that is seen as a mini-batch of 3d inputs |
| |
| .. math:: |
| |
| y = \frac{x - mean[x]}{ \sqrt{Var[x] + \epsilon}} * gamma + beta |
| |
| The mean and standard-deviation are calculated per-dimension over |
| the mini-batches and gamma and beta are learnable parameter vectors |
| of size C (where C is the input size). |
| |
| During training, this layer keeps a running estimate of its computed mean |
| and variance. The running sum is kept with a default momentum of 0.1. |
| |
| During evaluation, this running mean/variance is used for normalization. |
| |
| Args: |
| num_features: num_features from an expected input of size batch_size x num_features x height x width |
| eps: a value added to the denominator for numerical stability. Default: 1e-5 |
| momentum: the value used for the running_mean and running_var computation. Default: 0.1 |
| affine: a boolean value that when set to true, gives the layer learnable affine parameters. |
| |
| Shape: |
| - Input: :math:`(N, C, H, W)` |
| - Output: :math:`(N, C, H, W)` (same shape as input) |
| |
| Examples: |
| >>> # With Learnable Parameters |
| >>> m = nn.BatchNorm2d(100) |
| >>> # Without Learnable Parameters |
| >>> m = nn.BatchNorm2d(100, affine=False) |
| >>> input = autograd.Variable(torch.randn(20, 100, 35, 45)) |
| >>> output = m(input) |
| """ |
| |
| def _check_input_dim(self, input): |
| if input.dim() != 4: |
| raise ValueError('expected 4D input (got {}D input)' |
| .format(input.dim())) |
| super(BatchNorm2d, self)._check_input_dim(input) |
| |
| |
| class BatchNorm3d(_BatchNorm): |
| r"""Applies Batch Normalization over a 5d input that is seen as a mini-batch of 4d inputs |
| |
| .. math:: |
| |
| y = \frac{x - mean[x]}{ \sqrt{Var[x] + \epsilon}} * gamma + beta |
| |
| The mean and standard-deviation are calculated per-dimension over |
| the mini-batches and gamma and beta are learnable parameter vectors |
| of size C (where C is the input size). |
| |
| During training, this layer keeps a running estimate of its computed mean |
| and variance. The running sum is kept with a default momentum of 0.1. |
| |
| During evaluation, this running mean/variance is used for normalization. |
| |
| Args: |
| num_features: num_features from an expected input of size batch_size x num_features x depth x height x width |
| eps: a value added to the denominator for numerical stability. Default: 1e-5 |
| momentum: the value used for the running_mean and running_var computation. Default: 0.1 |
| affine: a boolean value that when set to true, gives the layer learnable affine parameters. |
| |
| Shape: |
| - Input: :math:`(N, C, D, H, W)` |
| - Output: :math:`(N, C, D, H, W)` (same shape as input) |
| |
| Examples: |
| >>> # With Learnable Parameters |
| >>> m = nn.BatchNorm3d(100) |
| >>> # Without Learnable Parameters |
| >>> m = nn.BatchNorm3d(100, affine=False) |
| >>> input = autograd.Variable(torch.randn(20, 100, 35, 45, 10)) |
| >>> output = m(input) |
| """ |
| |
| def _check_input_dim(self, input): |
| if input.dim() != 5: |
| raise ValueError('expected 5D input (got {}D input)' |
| .format(input.dim())) |
| super(BatchNorm3d, self)._check_input_dim(input) |