參考博客:https://www.cnblogs.com/guoyaohua/p/8724433.html
參考知乎:https://www.zhihu.com/question/38102762/answer/85238569
1.BN的原理
我們知道,神經網絡在訓練的時候,如果對圖像做白化(即通過變換將數據變成均值為0,方差為1)的話,訓練效果就會好。那么BN其實就是做了一個推廣,它對隱層的輸出也做了歸一化的操作。那么為什么歸一化操作能夠使得訓練效果好那么多呢?機器學習領域有個很重要的假設:IID獨立同分布假設,就是假設訓練數據和測試數據是滿足相同分布的,這是通過訓練數據獲得的模型能夠在測試集獲得好的效果的一個基本保障。假設我們用批量梯度下降法來訓練,在沒有BN層之前,你對輸入做了白化,對於每一個batch在喂到神經網絡之前分布是一致的,但是通過每一個隱層的激活函數后,每一個batch的隱層輸出分布可能就有很大差異了,而且隨着層數的加深,這種差異也會越來越大。
2.BN的公式表達
下面具體解釋一下上述公式的意思:前三步的作用就是把輸入數據分布歸一化成一個正態分布,這樣一來,每一個隱藏層未經激活的輸出值經過激活函數之后大部分都落在了激活函數的線性區域(參考sigmoid函數),但是由於神經網絡強大的表達能力就是基於它的高度非線性化,如果這種特性失去了,網絡在再深也沒有用了。原作者采取了一個辦法,就是第四步,這個步驟其實就是將正太分布進行一個偏移(scale and shift),從某種意義上來說,就是在線性和非線性之間做一個權衡,而這個偏移的參數gamma和bata是神經網絡在訓練時學出來的。另外提一下,公式3中的eplison應該是一個很小的正數,為了防止分母為0,tensorflow的源碼是這樣解釋的。
3.BN的參數推導
現在我們看下,如何通過鏈式法則更新BN中的參數(其中就相當於之前的傳播誤差
):
4.BN在實際運用中需要注意的問題 (此處參考博客:https://blog.csdn.net/xys430381_1/article/details/85141702 )
當我們的測試樣本前向傳導的時候,上面的均值u、標准差σ要哪里來?其實網絡一旦訓練完畢,參數都是固定的,這個時候即使是每批訓練樣本進入網絡,那么BN層計算的均值u、和標准差σ都是固定不變的。我們可以采用這些訓練階段的均值u、標准差σ來作為測試樣本所需要的均值、標准差,於是最后測試階段的u和σ計算公式如下:
上面簡單理解就是:對於均值來說直接計算所有batch u值的平均值;然后對於標准偏差采用每個batch σB的無偏估計。最后測試階段,BN的使用公式就是:
也就是說, 在test的時候,BN用的是固定的mean和var, 而這個固定的mean和var是通過訓練過程中對mean和var進行滑動平均得到的,被稱之為moving_mean和moving_var。在實際操作中,每次訓練時應當更新一下moving_mean和moving_var,然后把BN層的這些參數保存下來,留作測試和預測時使用。(如果不太了解滑動平均可以參考博文:https://blog.csdn.net/qq_18888869/article/details/83009504)
5.BN的好處(此處參考知乎:https://www.zhihu.com/question/38102762中龍鵬-言有三的回答)
(1) 減輕了對參數初始化的依賴,這是利於調參的朋友們的。
(2) 訓練更快,可以使用更高的學習率。
(3) BN一定程度上增加了泛化能力,dropout等技術可以去掉。
6.BN的缺陷
batch normalization依賴於batch的大小,當batch值很小時,計算的均值和方差不穩定。研究表明對於ResNet類模型在ImageNet數據集上,batch從16降低到8時開始有非常明顯的性能下降,在訓練過程中計算的均值和方差不准確,而在測試的時候使用的就是訓練過程中保持下來的均值和方差。
由於這一個特性,導致batch normalization不適合以下的幾種場景。
(1)batch非常小,比如訓練資源有限無法應用較大的batch,也比如在線學習等使用單例進行模型參數更新的場景。
(2)rnn,因為它是一個動態的網絡結構,同一個batch中訓練實例有長有短,導致每一個時間步長必須維持各自的統計量,這使得BN並不能正確的使用。在rnn中,對bn進行改進也非常的困難。不過,困難並不意味着沒人做,事實上現在仍然可以使用的,不過這超出了咱們初識境的學習范圍。