点击上方“码农突围”,马上关注

这里是码农充电第一站,回复“666”,获取一份专属大礼包

真爱,请设置“星标”或点个“在看”

作者 | hyk_1996

源:CSDN博客

编译:大白

1. nn.Module.cuda() 和 Tensor.cuda() 的作用效果差异

无论是对于模型还是数据,cuda()函数都能实现从CPU到GPU的内存迁移,但是他们的作用效果有所不同。

对于nn.Module:

model = model.cuda()
model.cuda() 

上面两句能够达到一样的效果,即对model自身进行的内存迁移。

对于Tensor:

和nn.Module不同,调用tensor.cuda()只是返回这个tensor对象在GPU内存上的拷贝,而不会对自身进行改变。因此必须对tensor进行重新赋值,即tensor=tensor.cuda().

例子:

model = create_a_model()
tensor = torch.zeros([2,3,10,10])
model.cuda()
tensor.cuda()
model(tensor)    # 会报错
tensor = tensor.cuda()
model(tensor)    # 正常运行

2. PyTorch 0.4 计算累积损失的不同

以广泛使用的模式total_loss += loss.data[0]为例。Python0.4.0之前,loss是一个封装了(1,)张量的Variable,但Python0.4.0的loss现在是一个零维的标量。对标量进行索引是没有意义的(似乎会报 invalid index to scalar variable 的错误)。使用loss.item()可以从标量中获取Python数字。所以改为:

total_loss += loss.item()

如果在累加损失时未将其转换为Python数字,则可能出现程序内存使用量增加的情况。这是因为上面表达式的右侧原本是一个Python浮点数,而它现在是一个零维张量。因此,总损失累加了张量和它们的梯度历史,这可能会产生很大的autograd 图,耗费内存和计算资源。

3. PyTorch 0.4 编写不限制设备的代码

# torch.device object used throughout this script
device = torch.device("cuda" if use_cuda else "cpu")
model = MyRNN().to(device)# train
total_loss= 0
for input, target in train_loader:input, target = input.to(device), target.to(device)hidden = input.new_zeros(*h_shape)       # has the same device & dtype as `input`...                                                               # get loss and optimizetotal_loss += loss.item()# test
with torch.no_grad():                                    # operations inside don't track historyfor input, targetin test_loader:...

4. torch.Tensor.detach()的使用

detach()的官方说明如下:

Returns a new Tensor, detached from the current graph.The result will never require gradient.

假设有模型A和模型B,我们需要将A的输出作为B的输入,但训练时我们只训练模型B. 那么可以这样做:

input_B = output_A.detach()

它可以使两个计算图的梯度传递断开,从而实现我们所需的功能。

5. ERROR: Unexpected bus error encountered in worker. This might be caused by insufficient shared memory (shm)

出现这个错误的情况是,在服务器上的docker中运行训练代码时,batch size设置得过大,shared memory不够(因为docker限制了shm).解决方法是,将Dataloader的num_workers设置为0.

6. pytorch中loss函数的参数设置

以CrossEntropyLoss为例:

CrossEntropyLoss(self, weight=None, size_average=None, ignore_index=-100, reduce=None, reduction='elementwise_mean')
  • 若 reduce = False,那么 size_average 参数失效,直接返回向量形式的 loss,即batch中每个元素对应的loss.

  • 若 reduce = True,那么 loss 返回的是标量:

    • 如果 size_average = True,返回 loss.mean().

    • 如果 size_average = False,返回 loss.sum().

  • weight : 输入一个1D的权值向量,为各个类别的loss加权,如下公式所示:

  • ignore_index : 选择要忽视的目标值,使其对输入梯度不作贡献。如果 size_average = True,那么只计算不被忽视的目标的loss的均值。

  • reduction : 可选的参数有:‘none’ | ‘elementwise_mean’ | ‘sum’, 正如参数的字面意思,不解释。

7. pytorch的可重复性问题

参考这篇博文:

https://blog.csdn.net/hyk_1996/article/details/84307108

8. 多GPU的处理机制

使用多GPU时,应该记住pytorch的处理逻辑是:

1)在各个GPU上初始化模型。

2)前向传播时,把batch分配到各个GPU上进行计算。

3)得到的输出在主GPU上进行汇总,计算loss并反向传播,更新主GPU上的权值。

4)把主GPU上的模型复制到其它GPU上。

9. num_batches_tracked参数

今天读取模型参数时出现了错误

KeyError: 'unexpected key "module.bn1.num_batches_tracked" in state_dict'

经过研究发现,在pytorch 0.4.1及后面的版本里,BatchNorm层新增了num_batches_tracked参数,用来统计训练时的forward过的batch数目,源码如下(pytorch0.4.1):

    if self.training and self.track_running_stats:self.num_batches_tracked += 1if self.momentum is None:  # use cumulative moving averageexponential_average_factor = 1.0 / self.num_batches_tracked.item()else:  # use exponential moving averageexponential_average_factor = self.momentum

