5月的最后一天,需要写点什么。
通过前几篇博客对Faster-RCNN算是有了一个比较全面的认识,接下来的半个月断断续续写了一些代码,基本上复现了论文。利用torchvision的VGG16预训练权重,在VOC02007trainval训练13个epoch,最后VOC2007test的map在0.69左右。当然利用caffe预训练的权重结果略好一些。
关于复现过程:起初只是对目标检测方向突然有了兴趣,想玩一玩,但是只跑跑代码看看结果带给人的新奇感仅仅持续了几分钟,所以找了份代码深究了一下,最后结合chainer的实现方案自己成功复现。
关于代码部分:需要加速的部分主要有RoI-Pooling和NMS。也简单看了看Cython,实现了C扩展。可是为了进一步加速需要cuda,这方面没有深究,所以代码可以利用自己实现的C扩展版本,也可以利用别人写好的cuda加速的版本,在调试代码的过程中,为了方便,直接利用法二。剩余其他部分都是自己完成。
关于心态方面:心血来潮想要实现Faster,可是直到实现的时候才发现有些细节根本难以顾及,断断续续写了一些子函数模块后,感觉想要放弃..可想了想以后万一需要再次接触Faster岂不又得重头看起,所以又是断断续续硬着头皮撸。代码大约不到一周写完了,痛苦的事情才刚刚开始,那就是调试。先是一些低级错误,比如类型匹配问题、路径问题等等。然后是逻辑错误,这是最难调试的,初步调试方法是眼瞅,强行瞅出一些基本的逻辑问题,然后是ipdb一行一行的过...前几天每次都能找出一些错误更正后将代码跑通然后回去睡觉,第二天满怀希望来了却发现损失不降,要不就是map太低...每晚都是带着希望回去,第二天发现还是不行... 列几个那几天陆续找出来的隐藏错误:
- PIL读进来的图像,size函数的顺序是(w,h)。而代码默认需要的顺序是(c, h, w)。
- IOU计算错误。这个是自己的算法错误...
- 损失函数计算错误,(n,c,h,w)应该先转换成(n,h,w,c)再reshape为(n,h×w,c)。
- chainer中的roi_pooling函数需要的roi坐标为(xmin, ymin,xmax,ymax),而代码里默认的顺序为(ymin, xmin, ymax, xmax)...
- RPN网络的两个卷积函数没加激活函数...
最初的目标是5月底之前实现Faster,当解决了所有bug之后,map终于正常了,也实现了既定的目标。故作文以记之...突然发现带给我的新奇感又没有了...
来张自己跑出来的测试图吧,纪念平平淡淡的五月,马上就迎来儿童节了...
然后明天就是总决赛了,詹姆斯撑住,撑住...骑士靠你了...头像是科比只是为了好玩...
知乎的两张图..
另外偶然发现了一个很棒的repo,实现了vgg和resnet两种结构,还有几种不同的roi pooling,以及多batch、多GPU,值得多多研究。
注:resnet直接用效果不升反降(当输入的图像尺寸比较小的时候,直接把vgg换成resnet效果反而会下降,但是如果提高输入图像的尺度的话,把vgg替换成resnet-101效果会更好,对于resnet这样非常深的网络,需要更大的尺度输入来让深层的feature map仍然保持空间信息),所以实现细节值得从代码里好好研究下,另外kaiming有一篇论文(Object Detection Networks on Convolutional Feature Maps)试验了rcnn系列目标检测中深层分类与深层特征的设计,以及对Network on Conv feature map (NoC)设计的方法。涉及对不同网络的设计方法,非常值得参考。