深度学习之YOLOV10训练自己的数据集一(4)

yolov10在训练数据集之前所需要的环境配置请看前三篇文章: 

深度学习之linux环境中配置Python3.9.0-优快云博客

深度学习之linux环境搭建----安装pytorch2.0.1和CUDA11.8配置yolov10(2)-优快云博客

深度学习之yolov10模型测试(3)-优快云博客

参考文章:YOLOv10 | 手把手教你利用yolov10训练自己数据集(含环境搭建、参数解析 、数据集查找、模型训练、推理、导出)-优快云博客

使用YOLOv10训练自己的【目标检测】数据集-【收集数据集】-【标注数据集】-【划分数据集】-【配置训练环境】-【训练模型】-【评估模型】-【导出模型】_yolov10 如何标注自己的数据集-优快云博客 我使用的是现有的数据集,没有数据集的伙伴们根据上面这篇博文去建立自己的数据集哈。

YOLOv10 默认使用的是 YOLO 格式的标签文件(.txt 文件)。如果你的标签文件是 XML 格式(如 Pascal VOC 格式),你需要先将它们转换为 YOLO 格式。

1. 转换 XML 文件为 YOLO 格式

首先,创建一个 Python 脚本,将 Pascal VOC 格式的 XML 文件转换为 YOLO 格式的文本文件。

  1. 确保你在 YOLOv10 环境中:

    conda activate yolov10

  2. 导航到 yolo-main 目录:

    cd ~/**/**/yolov10-main

  3. 使用文本编辑器创建 voc_to_yolo.py 脚本:

    nano voc_to_yolo.py

  4. 将以下代码复制粘贴到 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)
  5. 修改 xml_directoryoutput_directoryclasses 变量,使其指向你的数据集和类别名称。         

     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)

这样,脚本会自动遍历 imageslabels 目录下的所有子目录,将数据集划分为训练集、验证集和测试集。如果你的目录结构不同,请根据实际情况调整脚本中的路径。

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  # optional

      train_labels: /home/*/yolo10/car/labels/train
      val_labels: /home/*/yolo10/car/labels/val
      test_labels: /home/*/yolo10/car/labels/test  # optional

      nc: 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_scoresindmask_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
    

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值