LRN和Batch Norm

LRN

LRN全稱爲Local Response Normalization,局部相應歸一化層。git

message LRNParameter {
  optional uint32 local_size = 1 [default = 5];
  optional float alpha = 2 [default = 1.]; 
  optional float beta = 3 [default = 0.75];
  enum NormRegion {
    ACROSS_CHANNELS = 0; 
    WITHIN_CHANNEL = 1; 
  }
  optional NormRegion norm_region = 4 [default = ACROSS_CHANNELS];
  optional float k = 5 [default = 1.]; 
  enum Engine {
    DEFAULT = 0; 
    CAFFE = 1; 
    CUDNN = 2; 
  }
  optional Engine engine = 6 [default = DEFAULT];
}

NormRegion選擇通道間歸一化仍是通道內空間區域歸一化,默認是AcrOSS_CHANNELS,通道間。github

local_size表示:通道間時爲求和的通道數,通道內是爲求和的區間邊長,默認爲5。ide

alpha縮放因子,beta指數項。函數

在通道間歸一化模式中,局部區域範圍是:local_size*1*1;在通道內歸一化模式中,局部區域範圍是:1*local_size*local_size。歸一化後的值:學習

\widetilde{x_{i}}=\frac{x_{i}}{({k+\frac{\alpha}{N}\sum_{i=0}^{N}x_{i}^{2}})^{\beta}}

實現代碼見:lrn_layer.cpp,也比較簡單。測試

Batch Normalization

ZCA白化:http://blog.csdn.net/hjimce/article/details/50864602ui

對輸入數據進行預處理,減均值->zscore->白化能夠逐級提高隨機初始化的權重對數據分割的有效性,還能夠下降overfit的可能性。Google的這篇論文http://arxiv.org/pdf/1502.03167v3.pdf, 提出了BN層。google

首先,BN不是針對x(輸入的),而是針對Wx+b的,論文的解釋是:Wx+b每維的均值自己就接近0、方差接近1,因此在Wx+b後使用Batch Normalization能獲得更穩定的結果。spa

文中使用了相似z-score的歸一化方式:每一維度減去自身均值,再除以自身標準差。因爲使用的是隨機梯度降低法,這些均值和方差也只能在當前迭代的batch中計算。Wx+b的均值和方差是對整張map求得的,在batch_size * channel * height * width這麼大的一層中,對總共batch_size*height*width個像素點統計獲得一個均值和一個標準差,共獲得channel組參數.net

在Normalization完成後,Google的研究員仍對數值穩定性不放心,又加入了兩個參數gamma和beta,使得:

y^{k}=\gamma^{k}\widehat{x}^{k}+\beta^{k}

在BP的時候,咱們須要求最終的損失函數對gamma和beta兩個參數的導數,還要求損失函數對Wx+b中的x的導數,以便使偏差繼續向後傳播。

在訓練的最後一個epoch時,要對這一epoch全部的訓練樣本的均值和標準差進行統計,這樣在一張測試圖片進來時,使用訓練樣本中的標準差的指望和均值的指望對測試數據進行歸一化,注意這裏標準差使用的指望是其無偏估計:

123

優點是:更高的學習率,更快的訓練過程;防止過擬合,移除或使用較小的dropout;取消LRN層。

caffe的BN

參數定義:

message BatchNormParameter {
  // If false, accumulate global mean/variance values via a moving average. If
  // true, use those accumulated values instead of computing mean/variance
  // across the batch.
  optional bool use_global_stats = 1;
  // How much does the moving average decay each iteration?
  optional float moving_average_fraction = 2 [default = .999];
  // Small value to add to the variance estimate so that we don't divide by
  // zero.
  optional float eps = 3 [default = 1e-5];
}

use_global_stats若是是真使用保存的均值和方差,不然使用滑動平均計算新的均值和方差。測試時爲真,訓練時爲假。

moving_average_fraction滑動平均的衰減係數;eps爲分母附加項。

均值和方差的更新

BN層共存儲了3個數值:均值滑動和、方差滑動和、滑動係數和,計算公式以下:

設moving_average_fraction爲\lambda, 計算元素的數目爲m=bottom[0]->count()/channels_,均值滑動和爲\mu_{old},方差滑動和爲\sigma_{old},滑動係數和爲s_{old}

若是當前batch的均值和方差爲\mu\sigma,則更新後:

\mu_{new}=\lambda*\mu_{old}+\mu

\sigma_{new}=\lambda*\sigma_{old}+\frac{m-1}{m}*\sigma(無偏估計)

s_{new}=\lambda*s_{old}+1

均值和方差的使用

caffe到目前仍然沒有實現和論文原文保持一致的BN層,即沒有 α和β 參數,所以更新公式就比較簡單了,爲每個channel施加以下公式:

x=\frac{x-\mu}{\sigma}

可是須要注意的是,咱們存儲的是均值和方差的滑動和,所以還要作一些處理。

首先計算縮放因子:s=1/s_{old} .若是s_{old}=0,s=0.

處理後得:

均值:\mu=s*\mu_{old}

標準差:\sigma=s*\sigma_{old}   \sigma=(\sigma+eps)^{0.5}

caffe中使用batch_norm_layer和scale_layer兩個層能夠達到google論文中的效果,示例:https://github.com/KaimingHe/deep-residual-networks/blob/master/prototxt/ResNet-50-deploy.prototxt

相關文章
相關標籤/搜索