一、概念
权值初始化是指在网络模型训练之前,对各节点的权值和偏置初始化的过程,正确的初始化会加快模型的收敛,从而加快模型的训练速度,而不恰当的初始化可能会导致梯度消失或梯度爆炸,最终导致模型无法训练。
如上图所示的一个基本的CNN网络结构,数据在网络结构中流动时,会有如下的公式(默认没有偏置):
在反向传播的过程中,由于是复合函数的求导,根据链式求导法则,会有两组导数,一个是损失函数Cost对Z的导数,一个是损失函数对W的导数,
1、损失函数关于状态Z的梯度:
2、损失函数关于W的梯度:
可以看出,在网络结构中,一个参数的初始化关系到网络能否训练出好的结果或者以多快的速度收敛。所以对权值初始化有如下的要求:
- 参数不能全部初始化为0或全为1,也不能全部初始化同一个值;(反向传播时梯度的更新值一样)
- 参数的初始化值不能太大;(针对激活函数是sigmoid和tanh,参数太大,梯度会消失)
- 参数的初始化值也不能太小;(针对激活函数是relu和sigmoid,参数太小,梯度会消失)
所有的参数初始化为0或者相同的数
最简单的初始化方法是将所有的参数初始化为0或者一个常数,但是使用这种特征会使网络中的所有神经元学习到的是相同的特征。
假设神经网络中只有一个有2个神经元的隐藏层,现在将偏置参数初始化为:bias=0,权值矩阵初始化为一个常数α。 网络的输入为(x1,x2),隐藏层使用的激活函数为ReLU,则隐藏层的每个神经元的输出都是relu(αx1+αx2)。 这就导致,对于loss function的值来说,两个神经元的影响是一样的,在反向传播的过程中对应参数的梯度值也是一样,也就说在训练的过程中,两个神经元的参数一直保持一致,其学习到的特征也就一样,相当于整个网络只有一个神经元。
过大或过小的初始化
如果权值的初始值过大,则会导致梯度爆炸,使得网络不收敛;过小的权值初始值,则会导致梯度消失,会导致网络收敛缓慢或者收敛到局部极小值。如果权值的初始值过大,则loss function相对于权值参数的梯度值很大,每次利用梯度下降更新参数时,参数更新的幅度也会很大,这就导致loss function的值在其最小值附近震荡。而过小的初始值则相反,loss关于权值参数的梯度很小,每次更新参数时,更新的幅度也很小,着就会导致loss的收敛很缓慢,或者在收敛到最小值前在某个局部的极小值收敛了。
所以不恰当的初始化可能会引起梯度消失或梯度爆炸,所以下面来了解一下什么是梯度消失与爆炸
二、梯度消失与爆炸
以上图所示的三层全连接网络为例,假设要计算W2的梯度,根据链式求导法则如下:H2 = H1 * W1
W2的梯度回用到上一层神经元的输出H1,如果H1的输出非常小,那么W2的梯度也会非常小,这就可能会造成梯度消失的现象,尤其是当网络层数增多时,乘以一个小值后面权值的梯度会更小,甚至会消失。这就使得损失函数得不到更新,模型的训练会停滞。而当H1的输出非常大时,W2的梯度会非常大,就会发生梯度爆炸。
一旦发生梯度消失或者爆炸,就会导致模型无法训练,而如果想避免这个现象,就得控制网络输出层的一个尺度范围,也就是不能让它太大或者太小。这就需要对权值进行合理的初始化,下面从代码中来理解一下:
建立一个layer=100的多层感知机,其中每层的神经元个数neural_num=256,如下:
class MLP(nn.Module):
def __init__(self, neural_num, layers):
super(MLP, self).__init__()
self.linears = nn.ModuleList([nn.Linear(neural_num, neural_num, bias=False) for i in range(layers)])
self.neural_num = neural_num
def forward(self, x):
for (i, linear