Batch Normalization(BN層)詳解

image

1. 背景

本篇博文主要講解2015年深度學(xué)習(xí)領(lǐng)域,非常值得學(xué)習(xí)的一篇文獻(xiàn):《Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift》,這個算法目前已經(jīng)被大量的應(yīng)用,最新的文獻(xiàn)算法很多都會引用這個算法,進(jìn)行網(wǎng)絡(luò)訓(xùn)練,可見其強大之處非同一般啊。

近年來深度學(xué)習(xí)捷報連連、聲名鵲起,隨機梯度下架成了訓(xùn)練深度網(wǎng)絡(luò)的主流方法。盡管隨機梯度下降法對于訓(xùn)練深度網(wǎng)絡(luò)簡單高效,但是它有個毛病,就是需要我們?nèi)藶榈娜ミx擇參數(shù),比如學(xué)習(xí)率、參數(shù)初始化、權(quán)重衰減系數(shù)、Drop out比例等。這些參數(shù)的選擇對訓(xùn)練結(jié)果至關(guān)重要,以至于我們很多時間都浪費在這些的調(diào)參上。那么學(xué)完這篇文獻(xiàn)之后,你可以不需要那么刻意的慢慢調(diào)整參數(shù)。BN算法(Batch Normalization)其強大之處如下:

  1. 實際上深度網(wǎng)絡(luò)中每一層的學(xué)習(xí)率是不一樣的,一般為了網(wǎng)絡(luò)能夠正確的收斂、損失函數(shù)的值能夠有效的下降,常常將學(xué)習(xí)率設(shè)為所有層中學(xué)習(xí)率最小的那個值。但是 Batch Normalization 對每層數(shù)據(jù)規(guī)范化后,這個最低學(xué)習(xí)率就會被提高,所以網(wǎng)絡(luò)訓(xùn)練時可以設(shè)置較高的初始學(xué)習(xí)率,加快收斂。
  2. 你再也不用去理會過擬合中drop out、L2正則項參數(shù)的選擇問題,采用BN算法后,可以選擇更小的L2正則約束參數(shù)了,因為BN具有提高網(wǎng)絡(luò)泛化能力的特性;
  3. 再也不需要使用使用局部響應(yīng)歸一化層了(局部響應(yīng)歸一化是Alexnet網(wǎng)絡(luò)用到的方法,搞視覺的估計比較熟悉),因為BN本身就是一個歸一化網(wǎng)絡(luò)層;
  4. 可以把訓(xùn)練數(shù)據(jù)徹底打亂(防止每批訓(xùn)練的時候,某一個樣本都經(jīng)常被挑選到,文獻(xiàn)說這個可以提高1%的精度,這句話我也是百思不得其解啊)。

開始講解算法前,先來思考一個問題:我們知道在神經(jīng)網(wǎng)絡(luò)訓(xùn)練開始前,都要對輸入數(shù)據(jù)做一個歸一化處理,那么具體為什么需要歸一化呢?歸一化后有什么好處呢?原因在于神經(jīng)網(wǎng)絡(luò)學(xué)習(xí)過程本質(zhì)就是為了學(xué)習(xí)數(shù)據(jù)分布,一旦訓(xùn)練數(shù)據(jù)與測試數(shù)據(jù)的分布不同,那么網(wǎng)絡(luò)的泛化能力也大大降低;另外一方面,一旦每批訓(xùn)練數(shù)據(jù)的分布各不相同(batch 梯度下降),那么網(wǎng)絡(luò)就要在每次迭代都去學(xué)習(xí)適應(yīng)不同的分布,這樣將會大大降低網(wǎng)絡(luò)的訓(xùn)練速度,這也正是為什么我們需要對數(shù)據(jù)都要做一個歸一化預(yù)處理的原因。

對于深度網(wǎng)絡(luò)的訓(xùn)練是一個復(fù)雜的過程,只要網(wǎng)絡(luò)的前面幾層發(fā)生微小的改變,那么后面幾層就會被累積放大下去。一旦網(wǎng)絡(luò)某一層的輸入數(shù)據(jù)的分布發(fā)生改變,那么這一層網(wǎng)絡(luò)就需要去適應(yīng)學(xué)習(xí)這個新的數(shù)據(jù)分布,所以如果訓(xùn)練過程中,訓(xùn)練數(shù)據(jù)的分布一直在發(fā)生變化,那么將會影響網(wǎng)絡(luò)的訓(xùn)練速度。

