YOLOv8训练自定义数据集和运行参数解读

1、YOLOv8深度学习环境搭建及安装

1.1. Yolov8介绍

设置操作类型
YOLOv8模型可用于各种任务,包括检测、分割和分类。这些任务的不同之处在于它们产生的输出类型和它们要解决的特定问题。

**检测:**检测任务涉及识别和定位图像或视频中感兴趣的对象或区域。YOLO模型通过预测图像中物体的边界框和类标签,可以用于物体检测任务。
**分割:**分割任务包括将图像或视频划分为对应于不同对象或类的区域或像素。
**分类:**分类任务包括为输入(如图像或文本)分配类标签。YOLO模型可以通过预测输入图像的类别标签来进行图像分类任务
根据你要解决的特定问题,YOLOv8模型可以在不同的模式下使用。这些模式包括train、val和predict。

**训练(Train)*训练模式用于在数据集上训练模型。这种模式通常在模型的开发和测试阶段使用。
Val: Val模式用于评估模型在验证数据集上的性能。这种模式通常用于调整模型的超参数和检测过拟合。
Predict: Predict模式用于在新数据上使用模型进行预测。这种模式通常用于生产环境或将模型部署给用户时。

Key Value Description
task detect 可选择:detect, segment, classify
mode train 可选择: train, val, predict
resume False 当设置为True时,恢复上一次的任务。当设置为False时,从给定的model.pt中恢复。
model null 设置模型。格式因任务类型而异。支持model_name, model.yaml,model.pt
data null 设置数据,支持多数类型 data.yaml, data_folder, dataset_name

模型结构图:

1.2.环境详细配置

运行平台为联通云服务器,显卡配置为:T4(16GB),可设置单块和多块GPU
具体环境:

PyTorch 1.9.1
Python 3.8
Cuda 11.1
依赖库按照requirements.txt文件安装即可。

在YOLOv8代码包目录:pip install -r requirements.txt

1.3.安装YOLOv8所需要的ultralytics库

安装YOLOv8所需要的ultralytics库,在1.2的环境中,执行下述代码:

pip install ultralytics

1.4.下载YOLOv8代码包

下载YOLOv8代码,执行代码如下:

git clone https://github.com/ultralytics/ultralytics.git

自动下载

将服务器的文件目录cd到 path/your/ultralytics,激活配置的深度学习环境,至此,环境搭建结束!可开始模型的训练了。

YOLOv8代码包的内容如下图所示:

YOLOv8训练自定义数据集和运行参数解读_第1张图片

2、数据准备

2.1.数据集介绍及其结构

印刷电路板(PCB)瑕疵数据集:数据下载链接,是一个公共的合成PCB数据集,由北京大学发布,其中包含1386张图像以及6种缺陷(缺失孔,鼠标咬伤,开路,短路,杂散,伪铜),用于检测,分类和配准任务。

├── data
│   ├── Annotations  进行 detection 任务时的标签文件,xml 形式,文件名与图片名一一对应
│   ├── images  存放 .jpg 格式的图片文件
│   ├── ImageSets  存放的是分类和检测的数据集分割文件,包含 train.txt,val.txt,trainval.txt,test.txt
│   ├── labels  存放label标注信息的txt文件,与图片一一对应

├── ImageSets(train,val,test建议按照811比例划分)
│   ├── train.txt  写着用于训练的图片名称
│   ├── val.txt  写着用于验证的图片名称
│   ├── trainval.txt  train与val的合集
│   ├── test.txt  写着用于测试的图片名称

2.2.数据集划分

用途:主要是将数据集分类成训练数据集和测试数据集,默认train,val,test按照比例进行随机分类,运行后ImagesSets文件夹中会出现四个文件,主要是生成的训练数据集和测试数据集的图片名称,如下图。同时data目录下也会出现这四个文件,内容是训练数据集和测试数据集的图片路径。

import os
import random

trainval_percent = 0.9
train_percent = 0.9
xmlfilepath = '/home/PCB_detect_model/YOLOv8/ultralytics/PCB_dataSets/VOC_PCB/Annotations'
txtsavepath = '/home/PCB_detect_model/YOLOv8/ultralytics/PCB_dataSets/VOC_PCB/ImageSets'
total_xml = os.listdir(xmlfilepath)

num = len(total_xml)
list = range(num)
tv = int(num * trainval_percent)
tr = int(tv * train_percent)
trainval = random.sample(list, tv)
train = random.sample(trainval, tr)

ftrainval = open('/home/PCB_detect_model/YOLOv8/ultralytics/PCB_dataSets/VOC_PCB/ImageSets/trainval.txt', 'w')
ftest = open('/home/PCB_detect_model/YOLOv8/ultralytics/PCB_dataSets/VOC_PCB/ImageSets/test.txt', 'w')
ftrain = open('/home/PCB_detect_model/YOLOv8/ultralytics/PCB_dataSets/VOC_PCB/ImageSets/train.txt', 'w')
fval = open('/home/PCB_detect_model/YOLOv8/ultralytics/PCB_dataSets/VOC_PCB/ImageSets/val.txt', 'w')

for i in list:
    name = total_xml[i][:-4] + '\n'
    if i in trainval:
        ftrainval.write(name)
        if i in train:
            ftrain.write(name)
        else:
            fval.write(name)
    else:
        ftest.write(name)

ftrainval.close()
ftrain.close()
fval.close()
ftest.close()
  • 运行代码后,在VOC_PCB/ImageSets文件夹下生成下面四个txt文档:

YOLOv8训练自定义数据集和运行参数解读_第2张图片

  • txt文件里面的内容如下:

YOLOv8训练自定义数据集和运行参数解读_第3张图片

2.3.数据集格式转换

用途:用于yolo训练的txt格式代码。主要是将图片数据集标注后的xml文件中的标注信息读取出来并写入txt文件,运行后在labels文件夹中出现所有图片数据集的标注信息

# xml解析包
import xml.etree.ElementTree as ET
import pickle
import os
# os.listdir() 方法用于返回指定的文件夹包含的文件或文件夹的名字的列表

from os import listdir, getcwd
from os.path import join


sets = ['train', 'test', 'val']
classes = ['missing_hole', 'mouse_bite', 'open_circuit', 'short', 'spur', 'spurious_copper']


# 进行归一化操作

def convert(size, box):  # size:(原图w,原图h) , box:(xmin,xmax,ymin,ymax)
    dw = 1./size[0]     # 1/w
    dh = 1./size[1]     # 1/h
    x = (box[0] + box[1])/2.0   # 物体在图中的中心点x坐标
    y = (box[2] + box[3])/2.0   # 物体在图中的中心点y坐标
    w = box[1] - box[0]         # 物体实际像素宽度
    h = box[3] - box[2]         # 物体实际像素高度
    x = x*dw    # 物体中心点x的坐标比(相当于 x/原图w)
    w = w*dw    # 物体宽度的宽度比(相当于 w/原图w)
    y = y*dh    # 物体中心点y的坐标比(相当于 y/原图h)
    h = h*dh    # 物体宽度的宽度比(相当于 h/原图h)
    return (x, y, w, h)    # 返回 相对于原图的物体中心点的x坐标比,y坐标比,宽度比,高度比,取值范围[0-1]


# year ='2012', 对应图片的id(文件名)

