Source code for nntoolbox.components.self_normalizing

import torch
from torch import nn, Tensor
from typing import Sequence
from torch.nn.init import uniform_, _calculate_fan_in_and_fan_out
import math
import numpy as np


__all__ = ['SelfNormalizingMLP']


[docs]class SelfNormalizingMLP(nn.Sequential): ''' Implement Self-Normalizing Neural Networks: https://papers.nips.cc/paper/6698-self-normalizing-neural-networks.pdf ''' def __init__( self, in_features: int, out_features: int, hidden_layer_sizes: Sequence[int]=(512,), drop_ps=(0.5, 0.5) ): layers = [] if isinstance(drop_ps, float): drop_ps = [drop_ps for _ in range(len(hidden_layer_sizes) + 1)] for i in range(len(hidden_layer_sizes)): if i == 0: in_features = in_features else: in_features = hidden_layer_sizes[i - 1] drop_p = drop_ps[i] if drop_p != 0: layers.append(nn.AlphaDropout(p=drop_p)) layers.append(SelfNormalizingLinear( in_features=in_features, out_features=hidden_layer_sizes[i], bias=True, )) layers.append(nn.SELU()) if drop_ps[-1] != 0: layers.append(nn.AlphaDropout(p=drop_ps[-1])) layers.append(SelfNormalizingLinear(in_features=hidden_layer_sizes[-1], out_features=out_features, bias=True)) super(SelfNormalizingMLP, self).__init__(*layers)
class SelfNormalizingLinear(nn.Linear): ''' Linear layer with special initialization ''' def reset_parameters(self): self_normalize_normal_(self.weight) if self.bias is not None: # fan_in, _ = _calculate_fan_in_and_fan_out(self.weight) # bound = 1 / math.sqrt(fan_in) uniform_(self.bias, -0.0, 0.0) def self_normalize_normal_(tensor: Tensor): std = 1 / np.sqrt(tensor.shape[1]) with torch.no_grad(): return tensor.normal_(0.0, std)