天天看點

RNN - 梯度消失與爆炸

梯度消失和爆炸, 是神經網絡都會遇到問題, 最能了解, 反而從數學上, 梯度意義 和 梯度下降法(參數更新) 這塊就能了解.

Last we learned Recurrent Neural Netwoks (RNN) and why they'er great for Language Modeling (LM) 就之前整理 RNN 作為語言模型的神經網絡, 了解上還是可以, 關鍵點在于 W 的複用, 和 上一個狀态的輸出, 作為下一狀态的輸入. 如果對語言模型也稍微了解的話, 對于 RNN 就能很自然過渡, 網絡的邏輯, 也并不複雜.

這裡呢就想來讨論下, 最基礎的 RNN 所待解決的問題, 比如标題所談的梯度消失, 或者梯度爆炸. 然後如何去 fix them. 然後再引入一些 More complex RNN variants (其他的 RNN 變體 如 LSTM, GRU) 等, RNN 我感覺在應用上, 還是蠻不錯的.

然後呢就是關于Vanishing Gradient Problem (梯度消失) 進而引出 LSTM 和 GRU ... 還有各種變體, 如 Bidirectional -RNN; Multi - layer - RNN...

梯度消失與爆炸

這是神經網絡都可能會存在問題, 因為訓練大多基于BP 算法的, 從數學上看就是 多元函數求偏導, 以及求導過程中應用鍊式法則. 中間就是很多項相乘嘛, 如果都是 非常小的數相乘, 那整個結果就接近 0 了呀, 沒有梯度了.

RNN - 梯度消失與爆炸

就像這張圖所表示的那樣, 如果中間的項很小...那整體的結果, 就造成了梯度消失的問題 (Vanishing gradient) .

Vanishing gradient proof sketch

直接從隐含層來看出端倪.

\(h^{(t)} = \sigma(W_hh^{(t-1)} + W_xx^{(t)} + b_t )\)

隐含層取決于, 給定的輸入 x 先onehot 在 embedding, 再和複用的權值矩陣 W 相乘 and 上一個時間點的 W_h 和 h 的乘積. 再作為激活函數的輸入. 最後到一個值都在[0, 1] 之間的向量.

然後對 \(h^{(t-1)}\)

$\frac {\partial h^{(t)} {1}} {\partial h^{(t-1)}} = $ \(diag \ (\sigma ' (W_hh^{(t-1)} + W_xx^{(t)} + b_t ) )W_h\)

  • 鍊式法則而已. 相當于是 y = h(z), z = ax; 要求 y 對 x 的偏導, 即: h(z)' * 偏z 對 偏 x 的值 ....
  • 對于 sigmoid 函數(簡記 \(\sigma(x)\) 求導的結果是, \(\sigma(x) [1-\sigma(x)]\)
RNN - 梯度消失與爆炸

這個 latex 寫得讓人頭疼... 貼個圖算了, 尤其是這種複雜的上下标啥的.

當 \(W_h\) 非常小的時候, 它的 (i-j) 次方, 這個值就會變得非常小了呀. 注意 W_h 是個矩陣啥. 我們通過說的 矩陣的小, 指其 模 非常小 \(|W_h|\) 或者是說, 對這個矩陣 進行 特征分解 (eigenvalue, eigenvector) , 它最大的特征值 的絕對值 如果最大的特征值, 小于 1 則 \(||W_h||\) 這個行列式的值會變很小. (前人已經證明了, 我也沒懂, 就先記一個結論來用着) 如果最大的特征值大于1, 則可能會帶來梯度爆炸的問題 (exploding gradients).

Why is vanishing gradient a problem

解釋一: 從導數的意義上.

梯度消失的表現, 如下圖表示的那樣, 回歸到 導數的意義, 用來衡量 "變化率" \(\frac {dy} {dt}\)

RNN - 梯度消失與爆炸

出現梯度為零, 則表示, 對于 h 的一個微小增量, 而 j 并未受到啥影響. 從圖上來看, 就是隔得太遠, 如 j(4) 基本不會受到 h(1) 的影響了呗. 或者詳細一點可以這樣說:

Gradient signal from faraway is lost because it's much smaller than gradient signal from close-by

So model weights are only updated only with respect to near effects, not long-term effects.

**解釋二: **

Gradient can be viewed ans measure (測量) of the effect of the past on the future. 字面意思就是, 梯度, 可以看成是, 未來對現在的衡量. 梯度小, 則表示未來對現在的影響小.

未來影響現在?? 我感覺這個時間線, 似乎不太了解哦

總之哈, 梯度很小所反映的基本事實是:

  • 在第 t step 和 t + n step , 如果 n 比較大, 則 這兩個狀态的 單詞的 "關聯度" 比較小
  • 因而我們所計算出來的參數就不正确了哦.

Why is exploding gradient a problem

同樣的, 梯度爆炸, 也是一個大問題. (從用梯度下降法來更新參數, 能能直覺看出)

If the gradient becomes too big, then the SGD (随機梯度下降法) update step become too big.

\(\theta^{new} = \theta^{old} - \alpha \nabla _\theta J(\theta)\)

這一塊, 基本了解 ML 的都賊熟悉哈. 本質上是對參數向量的一個調整嘛, 當梯度 \(\nabla _\theta J(\theta)\)

This can cause bad updates : we take too large a step and reach a bad paramenter configuration (with large loss)

從代碼運作角度看,

In the worst case (更加糟糕的是) , this will result in inf or NaN in your network. Then you have to restart training from an earlier checkpoint. 就是代碼報錯, 要重寫搞, 一重寫運作, 幾個小時又過去了...這也是我不太想學深度學習的原因之一.

解決 - 梯度消失和爆炸

solve vanishing

先 pass 下

solve exploding

有種方法叫做, Gradient clipping: If the norm of the gradient is greater than some threshhold (閥值), scale it down before applying SGD update.

如下圖所示, 對參數向量 g 取模, 如果它大于某個閥值, 就 将其更新為 (下圖) 相當于對 g 進行了一個縮放 (變小了)

RNN - 梯度消失與爆炸

向量縮放的特點是, 沒有改變其原來的方向, SGD 中, 就還是沿着 梯度方向來調整參數 哦.

即, take a step in the same direction, but a small step. 有點東西哦.

小結

  • 熟練 RNN 的網絡結構和特性, 如 W 複用, 輸出 -> 輸入
  • 梯度消失, BP的參數訓練, 求導的鍊式法則, 可能會有項直接乘積非常小, 整個式子沒有梯度, 表 詞間的關聯性弱
  • 梯度爆炸, 也是在參數更新這塊, 調整步伐太大, 産生 NaN 或 Inf, 代碼就搞崩了直接
  • 解決梯度消失...
  • 解決梯度爆炸, 可以采用 clipping 的方式, 對向量進行縮放, 而不改變其方向.

繼續閱讀