Ubuntu darknet(yolov4)标记、训练自己的数据流程记录

文章目录

  • Ubuntu darknet(yolov4)标记、训练自己的数据流程记录
      • 0 数据准备
      • 1 创建数据集文件
      • 2 修改配置文件
      • 3 修改makefile文件
      • 4 开始训练
      • 5 关于停止训练的时机
      • 6 开始检测

Ubuntu darknet(yolov4)标记、训练自己的数据流程记录

参考:https://github.com/AlexeyAB/darknet

记录以下流程和错误,之后再用到,查询起来也快些。

翻译了部分参照文档,并按照流程走的~

提前工作有:

1.克隆了darknet代码;

2.数据已经标注完毕。且生成了对应的标签数据集

0 数据准备

标注工具使用了labelme,生成的是json文件,需要转换为txt格式的。

将labelme标记的.json数据,转为yolov4训练用的.txt数据。

图片和json文件保存在obj文件夹里。

python代码:

from os import getcwd
import numpy as np
import os
import json
import glob
wd = getcwd()
"labelme标注的json数据集转为keras yolo的txt训练集"
classes = ["car","pedestrian","truck","bus"]  #修改为待检测的类别名
image_ids = glob.glob(r"obj/*.jpg")           #jpg和json文件都在文件夹obj/里
print(image_ids)


def convert_annotation(image_id):
    jsonfile=open('%s.json' % (image_id))
    in_file = json.load(jsonfile)
    #print(in_file)
    height=in_file["imageHeight"]
    width=in_file["imageWidth"]
    size=[width,height]
    list_file = open('%s.txt'%(image_id.split('.')[0]), 'w')
    for i in range(0,len(in_file["shapes"])):
        object=in_file["shapes"][i]
        cls=object["label"]
        points=object["points"]
        dw = 1./(size[0])
        dh = 1./(size[1])
        min_x=min_y= np.inf
        max_x = max_y = 0
        for x, y in points:
            min_x = min(min_x, x)
            min_y = min(min_y, y)
            max_x = max(max_x, x)
            max_y = max(max_y, y)
        x=(min_x+max_x)/2.0
        print(x)
        y=(min_y+max_y)/2.0
        print(y)
        w=max_x-min_x
        h=max_y-min_y
        x = x*dw
        w = w*dw
        y = y*dh
        h = h*dh
        if cls not in classes:
            print("cls not in classes")
            continue
        cls_id = classes.index(cls)
        b = (x, y, w, h)
        list_file.write(str(cls_id)+" "+" ".join([str(a) for a in b]) )
        list_file.write('\n')
    list_file.close()
    jsonfile.close()
for image_id in image_ids:
   # list_file.write('%s.jpg' % (image_id.split('.')[0]))
    convert_annotation(image_id.split('.')[0])
    

该脚本程序会为每个.jpg文件生成一个.txt文件,而且都在obj目录下。

按照比例,划分训练集和测试集合,这里是9:1划分的:

gene train txt代码:

# coding: utf-8
import os

paths = "obj"    # 测试图片的路径
f = open('train.txt', 'w')   # 保存图片路径的txt文件
filenames = os.listdir(paths)
# 只获取jpg文件
files=[]
for file in filenames:
    if file.split('.')[-1]=='txt':
        continue
    else:
        files.append(file)
# 生成测试集
cnt=0
st=[1,2,3,4,5,6,7,8,9]
for filename in files:
        cnt+=1
        cnt=cnt%10
        if cnt not in st:
                cnt=0
                continue
        #print(cnt)
        out_path = "data/obj/" + filename  # 引号内为测试图片文件夹的路径
        print(out_path)
        f.write(out_path + '\n')
f.close()

gene test txt代码:

# coding: utf-8
import os

paths = "obj"    # 这里保存图片
f = open('test.txt', 'w')   # 最后得到的图片路径txt文件
filenames = os.listdir(paths)
# 只获取jpg文件
files=[]
for file in filenames:
    if file.split('.')[-1]=='txt':
        continue
    else:
        files.append(file)
# 生成测试集
cnt=0
st=[1,2,3,4,5,6,7,8,9]
for filename in files:
        cnt+=1
        cnt=cnt%10
        if cnt in st:
                continue
        #print(cnt)
        out_path = "data/obj/" + filename  # 引号内为测试图片文件夹的路径
        print(out_path)
        f.write(out_path + '\n')
        cnt=0
f.close()

现在,目录如下:

darknet
	data
		obj
		train.txt
		test.txt

1 创建数据集文件

data目录里创建数据集文件,tree

darknet
	data
		obj.names 		# 物体类别名称
		obj.data 		# 该文件夹保存数据集信息
		obj 			# 存放图片以及标签信息
		train.txt 		# 存放训练集地址
		test.txt 		# 存放检测集地址

以下分别解释data/下5个文件(夹)的作用:

  • obj.name 保存要检测物体的名称,一行写一个

  • obj.data 保存有五类信息:检测类别数量,训练集,验证集,类别名称,保存权重的文件夹,比如:

    classes= 2                        # 目标物体的类别数量
    train  = data/train.txt           # 训练数据集的路径
    test= data/test.txt               # 验证数据集的路径
    names = data/obj.names            # 目标物体的类别名称
    backup = backup/                  # 保存训练权重文件
    
  • obj 存放数据集图片和每张图片的标签信息,即:

    001.jpg
    001.txt
    002.jpg
    002.txt
    

    其中,每个.txt是对应.jpg的标签文件,其包含的信息有:

    <object-class>  <x_center>  <y_center>  <width>  <height>
    

    本人是将训练集和验证集的图片,都放在了obj文件夹里。

    每个.jpg文件,都有同名但.txt的文件相对应,且在obj文件夹里。

    001.txt文件中一行对应001.jpg中一个物体信息:类别 中心点x坐标 中心点y坐标 宽 高 ,可能有多行。

    计算方式如下:

    <x_center> = <absolute_x> / <image_width> 	即bounding box中心x实际坐标 / 图片实际宽度
    
    <y_center> = <absolute_y> / <image_height> 	即bounding box中心y实际坐标/图片实际高度
    
    <width> = <absolute_width> / <image_width>  即bbox宽度/图片实际宽度
    
    <height> = <absolute_width> / <image_width> 即bbox高度 /图片实际高度
    
  • train.txt 保存所有训练集图片的相对地址,如:

    data/obj/img001.jpg
    data/obj/img002.jpg
    data/obj/img003.jpg
    
  • test.txt 保存所有验证集图片的相对地址,如:

    data/obj/img11.jpg
    data/obj/img21.jpg
    data/obj/img31.jpg
    

2 修改配置文件

  1. 复制cfg文件夹下yolov4.cfgyolov4-obg.cfg

  2. 修改yolov4-obj.cfg中的内容:

    # step1: 修改batch和subdivisions
    L2: batch=64                # 原来就是64,根据gpu自己选择,但必须是2的倍数
    L3: subdivisions=16         # 根据自己的gpu选择,如果out of memory,则32或64,依次倍增。或者64,32,...,1,依次倍减batch值
    
    
    # step2: 修改图片的尺寸
    L7: width=608               # 这边我没有修改,该值必须被32整除。
    L8: height=608               
    L19: max_batches=500500     #该值最少是classes*2000
    L21:steps=400000,450000     #该值是 max_batches的80% 和 90%
    
    # step3: 修改classes(每个yolo层都需要修改一次,一共三次)
    L968: classes=2             # 和obj.data文件中classes值相同,=2表示只识别两类物体
    L1056: classes=2
    L1144: classes=2
     
    # step4: 修改每个yolo相邻的上一个convolution层的filter,一共3个
    L961: filters=21            # 因为我预测两类物体:21 = 3*(5+2),具体看下文解释
    L1049: filters=21
    L1137: filters=21
     
    

    L2,L3表示第2行,第3行。

    filters=21 是3*(5+2)=21得来的,如果一共检测4类物体,比如:car,pedestrian,truck,bus,则filters的值为3*(5+4)=27.关于为什么是5,还要乘3,可以看对应论文。

3 修改makefile文件

若无GPU,则不做任何修改,否则一些参数应修改为:

GPU=1: 表示在训练的时候使用CUDA进行加速训练(CUDA应该在 /usr/local/cuda文件夹下),若无,

CUDNN=1: 表示在训练的过程中使用CUDNN v5-v7进行加速(cuDNN应该在 /usr/local/cudnn文件夹下)

CUDNN_half=0: 为Tensor Cores (在Titan V / Tesla V100 / DGX-2等)上进行加速训练和推理。

OPENCV=1: 编译OpenCV 4.x/3.x/2.4.x等。OpenCV可以读取视频或者图片。

