PyTorch梯度裁剪避免训练loss nan的操作

近来在训练检测网络的时候会出现loss为nan的情况,需要中断重新训练,会很麻烦。因而选择使用PyTorch提供的梯度裁剪库来对模型训练过程中的梯度范围进行限制,修改之后,不再出现loss为nan的情况。

PyTorch中采用torch.nn.utils.clip_grad_norm_来实现梯度裁剪,链接如下:

https://pytorch.org/docs/stable/_modules/torch/nn/utils/clip_grad.html

训练代码使用示例如下:

from torch.nn.utils import clip_grad_norm_
outputs = model(data)
loss= loss_fn(outputs, target)
optimizer.zero_grad()
loss.backward()
# clip the grad
clip_grad_norm_(model.parameters(), max_norm=20, norm_type=2)
optimizer.step()

其中,max_norm为梯度的最大范数,也是梯度裁剪时主要设置的参数。

备注:网上有同学提醒在(强化学习)使用了梯度裁剪之后训练时间会大大增加。目前在我的检测网络训练中暂时还没有碰到这个问题,以后遇到再来更新。

补充:pytorch训练过程中出现nan的排查思路

1、最常见的就是出现了除0或者log0这种

看看代码中在这种操作的时候有没有加一个很小的数,但是这个数数量级要和运算的数的数量级要差很多。一般是1e-8。

2、在optim.step()之前裁剪梯度

optim.zero_grad()
loss.backward()
nn.utils.clip_grad_norm(model.parameters, max_norm, norm_type=2)
optim.step()

max_norm一般是1,3,5。

3、前面两条还不能解决nan的话

就按照下面的流程来判断。

...
loss = model(input)
# 1. 先看loss是不是nan,如果loss是nan,那么说明可能是在forward的过程中出现了第一条列举的除0或者log0的操作
assert torch.isnan(loss).sum() == 0, print(loss)
optim.zero_grad()
loss.backward()
# 2. 如果loss不是nan,那么说明forward过程没问题,可能是梯度爆炸,所以用梯度裁剪试试
nn.utils.clip_grad_norm(model.parameters, max_norm, norm_type=2)
# 3.1 在step之前,判断参数是不是nan, 如果不是判断step之后是不是nan
assert torch.isnan(model.mu).sum() == 0, print(model.mu)
optim.step()
# 3.2 在step之后判断,参数和其梯度是不是nan,如果3.1不是nan,而3.2是nan,
# 特别是梯度出现了Nan,考虑学习速率是否太大,调小学习速率或者换个优化器试试。
assert torch.isnan(model.mu).sum() == 0, print(model.mu)
assert torch.isnan(model.mu.grad).sum() == 0, print(model.mu.grad)

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • PyTorch 如何自动计算梯度

    在PyTorch中,torch.Tensor类是存储和变换数据的重要工具,相比于Numpy,Tensor提供GPU计算和自动求梯度等更多功能,在深度学习中,我们经常需要对函数求梯度(gradient). PyTorch提供的autograd包能够根据输入和前向传播过程自动构建计算图,并执行反向传播. 本篇将介绍和总结如何使用autograd包来进行自动求梯度的有关操作. 1. 概念 Tensor是这个pytorch的自动求导部分的核心类,如果将其属性.requires_grad=True,它将开

  • pytorch 禁止/允许计算局部梯度的操作

    一.禁止计算局部梯度 torch.autogard.no_grad: 禁用梯度计算的上下文管理器. 当确定不会调用Tensor.backward()计算梯度时,设置禁止计算梯度会减少内存消耗.如果需要计算梯度设置Tensor.requires_grad=True 两种禁用方法: 将不用计算梯度的变量放在with torch.no_grad()里 >>> x = torch.tensor([1.], requires_grad=True) >>> with torch.n

  • pytorch损失反向传播后梯度为none的问题

    错误代码:输出grad为none a = torch.ones((2, 2), requires_grad=True).to(device) b = a.sum() b.backward() print(a.grad) 由于.to(device)是一次操作,此时的a已经不是叶子节点了 修改后的代码为: a = torch.ones((2, 2), requires_grad=True) c = a.to(device) b = c.sum() b.backward() print(a.grad)

  • Pytorch中的自动求梯度机制和Variable类实例

    自动求导机制是每一个深度学习框架中重要的性质,免去了手动计算导数,下面用代码介绍并举例说明Pytorch的自动求导机制. 首先介绍Variable,Variable是对Tensor的一个封装,操作和Tensor是一样的,但是每个Variable都有三个属性:Varibale的Tensor本身的.data,对应Tensor的梯度.grad,以及这个Variable是通过什么方式得到的.grad_fn,根据最新消息,在pytorch0.4更新后,torch和torch.autograd.Variab

  • Pytorch获取无梯度TorchTensor中的值

    获取无梯度Tensor 遇到的问题: 使用两个网络并行运算,一个网络的输出值要给另一个网络反馈.而反馈的输出值带有网络权重的梯度,即grad_fn=<XXXBackward0>. 这时候如果把反馈值扔到第二网络中更新,会出现第一个计算图丢失无法更新的错误.哎哟喂,我根本不需要第一个网络的梯度好吗? 一开始用了一个笨办法,先转numpy,然后再转回torch.Tensor.因为numpy数据是不带梯度的. 但是我的原始tensor的放在cuda上的, cuda的张量是不能直接转Tensor,所以

  • Pytorch实现将模型的所有参数的梯度清0

    有两种方式直接把模型的参数梯度设成0: model.zero_grad() optimizer.zero_grad()#当optimizer=optim.Optimizer(model.parameters())时,两者等效 如果想要把某一Variable的梯度置为0,只需用以下语句: Variable.grad.data.zero_() 补充知识:PyTorch中在反向传播前为什么要手动将梯度清零?optimizer.zero_grad()的意义 optimizer.zero_grad()意思

  • pytorch 如何打印网络回传梯度

    需求: 打印梯度,检查网络学习情况 net = your_network().cuda() def train(): ... outputs = net(inputs) loss = criterion(outputs, targets) loss.backward() for name, parms in net.named_parameters(): print('-->name:', name, '-->grad_requirs:',parms.requires_grad, \ ' --

  • PyTorch梯度裁剪避免训练loss nan的操作

    近来在训练检测网络的时候会出现loss为nan的情况,需要中断重新训练,会很麻烦.因而选择使用PyTorch提供的梯度裁剪库来对模型训练过程中的梯度范围进行限制,修改之后,不再出现loss为nan的情况. PyTorch中采用torch.nn.utils.clip_grad_norm_来实现梯度裁剪,链接如下: https://pytorch.org/docs/stable/_modules/torch/nn/utils/clip_grad.html 训练代码使用示例如下: from torch

  • tensorflow中的梯度求解及梯度裁剪操作

    1. tensorflow中梯度求解的几种方式 1.1 tf.gradients tf.gradients( ys, xs, grad_ys=None, name='gradients', colocate_gradients_with_ops=False, gate_gradients=False, aggregation_method=None, stop_gradients=None, unconnected_gradients=tf.UnconnectedGradients.NONE )

  • pytorch 梯度NAN异常值的解决方案

    pytorch 梯度NAN异常值 gradient 为nan可能原因: 1.梯度爆炸 2.学习率太大 3.数据本身有问题 4.backward时,某些方法造成0在分母上, 如:使用方法sqrt() 定位造成nan的代码: import torch # 异常检测开启 torch.autograd.set_detect_anomaly(True) # 反向传播时检测是否有异常值,定位code with torch.autograd.detect_anomaly(): loss.backward()

  • PyTorch: 梯度下降及反向传播的实例详解

    线性模型 线性模型介绍 线性模型是很常见的机器学习模型,通常通过线性的公式来拟合训练数据集.训练集包括(x,y),x为特征,y为目标.如下图: 将真实值和预测值用于构建损失函数,训练的目标是最小化这个函数,从而更新w.当损失函数达到最小时(理想上,实际情况可能会陷入局部最优),此时的模型为最优模型,线性模型常见的的损失函数: 线性模型例子 下面通过一个例子可以观察不同权重(w)对模型损失函数的影响. #author:yuquanle #data:2018.2.5 #Study of Linear

  • 详解如何使用Pytorch进行多卡训练

    目录 1.DP 2.DDP 2.1Pytorch分布式基础 2.2Pytorch分布式训练DEMO 当一块GPU不够用时,我们就需要使用多卡进行并行训练.其中多卡并行可分为数据并行和模型并行.具体区别如下图所示: 由于模型并行比较少用,这里只对数据并行进行记录.对于pytorch,有两种方式可以进行数据并行:数据并行(DataParallel, DP)和分布式数据并行(DistributedDataParallel, DDP). 在多卡训练的实现上,DP与DDP的思路是相似的: 1.每张卡都复制

  • pytorch梯度剪裁方式

    我就废话不多说,看例子吧! import torch.nn as nn outputs = model(data) loss= loss_fn(outputs, target) optimizer.zero_grad() loss.backward() nn.utils.clip_grad_norm_(model.parameters(), max_norm=20, norm_type=2) optimizer.step() nn.utils.clip_grad_norm_ 的参数: param

  • pytorch实现seq2seq时对loss进行mask的方式

    如何对loss进行mask pytorch官方教程中有一个Chatbot教程,就是利用seq2seq和注意力机制实现的,感觉和机器翻译没什么不同啊,如果对话中一句话有下一句,那么就把这一对句子加入模型进行训练.其中在训练阶段,损失函数通常需要进行mask操作,因为一个batch中句子的长度通常是不一样的,一个batch中不足长度的位置需要进行填充(pad)补0,最后生成句子计算loss时需要忽略那些原本是pad的位置的值,即只保留mask中值为1位置的值,忽略值为0位置的值,具体演示如下: im

  • Tensorflow之梯度裁剪的实现示例

    tensorflow中的梯度计算和更新 为了解决深度学习中常见的梯度消失(gradient explosion)和梯度爆炸(gradients vanishing)问题,tensorflow中所有的优化器tf.train.xxxOptimizer都有两个方法: compute_gradients apply_gradients compute_gradients 对于compute_gradients方法,计算var_list中参数的梯度,使得loss变小.默认情况下,var_list为Grap

  • 人工智能学习Pytorch梯度下降优化示例详解

    目录 一.激活函数 1.Sigmoid函数 2.Tanh函数 3.ReLU函数 二.损失函数及求导 1.autograd.grad 2.loss.backward() 3.softmax及其求导 三.链式法则 1.单层感知机梯度 2. 多输出感知机梯度 3. 中间有隐藏层的求导 4.多层感知机的反向传播 四.优化举例 一.激活函数 1.Sigmoid函数 函数图像以及表达式如下: 通过该函数,可以将输入的负无穷到正无穷的输入压缩到0-1之间.在x=0的时候,输出0.5 通过PyTorch实现方式

  • 详解pytorch的多GPU训练的两种方式

    目录 方法一:torch.nn.DataParallel 1. 原理 2. 常用的配套代码如下 3. 优缺点 方法二:torch.distributed 1. 代码说明 方法一:torch.nn.DataParallel 1. 原理 如下图所示:小朋友一个人做4份作业,假设1份需要60min,共需要240min. 这里的作业就是pytorch中要处理的data. 与此同时,他也可以先花3min把作业分配给3个同伙,大家一起60min做完.最后他再花3min把作业收起来,一共需要66min. 这个

随机推荐