大概可以看出,这个参数和训练时的归一化的计算方式有关。

因此,我们可以知道该错误是由于训练和测试所用的pytorch版本(0.4.1版本前后的差异)不一致引起的。具体的解决方案是:如果是模型参数(Orderdict格式,很容易修改)里少了num_batches_tracked变量,就加上去,如果是多了就删掉。偷懒的做法是将load_state_dict的strict参数置为False,如下所示:

load_state_dict(torch.load(weight_path), strict=False)

还看到有人直接修改pytorch 0.4.1的源代码把num_batches_tracked参数删掉的,这就非常不建议了。

10. 训练时损失出现nan的问题

最近在训练模型时出现了损失为nan的情况,发现是个大坑。暂时先记录着。

可能导致梯度出现nan的三个原因:

1.梯度爆炸。也就是说梯度数值超出范围变成nan. 通常可以调小学习率、加BN层或者做梯度裁剪来试试看有没有解决。

2.损失函数或者网络设计。比方说,出现了除0,或者出现一些边界情况导致函数不可导,比方说log(0)、sqrt(0).

3.脏数据。可以事先对输入数据进行判断看看是否存在nan.

补充一下nan数据的判断方法:

注意!像nan或者inf这样的数值不能使用 == 或者 is 来判断!为了安全起见统一使用 math.isnan() 或者 numpy.isnan() 吧。

例如:

import numpy as np# 判断输入数据是否存在nan
if np.any(np.isnan(input.cpu().numpy())):print('Input data has NaN!')# 判断损失是否为nan
if np.isnan(loss.item()):print('Loss value is NaN!')

11. ValueError: Expected more than 1 value per channel when training

当batch里只有一个样本时,再调用batch_norm就会报下面这个错误:

  raise ValueError('Expected more than 1 value per channel when training, got input size {}'.format(size))

没有什么特别好的解决办法,在训练前用 num_of_samples % batch_size 算一下会不会正好剩下一个样本。

12. 优化器的weight_decay项导致的隐蔽bug

我们都知道weight_decay指的是权值衰减,即在原损失的基础上加上一个L2惩罚项,使得模型趋向于选择更小的权重参数,起到正则化的效果。但是我经常会忽略掉这一项的存在,从而引发了意想不到的问题。

这次的坑是这样的,在训练一个ResNet50的时候,网络的高层部分layer4暂时没有用到,因此也并不会有梯度回传,于是我就放心地将ResNet50的所有参数都传递给Optimizer进行更新了,想着layer4应该能保持原来的权重不变才对。但是实际上,尽管layer4没有梯度回传,但是weight_decay的作用仍然存在,它使得layer4权值越来越小,趋向于0。后面需要用到layer4的时候,发现输出异常(接近于0),才注意到这个问题的存在。

虽然这样的情况可能不容易遇到,但是还是要谨慎:暂时不需要更新的权值,一定不要传递给Optimizer,避免不必要的麻烦。

推荐阅读:
Python基础专题????
1、Python中的线程和进程2、Python多线程实战3、Python中数据深拷贝、浅拷贝4、Python中的作用域5、Python中的内存管理机制Python爬虫和数据分析专题????
1、Python爬取某站上海租房图片2、Python爬取拉勾网数据并进行数据可视化3、Python爬虫小白入门-爬取披头士乐队历年专辑封面-网易云音乐4、Python动手分析天猫内衣售卖数据,得到你想知道的信息5、Python抓取猫眼近10万条评论并分析电影《一出好戏》到底如何?6、Python爬虫实战:利用scrapy,短短50行代码下载整站短视频7、Python 通过采集两万条数据,对《无名之辈》影评分析8、想不想知道充气娃娃到底什么感觉?来!我用Python告诉你9、Python爬虫:动态爬取QQ说说并生成词云,分析朋友状况
10、Python + PyQt5 实现美剧爬虫可视工具
11、Python爬取批量获取高清壁纸12、有趣的一个Python爬虫实例(爬取段子,笑话,情感句子)13、Python爬虫获取电子书资源实战14、面试官问我会用Python爬虫腾讯视频么?我是这样回复的...15、18个Python爬虫实战案例(已开源)16、Python爬虫44万条数据:如何成为网易云音乐评论区的网红段子手?17、深夜,我用Python爬取了整个斗图网站,不服来斗18、再推荐23个Python爬虫开源项目代码:微信、淘宝、豆瓣19、我用Python爬了点你们需要的电影,这些电影真的很不错~20、Python爬取抖音高颜值小姐姐视频Python综合专题????
1、使用 Python 进行微信好友分析2、Python面试题37道(附答案)看完面试不愁了3、Python 利用opencv去除图片水印4、被女朋友三番两次拉黑后,我用 Python 写了个“舔狗”必备神器5、昨晚家里停网后,我动了邪念用Python破解了隔壁小姐姐的wifi密码6、东半球最强Python新手100天学习计划开源,这次再学不会算我输!7、向Excel说再见,神级编辑器统一表格与Python8、牛逼,竟然可以用 Python 操作 Word 文档,这么多的骚操作!
更多爬虫,关注“Python技术之巅”公号,后台回复:“爬虫实战”,获取独家整理的一份爬虫汇总。长按二维码识别关注分享Python&AI干货,点亮 在看

