动手学习深度学习(7)数值稳定性+模型初始化和激活函数

茴香豆 Lv5

本节中将讨论一些有用的启发式方法,来对模型选择合适的初始化参数,来避免梯度爆炸或者梯度消失。你会发现这些启发式方法在整个深度学习生涯中都很有用。

梯度消失和梯度爆炸

梯度消失(gradient vanishing):参数更新过小,在每次更新时几乎不会移动,导致模型无法学习。对底部层尤为严重:

  • 仅仅顶部层训练的较好
  • 无法使神经网络更深

通过下列代码的运行结果

1
2
3
4
5
6
7
8
%matplotlib inline
import torch
from d2l import troch 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', 'gradient'], figsize=(4.5, 2.5))

当sigmoid函数的输入很大或者很小时,它的梯度都会消失。

梯度爆炸(gradient exploding):参数更新过大,破坏了模型的稳定收敛。

对学习率敏感:

  • 学习率过大->大参数值->更大的梯度
  • 学习率过小->训练无进展

为了更好地说明这一点,我们生成100个高斯随机矩阵,并将它们与某个初始矩阵相乘。 对于我们选择的尺度(方差 σ^2=1 ),矩阵乘积发生爆炸。 当这种情况是由于深度网络的初始化所导致时,我们没有机会让梯度下降优化器收敛。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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)
# output
一个矩阵
tensor([[ 0.4382, -0.7687, 0.2731, -0.2587],
[-0.1789, -0.2395, 1.4915, 0.2634],
[-0.5272, 0.2403, 2.4397, -0.7587],
[ 0.9805, 0.4166, -0.1906, -0.2581]])
乘以100个矩阵后
tensor([[ 7.6616e+22, 4.2587e+22, -5.8065e+22, 1.2980e+23],
[-2.3790e+21, -1.3224e+21, 1.8030e+21, -4.0304e+21],
[-1.3796e+23, -7.6687e+22, 1.0456e+23, -2.3373e+23],
[ 8.5987e+20, 4.7795e+20, -6.5167e+20, 1.4567e+21]])

让训练更加稳定

目标:让梯度值在合理的范围内

  • 乘法变加法:ResNet,LSTM
  • 归一化:梯度归一化,梯度裁剪
  • 合理的权重初始和使用合理的激活函数

权重初始化

  • 在合理值区间里随机初始化参数
  • 训练开始的时候更容易由数值不稳定:靠近最优点平滑,远离最优点表面可能很复杂
  • 使用N(0, 0.01)来初始化可能对小网络没问题,但不能保证深度神经网络

Xavier初始化
MATHJAX-SSR-34

  • 正态分布 N(0,\sqrt{2/(n_{t-1}+n_t)})
  • 均匀分布 U(-\sqrt{6/(n_{t-1}+n_t)}, \sqrt{6/(n_{t-1}+n_t)})

激活函数

激活函数在0点附近应当与y=x函数近似。

  • Title: 动手学习深度学习(7)数值稳定性+模型初始化和激活函数
  • Author: 茴香豆
  • Created at : 2022-10-29 09:38:47
  • Updated at : 2022-10-29 11:27:05
  • Link: https://hxiangdou.github.io/2022/10/29/DL_7/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments
On this page
动手学习深度学习(7)数值稳定性+模型初始化和激活函数