YOLO算法:从v1到v3

近几年来,目标检测算法取得了很大的突破。比较流行的算法可以分为两类,一类是基于Region Proposal的R-CNN系算法(R-CNN,Fast R-CNN, Faster R-CNN),它们是two-stage的,需要先使用启发式方法(selective search)或者CNN网络(RPN)产生Region Proposal,然后再在Region Proposal上做分类与回归。而另一类是Yolo,SSD这类one-stage算法,其仅仅使用一个CNN网络直接预测不同目标的类别与位置。第一类方法是准确度高一些,但是速度慢,但是第二类算法是速度快,但是准确性要低一些。本文首先介绍的是Yolo1算法,其全称是You Only Look Once: Unified, Real-Time Object Detection,题目基本上把Yolo算法的特点概括全了:You Only Look Once说的是只需要一次CNN运算,Unified指的是这是一个统一的框架,提供end-to-end的预测,而Real-Time体现是Yolo算法速度快,达到实时。这个题目是Yolo-v1论文的,其性能是差于后来的SSD算法的,但是Yolo后来也继续进行改进,产生了Yolo9000算法,和Yolov3。
检测对于计算机视觉中就是检测到目标物的位置,而识别则是说,对检测到的这个东西,你告诉我这是属于哪一类,比如说检测到一只狗,你要告诉我这只狗是京巴还是藏獒。那么目标检测到底有什么用途呢?举个例子:比如在无人车上安装一个障碍物检测系统,那么无人车的摄像头就相当于人的眼睛,当捕捉到画面前方有障碍物时,要得到障碍物的具体位置和类别,以便及时作出决策。
为了理解yolo,首先先介绍一下滑动窗口技术。采用滑动窗口的目标检测算法思路非常简单,它将检测问题转化为了图像分类问题。其基本原理就是采用不同大小和比例(宽高比)的窗口在整张图片上以一定的步长进行滑动,然后对这些窗口对应的区域做图像分类(应该是在学习这个东西是目标物还是背景)如下图所示。但是你并不知道要检测的目标大小是什么规模,所以你要设置不同大小和比例的窗口去滑动,而且还要选取合适的步长,这样会产生很多的子区域,并且都要经过分类器去做预测,这需要很大的计算量,所以你的分类器不能太复杂,因为要保证速度。解决思路之一就是减少要分类的子区域,这就是R-CNN(基于区域提名的CNN)的一个改进策略,其采用了selective search方法来找到最有可能包含目标的子区域(Region Proposal),其实可以看成采用启发式方法过滤掉很多子区域,这会提升效率。


image

yolo设计理念
整体来看,Yolo算法采用一个单独的CNN模型实现end-to-end的目标检测,首先将输入图片resize到448x448,然后送入CNN网络,最后处理网络预测结果得到检测的目标。其速度更快,而且Yolo的训练过程也是端到端的。与滑动窗口不同的是,yolo先将图片分成SS个块。每个单元格会预测B个边界框(bounding box)以及边界框的置信度(confidence score)。所谓置信度其实包含两个方面,一是这个框中目标存在的可能性大小,二是这个边界框的位置准确度。前者我们把它记做Pr(obj),若框中没有目标物,则Pr(obj)=0,若含有目标物则Pr(obj)=1 。那么边界框的位置的准确度怎么去判断呢?我们使用了一种叫做IOU(交并比)的方法,意思就是说我预测的框与你真实的框相交的面积,和预测的框与真实框合并的面积的比例。我们可以记做IOU(pred),那么置信度就可以定义为这两项相乘。so,现在有了另一个问题,我每个格子预测的边界框应该怎么表示呢? 边界框的大小和位置可以用四个值来表示,(x,y,w,h)注意,不要凭空想象是一个矩形对角两个点的位置坐标,这里面的x,y是指预测出的边界框的中心位置相对于这个格子的左上角位置的偏移量,而且这个偏移量不是以像素为单位,而是以这个格子的大小为一个单位。如果不明白可以用下面这张图去举个例子。下面这个框的中心点所在的位置,相对于中心点所在的这个格子的x,y差不多是0.3, 0.7, (不明白的话就仔细琢磨一下)。而这个w,h指的是这个框的大小,占整张图片大小的宽和高的相对比例,想一下,有了中心点的位置,有了框的大小,画出一个框是很容易的对吧。(x,y,w,h,c)这五个值理论上都应该在[0,1]区间上。最后一个c是置信度的意思。一般一个网格会预测多个框,而置信度是用来评判哪一个框是最准确的,我们最想得到的框。

