权重初始化
预备知识
期望的性质
E(C)=C(1)
E(aX)=aE(X)(2)
E(X+Y)=E(X)+E(Y)(3)
E(i=1∑naiXi+C)=i=1∑naiE(Xi)+C(4)
当X和Y相互独立时,
E(XY)=E(X)E(Y)(5)
方差的性质
D(X)=E((X−E(X))2)=E(X2−2E(X)X+E2(X))=E(X2)−2E2(X)+E2(X)=E(X2)−E2(X)(6)
D(X)̸<0(7)
D(C)=0(8)
D(CX)=C2D(X)(9)
D(aX+bY)=a2D(X)+b2D(Y)+2abE(X−E(X))(Y−E(Y))
如果X,Y相互独立,则
D(aX+bY)=a2D(X)+b2D(Y)(10)
如果X,Y相互独立,且E(X)=E(Y)=0,由式(6)和式(5),
D(XY)=E((XY−E(XY))2)=E(X2Y2)−E2(XY)=E(X2)E(Y2)−E2(X)E2(Y)=E(X2)E(Y2)=E((X−E(X))2)E((Y−E(Y))2)=D(X)D(Y)(11)
为何初始化
神经网络使用误差反向传播算法(梯度下降)来训练,其需要从输出向输入逐层求导,根据导数(梯度)来更新权重,然后继续下一轮迭代。如果求出的导数(梯度)过小,那么权重的更新幅度会很小,学习速度就会变慢,甚至无法收敛。训练之前需要给神经网络的权重赋初始值,初始值的选择会对导数有很大影响。
以神经网络中常用的**函数sigmoid函数为例,如图,当函数的输入值的绝对值越来越大时,函数值越来越平滑,趋于饱和,梯度趋于0。如果把输入值限制在[−2,2]区间,sigmoid函数可以获得较大的梯度。神经网络的结构是线性变换层然后到**层,这就要求线性变换层的输出值在[−2,2]区间。通过给权重赋恰当的初始值,可以使线性变换输出值在较理想的范围内。
假设z为神经网络层线性变换的输出结果,w为该层参数,x为该层输入,
z=i=1∑nwixi+b
假设输入数据中每一维都是相互独立的,根据公式(3)、公式(10)和公式(11),z的方差为
D(z)=D(i=1∑nwixi)=i=1∑nD(wixi)=nD(wixi)=nD(wi)D(xi)(12)
若输入层有1000个神经元,隐藏层有1个神经元,输入数据x是1000维的全1向量。使用标准正态分布(均值为0,方差为1)来初始化权重矩阵w,偏执初始化为0,则输出z服从均值为0,方差为1000的正态分布。
由此可见,数据经过线性变换之后,方差被放大了数倍(放大的倍数与输入的维度相关),输出绝对值远大于1的概率也增大了,再经过sigmoid**,就有可能使sigmoid饱和,梯度变得很小,权重更新变得缓慢。
几种初始化方式
全零初始化
将所有参数都初始化为0,这时线性变换的输出的期望能达到理想状态。但是参数全0时不同神经元的输出相同,各神经元的梯度也完全一样,这将导致更新后的参数仍然保持一样的状态,神经网络将无法训练。所以全零初始化不可行。
随机初始化
简单的随机初始化(正态分布或者均匀分布)会遇到输入经线性变换后的方差增大的问题,如上所述。
Xavier初始化
Xavier初始化的基本思想是保持输出的方差和输入一致,这样可以避免**后所有的输出值趋向于0。
可以使用均值为0、方差为1的随机变量初始化权重,即D(wi)=1,但是由于线性变换输出的方差会随着神经元个数改变,所以需要加上对方差大小的规范化,具体做法是在随机初始化的基础上乘以规范化系数n1,其中n是输入神经元个数。根据公式(10)有
D(z)=D(i=1∑nn1wixi)=i=1∑n(n1)2D(wixi)=D(wixi)=D(wi)D(xi)=D(xi)
等价的也可以使用均值为0,方差为n1的随机变量来初始化权重,即D(wi)=n1,根据公式(12)有
D(z)=nD(wi)D(xi)=D(xi)
但是还有考虑反向传播的场景,反向传播是正向传播的逆过程,此时的输入是前向传播的输出,所以应该令
D(wi)=nin+nout1
Xavier初始化适用于**函数是sigmoid和tanh。使用的分布可以是正态分布或者均匀分布。
He初始化
Xavier初始化没有考虑非线性映射对下一层输入的影响,比如使用Relu**函数之后,输出的期望往往不是0。He初始化提出了改进方法:将非线性映射造成的影响考虑进参数初始化中,它提出方差规范化系数应该是n2而不是n1。
He初始化适用于**函数是Relu。使用的分布可以是正态分布或者均匀分布。
BN
BN层将输入数据分布变成标准正态分布(规范化),这样可以保证每一层神经网络的输入保持相同分布。它可以削弱不恰当的参数初始化造成的影响,使参数初始化不依赖于神经元个数。有BN层时,参数初始化可以使用随机初始化方式。
lecun初始化(正态分布)
tf.initializers.lecun_normal函数。
从方差为nin1的截断正态分布中采样,得到权重初始化值。
lecun初始化(均匀分布)
tf.initializers.lecun_uniform函数。
从[−nin3,nin3]的均匀分布中中采样,得到权重初始化值。
Xavier初始化(正态分布)
也叫Glorot初始化。
tf.initializers.GlorotNormal类。
从方差为nin+nout2的截断正态分布中采样,得到权重初始化值。
Xavier初始化(均匀分布)
tf.initializers.GlorotUniform类。
从[−nin+nout6,nin+nout6]的均匀分布中中采样,得到权重初始化值。
He初始化(正态分布)
tf.initializers.he_normal函数。
从方差为nin2的截断正态分布中采样,得到权重初始化值。
He初始化(均匀分布)
tf.initializers.he_uniform函数。
从[−nin6,nin6]的均匀分布中中采样,得到权重初始化值。
torch.nn.init.calculate_gain函数根据非线性函数来计算出权重初始化系数,后面会用到。
Xavier初始化(正态分布)
torch.nn.init.xavier_normal_函数。
Xavier初始化(均匀分布)
torch.nn.init.xavier_uniform_函数。
He初始化(正态分布)
torch.nn.init.kaiming_normal_函数。
He初始化(均匀分布)
torch.nn.init.kaiming_uniform_函数。