使⽤faster-rcnn.pytorch 训练⾃⼰数据集(完整版)
引⾔
最近在实验室复现faster-rcnn代码,基于此项⽬/(⽬前GitHub上star最多的faster-rcnn实现),成功测试源码数据集后,想使⽤⾃⼰的数据集爽⼀下。
本⽂主要介绍如何跑通源代码并“傻⽠式”训练⾃⼰的数据集~之前的此类博客都是介绍如何在原作者的caffe源码下进⾏数据集训练,那么本⽂针对⽬前形势⼀⽚⼤好的pytorh版faster-rcnn源码进⾏训练新的数据集,废话不多说,Lets go!
faster-rcnn pytorch 代码下载
pytorch0.4.0版源码:
pytorch1.0.0版源码:
具体配置此代码作者已在ReadMe介绍的很清楚,当然会有⼀些坑。
我复现代码的环境是python3.6+cuda10.1+Ubuntu16.04+Pytorch1.2。
配置环境及训练过程:
Tips:不要以为拿过代码以后,就可以直接跑demo!除⾮你的/models⾥⾯有训练好的模型。此处说的模型不是指Vgg或Resnet在分类数据集ImageNet 下训好的Transfer模型,⽽是指的是在⽬标检测集VOC或COCO下进⾏fine-tune的模型。对于VOC2007数据集,训练好后该模型⼤概1个G,所以代码作者没有上传到github,要不你就⾃⼰训练,要不你就跟训好的⼈要,不过建议你⾃⼰训练,跑trainval_net.py。
尝试测试pytorch0.4.0版本(0.4.0版本尝试失败,想快速跑通可直接跳到pytorch1.0.0版本训练过程),据ReadMe配置环境后,执⾏训练数据集命令⾏:
训练命令⾏⽰例:
“CUDA_VISIBLE_DEVICES”指代了gpu 的id ,这得看你实验室服务器哪块gpu 是闲置的。
“–dataset”指代你跑得数据集名称,我们就以pascal-voc 为例。
“–net”指代你的backbone ⽹络是啥,我们以vgg16为例。
"–bs"指的batch size 。
“–nw”指的是worker number,取决于你的Gpu 能⼒,我⽤的是Titan Xp 12G ,所以选择4。稍微差⼀些的gpu 可以选⼩⼀点的值。
“–cuda”指的是使⽤gpu 。
训好的model会存到models⽂件夹底下,此处暂时使⽤默认的训练参数。
训练阶段在roibatchLoader.py出现报错:解决⽅案在GitHub上有所讨论,但限于版本更新和pytorch放
弃对之前版本部分语法的⽀持,此问题是短时间内难以解决的死胡同,遂放弃0.4.0版本转⼊1.0.0版本据pytorch1.0.0分⽀ReadMe配置好pytorch环境后,运⾏训练时出现coco数据集导⼊问题
在中的建议下重新编译cocoAPI接⼝解决问题
训练命令⾏⽰例:
若是在服务器上长久运⾏,断掉连接关掉xshell后继续运⾏,可是使⽤nohup语句。实测在⼀块TITAN X上运⾏⼀个epoch需要40min,20epoch⼤概需要训练⼀天。 Notice:bs切记不要太⼤,本例中bs=16会爆12G的显存,如果出现如下报错,调⼩bs即可
CUDA_VISIBLE_DEVICES=0,1 python trainval_net.py --dataset pascal_voc --net res101 --cuda
AttributeError:'int' object has no attribute 'astype'
CUDA_VISIBLE_DEVICES=0,1 python trainval_net.py --dataset pascal_voc --net res101 --cuda
nohup python trainval_net.py --dataset pascal_voc --net res101 --epochs 10 --bs 4 --lr 0.01 --lr_decay_step 8 --cuda &
RuntimeError: CUDA out of memory. Tried to allocate 30.00 MiB (GPU 0; 11.93 GiB total capacity; 11.17 GiB already allocated; 5.81 MiB free;222.17 MiB cached)
nohub语句使⽤详情请见我的另⼀篇博客:
开始训练:python怎么读取文件中的数据
测试命令⾏⽰例:
注意,这⾥的三个check参数,是定义了训好的检测模型名称,我训好的名称为faster_rcnn_1_3_10021,代表了checksession = 1,checkepoch = 3, checkpoint =
10021,这样才可以读到模型“faster_rcnn_1_3_10021”。训练中,我设置的epoch为20,但训练到第3批就停了,所以checkepoch选择3,也就是选择最后那轮训好的模型,
理论上应该是效果最好的。当然着也得看loss。
测试集5000张图像,⼀块TITANX平均测试时间0.1s/张,占⽤显存5G左右。
在VOC上20个class的mAP为69%,实际训练12epoch能到75%左右,(我训练3epoch就结束了loss还未收敛到较低程度)
demo命令⾏⽰例:
此处我们需输⼊使⽤的⽹络(vgg16),以及训练好的模型路径(models)。我们测试的图⽚都在images⽂件夹⾥。在此处有坑。作者提供了4张image做测试,因为测试完的图像会输出到images⽂件夹⾥,所以做完⼀次测试,images⽂件夹会有8张图⽚(输出图⽚命名规则是在原图像⽂件名后⾯加上"_det"),⽽原作者没有把他⾃⼰测试后的图⽚删去,所以⼤家在做demo测试时,别忘把以"_det"结尾的检测输出⽂件先删去,否则测试完你的images⽂件夹可能会得到16张图像。。
当然,你可以放⼀些你⾃⼰在⽹上搜的图⽚在images⽂件夹⾥进⾏demo测试,看看效果。但检测类别⼀定在训练的类别中要有啊~
VOC2007数据集的类别在路径"/faster-rcnn.pytorch/lib/datasets/pascal_voc.py"⽂件中已注明,在此提醒:
python test_net.py --dataset pascal_voc --net res101 --checksession 1 --checkepoch 3 --checkpoint 10021  --cuda
python demo.py --net vgg16  --checksession 1  --checkepoch 20 --checkpoint 10021 --cuda --load_dir models
/
/个例实验
self._classes = ('__background__',  # always index 0
'aeroplane', 'bicycle', 'bird', 'boat',
'bottle', 'bus', 'car', 'cat', 'chair',
'cow', 'diningtable', 'dog', 'horse',
'motorbike', 'person', 'pottedplant',
'sheep', 'sofa', 'train', 'tvmonitor','plane')
放出⼀个识别⽹上的图⽚还不错的例⼦:
在测试的时候,如果没有gpu,则在命令⾏中不输⼊"–cuda"。但使⽤python3.5的朋友可能会遇到以下错误:
解决⽅法如下:
github/python/cpython/commit/9cd7e17640a49635d1c1f8c2989578a8fc2c1de6#diff-a2f8f044364f136b5879679b60c19172
修改weakref.py后可完美解决。
训练⾃⼰数据集
当你⾛到这⼀步,恭喜,你马上就可以为所欲为了。在此只介绍适合于新⼿(我就是)的傻⽠式数据集制作⽅法。
我们以⼀个只检测⼀类的数据集为例,我这⾥是⾃⼰标注的飞机测试集,类别名称为“plane”。
我们仍然采⽤VOC2007数据集的类。⽪不变,只是把我们⾃⼰的数据集“塞进去”
真正“起作⽤”的训练集其实是这四个⽂件夹,位置是
1.Annotations为标注⽂件夹,若⼲.xml⽂件。每⼀个图⽚都对应⼀个.xml⽂件,其中存储的是该图⽚的名称,长宽,⽬标框(GroundTrues)的左上右下坐标,⽬标框的类别名称。
2.ImagesSet⽂件夹下的Main⾥,保存了需要训练图⽚的名称,以txt⽂本存储。
3.JPEGImage⽂件夹保存了原图⽚。
所以看到这,你就明⽩,怎么把我们的数据集塞进去了。
⾸先把我们的原图塞进JPEGImage⽂件夹⾥。当然原⽂件夹的图⽚我们需要备份,并从JPEGImage⾥移除。
然后,需要制作我们⾃⼰数据集的xml标注⽂件,朋友们如果想问做出的xml⽂件标准是啥样的,因为不同的标注软件⽣成的标注⽂件五花⼋门,和VOC⼀样的xml⽂件怎么制作?在此给个传送门,⼤家耐⼼学习:
在此也给出如何更改xml⽂件中属性值的⽅法,链接如下:
⽤这个代码可以任意改变xml⾥的属性值,⽐如你想把xml⽂件中类别名称改变,或把图⽚名称、路径等值改变,参考上述代码链接。
1 //weakref.py 出错
2  Exception ignored in : <function WeakValueDictionary.__init__.<locals>.remove at 0x7f294b5c0730>
3    Traceback (most recent call last):
4      File "/anaconda2/envs/py35/lib/python3.5/weakref.py", line 117, in  remove
5    TypeError: 'NoneType' object is  not  callable
---VOC2007
------Annotations
------ImagesSet
---------Main
------JPEGImages
faster-rcnn.pytorch/data/VOCdevkit/VOC2007/
在此放出我⾃⼰的数据集标注xml⽂件:
图中画圈的属性,需修改与VOC⼀样,folder应修改为"VOC2007",类别的name属性,也可修改为你想识别的类别,在此我将所有⽬标的name都改为"plane",修改代码见上述的github代码。
在所有xml⽂件修改后,将它们放⼊Annotations⽂件夹中。
最后,⾃⼰制作,⾥⾯存储⾃⼰的待训练图⽚名称,记住不要带.jpg后缀,这个很简单如下图所⽰:
制作好后将该⽂件放⼊ImagesSet\Main中
弹药已装好,下⾯需要为炮台调准⽅向!修改python⽂件。Ok我承认需要更改的⼏个坑真的坑了我⼀个晚上。。
第⼀处:
这个⽂件⾥存着VOC数据库的class,需要更改我们识别的类别,我的做法是把原class注释掉,把⾃⼰的class加进去,如图,加⼊’plane’类,看到这你也许就知道啦,这⾥的类名和前⾯xml⽂件中,⽬标的name属性应该是⼀样的。
第⼆处:发⽣如下错误:
faster-rcnn.pytorch/lib/datasets/pascal_voc.py
基本上都会碰上,只要是你标注的框靠近边缘,都会出这个错误,不⽤急,按照下⾯⽅法改,完美解决:
blog.csdn/xzzppp/article/details/52036794
第三处:发⽣如下错误:
OK,别着急,⼀帆风顺是不可能的,该句指的是得到的图像数据库imdb⽂件没有‘width’,也就是没有读到图像的宽度值,⽽这个宽度值是通过图⽚读出来的,所以说明你的训练⽂件夹JPEGImage中没有ImagesSet\⾥列出的图⽚,我查了下,图⽚都放进去了,那为啥还出错呢?
原因是!在训练原数据集VOC时,图像数量是10021张(进⾏了数据增强),这时会保存训练信息⾄缓存中,⽂件路径为:
因此你在重新训练新数据集的时候,会读取这个缓存配置,以加快训练,那么此时就⼊坑了,我的新集合只有1000张,所以训练时读的缓存⾥,需要读的图像还是原来那10021张,那势必会不到这10021张图像,所以要做的就是,把这个缓存⽂件voc_2007_trainval_gt_roidb.pkl删掉!
改完此处,可以完美进⾏训练,当然训练命令⾏不⽤变,怎么样,够傻⽠吧~
第五处:
训完后,很想demo⼀下,看看训出来的模型如何,如果你觉得能顺利进⾏的话,那就图样图森破了,你会陷⼊第五个坑:
我们会发现,他说我们训的模型,预测层是两个节点(代表2类,飞机+背景),⽽测试的时候,发现模型是21类(原数据集的类数,20类+背景)。开始以为是训练前⽹络的输出类别数没有设置好,于是加各种断点原因,但发现训练时的⽹络预测的类数就是2类。
于是机智的我⼜好好想了⼀下,那⼀定是测试的时候出错了,,⽽且上图错误信息也已经说了,是demo.py出问题了,于是,修改⽅法就有了,需修改demo.py⽂件:assert (boxes[:,2]>=boxes[:,0]).all()
Keyerror:'width'
/home/zhangxin/faster-rcnn.pytorch/data/cache/voc_2007_trainval_gt_roidb.pkl
faster-rcnn.pytorch/demo.py //此处普及下设置断点代码
import  pdb;pdb.set_trace()

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。