torch.nn.init


作者:elfin



Top  ---  Bottom

​ 初始化在深度学习模型训练中占有非常重要的位置,好的初始化可以对模型性能有不小的提升。下面将介绍pytorch的一些初始化方法。


Top  ---  Bottom

1、calculate_gain

torch.nn.init.calculate_gain(nonlinearity, param=None)

​ 见名知意,这个接口是计算增益的!计算什么的增益呢?它计算的是非线性函数的增益。

nonlinearity gain
Linear / Identity 1
Conv{1,2,3}D 1
Sigmoid 1
Tanh \(\frac{5}{3}\)
ReLU \(\sqrt{2}\)
Leaky Relu \(\sqrt{\frac{2}{1 + negative\_slope^2}}\)
SELU \(\frac{3}{4}\)

参数:

  • nonlinearity:非线性函数(nn.functional name);
  • param:非线性函数的可选参数

案例:

# leaky_relu with negative_slope=0.2
>>> gain = nn.init.calculate_gain('leaky_relu', 0.2)
>>> gain


Top  ---  Bottom

2、uniform_

torch.nn.init.uniform_(tensor, a=0.0, b=1.0)

均匀分布初始化。需要指定张量对象,均匀分布的起始与终点值。

参数:

  • tensor:一个张量实例;
  • a:均匀分布的下确界;
  • b:均匀分布的上确界。

案例:

>>> w = torch.empty(3, 5)
>>> nn.init.uniform_(w)

Top  ---  Bottom

3、normal_

torch.nn.init.normal_(tensor, mean=0.0, std=1.0)

默认标准正态分布初始化。

……


Top  ---  Bottom

4、constant_

torch.nn.init.constant_(tensor, val)

使用val填充tensor.

……


Top  ---  Bottom

5、ones_

torch.nn.init.ones_(tensor)

使用1填充张量tensor.

……


Top  ---  Bottom

6、zeros_

torch.nn.init.zeros_(tensor)

使用0填充张量tensor.

……


Top  ---  Bottom

7、eye_

torch.nn.init.eye_(tensor)

用单位矩阵填充二维输入张量。在线性层中保留输入的标识,在线性层中保留尽可能多的输入。

案例:

>>> w = torch.empty(3, 5)
>>> nn.init.eye_(w)

Top  ---  Bottom

8、dirac_

torch.nn.init.dirac_(tensor, groups=1)

用狄拉克三角函数填充{3,4,5}维输入张量。在卷积层中保留输入的标识,在卷积层中保留尽可能多的输入通道。在groups>1的情况下,每组通道保持同一性。

