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)
以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。
相关推荐
-
Pytorch中的自动求梯度机制和Variable类实例
自动求导机制是每一个深度学习框架中重要的性质,免去了手动计算导数,下面用代码介绍并举例说明Pytorch的自动求导机制. 首先介绍Variable,Variable是对Tensor的一个封装,操作和Tensor是一样的,但是每个Variable都有三个属性:Varibale的Tensor本身的.data,对应Tensor的梯度.grad,以及这个Variable是通过什么方式得到的.grad_fn,根据最新消息,在pytorch0.4更新后,torch和torch.autograd.Variab
-
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 禁止/允许计算局部梯度的操作
一.禁止计算局部梯度 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 如何打印网络回传梯度
需求: 打印梯度,检查网络学习情况 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实现将模型的所有参数的梯度清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获取无梯度TorchTensor中的值
获取无梯度Tensor 遇到的问题: 使用两个网络并行运算,一个网络的输出值要给另一个网络反馈.而反馈的输出值带有网络权重的梯度,即grad_fn=<XXXBackward0>. 这时候如果把反馈值扔到第二网络中更新,会出现第一个计算图丢失无法更新的错误.哎哟喂,我根本不需要第一个网络的梯度好吗? 一开始用了一个笨办法,先转numpy,然后再转回torch.Tensor.因为numpy数据是不带梯度的. 但是我的原始tensor的放在cuda上的, cuda的张量是不能直接转Tensor,所以
-
PyTorch 如何自动计算梯度
在PyTorch中,torch.Tensor类是存储和变换数据的重要工具,相比于Numpy,Tensor提供GPU计算和自动求梯度等更多功能,在深度学习中,我们经常需要对函数求梯度(gradient). PyTorch提供的autograd包能够根据输入和前向传播过程自动构建计算图,并执行反向传播. 本篇将介绍和总结如何使用autograd包来进行自动求梯度的有关操作. 1. 概念 Tensor是这个pytorch的自动求导部分的核心类,如果将其属性.requires_grad=True,它将开
-
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. 这个
随机推荐
- Perl 批量添加Copyright版权信息
- php中static静态变量的使用方法详解
- 介绍使用WordPress时10个常用的MySQL查询
- 用VBS修改(设置)系统时间和日期的代码
- Struts2的s:radio标签使用及用jquery添加change事件
- 基于js实现的限制文本框只可以输入数字
- 递归删除一个节点以及该节点下的所有节点示例
- python socket多线程通讯实例分析(聊天室)
- JavaWeb实现图形报表折线图的方法
- C#中执行批处理文件(*.bat)的方法代码
- Android使用ViewPager加载图片和轮播视频
- VUE实现一个分页组件的示例
- Nodejs极简入门教程(二):定时器
- java中List集合及其遍历详解
- 启动sqlserver服务的bat脚本分享
- sqlserver isnull在数据库查询中的应用
- javascript学习笔记(二十) 获得和设置元素的特性(属性)
- 特殊的IP地址分析
- 浅谈SpringCloud实现简单的微服务架构
- python读写配置文件操作示例