我們知道網(wǎng)絡(luò)一旦train起來,那么參數(shù)就要發(fā)生更新,除了輸入層的數(shù)據(jù)外(因為輸入層數(shù)據(jù),我們已經(jīng)人為的為每個樣本歸一化),后面網(wǎng)絡(luò)每一層的輸入數(shù)據(jù)分布是一直在發(fā)生變化的,因為在訓(xùn)練的時候,前面層訓(xùn)練參數(shù)的更新將導(dǎo)致后面層輸入數(shù)據(jù)分布的變化。以網(wǎng)絡(luò)第二層為例:網(wǎng)絡(luò)的第二層輸入,是由第一層的參數(shù)和input計算得到的,而第一層的參數(shù)在整個訓(xùn)練過程中一直在變化,因此必然會引起后面每一層輸入數(shù)據(jù)分布的改變。我們把網(wǎng)絡(luò)中間層在訓(xùn)練過程中,數(shù)據(jù)分布的改變稱之為:“Internal Covariate Shift”。Paper所提出的算法,就是要解決在訓(xùn)練過程中,中間層數(shù)據(jù)分布發(fā)生改變的情況,于是就有了Batch Normalization,這個牛逼算法的誕生。

2. BN(Batch Normalization)算法原理

2.1 BN概述

就像激活函數(shù)層、卷積層、全連接層、池化層一樣,BN(Batch Normalization)也屬于網(wǎng)絡(luò)的一層。在前面我們提到網(wǎng)絡(luò)除了輸出層外,其它層因為低層網(wǎng)絡(luò)在訓(xùn)練的時候更新了參數(shù),而引起后面層輸入數(shù)據(jù)分布的變化。這個時候我們可能就會想,如果在每一層輸入的時候,再加個預(yù)處理操作那該有多好啊,比如網(wǎng)絡(luò)第三層輸入數(shù)據(jù)X3(X3表示網(wǎng)絡(luò)第三層的輸入數(shù)據(jù))把它歸一化至:均值0、方差為1,然后再輸入第三層計算,這樣我們就可以解決前面所提到的“Internal Covariate Shift”的問題了。

而事實上,paper的算法本質(zhì)原理就是這樣:在網(wǎng)絡(luò)的每一層輸入的時候,又插入了一個歸一化層,也就是先做一個歸一化處理,然后再進(jìn)入網(wǎng)絡(luò)的下一層。 不過文獻(xiàn)歸一化層,可不像我們想象的那么簡單,它是一個可學(xué)習(xí)、有參數(shù)的網(wǎng)絡(luò)層。既然說到數(shù)據(jù)預(yù)處理,下面就先來復(fù)習(xí)一下最強的預(yù)處理方法:白化。

2.2 預(yù)處理操作選擇

說到神經(jīng)網(wǎng)絡(luò)輸入數(shù)據(jù)預(yù)處理,最好的算法莫過于白化預(yù)處理。然而白化計算量太大了,很不劃算,還有就是白化不是處處可微的,所以在深度學(xué)習(xí)中,其實很少用到白化。經(jīng)過白化預(yù)處理后,數(shù)據(jù)滿足條件:a、特征之間的相關(guān)性降低,這個就相當(dāng)于pca;b、數(shù)據(jù)均值、標(biāo)準(zhǔn)差歸一化,也就是使得每一維特征均值為0,標(biāo)準(zhǔn)差為1。 如果數(shù)據(jù)特征維數(shù)比較大,要進(jìn)行PCA,也就是實現(xiàn)白化的第1個要求,是需要計算特征向量,計算量非常大,于是為了簡化計算,作者忽略了第1個要求,僅僅使用了下面的公式進(jìn)行預(yù)處理,也就是近似白化預(yù)處理:

在這里插入圖片描述