\[\delta \left ( x \right )= \left\{\begin{matrix} \infty ,\,if\,x=0\\ 0 ,\,\,if\,x\neq0 \end{matrix}\right. \]

\[H \left ( x \right )= \left\{\begin{matrix} 1 ,\,if\,x=0\\ 0 ,\,\,if\,x\neq0 \end{matrix}\right. \]

参数:

  • tensor:一个{3,4,5}维的输入张量;
  • groups:卷积层的分组。

案例:

>>> w = torch.empty(3, 16, 5, 5)
>>> nn.init.dirac_(w)
>>> w = torch.empty(3, 24, 5, 5)
>>> nn.init.dirac_(w, 3)

Top  ---  Bottom

9、xavier_uniform_

torch.nn.init.xavier_uniform_(tensor, gain=1.0)

xavier均匀分布\(\mathcal{U}(-a, a)\)采样填充张量tensor实现张量的初始化。

\[a = \text{gain} \times \sqrt{\frac{6}{fan\_in + fan\_out}} \]

其中:

  • \(fan\_in\)\(tensor.size(1) \times tensor[0][0].numel()\)
  • \(fan\_out\)\(tensor.size(0) \times tensor[0][0].numel()\)

参数:

  • tensor:一个torch张量
  • gain:可选的缩放因子

案例:

>>> w = torch.empty(3, 5)
>>> nn.init.xavier_uniform_(w, gain=nn.init.calculate_gain('relu'))

Top  ---  Bottom

10、xavier_normal_

torch.nn.init.xavier_normal_(tensor, gain=1.0)

xavier正态分布\(\mathcal{N}(0, \text{std}^2)\)采样填充张量tensor实现张量的初始化。

\[\text{std} = \text{gain} \times \sqrt{\frac{2}{fan\_in + fan\_out}} \]

\(fan\_in\)\(fan\_out\)同上。参数同上。

案例:

>>> w = torch.empty(3, 5)
>>> nn.init.xavier_normal_(w)

Top  ---  Bottom

11、kaiming_uniform_????

何凯明初始化是xavier初始化的变种,他的初始化方法是非常重要的方法!

torch.nn.init.kaiming_uniform_(tensor, a=0, mode='fan_in', nonlinearity='leaky_relu')

kaiming_uniform_均匀分布\(\mathcal{U}(-\text{bound}, \text{bound})\)采样填充张量tensor实现张量的初始化。

\[\text{bound} = \text{gain} \times \sqrt{\frac{3}{fan\_mode}} \]

参数:

  • tensor:一个torch张量
  • a:此层之后使用的整流器的负斜率(仅与“leaky_relu”一起使用)
  • mode:可选 “fan_in”(默认) 和 “fan_out”。前者保持forward的权值方差一致;后者保持backwards的权值方差一致。
  • nonlinearity:非线性函数(nn.functional name),建议仅与“relu”或“leaky_relu”一起使用(默认)。

案例:

>>> w = torch.empty(3, 5)
>>> nn.init.kaiming_uniform_(w, mode='fan_in', nonlinearity='relu')

Top  ---  Bottom

12、kaiming_normal_????

torch.nn.init.kaiming_normal_(tensor, a=0, mode='fan_in', nonlinearity='leaky_relu')

kaiming_normal_正态分布\(\mathcal{N}(0, \text{std}^2)\)采样填充张量tensor实现张量的初始化。

\[\text{std} = \frac{\text{gain}}{\sqrt{fan\_mode}} \]

参数同上。

案例:

>>> w = torch.empty(3, 5)
>>> nn.init.kaiming_normal_(w, mode='fan_out', nonlinearity='relu')

Top  ---  Bottom

13、orthogonal_

torch.nn.init.orthogonal_(tensor, gain=1)

用一个(半)正交矩阵填充输入张量,如《深层线性神经网络学习非线性动力学精确解》中所述。输入张量必须至少有2个维度,对于超过2个维度的张量,尾部维度将被平铺。

参数:

  • tensor:一个大于等于2维的张量
  • gain:可选的缩放因子

案例:

>>> w = torch.empty(3, 5)
>>> a = nn.init.orthogonal_(w)
>>> a
tensor([[ 0.8019, -0.0586, -0.3235, -0.3922,  0.3082],
        [ 0.1892,  0.0526,  0.0613,  0.7863,  0.5826],
        [-0.5395, -0.3481, -0.4893, -0.2158,  0.5493]])
>>> b = a[1,:]*a[2,:]
>>> b.numpy().sum()
8.940697e-08
>>> c = a[:,0]*a[:,1]
>>> c.numpy().sum()
0.1507516

通过上面的操作我们可以发现行向量两两正交!


Top  ---  Bottom

14、sparse_

torch.nn.init.sparse_(tensor, sparsity, std=0.01)

将2D 输入张量作为稀疏矩阵进行填充,其中非零元素将从正态分布\(\mathcal{N}(0, 0.01)\)中抽取。实际是先使用正态分布初始化,在按照sparsity乘以行数获取零元素的个数,在到初始化的张量中随机采样索引将张量对应位置置零。

参数:

  • tensor2D torch张量
  • sparsity:每列中要设置为零的元素的分数
  • std:用于产生非零值的正态分布的标准差

案例:

>>> w = torch.empty(3, 5)
>>> nn.init.sparse_(w, sparsity=0.1)
tensor([[ 0.0000, -0.0045,  0.0000,  0.0098,  0.0000],
        [-0.0174,  0.0000, -0.0116,  0.0118, -0.0096],
        [ 0.0005,  0.0060, -0.0041,  0.0000, -0.0107]])


Top  ---  Bottom

完!