1. 程式人生 > >Batch Normalization的概述和應用包括在CNN和RNN中的應用

Batch Normalization的概述和應用包括在CNN和RNN中的應用

Batch Normalization 學習筆記

一、背景意義

本篇博文主要講解2015年深度學習領域,非常值得學習的一篇文獻:《Batch Normalization: Accelerating Deep Network Training by  Reducing Internal Covariate Shift》,這個演算法目前已經被大量的應用,最新的文獻演算法很多都會引用這個演算法,進行網路訓練,可見其強大之處非同一般啊。

近年來深度學習捷報連連、聲名鵲起,隨機梯度下架成了訓練深度網路的主流方法。儘管隨機梯度下降法對於訓練深度網路簡單高效,但是它有個毛病,就是需要我們人為的去選擇引數,比如學習率、引數初始化、權重衰減係數、Drop out比例等。這些引數的選擇對訓練結果至關重要,以至於我們很多時間都浪費在這些的調參上。那麼學完這篇文獻之後,你可以不需要那麼刻意的慢慢調整引數。BN演算法(Batch Normalization)

其強大之處如下:

(1)你可以選擇比較大的初始學習率,讓你的訓練速度飆漲。以前還需要慢慢調整學習率,甚至在網路訓練到一半的時候,還需要想著學習率進一步調小的比例選擇多少比較合適,現在我們可以採用初始很大的學習率,然後學習率的衰減速度也很大,因為這個演算法收斂很快。當然這個演算法即使你選擇了較小的學習率,也比以前的收斂速度快,因為它具有快速訓練收斂的特性;

(2)你再也不用去理會過擬閤中drop out、L2正則項引數的選擇問題,採用BN演算法後,你可以移除這兩項了引數,或者可以選擇更小的L2正則約束引數了,因為BN具有提高網路泛化能力的特性;

(3)再也不需要使用使用區域性響應歸一化層了(區域性響應歸一化是Alexnet網路用到的方法,搞視覺的估計比較熟悉),因為BN本身就是一個歸一化網路層;

(4)可以把訓練資料徹底打亂(防止每批訓練的時候,某一個樣本都經常被挑選到,文獻說這個可以提高1%的精度,這句話我也是百思不得其解啊)。

開始講解演算法前,先來思考一個問題:我們知道在神經網路訓練開始前,都要對輸入資料做一個歸一化處理,那麼具體為什麼需要歸一化呢?歸一化後有什麼好處呢?原因在於神經網路學習過程本質就是為了學習資料分佈,一旦訓練資料與測試資料的分佈不同,那麼網路的泛化能力也大大降低;另外一方面,一旦每批訓練資料的分佈各不相同(batch 梯度下降),那麼網路就要在每次迭代都去學習適應不同的分佈,這樣將會大大降低網路的訓練速度,這也正是為什麼我們需要對資料都要做一個歸一化預處理的原因。

對於深度網路的訓練是一個複雜的過程,只要網路的前面幾層發生微小的改變,那麼後面幾層就會被累積放大下去。一旦網路某一層的輸入資料的分佈發生改變,那麼這一層網路就需要去適應學習這個新的資料分佈,所以如果訓練過程中,訓練資料的分佈一直在發生變化,那麼將會影響網路的訓練速度。

我們知道網路一旦train起來,那麼引數就要發生更新,除了輸入層的資料外(因為輸入層資料,我們已經人為的為每個樣本歸一化),後面網路每一層的輸入資料分佈是一直在發生變化的,因為在訓練的時候,前面層訓練引數的更新將導致後面層輸入資料分佈的變化。以網路第二層為例:網路的第二層輸入,是由第一層的引數和input計算得到的,而第一層的引數在整個訓練過程中一直在變化,因此必然會引起後面每一層輸入資料分佈的改變。我們把網路中間層在訓練過程中,資料分佈的改變稱之為:“Internal  Covariate Shift”。Paper所提出的演算法,就是要解決在訓練過程中,中間層資料分佈發生改變的情況,於是就有了Batch  Normalization,這個牛逼演算法的誕生。

