nx上darknet的使用-目标检测-自定义训练与制作预训练模型

目录

1  训练yolov4-tiny

1.1  文件准备

1.1.1  Annotations

1.1.2  JPEGImages

1.1.3  labels

1.1.4  trained_models

1.1.5  classes.name

1.1.6  create_labels_txt.py

1.1.7  custom_training.data

1.1.8  get_labels.py

1.1.9  get_train_val.py

1.1.10  train.txt

1.1.11  val.txt

1.1.12  yolov4-tiny.cfg

1.1.13  yolov4-tiny.conv.29

1.1.14  yolov4-tiny-test.cfg

1.2  训练过程

1.3  训练结果

2  制作预训练模型


1  训练yolov4-tiny

首先在darknet创建一个文件夹custom_training

文件夹中包含这些文件

我们从左往右来讲,在文章的最后有识别效果,如果想先看效果的可以拉下去,看完再拉上来

1.1  文件准备

1.1.1  Annotations

获取方式:标注软件标注图像后获得

这里面放的都是标注好的xml文件,使用不同的标注软件标注结果可能略有不同,但xml的文件格式都是一样的,我们打开一个看一下

下面这个xml是一个图中只有一个框子的

下面这个是一个图中有多个框子的

1.1.2  JPEGImages

获取方式:把标注的图像放进去

这里面放的都是被标注的图片,注意要与标注文件对应(比如0.jpg与0.xml)

1.1.3  labels

获取方式:由create_labels_txt.py转换xml文件获得

这个文件夹中都是放的xml转换过来的项目专用的txt文件(我们后面有一个文件专门转换它),由于是转换过来的,所以自然也是与图像一一对应的

我们打开一个看一下

下面这个是一个框的情况,发现里面有5个数,这5个数的含义依次是

  1. 标签号,从0开始
  2. 标注框的中心点x坐标 除 图像宽度 的比值
  3. 标注框的中心点y坐标 除 图像高度 的比值
  4. 标注框的宽度 除 图像宽度 的比值
  5. 标注框的高度 除 图像高度 的比值

我们下面再看一个多个框的情况

有几个框就有几行,最后不要有换行符

1.1.4  trained_models

创建一个空的文件夹就行了,这个文件夹是专门放训练好的模型文件的,没训练之前文件夹中是空的

在训练之后每1000个batch会自动保存一次,我训练了4000个batch,现在里面是这样的

后面要用的话用 yolov4-tiny_final.weights就可以了

1.1.5  classes.name

获取方式:用记事本写一个文件,后缀为.name就可以了

这里面写的是所有标注的标签,有几个就写几个,标签用换行符隔开,最后一行末尾没有换行符

我再举个例子

这里的顺序要与后续create_labels_txt.py的顺序一致

如果你不知道有多少标签,后面可以通过get_labels.py来查询

1.1.6  create_labels_txt.py

获取方式:一个py文件

文件中的内容是这样的

import xml.etree.ElementTree as ET
import os
import re
 
with open('classes.names','r') as f:
    classes = f.read().splitlines()
 
p = re.compile(r'(.*)\.')
for i in os.listdir('Annotations'):
    i = p.findall(i)[0]
    xml_file = '/home/nvidia/darknet/custom_training/Annotations/{}.xml'.format(i)
    tree = ET.parse(xml_file)
    root = tree.getroot()
 
    for size in root.iter('size'):
        width = int(size.find('width').text)
        height = int(size.find('height').text)
 
    all_content = ''
    for obj in root.iter('object'):
        cls = obj.find('name').text
        cls_id = classes.index(cls)
 
        xmlbox = obj.find('bndbox')
        xmin = int(xmlbox.find('xmin').text)
        ymin = int(xmlbox.find('ymin').text)
        xmax = int(xmlbox.find('xmax').text)
        ymax = int(xmlbox.find('ymax').text)
 
        x = (xmin+xmax)/2/width
        y = (ymin+ymax)/2/height
        w = (xmax-xmin)/width
        h = (ymax-ymin)/height
 
        one_content = '{} {:.4f} {:.4f} {:.4f} {:.4f}'.format(cls_id,x,y,w,h)
        all_content = all_content + one_content + '\n'
 
    all_content = all_content.strip('\n')
    file = open('./labels/{}.txt'.format(i),'w')
    print(all_content,file=file,flush=True)

有几个参数需要随着数据集变动

  • classes 这个是训练的标签,需要与classes.name的内容一致,注意顺序也要一致
  • xml_file 放的是Annotations中xml的文件,我这里放的绝对路径,也可以放相对路径
  • xmin,ymin,ymin,ymax 我不确定所有的标注文件是否都是这四个点(有的可能是直接给宽度),如果你的xml文件中写的是别的,那么你就对应改一下

  • cls_id 这个是labels中产生txt的第一个内容
  • x,y,w,h 这四个就是labels中产生的txt的后四个内容

如果按照我写的结构放置文件的话,直接运行就可以了

1.1.7  custom_training.data

获取方式:用记事本写,后缀改为data,最后一行末尾没有换行符

这里的信息的含义如下,注意所有路径都是绝对路径

字段 含义
classes 类别总数
train train.txt的绝对路径,train.txt我们后面会提到
valid val.txt的绝对路径,val.txt我们后面会提到
names classes.name的绝对路径
backup trained_models的绝对路径,注意后面要再加一个斜杠

1.1.8  get_labels.py

原理是用python的set()变量,set()变量中的元素不重复,访问xml中的name,将所有的内容添加的set中

1.1.9  get_train_val.py

这个是用来辅助创建train.txt与val.txt的

import os
 