公式簡單粗糙,但是依舊很牛逼。因此后面我們也將用這個公式,對某一個層網(wǎng)絡(luò)的輸入數(shù)據(jù)做一個歸一化處理。需要注意的是,我們訓(xùn)練過程中采用batch 隨機梯度下降,上面的E(xk)指的是每一批訓(xùn)練數(shù)據(jù)神經(jīng)元xk的平均值;然后分母就是每一批數(shù)據(jù)神經(jīng)元xk激活度的一個標(biāo)準(zhǔn)差了。

3. BN算法實現(xiàn)

3.1 算法流程

經(jīng)過前面簡單介紹,這個時候可能我們會想當(dāng)然的以為:好像很簡單的樣子,不就是在網(wǎng)絡(luò)中間層數(shù)據(jù)做一個歸一化處理嘛,這么簡單的想法,為什么之前沒人用呢?然而其實實現(xiàn)起來并不是那么簡單的。其實如果是僅僅使用上面的歸一化公式,對網(wǎng)絡(luò)某一層A的輸出數(shù)據(jù)做歸一化,然后送入網(wǎng)絡(luò)下一層B,這樣是會影響到本層網(wǎng)絡(luò)A所學(xué)習(xí)到的特征的。打個比方,比如我網(wǎng)絡(luò)中間某一層學(xué)習(xí)到特征數(shù)據(jù)本身就分布在S型激活函數(shù)的兩側(cè),你強制把它給我歸一化處理、標(biāo)準(zhǔn)差也限制在了1,把數(shù)據(jù)變換成分布于s函數(shù)的中間部分,這樣就相當(dāng)于我這一層網(wǎng)絡(luò)所學(xué)習(xí)到的特征分布被你搞壞了,這可怎么辦?于是文獻(xiàn)使出了一招驚天地泣鬼神的招式:變換重構(gòu),引入了可學(xué)習(xí)參數(shù)γ、β,這就是算法關(guān)鍵之處:

在這里插入圖片描述

每一個神經(jīng)元xk都會有一對這樣的參數(shù)γ、β。這樣其實當(dāng):
在這里插入圖片描述

在這里插入圖片描述

是可以恢復(fù)出原始的某一層所學(xué)到的特征的。因此我們引入了這個可學(xué)習(xí)重構(gòu)參數(shù)γ、β,讓我們的網(wǎng)絡(luò)可以學(xué)習(xí)恢復(fù)出原始網(wǎng)絡(luò)所要學(xué)習(xí)的特征分布。最后Batch Normalization網(wǎng)絡(luò)層的前向傳導(dǎo)過程公式就是:
在這里插入圖片描述

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

3.2 源碼實現(xiàn)

m = K.mean(X, axis=-1, keepdims=True)#計算均值  
std = K.std(X, axis=-1, keepdims=True)#計算標(biāo)準(zhǔn)差  
X_normed = (X - m) / (std + self.epsilon)#歸一化  
out = self.gamma * X_normed + self.beta#重構(gòu)變換  

上面的x是一個二維矩陣,對于源碼的實現(xiàn)就幾行代碼而已,輕輕松松。

3.3 實戰(zhàn)使用

  • (1) 可能學(xué)完了上面的算法,你只是知道它的一個訓(xùn)練過程,一個網(wǎng)絡(luò)一旦訓(xùn)練完了,就沒有了min-batch這個概念了。測試階段我們一般只輸入一個測試樣本,看看結(jié)果而已。因此測試樣本,前向傳導(dǎo)的時候,上面的均值u、標(biāo)準(zhǔn)差σ要哪里來?其實網(wǎng)絡(luò)一旦訓(xùn)練完畢,參數(shù)都是固定的,這個時候即使是每批訓(xùn)練樣本進(jìn)入網(wǎng)絡(luò),那么BN層計算的均值u、和標(biāo)準(zhǔn)差都是固定不變的。我們可以采用這些數(shù)值來作為測試樣本所需要的均值、標(biāo)準(zhǔn)差,于是最后測試階段的u和σ計算公式如下:


    在這里插入圖片描述

    上面簡單理解就是:對于均值來說直接計算所有batch u值的平均值;然后對于標(biāo)準(zhǔn)偏差采用每個batch σB的無偏估計。最后測試階段,BN的使用公式就是:


    在這里插入圖片描述
  • (2) 根據(jù)文獻(xiàn)說,BN可以應(yīng)用于一個神經(jīng)網(wǎng)絡(luò)的任何神經(jīng)元上。文獻(xiàn)主要是把BN變換,置于網(wǎng)絡(luò)激活函數(shù)層的前面。在沒有采用BN的時候,激活函數(shù)層是這樣的:
    z=g(Wu+b)

    也就是我們希望一個激活函數(shù),比如s型函數(shù)s(x)的自變量x是經(jīng)過BN處理后的結(jié)果。因此前向傳導(dǎo)的計算公式就應(yīng)該是:

    z=g(BN(Wu+b))

    其實因為偏置參數(shù)b經(jīng)過BN層后其實是沒有用的,最后也會被均值歸一化,當(dāng)然BN層后面還有個β參數(shù)作為偏置項,所以b這個參數(shù)就可以不用了。因此最后把BN層+激活函數(shù)層就變成了:

    z=g(BN(Wu))

