RNN梯度裁剪

RNN梯度裁剪

  最近抗疫在家蹲监狱,恰巧参加DataWhale组织的组队学习,这次的内容是深度学习,看到RNN的讲解这里,有一个“梯度裁剪”的方法不是很理解,故百度一波,整理一下,首先放上讲解中的定义(也是我百度出来的第一篇博客里的内容):
  循环神经网络中较容易出现梯度衰减或梯度爆炸,这会导致网络几乎无法训练。裁剪梯度(clip gradient)是一种应对梯度爆炸的方法。假设我们把所有模型参数的梯度拼接成一个向量 𝑔 ,并设裁剪的阈值是 𝜃 。裁剪后的梯度的 𝐿2 范数不超过 𝜃 。

             m i n ( θ ∣ ∣ g ∣ ∣ , 1 ) g min(\frac{\theta}{||g||},1)g min(gθ,1)g        (1)

  第一次看过这个定义后,我知道这方法无非就是设置一个阈值,当梯度过大时,反向传播(BP)就按设定的阈值来,至于上面的公式,看不懂。那么就从头道来,这里参考的是知乎大神,原文链接:深度炼丹之梯度裁剪

梯度爆炸问题的出现

  考虑最简单的形式,假设一个单层感知机:
Y = w X + b Y =wX+b Y=wX+b

其中Y是输出,X是输入,w是需要训练的参数,为进一步简化,设b=0,这样单层感知机变为:
Y = w X Y =wX Y=wX
  那么这个单层感知机的梯度grad是:
g r a d = d Y d w = X grad=\frac{dY}{dw}=X grad=dwdY=X
  现在带值进去看,假设w初始值 w 0 w_0 w0为1,X=120,学习率lr=0.1,现在进行BP过程:
w = w 0 − l r ∗ g r a d w=w_0-lr*grad w=w0lrgrad
w = 1 − 0.1 ∗ 120 = − 11 w=1-0.1*120=-11 w=10.1120=11
  这只是一次BP,梯度就这么大,在RNN里,有多少个时间序列,grad就会累乘多少个,当时间序列很长,每个grad都是远大于1的数值时,当BP过程传到前面时就会造成梯度爆炸。

pytorch中的梯度裁剪方法

  pytorch中使用clip_grad_value_()函数对grad进行限制,源码:

def clip_grad_value_(parameters, clip_value):
    r"""Clips gradient of an iterable of parameters at specified value.
    Gradients are modified in-place.

    Arguments:
        parameters (Iterable[Tensor] or Tensor): an iterable of Tensors or a
            single Tensor that will have gradients normalized
        clip_value (float or int): maximum allowed value of the gradients.
            The gradients are clipped in the range
    """

    if isinstance(parameters, torch.Tensor):
        parameters = [parameters]
    clip_value = float(clip_value)
    for p in filter(lambda p: p.grad is not None, parameters):
        p.grad.data.clamp_(min=-clip_value, max=clip_value)

源码中clip_value就是自己设置的阈值,从最后一行来看,这个函数的作用就是把grad限制在 ± \pm ±|clip_value|之内,貌似与公式(1)没什么关系 - -!

回看公式(1)

  通过上述理解,我再次看到公式(1)时: m i n ( θ ∣ ∣ g ∣ ∣ , 1 ) g min(\frac{\theta}{||g||},1)g min(gθ,1)g现固定一个你自己设置的阈值 θ \theta θ(为了方便说明,就设 θ \theta θ=2),由于式中g为梯度grad,当g很大时,会造成梯度爆炸问题,假设此时那那 ∣ ∣ g ∣ ∣ = 4 ||g|| =4 g=4 θ ∣ ∣ g ∣ ∣ = 0.5 < 1 \frac{\theta}{||g||}=0.5<1 gθ=0.5<1,那么 m i n ( θ ∣ ∣ g ∣ ∣ , 1 ) g = θ ∣ ∣ g ∣ ∣ g = 0.5 g min(\frac{\theta}{||g||},1)g=\frac{\theta}{||g||}g=0.5g min(gθ,1)g=gθg=0.5g
当g不是很大时,假设此时 ∣ ∣ g ∣ ∣ = 1 ||g||=1 g=1 θ ∣ ∣ g ∣ ∣ = 2 > 1 \frac{\theta}{||g||}=2>1 gθ=2>1,那么 m i n ( θ ∣ ∣ g ∣ ∣ , 1 ) g = 1 ∗ g = g min(\frac{\theta}{||g||},1)g=1*g=g min(gθ,1)g=1g=g
  通过对公式(1)的分析可以看出,梯度裁剪就是当你梯度太大时强行把梯度缩小(通过乘以一个小于1的数,即 θ ∣ ∣ g ∣ ∣ \frac{\theta}{||g||} gθ),当你梯度不是很大时,保持原样。

  至于解释中 “裁剪后的梯度的L2范数不超过 θ \theta θ ”我还不是很理解,以及为什么选择 θ ∣ ∣ g ∣ ∣ \frac{\theta}{||g||} gθ当裁剪系数,希望有大佬可以告诉我,前面内容表述如有理解不当烦请轻喷,谢谢。

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值