R-CNN
用Selective Search的方法获取一些可能的候选框,将这些候选框送进CNN中进行特征提取(作者尝试了卷积层或两个全连接层作为提取的特征,最后发现最后一层全连接层用于分类的效果更好),将提取到的特征放入SVM分类器和回归器,进行class-else多分类和边框回归(对每一个类别进行一次SVM分类)。
边框回归:(其中
{
P
x
,
P
y
,
P
w
,
P
h
}
\{P_x,P_y,P_w,P_h\}
{Px,Py,Pw,Ph}是经过stride缩放过的四个值;
d
i
(
P
)
d_i(P)
di(P)是wx+b,为预测值,即下面的
{
t
x
,
t
y
,
t
w
,
t
h
}
\{t_x,t_y,t_w,t_h\}
{tx,ty,tw,th})
{
G
x
^
=
P
w
d
x
(
P
)
+
P
x
G
y
^
=
P
h
d
y
(
P
)
+
P
y
G
x
^
=
P
w
exp
(
d
w
(
p
)
)
G
h
^
=
P
h
exp
(
d
h
(
p
)
)
⟹
{
t
x
=
G
x
−
P
x
P
w
t
y
=
G
y
−
P
y
P
h
t
w
=
log
(
G
w
P
w
)
t
h
=
log
(
G
h
P
h
)
\begin{cases} \hat{G_x} = P_wd_x(P)+P_x \\ \hat{G_y} = P_hd_y(P)+P_y \\ \hat{G_x} = P_w\exp(d_w(p)) \\ \hat{G_h} = P_h\exp(d_h(p)) \\ \end{cases} \implies \begin{cases} t_x = \frac{G_x-P_x}{P_w} \\ t_y = \frac{G_y-P_y}{P_h} \\ t_w = \log(\frac{G_w}{P_w}) \\ t_h = \log(\frac{G_h}{P_h}) \\ \end{cases}
⎩⎪⎪⎪⎨⎪⎪⎪⎧Gx^=Pwdx(P)+PxGy^=Phdy(P)+PyGx^=Pwexp(dw(p))Gh^=Phexp(dh(p))⟹⎩⎪⎪⎪⎨⎪⎪⎪⎧tx=PwGx−Pxty=PhGy−Pytw=log(PwGw)th=log(PhGh)
R-CNN系列,一次预测只针对一个RoI区域。
SVM适合小样本训练,所以IoU阈值为0.7。作者发现SVM的效果比Softmax要好
R-CNN有三个通道,CNN用于特征提取;SVM用于分类;回归层用于边框回归
SPP-net
共享卷积层 + 空间金字塔,共享卷积层用于避免重复计算(R-CNN对于每个候选区域都放入网络中计算,大量的重叠区域,造成重复计算)。
空间金字塔,用于处理不同size的输入在全连接层的维度固定问题(全连接层的参数需要固定输入层的大小)
SPP-net对每一张图片,只进行一次卷积运算,获得feature map,然后把这些候选框的坐标映射到feature上(使用EdgeBoxes算法来选取候选框,利用边缘信息确定框内的轮廓数与边缘重叠的轮廓数)。
候选框到特征图的映射:
x
n
e
w
l
e
f
t
=
⌊
x
o
l
d
l
e
f
t
s
t
r
i
d
e
⌋
+
1
x_{new}^{left} = \lfloor \frac{x_{old}^{left} }{stride}\rfloor + 1
xnewleft=⌊stridexoldleft⌋+1
y
n
e
w
l
e
f
t
=
⌊
y
o
l
d
l
e
f
t
s
t
r
i
d
e
⌋
+
1
y_{new}^{left} = \lfloor \frac{y_{old}^{left} }{stride}\rfloor + 1
ynewleft=⌊strideyoldleft⌋+1
x
n
e
w
r
i
g
h
t
=
⌈
x
o
l
d
r
i
g
h
t
s
t
r
i
d
e
⌉
+
1
x_{new}^{right} = \lceil \frac{x_{old}^{right} }{stride}\rceil + 1
xnewright=⌈stridexoldright⌉+1
y
n
e
w
r
i
g
h
t
=
⌈
y
o
l
d
r
i
g
h
t
s
t
r
i
d
e
⌉
+
1
y_{new}^{right} = \lceil \frac{y_{old}^{right} }{stride}\rceil + 1
ynewright=⌈strideyoldright⌉+1
这里的空间金字塔,是对feature maps取 3 3 3个层次的池化信息,为 4 ∗ 4 , 2 ∗ 2 , 1 ∗ 1 4*4,2*2,1*1 4∗4,2∗2,1∗1,再拼接起来。
Fast R-CNN
多任务学习 + RoI Pooling。多任务学习是网络同时学习分类和边框预测,RoI Pooling是简化版本的空间金字塔,只有一层的池化信息。
作者分析Lee为什么SPP-net能对整个网络进行参数调整(不能进行反向传播),是因为训练的时候,本批次都不是同一副图像,这样反向传播的时候需要的跨度就会非常大,因而导致低效。相对的,作者采用分层次小批量采样,每次使用 N N N张图片进行训练,N=1,2,在每张图片随机选取 b a t c h N \frac{batch}{N} Nbatch个候选区域。
边框回归的损失函数为smooth L1损失函数,分类损失函数采用softmax loss。
Faster R-CNN
RPN + Fast R-CNN,RPN用于区域生成,生产的区域经过NMS后投入RoI和预测网络中。
Faster R-CNN是第一个把整个目标检测全部纳入到一个网络中,其检测速度和准确率明显上升(每张生成建议框的时间仅需 10 10 10ms,而Fast R-CNN每张图片需要 3 3 3s)。
RPN的原理是利用GPU运算得到候选区域,而Fast R-CNN生成候选区域的方式是特征映射,是CPU运算。所以Faster RCNN比Fast R-CNN快的原因是GPU运算的快速。
FPN
FPN,Feature Pyramid Network。
FPN,多尺度融合,对不同语义层次进行预测。(因为对于底层信息来说,语义特征较为具体、细节,位置精度更高,高层语义信息的语义特征更为抽象,因此结合起来进行预测能提高目标检测的精确度。)
多尺度融合的时候,低层次特征进行 1 ∗ 1 1*1 1∗1conv,高层次特征进行 2 ∗ 2 2*2 2∗2上采样,将高低层次特征进行拼接融合。然后通过 3 ∗ 3 3*3 3∗3conv来融合不同语义特征之间的差异,然后进行预测。
FPN作用于RPN网络中,进行区域推荐
Yolo
Yolo是第一个one-stage的目标检测方法,其直观上把网络分为 S ∗ S S*S S∗S的网格,在每个网格预测k个边框,即每张图片最后的输出值为 S ∗ S ∗ ( 5 ∗ k + 20 ) S*S*(5*k+20) S∗S∗(5∗k+20)。(Yolo在每个网格只预测一个类别,对于重叠的不同类别不考虑,这也是其存在的问题之一。对于S的值,是网络设计得到的,而不是实现考虑的)
预训练的输入是 224 ∗ 224 224*224 224∗224,基于ImageNet的数据。在迁移到目标检测任务后,在网络增加4个卷积层,权重使用xavier初始化,且输入变成 448 ∗ 448 448*448 448∗448。网络架构是在GoogleNet的基础上改进的(使用1*1卷积层用于降维),全连接层的激活函数是Leaky ReLu,最后一层直接输出(因为Yolo是直接预测边框之,并没有回归,也没有使用多任务)。
对于one-stage网络而言,结构设计和损失函数设计是很重要的。Yolo的损失函数为:$$\begin{align} & \lambda_{coord}\sum_{i=0}{S2}\sum_{j=0}{K}\mathcal{I}_{ij}{obj}[(x_i-\hat{x_i})^2 + (y_i-\hat{y_i})^2] \
- & \lambda_{coord}\sum_{i=0}{S2}\sum_{j=0}{K}\mathcal{I}_{ij}{obj}[(\sqrt{x_i}-\sqrt{\hat{x_i}})^2 + (\sqrt{y_i}-\sqrt{\hat{y_i}})^2] \
- & \sum_{i=0}{S2}\sum_{j=0}{K}\mathcal{I}_{ij}{obj}(C_i-\hat{C_i})^2 \
- & \lambda_{noobj}\sum_{i=0}{S2}\sum_{j=0}{K}\mathcal{I}_{ij}{obj}(C_i-\hat{C_i})^2 \
- & \sum_{i=0}{S2}\mathcal{I}{i}^{obj}\sum{c \in class}(p_i© - \hat{p_i©})^2
\end{align}$$
其中,前两项是坐标误差,长宽开根号的原因是想大允许大边框的误差大一些(因为相同的长宽偏差,大边框的IoU损失没小边框那么大);第三四项是IoU置信度误差,因为没对象的边框比有对象的边框对很多,所以调低没对象边框的权重;第五项是分类误差。其中设置 λ c o o r d = 5 , λ n o o b j = 0.5 , I i j o b j \lambda_{coord}=5,\lambda_{noobj}=0.5,\mathcal{I}_{ij}^{obj} λcoord=5,λnoobj=0.5,Iijobj是如果这个网格的边框存在对象。
Yolo系列有特殊的数据增强方式:亮度翻转
Yolov2
添加了Anchor box,pathrough layer,前者是考虑到了边框回归比边框直接预测准确率要好一些,后者是为了获得适应不同输入大小的feature maps(经过了pooling的特征融合方式为拆分,进行点和,比如2626256拆成4个1313256,然后和13131024融合,该融合提升了1%的mAP)。
使用k-means选择合适的Anchor box。
一个网格的K个边框分别预测类别,Yolo对一个格子只赋予一个类别,而Yolov2对一个边框预测一个类别。
使用全卷积神经网络,Yolo的输出是一个 1 ∗ N 1*N 1∗N的向量,而Yolov2输出是一个 S ∗ S ∗ ( K ∗ ( 5 + C ) ) S*S*(K*(5+C)) S∗S∗(K∗(5+C))的Tensor 。
使用了一系列的训练方法,比如BN,比如高分辨率适应(作者发现,网络的迁徙学习,在迁移之后需要适应不同分辨率和适应不同学习任务,认为如果提前适应分辨率有助于增强精确度),比如多尺度训练(每10个epoch的输入分辨率都随机选取新的 32 32 32倍数的size)
Yolov3
借鉴了DSSD的思路(但上采样不是反卷积而是插值,Prediciton Module从ResNet模块变成简单的卷积模块后预测),增加了细粒度融合,进行多层分辨率预测;
使用sigmoid来代替softmax,以适应多标签数据集。
SSD
SSD借鉴了Yolo的one-stage思想及Faster R-CNN的anchor boxes(SSD的anchors指定了不同的长宽比,面积,以适应多尺度预测,即不同level的feature maps的anchor box不同;而Faster RCNN是单独level的feature map有不同尺度feature map,Yolov2是通过k-means聚类得到合适的K个anchor boxes)。
使用特殊的Atrous操作,使得SSD又好又快:原本pooling5使用 2 ∗ 2 , s t r i d e = 2 2*2, stride=2 2∗2,stride=2,会使feature maps的size缩小2倍,作者使用 3 ∗ 3 , s t r i d e = 1 , p a d d i n g = 1 3*3, stride=1,padding=1 3∗3,stride=1,padding=1的卷积代替,保存了feature maps大小。与此同时,感受野也改变了。为了使用原本预训练得到的网络参数,使用Atrous Algorithm来保证感受野;【查一下就知道了,类似于跳跃的局部连接来保证参数】
输出为 S ∗ S ∗ [ K ∗ ( 21 + 4 ) ] S*S*[K*(21+4)] S∗S∗[K∗(21+4)],其中21个类别输出,4个坐标输出。即和yolov2不同,没有边框执行度,而是直接判断是否属于背景。
去掉了yolo的全连接层,feature maps经过 3 ∗ 3 3*3 3∗3卷积层后直接就是结果;
anchor赋予对象的机制与yolov2不同,只要预测anchor box与其中一个GT的IoU大于0.5,即赋予对象到这个框,而yolov2是一个对象只会赋予到一个anchor box上。
损失函数和Faster RCNN一样,为softmax损失 + smooth L1损失。
DSSD
SSD有两个缺点:
- 低层feature map的表征能力不足,故对小尺度物体的检测效果比较差(但比单feature map时直接使用大anchor box直接预测小物体要好一些)【SSD利用多层的feature maps进行预测,但各层之间的信息的结合并没有充分的利用,虽有向上融合特征的操作】
- 在SSD中,不同level的feature map都是独立作为分类/回归的输入,因此容易出现相同物体被不同大小的预测框同时检测出来(大框和小框的IoU不足阈值,因此不会抑制小框)
DSSD算法就是为了解决浅层feature map的表征能力不够的问题。其核心思想是使用更好的基础网络(ResNet,SSD的基础网络是VGG)和skip连接(Devolution layer)来给浅层feature map更好的表征能力。同时,DSSD借鉴了MS-RCNN的想法:改善每个人物的分支网络同样可以提高准确率(就是从原先直接用feature maps预测cls和loc Reg的方式,变成在feature maps后添加ResNet模块来增加feature信息再预测cls和loc Reg)。
所以,DSSD就是ResNet基础网络+Deconvolution Module增加feature map预测层的语义信息 + Prediction Module
为什么对小目标不够鲁棒?
Yolo算法,对每个网格预测一个类别,K个边框,但可能出现两个类别目标在一个格子中,则出现漏检。
Yolov2算法,使用anchor框,在一个网格预测K个边框,且对每个边框赋予一个类别,因而能匹配大部分目标,算是解决了漏检问题。但若K个anchor box都比较大,较小的目标就没那么容易匹配了。则存在小目标漏检现象。
SSD算法,在更浅层一些的feature map上匹配更小的目标(浅层feature map使用更小的anchor),这样小目标捡漏的概率就大大减小了。但浅层提取的feature map表征能力不够,也就是浅层的feature map中每个网格虽然可以判断这个网格包含哪一个类,但不那么确定。可能会出现框对了,但分类错了,或置信度不高的情况。则可能对小目标出现错检现象的概率更高。故SSD对小目标不够鲁棒。
FSSD
FSSD仍是解决SSD浅层特征表征能力不足的问题,本网络的思路是将底层语义特征和高级语义特征结合起来,然后再进行SSD操作;
- Image pyramid
- RCNN系列
- FPN
- SSD
- FSSD(Feature Fusion Single Shot Multibox Detector)
很直观的看,FSSD是将各level的feature map进行concate,然后从fusion feature 上生产feature pyramid。
FSSD的上采样是双线性插值,特征融合方式为concate。
FSSD的FPS为17,mAP为80.9;DSSD的FPS为15,mAP为81.5。FSSD是基于VGG,DSSD是基于ResNet;FSSD的特征融合方式为concate,DSSD的特征融合方式为sum(点和,但作者发现点积的计算有更好的精度)
RSSD
RSSD,Rainbow SSD,论文名为Enhancement of SSD by concatenating feature maps for object detection。
RSSD,增加了一种特征融合方式。传统的特征融合方式有两种:1. 从前往后的pooling的特征融合;2. 从后往前的 Deconvolution/UpSample的特征融合。这两种融合方式都是单方向传递的,所以R-SSD就结合了两种传递。
在做concate之前都会对feature map做一个BN操作,因为不同层的feature map语义信息是不同的。
RetinaNet
该文章主要是提出Focal loss函数,用来消除样本比例不均衡问题。
作者分析了为什么two-stage的精度比one-stage高?作者实验发现,two-stage网络通过生产候选区域,消除了大量背景;而one-stage却要从大量的背景中找到少了目标,这样的负例太多了,,导致梯度回传的时候,可能会淹没正例消息,这导致模型的优化方向有时候不是我们预期的方向。(传统方法是使用OHEM方法,Online Hard Example Mining,通过对loss排序,选择loss最大的样本来训练,就能保证训练的区域都是难分的,但它容易把易于区域的样本给忽略)
Focal loss就是为了解决One-stage的精度问题。这个损失函数是在交叉熵损失函数的基础上进行的改进,它降低了容易分类样本的权重,让整个优化方向更加的专注于难分类样本;
标准的交叉熵损失函数(这里用二分类)
C
E
(
p
,
y
)
=
{
−
log
(
p
)
,
i
f
y
=
1
−
l
o
g
(
1
−
p
)
,
o
t
h
e
r
w
i
s
e
CE(p,y) = \begin{cases} -\log(p), & if \ y =1 \\ -log(1-p),&otherwise \end{cases}
CE(p,y)={−log(p),−log(1−p),if y=1otherwise
引进
α
\alpha
α,对不同样本产生的loss的权重进行控制(这样就解决了背景边框占比大的问题,但没区分难分和易分样本):
C
E
(
p
t
)
=
−
α
t
l
o
g
(
p
t
)
CE(p_t)=-\alpha_t log(p_t)
CE(pt)=−αtlog(pt)
p
t
=
{
p
,
i
f
y
=
1
1
−
p
,
o
t
h
e
r
w
i
s
e
p_t = \begin{cases} p, & if \ y=1 \\ 1-p, &otherwise \end{cases}
pt={p,1−p,if y=1otherwise
引入
γ
\gamma
γ,作为对难分和易分样本之间差异的权衡:
F
L
(
p
t
)
=
−
(
1
−
p
t
)
γ
log
(
p
t
)
FL(p_t)=-(1-p_t)^{\gamma}\log(p_t)
FL(pt)=−(1−pt)γlog(pt)
将
α
,
γ
\alpha,\gamma
α,γ结合,得到新的损失函数focal loss:
F
L
(
p
t
)
=
−
α
t
(
1
−
p
t
)
γ
log
(
p
t
)
FL(p_t)=-\alpha_t (1-p_t)^{\gamma}\log(p_t)
FL(pt)=−αt(1−pt)γlog(pt)
作者通过实验验证:当
α
=
0.25
,
γ
=
2
\alpha=0.25,\gamma=2
α=0.25,γ=2时,检测的效果会比较好
直观上看focal loss这个损失函数:当 p t p_t pt较大是, l o s s → 0 loss \rightarrow 0 loss→0,对loss的贡献就比较小;当 p t p_t pt很小时, 1 − p t → 1 1-p_t \rightarrow 1 1−pt→1,则和原来的交叉熵loss没什么区别,即当 1 − p t 1-p_t 1−pt越小,则代表预测越准,loss越小。
一行代码改进NMS
原论文名字为:soft-NMS Improving Object Detection With One Line of Code
一种新的NMS方式:降低较低置信度边框的置信度,而不是直接赋0(具体实现,直观上叫做直接删除边框)最后再依据置信度删除。
传统NMS存在的问题:若有同类别对象近似重叠,则这两目标的检测边框也重叠相当一部分,则有可能会抑制某个目标的边框(若NMS阈值设大了,会增加误检概率;若NMS阈值设小了,可能会出现上述现象)。
N
t
N_t
Nt为置信度,
M
M
M为当前得分最高框,
b
i
b_i
bi为待处理框,
S
i
S_i
Si为
b
i
b_i
bi的得分,则原先的NMS如下:
S
i
=
{
S
i
,
I
o
U
(
M
,
b
i
)
<
N
t
0
,
I
o
U
(
M
,
b
i
)
≥
N
t
S_i= \begin{cases} S_i, & IoU(M,b_i) < N_t \\ 0, & IoU(M,b_i) \geq N_t \end{cases}
Si={Si,0,IoU(M,bi)<NtIoU(M,bi)≥Nt
线性加权的方式改进:
S
i
=
{
S
i
,
I
o
U
(
M
,
b
i
)
<
N
t
S
i
(
1
−
I
o
U
(
M
,
b
i
)
)
,
I
o
U
(
M
,
b
i
)
≥
N
t
S_i= \begin{cases} S_i, & IoU(M,b_i) < N_t \\ S_i(1-IoU(M,b_i)), & IoU(M,b_i) \geq N_t \end{cases}
Si={Si,Si(1−IoU(M,bi)),IoU(M,bi)<NtIoU(M,bi)≥Nt
高斯加权的方式改进:
S
i
=
S
i
e
−
I
o
U
(
M
,
b
i
)
2
σ
S_i= S_ie^{-\frac{IoU(M,b_i)^2}{\sigma}}
Si=Sie−σIoU(M,bi)2
该改进能提高 1 % 1\% 1%的mAP,但不增加计算量。
IoU-net
将IoU作为优化目标,一种基于优化的边界框修正方法。
IoU引导式NMS + 基于优化的边界框修正流程。
解决的问题:1. 目标检测类别置信度和定位置信度不匹配问题;2. 迭代式边界框回归具有非单调性。
**IoU引导式NMS:**按边界置信度执行正常的NMS。但若丢弃的边框的cls-confidence比留下的大,便赋予,以保持两置信度一致。
**将边界框修正当做是一个修正过程:**更新边框参数时,① 在更新前判断该边框能预测的边框置信度PrevScore;② 计算梯度;③ 判断更新后的边框能预测的边框置信度NewScore; 若
∣
N
e
w
S
c
o
r
e
−
P
r
e
v
S
c
o
r
e
∣
<
Ω
1
|NewScore-PrevScore| < \Omega_1
∣NewScore−PrevScore∣<Ω1(
0.001
0.001
0.001左右,
Ω
1
\Omega_1
Ω1是early-stop的标志),则代表收敛了;若
N
e
w
S
c
o
r
e
−
P
r
e
v
S
c
o
r
e
<
Ω
2
<
0
NewScore-PrevScore < \Omega_2 < 0
NewScore−PrevScore<Ω2<0(
−
0.01
-0.01
−0.01左右),代表不能忍受这“逃逸”速度了。当上述两个条件发生,便不再更新该边框。