卷首語:
首先,筆者在這里祝大家新年快樂!!!今天我們來探討的問題是BN層在TensorFlow中的實現,以實踐為主,理論方面會跳過一些不易被理解的部分,讓大家可以快速搭建并投入使用。
在文章的最后我也會給出相應的效果對比,猶豫要不要學習的讀者可以先看看最后在做決定~
在訓練模型時,我們經常會在一些需要調整的參數上浪費時間:學習率,學習衰減率,正則……
況且即便我們調整了很多次參數,也未必見得可以提高模型的訓練效果,甚至還有可能產生梯度消失等等一系列令人頭疼的問題。
但是,這種現象在Inception-v2中就已經發生了改變。在Inception模型升級時引入了一種新的網絡層“Batch Normalization”
為了降低學習難度,筆者在這里給出一個精簡的公式:
下面,讓我們對公式逐一地進行分解(注:有微積分基礎的讀者想必就不用我多說了,可以跳過理論這段)
均值與方差
均值(mean):
首先,讓我們假設一數組:X = [1,2,3,4,5]
mean = 數組和/數量
mean = (1+2+3+4+5)/5
mean = 3
方差(variance):
讓我們繼續使用上一數組X
variance = (X12+ X22+…+ Xn2)/ n
variance = (12+ 22 + 32 + 42 + 52)/ 5
variance = (1 + 4 + 9 + 1 6 + 2 5 )/ 5
variance =? 45 / 5
variance =? 9
在TensorFlow中,該公式內的“均值”與“方差”可通過tf.nn.moments()函數來計算
內部參數
x:輸入進行計算的張量
axes:需要計算的維度
name:命名
keep_dims:是否保持維度
縮放與偏移
在公式中,我們可以將“縮放”與“偏移”理解為兩組可被訓練的Weights
縮放(scale):
在定義scale時一般初始化為0,維度必須和mean的一致
偏移(offset):
定義offset的情況和scale基本一致,但要注意的是offset一般情況下初始化為1
按照上面所講的,公式中的內容我們已經解析完全,接下來我們只需要套用一個現成的函數:
神來一筆:Variance_epsilon
在上面的函數中,我們將“輸入”“均值”“方差”“偏移”“縮放”都添加了進去,最后還有個參數:variance_epsilon = 0.001
這個參數的作用在官方解釋為:A small float number to avoid dividing by 0.
大概的意思就是需設定一個浮點數用來避免除以0產生的梯度爆炸
雖然在方差被除等于零是幾率很小的事,可在幾十層甚至幾百層的神經網絡里,計算量也要大的驚人,根據墨菲定律:會出錯的事總會出錯
滑動平均與滑動方差
注:BN層在訓練與測試時所用的滑動平均和滑動方差不同
申請滑動平均與滑動方差(這里就應該不用我多敘述了,純基礎范圍,不太理解的可以去找一下關于滑動平均的博文):
計算滑動平均與滑動方差:
存儲優化參數:
如此一來,在進行網絡訓練時,將is_training設為True;測試網絡時設為False即可。
精簡代碼
在前文中我們寫了很多行代碼才實現了BN層的基本功能。
但是,我們完全可以用一行代碼進行!
下面三種函數都可以實現BN層,因為都是封裝好的函數,有興趣的讀者完全可以自行測試。
有BN層的仿Lenet-5模型前趨關系代碼:
關于詳細如何實現BN層的,可以參考我給出的實例代碼,基于MNIST數據集非常簡單:https://pan.baidu.com/s/11cnPkDAiuOFN4wgUv-l7_w
卷尾語:萬般不愿,終于還是開學了...希望這學習的學習能有所提高!