一、前述
在梯度下降中,隨著演算法反向反饋到前面幾層,梯度會越來越小,最終,沒有變化,這時或許還沒有收斂到比較好的解,這就是梯度消失問題,深度學習遭受不穩定的梯度,不同層學習在不同的速度上
二、解決梯度彌散和消失方法一,初始化權重使用he_initialization
1、舉例
如果我們看邏輯啟用函式,當輸入比較大,不管正負,將會飽和在0或1,這樣梯度就是0,因此當反向傳播開始,它幾乎沒有梯度傳播回神經網路,所以就會導致只更改高的幾層,低的幾層不會變化,這就是為什麼替代Relu函式的原因。
2、初始化
我們需要每層輸出的方差等於它的輸入的方差,並且我們同時需要梯度有相同的方差,當反向傳播進入這層時和離開這層,方差也一樣。
上面理論不能同時保證,除非層有相同的輸入連線和輸出連線,
但是有一個不錯的妥協在實際驗證中,連線權重被隨機初始化,n_inputs和n_outputs是輸入和輸出的連線,也叫fan_in和fan_out,
這種初始化的策略叫Xaiver initialization
3、具體應用
看輸入和輸出的連線數找到對應公式計算半徑來隨機初始化權重,是最合理的,是最不容易產生梯度彌散的初始化權重。
4、He Initialization(變形的Relu啟用函式)
初始化策略對應ReLU啟用函式或者它的變形叫做He initialization
fully_connected()函式預設使用Xavier初始化對應uniform distribution(full_connected預設會初始化引數和bias)
我們可以改成He initialization使用variance_scaling_initializer()函式,如下
三、解決梯度彌散問題方法二,使用不飽和啟用函式解決單邊抑制
1、場景
選擇ReLU更多因為對於正數時候不飽和,同時因為它計算速度快
但是不幸的是,ReLU啟用函式不完美,有個問題是dying ReLU,在訓練的時候一些神經元死了。
2、解決方法
當它們輸出小於0,去解決這個,使用leaky ReLU,max(a*z,z),a=0.01,在乎執行效能速度,可以試試
3、常用不飽和啟用函式
leaky ReLU a是一個固定的值,需要手動實現
RReLU,Random,a是一個在給定範圍內隨機取值的數在訓練時,在測試的時候取a得平均值,過擬合
可以試試
PReLU,Parametric,a是一個在訓練過程中需要學習的超引數,它會被修改在反向傳播中,適合
大資料集
ELU,exponential,計算梯度的速度會慢一些,但是整體因為沒有死的神經元,整體收斂快,超參
數0.01(實際中用的不多),解決零點不可導的問題,ELU可以直接使用。
選擇啟用函式結論:
ELU > leaky ReLU > ReLU > tanh > logistic
四、解決梯度彌散方法三,利用Batch Normalization
1、場景
儘管使用He initialization和ELU可以很大程度減少梯度彌散問題在一開始訓練,但是不保證在訓練的後面不會發生
Batch Normalization可以更好解決問題。它應用於每層啟用函式之前,就是做均值和方差歸一化,對於每一批次資料並且還做放大縮小,平移,為了梯度下降的時候收斂的時候速度更快。
相當於把資料都拉到中間的位置了,有這個就不需要Dropout,Relu等等
2、本質
本質就是均值,歸一化,放大,縮小
3、具體使用原理
在測試時,使用全部訓練集的均值、方差,在Batch Normalization層,總共4個超引數被學習,
scale,offset,mean,standard deviation。
scale,offset,如下
mean,standard deviation。如下,B是每一批次
利用Batch Normalization即使是用飽和的啟用函式,梯度彌散問題也可以很好減輕
利用Batch Normalization對權重初始化就不那麼敏感了,用不用he_initlinze無所謂了,但最好用
利用Batch Normalization可以使用大一點的學習率來提速了。
利用Batch Normalization同樣的準確率,4.9% top-5錯誤率,速度減少14倍
利用Batch Normalization也是一種正則化,就沒必要使用dropout了或其他技術了
3、具體使用程式碼
4、程式碼優化
真正執行的時候程式碼如下: