神经网络权重初始化总结

神经网络之权重初始化

https://www.cnblogs.com/makefile/p/init-weight.html?utm_source=itdadao&utm_medium=referral

权重初始化

模型权重的初始化对于网络的训练很重要, 不好的初始化参数会导致梯度传播问题, 降低训练速度; 而好的初始化参数, 能够加速收敛, 并且更可能找到较优解. 如果权重一开始很小,信号到达最后也会很小;如果权重一开始很大,信号到达最后也会很大。不合适的权重初始化会使得隐藏层的输入的方差过大,从而在经过sigmoid这种非线性层时离中心较远(导数接近0),因此过早地出现梯度消失.如使用均值0,标准差为1的正态分布初始化在隐藏层的方差仍会很大. 不初始化为0的原因是若初始化为0,所有的神经元节点开始做的都是同样的计算,最终同层的每个神经元得到相同的参数.

好的初始化方法通常只是为了增快学习的速度(加速收敛),在某些网络结构中甚至能够提高准确率.

下面介绍几种权重初始化方式.

  1. 初始化为小的随机数,如均值为0,方差为0.01的高斯分布:
    W=0.01 * np.random.randn(D,H) 然而只适用于小型网络,对于深层次网络,权重小导致反向传播计算中梯度也小,梯度"信号"被削弱.
  2. 上面1中的分布的方差随着输入数量的增大而增大,可以通过正则化方差来提高权重收敛速率,初始权重的方式为正态分布: w = np.random.randn(n) / sqrt(n). 这会使得中间结果z=∑iwixi+bz=∑iwixi+b的方差较小,神经元不会饱和,学习速度不会减慢.
    论文 Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification by He et al. 中阐述了ReLU神经元的权值初始化方式,方差为2.0/n, 高斯分布权重初始化为: w = np.random.randn(n) * sqrt(2.0/n), 这是使用ReLU的网络所推荐的一种方式.
    论文[Bengio and Glorot 2010]: Understanding the difficulty of training deep feedforward neuralnetworks 中推荐使用 Var(W)=2nin+noutVar(W)=2nin+nout.
  3. Xavier (均匀分布)
  4. MSRA

上述初始化方式的1,2仅考虑每层输入的方差, 而后两种方式考虑输入与输出的方差, 保持每层的输入与输出方差相等. 2,4 方法中针对ReLU激活函数, 放大了一倍的方差.

Xavier权重初始化

Xavier初始化可以帮助减少梯度弥散问题, 使得信号在神经网络中可以传递得更深。是最为常用的神经网络权重初始化方法。

算法根据输入和输出神经元的数量自动决定初始化的范围: 定义参数所在的层的输入维度为n,输出维度为m,那么参数将从[−6m+n−−−−√,6m+n−−−−√][−6m+n,6m+n]均匀分布中采样。

公式推导

假设输入一层X,输出一层Y,那么

Y=W1X1+W2X2+⋯+WnXnY=W1X1+W2X2+⋯+WnXn


按照独立变量相乘的方差公式,可以计算出:

Var(WiXi)=E[Xi]2Var(Wi)+E[Wi]2Var(Xi)+Var(Wi)Var(Xi)Var(WiXi)=E[Xi]2Var(Wi)+E[Wi]2Var(Xi)+Var(Wi)Var(Xi)


我们期望输入X和权重W都是零均值,因此简化为

Var(WiXi)=Var(Wi)Var(Xi)Var(WiXi)=Var(Wi)Var(Xi)


进一步假设所有的Xi,WiXi,Wi都是独立同分布,则有:

Var(Y)=Var(W1X1+W2X2+⋯+WnXn)=nVar(Wi)Var(Xi)Var(Y)=Var(W1X1+W2X2+⋯+WnXn)=nVar(Wi)Var(Xi)


即输出的方差与输入有关,为使输出的方差与输入相同,意味着使nVar(Wi)=1nVar(Wi)=1.因此Var(Wi)=1n=1ninVar(Wi)=1n=1nin.

 

如果对反向传播的梯度运用同样的步骤,可得:Var(Wi)=1noutVar(Wi)=1nout.

