目标检测算法 2020_【目标检测】One-stage目标检测算法

原文 | One-stage object detection

中文 | 小小将:深入理解one-stage目标检测算法

今天看了上面这篇专栏文章,收获颇丰,整理一下要点。

【目录】

  • 1. One-stage目标检测算法流程
    • 为什么要对检测器实施约束?
  • 2. anchor是什么?有什么作用?
  • 3. 选择先验框的策略
    • 3.1 yolo选择先验框的策略
    • 3.2 SSD选择先验框的策略
  • 4. 怎样由最后的feature map转换成bbox的?
    • 四个坐标值
    • 20个类别概率
    • 一个置信度
  • 5. 网络是怎样学习的?
    • 5.1 卷积预测
    • 5.2 损失函数的设计
    • 5.3 使用优化器来训练
    • 5.4 训练策略&技巧

1. One-stage目标检测算法流程

输入: VOC数据集的一张图片(20个类别),输入尺寸设置为416×416,(SSD是300×300)

输出:13×13×125特征图(降采样了32倍,416/32=13)

【Attention】一般来说,如果数据集有c类,而模型有k个检测器(k是特征图上每个位置anchor的数量),那么网格需要有k×(4+1+c)个输出通道。

c1a7365c43e0e68782f03d8868e43c01.png
图1

最后得到的13×13特征图可以看成是13×13个单元格,每个单元格都有5个独立的物体检测器(anchor的k=5),每个检测器都预测一个边界框。

检测器的位置是固定的,它只能检测中心点落在该单元内的物体(这一限制是为了保证检测器不发生混乱,所以加以约束)。每个检测器产生25个值:

  • 20个值表征类别概率(使用softmax可以获取该检测器中目标所属的类别,也可以使用sigmoid进行多标签分类)
  • 1个值表示置信度(表明该检测器包含目标的可能性,介于0-1之间)
  • 4个值表示边界框坐标

由于每个单元格都有5个检测器,因此共有5×25=125个输出通道。

该模型总是预测固定数量的边界框:13×13个单元乘以5个检测器给出845个预测结果。显然,绝大多数的预测框都是无用信息。可以通过置信度来忽略掉一些预测框,再使用NMS可以去除重叠框。

为什么要对检测器实施约束?

为了让模型更容易学习,将每个检测器分配到图像中的固定位置去学习,每个检测器只负责学习附近的物体,而不会预测较远的问题,是onet-stage目标检测算法的技巧。(如果没有这样的约束,所有检测器都会在整张图中去预测,很容易出现混乱)

2. anchor是什么?有什么作用?

上面的分析可知,网格的划分对检测框的位置进行了约束,那么,是否可以对检测框的形状也进行约束呢?答案是肯定的。这就是anchor的任务。

anchor是提前设定好的一系列检测框(大小和尺寸都是提前定好了的),我们称为先验框,我们的检测器去学习任意形状或大小的物体或许很难,检测器仅预测相比先验框的偏移值,训练更容易,因为预测值全为零时等价于输出先验框,平均上更接近真实物体。如果没有先验框,每个检测器都必须从头开始学习不同的边界框形状,这相当困难。

3. 选择先验框的策略

先验框只是一个高度和宽度列表,在前面说了,每个网格单元预测5个先验框,这5个先验框分别使用不同的大小和长宽比,这样就可以尽可能的覆盖多种形状的目标。先验框数量和形状的选取规则是什么呢?

3.1 yolo选择先验框的策略

yolo系列通过在所有训练图像的所有边界框上进行k-means聚类来选择先验框(k=5,因此它找到五个最常见的物体形状)。因此,YOLO的先验框适合当前训练(和测试)的数据集。k-means算法中数据点是数据集中所有真实边界框的宽度和高度值。如果我们在Pascal VOC数据集的框中运行k-means,将得到5个簇:(k选为5并不是因为它效果最好,而是速度和精度之间折中的结果)

(PS:本文说的yolo普遍指yolo-v3)

934d36d3052931806294f353a9994202.png
图2

3.2 SSD选择先验框的策略

SSD不使用k-means来确定先验框。SSD在六个不同尺度(38*38、19*19、10*10、5*5、3*3、1*1)的特征图上都选取了先验框,在不同特征图上,每个网格单元选取的先验框数量是不同的(分别为4、6、6、6、4、4),对于先验框的尺寸,是使用数学公式计算得到的。因此SSD的先验框与数据集无关(SSD称它们为“default boxes”)。

另一个小差异是:YOLO的先验框只是宽度和高度,但SSD的先验框也有x,y位置。其实,YOLO也包含位置,只是默认先验框位置始终位于网格单元格的中心(对于SSD,先验框也是在网格中心)。

4. 怎样由最后的feature map转换成bbox的?

对于网络输出的13×13×125特征图,我们要将它们转换成边界框。

从图1可以看出,对于一个检测框,它的输出对应到特征图上就是橙色那一条线,有25个输出值:

4.1 四个表示坐标值

网络输出的不是绝对坐标,而是相对于先验框的4个偏移,通常为(delta_x, delta_y,delta_w, delta_h)的形式,前两个表示检测框中心与先验框中心点的偏移(先验框的中心点就是网格单元的中心),后两个表示检测框的宽高相对于先验框的缩放值。所以,要将这个坐标映射回真实图像中:

真实宽度box_w[i, j, b] = anchor_w[b] * exp(delta_w[i, j, b]) * 32

真实高度box_h[i, j, b] = anchor_h[b] * exp(delta_h[i, j, b]) * 32

