現在的神經網路通常都特別深,在輸出層向輸入層傳播導數的程序中,梯度很容易被激活函式或是權重以指數級的規模縮小或放大,從而產生“梯度消失”或“梯度爆炸”的現象,造成訓練速度下降和效果不理想,
如何避免或者減輕這一現象的發生呢?歸一化就是方法的一種,歸一化將網路中層與層之間傳遞的資料限制在一定范圍內,從而避免了梯度消失和爆炸的發生,下面介紹一種最基本的歸一化:批量歸一化(BN, Batch Normalization),另外還有層歸一化(LN, Layer Normalization)和權重歸一化(WN, Weight Normalization),和BN大同小異,
批量歸一化
批量歸一化層的是這樣定義的,當使用批量梯度下降(或小批量)時,對前一層的輸出在批量的維度上進行歸一化,即
\begin{align} &\hat{X}_i^t=\frac{X_i^{t-1}-E(X^{t-1})}{\sqrt{D(X^{t-1})+\varepsilon}} \\ \text{where}\;\; &E(X^{t-1}) = \frac{1}{n}\sum\limits_{i=1}^nX_i^{t-1}\notag\\ &D(X^{t-1}) = \frac{1}{n-1}\sum\limits_{i=1}^n\left[X_i^{t-1}-E(X^{t-1})\right]^2\notag \end{align}
其中$n$是輸入批量,$X_i^{t-1}$是前一層輸出批量中的第$i$個,$\varepsilon$是為避免0除而設定的較小數,以上都是按元素進行的操作,這樣做的顯式優點在于,大部分的輸出都被映射到了-1和1之間,而諸如sigmoid激活函式,在這個區間內的梯度是最大的,從而避免因激活函式值的飽和而產生的梯度消失,并且由于層輸出的歸一化約束,反向傳播的累積不會特別顯著,梯度爆炸也得以避免,
但是,如果僅僅進行以上操作,網路的擬合能力就會下降,這是因為,神經網路強大的擬合能力在于激活函式的非線性,經過以上操作,激活函式的輸入通常都集中在-1和1之間,而sigmoid函式在這區間內的導數變化率是比較低的,或者說是比較線性的,為了防止這一點,BN在這基礎上再加一個“反向”操作,將權重輸出再乘上自學習的標準差和均值,映射到激活函式曲率(或者說二階導數絕對值、導數變化率)相對更大的位置,在獲得較大導數的同時,保留激活非線性,公式如下:
$ \begin{aligned} &X_i^t= \gamma^t\hat{X}_i^t+\beta^t\\ \end{aligned} $
與$(1)$式聯合得到:
$ \begin{aligned} &X_i^t= \frac{\gamma^t}{\sqrt{D(X^{t-1})+\varepsilon}}X_i^{t-1} + \left(\beta^t-\frac{E(X^{t-1})\gamma^t}{\sqrt{D(X^{t-1})+\varepsilon}}\right) \\ \end{aligned} $
其中$\gamma,\beta$都是模型中用反向傳播學習的引數,這樣一來,BN層可以自己“決定”將輸出映射到合適位置,
另外,在訓練結束進行推理時,我們輸入模型的通常都是單個樣本,畢竟一個樣本是不能求樣本方差的,所以BN使用滑動平均(moving average)來保存所有輸入的均值和方差,以用于對單一輸入的歸一化,
Keras中BN的使用
Keras中已經實作了BN層可以直接使用,而不用我們自己重新寫這個輪子,使用方式如下:
x = keras.layers.BatchNormalization(axis=-1,#對輸入的哪個軸執行BN momentum=0.99,#滑動平均和方差的動量 epsilon=0.001,#防止0除的較小值 center=True,#是否使用beta調整歸一化后的輸出均值 scale=True,#是否使用gamma調整歸一化后的輸出方差 trainable=True)(x)
其中要注意axis,歸一化操作是針對axis維度指定的向量進行的,比如當BN層的前一層是二維卷積層,輸出的第一維是批量,然后是影像寬高,最后一維是通道,假如BN層axis=-1,均值就是整個批量的所有像素對應的通道向量的平均,方差的計算也是以這個維度進行,對于下面的代碼:
from keras import layers,Model,Input Input_img = Input(shape = [320,320,3]) x = layers.BatchNormalization(axis=-1, momentum=0.99, epsilon=0.001, center=True, scale=True)(Input_img) model = Model(Input_img,x) model.summary()
summary()輸出可訓練引數和不可訓練引數各6個,可訓練引數就是$\gamma,\beta$,不可訓練引數是滑動平均所保存的均值和方差,另外,如果將BN層的traninable標記設定為False,那么$\gamma,\beta$就會被固定,不會被訓練;而如果設定為True,則只有$\gamma,\beta$會被訓練,另外6個不可訓練引數依然是不可訓練狀態,因為它們是通過滑動平均而不是反向傳播來更新的,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/194800.html
標籤:其他
