这部分,我们来聊聊YOLO.
YOLO:You Only Look Once,顾名思义,就是希望网络在训练过程中,一张图片只要看一次就行,不需要去多次观察,比如滑框啥的,从而从底层原理上就减少了很多的计算量。
###0 - 扯扯

图1.YOLOv1检测过程
上图为YOLOv1的检测过程(其实第二版在整体框架上也大同小异,细节自然不同),模型都会统一将输入图片resize到448*448,然后建立CNN模型,在最后的全连接层上对应最后的输出结果。在流程上,模型就是一个整体,所以相对更容易优化,而且也减少了分离模型之间信息传递的缺失,直接就是从像素级别到预测类别和框位置的这么一个结果
Yolo是将对象检测看成一个回归问题(空间上对象框的预测和对应的类别概率)(待后面看到目标函数才知精彩)。
作者认为YOLO的优势有
1 - 因为其他模型需要先滑框或者基于当前位置框,用分类器分类当前框内是否有对象,然后接着对当前框进行微调等复杂的组成,这里就一个模型,所以快。
2 - 不同于滑框和基于锚点(就是提前定几个不同大小的框)等技术,YOLO基于全图进行训练所以,它能够编码潜在的图片中检测到的类别上下文信息(作者在v2版本就用了锚点)。所以相对Fast R-CNN来说,YOLO能够更少的得到假阳性(也就是把背景框出来了)。
3 - YOLO能学到更广泛的对象表征,所以在自然场景下训练比如COCO,然后在艺术风格图片上预测,效果也好于R-CNN系列。

###1 - YOLO框架

图2.YOLO的网络结构
该结构有24个卷积层2个全连接层,其中用1x1的卷积层来减少特征空间参数。作者是先将该网络在imagenet上以224*224先做分类预训练,然后留待后面检测。


图3.YOLO的目标函数
个人觉得yolov1中最出彩的就是这个目标函数了。这里我们一一解释:
如图2所示,最后会得到一个$7730$的张量,而如何将这个$7730$的张量对应到既要分类又要目标的框坐标预测,那就有意思了。首先看下图:

图4.模型
网格划分:YOLO的思想是先将图片划分成不同的网格,然后假如狗这个对象的中心是在第5行第2列(左上为原点),那么cell[5,2]就负责整个对象的检测。比如图4中划分成了$SS$个网格,其中S就是对应着最后的7,也就是这张图片一共分成了$77$个网格,所以最后的张量中$7730$中的30 就是针对当前网格所需要干的其他事情了。

框预测:基于每个网格,会预测需要的B个框(也就是担心预测的一个框不准,所以多预测几个),作者这里选择2个,即$B=2$,在框预测阶段,需要每个框给出5个值,分别是$x,y,w,h,confidence$。其中
i)$x,y$表示基于当前网格中心为参照得到的预测框的中心坐标;
ii)$w,h$表示预测框相对于整个图的width和height;
iii)\(confidence = P_{object}*IOU_{pred}^{truth}\)。这里IOU的想法是来自文档检索领域的,这里就不细说了,\(IOU=\frac{真实框\bigcap 预测框}{真实框 \bigcup 预测框}\).这里的置信度就是当前区域是否有对象的概率乘以IOU的值,可以看出如果当前区域没对象,那么该置信度就是为0.
iv)因为作者采用的是voc数据集,里面一共有20个类别,所以one-hot就是20维,所以上面的30对应的就是(2*5+20)。

回顾目标函数:基于上面的网格划分和框预测,我们知道最后的$7730$是会在每个网格上都计算一次,这里我们省去目标函数中的$S2$那个求和,即基于某一个网格I来分析(下面将$1_$缩写成$1_^$):
$$\begin\
& &\lambda_\sum_B1_[(x_I-\hat x_I)^2+(y_I-\hat y_I)^2]\
&+&\lambda_\sum_B1_[(\sqrt-\sqrt{\hat w_I})2+(\sqrt-\sqrt{\hat h_I})2]\
&+&\sum_B1_(C_I-\hat C_I)2\
&+& \lambda_\sum_
1_
(C_I-\hat C_I)2\
&+& 1_
\sum_{c \in classes}(p_I(c)-\hat p_I(c))2
\end$$
其中$1_
$表示第i个网格是否有对象的真值函数,即满足则为1,否则为0;而$1_
$表示在第i个网格中第j个预测候选框负责预测。I
在实现时,获取当前网格的30维度向量基础上,前面5位为一个预测候选框的值:d[:2]为$x,y$, d[2:4]为$w,h$; d[4]为置信度;剩下的d[10:30]为类别对象预测

那么就2种情况,当前网格有对象和没有对象。而且作者是这样说的,只惩罚当该网格中有对象的时候的分类错误,即如果不存在对象,那么分类上就不惩罚了;而且只惩罚负责预测当前对象的那个候选框,置于这个框怎么选,就是选取候选框中IOU最大的那个:
1 - 没有对象。则$1_^\(=0,从而该网格计算的损失函数值为\)\lambda_\sum_B1_(C_i-\hat C_i)^2$;
2 - 有对象。则开始计算损失值,首先计算B个预测候选框与真实框的IOU,然后只在那个最大IOU的候选框上计算$x,y,w,h$,和置信度。
其中$C$就是置信度,而$(C_I-\hat C_I)2$就是表示预测的置信度减去真实的置信度,因$confidence = P_*IOU_$,所以IOU一开始并无法给出,其中$C_I$就是模型给出的一个值,而$\hat C_I$是在训练过程中才能给出的值。(置信度等于出现对象概率乘以IOU,因对象概率在目标函数其他地方就已存在,我们剥离对象概率,所以就是预测IOU的值等于真实IOU的值。即当模型在test的时候,该值能告知当前预测框的置信度)
结合github上hizhangp的代码理解

def loss_layer(self, predicts, labels, scope='loss_layer'):
with tf.variable_scope(scope):
#从预测的向量中取出对应的部分
predict_classes = tf.reshape(predicts[:, :self.boundary1], [self.batch_size, self.cell_size, self.cell_size, self.num_class])
predict_scales = tf.reshape(predicts[:, self.boundary1:self.boundary2], [self.batch_size, self.cell_size, self.cell_size, self.boxes_per_cell])
predict_boxes = tf.reshape(predicts[:, self.boundary2:], [self.batch_size, self.cell_size, self.cell_size, self.boxes_per_cell, 4]) #从label中计算并生成,response表示某个对象的中心是否落在当前cell中
response = tf.reshape(labels[:, :, :, 0], [self.batch_size, self.cell_size, self.cell_size, 1])
#从label中计算当前对象的坐标信息
boxes = tf.reshape(labels[:, :, :, 1:5], [self.batch_size, self.cell_size, self.cell_size, 1, 4])
boxes = tf.tile(boxes, [1, 1, 1, self.boxes_per_cell, 1]) / self.image_size
#因为是label,所以box就一个,从5:25都是20类的类别信息
classes = labels[:, :, :, 5:] offset = tf.constant(self.offset, dtype=tf.float32)
offset = tf.reshape(offset, [1, self.cell_size, self.cell_size, self.boxes_per_cell])
offset = tf.tile(offset, [self.batch_size, 1, 1, 1])
predict_boxes_tran = tf.stack([(predict_boxes[:, :, :, :, 0] + offset) / self.cell_size,
(predict_boxes[:, :, :, :, 1] + tf.transpose(offset, (0, 2, 1, 3))) / self.cell_size,
tf.square(predict_boxes[:, :, :, :, 2]),
tf.square(predict_boxes[:, :, :, :, 3])])
predict_boxes_tran = tf.transpose(predict_boxes_tran, [1, 2, 3, 4, 0])
#计算预测出来的box与真实box的IOU
iou_predict_truth = self.calc_iou(predict_boxes_tran, boxes) # calculate I tensor [BATCH_SIZE, CELL_SIZE, CELL_SIZE, BOXES_PER_CELL]
#选择IOU最大的那个候选框作为预测框
object_mask = tf.reduce_max(iou_predict_truth, 3, keep_dims=True)
object_mask = tf.cast((iou_predict_truth >= object_mask), tf.float32) * response # calculate no_I tensor [CELL_SIZE, CELL_SIZE, BOXES_PER_CELL]
noobject_mask = tf.ones_like(object_mask, dtype=tf.float32) - object_mask boxes_tran = tf.stack([boxes[:, :, :, :, 0] * self.cell_size - offset,
boxes[:, :, :, :, 1] * self.cell_size - tf.transpose(offset, (0, 2, 1, 3)),
tf.sqrt(boxes[:, :, :, :, 2]),
tf.sqrt(boxes[:, :, :, :, 3])])
boxes_tran = tf.transpose(boxes_tran, [1, 2, 3, 4, 0]) # class_loss
#当response为1,则表示当前cell有对象,否则当前cell的分类loss为0
class_delta = response * (predict_classes - classes)
class_loss = tf.reduce_mean(tf.reduce_sum(tf.square(class_delta), axis=[1, 2, 3]), name='class_loss') * self.class_scale # object_loss
#选取最大那个IOU作为预测框,然后计算置信度的损失,这里predict_scales是网络预测出的值,iou_predict_truth是当前预测框与真实框的IOU
object_delta = object_mask * (predict_scales - iou_predict_truth)
object_loss = tf.reduce_mean(tf.reduce_sum(tf.square(object_delta), axis=[1, 2, 3]), name='object_loss') * self.object_scale # noobject_loss
noobject_delta = noobject_mask * predict_scales
noobject_loss = tf.reduce_mean(tf.reduce_sum(tf.square(noobject_delta), axis=[1, 2, 3]), name='noobject_loss') * self.noobject_scale # coord_loss
coord_mask = tf.expand_dims(object_mask, 4)
boxes_delta = coord_mask * (predict_boxes - boxes_tran)
coord_loss = tf.reduce_mean(tf.reduce_sum(tf.square(boxes_delta), axis=[1, 2, 3, 4]), name='coord_loss') * self.coord_scale tf.losses.add_loss(class_loss)
tf.losses.add_loss(object_loss)
tf.losses.add_loss(noobject_loss)
tf.losses.add_loss(coord_loss)