#L69 将NVCC=nvcc改为你自己的nvcc的路径
NVCC=/usr/local/cuda/bin/nvcc

注意L109和L121以下的3行:看一下cuda的默认路径,是否和自己的一致,不一致就需要修改。有的人是NVCC=/usr/local/cuda9.0/bin/nvcc,则需要修改。

以上就是开始训练前的准备。

4 开始训练

  1. 下载预训练权值yolov4.conv.137,放在darknet/里

  2. 执行./darknet detector train data/obj.data cfg/yolov4-obj.cfg yolov4.conv.137 -map

Note:

1.指定GPU:

#如果想要指定具体的gpu进行训练,使用-i来指定,比如我想使用索引为2的gpu进行训练:
./darknet detector train data/obj.data cfg/yolov4-obj.cfg yolov4.conv.137 -i 2 -map

2.训练时不显示loss窗口的命令:

./darknet detector train data/obj.data cfg/yolo-obj.cfg yolov4.conv.137 -dont_show

3.在远程界面,显示mAP&Loss图表:

./darknet detector train data/obj.data cfg/yolo-obj.cfg yolov4.conv.137 -dont_show -mjpeg_port 8090 -map

然后使用浏览器打开链接:http://ip-address:8090

训练过程中,darknet自动保存权值文件到backup/

backup文件夹下的yolo-obj_last.weights文件会每隔1000个iterations保存一次,新的会替代旧的

darknet总的训练步长可以在yolov4-obj.cfg文件中修改max_batches的大小(默认max_batches = 500500)

-map表示可视化显示mAP&Loss 图表,每4Epochs

训练完成后,在backup/查看结果文件:yolo-obj_final.weights

每100次迭代,比如2000次迭代后,由于外因,你停止了检测,之后可以使用:./darknet detector train data/obj.data yolo-obj.cfg backup/yolo-obj_2000.weights 来继续训练。

当avg-average loss (error)值达到最低时,你也可以提前停止训练。

5 关于停止训练的时机

关于什么停止训练,官网文档大概意思是:

  1. 当loss 0.xxxxxx avg 不再变化的时候,停止训练
  2. 一旦停止了训练,在backup文件夹中选择最合适的权重。
    如果你在9000 iterations停止训练,可能最好的模型在7000, 8000, 9000之间,不确定会不会产生过拟合,因此你需要找到提前停止训练的点(Early Stopping Point):
    Ubuntu darknet(yolov4)标记、训练自己的数据流程记录_第1张图片

在Early Stopping Point处,权值文件是最佳的,关于怎么寻找到该点,文档大概意思是:

  1. 准备验证集。你需要在 obj.data中将valid = data/test.txt 修改成 valid = data/valid.txt (valid.txt的格式和train.txt一样),如果你没有验证集,你可以直接将train.txt的内容直接复制到valid.txt文件中。
  2. 对候选权重,测试mAP。如果你是在9000 iterations停止训练的,你就需要对之前保存的权重进行测试:

具体步骤是:

step1.测试7000 iterations的mAP:

./darknet detector map data/obj.data cfg/yolov4-obj.cfg backup/yolo-obj_7000.weights

​ step2: 测试8000 iterations的mAP

./darknet detector map data/obj.data cfg/yolov4-obj.cfg backup/yolo-obj_8000.weights

​ step3: 测试9000 iterations的mAP

./darknet detector map data/obj.data cfg/yolov4-obj.cfg backup/yolo-obj_9000.weights

选择mAP值或者IOU值最高的权重文件,该文件就是最优的训练权重。

6 开始检测

训练好权重之后,我们可以使用权重进行检测,在终端中输入下面命令就行:

./darknet detector test data/obj.data cfg/yolo-obj.cfg yolo-obj_8000.weights

检测视频命令是:

#  只显示FPS,不显示图像
./darknet detector demo data/obj.data cfg/yolov4-obj.cfg backup/yolov4-obj_9000.weights data/demo3.mp4  -dont_show -ext_output
# 显示FPS,显示图像,保存检测视频结果
./darknet detector demo data/obj.data cfg/yolov4-obj.cfg backup/yolov4-obj_9000.weights data/demo3.mp4  -ext_output -out_filename res.mp4

以上。

大部分都是按照AlexeyAB/darknet上的参考文档走的,基本没有遇到问题。

你可能感兴趣的:(deep,learning,Ubuntu,darknet,yolov4,labelme,深度学习,1024程序员节)