对于yolov2,我们首先输入图像为448x448,训练分类网络,在ImageNet上迭代10个epochs.这就使得网络有时间去调整其滤波其以更好地处理high resolution input.之后我们用该分类网络初始化我们的检测网络,精度提高大约4%mAP.
yolo直接从全连接层预测bounding box的坐标点.与直接预测坐标点不同,Faster R-CNN预测bounding box使用手动得到的先验(文献15).仅仅使用卷积层,Faster R-CNN中的RPN网络可以预测anchor box的偏移和置信度.由于预测层是可以卷积的,RPN在feature map的每个location预测anchor box的偏移.通过预测偏移而不是坐标点可以简化问题,并使得网络更容易学习.
我们移除yolo的全连接层,并使用anchor box预测bounding box.
首先,去除一个pooling layer以使网络的卷积层higher resolution输出.同时,缩小网络移除例416的输入图像而不是448x448.我们这样做事应为,我们在feature map中想得到奇数的location,从而只有一个center cell.
物体,特别是大物体,趋向于在图像的中心,因此对于预测这些物体,在中心有一个location是好的,而不是有在中心周围有四个location.yolo的卷积层通过参数32下采样图像,输入图像为416,我们便可以得到输出feature map为13x13.
对于anchor boxes,我们同样从空间location拆分类别预测机制,而不是对于每个anchor box都预测类别和物体.与yolo一样,物体检测仍然预测真实值的IOU,并且所得到的box和类别用于预测所给予的物体的类别的条件概率.
使用anchor boxes,我们可以得到一个小的精度下降.yolo对于每幅图像仅预测98 个boxes,但有anchor boxes时,我们的模型预测超过1000个boxes.没有anchor boxes,我们的中间模型得到69.5mAP,recall为81%.计时mAP下降,recall means的增长也是可以提升的.
我们使用yolo的时候,对于anchor boxes,我们遇到连个问题.
第一个问题就是box的维度是很难得到的.网络可以学会合理地调整boxed,但是如果我们选择更好的先验用于网络的开始,那么我们就可以使得网络更容易学习更好地检测物体.与手动选择先验不同,我们采用k-means聚类训练bounding boxes以自动得到好的先验.如果我们使用标准k-means,采用欧式距离,那么更大的boxes相比于更小的boxes会导致更多的额错误.然而,我们所想要的先验是可以得到好的IOU得分的先验,其是独立于box的大小的.因此我们使用下列具体矩阵:
我们取不同的k值进行k-means聚类,并画出average IOU与k的关系图,如图2所示. 我们选择k=5,以平衡模型复杂度和high recall.聚类中心即为anchor boxes.表1可以看出.聚类IOU效果更好.
第二个问题模型的稳定性,特别是在早起的迭代中.大多数稳定性问题是由于预测box的(x,y) location.在区域中,所提的网络可以预测值tx,ty,因此中心坐标点可以通过下式计算:
例如,预测值tx=1会通过anchor box的宽使得box往右移,而tx=-1,会使得其往左移同样的距离.
由于上述公式是无约束条件的,因此anchor box可以在图像的任何位置点,而不用考虑预测的box 的location在何处.通过随机初始化,模型花了很长一段时间达到稳定预测偏移值.
代替预测偏移值,我们采用yolo的方法,预测相对于grid cell的location 的location 候选点.者可以使ground truth值落于0到1之间.我们使用逻辑激活函数约束网络预测使得其出于该范围(0到1).
在每个输出feature map中,对于每个cell,网络预测5个bounding boxes.对于每个bounding box,网络预测5个候选点(location),分别为tx,ty,tw,th,to.如果该cell从图像的左上角偏移(cx,cy),那么bounding box先验有宽,高分别为pw,ph.这样预测对应为:
由于我们约束location 预测,使得网络参数更容易学习,网络也更稳定.使用方向上的维度聚类,预测bounding box的中心位置相比anchor box版的yolo改善了大约5%.
改善的yolo可以在13x13的feature map中预测方向.尽管这对于大的物体是足够的,但是如果改善特征没那么也可以在小的物体上取得好的效果.Faster R-CNN和SSD都在可变的feature map上运行proposal network,以得到resolution的范围.我们采用一个不同的方案,仅仅添加passthrough 层,这个层可以可以从他前面的层获得特征,为26x26 resolution.
passthrough 层通过堆放相邻的特征到不同的通道而不是spatial location,来串联higher resolution特征和low resolution特征,这种方法类似于ResNet中的身份映射(identity mappings).这样就将26x26x512的feature map转换为13x13x2048大小的feature map,这样该feature mao就可以与原始的特征串联.我们的检测运行在这个扩充的feature map上,因而其可以获得更好的特征.这大概可以提高1%的效果
原始的yolo对输入224x224的图像high resolution为448x448,我们添加了anchor box,改变resolution为416x416.然而,由于我们的模型仅仅使用卷积和池化层,也可以对其resize.
我们希望yolov2可以快速地处理不同大小的图像,因此,我们训练这个模块到模型中.
代替固定输入图像的大小,我们每几次迭代就改变网络.每10个baches,网络随机悬着一个新的图像维度大小.由于模型下采样系数为32,我们采用32的倍数,{320,352,...,608}.这样最小的high resolution大小为320x320,最大的为608x608.我们resize 网络为这些维度,并继续训练.
这个策略就可以迫使网络可以学会预测对于不同大小的输入图像.这也意味着同一个网络可以检测不同分辨率的物体.对于小的图像,网络运行速度更快,因此yolov2使得速度和进度都达到了.
处理228x228的输入图像,需要90FPS ,几乎和Fast R-CNN一样好.这使得岂可以用于视频处理.
对于高分辨率输入图像,yolov2为state of the art 检测,在VOC 2007上精度为78.6mAP ,并且速度也在实时上.相关对比见表3.
我们希望检测高精度且速度快,大多数检测应用,像自动驾驶机器人,依赖于低延迟预测.为了最大化效果,我们设计yolo2尽量快.
大多数检测框架将VGG-16作为基础的特征提取,VGG16是一个功能强大的,精度高的分类网络,但是他复杂度高,这是,没有必要的.对于一张224x224的图像的一个通道,VGG16的卷积层需要30.69 billion浮点操作.yolo架构使用传统的网络,基于Googlenet 结构(文献19),这个网络比VGG16更快,然而精度比VGG16稍微低一点.top5的224x224的精度,yolo的传统网络为88%,ImageNet(VGG16)为90%.
我们提出了一个新的分类模型,以用于yolov2的基础网络.与VGG模型类是,我们大多数使用3x3的滤波器,并在每个池化层的后面,将通道扩充为双倍.采用Network in Network(NIN)的方法,我们使用全局平均池化,同时使用1x1滤波来压缩3x3卷积的特征表示(文献9).我们使用batch normalization稳定训练,加速收敛,规则化模型(文献7).
我们的最后模型,称做Darknet-19,有19个卷积层和5个最大池化层,具体见table6.
Darknet-19只需要5.58 billion的计算量,在ImageNet上精度为top-1,72.9%;top-5,91.2%.
我们迭代160 epoches,在标准的ImageNet 1000类别分类数据上训练分类网络,采用sgd,学习率0,1,polynomial rate decay为4,weight decay 为0.0005,momentum0.9 训练Darknet neural network framework网络(文献13).训练的时候,我们使用标准的数据增强策略,包括随机裁剪,旋转,色调,饱和度和曝光.输入图像大小为224x224.
训练好后,为了改善网络效果,我们high resolution 图像为448x448大小,迭代10个epoch,学习率为0.001.通过这个high resolution图像训练,网络实现精度,top-1, 76.5%.top-5, 93.3%.
我们通过移除最后的一个卷积层并用3x3卷积层,1024滤波器,加上1x1卷积层代替他,得到检测输出.
对于VOC,我们预测5个boxes,每个box有5个坐标掉,20个类别,因此需要125 个滤波器.我们同样添加一个passthrough 层到最后的3x3x512和倒数第二个卷积层之间,以便模型可以使用更好的特征.
我们训练网络,160 epoch,开始学习率为0.001,60,90 epoch后学习率除以10.
我们提出了一个机制,用于联合训练分类和检测数据.我们的方法是使用标定好的检测图像来学习检测特殊的信息,例如bounding box坐标预测,物体,以及怎样分类普遍的物体.该机制使用图像,仅有类别标签,并扩充可以检测的物体类别.
训练的时候,我们混合检测和分类数据.当网络输入为标记为检测的图像是,我们可以后向传播,这基于整个yolov2 损失函数.当我们输入图像标记为分类,我们仅仅后向传播来自于分类的损失函数.
这个算法也带来了几项挑战.检测数据仅仅包含普通的物体和常见的label,例如dog 或者boat. 分裂数据相对来说标记类别更多,更广,包括“Norfolk terrier”, “Yorkshire terrier”, and “Bedlington terrier”等.
ImageNet有超过100中的dog,如果我们训练他们,我们需要将标签进行合并.
大多数分类算法使用softmax层处理素有可能的类别,以计算最后的类别概率.使用softmax 是假设类别之间是相互不包含的,这就使得合并数据带来问题,例如,你不会不想合并ImageNet 和COCO,这是因为“Norfolk terrier” and “dog”不是互不包含的,因为“Norfolk terrier” 包含于“dog”.
我们可以使用一个多标签模型来结合数据,这不用考虑数据是否相互独立.这个方法就可以忽略数据是否包含.
ImageNet标签采用WordNet的形式,使用一个语言图结构表示数据关系(文献12).
我们使用一个hirarchical 树建立树结构数据,预测每个类别的概率,例如有:
对于树中的每个结点的概率,可以依次乘以该root node上的所有的条件概率.
数据合并例子如下:
这样,当输入带有分类标记的图像是,我们仅仅后向传导分类损失函数.为了这样做,我们仅仅寻找可以预测类别最大概率的bounding box,并计算该类别的预测树上的损失函数.我们同样假设假设预测box与ground truth box存在至少0.3 IOU的重叠,我们基于此后向传播物体损失函数.
和这个联合训练,训练检测数据COCO,yolo9000学会寻找图像中的物体,训练ImageNet则学会分类各种各样的物体.
我们在ImageNet检测任务上评测yolo9000模型,ImageNet的检测任务为COCO,44个物体类别,这意味着yolo9000仅仅遇到了测试数据中的分类数据,而没有检测数据.yolo9000得到整体上得到19.7mAP,16.0mAP为非联合的156物体类别,而模型没有遇到任何标记的检测数据.DPM上永不分监督训练yolo9000mAP,得到一个更高的mAP值.该模型同样能同时检测9000个其他物体类别,而且都是实时.
当我们在ImageNet上分析yolo9000的性能是,我们发现模型能很好的回到新的物种的动物,但同时有很难会到布料,设备等.新的动物是很容易学到的,这是因为在COCO数据集中,动物类别很多,相反,COCO没有任何关于布料的label 的bounding box,因此yolo9000检测像sunglasses,suimming trunks.
darknet提供了yolo,yolo9000的训练代码,配置文件分别为darknet/cfg/yolo.cfg,darknet/cfg/yolo9000.cfg,其中yolo为80个类别,yolo9000为9418个类别.
为了便于理解网络结构,贴出yolo9000.cfg文件:
[net]
# Testing
batch=1
subdivisions=1
# Training
# batch=64
# subdivisions=8
batch=1
subdivisions=1
height=544
width=544
channels=3
momentum=0.9
decay=0.0005
learning_rate=0.001
burn_in=1000
max_batches = 500200
policy=steps
steps=400000,450000
scales=.1,.1
hue=.1
saturation=.75
exposure=.75
[convolutional]
batch_normalize=1
filters=32
size=3
stride=1
pad=1
activation=leaky
[maxpool]
size=2
stride=2
[convolutional]
batch_normalize=1
filters=64
size=3
stride=1
pad=1
activation=leaky
[maxpool]
size=2
stride=2
[convolutional]
batch_normalize=1
filters=128
size=3
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=64
size=1
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=128
size=3
stride=1
pad=1
activation=leaky
[maxpool]
size=2
stride=2
[convolutional]
batch_normalize=1
filters=256
size=3
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=128
size=1
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=256
size=3
stride=1
pad=1
activation=leaky
[maxpool]
size=2
stride=2
[convolutional]
batch_normalize=1
filters=512
size=3
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=256
size=1
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=512
size=3
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=256
size=1
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=512
size=3
stride=1
pad=1
activation=leaky
[maxpool]
size=2
stride=2
[convolutional]
batch_normalize=1
filters=1024
size=3
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=512
size=1
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=1024
size=3
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=512
size=1
stride=1
pad=1
activation=leaky
[convolutional]
batch_normalize=1
filters=1024
size=3
stride=1
pad=1
activation=leaky
[convolutional]
filters=28269
size=1
stride=1
pad=1
activation=linear
[region]
anchors = 0.77871, 1.14074, 3.00525, 4.31277, 9.22725, 9.61974
bias_match=1
classes=9418
coords=4
num=3
softmax=1
jitter=.2
rescore=1
object_scale=5
noobject_scale=1
class_scale=1
coord_scale=1
thresh = .6
absolute=1
random=1
tree=data/9k.tree
map = data/coco9k.map