论文地址:https://arxiv.org/pdf/2005.13243.pdf
tf keras的:
源代码:https://gitlab.com/irafm-ai/poly-yolo
https://github.com/BYLi-AI/poly-yolo
- Keras 2.3.0
- Tensorflow 1.15.0
- Numpy, PIL, OpenCV
- cudatoolkit 10.0
- cuDNN compatible with cudatoolkit 10.0
torch版,19年的:
https://github.com/baristahell/poly-YOLOv3
YOLOv3改进版来了!与YOLOv3相比,Poly-YOLO的训练参数只有其60%,但mAP却提高了40%!并提出更轻量的Poly-YOLO Lite。
目标检测是一个过程,其中包含感兴趣对象的所有重要区域都被限制而忽略背景。通常,目标以一个框为边界,框用其左上角的空间坐标及其宽度和高度表示。这种方法的缺点是对于形状复杂的物体,边界框还包括背景,由于边界框没有紧紧包裹物体,背景会占据很大一部分区域。这种行为会降低应用在边界框上的分类器的性能,或者可能无法满足精确检测的要求。为了避免这个问题,Faster R-CNN或RetinaNet等经典检测器被修改为Mask R-CNN或RetinaMask的版本。这些方法还可以推断实例分割,即边界框中的每个像素都被分类为对象/背景类。这些方法的局限性在于它们的计算速度,它们无法在非高层硬件上达到实时性能。
我们关注的问题是创建一个具有实例分割和中层显卡实时处理能力的精确检测器。
二、前言
Poly-Yolo实例分割案例
目标检测模型可以分为两组,两级和一级检测器。两级检测器将过程拆分如下。在第一阶段,提出感兴趣的区域(RoI),在随后的阶段,在这些候选的区域内进行边界框回归和分类。一级检测器一次预测边界框及其类别。两级检测器在定位和分类精度方面通常更精确,但在处理方面比一级检测器慢。这两种类型都包含用于特征提取的主干网络和用于分类和回归的头部网络。通常,主干是一些SOTA网络,例如ResNet或ResNext,在ImageNet或OpenImages上进行了预训练。尽管如此,一些方法 也从头开始尝试训练。
今天分享的框架提出了性能更好的YOLOv3新版本,并扩展了名为Poly-YOLO。Poly-YOLO建立在YOLOv3的原始思想的基础上,并消除了它的两个弱点:标签重写和anchor分配不平衡。
Poly-YOLO使用stairstep上采样通过hypercolumn技术聚合轻型SE-Darknet-53主干网中的特征来减少问题,并产生高分辨率的单尺度输出。与YOLOv3相比:Poly-YOLO的可训练参数只有60%,但mAP却提高了40%。更少参数和更低输出分辨率的Poly-YOLO Lite,具有与YOLOv3相同的精度,但体积小三倍,速度快两倍,更适用于嵌入式设备。
今天主要就是说怎么解决Yolov3两大问题。
左图说明了输入图像上的 YOLO 网格,黄点表示检测到的对象的中心。右图说明了检测结果。
第一个问题:标签重写
标签重写是指由于yolo特有的网格负责预测bbox的特点,可能会出现两个物体分配给了同一个anchor,导致仅仅有一个物体被保留负责预测,另一个物体被当做背景忽略了。当输入分辨率越小,物体越密集,物体的wh大小非常接近时候,标签重写现象比较严重。如上图所示,红色表示被重写的bbox,可以看出27个物体有10个被重写了。
具体来说,以416 *416大小的图像为例,在图像分辨率随着卷积下降到13 * 13的特征图大小时,这时候特征图一个像素点的对应是32*32大小的图像patch。而YOLOV3在训练时候,如果出现相同两个目标的中心位于同一个cell,且分配给同一个anchor,那么前面一个目标就会被后面目标重写,也就是说两个目标由于中心距离太近以至于在特征图上将采样成为同一个像素点的时候,这时候其中有个目标会被重写而无法进行到训练当中。
这种现象在coco数据上不明显的原因是bbox分布比较均匀,不同大小物体会分配到不同预测层,标签重写概率比较低。但是在很多实际应用中,比如工业界的特定元件检测时候,物体排布非常紧密,且大小几乎一致,此时就可能会出现标签重写问题了,作者论文指出在Cityscapes数据上该现象也比较明显。
第二个问题:Anchor分配不均衡
yolo系列采用kmean算法聚类得到特定要求的9个anchor,并且以每三个为一组,用于大输出图(检测小物体),中等输出图和小输出图层(检测大物体)的默认anchor。可以看出不同大小的物体会被这三组anchor分配到不同预测层进行预测。
但是这种kmean算法得出的结果是有问题的,在实际项目中也发现了。前面说过大部分特定场景的目标检测数据集,并不是和coco自然场景一样,啥尺度都有,实际项目中大部分物体都是差不多大的,或者说仅仅有特定的几种尺度,此时采用kmean这一套流程就会出现:几乎一样大的物体被强制分到不同层去预测,这个训练方式对网络来说非常奇怪,因为物体和物体之间wh可能就差了一点点,居然强制分层预测,这明显不合理。本文作者生成的仿真数据其实也是这个特点。
作者指出,kmean这种设置,仅仅在:M ∼ U(0, r)情况下采用合理的。其中r是输入图片分辨率,例如416。该式子的意思是物体的大小分布是满足边界为0到r的均匀分布,也就是说在416x416图片上,各种大小尺度的bbox都会存在的情况下,kmean做法是合理的。但是可能大部分场景都是:M ∼ N (0.5r, r),即均值为0.5r,标准差为r的物体分布,如果按照默认的kmean算法对anchor的计算策略,那么由于大部分物体都是中等尺寸物体,会出现其余两个分支没有得到很好训练,或者说根本就没有训练,浪费网络。
三、新框架及解决方法
对于标签重写问题,只能通过要么增加输入图片分辨率大小;要么增加输出特征图大小实现。本文的做法是增加输出特征图大小。
原始的yolov3,输入大小是输出特征图的8/16和32倍,通过上述数据可以发现标签重写比例蛮高的。而通过增加输出特征图大小后可以显著降低重写比例。
对于kmean聚类带来的问题,有两种解决办法:
-
kmean聚类流程不变,但是要避免出现小物体被分配到小输出特征图上面训练和大物体被分配到大输出特征图上面训练问题,具体就是首先基于网络输出层感受野,定义三个大概范围尺度,然后设置两道阈值,强行将三个尺度离散化分开;然后对bbox进行单独三次聚类,每次聚类都是在前面指定的范围内选择特定的bbox进行,而不是作用于整个数据集。主要是保证kmean仅仅作用于特定bbox大小访问内即可,就可以避免上面问题了。但是缺点也非常明显,如果物体大小都差不多,那么几乎仅仅有一个输出层有物体分配预测,其余两个尺度在那里空跑,浪费资源。
-
就只有一个输出层,所有物体都是在这个层预测即可。可以避免kmean聚类问题,但是为了防止标签重写,故把输出分辨率调高,此时就完美了。作者实际上采用的是1/4尺度输出,属于高分辨率输出,重写概率很低。
根据上图可以发现:
(1) 网络方面,为了减少参数量,首先减少了通道数目,同时为了提高性能,引入了SE单元来加强特征
(2) 和yolov3的最大区别是输出层是一个,但是也采用了多尺度融合方式
(3) neck部分提出了hypercolumn+stairstep上采样操作
左边是标准的hypercolumn操作,右边是作者提出的。实验表明右边的方式更好,因为loss更低。
通过上述参数设置,作者设计的neck和head较轻,共有37.1M的参数,显著低于YOLOv3的61.5M,Poly-YOLO比YOLOv3的精度更高,在可训练参数减少40%的情况下,mAP精度大概也提高了40%。同时为了进一步提速,作者还设计了lite版本,参数仅仅16.5M,精度和yolov3接近。
四、实验及可视化
左:矩形网格,取自YOLOv3。目标边界框以其中心为中心的单元格预测其边界框坐标。 右图:Poly-YOLO中用于检测多边形顶点的基于圆形扇区的网格。 网格的中心与目标边界框的中心重合。 然后每个圆形扇区负责检测特定顶点的极坐标。 不存在顶点的扇区应产生等于零的置信度。
矩形检测和多边形检测对比