目标检测之Yolov3 darknet训练自己的数据集

1配置darknet环境

参考官网 darknet

git clone https://github.com/pjreddie/darknet
cd darknet

更改Makefile, 令GPU=1,CUDNN=1,OPENCV=1

ARCH= -gencode arch=compute_30,code=sm_30 \

      -gencode arch=compute_35,code=sm_35 \

      -gencode arch=compute_50,code=[sm_50,compute_50] \

      -gencode arch=compute_52,code=[sm_52,compute_52] \

      -gencode arch=compute_61,code=[sm_61,compute_61]
make

2制作特定格式的数据集

1.cfg/**.data

classes = 9 # 你的数据集类别数
train  = /home/ktjiang/animal/data/list/train.txt #训练集路径,图片和标签要在同一个文件夹下,一个图片img对应一个标签txt
valid  = /home/ktjiang/animal/data/list/test.txt #验证集路径, 图片和标签要在同一个文件夹下,一个图片img对应一个标签txt
names = data/animal.names #数据集类别名称
backup = backup #训练权重保存路径

2.data/**.names

类别从0开始,为方便,添加一个unknown类别,实际类别只有8类

unknown # 0
AmurLeopard # 1
AmurTiger # 2
Car # 3
Cow # 4
Dog # 5
RacoonDog # 6
Red_Fox # 7
WildBoar # 8

3.train.txt, test.txt

训练集和测试集图片的路径信息,其中/home/ktjiang/animal/data/train//home/ktjiang/animal/data/val/文件夹下还包含对应的*.txt(标签信息)

train.txt

/home/ktjiang/animal/data/train/2000001.jpg
/home/ktjiang/animal/data/train/1000011.jpg
/home/ktjiang/animal/data/train/3000084.jpg

test.txt

/home/ktjiang/animal/data/val/2000068.jpg
/home/ktjiang/animal/data/val/8000043.jpg
/home/ktjiang/animal/data/val/5000117.jpg

4.label格式(归一化)

class_idx_centery_centerwh
10.660.290.190.39

假设一个标注的boundingbox的左下角和右上角坐标分别为(x1,y1)(x2,y2),图像的宽和高分别为w,h

归一化的中心点x坐标x_center计算公式:((x2+x1) / 2.0)/ w
归一化的中心点y_center坐标计算公式:((y2+y1) / 2.0)/ h
归一化的目标框宽度w的计算公式: (x2-x1) / w
归一化的目标框高度h计算公式:((y2-y1)/ h

如果图片的高度、宽度未知,可以通过cv2读取

imginfo = cv2.imread(img_dir + img_name + '.jpg').shape

imginfo里存的是图像的[h, w,通道数] ,这一需要注意imginfo结果里的顺序

5.新建一个cfg/yolov3_**.cfg配置文件

Testing # 测试模式,此模式下,下面的两行要放出来,训练模式下面的两行要注释掉
batch=1
subdivisions=1
#Training # 训练模式,此模式下,下面的两行要放出来,测试模式下面的两行要注释掉
#batch=64
#subdivisions=16 #每个batch分为16组,每组为batch/subdivision=4张图片
width=608 #网络输入的宽,高,通道数
height=608
channels=3
momentum=0.9
decay=0.0005
angle=0
saturation = 1.5
exposure = 1.5
hue=.1
learning_rate=0.001 #学习率
burn_in=1000
max_batches = 50200 #迭代次数
policy=steps
steps=40000,45000 #学习率变动步长
scales=.1,.1 #学习率变动因子,也即batch=40000时,learning_rate=0.0001, batch=45000时,learning_rate=0.00001

每一个yolo层的上一层卷积层的filter需要改变,random根据自己的显存决定(需要改变3个地方,3个yolo层)

[convolutional]
size=1
stride=1
pad=1
filters=42   # 3*(num_class + 5(注:4bbox+1confidence)) 这里num_class=9
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=9
num=9
jitter=.3
ignore_thresh = .7
truth_thresh = 1
random=1 # 多尺度训练打开,0为关闭

6.开始训练

./darknet detector train cfg/animal.data cfg/yolov3_animals.cfg darknet53.conv.74 -gpus 0,1,2,3 >log.txt

7.训练问题汇总

CUDA: out of memory 以及 resizing 问题

显存不够,调小batch,关闭多尺度训练:random = 0。

在迭代前期,loss很大,正常吗?

经过几个数据集的测试,前期loss偏大是正常的,后面就很快收敛了

训练出现nan的问题?

训练的时候若数据集小目标较少,106层会大概率输出nan,这是数据集的问题。如果数据集没有问题,可以通过调大batch或者调小learning_rate来解决.regin 82, regin 94, regin 106分别负责检测大,中,小物体,对应的feature map 大小为1313, 2626,52*52.对于大小为 416 x 416 的图像,YOLO 预测 ((52 x 52) + (26 x 26) + 13 x 13)) x 3 = 10647 个边界框

检测不到目标、计算recall为0,验证没有产生结果文件?

运行test,recall,vaild命令时,<test_cfg>文件中batch和subdivisions两项必须为1。官方cfg中两者值分别为64和16。

测试标签上如何添加置信值

由于官方代码测试只标注了类别,标签文字较大。使用过程中希望减小标签,并加上检测的置信值。

修改src/image.c文件draw_detections函数,前面部分代码修改如下:

void draw_detections(image im, detection *dets, int num, float thresh, char **names, image **alphabet, int classes)
{
    int i,j;
    for(i = 0; i < num; ++i){
        char labelstr[4096] = {0};
        int class = -1;
        for(j = 0; j < classes; ++j){
            if (dets[i].prob[j] > thresh){
                if (class < 0) {
                    char a[20];
                    sprintf(a,"%g", dets[i].prob[j]);
                    strcat(labelstr, names[j]);
                    strcat(labelstr,":");
                    strcat(labelstr,a);
                    class = j;
                } else {
                    char a[20];
                    sprintf(a,"%g",dets[i].prob[j]);
                    strcat(labelstr, ", ");
                    strcat(labelstr,names[j]);
                    strcat(labelstr,":");
                    strcat(labelstr,a);
                }
                printf("%s: %.0f%%\n", names[j], dets[i].prob[j]*100);
            }
        }

修改src/image.c文件draw_detections函数中get_label函数调用的参数

if (alphabet) {
                image label = get_label(alphabet, labelstr, (im.h*.03));
                draw_label(im, top + width, left, label, rgb);
                free_image(label);
            }
image label = get_label(alphabet, labelstr, (im.h*.02));

源码中为0.03,修改为0.02后,标签文字减小,可以根据需要调整。

修改代码后需要使用make clean,make重新编译。

使用多GPU训练时,由于并行处理,训练迭代次数会一次跳过几轮,导致某些整数次迭代的模型没有保存。

修改example/detector.c文件中的第148行

源代码为:if(i%10000==0 || (i<1000 && i%100==0))//迭代小于1000次,每100次保存模型,大于1000次,每10000次保存模型。

可以根据需要修改训练多少轮保存一个模型,if(i%1000==0 || (i<1000 && i%100==0)),大于1000次,每1000次保存模型。

8.测试问题

./darknet detector test cfg/animal.data cfg/yolov3_animals.cfg backup/yolov3_final.weights -thresh 0.2 -gpus 0,1,2,3

验证
计算MAP和RECALL

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值