由于nin,noutnin,nout通常不相等,所以这两个方差无法同时满足,作为一种折中的方案,可使用介于1nin,1nout1nin,1nout之间的数来代替:简单的选择是Var(Wi)=2nin+noutVar(Wi)=2nin+nout.

可以根据均匀分布的方差,反推出W的均匀分布:

由于 [a,b] 区间的均匀分布的方差为:Var=(b−a)212Var=(b−a)212,使其零均值,则b=-a,所以Var=(2b)212=2nin+noutVar=(2b)212=2nin+nout,可得b=6√nin+nout√b=6nin+nout.

因此,Xavier初始化的就是按照下面的均匀分布(uniform distribution):

W∼U[−6–√nj+nj+1−−−−−−−−√,6–√nj+nj+1−−−−−−−−√]W∼U[−6nj+nj+1,6nj+nj+1]

 

xavier权重初始化的作用,使得信号在经过多层神经元后保持在合理的范围(不至于太小或太大)。

caffe当前的xavier实现代码

/* 输入blob的shape:(num, a, b, c)对应(输出channel,输入channel,b*c=kernel size)
 扇入 fan_in = a * b * c
 扇出 fan_out = num * b * c
 scale = sqrt(3 / n) 这里的n根据参数决定:fan_in, fan_out, 或着平均。
 这里的sqrt(3 / n)中当n=(n_j + n_{j+1})/2时就是上面式子中的$\sqrt{6}/\sqrt{n_j + n_{j+1}}.
 然后用[-scale,scale]的均匀分布随机采样初始化权重
*/
template <typename Dtype>  
class XavierFiller : public Filler<Dtype> {  
 public:  
  explicit XavierFiller(const FillerParameter& param)  
      : Filler<Dtype>(param) {}  
  virtual void Fill(Blob<Dtype>* blob) {
    int fan_in = blob->count() / blob->num();  
    int fan_out = blob->count() / blob->channels();  
    Dtype n = fan_in;  
    if (this->filler_param_.variance_norm() == 
        FillerParameter_VarianceNorm_AVERAGE) {  
      n = (fan_in + fan_out) / Dtype(2);  
    } else if (this->filler_param_.variance_norm() ==  
        FillerParameter_VarianceNorm_FAN_OUT) {  
      n = fan_out;  
    }  
    Dtype scale = sqrt(Dtype(3) / n);
    caffe_rng_uniform<Dtype>(blob->count(), -scale, scale,  
        blob->mutable_cpu_data());
  }  
};  

MSRA Filler

上边所提的初始化方式为使每层方差一致,从而不会发生前向传播爆炸和反向传播梯度消失等问题。对于ReLU激活函数,其使一半数据变成0,初始时这一半的梯度为0,而tanh和sigmoid等的输出初始时梯度接近于1.因此使用ReLU的网络的参数方差可能会波动。论文Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification,Kaiming He中提出使用Var(W)=2ninVar(W)=2nin放大一倍方差来保持方差的平稳。

前向和后向推导的方差均控制在2n2n,综合起来使用均值为0,方差为4nin+nout−−−−−−√4nin+nout的高斯分布.

caffe MSRA Filler实现代码

/**
 * Fills a Blob with values $ x \sim N(0, \sigma^2) $
 * A Filler based on the paper [He, Zhang, Ren and Sun 2015]: 
 * Specifically accounts for ReLU nonlinearities.
 */
template <typename Dtype>
class MSRAFiller : public Filler<Dtype> {
 public:
  explicit MSRAFiller(const FillerParameter& param)
      : Filler<Dtype>(param) {}
  virtual void Fill(Blob<Dtype>* blob) {
    CHECK(blob->count());
    int fan_in = blob->count() / blob->num();
    int fan_out = blob->count() / blob->channels();
    Dtype n = fan_in;  // default to fan_in
    if (this->filler_param_.variance_norm() ==
        FillerParameter_VarianceNorm_AVERAGE) {
      n = (fan_in + fan_out) / Dtype(2);
    } else if (this->filler_param_.variance_norm() ==
        FillerParameter_VarianceNorm_FAN_OUT) {
      n = fan_out;
    }
    Dtype std = sqrt(Dtype(2) / n);
    caffe_rng_gaussian<Dtype>(blob->count(), Dtype(0), std,
        blob->mutable_cpu_data());
    CHECK_EQ(this->filler_param_.sparse(), -1)
         << "Sparsity not supported by this Filler.";
  }
};

