參考:BN學習筆記新博,用自己的的理解和語言總結一下。
背景
BN,全稱Batch Normalization,是2015年提出的一種方法业簿,在進行深度網絡訓練時,大都會采取這種算法阳懂。
原文鏈接:Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift
盡管梯度下降法訓練神經網絡很簡單高效梅尤,但是需要人為地去選擇參數,比如學習率岩调,參數初始化巷燥,權重衰減系數,Dropout比例等号枕,而且這些參數的選擇對于訓練結果至關重要缰揪,以至于我們很多時間都浪費到這些調參上。BN算法的強大之處在下面幾個方面:
- 可以選擇較大的學習率葱淳,使得訓練速度增長很快钝腺,具有快速收斂性。
- 可以不去理會Dropout赞厕,L2正則項參數的選擇艳狐,如果選擇使用BN,甚至可以去掉這兩項坑傅。
- 去掉局部響應歸一化層僵驰。(AlexNet中使用的方法,BN層出來之后這個就不再用了)
- 可以把訓練數據打亂唁毒,防止每批訓練的時候蒜茴,某一個樣本被經常挑選到。(不是很理解敖鳌)
首先來說歸一化的問題粉私,神經網絡訓練開始前,都要對數據做一個歸一化處理近零,歸一化有很多好處诺核,原因是網絡學習的過程的本質就是學習數據分布,一旦訓練數據和測試數據的分布不同久信,那么網絡的泛化能力就會大大降低窖杀,另外一方面,每一批次的數據分布如果不相同的話裙士,那么網絡就要在每次迭代的時候都去適應不同的分布入客,這樣會大大降低網絡的訓練速度,這也就是為什么要對數據做一個歸一化預處理的原因。另外對圖片進行歸一化處理還可以處理光照桌硫,對比度等影響夭咬。
另外,為什么要進行歸一化還有一些原因铆隘,可以參考這里
網絡一旦訓練起來卓舵,參數就要發(fā)生更新,出了輸入層的數據外膀钠,其它層的數據分布是一直發(fā)生變化的掏湾,因為在訓練的時候,網絡參數的變化就會導致后面輸入數據的分布變化托修,比如第二層輸入忘巧,是由輸入數據和第一層參數得到的,而第一層的參數隨著訓練一直變化睦刃,勢必會引起第二層輸入分布的改變砚嘴,把這種改變稱之為:Internal Covariate Shift,BN就是為了解決這個問題的涩拙。
BN
和卷積層际长,激活層,全連接層一樣兴泥,BN層也是屬于網絡中的一層工育。我們前面提到了,前面的層引起了數據分布的變化搓彻,這時候可能有一種思路是說:在每一層輸入的時候如绸,在加一個預處理多好。比如歸一化到均值為0旭贬,方差為1怔接,然后再送入輸入進行學習∠」欤基本思路是這樣的扼脐,然而實際上沒有這么簡單,如果我們只是使用簡單的歸一化方式:對某一層的輸入數據做歸一化奋刽,然后送入網絡的下一層瓦侮,這樣是會影響到本層網絡所學習的特征的,比如網絡中學習到的數據本來大部分分布在0的右邊佣谐,經過RELU激活函數以后大部分會被激活肚吏,如果直接強制歸一化,那么就會有大多數的數據無法激活了狭魂,這樣學習到的特征不就被破壞掉了么罚攀?論文中對上面的方法做了一些改進:變換重構吁断,引入了可以學習的參數,這就是算法的關鍵之處:這兩個希臘字母就是要學習的坞生。
每一個神經元x_k都會有這樣的一對參數,當:
這樣的時候可以恢復出原始的某一層學習到的特征的掷伙,因此我們引入這個可以學習的參數使得我們的網絡可以恢復出原始網絡所要學習的特征分布是己,最后BN層的前向傳導公式為:
上面公式中的m指的是mini-batch size。也就是每一個batch來做一個這樣的BN任柜。代碼對應也是四句話卒废。
m = K.mean(X, axis=-1, keepdims=True) #計算均值
std = K.std(X, axis=-1, keepdims=True) #計算標準差
X_normed = (X - m) / (std + self.epsilon) #歸一化
out = self.gamma * X_normed + self.beta #重構變換
上面的x是一個二維矩陣,對于源碼的實現就是上面幾行了宙地。
使用
一旦網絡訓練結束摔认,就沒有了batch這個概念了,測試階段的時候我們一般只輸入一個樣本來看一下預測結果宅粥。因此測試樣本前向傳導的時候参袱,上面式子里的均值和標準差從哪里來?其實網絡一旦訓練完畢秽梅,參數都是固定的抹蚀,這個時候即便是訓練數據進來一個batch,BN層計算的均值和標準差都是基本不變的(網絡趨于穩(wěn)定)企垦,我們可以采用這些數值作為測試樣本所需要的均值和標準差环壤,于是最后測試階段的均值和標準差為:
上面簡單理解就是:對于均值來說直接計算所有batch u值的平均值;然后對于標準偏差采用每個batch σB的無偏估計钞诡。最后測試階段郑现,BN的使用公式就是
BN可以用于一個神經網絡的任何一個神經元上,文獻中主要是把BN變換放在激活函數層的前面荧降,所以前向傳導的計算公式應該是:z=g(BN(Wu+b))接箫,因為偏置參數經過BN層其實是不起作用的,因為也會被均值歸一化(平移)誊抛,所以這個參數就可以不要了列牺,可以寫成:z=g(BN(Wu))
BN在CNN上的使用。
上面所說的是BN對于每一個神經元都做處理拗窃,對于卷積神經網絡來說呢瞎领?比如某一層卷積層的維度是:1001006,如果對每一個神經元都進行BN的話随夸,那就需要600萬*2的參數九默,這是相當恐怖的,所以其實卷積神經網絡使用BN的時候宾毒,也做了權重共享的策略驼修,把一張?zhí)卣鲌D當做一個神經元來處理。
比如某層的特征維度是[m,f,p,q],分別是batch_num:m,維度: f,特征尺寸p,q乙各。CNN中可把每個特征圖看成是一個特征處理(神經元)墨礁,因此在使用BN的時候,Mini-batch size的大小就是mpq耳峦,對于每一個特征圖只有一對科學系的參數恩静。說白了,就是相當于求所有樣本(batch_num:m個)所對應的的一個特征圖的所有神經元的平均值和方差蹲坷,然后對這一個神經元做歸一化驶乾,假設特征維度只有一維的話,就相當于一個batch的所有圖片像素的均值和方差來對每一張圖片來做歸一化循签,也是容易理解的级乐。