深度学习-学习笔记(数值稳定性)

最近看李沐老师的动手学深度学习,有很多收获,因此将老师讲课内容稍作总结,以便以后翻阅学习

数值稳定性

数值稳定性是神经网络模型一个非常重要的内容,模型不稳定一般与梯度消失梯度爆炸有关。梯度消失时,模型会停止训练,梯度爆炸时,参数会变得特别大。
为了保持数值的稳定,我们需要选择合适的参数初始化方案和合理的非线性激活函数

梯度的计算

一个d层的神经网络,每一层用 l l l表示,则 h ( l ) \boldsymbol{h}^{(l)} h(l)表示第 l l l层的输出, h ( l − 1 ) \boldsymbol{h}^{(l-1)} h(l1)表示第 l l l层的输入( h ( 0 ) = x \boldsymbol{h}^{(0)}=\boldsymbol{x} h(0)=x),则
h ( l ) = f l ( h l − 1 ) \boldsymbol{h}^{(l)}=f_{l}(\boldsymbol{h}^{l-1}) h(l)=fl(hl1) y = l ○ f d ○ . . . ○ f 1 ( x ) y=l○f_{d}○...○f_{1}(x) y=lfd...f1(x)(这里y包含了损失函数,不是模型的输出)
∂ l ∂ W l = ∂ l ∂ h d ∂ h d ∂ h d − 1 . . . ∂ h l + 1 ∂ h l ∂ h l ∂ W l \frac{\partial l}{\partial \boldsymbol{W}^{l}}=\frac{\partial l}{\partial \boldsymbol{h}^{d}} \frac{\partial \boldsymbol{h}^{d}}{\partial \boldsymbol{h}^{d-1}}...\frac{\partial \boldsymbol{h}^{l+1}}{\partial \boldsymbol{h}^{l}} \frac{\partial \boldsymbol{h}^{l}}{\partial \boldsymbol{W}^{l}} Wll=hdlhd1hd...hlhl+1Wlhl(向量关于向量的导数是矩阵,公式为矩阵乘法)中间有连乘项:
∏ i = l d − 1 ∂ h i + 1 ∂ h i \prod_{i=l}^{d-1}{\frac{\partial \boldsymbol{h}^{i+1}}{\partial \boldsymbol{h}^{i}}} i=ld1hihi+1

  • 对于简单的MLP模型(忽略偏移bias),
    f l ( h l − 1 ) = σ ( W l h l − 1 ) ( σ 是 激 活 函 数 ) f_l(\boldsymbol{h}^{l-1})=\sigma (\boldsymbol{W^{l}h^{l-1}}) (\sigma是激活函数) fl(hl1)=σ(Wlhl1)(σ) ∂ h l ∂ h l − 1 = d i a g ( σ ′ ( W l h l − 1 ) ) ( W l ) T ( σ ′ 是 σ 的 导 数 函 数 , ‘ 为 什 么 是 对 角 矩 阵 目 前 还 不 明 白 ’ ) \frac{\partial \boldsymbol{h}^{l}}{\partial \boldsymbol{h}^{l-1}} = diag(\sigma^{'} (\boldsymbol{W^{l}h^{l-1}}))(\boldsymbol{W^{l}})^{T} (\sigma^{'}是\sigma的导数函数,‘为什么是对角矩阵目前还不明白’) hl1hl=diag(σ(Wlhl1))(Wl)T(σσ)
    ∏ i = l d − 1 ∂ h i + 1 ∂ h i = ∏ i = l d − 1 { d i a g ( σ ′ ( W i + 1 h i ) ) ( W i + 1 ) T } \prod_{i=l}^{d-1}{\frac{\partial \boldsymbol{h}^{i+1}}{\partial \boldsymbol{h}^{i}}} = \prod_{i=l}^{d-1}\{{diag(\sigma^{'} (\boldsymbol{W^{i+1}h^{i}}))(\boldsymbol{W^{i+1}})^{T}}\} i=ld1hihi+1=i=ld1{diag(σ(Wi+1hi))(Wi+1)T}
    这其中的连乘项是每一层激活函数的导数乘以对应的参数w
    当神经网络层数很深时( d − l d-l dl很大):
    1. 连乘项稍微大于1时: 1. 5 100 ≈ 4 ∗ 1 0 17 1.5^{100}\approx4*10^{17} 1.510041017梯度爆炸
    2. 连乘项稍微小于1时: 0. 8 100 ≈ 2 ∗ 1 0 − 10 0.8^{100}\approx2*10^{-10} 0.810021010梯度消失

(注意: 由于连乘项不止有激活函数的导数,还包含参数w,所以Relu不能完全消除梯度消失和梯度爆炸,只能缓解)

梯度爆炸

由于损失函数对参数的梯度是一个连乘的形式,神经网络很深时,哪怕连乘项比1大一点,如 1. 5 100 ≈ 4 ∗ 1 0 17 1.5^{100}\approx4*10^{17} 1.510041017,也会导致梯度特别大。

梯度爆炸的问题

  • 值会超出计算机浮点数的值域(infinity)
    • GPU会使用16位浮点数(6e-5 - 6e4),此时尤为严重
  • 对学习率敏感
    • 学习率稍微大一点就会造成很大的更新,稍微小一点训练又无进展,很难调

梯度消失

某些激活函数,如sigmoid和tanh,在定义域两端的导数很小,无限接近0,导致连乘项很小,即使连乘项稍微小于1,网络层数过深时也会导致梯度无限接近0,如 0. 8 100 ≈ 2 ∗ 1 0 − 10 0.8^{100}\approx2*10^{-10} 0.810021010

梯度消失的问题

  • 值很小时计算机会把它当做0
    • 特别是16位浮点数
  • 导致训练没有进展,调整学习率也没有用
  • 顶层可能可以正常训练,底层网络梯度很小导致无法更新参数,相当于很浅的网络

小结

由于损失函数对参数的梯度是一个n个数的累乘,当数值过大或过小时都会使模型不稳定(梯度消失或梯度爆炸)
为了使训练更加稳定,我们需要使梯度在一个合理的范围内,有很多方法,如:

  • 将梯度的连乘形式变成加法(ResNet,LSTM)
  • 归一化(梯度归一化,梯度裁剪)
  • 选择合适的权重初始和激活函数

你可能感兴趣的:(深度学习-学习笔记,深度学习,神经网络)