二、初識BN(Batch  Normalization)

1、BN概述

就像啟用函式層、卷積層、全連線層、池化層一樣,BN(Batch Normalization)也屬於網路的一層。在前面我們提到網路除了輸出層外,其它層因為低層網路在訓練的時候更新了引數,而引起後面層輸入資料分佈的變化。這個時候我們可能就會想,如果在每一層輸入的時候,再加個預處理操作那該有多好啊,比如網路第三層輸入資料X3(X3表示網路第三層的輸入資料)把它歸一化至:均值0、方差為1,然後再輸入第三層計算,這樣我們就可以解決前面所提到的“Internal Covariate Shift”的問題了。

而事實上,paper的演算法本質原理就是這樣:在網路的每一層輸入的時候,又插入了一個歸一化層,也就是先做一個歸一化處理,然後再進入網路的下一層。不過文獻歸一化層,可不像我們想象的那麼簡單,它是一個可學習、有引數的網路層。既然說到資料預處理,下面就先來複習一下最強的預處理方法:白化。

2、預處理操作選擇

說到神經網路輸入資料預處理,最好的演算法莫過於白化預處理。然而白化計算量太大了,很不划算,還有就是白化不是處處可微的,所以在深度學習中,其實很少用到白化。經過白化預處理後,資料滿足條件:a、特徵之間的相關性降低,這個就相當於pca;b、資料均值、標準差歸一化,也就是使得每一維特徵均值為0,標準差為1如果資料特徵維數比較大,要進行PCA,也就是實現白化的第1個要求,是需要計算特徵向量,計算量非常大,於是為了簡化計算,作者忽略了第1個要求,僅僅使用了下面的公式進行預處理,也就是近似白化預處理:


公式簡單粗糙,但是依舊很牛逼。因此後面我們也將用這個公式,對某一個層網路的輸入資料做一個歸一化處理。需要注意的是,我們訓練過程中採用batch 隨機梯度下降,上面的E(xk)指的是每一批訓練資料神經元xk的平均值;然後分母就是每一批資料神經元xk啟用度的一個標準差了。

三、BN演算法實現

1、BN演算法概述

經過前面簡單介紹,這個時候可能我們會想當然的以為:好像很簡單的樣子,不就是在網路中間層資料做一個歸一化處理嘛,這麼簡單的想法,為什麼之前沒人用呢?然而其實實現起來並不是那麼簡單的。其實如果是僅僅使用上面的歸一化公式,對網路某一層A的輸出資料做歸一化,然後送入網路下一層B,這樣是會影響到本層網路A所學習到的特徵的。打個比方,比如我網路中間某一層學習到特徵資料本身就分佈在S型啟用函式的兩側,你強制把它給我歸一化處理、標準差也限制在了1,把資料變換成分佈於s函式的中間部分,這樣就相當於我這一層網路所學習到的特徵分佈被你搞壞了,這可怎麼辦?於是文獻使出了一招驚天地泣鬼神的招式:變換重構,引入了可學習引數γ、β,這就是演算法關鍵之處:

 

每一個神經元xk都會有一對這樣的引數γ、β。這樣其實當:


是可以恢復出原始的某一層所學到的特徵的。因此我們引入了這個可學習重構引數γ、β,讓我們的網路可以學習恢復出原始網路所要學習的特徵分佈。最後Batch Normalization網路層的前向傳導過程公式就是:

 

上面的公式中m指的是mini-batch size。

2、原始碼實現

  1. m = K.mean(X, axis=-1, keepdims=True)#計算均值
  2. std = K.std(X, axis=-1, keepdims=True)#計算標準差
  3. X_normed = (X - m) / (std + self.epsilon)#歸一化
  4. out = self.gamma * X_normed + self.beta#重構變換
上面的x是一個二維矩陣,對於原始碼的實現就幾行程式碼而已,輕輕鬆鬆。

3、實戰使用

(1)可能學完了上面的演算法,你只是知道它的一個訓練過程,一個網路一旦訓練完了,就沒有了min-batch這個概念了。測試階段我們一般只輸入一個測試樣本,看看結果而已。因此測試樣本,前向傳導的時候,上面的均值u、標準差σ 要哪裡來?其實網路一旦訓練完畢,引數都是固定的,這個時候即使是每批訓練樣本進入網路,那麼BN層計算的均值u、和標準差都是固定不變的。我們可以採用這些數值來作為測試樣本所需要的均值、標準差,於是最後測試階段的u和σ 計算公式如下:


上面簡單理解就是:對於均值來說直接計算所有batch u值的平均值;然後對於標準偏差採用每個batch σB的無偏估計。最後測試階段,BN的使用公式就是:


(2)根據文獻說,BN可以應用於一個神經網路的任何神經元上。文獻主要是把BN變換,置於網路啟用函式層的前面。在沒有采用BN的時候,啟用函式層是這樣的:

z=g(Wu+b)

也就是我們希望一個啟用函式,比如s型函式s(x)的自變數x是經過BN處理後的結果。因此前向傳導的計算公式就應該是:

z=g(BN(Wu+b))

其實因為偏置引數b經過BN層後其實是沒有用的,最後也會被均值歸一化,當然BN層後面還有個β引數作為偏置項,所以b這個引數就可以不用了。因此最後把BN層+啟用函式層就變成了:

z=g(BN(Wu))

四、Batch Normalization在CNN中的使用

通過上面的學習,我們知道BN層是對於每個神經元做歸一化處理,甚至只需要對某一個神經元進行歸一化,而不是對一整層網路的神經元進行歸一化。既然BN是對單個神經元的運算,那麼在CNN中卷積層上要怎麼搞?假如某一層卷積層有6個特徵圖,每個特徵圖的大小是100*100,這樣就相當於這一層網路有6*100*100個神經元,如果採用BN,就會有6*100*100個引數γ、β,這樣豈不是太恐怖了。因此卷積層上的BN使用,其實也是使用了類似權值共享的策略,把一整張特徵圖當做一個神經元進行處理。

卷積神經網路經過卷積後得到的是一系列的特徵圖,如果min-batch sizes為m,那麼網路某一層輸入資料可以表示為四維矩陣(m,f,p,q),m為min-batch sizes,f為特徵圖個數,p、q分別為特徵圖的寬高。在cnn中我們可以把每個特徵圖看成是一個特徵處理(一個神經元),因此在使用Batch Normalization,mini-batch size 的大小就是:m*p*q,於是對於每個特徵圖都只有一對可學習引數:γ、β。說白了吧,這就是相當於求取所有樣本所對應的一個特徵圖的所有神經元的平均值、方差,然後對這個特徵圖神經元做歸一化。下面是來自於keras卷積層的BN實現一小段主要原始碼:

  1. input_shape = self.input_shape  
  2.  reduction_axes = list(range(len(input_shape)))  
  3.  del reduction_axes[self.axis]  
  4.  broadcast_shape = [1] * len(input_shape)  
  5.  broadcast_shape[self.axis] = input_shape[self.axis]  
  6.  if train:  
  7.      m = K.mean(X, axis=reduction_axes)  
  8.      brodcast_m = K.reshape(m, broadcast_shape)  
  9.      std = K.mean(K.square(X - brodcast_m) + self.epsilon, axis=reduction_axes)  
  10.      std = K.sqrt(std)  
  11.      brodcast_std = K.reshape(std, broadcast_shape)  
  12.      mean_update = self.momentum * self.running_mean + (1-self.momentum) * m  
  13.      std_update = self.momentum * self.running_std + (1-self.momentum) * std  
  14.      self.updates = [(self.running_mean, mean_update),  
  15.                      (self.running_std, std_update)]  
  16.      X_normed = (X - brodcast_m) / (brodcast_std + self.epsilon)  
  17.  else:  
  18.      brodcast_m = K.reshape(self.running_mean, broadcast_shape)  
  19.      brodcast_std = K.reshape(self.running_std, broadcast_shape)  
  20.      X_normed = ((X - brodcast_m) /  
  21.                  (brodcast_std + self.epsilon))  
  22.  out = K.reshape(self.gamma, broadcast_shape) * X_normed + K.reshape(self.beta, broadcast_shape)  