###2 - 训练过程
#####1 - 预训练
在设计出图2的网络结构基础上,需要先基于imagenet的一个预训练,从而找到较好的初始值作为后面的对象检测。所以作者先将图2的前20层卷积层后面部分全部删除,然后加个平均池化层和一个全连接层。作者在imagenet 2012 上训练了1个礼拜,并在验证集上获得了top5 88%准确度。
#####2 - 将模型用于检测
在得到上述训练好的模型基础上,将后面的平均池化层和全连接层扔掉,接上4个卷积层和2个全连接层(权重都是随机初始化),然后将图片输入大小从224224调整到448448。为了好计算,所以只使用了平方函数,然后为了使得分类导致的惩罚和定位导致的惩罚程度有所不同,增加有对象基础上的定位误差,减少无对象的置信度;并且在大对象上的框误差的严重程度远小于小对象上的框误差程度,所以接着在$w,h$上使用了开根号。

object detection[YOLO]的更多相关文章

  1. 论文阅读笔记二十八:You Only Look Once: Unified,Real-Time Object Detection(YOLO v1 CVPR2015)

    论文源址:https://arxiv.org/abs/1506.02640 tensorflow代码:https://github.com/nilboy/tensorflow-yolo 摘要 该文提出 ...

  2. 读论文系列:Object Detection CVPR2016 YOLO

    CVPR2016: You Only Look Once:Unified, Real-Time Object Detection 转载请注明作者:梦里茶 YOLO,You Only Look Once ...

  3. [Localization] YOLO: Real-Time Object Detection

    Ref: https://pjreddie.com/darknet/yolo/ 关注点在于,为何变得更快? 论文笔记:You Only Look Once: Unified, Real-Time Ob ...

  4. YOLO object detection with OpenCV

    Click here to download the source code to this post. In this tutorial, you’ll learn how to use the Y ...

  5. 机器学习:YOLO for Object Detection (一)

    最近看了基于CNN的目标检测另外两篇文章,YOLO v1 和 YOLO v2,与之前的 R-CNN, Fast R-CNN 和 Faster R-CNN 不同,YOLO 将目标检测这个问题重新回到了基 ...

  6. Object Detection(RCNN, SPPNet, Fast RCNN, Faster RCNN, YOLO v1)

    RCNN -> SPPNet -> Fast-RCNN -> Faster-RCNN -> FPN YOLO v1-v3 Reference RCNN: Rich featur ...

  7. [YOLO]《You Only Look Once: Unified, Real-Time Object Detection》笔记

    一.简单介绍 目标检测(Objection Detection)算是计算机视觉任务中比较常见的一个任务,该任务主要是对图像中特定的目标进行定位,通常是由一个矩形框来框出目标. 在深度学习CNN之前,传 ...

  8. Object Detection︱RCNN、faster-RCNN框架的浅读与延伸内容笔记

    一.RCNN,fast-RCNN.faster-RCNN进化史 本节由CDA深度学习课堂,唐宇迪老师教课,非常感谢唐老师课程中的论文解读,很有帮助. . 1.Selective search 如何寻找 ...

  9. 论文学习-深度学习目标检测2014至201901综述-Deep Learning for Generic Object Detection A Survey

    目录 写在前面 目标检测任务与挑战 目标检测方法汇总 基础子问题 基于DCNN的特征表示 主干网络(network backbone) Methods For Improving Object Rep ...

随机推荐

  1. Windows 10文件夹Shirt+鼠标右键出现“在此处打开命令窗口”

    Windows 10文件夹Shirt+鼠标右键出现“在此处打开命令窗口” Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\Directo ...

  2. GDPR 和个人信息保护的小知识

    从2018年5月25日起,欧盟的<通用数据保护条例>(简称 GDPR,General Data Protection Regulation)开始强制施行.这个规范加强了对个人信息的保护,并 ...

  3. tsung HTTP协议统计报告分析

    tsung HTTP协议统计报告分析 by:授客 QQ:1033553122 1.   Main Static l  higest 10sec mean: 基于每10s的统计,最大耗时 l  lowe ...

  4. Retrieve OpenGL Context from Qt 5.5 on OSX

    In the latest Qt 5.5, the QOpenGLWidget is much better and has less bugs than the QGLWidget, but it ...

  5. ionic开发中,输入法键盘弹出遮挡住div元素

    采用ionic 开发中,遇到键盘弹出遮挡元素的问题. 以登陆页面为例,输入用户名和密码时,键盘遮挡了登陆按钮. 最终采用自定义指令解决了问题: .directive('popupKeyBoardSho ...

  6. [iOS]创建界面方法的讨论

    以前在入门的时候,找的入门书籍上编写的 demo 都是基于 Storyboards 拖界面的.后来接触公司项目,发现界面都是用纯代码去写复杂的 autoLayout 的.再然后,领导给我发了个 Mas ...

  7. [Objective-C]编程艺术 笔记整理

    看了<禅与 Objective-C 编程艺术>,发现不少平时不注意的或注意但没有系统总结的东西,特此记录一下. 这次没有整理完,后续更新会结合手里的一些其他资料整理. 新博客wossone ...

  8. python第一百零八天---Django 3 session 操作

    上节内容回顾: 1.请求周期 url> 路由 > 函数或类 > 返回字符串或者模板语言? Form表单提交: 提交 -> url > 函数或类中的方法 - .... Ht ...

  9. Android 自定义ListView单击事件失效

    因为自带的listView不能满足项目需求,通过实现自己的Adapter去继承ArrayAdapter 来实现自定义ListView的Item项目. 出现点击ListView的每一项都不会执行setO ...

  10. Python爬虫之Urllib库的基本使用

    # get请求 import urllib.request response = urllib.request.urlopen("http://www.baidu.com") pr ...