yolov10在训练数据集之前所需要的环境配置请看前三篇文章:
深度学习之linux环境中配置Python3.9.0-优快云博客
深度学习之linux环境搭建----安装pytorch2.0.1和CUDA11.8配置yolov10(2)-优快云博客
参考文章:YOLOv10 | 手把手教你利用yolov10训练自己数据集(含环境搭建、参数解析 、数据集查找、模型训练、推理、导出)-优快云博客
使用YOLOv10训练自己的【目标检测】数据集-【收集数据集】-【标注数据集】-【划分数据集】-【配置训练环境】-【训练模型】-【评估模型】-【导出模型】_yolov10 如何标注自己的数据集-优快云博客 我使用的是现有的数据集,没有数据集的伙伴们根据上面这篇博文去建立自己的数据集哈。
YOLOv10 默认使用的是 YOLO 格式的标签文件(.txt
文件)。如果你的标签文件是 XML 格式(如 Pascal VOC 格式),你需要先将它们转换为 YOLO 格式。
1. 转换 XML 文件为 YOLO 格式
首先,创建一个 Python 脚本,将 Pascal VOC 格式的 XML 文件转换为 YOLO 格式的文本文件。
-
确保你在 YOLOv10 环境中:
conda activate yolov10
-
导航到
yolo-main
目录:cd ~/**/**/yolov10-main
-
使用文本编辑器创建
voc_to_yolo.py
脚本:nano voc_to_yolo.py
-
将以下代码复制粘贴到
voc_to_yolo.py
中,然后保存并退出编辑器:import os import xml.etree.ElementTree as ET def convert(size, box): dw = 1. / size[0] dh = 1. / size[1] x = (box[0] + box[1]) / 2.0 - 1 y = (box[2] + box[3]) / 2.0 - 1 w = box[1] - box[0] h = box[3] - box[2] x = x * dw w = w * dw y = y * dh h = h * dh return (x, y, w, h) def convert_annotation(xml_file, classes): in_file = open(xml_file) tree = ET.parse(in_file) root = tree.getroot() size = root.find('size') w = int(size.find('width').text) h = int(size.find('height').text) yolo_lines = [] for obj in root.iter('object'): difficult = obj.find('difficult').text cls = obj.find('name').text if cls not in classes or int(difficult) == 1: continue cls_id = classes.index(cls) xmlbox = obj.find('bndbox') b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text), float(xmlbox.find('ymax').text)) yolo_box = convert((w, h), b) yolo_lines.append(f"{cls_id} " + " ".join([str(a) for a in yolo_box]) + '\n') return yolo_lines def convert_dataset(xml_dir, output_dir, classes): if not os.path.exists(output_dir): os.makedirs(output_dir) for xml_file in os.listdir(xml_dir): if xml_file.endswith(".xml"): xml_path = os.path.join(xml_dir, xml_file) yolo_lines = convert_annotation(xml_path, classes) yolo_file = os.path.join(output_dir, os.path.splitext(xml_file)[0] + ".txt") with open(yolo_file, 'w') as out_file: out_file.writelines(yolo_lines) if __name__ == "__main__": xml_directory = "/path/to/xml/files" output_directory = "/path/to/yolo/labels" classes = ["class1", "class2", "class3"] # your class names convert_dataset(xml_directory, output_directory, classes)
-
修改
xml_directory
、output_directory
和classes
变量,使其指向你的数据集和类别名称。
6.在终端中运行以下命令:
python voc_to_yolo.py
这样,所有的 XML 文件将会被转换为 YOLO 格式的标签文件并存放在指定的输出目录中。
2.划分数据集
car
├─images
└─all
└─labels
└─all
这是目前数据集的目录结构,需要划分数据集。
依旧是在此环境路径下创建一个python脚本,写入代码,划分数据集。
import os
import shutil
import random
def split_dataset(images_dir, labels_dir, output_dir, train_ratio=0.8, val_ratio=0.1, test_ratio=0.1):
images = [f for f in os.listdir(images_dir) if f.endswith('.jpg')]
random.shuffle(images)
train_count = int(len(images) * train_ratio)
val_count = int(len(images) * val_ratio)
test_count = len(images) - train_count - val_count
train_images = images[:train_count]
val_images = images[train_count:train_count + val_count]
test_images = images[train_count + val_count:]
def copy_files(file_list, src_dir, dst_dir):
if not os.path.exists(dst_dir):
os.makedirs(dst_dir)
for file in file_list:
src_file = os.path.join(src_dir, file)
dst_file = os.path.join(dst_dir, file)
shutil.copy(src_file, dst_file)
label_file = file.replace('.jpg', '.txt')
src_label_file = os.path.join(labels_dir, label_file)
if os.path.exists(src_label_file):
dst_label_dir = os.path.join(output_dir, 'labels', os.path.basename(dst_dir))
if not os.path.exists(dst_label_dir):
os.makedirs(dst_label_dir)
dst_label_file = os.path.join(dst_label_dir, label_file)
shutil.copy(src_label_file, dst_label_file)
copy_files(train_images, images_dir, os.path.join(output_dir, 'images/train'))
copy_files(val_images, images_dir, os.path.join(output_dir, 'images/val'))
copy_files(test_images, images_dir, os.path.join(output_dir, 'images/test'))
print(f"Dataset split completed: {train_count} train, {val_count} val, {test_count} test")
if __name__ == "__main__":
images_directory = "/home/***/car/images/all" # 修改为你的图像目录
labels_directory = "/home/***/car/labels/all" # 修改为你的标签目录
output_directory = "/home/***/car" # 修改为输出目录
split_dataset(images_directory, labels_directory, output_directory)
这样,脚本会自动遍历 images
和 labels
目录下的所有子目录,将数据集划分为训练集、验证集和测试集。如果你的目录结构不同,请根据实际情况调整脚本中的路径。
3.模型训练
-
准备数据集配置文件:
- 创建
data.yaml
文件,包含数据集路径和类别信息。
- 创建
nano data.yaml
-
创建模型配置文件:(这一部分有一些复杂,写的比较乱,只是记录了我遇到的错误以及解决方案,有实力的话找chatgpt帮忙训练吧)
根据需要修改data.yaml
文件。-
train: /home/*/yolo10/car/images/train
val: /home/*/yolo10/car/images/val
test: /home/*/yolo10/car/images/test # optionaltrain_labels: /home/*/yolo10/car/labels/train
val_labels: /home/*/yolo10/car/labels/val
test_labels: /home/*/yolo10/car/labels/test # optionalnc: 1 # number of classes
names: ['car'] # class names
-
运行训练脚本:
- 使用
train.py
脚本开始训练模型。 - python train.py --data data.yaml --cfg models/yolov10.yaml --weights '' --epochs 100 --batch-size 16 --img-size 640
- 这个语句出错率很高,建议使用AI复查不断修改。最后创建了一个train——yolov10.py文件加入了代码,但到最后运行的时候还是出错了。
-
import sys import os from ultralytics import YOLO # 将项目根目录添加到 Python 路径 sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) if __name__ == '__main__': import argparse parser = argparse.ArgumentParser() parser.add_argument('--data', type=str, required=True, help='data.yaml path') parser.add_argument('--cfg', type=str, required=True, help='model.yaml path') parser.add_argument('--weights', type=str, default='', help='initial weights path') parser.add_argument('--epochs', type=int, default=100, help='number of epochs') parser.add_argument('--batch', type=int, default=16, help='batch size') parser.add_argument('--imgsz', type=int, default=640, help='image size') opt = parser.parse_args() model = YOLO(opt.cfg) # 初始化 YOLO 模型 model.train(data=opt.data, epochs=opt.epochs, batch=opt.batch, imgsz=opt.imgsz)
运行以下命令:
python train_yolov10.py --data data.yaml --cfg ultralytics/cfg/models/v10/yolov10n.yaml --weights '' epochs=100 batch=16 imgsz=640
- 到最后才发现torch版本和torchvison版本不匹配,可能原先下载的时候出了什么差错,只能重装。
-
pip uninstall torch torchvision
过程极其漫长,下了一晚上@_@conda install pytorch==2.0.1 torchvision==0.15.2 -c pytorch
下载好以后运行命令,依旧报错了,CUDA 设备端断言错误,又添加了: -
export CUDA_LAUNCH_BLOCKING=1
运行后还是报错,修改ultralytics/engine/trainer.py,在 for i, batch in enumerate(self.dataloader): 循环的开始部分插入打印语句 print("Batch data:", batch)。
-
根据输出结果判断:遇到的错误与 CUDA 设备上的设备端断言失败有关。这通常是由越界索引引起的,当张量具有意外的形状或值时,可能会发生这种情况。
可以采取以下一些步骤来排查和解决此问题:
-
启用详细的 CUDA 错误消息: 在启用标志的情况下重新编译 PyTorch。这将提供有关设备端断言的更详细的错误消息,这有助于查明错误的确切位置和原因。为此,您需要使用标志从源代码构建 PyTorch。以下是一组简化的步骤:
# Clone the PyTorch repository git clone --recursive https://github.com/pytorch/pytorch cd pytorch # Set the environment variable export TORCH_USE_CUDA_DSA=1 # Install dependencies pip install -r requirements.txt # Build and install PyTorch python setup.py install
第一步执行时长大概在20分钟左右,使用pip下载问题挺多。找一个网络好的时候下载。若有无法克隆的选项请参考这篇文章:深度学习之pytorch编译-优快云博客
-
然后执行第二步。
OK,fine,解决了pytorch编译,又来一个GCC版本不匹配。升级 GCC版本参考这篇文章:深度学习之训练数据集时遇到GCC版本不匹配-优快云博客
最后一步也很烦人,也是报出了好多错误^~^
- 使用
-
-
运行语句出错检查:
python train_yolov10.py --data data.yaml --cfg ultralytics/cfg/models/v10/yolov10n.yaml --weights '' --epochs 100 --batch 16 --imgsz 640
- 这句代码在使用前请检查好数据集的标签和格式正确。特别是检查
data.yaml
文件中定义的类别数目(nc
)是否正确。如果你的数据集中只有一个类别,确保在ultralytics/cfg/models/v10/yolov10n.yaml
文件中定义的nc
也是 1。- 若误信息中提到有新版本的
ultralytics
库可用。尝试更新库并重新运行训练。pip install -U ultralytics- 在
ultralytics/utils/tal.py
文件中的get_box_metrics
函数里添加一些调试信息,打印pd_scores
、ind
和mask_gt
的形状和内容,确认它们的维度是否符合预期。- 确保所有标签文件中的类别编号从
0
开始,而不是从1
开始。import os def check_and_correct_labels(label_path): for root, dirs, files in os.walk(label_path): for label_file in files: if label_file.endswith(".txt"): file_path = os.path.join(root, label_file) print(f"Processing file: {file_path}") with open(file_path, 'r') as file: lines = file.readlines() corrected_lines = [] for line in lines: parts = line.strip().split() if len(parts) > 0: class_id = int(parts[0]) if class_id != 0: print(f"Correcting class ID {class_id} to 0 in file: {file_path}") parts[0] = '0' corrected_lines.append(' '.join(parts)) with open(file_path, 'w') as file: file.write('\n'.join(corrected_lines) + '\n') label_path = '/***/yolo10/yolov10-main/lables' # 修改为你的labels文件夹的路径 check_and_correct_labels(label_path)
确保你已经将上述脚本保存为
fix_labels_recursive.py
,并将路径label_path
修改为你的实际标签文件路。在终端中导航到脚本所在的目录:cd ~/***/yolov10-main
在终端中运行脚本:
python fix_labels_recursive.py