def convert_annotation(image_id):
    '''
    将对应文件名的xml文件转化为label文件,xml文件包含了对应的bunding框以及图片长款大小等信息,
    通过对其解析,然后进行归一化最终读到label文件中去,也就是说
    一张图片文件对应一个xml文件,然后通过解析和归一化,能够将对应的信息保存到唯一一个label文件中去
    labal文件中的格式:calss x y w h  同时,一张图片对应的类别有多个,所以对应的bunding的信息也有多个
    '''
    # 对应的通过year 找到相应的文件夹,并且打开相应image_id的xml文件,其对应bund文件
    in_file = open('/home/PCB_detect_model/YOLOv8/ultralytics/PCB_dataSets/VOC_PCB/Annotations/%s.xml' % (image_id), encoding='utf-8')
    # 准备在对应的image_id 中写入对应的label,分别为
    #     
    out_file = open('/home/PCB_detect_model/YOLOv8/ultralytics/PCB_dataSets/VOC_PCB/labels/%s.txt' % (image_id), 'w', encoding='utf-8')
    # 解析xml文件
    tree = ET.parse(in_file)
    # 获得对应的键值对
    root = tree.getroot()
    # 获得图片的尺寸大小
    size = root.find('size')
    # 如果xml内的标记为空,增加判断条件
    if size != None:
        # 获得宽
        w = int(size.find('width').text)
        # 获得高
        h = int(size.find('height').text)
        # 遍历目标obj
        for obj in root.iter('object'):
            # 获得difficult ??
            difficult = obj.find('difficult').text
            # 获得类别 =string 类型
            cls = obj.find('name').text
            # 如果类别不是对应在我们预定好的class文件中,或difficult==1则跳过
            if cls not in classes or int(difficult) == 1:
                continue
            # 通过类别名称找到id
            cls_id = classes.index(cls)
            # 找到bndbox 对象
            xmlbox = obj.find('bndbox')
            # 获取对应的bndbox的数组 = ['xmin','xmax','ymin','ymax']
            b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text),
                 float(xmlbox.find('ymax').text))
            print(image_id, cls, b)
            # 带入进行归一化操作
            # w = 宽, h = 高, b= bndbox的数组 = ['xmin','xmax','ymin','ymax']
            bb = convert((w, h), b)
            # bb 对应的是归一化后的(x,y,w,h)
            # 生成 calss x y w h 在label文件中
            out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')
# 返回当前工作目录
wd = getcwd()
print(wd)
for image_set in sets:
    '''
    对所有的文件数据集进行遍历
    做了两个工作:
    1.将所有图片文件都遍历一遍,并且将其所有的全路径都写在对应的txt文件中去,方便定位
    2.同时对所有的图片文件进行解析和转化,将其对应的bundingbox 以及类别的信息全部解析写到label 文件中去
      最后再通过直接读取文件,就能找到对应的label 信息
    '''
    # 先找labels文件夹如果不存在则创建
    if not os.path.exists('/home/PCB_detect_model/YOLOv8/ultralytics/PCB_dataSets/VOC_PCB/labels/'):
        os.makedirs('/home/PCB_detect_model/YOLOv8/ultralytics/PCB_dataSets/VOC_PCB/labels/')
    # 读取在ImageSets/Main 中的train、test..等文件的内容
    # 包含对应的文件名称
    image_ids = open('/home/PCB_detect_model/YOLOv8/ultralytics/PCB_dataSets/VOC_PCB/ImageSets/%s.txt' % (image_set)).read().strip().split()
    # 打开对应的2012_train.txt 文件对其进行写入准备
    list_file = open('/home/PCB_detect_model/YOLOv8/ultralytics/PCB_dataSets/VOC_PCB/%s.txt' % (image_set), 'w')
    # 将对应的文件_id以及全路径写进去并换行
    for image_id in image_ids:
        list_file.write('/home/PCB_detect_model/YOLOv8/ultralytics/PCB_dataSets/VOC_PCB/images/%s.jpg\n' % (image_id))
        # 调用  year = 年份  image_id = 对应的文件名_id
        convert_annotation(image_id)
    # 关闭文件
    list_file.close()
  • labels文件夹里面的内容如下:
    YOLOv8训练自定义数据集和运行参数解读_第4张图片

  • txt文件每一行为一个目标的信息,包含class, x_center, y_center, width, height。格式如下:

    YOLOv8训练自定义数据集和运行参数解读_第5张图片

3、模型训练

3.1.新建一个PCB数据集yaml文件—PCB.yaml

train: /home/xuh/AI_Industrial_Internet/PCB_detect_model/YOLOv8/ultralytics/PCB_dataSets/VOC_PCB/train.txt
val: /home/xuh/AI_Industrial_Internet/PCB_detect_model/YOLOv8/ultralytics/PCB_dataSets/VOC_PCB/val.txt
test: /home/xuh/AI_Industrial_Internet/PCB_detect_model/YOLOv8/ultralytics/PCB_dataSets/VOC_PCB/test.txt

# number of classes
nc: 6

# class names
names: ['missing_hole', 'mouse_bite', 'open_circuit', 'short', 'spur', 'spurious_copper']

3.2 训练代码

YOLOv8模型的训练设置是指用于在数据集上训练模型的各种超参数和配置。这些设置会影响模型的性能、速度和精度。一些常见的YOLO训练设置包括批量大小、学习率、动量和权重衰减。其他可能影响训练过程的因素包括优化器的选择、损失函数的选择、训练数据集的大小和组成。重要的是要仔细调整和试验这些设置,以实现给定任务的最佳性能。

YOLOv8关于模型训练和预测的超参数在ultralytics/yolo/cfg/default.yaml中设置,这是与先前版本的最大的不同,通过使用这些指令我们就可以实现各种我们所需的操作。

default.yaml内容

#只展示了一部分超参数

task: detect  # (str) YOLO task, i.e. detect, segment, classify, pose
mode: train  # (str) YOLO mode, i.e. train, val, predict, export, track, benchmark

# Train settings -------------------------------------------------------------------------------------------------------
model:  # (str, optional) path to model file, i.e. yolov8n.pt, yolov8n.yaml
data:  # (str, optional) path to data file, i.e. coco128.yaml
epochs: 100  # (int) number of epochs to train for
patience: 50  # (int) epochs to wait for no observable improvement for early stopping of training
batch: 16  # (int) number of images per batch (-1 for AutoBatch)
imgsz: 640  # (int | list) input images size as int for train and val modes, or list[w,h] for predict and export modes
save: True  # (bool) save train checkpoints and predict results
save_period: -1 # (int) Save checkpoint every x epochs (disabled if < 1)
cache: False  # (bool) True/ram, disk or False. Use cache for data loading
device:  # (int | str | list, optional) device to run on, i.e. cuda device=0 or device=0,1,2,3 or device=cpu
workers: 8  # (int) number of worker threads for data loading (per RANK if DDP)
project:  # (str, optional) project name
name:  # (str, optional) experiment name, results saved to 'project/name' directory
exist_ok: False  # (bool) whether to overwrite existing experiment
pretrained: True  # (bool | str) whether to use a pretrained model (bool) or a model to load weights from (str)
optimizer: auto  # (str) optimizer to use, choices=[SGD, Adam, Adamax, AdamW, NAdam, RAdam, RMSProp, auto]
verbose: True  # (bool) whether to print verbose output
seed: 0  # (int) random seed for reproducibility
deterministic: True  # (bool) whether to enable deterministic mode
single_cls: False  # (bool) train multi-class data as single-class
rect: False  # (bool) rectangular training if mode='train' or rectangular validation if mode='val'
cos_lr: False  # (bool) use cosine learning rate scheduler
close_mosaic: 10  # (int) disable mosaic augmentation for final epochs (0 to disable)
resume: False  # (bool) resume training from last checkpoint
amp: True  # (bool) Automatic Mixed Precision (AMP) training, choices=[True, False], True runs AMP check
fraction: 1.0  # (float) dataset fraction to train on (default is 1.0, all images in train set)
profile: False  # (bool) profile ONNX and TensorRT speeds during training for loggers
freeze: None  # (int | list, optional) freeze first n layers, or freeze list of layer indices during training
# Segmentation
overlap_mask: True  # (bool) masks should overlap during training (segment train only)
mask_ratio: 4  # (int) mask downsample ratio (segment train only)
# Classification
dropout: 0.0  # (float) use dropout regularization (classify train only)

YOLOv8提供CLI和python两种训练方式

CLI就是直接在终端运行指令

python需要新建一个python文件,然后运行代码

yolov8命令行的统一运行格式为:

yolo TASK MODE ARGS

其中主要是三部分传参:

TASK(可选) :含义是选择任务类型,从[detect、segment、classification]中选一个。如果没有显式传递,YOLOv8将尝试从模型类型中猜测TASK。
MODE(必选) :是训练、验证还是预测的任务,可从[train, val, predict, export]中选一个
ARGS(可选) : 是任意数量的自定义arg=value对,如imgsz=320,覆盖默认值。

1.CLI指令

命令行中执行代码:

yolo task=detect mode=train model=/home/xuh/AI_Industrial_Internet/PCB_detect_model/YOLOv8/ultralytics/weights/yolov8s.pt data=/home/xuh/AI_Industrial_Internet/PCB_detect_model/YOLOv8/ultralytics/PCB_dataSets/VOC_PCB/PCB.yaml batch=32 epochs=100 imgsz=640 workers=16 device='0,1'

2.python指令训练方式

在YOLOv8包中,新建train.py,代码如下:

from ultralytics import YOLO

# Load a model
# model = YOLO('yolov8n.yaml')  # build a new model from YAML   从YAML中构建一个新模型
# model = YOLO('yolov8n.pt')  # load a pretrained model (recommended for training) 加载预训练的模型(推荐用于训练)
model = YOLO('yolov8s.yaml').load('ultralytics/weights/yolov8s.pt ')  # build from YAML and transfer weights 从YAML构建并传递权重

# Train the model
model.train(data='ultralytics/PCB_dataSets/VOC_PCB/PCB.yaml', epochs=100, imgsz=640)

model类方法train(训练)的参数:

Key Value Description
device “1” Cuda设备,即0或0、1、2、3或cpu。选择可用的cuda0设备
epochs 100 需要训练的epoch数
workers 8 每个进程使用的cpu worker数。使用DDP自动伸缩
batch 16 Dataloader的batch大小
imgsz 640 Dataloader中图像数据的大小
optimizer SGD 支持的优化器:Adam, SGD, RMSProp
single_cls False 将多类数据作为单类进行训练
image_weights False 使用加权图像选择进行训练
rect False 启用矩形训练
cos_lr False 使用cosine LR调度器
lr0 0.01 初始化学习率
lrf 0.01 最终的OneCycleLR学习率
momentum 0.937 作为SGD的momentum和Adam的beta1
weight_decay 0.0005 优化器权重衰减
warmup_epochs 3.0 Warmup的epoch数,支持分数
warmup_momentum 0.8 warmup的初始动量
warmup_bias_lr 0.1 Warmup的初始偏差lr
box 0.05 Box loss gain
cls 0.5 cls loss gain
cls_pw 1.0 cls BCELoss positive_weight
obj 1.0 bj loss gain (scale with pixels)
obj_pw 1.0 obj BCELoss positive_weight
iou_t 0.20 iou训练时的阈值
anchor_t 4.0 anchor-multiple阈值
fl_gamma 0.0 focal loss gamma
label_smoothing 0.0
nbs 64 nominal batch size
overlap_mask True 分割:在训练中使用掩码重叠
mask_ratio 4 分割:设置掩码下采样
dropout False 分类:训练时使用dropout

4、模型预测

YOLO模型的预测设置是指用于在新数据上使用模型进行预测的各种超参数和配置。这些设置会影响模型的性能、速度和精度。一些常见的YOLO预测设置包括置信度阈值、非最大抑制(NMS)阈值和要考虑的类别数量。其他可能影响预测过程的因素包括输入数据的大小和格式,是否存在额外的特征(如掩码或每个框的多个标签),以及模型正在用于的特定任务。重要的是要仔细调整和试验这些设置,以实现给定任务的最佳性能。

1.predcit方法的参数

