faster-rcnn中使用clip_gradient函数防止梯度爆炸

clip_gradient 的作用就是让权重的更新限制在一个合适的范围:

  • 首先设置一个梯度阈值:clip_gradient
  • 在反向传播中求出各参数的梯度,这里我们不直接使用梯度进行参数更新,我们求这些梯度的l2范数||g||
  • 然后比较||g||与clip_gradient的大小
  • 如果前者大,求缩放因子clip_gradient/||g||, 由缩放因子可以看出梯度越大,则缩放因子越小,这样便很好地控制了梯度的范围
  • 最后将梯度乘上缩放因子便得到最后所需的梯度

pytorch版代码如下:

#使用梯度剪切,防止梯度爆炸
def clip_gradient(model, clip_norm):
    """Computes a gradient clipping coefficient based on gradient norm."""
    #基于梯度范数计算梯度剪切系数。
    totalnorm = 0
    for p in model.parameters():
        if p.requires_grad and p.grad is not None:
            modulenorm = p.grad.norm()  #计算该参数所有梯度的L2范数
            totalnorm += modulenorm ** 2
    totalnorm = torch.sqrt(totalnorm).item()
    norm = (clip_norm / max(totalnorm, clip_norm))  #得到梯度剪切系数
    for p in model.parameters():
        if p.requires_grad and p.grad is not None:
            p.grad.mul_(norm)

其中,二阶范数(也称L2范数)是最常见的范数,即欧几里得距离,表达式如下:

                                                                                           \left \| x \right \|_{p}=\sqrt[p]{x_{1}^{p}+x_{2}^{p}+...+x_{n}^{p}}

即,对N个数据求p范数。代码中norm()函数参数都使用默认值,那么就是求所有数值的2范数。


参考链接:https://blog.csdn.net/u010814042/article/details/76154391

你可能感兴趣的:(#,Faster-rcnn)