这里的i,j表示网格单元的序号(第几行第几列),b表示检测器的序号(对于每个网格单元,有5个检测器)。若delta_w>0,那么exp(delta_w)大于1,此时预测框比先验框大。特别地,delta_w=0,那么exp(delta_w)为1,此时预测框与先验框一样大小。顺便说一下,这里之所以要乘以32是因为先验框坐标是13x13网格上的,网格上各个像素点等价于原始416x416图像上的32个像素点。

对于真实位置的计算,yolo和SSD算法不同,yolo如下:

真实位置x box_x[i, j, b] = (i + sigmoid(delta_x[i, j, b])) * 32

真实位置y box_y[i, j, b] = (j + sigmoid(delta_y[i, j, b])) * 32

SSD为:

真实位置x box_x[i, j, b] = (anchor_x[b] + delta_x[i, j, b]*anchor_w[b]) * image_w

真实位置y box_y[i, j, b] = (anchor_y[b] + delta_y[i, j, b]*anchor_h[b]) * image_h

区别主要在两点:

  1. yolo使用了sigmoid函数,将delta_xdelta_y限制在0~1之间,保证检测器只预测中心点在该单元格中的物体。而SSD中,物体的中心可以落在单元格的外面。
  2. SSD预测的坐标是相对于先验框中心而不是单元格中心。实际上一般情况下两个中心是重合的,但是SSD和YOLO采用的坐标系不一样。SSD的先验框坐标是归一化到[0,1],这样它们独立于网格大小,yolo的先验框坐标是网格的坐标(没有归一化)(SSD之所以这样是采用了不同大小的网格)

【Attention】

只有在预测的时候,才需要将预测框的坐标映射回原图。在训练的时候,是将ground truth通过log运算也转换为相对于先验框的偏移值,两个偏移值在做loss。

4.2 20个表示类别概率

对于每个检测框,网络为其输出了20个类别值(对于VOC数据集),这个值需要经过softmax或者sigmoid得到概率分布,使用sigmoid时变成了一个multi-label多标签分类器,每个预测框可以同时有多个类别,YOLOv3使用的就是sigmoid。

4.3 一个置信度

对于yolo,除了坐标之外,模型每个边界框预测了一个置信度,一般采用sigmoid函数得到0~1的概率值。

对于SSD,没有预测置信度,而是给分类器增加了一个特殊的类:背景。如果分类结果是背景,那么意味着检测器没有找到物体,这实际上等价于YOLO给出一个较低的置信度。

5. 网络是怎样学习的?

5.1 卷积预测

13×13的网格是卷积层得到的. 卷积实际上是在整个输入图像上以较小的窗口(卷积核)进行滑动,卷积核在每个位置是共享的。我们的样例模型最后的卷积层包含125个卷积核。

这125个卷积核在13×13特征图中的每个位置上滑动,并在每个位置上进行预测。然后,我们将这125个数字解释为5个预测边界框。最初,在每个网格位置预测到的125个数字将是完全随机和无意义的,但是随着训练,损失函数将引导模型学习做出更有意义的预测。

尽管每个网格单元中有5个检测器,但对于845个检测器来说,这个模型实际上只学习了总共5个检测器,而不是每个网格单元都学习5个唯一的检测器。这是因为卷积层的权重在每个位置都相同,因此在网格单元之间共享。但模型为每个先验框学习一个检测器,它们在图像上滑动,以获得845个预测值,网格上每个位置有5个。因此,尽管我们总共只有5个独特的检测器,但由于卷积的缘故,这些检测器与它们在图像中的位置无关,因此无论它们位于何处,都可以检测到物体。每个位置的输入像素与检测器所学习到的权重,决定了该位置的最终边界框预测。

这也解释了为什么模型总是预测边界框相对于网格单元中心的位置。由于该模型具有卷积性质,无法预测绝对坐标,而卷积核在图像上滑动,因此它们的预测总是相对于在特征图中的当前位置。

为了使得网络的输出接近我们想要的结果,需要设计一个损失函数,将预测框与真实框进行比较。

5.2 损失函数的设计

需要将ground truth与检测器进行匹配,常用的匹配策略是:当检测器与ground truth的IOU大于一个阈值时,就给该检测器分配一个正类标签,类别为ground truth的物体类别。一个ground truth可以分配给多个检测器,但是一个检测器只能与一个ground truth匹配(如果检测器与多个ground truth的IOU都超过了阈值,选IOU最大的那个ground truth进行匹配)。

与ground truth成功匹配的检测器为正例,与所有ground truth都没匹配上的检测器就是负例。

根据网络输出的三部分:分类概率、置信度、坐标,我们设计的损失函数也要能覆盖这三个方面,即在:分类错误、置信度太低、坐标偏差的时候,需要使用损失函数来惩罚。

(1)对于负例

损失函数仅包含置信度,因为没有真实框,所以不需计算类别损失和坐标损失。我们希望负例的置信度尽可能低(置信度表示检测器是否认为有一个物体的中心在这个网格单元中),理想的置信度应该为0.

SSD没有置信度损失,因为它将背景作为一个特殊的类来处理。如果预测的是背景类,那个检测器被认为没有检测到物体。

(2)对于正例

对于yolo,有三部分loss:

置信度loss+分类loss+坐标loss,其中坐标loss权重最大。(平方和误差(sum-squared error,SSE))

对于SSD,有两部分loss:(MultiBoxLoss)

分类loss+坐标回归loss(分别使用的是softmax loss和Smooth L1 loss)

5.3 使用优化器来训练

选择SGD对模型进行训练。

5.4 训练策略&技巧

  • 难例挖掘(Hard negative mining)。前面已经说过大部分检测器是不负责检测任何物体的。这意味着正例数量要远少于负例。YOLO采用一个超参数no_object_scale 来处理这种情况,但是SSD采用难例挖掘:它不是计算所有负例的损失,而是只计算那些预测结果最错的部分损失(即置信度较高的负例)。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值