1. 程式人生 > >梯度消失和梯度爆炸的原因和解決方案

梯度消失和梯度爆炸的原因和解決方案

產生消失的梯度問題的原因

注:實際上就是梯度計算過程中,w值和啟用函式的導數值相乘大於1或者小於1的問題,如果是大於1,那麼經歷過很多個隱藏層梯度就會越來越大,即梯度爆炸,如果是小於1當然就是梯度消失啦!!!

所以w初始化大,w值和啟用函式的導數值相乘可能越來越大,造成梯度爆炸。

所以w初始化小,w值和啟用函式的導數值相乘可能越來越小,造成梯度消失。

sigmoid的導數的最大值就很小,每一層的sigmoid的輸入越大,造成的最後算出的sigmoid的梯度就變得很小。

以這樣的網路為例:

表示誤差

表示e的經過sigmoid之後輸入的結果,就是e現在的值,第3層的第1個神經元。

 表示 e的沒有經過sigmoid之後的輸入,不是e的值。

這裡還看不出來下面的權值乘以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),
          比較高效的寫法為: