如何批量运行YOLOv8模型验证:全面指南及脚本解析

在计算机视觉领域,目标检测模型的训练与验证是确保模型性能的关键步骤。YOLO(You Only Look Once)系列模型因其高效的检测速度和精确度,广泛应用于实时目标检测任务。随着项目规模的扩大,训练多个改进版本的YOLOv8模型并进行批量验证成为必要。本文将详细介绍如何批量运行YOLOv8模型的验证过程,并提供一个高效的Python脚本,帮助您自动化这一流程。

目录

  1. 前言
  2. 环境配置
  3. 项目结构
  4. 批量验证脚本详解
  5. 如何运行脚本
  6. 预期输出
  7. 常见问题及解决方案
  8. 总结

前言

在深度学习项目中,训练多个模型版本以优化性能是常见的做法。随着模型数量的增加,手动验证每个模型的性能不仅耗时,而且容易出错。为了提高效率,自动化批量验证过程显得尤为重要。本文将介绍如何使用Python脚本批量运行YOLOv8模型的验证,并将验证结果组织到指定的文件夹中,方便后续分析和管理。

环境配置

在开始之前,确保您的系统满足以下条件:

  • 操作系统:Windows/Linux/macOS
  • Python版本:3.8及以上
  • 必要库
    • ultralytics
    • PyYAML
    • torch(与CUDA版本兼容)

安装必要的库

使用以下命令安装所需的Python库:

pip install ultralytics pyyaml torch

确保您的PyTorch版本与您的CUDA版本兼容,以充分利用GPU加速。

项目结构

为了有效地组织项目,建议采用以下目录结构:

ultralytics-128/
├── data.yaml
├── train/
│   ├── yolov8-AIFI-training/
│   │   └── weights/
│   │       └── best.pt
│   ├── yolov8-ASF-DySample-training/
│   │   └── weights/
│   │       └── best.pt
│   └── yolov8-ASF-P2-training/
│       └── weights/
│           └── best.pt
├── val/
└── validation_results/
  • data.yaml:YOLO数据集配置文件,包含训练和验证集的路径。
  • train/:存放各个训练模型的子文件夹,每个子文件夹代表一个不同的模型版本。
  • val/:YOLO验证过程的输出目录。
  • validation_results/:批量验证结果的保存目录,每个模型的结果保存在与其改进点名称相同的子文件夹中。

批量验证脚本详解

脚本功能概述

该脚本的主要功能包括:

  1. 遍历训练目录:自动查找所有包含weights/best.pt文件的子文件夹。
  2. 加载模型:使用Ultralytics YOLO库加载每个模型。
  3. 运行验证:对每个模型运行验证,并将结果保存到指定的输出目录。
  4. 打印详细信息:在终端中显示每个模型的验证过程及结果。
  5. 错误处理:捕获并报告在加载模型或运行验证过程中遇到的任何错误。

逐行代码解析

以下是完整的Python脚本,并附有详细的中文注释:

import os
import yaml
import warnings
import sys

from ultralytics import YOLO

def get_file_size(file_path):
    """
    获取文件大小,返回以KB和MB为单位的大小。
    
    参数:
        file_path (str): 文件的完整路径。
    
    返回:
        tuple: 文件大小的KB和MB,保留两位小数。
    """
    size_bytes = os.path.getsize(file_path)  # 获取文件大小(字节数)
    size_kb = size_bytes / 1024  # 将字节数转换为KB
    size_mb = size_kb / 1024  # 将KB转换为MB
    return round(size_kb, 2), round(size_mb, 2)  # 返回保留两位小数的KB和MB大小

def get_system_info():
    """
    获取系统信息,包括 Ultralytics YOLO 版本、Python 版本、Torch 版本和 CUDA 信息。
    
    返回:
        str: 格式化后的系统信息字符串。
    """
    import ultralytics
    import platform
    import torch

    python_version = platform.python_version()  # 获取Python版本
    torch_version = torch.__version__  # 获取PyTorch版本
    ultralytics_version = ultralytics.__version__  # 获取Ultralytics YOLO版本

    if torch.cuda.is_available():
        device = torch.cuda.get_device_name(0)  # 获取第一个GPU的名称
        cuda_memory = torch.cuda.get_device_properties(0).total_memory / (1024 ** 2)  # 获取GPU总内存并转换为MiB
        cuda_info = f"CUDA:0 (NVIDIA {device}, {cuda_memory:.0f}MiB)"  # 格式化CUDA信息
    else:
        cuda_info = "CPU"  # 如果没有GPU可用,则标记为CPU

    # 格式化系统信息字符串
    system_info = f"Ultralytics YOLOv8.{ultralytics_version} 🚀 Python-{python_version} torch-{torch_version}+{cuda_info}"
    return system_info  # 返回系统信息

def main():
    # 忽略所有警告信息
    warnings.filterwarnings('ignore')

    # 配置路径
    train_dir = 'C:/Users/DaoXin/PycharmProjects/ultralytics-128/train/'  # 训练模型所在目录
    data_yaml = 'C:/Users/DaoXin/PycharmProjects/ultralytics-128/data.yaml'  # 数据集配置文件路径

    # 配置输出目录
    output_dir = 'C:/Users/DaoXin/PycharmProjects/ultralytics-128/validation_results/'  # 指定输出目录
    os.makedirs(output_dir, exist_ok=True)  # 如果输出目录不存在,则创建该目录

    # 检查路径是否存在
    if not os.path.exists(train_dir):
        print(f"Training directory {train_dir} does not exist.")  # 如果训练目录不存在,打印错误信息
        sys.exit(1)  # 退出脚本,返回错误状态码1
    if not os.path.exists(data_yaml):
        print(f"Data YAML file {data_yaml} does not exist.")  # 如果数据集配置文件不存在,打印错误信息
        sys.exit(1)  # 退出脚本,返回错误状态码1

    # 读取 data.yaml 获取验证集路径
    with open(data_yaml, 'r') as f:
        data = yaml.safe_load(f)  # 使用PyYAML安全加载配置文件
    val_path = data.get('val', '')  # 获取验证集路径,如果不存在则返回空字符串
    if not os.path.exists(val_path):
        print(f"Validation path {val_path} does not exist.")  # 如果验证集路径不存在,打印错误信息
        num_images = 0  # 设置验证集图片数量为0
    else:
        # 定义支持的图片扩展名
        image_extensions = ['.jpg', '.jpeg', '.png', '.bmp', '.tiff', '.gif']
        # 统计验证集中的图片数量
        num_images = len([f for f in os.listdir(val_path) if os.path.splitext(f)[1].lower() in image_extensions])
    print(f"Number of validation images: {num_images}\n")  # 打印验证集中的图片数量

    # 获取系统信息并打印
    system_info = get_system_info()
    print(system_info)  # 打印系统信息
    print("-" * 80)  # 打印分隔线,便于阅读

    # 遍历 train_dir 下的所有子文件夹
    for folder_name in os.listdir(train_dir):
        folder_path = os.path.join(train_dir, folder_name)  # 获取子文件夹的完整路径
        if os.path.isdir(folder_path):  # 检查当前路径是否为目录
            best_pt_path = os.path.join(folder_path, 'weights', 'best.pt')  # 构建 best.pt 文件的路径
            if os.path.exists(best_pt_path):  # 检查 best.pt 文件是否存在
                size_kb, size_mb = get_file_size(best_pt_path)  # 获取 best.pt 文件的大小
                print(f"Processing {best_pt_path} (Size: {size_kb}KB, {size_mb}MB)")  # 打印正在处理的模型信息

                try:
                    # 加载模型
                    model = YOLO(best_pt_path)  # 使用Ultralytics YOLO加载模型

                    # 打印模型摘要
                    model_info = model.info()  # 获取模型摘要信息
                    print(model_info)  # 打印模型摘要

                    # 运行验证
                    results = model.val(
                        data=data_yaml,        # 数据集配置文件路径
                        split='val',           # 指定验证集
                        imgsz=640,             # 输入图片大小
                        batch=16,              # 批处理大小
                        device='0',            # 指定使用的设备,例如 '0' 表示第一块GPU
                        project=output_dir,    # 指定验证结果保存的基础目录
                        name=folder_name,      # 指定子文件夹名称为当前改进点名称
                        verbose=True           # 启用详细输出,显示进度条和详细信息
                    )

                    print(f"Validation completed for {folder_name}.")  # 打印验证完成的信息
                    print("-" * 80)  # 打印分隔线,便于阅读

                except Exception as e:
                    print(f"Error processing {best_pt_path}: {e}")  # 如果发生异常,打印错误信息
                    print("-" * 80)  # 打印分隔线,便于阅读
            else:
                print(f"best.pt not found in {folder_path}")  # 如果 best.pt 文件不存在,打印提示信息
                print("-" * 80)  # 打印分隔线,便于阅读
        else:
            print(f"Skipping non-folder item: {folder_path}")  # 如果当前项不是文件夹,打印跳过信息
            print("-" * 80)  # 打印分隔线,便于阅读

if __name__ == '__main__':
    main()  # 调用主函数,开始执行脚本

代码详解

  1. 导入必要的库

    import os
    import yaml
    import warnings
    import sys
    
    from ultralytics import YOLO
    
    • os:用于文件和目录操作。
    • yaml:用于读取和解析YAML配置文件。
    • warnings:用于控制警告信息的显示。
    • sys:用于与Python解释器交互,如退出脚本。
    • ultralytics.YOLO:导入Ultralytics YOLO库,用于加载和运行YOLO模型。
  2. 定义获取文件大小的函数

    def get_file_size(file_path):
        ...
    
    • 该函数接受一个文件路径,返回文件的KB和MB大小,保留两位小数。
  3. 定义获取系统信息的函数

    def get_system_info():
        ...
    
    • 该函数收集并返回系统的详细信息,包括YOLO版本、Python版本、PyTorch版本以及CUDA(GPU)信息。
  4. 定义主函数

    def main():
        ...
    
    • 这是脚本的主入口,负责配置路径、读取配置文件、遍历训练目录中的模型、加载模型并运行验证。
  5. 忽略警告信息

    warnings.filterwarnings('ignore')
    
    • 设置忽略所有的警告信息,保持终端输出的整洁。
  6. 配置路径

    train_dir = 'C:/Users/DaoXin/PycharmProjects/ultralytics-128/train/'  # 训练模型所在目录
    data_yaml = 'C:/Users/DaoXin/PycharmProjects/ultralytics-128/data.yaml'  # 数据集配置文件路径
    
    • train_dir:存放各个训练模型的主目录,每个子目录代表一个不同的模型版本。
    • data_yaml:数据集的配置文件路径,包含训练和验证集的详细信息。
  7. 配置输出目录

    output_dir = 'C:/Users/DaoXin/PycharmProjects/ultralytics-128/validation_results/'  # 指定输出目录
    os.makedirs(output_dir, exist_ok=True)  # 如果输出目录不存在,则创建该目录
    
    • output_dir:指定验证结果的保存位置。
    • os.makedirs:创建输出目录,如果目录已存在则不会抛出异常。
  8. 检查路径是否存在

    if not os.path.exists(train_dir):
        print(f"Training directory {train_dir} does not exist.")
        sys.exit(1)
    if not os.path.exists(data_yaml):
        print(f"Data YAML file {data_yaml} does not exist.")
        sys.exit(1)
    
    • 检查训练目录和数据集配置文件是否存在。如果不存在,打印错误信息并退出脚本。
  9. 读取 data.yaml 文件获取验证集路径

    with open(data_yaml, 'r') as f:
        data = yaml.safe_load(f)  # 使用PyYAML安全加载配置文件
    val_path = data.get('val', '')  # 获取验证集路径,如果不存在则返回空字符串
    if not os.path.exists(val_path):
        print(f"Validation path {val_path} does not exist.")  # 如果验证集路径不存在,打印错误信息
        num_images = 0  # 设置验证集图片数量为0
    else:
        # 定义支持的图片扩展名
        image_extensions = ['.jpg', '.jpeg', '.png', '.bmp', '.tiff', '.gif']
        # 统计验证集中的图片数量
        num_images = len([f for f in os.listdir(val_path) if os.path.splitext(f)[1].lower() in image_extensions])
    print(f"Number of validation images: {num_images}\n")  # 打印验证集中的图片数量
    
    • 打开并读取 data.yaml 文件,获取验证集的路径 val_path
    • 检查 val_path 是否存在。如果不存在,设置 num_images 为0。
    • 如果存在,统计验证集中符合指定图片扩展名的图片数量,并打印出来。
  10. 获取并打印系统信息

    system_info = get_system_info()
    print(system_info)  # 打印系统信息
    print("-" * 80)  # 打印分隔线,便于阅读
    
    • 调用 get_system_info 函数获取系统信息,并打印出来。
    • 打印分隔线,便于阅读后续输出。
  11. 遍历训练目录下的所有子文件夹

    for folder_name in os.listdir(train_dir):
        folder_path = os.path.join(train_dir, folder_name)  # 获取子文件夹的完整路径
        if os.path.isdir(folder_path):  # 检查当前路径是否为目录
            best_pt_path = os.path.join(folder_path, 'weights', 'best.pt')  # 构建 best.pt 文件的路径
            if os.path.exists(best_pt_path):  # 检查 best.pt 文件是否存在
                size_kb, size_mb = get_file_size(best_pt_path)  # 获取 best.pt 文件的大小
                print(f"Processing {best_pt_path} (Size: {size_kb}KB, {size_mb}MB)")  # 打印正在处理的模型信息
    
                try:
                    # 加载模型
                    model = YOLO(best_pt_path)  # 使用Ultralytics YOLO加载模型
    
                    # 打印模型摘要
                    model_info = model.info()  # 获取模型摘要信息
                    print(model_info)  # 打印模型摘要
    
                    # 运行验证
                    results = model.val(
                        data=data_yaml,        # 数据集配置文件路径
                        split='val',           # 指定验证集
                        imgsz=640,             # 输入图片大小
                        batch=16,              # 批处理大小
                        device='0',            # 指定使用的设备,例如 '0' 表示第一块GPU
                        project=output_dir,    # 指定验证结果保存的基础目录
                        name=folder_name,      # 指定子文件夹名称为当前改进点名称
                        verbose=True           # 启用详细输出,显示进度条和详细信息
                    )
    
                    print(f"Validation completed for {folder_name}.")  # 打印验证完成的信息
                    print("-" * 80)  # 打印分隔线,便于阅读
    
                except Exception as e:
                    print(f"Error processing {best_pt_path}: {e}")  # 如果发生异常,打印错误信息
                    print("-" * 80)  # 打印分隔线,便于阅读
            else:
                print(f"best.pt not found in {folder_path}")  # 如果 best.pt 文件不存在,打印提示信息
                print("-" * 80)  # 打印分隔线,便于阅读
        else:
            print(f"Skipping non-folder item: {folder_path}")  # 如果当前项不是文件夹,打印跳过信息
            print("-" * 80)  # 打印分隔线,便于阅读
    
    • 遍历训练目录中的每个子文件夹
      • 使用 os.listdir(train_dir) 获取训练目录下的所有项(文件和文件夹)。
      • 对每个 folder_name,构建其完整路径 folder_path
      • 使用 os.path.isdir(folder_path) 检查当前项是否为目录。
    • 检查 best.pt 文件是否存在
      • 构建 best_pt_path,即当前子文件夹中的 weights/best.pt 文件路径。
      • 如果 best_pt_path 存在,继续处理;否则,打印提示信息并跳过。
    • 获取并打印 best.pt 文件大小
      • 调用 get_file_size(best_pt_path) 获取文件大小(KB和MB)。
      • 打印正在处理的模型路径及其大小信息。
    • 加载模型并打印模型摘要
      • 使用 YOLO(best_pt_path) 加载模型。
      • 调用 model.info() 获取并打印模型的摘要信息。
    • 运行验证
      • 调用 model.val() 方法进行模型验证,传入相关参数:
        • data: 数据集配置文件路径。
        • split: 指定验证集。
        • imgsz: 输入图片大小。
        • batch: 批处理大小。
        • device: 指定运行设备,如 '0' 表示使用第一块GPU。
        • project: 指定验证结果保存的基础目录。
        • name: 指定子文件夹名称,为当前改进点名称。
        • verbose: 启用详细输出,显示进度条和详细信息。
    • 打印验证完成信息
      • 如果验证成功,打印验证完成的信息及分隔线。
    • 错误处理
      • 如果在加载模型或运行验证过程中发生异常,捕获并打印错误信息,同时打印分隔线。
    • 处理非文件夹项
      • 如果当前项不是文件夹,打印跳过信息及分隔线。
  12. 脚本入口

    if __name__ == '__main__':
        main()  # 调用主函数,开始执行脚本
    
    • 这是Python脚本的标准入口,确保当脚本被直接运行时,调用 main() 函数开始执行。

如何运行脚本

按照以下步骤运行批量验证脚本:

  1. 配置路径

    • 训练目录 (train_dir)
      • 确保 train_dir 指向包含各个模型子文件夹的主目录。每个子文件夹应包含 weights/best.pt 文件。
    • 数据集配置文件 (data_yaml)
      • 确保 data_yaml 文件路径正确,并且文件内容符合YOLO的配置要求,包含训练和验证集的路径。
    • 输出目录 (output_dir)
      • 脚本将验证结果保存在 output_dir 目录下与模型改进点名称相同的子文件夹中。确保该目录有足够的存储空间。
  2. 运行脚本

    • 使用终端或集成开发环境(如PyCharm)运行脚本:
      python batch_val.py
      
    • 替换 batch_val.py 为您的脚本文件名。
  3. 监控输出

    • 脚本将在终端中打印每个模型的处理过程,包括模型摘要和验证结果。
    • 验证结果将自动保存在 output_dir 目录下相应的子文件夹中,方便后续分析。

预期输出

运行脚本后,终端将显示类似以下内容:

Number of validation images: 127

Ultralytics YOLOv8.1.9 🚀 Python-3.10.15 torch-2.3.1+cu118 CUDA:0 (NVIDIA GeForce RTX 4070 Ti, 12282MiB)
--------------------------------------------------------------------------------
Processing C:/Users/DaoXin/PycharmProjects/ultralytics-128/train/yolov8-AIFI-training/weights/best.pt (Size: 5369.39KB, 5.24MB)
YOLOv8-AIFI-training summary (fused): 193 layers, 2612505 parameters, 0 gradients, 6.7 GFLOPs
...
Validation completed for yolov8-AIFI-training.
--------------------------------------------------------------------------------
Processing C:/Users/DaoXin/PycharmProjects/ultralytics-128/train/yolov8-ASF-DySample-training/weights/best.pt (Size: 5623.06KB, 5.49MB)
YOLOv8-ASF-DySample-training summary (fused): 206 layers, 2734969 parameters, 0 gradients, 7.3 GFLOPs
...
Validation completed for yolov8-ASF-DySample-training.
--------------------------------------------------------------------------------
Processing C:/Users/DaoXin/PycharmProjects/ultralytics-128/train/yolov8-ASF-P2-training/weights/best.pt (Size: 5041.93KB, 4.92MB)
YOLOv8-ASF-P2-training summary (fused): 243 layers, 2371484 parameters, 0 gradients, 10.7 GFLOPs
...
Validation completed for yolov8-ASF-P2-training.
--------------------------------------------------------------------------------

同时,验证结果将保存在以下目录中:

C:/Users/DaoXin/PycharmProjects/ultralytics-128/validation_results/yolov8-AIFI-training/
C:/Users/DaoXin/PycharmProjects/ultralytics-128/validation_results/yolov8-ASF-DySample-training/
C:/Users/DaoXin/PycharmProjects/ultralytics-128/validation_results/yolov8-ASF-P2-training/

每个子文件夹中将包含验证生成的所有文件,例如:

  • results.json
  • confusion_matrix.png
  • precision_recall_curve.png
  • 以及其他验证相关的输出文件。

常见问题及解决方案

1. 脚本报错:'DetMetrics' object is not subscriptable

原因:在尝试访问results.metrics属性时,由于DetMetrics对象中没有该属性,导致错误。

解决方案:确保脚本不再尝试访问不存在的属性,仅依赖print输出模型的验证信息。本文提供的脚本已移除对results.metrics的访问,避免此类错误。

2. 验证结果文件夹未生成

原因:脚本中的output_dir路径配置错误或没有权限创建目录。

解决方案:检查output_dir路径是否正确,并确保脚本有权限在该路径下创建文件夹和写入文件。

3. GPU未被正确使用

原因device参数配置错误,或者PyTorch未正确识别GPU。

解决方案

  • 确保CUDA已正确安装,并与PyTorch版本兼容。
  • 检查device='0'是否对应正确的GPU编号,或使用device='cpu'在CPU上运行。
  • 使用以下代码验证PyTorch是否检测到GPU:
    import torch
    print(torch.cuda.is_available())  # 应返回True
    print(torch.cuda.get_device_name(0))  # 打印GPU名称
    

总结

本文详细介绍了如何批量运行YOLOv8模型的验证过程,并提供了一个高效的Python脚本,帮助您自动化这一流程。通过合理配置目录结构和脚本参数,您可以轻松管理多个模型版本的验证结果,提升工作效率。希望本文对您的项目有所帮助,若有任何疑问或建议,欢迎在下方留言交流。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