bias初始化

通常初始化为0(若初始化为0.01等值,可能并不能得到好的提升,反而可能下降)

Batch Normalization

在网络中间层中使用 Batch Normalization 层一定程度上能够减缓对较好的网络参数初始化的依赖,使用方差较小的参数分布即可. 参考论文 Batch Normalization

总结

  1. 当前的主流初始化方式 Xavier,MSRA 主要是为了保持每层的输入与输出方差相等, 而参数的分布采用均匀分布或高斯分布均可.
  2. 在广泛采用 Batch Normalization 的情况下, 使用普通的小方差的高斯分布即可.
  3. 另外, 在迁移学习的情况下, 优先采用预训练的模型进行参数初始化.

weight initialization

weight initialization

 

参考

原文: https://www.cnblogs.com/makefile/p/init-weight.html?utm_source=itdadao&utm_medium=referral © 康行天下


著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
原文: https://www.cnblogs.com/makefile/p/init-weight.html?utm_source=itdadao&utm_medium=referral © 康行天下
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
原文: https://www.cnblogs.com/makefile/p/init-weight.html?utm_source=itdadao&utm_medium=referral © 康行天下

### 权重初始化的最佳实践与方法 在神经网络中,权重初始化是一个非常重要的环节。如果初始权重设置不当,则可能导致梯度消失或爆炸等问题,从而影响模型的收敛速度和最终性能。 #### 方法概述 常见的权重初始化方法包括随机初始化、Xavier 初始化以及 He 初始化等。以下是这些方法的具体介绍: 1. **随机初始化** 随机初始化是最简单的方法之一,通常会从均匀分布或正态分布中抽取权重值。然而,这种方法可能无法很好地适应深层网络结构,因为随着层数增加,激活函数可能会导致梯度逐渐变小或者变得过大[^4]。 2. **Xavier Initialization (Glorot Initialization)** Xavier 初始化旨在解决传统随机初始化带来的问题。它基于这样一个假设:每层输入信号的标准差应该等于其输出标准差。对于使用 Sigmoid 或 Tanh 激活函数的情况特别有效。具体而言,当采用均匀分布时,权重可以从范围 \([-limit, limit]\) 中选取,其中 \(limit=\sqrt{\frac{6}{n_{in}+n_{out}}}\),\(n_{in}\) 和 \(n_{out}\) 分别表示当前层节点数及其下一层节点数;如果是正态分布,则均值为零,方差设定为\(\frac{2}{n_{in} + n_{out}}\) 。 3. **He Initialization** 对于 ReLU 类型的非线性激活函数来说,He 初始化更为合适。该技术调整了上述公式中的分母部分,仅考虑输入单元数量而非平均两者。因此,在利用正态分布的情况下,方差被定义成\(\frac{2}{n_{in}}\) ,这有助于保持前向传播过程中各层间数据流动稳定并促进更快学习过程发生 。 下面展示了一个简单的例子来说明如何在 PyTorch 中实现不同的权重初始化策略: ```python import torch.nn as nn import math def init_weights(m): if isinstance(m, nn.Linear): # Linear Layer nn.init.xavier_uniform_(m.weight.data) m.bias.data.fill_(0) model = nn.Sequential( nn.Linear(784, 128), nn.ReLU(), nn.Linear(128, 64), nn.ReLU(), nn.Linear(64, 10) ).apply(init_weights) ``` 此代码片段展示了怎样通过自定义 `init_weights` 函数遍历整个模型,并根据不同类型的模块应用相应的初始化方案。这里选择了 Xavier Uniform 方式处理全连接层(`nn.Linear`) 的权值矩阵,并将偏置项全部赋值为零。 另外值得注意的是,在某些特殊架构比如卷积神经网络(CNNs)里边还存在局部感受野的概念,这意味着即使是在同一个特征图内部也可能存在着空间上的依赖关系需要加以建模。所以在实际操作当中往往还需要结合具体的业务场景做出适当的选择与优化[^2]。 最后一点补充关于批量标准化(Batch Normalization), 它可以一定程度缓解由于不良权重初值所引发的一些数值不稳定现象,但并不能完全替代良好的初始化工作 [^3].
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值