CheXNet最后一关:denseNet_localization.py

denseNet_localization.py的问题

如果说前期数据准备是整个项目开始的最大障碍,那么 denseNet_localization.py 就是终结它之前的终极考验(当然是对我这个菜鸡来说)。说实话,在这个.py文件中遇到太多关键的问题,以至于在我想把它们整理出来的时候一时间找不到头绪。和大哥在106接近两小时的debug,收获真的太多了(99%的工作为大哥完成)。下面我按时间线说一下遇到的主要问题以及解决方案。

1.missing keys、unexpected keys以及size mismatch

最开始我用两GPU训练,得到权重放在denseNet_localization.py中,如下图

在这里插入图片描述

出现问题:
① missing keys:n个网络层丢失+unexpected keys:n个未知网络层
② size mismatch for module.densenet121.classifier.0.weight: copying a param with shape torch.Size([1, 1024]) from checkpoint, the shape in current model is torch.Size([8, 1024]).
size mismatch for module.densenet121.classifier.0.bias: copying a param with shape torch.Size([1]) from checkpoint, the shape in current model is torch.Size([8]).

我首先注意到第一个问题,意识到权重少东西,但没有第一时间深入解决,而是直接在调用权重之后添加“False”将其消除。第二个问题是size不匹配的原因,我想到原始项目训练有8类目标,而我这次训练只选用了一个目标,我把8改为1,问题解决。

注意一下这个句子:model = torch.nn.DataParallel(model),这是一个多GPU训练调用的函数,我个人很反感这个函数,一个是由它引出的问题实在太多,包括上面的missing keys也和它有关,另外就是它多GPU的资源分配并不平均,导致资源的浪费,我们最后消除了这个函数,关于它我之后会详细研究一波,到时候再写一篇博客总结一下。

2.Invalid layer name: module.densenet121.features.denseblock4.denselayer16.conv.2

源码中,有这么一段:

在这里插入图片描述

GradCAM函数的功能大致可以概括为:选取一个层,以实现目标的localization可视化。分析densenet121网络结构,发现 densenet121.features.denseblock4.denselayer16.conv2 是很深入的层,所以作者选取它作为localization的层是很合理的,但 layer name 为什么会无效呢?这个问题在GitHub的issue里有提到,见此链接:GitHub issue#2但我按照那个老兄的方法修改,无济于事,到底是什么原因?

这里先按下不表,看第三个问题。

3. if id(module[1]) == key: if module[0] == target_layer:

在这里插入图片描述

这段代码折磨我们很久,个人认为也是整个.py文件最精髓的一段。也就是说,只有当两个条件都满足的时候,才能返回value值。通过debug发现,key的值是不变量,但众多的id(module[1])没有一个和key匹配的,就很离谱。但module[0]中发现了module.densenet121.features.denseblock4.denselayer16.conv2这个层的名称。经过一番苦苦查找和debug,我们突然发现在 Invalid layer name 前还有一个我们一直忽略的问题:

THCudaCheck FAIL file=/pytorch/aten/src/THC/THCGeneral.cpp line=405 error=11:invalid argume

经过查询,得知这个问题由于cuda版本和本机环境冲突导致。查找项目的cuda版本为8.0,而我们的系统cuda版本为10.1,好像看到了曙光。修改cuda版本,问题解决,但 Invalid layer name 这个问题仍然挥之不去,这时大哥说,有没有可能是多GPU训练的问题,导致权重分配不均,丢失值,而且版本也会影响网络层的命名。如果真是这个问题,那么 missing keys 和 Invalid layer name 都可以解决了。

我重新调用一个GPU训练数据,将权重放入 denseNet_localization.py 中,没有False,没有出现 missing keys,看来我们的想法是正确的。

debug key的值,发现这一次和 id.module[0]一一匹配,但 Invalid layer name 还是存在,再次debug,这次发现那个网络层的名字变成了 densenet121.features.denseblock4.denselayer16.conv2 ,修改后,成功生成 bbox.txt文件!修改cuda版本后,网络层名字也会改变。

后记

通过这次的经历,总结如下几点:

关键点:训练层名字(细心)
单GPU和多GPU问题(最好按照项目的做法来选取)
维度问题(类别数决定)
版本:cuda8.0—cuda10.1
Pytorch1.1.0—1.4.0
不同版本导致densenet网络层的名字不同

感谢大哥周末抽出时间帮我看代码、改代码,自己要学的东西太多了。目前项目算是告一段落,希望再接再厉!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值