第一部分: 论文与代码
论 文:https://pjreddie.com/media/files/papers/YOLOv3.pdf
翻 译:https://zhuanlan.zhihu.com/p/34945787
代 码:https://github.com/pjreddie/darknet
官 网:https://pjreddie.com/darknet/yolo
旧 版:
https://pjreddie.com/darknet/yolov2/
https://pjreddie.com/darknet/yolov1/
第二部分: 如何训练自己的数据
说明:
(1)平台 linux + 作者官方代码
(2)为了方便大家学习,这里提供了182张训练数据、标注以及对应的配置文件,数据是4类【人,车头,车尾,车侧身】:
(忘记上传training_list.txt了,就是所有标注文件对应的图片路径,自己弄一下就行了)
训练自己的数据主要分以下几步:
(0)数据集制作:
A.制作VOC格式的xml文件
工具:LabelImg
B.将VOC格式的xml文件转换成YOLO格式的txt文件
脚本:voc_label.py,根据自己的数据集修改就行了。
(1)文件修改:
(A)关于 .data .names 两个文件修改非常简单,参考官网或者我上面链接中的对应文件。
(B)关于cfg修改,以6类目标检测为例,主要有以下几处调整(蓝色标出),也可参考我上传的文件,里面对应的是4类。
[net]
# Testing
# batch=1
# subdivisions=1
# Training
batch=64 subdivisions=8
......
[convolutional]
size=1
stride=1
pad=1
filters=33###75
activation=linear
[yolo]
mask = 6,7,8
anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326
classes=6###20
num=9
jitter=.3
ignore_thresh = .5
truth_thresh = 1
random=0###1
......
[convolutional]
size=1
stride=1
pad=1
filters=33###75
activation=linear
[yolo]
mask = 3,4,5
anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326
classes=6###20
num=9
jitter=.3
ignore_thresh = .5
truth_thresh = 1
random=0###1......
[convolutional]
size=1
stride=1
pad=1
filters=33###75
activation=linear
[yolo]
mask = 0,1,2
anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326
classes=6###20
num=9
jitter=.3
ignore_thresh = .5
truth_thresh = 1
random=0###1
A.filters数目是怎么计算的:3x(classes数目+5),和聚类数目分布有关,论文中有说明;
B.如果想修改默认anchors数值,使用k-means即可,稍候提供;
C.如果显存很小,将random设置为0,关闭多尺度训练;
D.其他参数如何调整,抽空再补充;
E.前100次迭代loss较大,后面会很快收敛;
F.模型测试:
6类测试效果
4类的测试效果,182张迭代900次时的检测效果。
H.如果训练还有问题或其他疑问,请参考第三部分或者网络搜索。
I.如何测试以及测试中的问题,请参考第四部分或者网络搜索。
第三部分:训练问题详解
Tips0: 数据集问题
如果是学习如何训练,建议不要用VOC或者COCO,这两个数据集复杂,类别较多,复现作者的效果需要一定的功力,迭代差不多5w次,就可以看到初步的效果。所以,不如挑个简单数据集的或者手动标注个几百张就可以进行训练学习。
Tips1: CUDA: out of memory 以及 resizing 问题
显存不够,调小batch,关闭多尺度训练:random = 0。
Tips2: 在迭代前期,loss很大,正常吗?
经过几个数据集的测试,前期loss偏大是正常的,后面就很快收敛了。
Tips3: YOLOV3中的mask作用?
参考#558 #567
Every layer has to know about all of the anchor boxes but is only predicting some subset of them. This could probably be named something better but the mask tells the layer which of the bounding boxes it is responsible for predicting. The first yolo
layer predicts 6,7,8 because those are the largest boxes and it's at the coarsest scale. The 2nd yolo
layer predicts some smallers ones, etc.
The layer assumes if it isn't passed a mask that it is responsible for all the bounding boxes, hence the if
statement thing.
Tips3: YOLOV3中的num作用?
#参考567
num 是 9,但是每个yolo层实际上只预测3个由mask定义的anchors。所以是 (20+1+4)*3 = 75.如果你使用了不同数量的anchors你需要支出你想要预测哪一层的那几个anchors,并且这个filter的数量取决于分布.
根据作者的文章每个yolo (detection)层获取 3 个和他的尺寸size相关的anchors, mask就是selected anchor 的indices。
Tips4: YOLOV3训练出现nan的问题?
参考#566
你移动是在一些小物体上面训练! nan's appear when there are no objects in a batch of images since i definitely divide by zero. For example, Avg IOU is the sum of IOUs for all objects at that level / # of objects, if that is zero you get nan. I could probably change this so it just does a check for zero 1st, just wasn't a priority.
所以在显存允许的情况下,可适当增加batch大小,可以一定程度上减少NAN的出现。
Tips5: Anchor box作用是?
参考#568
在真实标签(ground truth label)上进行聚类之后 ,发现大多数bbox有固定的长宽比例(certain height-width ratios).所以yolov2和v3并没有直接预测一个bbox,而失去预测有特定长宽比的预定义的一组box的off-sets(这些预定义的盒子就是anchor boxes) predetermined set of boxes are the anchor boxes.
Anchors初始化 (width, height), 其中一些 (最接近物体大小的)anchor box的大小将会被resized 为物体的大小( 使用一些神经网络 (final feature map)的输出):
Lines 88 to 89 in 6f6e475
b.w = exp(x[index + 2*stride]) * biases[2*n] / w;
b.h = exp(x[index + 3*stride]) * biases[2*n+1] / h;
x[...]
- 神经网络的输出biases[...]
- anchorsb.w
和b.h
将要在image上画出的bounding box的长和宽
因此,这个网络应该预测物体最终的大小,但是只应该调节与物体大小最接近的anchor的大小为物体大小
Yolo v3 中anchors (width, height) - are sizes of objects on the image that resized to the network size (width=
and height=
in the cfg-file).
Yolo v2 anchors (width, height) - are sizes of objects relative to the final feature map (比yolo v3中cfg默认的小32倍).
Tips6: YOLOv2和YOLOv3中anchor box为什么相差很多?
参考#562 #555
anchors取决于网络输入的大小而不是网络输出的大小 (final-feature-map): #555 (comment) 所以anchors的值是之前的32倍.
filters=(classes+1+coords)*anchors_num
anchors_num 是该层mask
的一个值.如果没有mask
则 anchors_num = num
是这层的anchor
Lines 31 to 37 in e4acba6
if(mask)
l.mask = mask;
else{
l.mask = calloc(n, sizeof(int));
for(i = 0; i < n; ++i){
l.mask[i] = i;
}
}
[yolo]
层只使用mask中定义的anchors,所以作者YOLOv2 的设计有问题,作者让anchor box的大小和最后一层特征图的大小相关. 由于网络是经过下采样(32)的,也就是说anchor box实际上是和32 pixel有联系的,所以 9x9的anchor实际上是 288px x 288px.
YOLOv3的 anchor大小实际上是像素值.这简化了许多工作并且实现起来有点困难。
Tips7: YOLOv3打印的参数都是什么含义?
详见yolo_layer.c文件的forward_yolo_layer函数。
printf("Region %d Avg IOU: %f, Class: %f, Obj: %f, No Obj: %f, .5R: %f, .75R: %f, count: %d\n", net.index, avg_iou/count, avg_cat/class_count, avg_obj/count, avg_anyobj/(l.w*l.h*l.n*l.batch), recall/count, recall75/count, count);
刚开始迭代,由于没有预测出相应的目标,所以查全率较低【.5R 0.75R】,会出现大面积为0的情况,这个是正常的。
第四部分:测试问题
好多童鞋已经成功训练了,但是在测试的时候又遇到了一些问题。最近事情比较多,不能一一回复,先将提问比较多的问题整理下来,然后稍候统一给出答案。
(1)bounding box正确,标签错乱
原因是作者在代码中设置了默认,所以修改darknet.c文件,将箭头指示的文件替换成自己的。然后重新编译即可。
(2)模型保存问题
A:保存模型出错?
一般是 .data 文件中指定的文件夹无法创建,导致模型保存时出错。自己手动创建即可。
B:模型什么时候保存?如何更改
迭代次数小于1000时,每100次保存一次,大于1000时,每10000次保存一次。
自己可以根据需求进行更改,然后重新编译即可。代码位置:detect.c line 138
(3)中文标签问题
这个解决方案较多,我就简单的说一下我的方案。
A:首先生成对应的中文标签,
修改代码中的字体,将其替换成指中文字体,如果提示提示缺少**模块,安装就行了。
B:添加自己的读取标签和画框函数
(4)图片上添加置信值
如果编译时没有制定opencv,基本上很难实现。如果编译时指定了opencv,在画框的函数里面添加一下就行了。
(5)图片保存名称
测试的时候,保存的默认名称是predictions.自己改成对应的图片名称即可。
第五部分:论文阅读
优点:速度快,精度提升,小目标检测有改善;
不足:中大目标有一定程度的削弱,遮挡漏检,速度稍慢于V2。
第五部分 相关资源:
前4部分作者博客:YOLOv3: 训练自己的数据
入门文档:知乎-目标检测
voc版本数据集制作:voc格式数据集
yolo主页:yolo home
翻译:知乎yolov3翻译
github开源:github开源
yolo源码解析专栏:
csdn论文笔记:论文笔记
YOLO v1~v3回顾:yolo合集
介绍YOLOv2的一篇佳作:yolo9000
k-means解说:k-means算法详解
用gt box进行聚类的博文:gt box k-means
某人的PPT:yolo小ppt
yolo源码解读:路人甲
第六部分 思考:
1.为什么v3和v2版本的测试性能提高很大,但速度却没有降低?
2.为什么v3性能上能有这么大的改进?或者说为什么v3在没有提高输入数据分辨率的前提下,对小目标检测变得这么好?
v3和v2不一样的地方总结一下:
- loss不同:作者v3替换了v2的softmax loss 为logistic loss,而且每个ground truth只匹配一个先验框。
- anchor bbox prior不同:v2作者用了5个anchor,一个折衷的选择,所以v3用了9个anchor,提高了IOU。
- detection的策略不同:v2只有一个detection,v3变成了3个,分别是一个下采样的,feature map为13*13,还有2个上采样的eltwise sum,feature map为26*26,52*52,也就是说v3的416版本已经用到了52的feature map,而v2把多尺度考虑到训练的data采样上,最后也只是用到了13的feature map,这应该是对小目标影响最大的地方。
- backbone不同:这和上一点是有关系的,v2的darknet-19变成了v3的darknet-53,为啥呢?就是需要上采样啊,卷积层的数量自然就多了,另外作者还是用了一连串的3*3、1*1卷积,3*3的卷积增加channel,而1*1的卷积在于压缩3*3卷积后的特征表示,这波操作很具有实用性,一增一减,效果棒棒。
YOLO称得上是目标检测界的翘楚,资源太多我做了个汇总!都注明了资源来源!如若有侵犯到您的权益,请私聊我删除哦!共同进步~
标签:box,yolo,anchors,YOLO,mask,v3,Incremental,anchor From: https://blog.51cto.com/u_12667998/7074800