image

框预测好了,接下来就是分类的问题,每个单元格预测出(x,y,w,h,c)的值后,还要给出对于C个类别的概率值。现在重新提一下字母的含义,B是边界框的个数,C是我有多少个类别要分类。S是我怎么划分单元格。那么我每个单元格要预测B
5+C个值。如果将输入图片划分为S×S网格,那么最终预测值为S×S×(B∗5+C)大小的张量。

网络模型:


image

对于卷积层和全连接层,采用Leaky ReLU激活函数:max(x,0.1x)max(x,0.1x)。最后一层采用线性激活函数。

可以看到网络的最后输出为7×7×30大小的张量。这和前面的讨论是一致的。这个张量所代表的具体含义如下图所示。对于每一个单元格,前20个元素是类别概率值,然后2个元素是边界框置信度,两者相乘可以得到类别置信度,最后8个元素是边界框的(x,y,w,h)。大家可能会感到奇怪,对于边界框为什么把置信度c和(x,y,w,h)都分开排列,而不是按照(x,y,w,h,c)这样排列,其实纯粹是为了计算方便,因为实际上这30个元素都是对应一个单元格,其排列是可以任意的。但是分离排布,可以方便地提取每一个部分。这里来解释一下,首先网络的预测值是一个二维张量PP,其shape为[batch,7×7×30]。采用切片,那么就是类别概率部分,而是置信度部分,最后剩余部分是边界框的预测结果。这样,提取每个部分是非常方便的,这会方面后面的训练及预测时的计算。

image

下面是训练损失函数的分析,Yolo算法将目标检测看成回归问题,采用的是均方差损失函数。但是对不同的部分造成的误差采用了不同的权重值。还有一点就是较小的边界框的坐标误差应该要比较大的边界框要更敏感。为了保证这一点,将网络的边界框的宽与高预测改为对其平方根的预测,即预测值变为,为什么呢?因为你想一下比如w和h为0.1或者更小,那么我稍微一点点的幅度,我这个框变化就很明显。比如我从0.1到0.15,这个变化相对于0.1增加很多,但是同样的我预测有误差,而误差是从0.4到0.45,这个增大几乎是看不出来的。因此对于一个小框,如果我偏移大的话,会更加影响框的准确性,有可能因为我这一个小小的偏移,导致我这个物体不再框里面了,所以这就是为什么要让小得边界框的误差比大的边界框误差要更加敏感。通过开根号可以达到这个效果,因为一个小于一的数,开平方会被放大,而且越小,开平方后相比原来的数差别就更大。(如果不理解这一点可以慢慢思考一下,或者跳过也没关系)
————————————————


image

其中第一项是边界框中心坐标的误差项,指的是第 i 个单元格存在目标,且该单元格中的第 j 个边界框负责预测该目标。第二项是边界框的高与宽的误差项。第三项是包含目标的边界框的置信度误差项。第四项是不包含目标的边界框的置信度误差项。而最后一项是包含目标的单元格的分类误差项,指的是第 i 个单元格存在目标。

当然这其中还用到了另一种机制,叫做NMS(non maximum suppression)非极大值抑制算法。NMS算法主要解决的是一个目标被多次检测的问题。这个机制不是针对YOLO的,而是对于各种检测算法都有用到。就比如说YOLO,yolo-v1预测了两个边界框,但是我检测的时候总不能把两个框都画上去吧,因此我只取概率值最大的那个框,这就叫做非极大值抑制,除了极大概率的那个框,别的我丢弃。

image

YOLO的缺点

1.YOLO对相互靠的很近的物体,还有很小的群体 检测效果不好,这是因为一个网格中只预测了两个框,并且只属于一类。

2.同一类物体出现的新的不常见的长宽比和其他情况时,泛化能力偏弱。

3.由于损失函数的问题,定位误差是影响检测效果的主要原因。尤其是大小物体的处理上,还有待加强。

yolo-v2的改进
Batch Normalization
CNN在训练过程中网络每层输入的分布一直在改变, 会使训练过程难度加大,但可以通过normalize每层的输入可以解决这个问题。新的YOLO网络在每一个卷积层后添加batch normalization,通过这一方法,mAP(精度)获得了2%的提升。batch normalization 也有助于规范化模型,可以在舍弃dropout优化后依然不会过拟合。
High Resolution Classifier
目前的目标检测方法中,基本上都会使用ImageNet预训练过的模型(classifier)来提取特征,如果用的是AlexNet网络,那么输入图片会被resize到不足256 * 256,导致分辨率不够高,给检测带来困难。为此,新的YOLO网络把分辨率直接提升到了448 * 448,这也意味之原有的网络模型必须进行某种调整以适应新的分辨率输入。
对于YOLOv2,作者首先对分类网络(自定义的darknet)进行了微调,分辨率改成448 * 448,在ImageNet数据集上训练10轮(10 epochs),训练后的网络就可以适应高分辨率的输入了。然后,作者对检测网络部分(也就是后半部分)也进行微调。这样通过提升输入的分辨率,mAP(精度)获得了4%的提升。
Convolutional With Anchor Boxes
之前的YOLO利用全连接层的数据完成边框的预测,导致丢失较多的空间信息,定位不准。作者在这一版本中借鉴了Faster R-CNN中的anchor思想,回顾一下,anchor是RPN网络中的一个关键步骤,说的是在卷积特征图上进行滑窗操作,每一个中心可以预测9种不同大小的建议框。

image

而yolo-v3则是将格子划分的更细了一些从1313细化到了1919,每个框预测3个框,在一定程度上缓解了小目标检测不到的问题以及多个框重叠在一起只能画出一个框的问题。细节请去阅读论文。

对于yolo,官方给出了使用darknet框架训练的压缩包。但是使用darknet框架训练,难以理解其中的细节了,调试起来非常困难,对于darknet,我做到的只能是做出训练数据,然后把数据丢进网络进行训练,完全没有tensorflow的那种运算框架非常清晰地感觉。(甚至找不到darknet训练网络的时候损失函数定义在哪里。)之后我可以给出一个用darknet训练yolo的具体步骤,但是我还是想去用tensorflow或者keras训练自己的数据。在tensorflow或者keras的train.py文件中可以清晰地看出逻辑关系。
yolo_v3是我最近一段时间主攻的算法,写下博客,以作分享交流。

yolo_v3作为yolo系列目前最新的算法,对之前的算法既有保留又有改进。先分析一下yolo_v3上保留的东西:

“分而治之”,从yolo_v1开始,yolo算法就是通过划分单元格来做检测,只是划分的数量不一样。
采用"leaky ReLU"作为激活函数。
端到端进行训练。一个loss function搞定训练,只需关注输入端和输出端。
从yolo_v2开始,yolo就用batch normalization作为正则化、加速收敛和避免过拟合的方法,把BN层和leaky relu层接到每一层卷积层之后。
多尺度训练。在速度和准确率之间tradeoff。想速度快点,可以牺牲准确率;想准确率高点儿,可以牺牲一点速度。

image

yolo每一代的提升很大一部分决定于backbone网络的提升,从v2的darknet-19到v3的darknet-53。yolo_v3还提供替换backbone——tiny darknet。要想性能牛叉,backbone可以用Darknet-53,要想轻量高速,可以用tiny-darknet。总之,yolo就是天生“灵活”,所以特别适合作为工程算法。
当然,yolo_v3在之前的算法上保留的点不可能只有上述几点。由于本文章主要针对yolo_v3进行剖析,不便跑题,下面切入正题。
为了让yolo_v3结构图更好理解,我对图1做一些补充解释:
DBL: 如图1左下角所示,也就是代码中的Darknetconv2d_BN_Leaky,是yolo_v3的基本组件。就是卷积+BN+Leaky relu。对于v3来说,BN和leaky relu已经是和卷积层不可分离的部分了(最后一层卷积除外),共同构成了最小组件。
resn:n代表数字,有res1,res2, … ,res8等等,表示这个res_block里含有多少个res_unit。这是yolo_v3的大组件,yolo_v3开始借鉴了ResNet的残差结构,使用这种结构可以让网络结构更深(从v2的darknet-19上升到v3的darknet-53,前者没有残差结构)。对于res_block的解释,可以在图1的右下角直观看到,其基本组件也是DBL。
concat:张量拼接。将darknet中间层和后面的某一层的上采样进行拼接。拼接的操作和残差层add的操作是不一样的,拼接会扩充张量的维度,而add只是直接相加不会导致张量维度的改变。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容