YOLO

YOLO核心思想:从R-CNN到Fast R-CNN一直采用的思路是proposal+分类 (proposal 提供位置信息, 分类提供类别信息)精度已经很高,但是速度还不行。 YOLO提供了另一种更为直接的思路: 直接在输出层回归bounding box的位置和bounding box所属的类别(整张图作为网络的输入,把 Object Detection 的问题转化成一个 Regression 问题)。

YOLO的主要特点:

  • 速度快,能够达到实时的要求。在 Titan X 的 GPU 上 能够达到 45 帧每秒。
  • 使用全图作为 Context 信息,背景错误(把背景错认为物体)比较少。
  • 泛化能力强。

大致流程:

  1. Resize成448*448,图片分割得到7*7网格(cell)
  2. CNN提取特征和预测:卷积不忿负责提特征。全链接部分负责预测:a) 7*7*2=98个bounding box(bbox) 的坐标

 和是否有物体的confidence 。  b) 7*7=49个cell所属20个物体的概率。

  1. 过滤bbox(通过nms)

网络设计:

网络结构借鉴了 GoogLeNet 。24个卷积层,2个全链接层。(用1×1 reduction layers 紧跟 3×3 convolutional layers 取代Goolenet的 inception modules )

训练:

预训练分类网络: 在 ImageNet 1000-class competition dataset上预训练一个分类网络,这个网络是Figure3中的前20个卷机网络+average-pooling layer+ fully connected layer (此时网络输入是224*224)。

训练检测网络:转换模型去执行检测任务,《Object detection networks on convolutional feature maps》提到说在预训练网络中增加卷积和全链接层可以改善性能。在他们例子基础上添加4个卷积层和2个全链接层,随机初始化权重。检测要求细粒度的视觉信息,所以把网络输入也又224*224变成448*448。见Figure3。 

  • 一幅图片分成7x7个网格(grid cell),某个物体的中心落在这个网格中此网格就负责预测这个物体。
  • 最后一层输出为 (7*7)*30的维度。每个 1*1*30的维度对应原图7*7个cell中的一个,1*1*30中含有类别预测和bbox坐标预测。总得来讲就是让网格负责类别信息,bounding box主要负责坐标信息(部分负责类别信息:confidence也算类别信息)。具体如下:
    • 每个网格(1*1*30维度对应原图中的cell)要预测2个bounding box (图中黄色实线框)的坐标(

    ,w,h) ,其中:中心坐标的

     相对于对应的网格归一化到0-1之间,w,h用图像的width和height归一化到0-1之间。 每个bounding box除了要回归自身的位置之外,还要附带预测一个confidence值。 这个confidence代表了所预测的box中含有object的置信度和这个box预测的有多准两重信息:confidence = 

    。其中如果有ground true box(人工标记的物体)落在一个grid cell里,第一项取1,否则取0。 第二项是预测的bounding box和实际的ground truth box之间的IOU值。即:每个bounding box要预测 

    ,共5个值 ,2个bounding box共10个值,对应 1*1*30维度特征中的前10个。

    • 每个网格还要预测类别信息,论文中有20类。7x7的网格,每个网格要预测2个 bounding box 和 20个类别概率,输出就是 7x7x(5x2 + 20) 。 (通用公式: SxS个网格,每个网格要预测B个bounding box还要预测C个categories,输出就是S x S x (5*B+C)的一个tensor。 注意:class信息是针对每个网格的,confidence信息是针对每个bounding box的)

损失函数设计:

损失函数的设计目标就是让坐标(x,y,w,h),confidence,classification 这个三个方面达到很好的平衡。简单的全部采用了sum-squared error loss来做这件事会有以下不足: a) 8维的localization error和20维的classification error同等重要显然是不合理的; b) 如果一个网格中没有object(一幅图中这种网格很多),那么就会将这些网格中的box的confidence push到0,相比于较少的有object的网格,这种做法是overpowering的,这会导致网络不稳定甚至发散。 解决方案如下:

  • 更重视8维的坐标预测,给这些损失前面赋予更大的loss weight, 记为 

 ,在pascal VOC训练中取5。(上图蓝色框)

  • 对没有object的bbox的confidence loss,赋予小的loss weight,记为 

 ,在pascal VOC训练中取0.5。(上图橙色框)

  • 有object的bbox的confidence loss (上图红色框) 和类别的loss (上图紫色框)的loss weight正常取1。
  • 对不同大小的bbox预测中,相比于大bbox预测偏一点,小box预测偏一点更不能忍受。而sum-square error loss中对同样的偏移loss是一样。 为了缓和这个问题,作者用了一个比较取巧的办法,就是将box的width和height取平方根代替原本的height和width。 如下图:small bbox的横轴值较小,发生偏移时,反应到y轴上的loss(下图绿色)比big box(下图红色)要大。
  • 一个网格预测多个bounding box,在训练时我们希望每个object(ground true box)只有一个bounding box专门负责(一个object 一个bbox)。具体做法是与ground true box(object)的IOU最大的bounding box 负责该ground true box(object)的预测。这种做法称作bounding box predictor的specialization(专职化)。每个预测器会对特定(sizes,aspect ratio or classed of object)的ground true box预测的越来越好。(个人理解:IOU最大者偏移会更少一些,可以更快速的学习到正确位置)

测试:

Test的时候,每个网格预测的class信息( 

 )和bounding box预测的confidence信息( 

 ) 相乘,就得到每个bounding box的class-specific confidence score。

    • 等式左边第一项就是每个网格预测的类别信息,第二三项就是每个bounding box预测的confidence。这个乘积即encode了预测的box属于某一类的概率,也有该box准确度的信息。
    • 对每一个网格的每一个bbox执行同样操作: 7x7x2 = 98 bbox (每个bbox既有对应的class信息又有坐标信息)
  • 得到每个bbox的class-specific confidence score以后,设置阈值,滤掉得分低的boxes,对保留的boxes进行NMS处理,就得到最终的检测结果。 

缺陷:

  • YOLO对相互靠的很近的物体(挨在一起且中点都落在同一个格子上的情况),还有很小的群体 检测效果不好,这是因为一个网格中只预测了两个框,并且只属于一类。
  • 测试图像中,当同一类物体出现的不常见的长宽比和其他情况时泛化能力偏弱。
  • 由于损失函数的问题,定位误差是影响检测效果的主要原因,尤其是大小物体的处理上,还有待加强。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Hongten

ArrayList VS Vector(ArrayList和Vector的区别)_面试的时候经常出现

2442
来自专栏拭心的安卓进阶之路

Java 集合深入理解(6):AbstractList

今天心情比天蓝,来学学 AbstractList 吧! ? 什么是 AbstractList ? AbstractList 继承自 AbstractCollec...

20910
来自专栏xingoo, 一个梦想做发明家的程序员

20120918-向量实现《数据结构与算法分析》

#include <iostream> #include <list> #include <string> #include <vector> #include...

1906
来自专栏xingoo, 一个梦想做发明家的程序员

AOE关键路径

这个算法来求关键路径,其实就是利用拓扑排序,首先求出,每个节点最晚开始时间,再倒退求每个最早开始的时间。 从而算出活动最早开始的时间和最晚开始的时间,如果这两个...

2657
来自专栏MelonTeam专栏

ArrayList源码完全分析

导语: 这里分析的ArrayList是使用的JDK1.8里面的类,AndroidSDK里面的ArrayList基本和这个一样。 分析的方式是逐个API进行解析 ...

4809
来自专栏alexqdjay

HashMap 多线程下死循环分析及JDK8修复

1.2K4
来自专栏xingoo, 一个梦想做发明家的程序员

Spark踩坑——java.lang.AbstractMethodError

百度了一下说是版本不一致导致的。于是重新检查各个jar包,发现spark-sql-kafka的版本是2.2,而spark的版本是2.3,修改spark-sql-...

1300
来自专栏开发与安全

算法:AOV网(Activity on Vextex Network)与拓扑排序

在一个表示工程的有向图中,用顶点表示活动,用弧表示活动之间的优先关系,这样的有向图为顶点表示活动的网,我们称之为AOV网(Activity on Vextex ...

4087
来自专栏拭心的安卓进阶之路

Java 集合深入理解(12):古老的 Vector

今天刮台风,躲屋里看看 Vector ! 都说 Vector 是线程安全的 ArrayList,今天来根据源码看看是不是这么相...

2547
来自专栏Java Edge

AbstractList源码解析1 实现的方法2 两种内部迭代器3 两种内部类3 SubList 源码分析4 RandomAccessSubList 源码:AbstractList 作为 Lis

它实现了 List 的一些位置相关操作(比如 get,set,add,remove),是第一个实现随机访问方法的集合类,但不支持添加和替换

632

扫码关注云+社区