神經網絡之權重初始化


權重初始化

模型權重的初始化對於網絡的訓練很重要, 不好的初始化參數會導致梯度傳播問題, 降低訓練速度; 而好的初始化參數, 能夠加速收斂, 並且更可能找到較優解. 如果權重一開始很小,信號到達最后也會很小;如果權重一開始很大,信號到達最后也會很大。不合適的權重初始化會使得隱藏層的輸入的方差過大,從而在經過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=\sum_i w_ix_i+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 中推薦使用 \(\text{Var}(W) = \frac{2}{n_\text{in} + n_\text{out}}\).
  3. Xavier (均勻分布)
  4. MSRA

上述初始化方式的1,2僅考慮每層輸入的方差, 而后兩種方式考慮輸入與輸出的方差, 保持每層的輸入與輸出方差相等. 2,4 方法中針對ReLU激活函數, 放大了一倍的方差.

Xavier權重初始化

Xavier初始化可以幫助減少梯度彌散問題, 使得信號在神經網絡中可以傳遞得更深。是最為常用的神經網絡權重初始化方法。

算法根據輸入和輸出神經元的數量自動決定初始化的范圍: 定義參數所在的層的輸入維度為n,輸出維度為m,那么參數將從\([-{\sqrt{6\over m+n}},{\sqrt{6\over m+n}}]\)均勻分布中采樣。

公式推導

假設輸入一層X,輸出一層Y,那么

\[Y = W_1X_1 + W_2X_2 + \dotsb + W_n X_n \]

按照獨立變量相乘的方差公式,可以計算出:

\[\text{Var}(W_iX_i) = E[X_i]^2 \text{Var}(W_i) + E[W_i]^2 \text{Var}(X_i) + \text{Var}(W_i)\text{Var}(X_i) \]

我們期望輸入X和權重W都是零均值,因此簡化為

\[\text{Var}(W_iX_i) = \text{Var}(W_i)\text{Var}(X_i) \]

進一步假設所有的\(X_i,W_i\)都是獨立同分布,則有:

\[\text{Var}(Y) = \text{Var}(W_1X_1 + W_2X_2 + \dotsb + W_n X_n) = n\text{Var}(W_i)\text{Var}(X_i) \]

即輸出的方差與輸入有關,為使輸出的方差與輸入相同,意味着使\(n\text{Var}(W_i)=1\).因此\(\text{Var}(W_i) = \frac{1}{n}=\frac{1}{n_{in}}\).

如果對反向傳播的梯度運用同樣的步驟,可得:\(\text{Var}(W_i) = \frac{1}{n_\text{out}}\).

由於\(n_{in},n_{out}\)通常不相等,所以這兩個方差無法同時滿足,作為一種折中的方案,可使用介於\(\frac{1}{n_{in}},\frac{1}{n_{out}}\)之間的數來代替:簡單的選擇是\(\text{Var}(W_i) = \frac{2}{n_\text{in} + n_\text{out}}\).

可以根據均勻分布的方差,反推出W的均勻分布:

由於 [a,b] 區間的均勻分布的方差為:\(\text{Var}={(b-a)^2\over 12}\),使其零均值,則b=-a,所以\(\text{Var}={(2b)^2\over 12}=\frac{2}{n_\text{in} + n_\text{out}}\),可得\(b={\sqrt{6}\over \sqrt{n_{in}+n_{out}}}\).

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

\[W \sim U[-{\sqrt{6}\over \sqrt{n_j+n_{j+1}}},{\sqrt{6}\over \sqrt{n_j+n_{j+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中提出使用\(\text{Var}(W) = \frac{2}{n_\text{in}}\)放大一倍方差來保持方差的平穩。

前向和后向推導的方差均控制在\({2\over n}\),綜合起來使用均值為0,方差為\(\sqrt{4\over n_{in}+n_{out}}\)的高斯分布.

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

參考


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM