梯度消失梯度爆炸-Gradient Clip

梯度爆炸與梯度消失

梯度消失梯度爆炸-Gradient Clip

實際現象: 當我們使用sigmoid function作為激活函數時,隨著神經網絡的隱藏層數增加,訓練誤差反而增大,造成了深度網絡的不穩定。

梯度彌散: 靠近輸出層的hidden layer 梯度大,參數更新更快,所以很快就會收斂。而靠近輸入層的hidden layer梯度小,參數更新慢,幾乎和初始狀態一樣,隨機分佈。

梯度爆炸: 當前面hidden layer的梯度通過訓練變大,而後面的梯度將會指數級增大。

現象原因: sigmoid函數會將[+∞,-∞]的輸入壓縮到[0,1],導致當輸入更新時,輸出的更新會很小。在這種情況下,就會隨著隱藏層數的增加,反向傳遞時,數值更新將會越來越小。

解決方法:

  1. Relu函數代換Sigmoid函數。
  2. 逐層貪婪預訓練,如同訓練自編碼器的過程,每次只訓練一層參數。由於得到的參數將會是局部最優,所以需要對整個網絡再進行調優。
  3. 梯度減切Gradient Clip。設置一個梯度減切的閾值,如果在更新梯度的時候,梯度超過這個閾值,則會將其限制在這個範圍之內,防止梯度爆炸。
  4. 正則。對參數加入正則規範,限制參數範數過大。
  5. 加入batch normalization層。
  6. 加入殘差結構。
  7. LSTM層由於有記憶,可以緩解梯度消失的發生。

Gradient Clip

簡述

該方法簡單,但是粗暴,閾值人為定義。設置上界閾值,面對梯度爆炸,設置下界閾值,也可以用於梯度消失。

梯度爆炸解釋

在一個只有一個隱藏節點的網絡中,損失函數和權值w偏置b構成error surface,宛如一堵牆,如下圖所示:

梯度消失梯度爆炸-Gradient Clip

損失函數每次迭代都是每次一小步,但是當遇到這堵牆時,在牆上的某點計算梯度,梯度會瞬間增大,指向某處不理想的位置。如果我們將大梯度縮放,就可以把該梯度的誤導控制在可接受範圍內,如虛線箭頭所示。

算法步驟

梯度消失梯度爆炸-Gradient Clip

  1. 設置梯度閾值threshold
  2. 求出梯度的L2範數||g||。
  3. 比較||g||與threshold的大小。
  4. 如果||g||大於threshold,則求threshold/||g||得到縮放因子。
  5. 將梯度乘上縮放因子得到最終的梯度。

效果實驗

無gradient clip:模型在2000次迭代出發生了梯度爆炸。

梯度消失梯度爆炸-Gradient Clip

有gradient clip:可以發現clip_gradient在前期有效了控制了梯度爆炸的影響,使得最終的loss能下降到滿意的結果

梯度消失梯度爆炸-Gradient Clip

Tensorflow and Pytorch GradientClip

Tensorflow

<code># 1. 計算局部範數(快)
tf.clip_by_norm(grads, clip_norm=5)
# 2. 計算全局範數(慢)
tf.clip_by_global_norm(grads, clip_norm=5)
# 計算所有梯度的平方和global_norm,
# 如果梯度平方和global_norm 超過我們指定的clip_norm,

# 那麼就對梯度進行縮放;否則就按照原本的計算結果,/<code>

Pytorch

<code># 這個函數計算的是全局梯度範數
torch.nn.utils.clip_grad_norm(parameters=model.parameters(), max_norm=5, norm_type=2)
# parameters: an iterable of Variables that will have gradients normalized
# max_norm: max norm of the gradients(閾值設定)
# norm_type: type of the used p-norm. Can be'inf'for infinity norm(定義範數類型)/<code>

Keras

<code>from keras import optimizers
# 所有參數梯度將被裁剪,讓其l2範數最大為1:g * 1 / max(1, l2_norm)
sgd = optimizers.SGD(lr=0.01, clipnorm=1.)

# 所有參數d 梯度將被裁剪到數值範圍內:
# 最大值0.5
# 最小值-0.5
sgd = optimizers.SGD(lr=0.01, clipvalue=0.5)/<code>


分享到:


相關文章: