梯度消失和梯度爆炸的原因和解決方案
產生消失的梯度問題的原因
注:實際上就是梯度計算過程中,w值和啟用函式的導數值相乘大於1或者小於1的問題,如果是大於1,那麼經歷過很多個隱藏層梯度就會越來越大,即梯度爆炸,如果是小於1當然就是梯度消失啦!!!
所以w初始化大,w值和啟用函式的導數值相乘可能越來越大,造成梯度爆炸。
所以w初始化小,w值和啟用函式的導數值相乘可能越來越小,造成梯度消失。
sigmoid的導數的最大值就很小,每一層的sigmoid的輸入越大,造成的最後算出的sigmoid的梯度就變得很小。
以這樣的網路為例:
表示誤差
表示e的經過sigmoid之後輸入的結果,就是e現在的值,第3層的第1個神經元。
從這裡還看不出來下面的權值乘以sigmoid對於z的偏導的形式,這是因為此神經元的梯度的計算只可能會用到後面神經元的權值,這個是最後一層的權值,所以看不出來。
這裡就能看出來了,計算的時候使用了(前面一個sigmoid對後面一個神經元的a之前的z的偏導)和(後面一個神經元對後後面一個神經元的權值!)
然而對於最後一層的神經元,因為沒有後後面一個神經元,所以看不出來乘以權值的形式、。。。唉,在這裡糾結了很久
先看一個極簡單的深度神經網路:每一層都只有一個單一的神經元。如下圖:
代價函式C對偏置b1的偏導數的結果計算如下:
先看一下sigmoid 函式的影象:、
下面是導數的影象:
該導數在σ′(0) = 1/4時達到最高。現在,如果我們使用標準方法來初始化網路中的權重,那麼會使用一個均值為0 標準差為1 的高斯分佈。因此所有的權重通常會滿足|wj|<1。從而有wjσ′(zj) < 1/4。
這其實就是消失的梯度出現的本質原因了。
可以考慮將權重初始化大一點的值,但這可能又會造成激增的梯度問題。
根本的問題其實並非是消失的梯度問題或者激增的梯度問題,而是在前面的層上的梯度是來自後面的層上項的乘積。所以神經網路非常不穩定。唯一可能的情況是以上的連續乘積剛好平衡大約等於1,但是這種機率非常小。
所以只要是sigmoid函式的神經網路都會造成梯度更新的時候極其不穩定,產生梯度消失或者激增問題。
解決梯度消失問題
使用ReLU。
使用ReLU 函式時:gradient = 0 (if x < 0), gradient = 1 (x > 0)。不會產生梯度消失問題。、
注:實際上就是梯度計算過程中,w值和啟用函式的導數值相乘大於1或者小於1的問題,如果是大於1,那麼經歷過很多個隱藏層梯度就會越來越大,即梯度爆炸,如果是小於1當然就是梯度消失啦。
轉載:https://www.cnblogs.com/tsiangleo/p/6151560.html
relu和leaky reluqing請見:
Relu 及 leakyRelu是深度學習中常用的啟用函式,看了幾篇部落格後,做一個小的總結。
1. Relu:
數學表示式:a = max(0, z)
函式影象為:
優點:由上圖可以看出,Relu得到的SGD的收斂速度較快
缺點:訓練的時候很容易‘die'了,對於小於0的值,這個神經元的梯度永遠都會是0,在實際操錯中,如果learning rate很大,很可能網路中較多的神經元都'dead'了,即使是較小的learning rate,這種情況也很有可能發生。
為了解決以上的問題,提出了leakyRelu啟用函式:
2. leakyRelu:
數學表示式:y = max(0, x) + leak*min(0,x) (leak是一個很小的常數,這樣保留了一些負軸的值,使得負軸的資訊不會全部丟失)
leakyRelu的影象:
3. 在tf中的實現:
Relu在tf中有官方的實現,可以直接呼叫函式 tf.nn.relu( features, name= None )
leakyRelu的簡單實現可以這麼寫: tf.maximum(leak * x, x),
比較高效的寫法為: