当前位置: 首页 > news >正文

YOLOv11模型训练

一、数据集

创建的个人数据集GL dataset

标注:用Labelme标注图片,得到图片标注json文件

数据格式:使用labelme2yolo.py将数据集转换为YOLO数据格式

#labelme2yolo.py
import os
import sys
import argparse
import shutil
import math
from collections import OrderedDictimport json
import cv2
import PIL.Imagefrom sklearn.model_selection import train_test_split
from labelme import utilsclass Labelme2YOLO(object):def __init__(self, json_dir, to_seg=False):self._json_dir = json_dirself._label_id_map = self._get_label_id_map(self._json_dir)self._to_seg = to_segi = 'YOLODataset'i += '_seg/' if to_seg else '/'self._save_path_pfx = os.path.join(self._json_dir, i)def _make_train_val_dir(self):self._label_dir_path = os.path.join(self._save_path_pfx, 'labels/')self._image_dir_path = os.path.join(self._save_path_pfx, 'images/')for yolo_path in (os.path.join(self._label_dir_path + 'train/'),os.path.join(self._label_dir_path + 'val/'),os.path.join(self._image_dir_path + 'train/'), os.path.join(self._image_dir_path + 'val/')):if os.path.exists(yolo_path):shutil.rmtree(yolo_path)os.makedirs(yolo_path)    def _get_label_id_map(self, json_dir):label_set = set()for file_name in os.listdir(json_dir):if file_name.endswith('json'):json_path = os.path.join(json_dir, file_name)data = json.load(open(json_path, encoding='utf-8'))for shape in data['shapes']:label_set.add(shape['label'])return OrderedDict([(label, label_id) \for label_id, label in enumerate(label_set)])def _train_test_split(self, folders, json_names, val_size):if len(folders) > 0 and 'train' in folders and 'val' in folders:train_folder = os.path.join(self._json_dir, 'train/')train_json_names = [train_sample_name + '.json' \for train_sample_name in os.listdir(train_folder) \if os.path.isdir(os.path.join(train_folder, train_sample_name))]val_folder = os.path.join(self._json_dir, 'val/')val_json_names = [val_sample_name + '.json' \for val_sample_name in os.listdir(val_folder) \if os.path.isdir(os.path.join(val_folder, val_sample_name))]return train_json_names, val_json_namestrain_idxs, val_idxs = train_test_split(range(len(json_names)), test_size=val_size)train_json_names = [json_names[train_idx] for train_idx in train_idxs]val_json_names = [json_names[val_idx] for val_idx in val_idxs]return train_json_names, val_json_namesdef convert(self, val_size):json_names = [file_name for file_name in os.listdir(self._json_dir) \if os.path.isfile(os.path.join(self._json_dir, file_name)) and \file_name.endswith('.json')]folders =  [file_name for file_name in os.listdir(self._json_dir) \if os.path.isdir(os.path.join(self._json_dir, file_name))]train_json_names, val_json_names = self._train_test_split(folders, json_names, val_size)self._make_train_val_dir()# convert labelme object to yolo format object, and save them to files# also get image from labelme json file and save them under images folderfor target_dir, json_names in zip(('train/', 'val/'), (train_json_names, val_json_names)):for json_name in json_names:json_path = os.path.join(self._json_dir, json_name)json_data = json.load(open(json_path, encoding='utf-8'))print('Converting %s for %s ...' % (json_name, target_dir.replace('/', '')))img_path = self._save_yolo_image(json_data, json_name, self._image_dir_path, target_dir)yolo_obj_list = self._get_yolo_object_list(json_data, img_path)self._save_yolo_label(json_name, self._label_dir_path, target_dir, yolo_obj_list)print('Generating dataset.yaml file ...')self._save_dataset_yaml()def convert_one(self, json_name):json_path = os.path.join(self._json_dir, json_name)json_data = json.load(open(json_path, encoding='utf-8'))print('Converting %s ...' % json_name)img_path = self._save_yolo_image(json_data, json_name, self._json_dir, '')yolo_obj_list = self._get_yolo_object_list(json_data, img_path)self._save_yolo_label(json_name, self._json_dir, '', yolo_obj_list)def _get_yolo_object_list(self, json_data, img_path):yolo_obj_list = []img_h, img_w, _ = cv2.imread(img_path).shapefor shape in json_data['shapes']:# labelme circle shape is different from others# it only has 2 points, 1st is circle center, 2nd is drag end pointif shape['shape_type'] == 'circle':yolo_obj = self._get_circle_shape_yolo_object(shape, img_h, img_w)else:yolo_obj = self._get_other_shape_yolo_object(shape, img_h, img_w)yolo_obj_list.append(yolo_obj)return yolo_obj_listdef _get_circle_shape_yolo_object(self, shape, img_h, img_w):label_id = self._label_id_map[shape['label']]obj_center_x, obj_center_y = shape['points'][0]radius = math.sqrt((obj_center_x - shape['points'][1][0]) ** 2 +(obj_center_y - shape['points'][1][1]) ** 2)if self._to_seg:retval = [label_id]n_part = radius / 10n_part = int(n_part) if n_part > 4 else 4n_part2 = n_part << 1pt_quad = [None for i in range(0, 4)]pt_quad[0] = [[obj_center_x + math.cos(i * math.pi / n_part2) * radius,obj_center_y - math.sin(i * math.pi / n_part2) * radius]for i in range(1, n_part)]pt_quad[1] = [[obj_center_x * 2 - x1, y1] for x1, y1 in pt_quad[0]]pt_quad[1].reverse()pt_quad[3] = [[x1, obj_center_y * 2 - y1] for x1, y1 in pt_quad[0]]pt_quad[3].reverse()pt_quad[2] = [[obj_center_x * 2 - x1, y1] for x1, y1 in pt_quad[3]]pt_quad[2].reverse()pt_quad[0].append([obj_center_x, obj_center_y - radius])pt_quad[1].append([obj_center_x - radius, obj_center_y])pt_quad[2].append([obj_center_x, obj_center_y + radius])pt_quad[3].append([obj_center_x + radius, obj_center_y])for i in pt_quad:for j in i:j[0] = round(float(j[0]) / img_w, 6)j[1] = round(float(j[1]) / img_h, 6)retval.extend(j)return retvalobj_w = 2 * radiusobj_h = 2 * radiusyolo_center_x= round(float(obj_center_x / img_w), 6)yolo_center_y = round(float(obj_center_y / img_h), 6)yolo_w = round(float(obj_w / img_w), 6)yolo_h = round(float(obj_h / img_h), 6)return label_id, yolo_center_x, yolo_center_y, yolo_w, yolo_hdef _get_other_shape_yolo_object(self, shape, img_h, img_w):label_id = self._label_id_map[shape['label']]if self._to_seg:retval = [label_id]for i in shape['points']:i[0] = round(float(i[0]) / img_w, 6)i[1] = round(float(i[1]) / img_h, 6)retval.extend(i)return retvaldef __get_object_desc(obj_port_list):__get_dist = lambda int_list: max(int_list) - min(int_list)x_lists = [port[0] for port in obj_port_list]        y_lists = [port[1] for port in obj_port_list]return min(x_lists), __get_dist(x_lists), min(y_lists), __get_dist(y_lists)obj_x_min, obj_w, obj_y_min, obj_h = __get_object_desc(shape['points'])yolo_center_x= round(float((obj_x_min + obj_w / 2.0) / img_w), 6)yolo_center_y = round(float((obj_y_min + obj_h / 2.0) / img_h), 6)yolo_w = round(float(obj_w / img_w), 6)yolo_h = round(float(obj_h / img_h), 6)return label_id, yolo_center_x, yolo_center_y, yolo_w, yolo_hdef _save_yolo_label(self, json_name, label_dir_path, target_dir, yolo_obj_list):txt_path = os.path.join(label_dir_path, target_dir, json_name.replace('.json', '.txt'))with open(txt_path, 'w+') as f:for yolo_obj_idx, yolo_obj in enumerate(yolo_obj_list):yolo_obj_line = ""for i in yolo_obj:yolo_obj_line += f'{i} 'yolo_obj_line = yolo_obj_line[:-1]if yolo_obj_idx != len(yolo_obj_list) - 1:yolo_obj_line += '\n'f.write(yolo_obj_line)def _save_yolo_image(self, json_data, json_name, image_dir_path, target_dir):img_name = json_name.replace('.json', '.png')img_path = os.path.join(image_dir_path, target_dir,img_name)if not os.path.exists(img_path):img = utils.img_b64_to_arr(json_data['imageData'])PIL.Image.fromarray(img).save(img_path)return img_pathdef _save_dataset_yaml(self):yaml_path = os.path.join(self._save_path_pfx, 'dataset.yaml')with open(yaml_path, 'w+') as yaml_file:yaml_file.write('train: %s\n' % \os.path.join(self._image_dir_path, 'train/'))yaml_file.write('val: %s\n\n' % \os.path.join(self._image_dir_path, 'val/'))yaml_file.write('nc: %i\n\n' % len(self._label_id_map))names_str = ''for label, _ in self._label_id_map.items():names_str += "'%s', " % labelnames_str = names_str.rstrip(', ')yaml_file.write('names: [%s]' % names_str)if __name__ == '__main__':parser = argparse.ArgumentParser()parser.add_argument('--json_dir',type=str,help='Please input the path of the labelme json files.')parser.add_argument('--val_size',type=float, nargs='?', default=0.1,help='Please input the validation dataset size, for example 0.1 ')parser.add_argument('--json_name',type=str, nargs='?', default=None,help='If you put json name, it would convert only one json file to YOLO.')parser.add_argument('--seg', action='store_true',help='Convert to YOLOv5 v7.0 segmentation dataset')args = parser.parse_args(sys.argv[1:])convertor = Labelme2YOLO(args.json_dir, to_seg=args.seg)if args.json_name is None:convertor.convert(val_size=args.val_size)else:convertor.convert_one(args.json_name)

yolo数据集目录:

dataset/
├── images/
│   ├── train/
│   │   ├── xxx.jpg
│   │   └── ...
│   ├── val/
│   │   ├── yyy.jpg
│   │   └── ...
│   └── test/              # 可选(推理/测试用)
│       ├── zzz.jpg
│       └── ...
├── labels/
│   ├── train/
│   │   ├── xxx.txt
│   │   └── ...
│   ├── val/
│   │   ├── yyy.txt
│   │   └── ...
│   └── test/              # 可选
│       ├── zzz.txt
│       └── ...
└── data.yaml              # 数据配置文件

数据集图片按照 训练集(train):验证集(val):测试集(test) = 8:1:1 的比例

二、模型配置

目标检测模型(传统深度学习模型https://github.com/ultralytics/ultralytics

安装yolo模型:安装Ultralytics -Ultralytics YOLO 文档

选择yolo11m.pt

#我的代码和环境
Ultralytics 8.3.131 
Python-3.10.16 
torch-1.12.1+cu113 #CUDA:11.3
CUDA:2 (NVIDIA GeForce GTX TITAN X, 12213MiB)

三、执行训练

 参数:配置 -Ultralytics YOLO 文档

#训练命令
yolo detect train   data=/gl_yolo/dataset.yaml   model=/ultralytics/gl_yolo/yolo11m.pt   epochs=100   batch=16   imgsz=640   device=2   amp=True   workers=8 cache=True

训练过程中遇到的问题

1、错误信息:

ImportError: Cannot load backend 'tkagg' which requires the 'tk' interactive framework, as 'headless' is currently running

解决方案:

MPLBACKEND=Agg

MPLBACKEND=Agg 用于防止 Tk backend 报错(无图形界面的服务器环境必须加)

2、错误信息:

ImportError: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.29' not found (required by /anaconda3/envs/yolo/lib/python3.10/site-packages/PIL/../../.././libLerc.so.4)

解决方案:

LD_LIBRARY_PATH=$CONDA_PREFIX/lib:$LD_LIBRARY_PATH

3、错误信息:

RuntimeError: Numpy is not availablenumpy                     2.2.5                    pypi_0    pypi
numpy-base                2.0.1           py310hb5e798b_1

解决方案:

pip uninstall numpy
conda uninstall numpy
conda install numpy==1.23.5

最终的训练命令:

LD_LIBRARY_PATH=$CONDA_PREFIX/lib:$LD_LIBRARY_PATH \
MPLBACKEND=Agg \
nohup yolo detect train \data=/ultralytics/gl_yolo/dataset.yaml \model=/ultralytics/gl_yolo/yolo11m.pt \epochs=100 \batch=16 \imgsz=640 \device=2 \amp=True \workers=8 \
cache=True > train.log 2>&1 &

nohup 命令允许将一个命令放到后台运行,并且即使关闭终端或注销,进程也不会停止 

结果:

四、生成的训练结果

Ultralytics YOLO 会在训练结束(或中途):

        每完成 一个 epoch,会记录一次训练结果到 runs/detect/train/results.csv

        每次验证后,也会生成 多个曲线图:

                F1 curve.png

                PR curve.png

                R curve.png

                P curve.png

                confusion_matrix.png 等

        训练完成后,会生成综合图:results.png,其中包含:

                box loss, cls loss, DFL loss(回归损失)

                P / R / mAP@50 / mAP@50-95 等

重新生成某些图像(如 confusion_matrix.png)命令:

LD_LIBRARY_PATH=$CONDA_PREFIX/lib:$LD_LIBRARY_PATH \
MPLBACKEND=Agg 
yolo detect val \model=runs/detect/train/weights/best.pt \data=/ultralytics/gl_yolo/dataset.yaml \save_json=True \save_txt=True

结果:生成val文件夹,其中含有下列内容

Labels 文件夹
confusion matrix.png
p confusion matrix normalized.png
F1 curve.png
P curve.png
PR curve.png
predictions.json
R curve.png
val batch0 labels.jpg
val batch0 pred.jpg
val batch1 labels.jpg
val batch1 pred.jpg
val batch2 labels.jpg
val batch2 pred.jpg

文件名

说明

confusion_matrix.png

标准混淆矩阵,显示每个类别的真实值与预测值之间的对应情况(横轴预测,纵轴真实)。用于分析分类错误。

confusion_matrix_normalized.png

归一化混淆矩阵(按真实标签行归一化),更清晰反映每类预测准确率。适合样本不均衡的情况。

F1_curve.png

显示每个类别的 F1 分数(综合考虑精度和召回率)随阈值变化的曲线。用于挑选最佳置信度阈值。

P_curve.png

精度(Precision)随置信度阈值的变化曲线。越平稳越好。

R_curve.png

召回率(Recall)随置信度阈值变化的曲线。

PR_curve.png

精度-召回曲线(Precision vs Recall Curve),越靠近右上角说明模型越好。

predictions.json

保存了模型在验证集上的预测结果(包括类别、置信度、边界框等),供 COCO 等评估工具使用。

文件名

说明

val_batch0_labels.jpg

可视化验证集中第一个 batch 的真实标签框(ground truth)。

val_batch0_pred.jpg

可视化第一个 batch 的预测框(含置信度和类别)。

val_batch1_labels.jpg

第二个 batch 的真实标签框。

val_batch1_pred.jpg

第二个 batch 的预测框。

val_batch2_labels.jpg

第三个 batch 的真实标签框。

val_batch2_pred.jpg

第三个 batch 的预测框。

YOLOv8 中的图表生成方式

当你运行 YOLOv8 的训练命令:

yolo train model=yolov8n.pt data=your_data.yaml epochs=100 imgsz=640

YOLOv8 会在训练过程中自动保存以下图表(在 runs/train/exp*/ 文件夹下):

📈 YOLOv8 自动生成的图表包括:

图表类型说明
results.png包含以下图表的合成图:
- 训练损失(box loss, cls loss 等)
- 精度(Precision)
- 召回率(Recall)
- mAP@0.5
confusion_matrix.png混淆矩阵图
F1_curve.pngF1 分数随阈值变化的曲线
PR_curve.pngPrecision-Recall 曲线图

你可以使用以下命令单独执行验证,重新生成这些图表:

yolo val model=runs/train/exp/weights/best.pt data=your_data.yaml

🗂 文件结构示意:

runs/
└── train/└── exp/├── results.png                ← 所有图表的汇总├── confusion_matrix.png       ← 混淆矩阵├── PR_curve.png               ← PR 曲线├── F1_curve.png               ← F1 曲线└── weights/├── best.pt└── last.pt

你可以直接打开这些 .png 文件查看图表。

http://www.xdnf.cn/news/594883.html

相关文章:

  • Spring Ioc和Aop,Aop的原理和实现案例,JoinPoint,@Aspect,@Before,@AfterReturning
  • 如何使用小爱音响控制海尔等第三方平台设备
  • 从实验室到产业化:探究FSHD 技术发展史如何重塑显示行业格局?
  • 【物理学】声子:凝聚态物理中的关键概念
  • 视觉理解多模态模型转为API服务
  • 【Hexo】1.搭建本地初始默认的博客
  • 链表day4
  • 多线程初阶(3)
  • 数据表格控件TeeGrid for VCL/FMX:让数据“说话”更直观!
  • Android滑动冲突解决方法
  • 西交交互增强与细节引导的具身导航!OIKG:基于观察图交互与关键细节融合框架下的视觉语言导航
  • unittest
  • GITLIbCICD流水线搭建
  • 【Java高阶面经:数据库篇】17、分库分表分页查询优化:告别慢查询与内存爆炸
  • 软件设计师“设计原则”真题考点分析——求三连
  • [Usaco2007 Dec]队列变换 题解
  • AUTOSAR图解==>AUTOSAR_SRS_PortDriver
  • 硅基计划2.0 学习总结 叁
  • CLIP中的被动学习
  • OpenAI宣布:核心API支持MCP,助力智能体开发
  • memcpy 函数的使用 (C语言)
  • 110kV/630mm2电缆5km的交流耐压试验兼顾110kVGIS开关用
  • 彩礼的异化:婚姻市场中的资本规训与性别政治批判
  • NV013NV024美光固态闪存NV028NV034
  • Tomcat多实例配置
  • 从零开始学习QT——第一步
  • vue组件渲染到iframe里面(同域名下),组件可以在同一项目下维护
  • VPC的作用
  • python调wfdb库读欧洲st-t数据库
  • 让办公更聪明:OA系统如何重塑企业协作模式