a = 0
train_txt = open('train.txt','w')
val_txt = open('val.txt','w')
for i in os.listdir('JPEGImages'):
    a = a + 1
    if a < 15712: #train
        print('/home/nvidia/darknet/custom_training/JPEGImages/' + i,file=train_txt,flush=True)
    else: #test
        print('/home/nvidia/darknet/custom_training/JPEGImages/' + i,file=val_txt,flush=True)

6065是我当前有7581张图片,我想选择其中的80%(6065张)作为训练图片,其余的作为测试图片

1.1.10  train.txt

获取方式:笔记本搞

这里放的是训练图像的绝对路径

1.1.11  val.txt

获取方式:笔记本搞

这里放的是所有测试图像的绝对路径,方法与train.txt相同,让其余图像作为测试图像

1.1.12  yolov4-tiny.cfg

获取方式:在darkent的cfg中有,复制过来

yolov4-tiny.cfg与其余的yolo模型修改起来差不多,我比较常用yolov4-tiny.cfg与yolov4-custom.cfg,这两个cfg文件在这个文件夹中都有,tiny速度快但精度差,custom精度高但速度慢,下面说几个经常改的参数

  • batch与subdivisions

训练模型时可能会出现CUDA爆掉的情况,这个时候我们需要修改batch与subdivisions,batch是会影响训练结果的,太小是不行的,subdivisions的意思是把batch分成多少份,我下面这种图就是batch为64,然后把batch再分成64份一点一点儿给,这样就不会出现CUDA爆掉的问题了

  • width与height

这个并不是图像的宽与高,这个实际上是模型的输入大小,宽和高必须为32的倍数

你的模型宽高越大,训练时间越长,模型越精准,预测的更慢

你的模型宽高越小,训练时间越短,模型越不精准,预测的更快

  • learning_rate

learning_reate是学习速率,我们在训练的过程中可能会出现loss为NaN的情况,这个时候就不用再训练了,这个情况叫梯度爆炸或梯度消失,这个时候可以尝试改一下学习率

  • max_batches与steps

在帮助文档中建议 max_batches的值设置为(种类数)*2000

step有两个值,第一个值是max_batches的80%,第二个值是max_batches的90%

  • classes与filters

classes是训练的类别数量,比如你要识别5种不同的东西classes就给5,识别7种类别不同的东西就给7

filters计算公式为(种类数+5)*3,我下面图片种类数为2,所以这里的filters是21

在yolov4-custom.cfg中一共有三处,在yolv4-tiny.cfg有两处,都要改

1.1.13  yolov4-tiny.conv.29

获取方式:从我上面的网盘链接中搞,或者用这个github链接 https://github.com/AlexeyAB/darknet/releases/download/darknet_yolo_v4_pre/yolov4-tiny.conv.29

这个链接是在项目 GitHub - AlexeyAB/darknet: YOLOv4 / Scaled-YOLOv4 / YOLO - Neural Networks for Object Detection (Windows and Linux version of Darknet ) 中的这里

1.1.14  yolov4-tiny-test.cfg

获取方式:把yolov4-tiny.cfg复制过来,然后改一些东西

只改batch,把下面的batch注释掉

这个其实你改不改都行,在测试的时候直接使用yolv4-tiny.cfg进行使用就行

1.2  训练过程

在darkent路径下打开终端,之后输入

./darknet detector train custom_training/custom_training.data custom_training/yolov4-tiny.cfg custom_training/yolov4-tiny.conv.29

输入之后终端的情况是这样的

而且会出现一个图,这里会记录我们每一个batch的loss情况

训练接触后会显示模型已保存,我大致训练了两个小时左右

我的loss情况是这样的

最终loss是0.1498左右

1.3  训练结果

在darknet下打开终端后输入

./darknet detector test custom_training/custom_training.data custom_training/yolov4-tiny-test.cfg custom_training/trained_models/yolov4-tiny_final.weights custom_training/JPEGImages/000001.jpg

最后的图片路径你可以自定义,输入之后终端是这样的

之后会出现一个小图像

把它放大后的效果是这样的

2  制作预训练模型

我们先说层这个概念,在训练的开始你可以看到你选用的模型一共有多少层。

你可以将训练好的模型作为预训练模型,比如

./darknet partial ./custom_training/yolov3-tiny.cfg ./custom_training/yolov3-tiny_final.weights ./yolov3-tiny.conv.15 15
  • ./darknet partial[训练模型用到的cfg位置] [训练好的模型文件位置] [要生成的预训练模型文件位置] [保留网络层数权重]

之后就在执行代码的位置就会得到 yolov3-tiny.conv.15 这个预训练模型文件 

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-12 20:46:03       66 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-12 20:46:03       70 阅读
  3. 在Django里面运行非项目文件

    2024-07-12 20:46:03       57 阅读
  4. Python语言-面向对象

    2024-07-12 20:46:03       68 阅读

热门阅读

  1. Linux 命令个人学习笔记

    2024-07-12 20:46:03       18 阅读
  2. SpringBoot实现Read Through模式

    2024-07-12 20:46:03       20 阅读
  3. linux中vim切换输入中文

    2024-07-12 20:46:03       17 阅读
  4. 模型剪枝知识点整理

    2024-07-12 20:46:03       21 阅读
  5. 雅思词汇及发音积累 2024.7.12

    2024-07-12 20:46:03       23 阅读
  6. php上传文件

    2024-07-12 20:46:03       17 阅读
  7. linux kernel ptr dump

    2024-07-12 20:46:03       19 阅读
  8. 软设之备忘录模式

    2024-07-12 20:46:03       21 阅读
  9. Nginx 高效加速策略:动静分离与缓存详解

    2024-07-12 20:46:03       23 阅读
  10. python 读取pcap文件并筛选数据包

    2024-07-12 20:46:03       20 阅读
  11. 在 Qt 中暂停程序的几种方法

    2024-07-12 20:46:03       20 阅读