YOLOv3
YOLO v1学习笔记:https://blog.youkuaiyun.com/JSerenity/article/details/88598503
YOLO v2学习笔记:https://blog.youkuaiyun.com/JSerenity/article/details/88672337
主要思想:
把目标检测看成一个回归问题。靠一个卷积网络完成整个检测任务,实现端到端的目标检测。速度相当的快。
与其他方法的简单比较:
滑动窗口法: 一个框一个框的滑动并进行图像分类
R-CNN:
先生成预选框
在这些预选框上进行图像分类
然后再优化修正
YOLO:
一个卷积网络完成所有任务。
预测框的位置、大小和物体分类都是通过CNN直接预测出来的。它有75个卷积层,使用跳跃连接和上卷积。不使用pooling,而是采用步幅为2的卷积层来完成下卷积。这样避免了低层的特征的loss容易贡献给pooling层。
网络采用DarkNet53,卷积层用来提取特征获得feature map,使用1x1的卷积核计算预测类别概率和坐标。输入为416x416的图像通过卷积会得到13x13的feature map。
YOLO如何进行预测
YOLO将图像划分为SxS的网格。如果物体中心落在某个格子,则这个格子负责检测它。每个格子预测B个bounding boxes, confidence和C个类别的概率。每个bounding box包含5个预测值: t x , t y , t w , t h , c o n f i d e n c e t_x,t_ y, t_w, t_h, confidence tx,ty,tw,th,confidence。(x,y)值为与格子相对的box的中心坐标。宽和高的值是相对于整个图像的。confidence为格子中是否有物体和有物体的概率是多大。
c o n f i d e n c e : P r ( O b j e c t ) ∗ I O U p r e d t r u t h confidence : Pr(Object)*IOU^{truth}_{pred} confidence:Pr(Object)∗IOUpredtruth,C个类别的概率表示为 P r ( C l a s s i ∣ O b j e c t ) Pr(Class_i|Object) Pr(Classi∣Object)。如果格子中没有物体则confidence为0。无论有多少个bounding boxes,我们只预测一组C个类别的概率。
测试的时候我们将confidence和C个类别的概率相乘,得到的是每个box的class-specific confidence score。这个分数结合了某个类别的物体出现在格子中的概率和预测框的准确度:
P r ( C l a s s i ∣ O b j e c t ) ∗ P r ( O b j e c t ) ∗ I O U p r e d t r u t h = P r ( C l a s s i ) ∗ I O U p r e d t r u t h Pr(Class_i|Object) * Pr(Object)*IOU^{truth}_{pred} = Pr(Class_i)*IOU^{truth}_{pred} Pr(Classi∣Object)∗Pr(Object)∗IOUpredtruth=Pr(Classi)∗IOUpredtruth
卷积得到feature map为一个
S
×
S
×
B
×
(
5
+
C
)
S\times S\times B \times(5+C)
S×S×B×(5+C)张量。YOLOv3会得到三个这样的feature map,并在上面做预测。随着网络的不断加深,得到三个不同尺度的feature map,后面会讲到。
Anchor Boxes
在YOLOv1中,是直接预测目标框的宽和高的。但这样的缺点是导致梯度在训练过程中很不稳定。所以我们首先设置一些预选框,叫anchor。然后预测目标框和预选框的偏移量。在YOLOv3中,每个格子都有产生3个不同形状的预选框。
Bounding box prediction & cost function calculation
YOLOv3用logistic regression为每一个bounding box预测一个objectness score。即这块位置是目标的可能性有多大。这一步是在predict之前进行的,可以去掉不必要anchor,可以减少计算量。如果模板框不是最佳的即使它超过我们设定的阈值,我们还是不会对它进行predict。不同于faster R-CNN的是,yolo_v3只会对1个prior进行操作,也就是那个最佳prior。而logistic回归就是用来从9个anchor priors中找到objectness score(目标存在可能性得分)最高的那一个。logistic回归就是用曲线对prior相对于 objectness score映射关系的线性建模。如果一个prior和GT的重叠度大于其他的prior,则它的objectness score应该为1。另外的高于预设threshold(默认值为5)的priors不会有cost。每一个GT物体只与一个prior相关联。如果一个prior没有GT与之相关联,则不会导致分类和位置误差,而只有objectness误差。
b x = σ ( t x ) + c x b_x = \sigma(t_x) + c_x bx=σ(tx)+cx
b y = σ ( t y ) + c y b_y = \sigma(t_y) + c_y by=σ(ty)+cy
b w = p w e t w b_w = p_we^{t_w} bw=pwetw
b h = p h e t h b_h = p_he^{t_h} bh=pheth
Feature Pyramid Networks(FPN) like Feature Pyramid
YOLOv3在每一个格子上做3个预测。每个预测包含一个boundary box,一个objectness和80类别得分。 ( N × N × [ 3 × ( 4 + 1 + 80 ) ] ) (N \times N \times [3 \times(4+1+80)]) (N×N×[3×(4+1+80)])
- 最后一层feature map
- 退回2层然后上采样
- 重复2
YOLOv3同样使用k-means聚类来决定9个priors。对于COCO,这9个priors分别为(10×13),(16×30),(33×23),(30×61),(62×45),(59× 119),(116 × 90),(156 × 198),(373 × 326)。这9个priors将按比例调整为3组9个的priors以适应不同尺度的feature map。
Feature extractor
一个新的53层的Darknet-53替换了Darknet-19.
Darknet-53
YOLOv3再次通过牺牲速度来提高精度。精度的提升得益于更复杂的网络结构Darknet的提升。
YOLOv2使用的Darknet-19缺乏了许多重要的被广泛使用的元素如:残差块、跳跃连接和上取样。YOLOv3则包含了这些重要内容。
Darknet-53用53层网络在Imagenet上面训练,然后再增加53层训练检测任务。一共使用了106层卷积层。这是为什么YOLOv3比v2要慢。
Detection at three Scales
YOLOv3最显著的特点是在三个不同尺度的feature maps上做预测。yolo v3输出了3个不同尺度的feature map,然后使用1x1的卷积核在这三个feature maps上卷积完成预测。
第一次预测:在82层,feature map大小为13x13x255。
第二次预测:对79层的feature map进行几层卷积,再进行2x上采样得到26x26维。然后和61层连接起来。然后,再次对它进行几个1x1卷积层处理,以融合61层的特征。在94层,feature map大小为26x26x255。
第二次预测:像第二次预测类似,最后在106层,feature map大小为52x52x255。
上采样层与前面的卷积层相连,有助于保留细粒度特征,有助于检测小物体,以帮助解决YOLOv2的痛点。
13x13的层负责检测大物体,26x26的层负责检测中等大小物体,52x52的层负责检测小物体。
Class Prediction
YOLOv3将用于计算输入属于某一类的可能性的softmax替换为一个独立的logistic分类器。YOLOv3使用binary cross-entropy loss而不是使用mean square error去计算分类误差。这也通过避免softmax函数降低了计算复杂度。
Loss function
下面是YOLOv1和v2使用的loss function。最后的三项使用的squared errors。在YOLOv3中他们被cross-entropy error所代替。换句话说,object confidence和class predictions通过logistic regression来预测。
loss function的代码:
xy_loss = object_mask * box_loss_scale * K.binary_crossentropy(raw_true_xy, raw_pred[..., 0:2],
from_logits=True)
wh_loss = object_mask * box_loss_scale * 0.5 * K.square(raw_true_wh - raw_pred[..., 2:4])
confidence_loss = object_mask * K.binary_crossentropy(object_mask, raw_pred[..., 4:5], from_logits=True) + \
(1 - object_mask) * K.binary_crossentropy(object_mask, raw_pred[..., 4:5],
from_logits=True) * ignore_mask
class_loss = object_mask * K.binary_crossentropy(true_class_probs, raw_pred[..., 5:], from_logits=True)
xy_loss = K.sum(xy_loss) / mf
wh_loss = K.sum(wh_loss) / mf
confidence_loss = K.sum(confidence_loss) / mf
class_loss = K.sum(class_loss) / mf
loss += xy_loss + wh_loss + confidence_loss + class_loss
YOLO特点:
-
YOLO将图像划分为SxS的网格,每个格子预测bouding box。
-
采用leaky ReLU作为激活函数。
-
端到端训练。
-
从yolo_v2开始,yolo就用batch normalization作为正则化、加速收敛和避免过拟合的方法,把BN层和leaky relu层接到每一层卷积层之后。
-
可以灵活切换backbone网络,在速度和准确率之间tradeoff。
-
yolo每一代的提升很大一部分决定于backbone网络的提升。
论文:https://pjreddie.com/media/files/papers/YOLOv3.pdf
参考:
https://towardsdatascience.com/yolo-v3-object-detection-53fb7d3bfe6b
https://medium.com/@jonathan_hui/real-time-object-detection-with-yolo-yolov2-28b1b93e2088
https://blog.youkuaiyun.com/leviopku/article/details/82660381