4. Batch Normalization在CNN中的使用

通過上面的學(xué)習(xí),我們知道BN層是對于每個神經(jīng)元做歸一化處理,甚至只需要對某一個神經(jīng)元進(jìn)行歸一化,而不是對一整層網(wǎng)絡(luò)的神經(jīng)元進(jìn)行歸一化。既然BN是對單個神經(jīng)元的運算,那么在CNN中卷積層上要怎么搞?假如某一層卷積層有6個特征圖,每個特征圖的大小是100100,這樣就相當(dāng)于這一層網(wǎng)絡(luò)有6100100個神經(jīng)元,如果采用BN,就會有6100*100個參數(shù)γ、β,這樣豈不是太恐怖了。因此卷積層上的BN使用,其實也是使用了類似權(quán)值共享的策略,把一整張?zhí)卣鲌D當(dāng)做一個神經(jīng)元進(jìn)行處理。

卷積神經(jīng)網(wǎng)絡(luò)經(jīng)過卷積后得到的是一系列的特征圖,如果min-batch sizes為m,那么網(wǎng)絡(luò)某一層輸入數(shù)據(jù)可以表示為四維矩陣(m,f,p,q),m為min-batch sizes,f為特征圖個數(shù),p、q分別為特征圖的寬高。在cnn中我們可以把每個特征圖看成是一個特征處理(一個神經(jīng)元),因此在使用Batch Normalization,mini-batch size 的大小就是:mpq,于是對于每個特征圖都只有一對可學(xué)習(xí)參數(shù):γ、β。說白了吧,這就是相當(dāng)于求取所有樣本所對應(yīng)的一個特征圖的所有神經(jīng)元的平均值、方差,然后對這個特征圖神經(jīng)元做歸一化。下面是來自于keras卷積層的BN實現(xiàn)一小段主要源碼:

input_shape = self.input_shape  
 reduction_axes = list(range(len(input_shape)))  
 del reduction_axes[self.axis]  
 broadcast_shape = [1] * len(input_shape)  
 broadcast_shape[self.axis] = input_shape[self.axis]  
 if train:  
     m = K.mean(X, axis=reduction_axes)  
     brodcast_m = K.reshape(m, broadcast_shape)  
     std = K.mean(K.square(X - brodcast_m) + self.epsilon, axis=reduction_axes)  
     std = K.sqrt(std)  
     brodcast_std = K.reshape(std, broadcast_shape)  
     mean_update = self.momentum * self.running_mean + (1-self.momentum) * m  
     std_update = self.momentum * self.running_std + (1-self.momentum) * std  
     self.updates = [(self.running_mean, mean_update),  
                     (self.running_std, std_update)]  
     X_normed = (X - brodcast_m) / (brodcast_std + self.epsilon)  
 else:  
     brodcast_m = K.reshape(self.running_mean, broadcast_shape)  
     brodcast_std = K.reshape(self.running_std, broadcast_shape)  
     X_normed = ((X - brodcast_m) /  
                 (brodcast_std + self.epsilon))  
 out = K.reshape(self.gamma, broadcast_shape) * X_normed + K.reshape(self.beta, broadcast_shape)

5. 最后

image
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,247評論 6 543
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,520評論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,362評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,805評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 72,541評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,896評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,887評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,062評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,608評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,356評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,555評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,077評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,769評論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,175評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,489評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,289評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 48,516評論 2 379

推薦閱讀更多精彩內(nèi)容