個人總結:2015年個人最喜歡深度學習的一篇paper就是Batch Normalization這篇文獻,採用這個方法網路的訓練速度快到驚人啊,感覺訓練速度是以前的十倍以上,再也不用擔心自己這破電腦每次執行一下,訓練一下都要跑個兩三天的時間。另外這篇文獻跟空間變換網路《Spatial Transformer Networks》的思想神似啊,都是一個變換網路層。

五、BN在CNN和RNN中的使用

|CNNBatchNorm

CNNDNN不一樣,某個卷積層包含多個FilterMap,而每個Filter Map其實是引數共享的,偵測同一類特徵,是通過在輸入影象上的區域性掃描的方式遍歷覆蓋整個輸入影象的,但是單個Filter Map本身可能是二維甚至多維的,如果是二維的,那麼包含p*q個神經元。那麼此時要應用BN其實有兩種選擇:

一種是把一個FilterMap看成一個整體,可以想象成是一個Filter Map對應DNN隱層中的一個神經元,所以一個Filter Map的所有神經元共享一個ScaleShift引數,Mini-Batchm個例項的統計量均值和方差是在p*q個神經元裡共享,就是說從m*p*q個啟用裡面算Filter Map全域性的均值和方差,這體現了Filter Map的共享引數特性,當然在實際計算的時候每個神經元還是各算各的BN轉換值,只不過採用的統計量和Scale,shift引數用的都是共享的同一套值而已。

另外一種是FilterMap的每個神經元都看成獨立的,各自儲存自己的ScaleShift引數,這樣一個Filter Map就有m*q*2個引數而不是大家共享這兩個引數,同樣地,均值和方差也是各算各的,意即每個神經元在m個例項的啟用中計算統計量。

很明顯,第一種方法能夠體現卷積層FilterMap的思想本質,所以在CNN中用BN是採用第一種方式。在推理時,也是類似的改動,因為推理時均值和方差是在所有訓練例項中算出的統計量,所以所有的神經元用的都一樣,區別主要在於Scale引數和Shift引數同一個Filter Map的神經元一樣共享同樣的引數來計算而已,而DNN中是每個神經元各自算各自的,僅此而已。

影象處理等廣泛使用CNN的工作中很多都使用了BN了,實踐證明很好用。

|RNNBatchNorm

                                                    1 RNNBN方向

對於RNN來說,希望引入BN的一個很自然的想法是在時間序列方向展開的方向,即水平方向(圖1)在隱層神經元節點引入BN,因為很明顯RNN在時間序列上展開是個很深的深層網路,既然BN在深層DNNCNN都有效,很容易猜想這個方向很可能也有效。

另外一個角度看RNN,因為在垂直方向上可以疊加RNN形成很深的Stacked  RNN,這也是一種深層結構,所以理論上在垂直方向也可以引入BN,也可能會有效。但是一般的直覺是垂直方向深度和水平方向比一般深度不會太深,所以容易覺得水平方向增加BN會比垂直方向效果好。

那麼事實如何呢?這些猜想是否正確呢?

目前在RNN中引入BN的有幾項工作,目前有些矛盾的結論,所以後面還需要更深入的實驗來下確定的結論。我們歸納下目前能下的一些結論。

Batch normalized recurrent neural networks”這個工作是最早嘗試將BN引入RNN的,它構建了5層的RNNLSTM,它的結論是:水平方向的BN對效果有損害作用,垂直方向BN能夠加快引數收斂速度,但是相對基準無BN對照組實驗看可能存在過擬合問題。但是這個過擬合是由於訓練資料規模不夠還是模型造成的並無結論。

