一般来说全连接网络的结构示意图如上:
我们先来看w2的梯度:
可以看到,梯度的值严重依赖于中间层的输出值。因此,我们必须控制这种输出的范围。 才能够让我们各个层的标准差处于正常范围。
方差一致性:保持数据尺度维持在恰当的范围,通常方差为1.
激活函数:饱和函数,如Sigmoid,Tanh
同时考虑了前向传播和反向传播的数据尺度问题。最后我们得到权值的方差应该为:
D ( W ) = 2 n i + n i + 1 D(W) = \frac{2}{n_i+n_{i+1}} D(W)=ni+ni+12
其中, n i n_i ni表示输入神经元的个数, n i + 1 n_{i+1} ni+1表示输出神经元的个数。
通常情况下:Xavier采用均匀分布。如果它满足的分布如下:
可以得出如上的D(W)。
即,我们需要让
D ( W ) = 2 n i + n i + 1 = a 2 3 D(W)= \frac{2}{n_i+n_{i+1}} = \frac{a^2}{3} D(W)=ni+ni+12=3a2
可以得到: a = 6 n i + n i + 1 a = \frac{\sqrt{6}}{\sqrt{n_i+n_{i+1}}} a=ni+ni+16
由于非饱和激活函数ReLU的使用,Xavier的方法不再适用。
为了解决非饱和激活函数下,Xiaver的初始化方法不再适用的问题,何恺明提出了新的初始化方法。
这种方法适用于ReLU函数及其变种函数。
在这类激活函数下,可以推导出:
D ( W ) = 2 n i D(W) = \frac{2}{n_i} D(W)=ni2
对于ReLU的变种(即负半轴具有一定斜率)的情况下:
D ( W ) = 2 ( 1 + a 2 ) × n i D(W)=\frac{2}{(1 + a^2)\times n_i} D(W)=(1+a2)×ni2
其中,a即为负半轴的斜率。
结合以上,权值的标准差为:
s t d ( W ) = 2 ( 1 + a 2 ) × n i std(W) = \sqrt{\frac{2}{(1+a^2)\times n_i}} std(W)=(1+a2)×ni2
好的,现在根据这个公式对权值进行初始化。再次观察网络层的输出范围:
nn.init.normal_(m.weight.data, std=np.sqrt(2 / self.neural_num))
以上,就是利用我的推导得出的标准差,对W进行0均值,std为 2 神 经 元 个 数 \sqrt{\frac{2}{神经元个数}} 神经元个数2的初始化。在这种情况下,我们查看输出:
layer:0, std:0.826629638671875
layer:1, std:0.8786815404891968
layer:2, std:0.9134422540664673
layer:3, std:0.8892471194267273
...
可以看到,恺明法的初始化是可以让各个层的输出值的std大约在1附近。
Pytorch中提供了恺明初始化的方法,使用的代码如下:
nn.init.kaiming_normal_(m.weight.data)
以上。