YOLOv8K折交叉验证(yolov8目标检测+k折交叉验证法)

一、官网下载YOLOv8(建议开梯子)

网址:https://github.com/ultralytics/ultralytics

二、xshell和xftp的使用

参考:Windows 下 xshell 和 xftp 安装与使用

三、AutoDL平台的使用

官网:https://www.autodl.com

参考:AutoDL使用教程

四、YOLOv8教程

参考:教程

运行结果

五、遇到的一点问题

1、classes.yaml

类似以下

2、分类代码

以下代码直接复制成新python文件,粘贴到data的同级目录下

import datetime
import shutil
from pathlib import Path
from collections import Counter
import os

import yaml
import numpy as np
import pandas as pd
from ultralytics import YOLO
from sklearn.model_selection import KFold

# 定义数据集路径
dataset_path = Path('./data')  # 替换成你的数据集路径

# 获取所有标签文件的列表
labels = sorted(dataset_path.rglob("*labels/*.txt"))  # 所有标签文件在'labels'目录中

# 获取当前文件的绝对路径
current_file_path = os.path.abspath(__file__)

# 获取当前文件所在的文件夹路径(即当前文件的根目录)
root_directory = os.path.dirname(current_file_path)

print("当前文件运行根目录:", root_directory)

# 从YAML文件加载类名
yaml_file = 'data/classes.yaml'
with open(yaml_file, 'r', encoding="utf8") as y:
    classes = yaml.safe_load(y)['names']
cls_idx = sorted(classes.keys())

# 创建DataFrame来存储每张图像的标签计数
indx = [l.stem for l in labels]  # 使用基本文件名作为ID(无扩展名)
labels_df = pd.DataFrame([], columns=cls_idx, index=indx)

# 计算每张图像的标签计数
for label in labels:
    lbl_counter = Counter()

    with open(label, 'r') as lf:
        lines = lf.readlines()

    for l in lines:
        # YOLO标签使用每行的第一个位置的整数作为类别
        lbl_counter[int(l.split(' ')[0])] += 1

    labels_df.loc[label.stem] = lbl_counter

# 用0.0替换NaN值
labels_df = labels_df.fillna(0.0)

# 使用K-Fold交叉验证拆分数据集
ksplit = 5
kf = KFold(n_splits=ksplit, shuffle=True, random_state=20)  # 设置random_state以获得可重复的结果
kfolds = list(kf.split(labels_df))
folds = [f'split_{n}' for n in range(1, ksplit + 1)]
folds_df = pd.DataFrame(index=indx, columns=folds)

# 为每个折叠分配图像到训练集或验证集
for idx, (train, val) in enumerate(kfolds, start=1):
    folds_df[f'split_{idx}'].loc[labels_df.iloc[train].index] = 'train'
    folds_df[f'split_{idx}'].loc[labels_df.iloc[val].index] = 'val'

# 计算每个折叠的标签分布比例
fold_lbl_distrb = pd.DataFrame(index=folds, columns=cls_idx)
for n, (train_indices, val_indices) in enumerate(kfolds, start=1):
    train_totals = labels_df.iloc[train_indices].sum()
    val_totals = labels_df.iloc[val_indices].sum()

    # 为避免分母为零,向分母添加一个小值(1E-7)
    ratio = val_totals / (train_totals + 1E-7)
    fold_lbl_distrb.loc[f'split_{n}'] = ratio

# 创建目录以保存分割后的数据集
save_path = Path(dataset_path / f'{datetime.date.today().isoformat()}_{ksplit}-Fold_Cross-val')
save_path.mkdir(parents=True, exist_ok=True)

# 获取图像文件列表
images = sorted((dataset_path / 'images').rglob("*.jpg"))  # 更改文件扩展名以匹配你的数据
ds_yamls = []

