YOLO v2

这篇文章主要想记录一下YOLO算法的工作流程,文章主要基于YOLO v2来写的。

Introduction

不同于两阶段的检测算法(RCNN系列),YOLO是一种一阶段的检测算法。它将检测问题视为一个回归问题:使用一个网络直接预测bounding box的位置和类别概率。作为一种一阶段的检测网络,它的速度也非常的快,达到了45fps。但是相比于faster rcnn,YOLO v1由于直接预测bounding box的位置,所以它在物体位置的定位上有更大的误差,因此在v2中作者对这一问题提出了改进的方法。

Method

Grid cell

首先,不同于RCNN系列使用selective search或者region proposal networks在原图上生成一系列可能包含物体的regions然后再做检测的方法,YOLO的做法是先将原图分成S x S个grid cell。然后对每grid cell预测$B$个bounding boxes。需要注意的是,在YOLO v1中,每个grid cell只会预测一个类,因此预测的输出为一个SxSx(B*5+C)维的向量,其中5是因为预测4个坐标向量+1个是否是object的概率。具体来说,YOLO v1的设置为S=7,B=2,这样在VOC的数据集上,YOLO的输出就是7x7x30。而在v2中,针对小目标检测比较差的情况,借鉴了rcnn的做法加入了anchor boxes。具体来说,就是把v1中最后的全连接层移除,用一个1x1的卷积层取而代之。卷积层的输出channels就是我们希望预测的类别数。同时不同于v1每个cell预测一个类别,v2中对每个bounding box预测一个类别。这样最终的输出就变成了SxSxB(5+c),其中S=13,B=5,C为dataset的类别数。通过预测更多的bounding box和引入anchor的思想,将recall提升了7%。

接着让我们详细的来看一下需要预测的4个坐标还有object的概率是怎么定义的。对于4个位置的坐标,$x,y$为box的中心相对于对应的grid cell左上角的偏移,$w,h$是bounding box的相对于先验anchor宽高的偏移。对于是否为object的概率,定义为$Pr(Object)*IOU_{pred}^{truth}$来定义。因此,预测值和真实值就有以下的映射关系:

其中$t_x,t_y,t_w,t_h,t_o$就是我们希望网络学习的5个关于bounding box的值,当该bounding box内含有物体时,则还应学习物体的类别概率。

此外,不同于faster rcnn中anchor boxes的长宽都是通过手工设置,比如1:1,2:1,1:2,yolo v2的anchor box的长宽是通过kmeans进行聚类生成的。比如在v2中,每个cell有5个bounding boxes,就把dataset中所有的gt boxes的长宽进行聚类,生成5个聚类中心,用这5个中心的长宽作为我们预设的anchor boxes的长宽。

Fine-grained features

为了提高小物体的检出率,借鉴特征融合的思想,将前面低层的特征和最后的高层特征进行融合。以v2这篇论文提出的darknet-19为例,原本是直接在最后的13x13的特征图上预测,但是考虑到在这个分辨率下可能会丢失部分小目标,因此将前面的26x26的特征图通过一个passthrough layer与13x13的特征图融合。考虑到这两层的特征分辨率不同,没法直接进行融合,因此yolo的做法是先将低层的26x26x512的特征拆分成13x13x2048,然后再将其和高层的13x13x1024特征图直接在channel维度进行拼接融合。一个简单的示意图如下,假设输入的特征图为4x4x1,stride=2,那么变换后的特征图就是2x2x4。

Others

为了提高mAP,文中还介绍了一些其他的tricks,比如在层与层之间加入batch norm进行正则化,加入多尺度训练,在较高的分辨率下进行预测等,作者画了张表格来说明这些改进所带来的提升,具体可以参阅原文:

How to implement?

