动手学深度学习14/76
数值稳定性、模型初始化、激活函数python
神经网络的梯度
考虑如下有d层神经网络,t是第t层隐藏层输出。
h
t
=
f
t
(
h
t
−
1
)
a
n
d
y
=
l
⋅
f
d
⋅
⋅
⋅
f
1
(
x
)
h^t=f_t(h^{t-1}) \ \ and \ \ y=l\ ·\ f_d\ ···f_1(x)
ht=ft(ht−1) and y=l ⋅ fd ⋅⋅⋅f1(x)
计算损失函
l
l
l数关于参数
W
t
W_t
Wt的梯度
数值稳定性常见两个问题
-
梯度爆炸(relu)
1.5的100次方约等于4×10的17次方
值超出值域(infinity)
–对于16位浮点数尤为严重
对学习率敏感
–如果学习率太大->大1参数值->更大的梯度
– 如果学习率太小->训练无进展
–可能需要在训练过程中不断调整学习率 -
梯度消失(sigmoid)
0.8的100次方约等于2×10的-10次方
梯度值变为0
–对16位浮点数尤为严重(16比32速度快一些)
训练没有进展
– 不管如何选择学习率
对于底部层尤为严重
– 仅仅顶部层训练好
–无法让神经网络更深
总结
当数值过大或者过小会导致数值问题
常发生在深度模型中,因为其会对n个数累乘。
让训练更加稳定
目标:让梯度值在合理的范围内
–例如[1e-6,1e3]
将乘法变加法
–ResNet,LSTM
归一化
–梯度归一化。梯度裁剪
合理的权值初始和激活函数
让每层的方差是一个常数
将每层的输出和梯度都看做随机变量
让他们的均值和方差保持一致(随机初始化)
t是第t层的输出,i是第i个元素,h隐藏层。
正向
E
[
h
i
t
]
=
0
V
a
r
[
h
i
t
]
=
a
正向\ \ \ \ \ \ E[h_i^t]=0\ \ \ \ Var[h_i^t]=a
正向 E[hit]=0 Var[hit]=a
反向
E
[
∂
l
∂
h
i
t
]
=
0
V
a
r
[
∂
l
∂
h
i
t
]
=
b
反向\ \ \ \ \ \ E[\frac{\partial l}{\partial h_i^t}]=0\ \ \ \ Var[\frac{\partial l}{\partial h_i^t}]=b
反向 E[∂hit∂l]=0 Var[∂hit∂l]=b
权重初始化
-在合理值区间里随机初始参数
-训练开始的时候更容易有数值不稳定
----远离最优解的地方损失函数表面可能很复杂
----最优解附近表面会比较平(梯度比较小)
-使用N(0,0.01)来初始可能对小网络没问题,但不能保证深度神经网络
也就是,这里的的约束是,方差要根据输入和输出的维度进行初始化。
这里推导出来,就是激活函数,输入等于输出,y=x。
在0点附近,tanh()和relu()都符合y=x,sigmoid要改动
总结
合理的权重初始值和激活函数的选取可以提升数值稳定性。
QA
- inf解决:权重初始化方差小一些,学习率调小。
- 训练2epoch后准确率稳定在50%,可能数据稳定性不好。
- 中间值nan,可能是梯度爆炸。
- sigmoid容易引起梯度消失,用relu可以一定程度解决。
- 随机初始化可以先尝试用上面的Xavier约束
- 正态分布容易推理。