作者:Joseph Redmon,Santosh Divvala , Ross Girshick , Ali Farhadi
发表时间:2015
Paper 原文:You Only Look Once:Unified, Real-Time Object Detection
先来看看 YOLO V1 的网络结构,如下图(来自目标检测 YOLO)所示。这里 backbone 是基于 GoogleNet 修改的。
具体来说,这里的 GoogLeNet modification(20 layers)就是采用 1×1 卷积层加 3×3 卷积层替换了 GoogLeNet 中的 Inception 模块,然后去掉了第二层 1x1 的卷积层和最后的 fc 层,更多关于 GoogLeNet 的介绍可以参考 CV 经典主干网络 (Backbone) 系列: GoogLeNet V1 到 V4。
YOLO v1 的具体结构如下。整个网络有 24 个卷积层,2 个全连接层, 4 个 pooling 层,整个网络 的 stride 为 64。
另外除了最后一层使用线性激活函数之外,其他层都使用 Leaky ReLU 激活函数,关于激活函数可以参考深度神经网络中常用的激活函数的优缺点分析。
index | kernal size | feature map size |
---|---|---|
input | - | 3x448x448 |
conv1 | 64x3x7x7-S_2-P_3 | 64x224x224 |
pool1 | 2x2-S_2 | 64x112x112 |
conv2 | 192x3x3-S_1-P_1 | 192x112x112 |
pool2 | 2x2-S_2 | 192x56x56 |
conv3 | 128x1x1-S_1-P_0 | 128x56x56 |
conv4 | 256x3x3-S_1-P_1 | 256x56x56 |
conv5 | 256x1x1-S_1-P_0 | 256x56x56 |
conv6 | 512x3x3-S_1-P_1 | 512x56x56 |
pool3 | 2x2-S_2 | 512x28x28 |
conv7 | 256x1x1-S_1-P_0 | 256x28x28 |
conv8 | 512x3x3-S_1-P_1 | 512x28x28 |
conv9 | 256x1x1-S_1-P_0 | 256x28x28 |
conv10 | 512x3x3-S_1-P_1 | 512x28x28 |
conv11 | 256x1x1-S_1-P_0 | 256x28x28 |
conv12 | 512x3x3-S_1-P_1 | 512x28x28 |
conv13 | 256x1x1-S_1-P_0 | 256x28x28 |
conv14 | 512x3x3-S_1-P_1 | 512x28x28 |
conv15 | 512x1x1-S_1-P_0 | 512x28x28 |
conv16 | 1024x3x3-S_1-P_1 | 1024x28x28 |
pool4 | 2x2-S_2 | 1024x14x14 |
conv17 | 512x1x1-S_1-P_0 | 512x14x14 |
conv18 | 1024x3x3-S_1-P_1 | 1024x14x14 |
conv19 | 512x1x1-S_1-P_0 | 512x14x14 |
conv20 | 1024x3x3-S_1-P_1 | 1024x14x14 |
conv21 | 1024x3x3-S_1-P_1 | 1024x28x28 |
conv22 | 1024x3x3-S_2-P_1 | 1024x7x7 |
conv23 | 1024x3x3-S_1-P_1 | 1024x7x7 |
conv24 | 1024x3x3-S_1-P_1 | 1024x7x7 |
fc1 | - | 4096x1 |
fc2 | - | 1470x1 |
跳出具体的网络结构,我们从全局的观点来看看 YOLO v1 的结构。
从结构可以看出,YOLO v1 的整体结构很清晰,输入图片(448x448x3)经过 24 conv + 2 fc 后得到的 feature map size 为 1470x1,然后做了一个 reshape 操作,将 1470x1 reshape 为 7x7x30,所有的操作都没有什么特别之处。
只是为什么要做这个 reshape 操作了,这就是非常关键的一步了。具体可以参考下面的网络原理部分。
上面已经提到, YOLO V1 中将检测任务视作一个回归任务,即 location 和分类的结果都是通过回归的方式得到。那么 YOLO V1 到底是如何工作的呢?
到这里就可以理解上面为什么要将 1470x1 reshape 为 7x7x30了。 30 是指 2x(4+1) + 20。这里 2 就是 上面的 B,4+1 是指每个 bbox 的预测值,包括 ( x , y , w , h , c o n f i d e n c e ) (x,y,w,h,confidence) (x,y,w,h,confidence),这里的 20 是 20 个类别对应的分类置信度(不包括背景)。
YOLO 的损失函数由三部分组成,位置损失,置信度损失以及分类损失函数。
L o s s 1 = λ c o o r d ∑ i = 0 S 2 ∑ j = 0 B Π i j o b j [ ( x i − x ^ i ) 2 + ( y i − y ^ i ) 2 ] + λ c o o r d ∑ i = 0 S 2 ∑ j = 0 B Π i j o b j [ ( w i − w ^ i ) 2 + ( h i − h ^ i ) 2 ] Loss_1 = \lambda_{coord} \sum_{i=0}^{S^2}\sum_{j=0}^{B}\Pi_{ij}^{obj}[(x_i-\hat{x}_i)^2+(y_i-\hat{y}_i)^2]+\lambda_{coord} \sum_{i=0}^{S^2}\sum_{j=0}^{B}\Pi_{ij}^{obj}[(\sqrt{w_i}-\sqrt{\hat{w}_i})^2+(\sqrt{h_i}-\sqrt{\hat{h}_i})^2] Loss1=λcoordi=0∑S2j=0∑BΠijobj[(xi−x^i)2+(yi−y^i)2]+λcoordi=0∑S2j=0∑BΠijobj[(wi−w^i)2+(hi−h^i)2]
其中
Π i j o b j = { 1 如 果 c e l l i 的 b b o x j 负 责 预 测 目 标 0 否 则 \Pi_{ij}^{obj} =\left\{ \begin{aligned} &1 \space如果 cell_i 的 bbox_j 负责预测目标\\ &0 \space 否则 \end{aligned} \right. Πijobj={1 如果celli的bboxj负责预测目标0 否则
对于位置损失,主要是计算 bbox 的 ( x , y , w , h ) (x,y,w,h) (x,y,w,h) 和对应的 ground truth box 的 ( x ^ , y ^ , w ^ , h ^ ) (\hat{x},\hat{y},\hat{w},\hat{h}) (x^,y^,w^,h^) 之间的 sum-squared error,需要注意的是并不是所有的 bbox 都参与 loss 的计算,首先必须是 c e l l i cell_i celli 中存在 object,并且 c e l l i cell_i celli 中的第 j 个 bbox 和 ground truth box 有最大的 IoU 值,那么这个 b b o x j bbox_j bboxj 才参与 loss 的计算,其他的不满足条件的 bbox 不参与。即,一个 ground truth box 只需要一个 bbox 来负责,而有最大 IoU 的 bbox 更接近 ground truth,所以学习起来更快。
对不同大小的box预测中,相比于大box预测偏一点,小box预测偏一点肯定更不能被忍受的。而sum-square error loss中对同样的偏移loss是一样。
为了缓和这个问题,作者用了一个比较取巧的办法,就是将 bbox 的 width 和 height 取平方根代替原本的 height 和 width。这个参考下面的图很容易理解,小 bbox 的横轴值较小,发生偏移时,反应到y轴上相比大 bbox 要大。
L o s s 2 = ∑ i = 0 S 2 ∑ j = 0 B Π i j o b j ( C i − C ^ i ) 2 + λ n o o b j ∑ i = 0 S 2 ∑ j = 0 B Π i j n o o b j ( C i − C ^ i ) 2 Loss_2 = \sum_{i=0}^{S^2}\sum_{j=0}^{B}\Pi_{ij}^{obj}(C_i-\hat{C}_i)^2 + \lambda_{noobj} \sum_{i=0}^{S^2}\sum_{j=0}^{B}\Pi_{ij}^{noobj}(C_i-\hat{C}_i)^2 Loss2=i=0∑S2j=0∑BΠijobj(Ci−C^i)2+λnoobji=0∑S2j=0∑BΠijnoobj(Ci−C^i)2
置信度损失的计算分两种情况,一种是有 object 的 cell 的置信度计算,另一种是没有 object 的 cell 的置信度计算。两种情况都是 cell 中所有的 bbox 都参与计算。对于有 object 的 cell 中的 bbox 的置信度的 ground truth 就是 1 ∗ I O U ( p r e d , t r u t h ) 1*IOU(pred,truth) 1∗IOU(pred,truth)。需要注意的是这个IOU是在训练过程中不断计算出来的,因为网络在训练过程中每次预测的 bbox 是变化的,所以 bbox 和 ground truth 计算出来的 IOU 每次也会不一样。而对于没有 object 的 cell 中的 bbox 的置信度的 ground truth 为 0 ∗ I O U ( p r e d , t r u t h ) = 0 0*IOU(pred,truth) = 0 0∗IOU(pred,truth)=0 ,因为不包含物体。
L o s s 3 = ∑ i = 0 S 2 Π i o b j ∑ c ∈ c l a s s e s ( p i ( c ) − p ^ i ( c ) ) 2 Loss_3 = \sum_{i=0}^{S^2}\Pi_{i}^{obj}\sum_{c \in classes}(p_i(c)-\hat{p}_i(c))^2 Loss3=i=0∑S2Πiobjc∈classes∑(pi(c)−p^i(c))2
YOLO 中将分类损失当作回归来计算,使用 sum-squared error 来计算分类误差,需要注意的是只有包含 object 的 cell 才参与分类 loss 的计算,即 object 中心点落入的 cell 才进行分类 loss 的计算,而这个 cell 的 ground truth label 就是该物体的label。
YOLO 有 3 种 loss,显然各种 loss 的重要程度是不一样的,所以各个 loss 有不同的权重。
总结起来就是:
当然 YOLO V1 的优势就是速度快,可以进行实时的检测,而且准确度也还不错。如下图所示。