以下会以伪代码的形式介绍一下作者在代码层面如何实现训练和预测的流程的,参考了作者的darknet版的实现,前面的backbone就是正常的卷积操作,主要的改进是在最后的loss函数计算上,这一部分代码主要在region_layer中。

  1. 当输入的图片size为416x416时,对于全卷积网络而言,其最后一层的输出为13x13x(5x(5+c)),其中C为dataset的类别数,对于voc而言就是20
  2. 将输出的tensor进行拆分,得到x,y,w,h,obj_conf,class_conf这几个子tensor,除了最后一个子tensor的维度为13x13x(5xC),其他几个子tensor的维度都是13x13x5
  3. 接下去首先看一下yolo的total loss是什么样的,看上去很长的一串,但是仔细拆分的话其实可以看作是三部分损失的加权和。首先我们来看看$\mathbb{1}_{ij}^{obj}$, $\mathbb{1}_{ij}^{noobj}$和$\mathbb{1}_{i}^{obj}$这三个指示符分别代表什么。首先第一个是指当某个gt box落在第i个grid cell中的第j个bounding boxes中时为1,第二个是指第i个grid cell内没有gt box时为1,第三个是指gt box位于第i个grid cell时为1。那么,什么叫第i个grid cell的第j个bounding box内有物体呢?假设有一张大小为416x416的图片,有一个gt box,它的中心点为(100,200),宽为50,高为100,那么这个中心点就位于第(ceil(100416*13),ceil(200416*13))=(4,7)个cell。但是这个cell中有若干个bounding boxes,文中使用了”responsible”这个词来表示对预测物体“负责”的bounding box。它是在这若干个bounding boxes中与gt box的iou最大的那个bounding box。对于$\mathbb{1}_{ij}^{noobj}$,并不是简单地对$\mathbb{1}_{ij}^{obj}$进行取反,因为这样做会导致训练时正负比例的差距太过悬殊,因此会将gt box与第i,j个模型预测的pred box计算iou,如果大于阈值,则不再计算这个box的no object loss。也就是说如果某个box既不用对预测物体“负责”,但是这个位置的预测框与gt box的iou又大于一定值,那么它就会被丢弃,也就是不参与任何一项损失的计算。关于最后那个$\mathbb{1}_{i}^{obj}$,其实它是yolo v1的写法,因为yolo v1对每个cell只预测一组class confidence,而到了v2中会对grid cell中的每个anchor box预测一组class confidence。从v2的代码来看,这个其实和第一个$\mathbb{1}_{ij}^{obj}$的取值应该是一样的。
  4. 计算no object loss,这一部分代码位于

    //计算no object loss
    for j in range(h):
        for i in range(w):
            for n in range(num_anchor):
                获得当前位置对应的pred_box
                for truth_box in gt_boxes: //遍历所有的gt boxes
                    计算truth_box与pred_box的iou,保留最大的best_iou
                如果best_iou大于threshold,忽略,反之则计算这个位置的object confidence的loss
                对于开始训练后的前12800张图片,即使这个位置没有object,也会额外计算一个坐标的loss
                使用一个虚拟的truth,它的x,y为cell的中心,w,h为当前anchor的w和h
                这样做是为了避免在训练的早期阶段网络发散,加快网络的收敛
    
  5. 计算object, coordinate and class loss,这一部分代码位于

    //计算object, coordinate and class loss
    for truth_box in gt_boxes:
        找到truth_box中心坐落在第(i,j)个grid cell中
        //在这个grid cell中
        for n in range(num_anchor):
            获得这个位置的先验anchor框,与truth_box计算iou,保存最大的iou和对应的索引best_n
            利用i,j,best_n就可以计算对应位置的pred_box与gt_box的
            object, coordinate和class loss
    
  6. 还有一点需要说明,在上面给的代码中循环条件都写着t<30,是因为作者假设一张图内最多存在30个gt boxes


References

  1. https://arxiv.org/pdf/1506.02640
  2. https://arxiv.org/pdf/1612.08242
  3. https://pjreddie.com/darknet/yolo/
  4. https://github.com/hgpvision/darknet/blob/master/src/region_layer.c

Related