梯度爆炸/消失
梯度消失 : 參數更新過小,在每次更新時幾乎不會移動,導致模型無法學習。
%matplotlib inline
import torch
from d2l import torch as d2l
# 梯度消失 參數更新過小,在每次更新時幾乎不會移動,導致模型無法學習
x = torch.arange(-8.0, 8.0, 0.1, requires_grad=True)
y = torch.sigmoid(x)
y.backward(torch.ones_like(x))
d2l.plot(x.detach().numpy(),[y.detach().numpy(),x.grad.numpy()],legend=["Sigmoid","Grad"],figsize=(4.5,2.5))
梯度爆炸 : 參數更新過大,破壞了模型的穩定收斂。
M = torch.normal(0, 1, size=(4,4))
print('一個矩陣 \n',M)
for i in range(100):
M = torch.mm(M,torch.normal(0, 1, size=(4, 4)))
print('乘以100個矩陣后\n', M)
[out]:一個矩陣
tensor([[ 0.7392, -0.7381, 0.1063, 0.5866],
[-0.0302, -1.4010, 0.2725, -0.3175],
[-1.9900, -1.1248, 1.7442, 1.3487],
[-0.5263, 0.5572, 0.2403, 0.6967]])
乘以100個矩陣后
tensor([[ 1.4398e+25, -4.8513e+24, -2.9295e+23, -2.8513e+24],
[ 1.3503e+25, -4.5497e+24, -2.7475e+23, -2.6741e+24],
[-1.8323e+25, 6.1736e+24, 3.7281e+23, 3.6285e+24],
[-1.4487e+25, 4.8811e+24, 2.9476e+23, 2.8689e+24]])
具體的可以參考沐神D2l文章:http://zh.d2l.ai/chapter_multilayer-perceptrons/numerical-stability-and-init.html#id5
對於沐神所說的改變權重的順序或者重排列,不能夠改善梯度爆炸和梯度消失。這里是因為改變權重順序或者重排列只是讓我們的MLP換了另外一種線性表達,本質上還是線性。為了讓訓練更加穩定,我們有很多種方法可以限制梯度:
- 把梯度限制在一定的范圍內。
- 將乘法變成加法: ResNet , LSTM
- 歸一化: 梯度歸一化。梯度裁剪。
- 合理權重初始化和激活函數。
其中一個比較不錯的權重初始化的方式是Xavier。
Xavier初始化
解決(或至少減輕)上述問題的一種方法是進行參數初始化, 優化期間的注意和適當的正則化也可以進一步提高穩定性。
讓我們看看某些沒有非線性的全連接層輸出(例如,隱藏變量)\(o_i\) 的尺度分布。 對於該層 \(n_{in}\) 輸入 \(x_j\) 及其相關權重 \(w_{ij}\) ,輸出由下式給出
權重 \(w_{ij}\) 都是從同一分布中獨立抽取的。 此外,讓我們假設該分布具有零均值和方差 \(σ^2\) 。 請注意,這並不意味着分布必須是高斯的,只是均值和方差需要存在。 現在,讓我們假設層 \(x_j\) 的輸入也具有零均值和方差 \(γ^2\) , 並且它們獨立於 \(w_{ij}\) 並且彼此獨立。 在這種情況下,我們可以按如下方式計算 \(o_i\) 的平均值和方差:
保持方差不變的一種方法是設置 \(n_{in}σ^2=1\) 。 現在考慮反向傳播過程,我們面臨着類似的問題,盡管梯度是從更靠近輸出的層傳播的。 使用與前向傳播相同的推斷,我們可以看到,除非 \(n_{out}σ^2=1\) , 否則梯度的方差可能會增大,其中 \(n_{out}\) 是該層的輸出的數量。 這使得我們進退兩難:我們不可能同時滿足這兩個條件。 相反,我們只需滿足:
通常,Xavier初始化從均值為零,方差 \(\sigma^2 = \frac{2}{n_\mathrm{in} + n_\mathrm{out}}\) 的高斯分布中采樣權重。我們也可以利用Xavier的直覺來選擇從均勻分布中抽取權重時的方差。 注意均勻分布 \(U(−a,a)\) 的方差為 \(\frac{a^2}{3}\) 。 將 \(\frac{a^2}{3}\) 代入到 \(\sigma^2\) 的條件中,將得到初始化值域:
盡管在上述數學推理中,“不存在非線性”的假設在神經網絡中很容易被違反, 但Xavier初始化方法在實踐中被證明是有效的。
最后做個總結的話就是:
- 需要用啟發式的初始化方法來確保初始梯度既不太大也不太小。
- ReLU激活函數緩解了梯度消失問題,這樣可以加速收斂。
- 隨機初始化是保證在進行優化前打破對稱性的關鍵。
- Xavier初始化表明,對於每一層,輸出的方差不受輸入數量的影響,任何梯度的方差不受輸出數量的影響。