pytorch从零实现FasterRCNN检测器及优化:一

本文介绍 pytorch从零实现FasterRCNN检测器及优化:一

pytorch从零实现FasterRCNN检测器及优化:一

This article was original written by Jin Tian, welcome re-post, first come with https://jinfagang.github.io . but please keep this copyright info, thanks, any question could be asked via wechat: jintianiloveu

准备花4个文章的长度来传授大家如何从0实现一个FasterRCNN检测器,为目标检测从业者、人工智能入门者、科研工作者、研究生等提供一个提纲惬领、抛砖引玉的作用。 虽然现在网络有很多实现,但是大家需要思考一些问题:他们是最优的吗?你真的理解他们的操作吗?你知道如何优化吗?如果不解决这些问题,你等于没有学会,本文从这个角度出发,教授大家如何学习,其实我可以这么说,看完这篇文章,深度学习你入门了80%.

看完全文再回过头来看的部分

这部分大家可以忽略,等你看完之后再来看这里。这部分我想讲一些细节,以问题的方式给出,如果你看完全文之后,再回国头来看这些问题还不知道怎么回事,那你就再看一遍。问题的提出是根据一些细节来展开的。

  1. ROI Pooling这个层是做什么的?

    fastercnn有一个很重要的操作,就是在RPN之后,有一个roi pooling的过程,这个是干嘛的?它的输入输出是什么?为什么要有这个步骤?首先,RPN的输出是什么?一系列的框,这些框实际上已经是特征图上的坐标了(location 坐标),这些东西可以用来作为目标的输出,但是它只有前景概率和背景概率,你还无法告诉你这个目标框的类别到底是啥。此时你需要将RPN的输出输入到classifier head做分类,输入到regression head做位置的微调,但是你RPN输出的是bbox,这最多就是 5维度的矩阵(坐标加前背景概率),无法和分类head和位置回归head链接的。此时就需要一个层,从RPN位置得到特征图,ok,特征图简单,直接根据坐标在特征图里面crop出来。但是你会发现,crop出来的尺寸是不同的,比如有的box大,有的box小,此时你无法(再次)输入到分类head和回归head中,咋办? 借用SPPNet的思想,不管你多大的尺寸,我都分割成固定的size,比如7x7, 然后再把结果全部变成7x7的大小 (再每个7x7的小放歌里面再取平均值或者最大值), 从而组成ROI Pooling,此时,这个操作就类似与pooling,只不过呢,pooling一般是对单张图片做,而ROI Pooling是对所有的ROI进行操作,并且将结果固定在一个输出。其实呢,这个ROI Pooling并没有太多的降低精度,因为实际上输入到ROI的尺寸就比较小,比如你输入图片224,那么输入ROI的尺寸是除以16,也就是14,将当于减少了一半而已。

    **但是ROI Pooling真正的问题是什么呢?

  2. ROI Pooling的局限

    上述操作是FasterRCNN的标准做法,他其实有损定位精度,为什么呢?因为你ROIPooling处理的都是像素点,像素点没有小数,你不可能20.1个像素吧,但是原始的框到达RPN出来之后,它的尺寸是有小数的(尽管此时体现不出来),而ROI会直接当成整数,而ROI的输出再次是整数,小数会被忽略,这样,原始的box,可能因为这两个操作,导致最终的box存在20个像素点的误差,那这个误差是很大的。

    所以在MaskRCNN这篇里面,作者就提出了ROIAlign的改进层, 我们后面会尝试优化ROI Pooling。

  3. RPN的Proposals到底是怎么生成的

    这个问题真没有办法回答,你必须要动手去写一遍,写什么呢?如何生成anchor,其实很多人讲proposal是生成的,这样不好理解,实际上proposal是人工写的,然后让网络去判断而已,这个部分很多细节,比如anchor的每一个尺度的长宽,长宽比大家都是知道不同的ratio,但是他们的长宽到底是怎么计算的?以及为什么采用根号的方式去乘以一个比例,很多人不知道这一点。而且这个操作,训练和预测你必须要分两种情况去做,比如训练的时候你可以生成更多的proposal,而测试的时候你没有必要生成那么多,简单的几个就行。知道了这些你就知道如何加速fasterrcnn算法了。包括他的简单升级版本,retinanet,rfcn等等。

  4. 为什么总有人说fastercnn慢?

    很多人说二阶段慢,但是我可以告诉大家,fasterrcnn加速到极限可以在gpu上跑到30-40fps,怎么做得到?首先你的nms可以加速,你的roi层可以加速,你的训练的时候测试的时候proposal可以调节,你甚至可以开多线程在nms阶段去计算加速,当然这是从工程优化角度,从理论角度,你可以用mobilenetv2, 用shufflenetv3 这种轻辆及别的网络去加速,但是不管怎么样,我个人觉得二阶段网络在很多场合是比一阶段好很多的。牢记一点不要从github随便找个代码跑一下就说fastercnn慢, 即便论文给你的速度就很慢,你也有办法把他加速到极致。最后如果你做到了这一点,恭喜你,目标检测领域你已经成了master。

1. 工程架构

最后,我们不得不,万事开头难,先开始整理一下工程架构,我们需要哪些东西?首先你需要一个anchor生成器,这个玩意基本上是最基础的设备了,至于anchor怎么生成,其实也很简单。根据一系列的scale,ratio,给定一个基本的size,生成相对应的anchors。然后你还需要一个AnchorTargetGenerator, 这个玩意是做啥的呢。其实也很简单,就是将groud truth的bbox,专程anchor。这样你才能和RPN输出的anchor来做反响传播。

说这么多其实你并没有听懂。