Deep speech 2: End-to-end speech recognition in english and mandarin.”這個工作也嘗試將BN引入RNN,也得出了水平方向的BN不可行,垂直方向的BN對加快收斂速度和提升分類效果有幫助,這點和第一個工作結論一致。另外,新的結論是:在訓練資料足夠大的情況下,如果垂直方向網路深度不深的話,垂直方向的BN效果也會有損害作用,這個其實和工作一的結論基本一致,也說明了這個過擬合不是訓練資料不夠導致的,而是淺層模型加入BN效果不好。但是如果垂直方向深度足夠深,那麼加入BN無論是訓練速度還是分類效果都獲得了提高。

Recurrent Batch Normalization”是最新的工作,164月份的論文。它的實驗結果推翻了上面兩個工作的結論。證明了水平方向BN是能夠加快訓練收斂速度以及同時提升模型泛化能力的。論文作者認為前面兩個工作之所以BN在水平方向上不行,很可能主要是BNScale引數設定不太合理導致的,他們的結論是:Scale引數要足夠小才能獲得好的實驗效果,如果太大會阻礙資訊傳播。

所以總結一下,目前能下的結論是:

  1. RNN垂直方向引入BN的話:如果層數不夠深(這個深度我感覺5層是個分界點,5層的時候效果不穩定,時好時壞,高於5層效果就是正面的了),那麼BN效果不穩定或者是損害效果,深度如果夠多的話,能夠加快訓練收斂速度和泛化效能。

 2.在隱層節點做BN的話:

這麼做肯定是不行的,就是說不能在垂直方向輸入和水平方向輸入啟用加完後進行BN,這等於同時對水平和垂直方向做BN,垂直和水平方向必須分別做BN,就是說要這樣:

相關推薦

LightOJ 1098 - A New Function (前n項的因子包括本身1)

blank func lld class space algorithm php 求和 scan 題意:http://www.lightoj.com/volume_showproblem.php?problem=1098 通過一個因子,求出與此因子相對應的其他因子,求和;

Golanghttp請求設定cookieheader(包括GETPOST請求)

//http請求 func httpHandle(method, urlVal,data string) { client := &http.Client{} var req *http.Request if data == "" { urlArr := strings.Sp

8.可變物件(無序表有序表——含java庫應用)

在下列引用中,在chris 修改last的值後,list中的值也改變。因為list和chris引用的是同一個物件。 所以chris客戶可以修改它植入list中的物件。這是一個便利的方案。 但修改ADT中可變物件的能力,使客戶有可能破壞ADT的完整性。

Batch Normalization概述應用包括CNNRNN應用

Batch Normalization 學習筆記一、背景意義本篇博文主要講解2015年深度學習領域,非常值得學習的一篇文獻:《Batch Normalization: Accelerating Deep

多工學習概述論文:從定義方法到應用原理分析

多工學習是一個很有前景的機器學習領域,相關的理論和實驗研究成果以及應用也在不斷湧現。近日,香港科技大學電腦科學與工程系的楊強教授和張宇助理教授在《國家科學評論(National Science Review)》2018 年 1 月份釋出的「機器學習」專題期刊中發表了題為《An overview of

批歸一化(Batch Normalization)、L1正則化L2正則化

from: https://www.cnblogs.com/skyfsm/p/8453498.html https://www.cnblogs.com/skyfsm/p/8456968.html BN是由Google於2015年提出,這是一個深度神經網路訓練的技巧,它不僅可以加快了

編寫一個Java 應用程式,計算兩個大整數的、差、積商,並計算一個大整數的因 子個數(因子包括1 大整數本身)。