# 循环遍历每个折叠并复制图像和标签
for split in folds_df.columns:
    # 为每个折叠创建目录
    split_dir = save_path / split
    split_dir.mkdir(parents=True, exist_ok=True)
    (split_dir / 'train' / 'images').mkdir(parents=True, exist_ok=True)
    (split_dir / 'train' / 'labels').mkdir(parents=True, exist_ok=True)
    (split_dir / 'val' / 'images').mkdir(parents=True, exist_ok=True)
    (split_dir / 'val' / 'labels').mkdir(parents=True, exist_ok=True)



    # 创建数据集的YAML文件
    dataset_yaml = split_dir / f'{split}_dataset.yaml'
    ds_yamls.append(dataset_yaml.as_posix())
    split_dir = os.path.join(root_directory, split_dir.as_posix())

    with open(dataset_yaml, 'w') as ds_y:
        yaml.safe_dump({
            'path': split_dir,
            'train': 'train',
            'val': 'val',
            'names': classes
        }, ds_y)
print(ds_yamls)

# 将文件路径保存到一个txt文件中
with open('data/file_paths.txt', 'w') as f:
    for path in ds_yamls:
        f.write(path + '\n')

# 为每个折叠复制图像和标签到相应的目录
for image, label in zip(images, labels):
    for split, k_split in folds_df.loc[image.stem].items():
        # 目标目录
        img_to_path = save_path / split / k_split / 'images'
        lbl_to_path = save_path / split / k_split / 'labels'

        # 将图像和标签文件复制到新目录中
        # 如果文件已存在,可能会抛出SamefileError
        shutil.copy(image, img_to_path / image.name)
        shutil.copy(label, lbl_to_path / label.name)

运行后会在data目录下生成一个文件夹,里面有n种不同划分的数据集

split的数量取决以上代码中ksplit的设置

注意:我遇到的情况是文件夹生成后非空不可删,一定仔细确定split的数量设置,不然,我是autodl重开租用新主机

3、训练代码

同样复制为新python文件,粘贴在data的同级目录中

from ultralytics import YOLO

weights_path = 'checkpoints/yolov8s.pt'
model = YOLO(weights_path, task='train')
ksplit = 5
# 从文本文件中加载内容并存储到一个列表中
ds_yamls = []
with open('data/file_paths.txt', 'r') as f:
    for line in f:
        # 去除每行末尾的换行符
        line = line.strip()
        ds_yamls.append(line)

# 打印加载的文件路径列表
print(ds_yamls)


results = {}
for k in range(ksplit):
    dataset_yaml = ds_yamls[k]
    model.train(data=dataset_yaml, batch=6, epochs=2, imgsz=1280, device=0, workers=8, single_cls=False, ) 

以上的ksplit数量设置也要和分类代码中一致,如果autodl开的单卡,batch设置2,开的双卡,batch设置4,以此类推,剩下参数根据需要设置。运行报错的话可以尝试将以上代码改成

from ultralytics import YOLO

weights_path = 'yolov8s.pt'
model = YOLO(weights_path, task='train')
ksplit = 5
# 从文本文件中加载内容并存储到一个列表中
ds_yamls = []
with open('data/file_paths.txt', 'r') as f:
    for line in f:
        # 去除每行末尾的换行符
        line = line.strip()
        ds_yamls.append(line)

# 打印加载的文件路径列表
print(ds_yamls)


results = {}
for k in range(ksplit):
    dataset_yaml = ds_yamls[k]
    model.train(data=dataset_yaml, batch=6, epochs=2, imgsz=1280, device=0, workers=8, single_cls=False, ) 

4、压缩包下载

因为官网下载ultralytics后解压会有两个

建议删掉一个,不然autodl里面可能遇到不知名的路径错误

5、新人的话可以看看【目标检测】2024最新-用YOLOv8训练自己的数据集(保姆级教学)_yolov8 预训练模型怎么选择-CSDN博客

第一次跑出bus.jpg的感觉还是很不错的,不过要学些终端知识,慢慢来就好了

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值