谈谈我在PyTorch踩过的12坑相关推荐

  1. PyTorch踩过的12坑 | CSDN博文精选

    作者 | hyk_1996 来源 | CSDN博客 1. nn.Module.cuda() 和 Tensor.cuda() 的作用效果差异 无论是对于模型还是数据,cuda()函数都能实现从CPU到G ...

  2. pytorch统计矩阵非0的个数_PyTorch常见的12坑

    原标题:PyTorch常见的12坑 1. nn.Module.cuda 和 Tensor.cuda 的作用效果差异 无论是对于模型还是数据,cuda函数都能实现从CPU到GPU的内存迁移,但是他们的作 ...

  3. Pytorch踩坑记录:关于用net.eval()和with no grad装饰器计算结果不一样的问题

    Pytorch踩坑记录 相同点 net.eval()和with toch.no_grad()的相同点:都停止反向传播 不同点: 1.net.eval() 用net.eval(),此时BN层会用训练时的 ...

  4. 安装python爬虫scrapy踩过的那些坑和编程外的思考

    '转载地址:http://www.cnblogs.com/rwxwsblog/p/4557123.html' 这些天应朋友的要求抓取某个论坛帖子的信息,网上搜索了一下开源的爬虫资料,看了许多对于开源爬 ...

  5. charles都踩过哪些坑_开水果店的你,踩过了哪些坑?

    我们认为,开水果店遇到的大小问题,很多时候是有共性的.不论是开店新手还是老手,看看这里的案例,是否可以避免走一些弯路呢? 案例1 刘大飞第1次创业开水果踩过的那些坑.创业开水果店之前,刘大飞和合伙人一 ...

  6. (转)Redis上踩过的一些坑-美团

    上上周和同事(龙哥)参加了360组织的互联网技术训练营第三期,美团网的DBA负责人侯军伟给大家介绍了美团网在redis上踩得一些坑,讲的都是干货和坑. 分为5个部分: 一.周期性出现connect t ...

  7. Redis上踩过的一些坑-美团

    上上周和同事(龙哥)参加了360组织的互联网技术训练营第三期,美团网的DBA负责人侯军伟给大家介绍了美团网在redis上踩得一些坑,讲的都是干货和坑. 分为5个部分: 一.周期性出现connect t ...

  8. 那些年我们踩过的Hive坑

    原文地址:https://blog.csdn.net/sunnyyoona/article/details/51648871 1. 缺少MySQL驱动包 1.1 问题描述 Caused by: org ...

  9. [Hive]那些年我们踩过的Hive坑

    1. 缺少MySQL驱动包 1.1 问题描述 Caused by: org.datanucleus.store.rdbms.connectionpool.DatastoreDriverNotFound ...

最新文章

  1. leveldb源码分析:数据查询
  2. SAP MM Movement Type 503的使用
  3. python github登陆_用Python模拟登陆GitHub并获取信息
  4. LeetCode-链表-19. 删除链表的倒数第 N 个结点
  5. QAQorz的训练记录
  6. tcp为什么要三次握手,而不能二次握手?
  7. Nginx monitor
  8. python 字符串 变量_Python检查变量是字符串
  9. JavaEE Tutorials (9) - 运行持久化示例
  10. Atitit node.js的缺点 优缺点 和php比较 1. 门槛比较 php简单,node麻烦 1 1.1. php的优势是语法简单易学,学习曲线平滑度可能居所有语言之首 2 1.2. 当用N
  11. rk3568 android 11 更换系统签名
  12. Ubuntu修改hosts文件
  13. 数据库查询优化-添加索引
  14. AD快捷键的设置及推荐
  15. MySQL按日期依次统计
  16. 程序员的幽默你不懂:那些让你爆笑的程序员段子
  17. Longest Common Subsequence
  18. Dubbo面试题总结
  19. 基于JSP技术和SSM框架的Web聊天系统的设计和开发
  20. 前端学习---JS高级教程

热门文章

  1. 一个在线显示doc文本的实例
  2. 行车安全的基础是技术和经验
  3. Direct2D 图形计算
  4. R语言使用cph函数和rcs函数构建限制性立方样条cox回归模型、使用rms包的Predict函数计算指定连续变量在不同分组变量下和风险比HR值的关系、使用ggplot2可视化变量与风险值HR的关系
  5. typora导出word指定样式_Word长文档排版以写论文为例
  6. Java实现 计算数的平方根
  7. Linux Ubuntu常用软件
  8. RK系列(RK3568) 收音机tef6686芯片驱动,i2c驱动
  9. 【HighChart教程】编程语言详细程度的互动比较
  10. Marvin java图像处理