1 package ex6_2; 2 import java.math.BigInteger; 3 4 public class BigintegerExample { 5 public static void main(String[] args) { 6

TensorFlow 的正則化(Batch Normalization)詳解實現程式碼

        雖然在訓練初期使用 He 初始化方法初始ELU(或者其他派生的ReLU)能夠有效的防止梯度彌散、爆炸問題。但是這種方式無法保證梯度問題不會在訓練過程中產生。         2015年的一篇paper( “Batch Normalization: Accel

TensorFlow實現Batch Normalization詳解程式碼實現

為什麼我們要進行標準化? 具有統一規格的資料更方便神經網路學習到資料的規律。 舉個非常簡單的例子。假設我們的啟用函式是f(x)=tanh,輸入資料x從-10到10。如下圖所示: 加上標準化工序後,x被調整到[-1,1],那麼with和without標準化工序的資料輸

【機器學習trick】Batch-Normalization的理解研究

Batch-Normalization概述 15年穀歌發表了一篇文章,名字是《Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shif

Batch Normalization--全連線神經網路卷積神經網路實戰

Batch Normalization原理 網上部落格一大堆,說的也很明白,這裡就簡單的說一下我的個人理解: 對每一個特徵值進行 0均值化,利於神經網路擬合時,對於自身的引數b,無需修改很多次,

iOS應用跳轉(包括iPhone原有應用跳轉第三方應用跳轉)

iOS應用間跳轉簡介 在開發的過程中,我們經常會遇到需要從一個應用程式跳轉到另一個應用程式的場景。這就需要我們掌握iOS應用程式之間的相互跳轉知識。 應用間跳轉應用場景 使用第三方使用者登入,跳轉到需授權的App。如QQ登入,微信登入等

DOM4J操作XML(包括封裝解析)

針對 con auth 名稱 解析 static 格式化 read urn DOM4J操作XML(包括封裝和解析) 先來看看dom4j中相應XML的DOM樹建立的繼承關系 針對於XML標準定義。相應於圖2-1列出的內容,dom4j提供了下面實現:

使用RPM包工具源碼包編譯安裝Linux應用程序

linux rpm 軟件包安裝 楊書凡 源碼包編譯安裝 系統命令:一般在/bin和/sbin目錄中,或為Shell內部指令,完成對系統的基本管理工作,例如IP配置工具應用程序:通常在/usr/bin和/usr/sbin目錄中,完成相對獨立的其他輔助任務,例如網頁瀏覽器Linux應用程序的組

Jenkins+docker實現應用發布更新

jenkins docker Jenkins+docker實現應用發布Jenkins:centos6.5 ip:192.168.83.84Docker:centos7.2 ip:192.168.83.60 一、安裝Jenkins最新版:sudo wget -O /etc/yum.repos.d/jen

根據馬甲、應用商店、統計每天的註冊量,要求可以根據選擇馬甲app,馬甲appstroreuser_login不同表問題

統計 eat create group ror 一次 instr 發現 用戶登錄 這個馬甲屬於一個表,appStore另一張表,用戶登錄表,主要操作的就是這三個表。 我這裏的馬甲和app的id都與用戶登錄表中的channel對應,在channel存放的是majiaId +

後臺發送http請求通用方法,包括getpost

util line 通用方法 返回 finall 6.0 val except ktr package com.examsafety.service.sh; import java.io.BufferedReader; import java.io.IOExceptio

(51)LINUX應用編程網絡編程之六Linux高級IO

linu read 簡單 長度 更新 非阻塞 argv 應用程序 事情 3.6.1.非阻塞IO 3.6.1.1、阻塞與非阻塞 阻塞:阻塞具有很多優勢(是linux系統的默認設置),單路IO的時候使用阻塞式IO沒有降低CPU的性能 補充:阻塞/非阻塞, 它們是程序在等待消息(

(50)LINUX應用編程網絡編程之五 Linux信號(進程間通信)

sign 變量類型 {0} 退出 指向 示例 div 失效 key 信號實現進程間的通信 3.5.1.什麽是信號 3.5

UWP 應用獲取各類系統、用戶信息 (1) - 設備系統的基本信息、應用包信息、用戶數據賬戶信息用戶賬戶信息

hone 說明 ima for layout ica arch 接受 resources 原文:UWP 應用獲取各類系統、用戶信息 (1) - 設備和系統的基本信息、應用包信息、用戶數據賬戶信息和用戶賬戶信息應用開發中,開發者時常需要獲取一些系統、用戶信息用於數據統計遙測、