LRN和Batch Norm


LRN

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

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,通道間。

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

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/50864602

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

首先,BN不是針對x(輸入的),而是針對Wx+b的,論文的解釋是:Wx+b每維的均值本身就接近0、方差接近1,所以在Wx+b后使用Batch Normalization能得到更穩定的結果。

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

在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


免責聲明!

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



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