Key Value Description
source ultralytics/assets 输入源。支持图片、文件夹、视频、网址
show False 查看预测图片
save_txt False 保存结果到txt文件中
save_conf False 保存condidence scores
save_crop Fasle
hide_labels False 隐藏labels
hide_conf False 隐藏confidence scores
vid_stride False 输入视频帧率步长
line_thickness 3 边框厚度(单位:像素)
visualize False 可视化模型特征
augment False 增强推理
agnostic_nms False Class-agnostic NMS
retina_masks False 分割:高分辨率掩模

1.CLI指令

yolo task=detect mode=predict model=runs/detect/train2/weights/best.pt source=data/images device=0

2.python指令预测方式

在YOLOv8包中,新建predict.py,代码如下:

from ultralytics import YOLO
# Load a model
model = YOLO('runs/detect/train4/weights/best.pt')  # load a custom model

# Predict with the model
results = model.predict(source='ultralytics/PCB_dataSets/test_img/l_light_01_missing_hole_05_2_600.jpg',save=True)  # predict on an image

2. model类predcit方法的返回值

返回值是一个对象列表,具有如下属性:

属性 类型 描述
orig_img numpy.ndarray 原始图像的numpy数组。
orig_shape tuple 原始图像的形状,格式为(高度,宽度)。
boxes Boxes, 可选 包含检测边界框的Boxes对象。
masks Masks, 可选 包含检测掩码的Masks对象。
probs Probs, 可选 包含每个类别的概率的Probs对象,用于分类任务。
keypoints Keypoints, 可选 包含每个对象检测到的关键点的Keypoints对象。
speed dict 以毫秒为单位的每张图片的预处理、推理和后处理速度的字典。
names dict 类别名称的字典。
path str 图像文件的路径。

5、模型验证

CLI指令验证方式

yolo task=detect mode=val model=yolov8n.pt
# mode=val 就是看验证集
yolo task=detect mode=val split=val model=runs/detect/train2/weights/best.pt data=ultralytics/datasets/MoonCake.yaml
# mode=test 就是看测试集
yolo task=detect mode=val split=test model=runs/detect/train2/weights/best.pt data=ultralytics/datasets/MoonCake.yaml

Python指令验证方式

在YOLOv8代码包中,新建val.py,代码如下:

from ultralytics import YOLO

# Load a model
# model = YOLO('yolov8n.pt')  # load an official model
model = YOLO('runs/detect/train4/weights/best.pt')  # load a custom model

# Validate the model
metrics = model.val()  # no arguments needed, dataset and settings remembered
metrics.box.map    # map50-95
metrics.box.map50  # map50
metrics.box.map75  # map75
metrics.box.maps   # a list contains map50-95 of each category

model类方法val(验证)的参数:

一些比较常用的传参:

model	需要评估的pt模型文件路径
data	需要评估的数据集yaml文件
imgsz	评估图片推理大小,默认640
batch	评估推理批次,默认16
save_json	是否保存评估结果为json输出,默认False
save_hybrid	是否保存混合版本的标签(标签+额外的预测)
conf	模型评估置信度阈值,默认0.001
iou	模型评估iou阈值,默认0.6
max_det	单张图最大检测目标数量,默认300
half	是否使用fp16推理,默认True
device	要运行的设备,即cuda device =0或Device =0,1,2,3或device = cpu
dnn	是否使用use OpenCV DNN for ONNX inference,默认Flase
rect	是否使用矩形推理,默认False
split	数据集分割用于验证,即val、 test、train,默认val

6、参考文章

1.YOLOv8官方文档
2.YOLOv8运行参数解读
3.YOLOV8模型训练+部署(实战)
4.Jetson nano部署YOLOv8
5.YOLOv8训练自己的数据集(超详细)
6.【YOLO】YOLOv8训练自定义数据集(4种方式)
这几篇文章写的都很棒,受益良多。

你可能感兴趣的:(YOLO,深度学习,pytorch,计算机视觉)