怎么样让客户做网站和小程序,龙江网站建设公司,wordpress 慢 优化,微营销的软件有哪些YOLOv8专栏导航#xff1a;点击此处跳转 K折交叉验证
K折交叉验证#xff08;K-Fold Cross-Validation#xff09;是一种常用的机器学习模型评估方法#xff0c;可以帮助我们评估模型的性能#xff0c;特别适用于数据集相对较小的情况。
在K折交叉验证中#xff0c;将原… YOLOv8专栏导航点击此处跳转 K折交叉验证
K折交叉验证K-Fold Cross-Validation是一种常用的机器学习模型评估方法可以帮助我们评估模型的性能特别适用于数据集相对较小的情况。
在K折交叉验证中将原始数据集分成K个子集然后依次将其中一个子集作为验证集其余K-1个子集作为训练集进行模型训练和评估。这样可以得到K个模型每个模型都在不同的验证集上进行评估最后将K个模型的评估结果求平均或取最优结果作为最终评估。
优点
充分利用数据集 在K折交叉验证中整个数据集被划分为K个互斥的折叠Folds。每次训练模型时都有K-1个折叠用于训练而剩下的一个用于验证。这样每个样本都有机会作为验证集的一部分从而充分利用了数据集中的所有样本。减轻过拟合风险 由于每个样本都会在训练集和验证集中出现模型在验证集上的性能评估更具有代表性。这有助于减轻由于数据稀疏或类别不平衡导致的过拟合问题。更稳健的模型评估 K折交叉验证计算多次模型性能的平均值提供了更稳健的性能评估。这对于对抗数据稀疏和类别不平衡等挑战的模型评估尤为重要因为它减少了单次评估可能引入的随机性。处理类别不平衡 如果数据集中某些类别的样本数量较少K折交叉验证可以确保每个折叠中都包含这些少见类别的样本。这有助于确保模型在少见类别上的性能得到充分评估并提高对类别不平衡的鲁棒性。 YOLOv8
YOLOv8 是由 YOLOv5 的发布者 Ultralytics 发布的最新版本的 YOLO。它可用于对象检测、分割、分类任务以及大型数据集的学习并且可以在包括 CPU 和 GPU 在内的各种硬件上执行。
YOLOv8是一种尖端的、最先进的 (SOTA) 模型它建立在以前成功的 YOLO 版本的基础上并引入了新的功能和改进以进一步提高性能和灵活性。YOLOv8 旨在快速、准确且易于使用这也使其成为对象检测、图像分割和图像分类任务的绝佳选择。具体创新包括一个新的骨干网络、一个新的 Ancher-Free 检测头和一个新的损失函数还支持YOLO以往版本方便不同版本切换和性能对比。
YOLOv8的K折交叉验证实现步骤
首先将数据集划分成K个子集可以使用现有的数据集划分函数或手动划分。然后使用一个循环迭代K次每次将其中一个子集作为验证集其余K-1个子集作为训练集。在每次迭代中使用训练集进行模型训练并使用验证集进行模型评估。可以根据需要调整模型的超参数或其他设置。例如可以尝试不同的学习率、迭代次数等。最后将K次迭代中的评估结果进行平均或取最优结果作为最终的模型评估结果。
官方项目下载
git clone https://github.com/ultralytics/ultralytics.gitYOLOv8-K折交叉验证代码实现
在上述下载好的项目文件夹下新建k-fold-train.py文件并添加下述代码
import argparse
import datetime
from itertools import chain
import os
from pathlib import Path
import shutil
import yaml
import pandas as pd
from collections import Counter
from sklearn.model_selection import KFold
from tqdm import tqdm
from concurrent.futures import ThreadPoolExecutor
from ultralytics import YOLONUM_THREADS min(8, max(1, os.cpu_count() - 1))def parse_opt():parser argparse.ArgumentParser()parser.add_argument(--data, defaultr./data) # 数据集路径parser.add_argument(--ksplit, default5, typeint) # K-Fold交叉验证拆分数据集parser.add_argument(--im_suffixes, default[jpg, png, jpeg], helpimages suffix) # 图片后缀名return parser.parse_args()def run(func, this_iter, descProcessing):with ThreadPoolExecutor(max_workersNUM_THREADS, thread_name_prefixMyThread) as executor:results list(tqdm(executor.map(func, this_iter), totallen(this_iter), descdesc))return resultsdef main(opt):dataset_path, ksplit, im_suffixes Path(opt.data), opt.ksplit, opt.im_suffixessave_path Path(dataset_path / f{datetime.date.today().isoformat()}_{ksplit}-Fold_Cross-Valid)save_path.mkdir(parentsTrue, exist_okTrue)# 获取所有图像和标签文件的列表images sorted(list(chain(*[(dataset_path / images).rglob(f*.{ext}) for ext in im_suffixes])))# images sorted(image_files)labels sorted((dataset_path / labels).rglob(*.txt))root_directory Path.cwd()print(当前文件运行根目录:, root_directory)if len(images) ! len(labels):print(* * 20)print(当前数据集和标签数量不一致)print(* * 20)# 从YAML文件加载类名classes_file sorted(dataset_path.rglob(classes.yaml))[0]assert classes_file.exists(), 请创建classes.yaml类别文件if classes_file.suffix .txt:passelif classes_file.suffix .yaml:with open(classes_file, r, encodingutf8) as f:classes yaml.safe_load(f)[names]cls_idx sorted(classes.keys())# 创建DataFrame来存储每张图像的标签计数indx [l.stem for l in labels] # 使用基本文件名作为ID无扩展名labels_df pd.DataFrame([], columnscls_idx, indexindx)# 计算每张图像的标签计数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])] 1labels_df.loc[label.stem] lbl_counter# 用0.0替换NaN值labels_df labels_df.fillna(0.0)kf KFold(n_splitsksplit, shuffleTrue, random_state20) # 设置random_state以获得可重复的结果kfolds list(kf.split(labels_df))folds [fsplit_{n} for n in range(1, ksplit 1)]folds_df pd.DataFrame(indexindx, columnsfolds)# 为每个折叠分配图像到训练集或验证集for idx, (train, val) in enumerate(kfolds, start1):folds_df[fsplit_{idx}].loc[labels_df.iloc[train].index] trainfolds_df[fsplit_{idx}].loc[labels_df.iloc[val].index] val# 计算每个折叠的标签分布比例fold_lbl_distrb pd.DataFrame(indexfolds, columnscls_idx)for n, (train_indices, val_indices) in enumerate(kfolds, start1):train_totals labels_df.iloc[train_indices].sum()val_totals labels_df.iloc[val_indices].sum()# 为避免分母为零向分母添加一个小值1E-7ratio val_totals / (train_totals 1E-7)fold_lbl_distrb.loc[fsplit_{n}] ratiods_yamls []for split in folds_df.columns:split_dir save_path / splitsplit_dir.mkdir(parentsTrue, exist_okTrue)(split_dir / train / images).mkdir(parentsTrue, exist_okTrue)(split_dir / train / labels).mkdir(parentsTrue, exist_okTrue)(split_dir / val / images).mkdir(parentsTrue, exist_okTrue)(split_dir / val / labels).mkdir(parentsTrue, exist_okTrue)dataset_yaml split_dir / f{split}_dataset.yamlds_yamls.append(dataset_yaml.as_posix())split_dir (root_directory / split_dir).as_posix()with open(dataset_yaml, w) as ds_y:yaml.safe_dump({train: split_dir /train/images,val: split_dir /val/images,names: classes}, ds_y)# print(ds_yamls)with open(dataset_path / yaml_paths.txt, w) as f:for path in ds_yamls:f.write(path \n)args_list [(image, save_path, folds_df) for image in images]run(split_images_labels, args_list, descfCreating dataset)def split_images_labels(args):image, save_path, folds_df argslabel image.parents[1] / labels / f{image.stem}.txtif label.exists():for split, k_split in folds_df.loc[image.stem].items():# 目标目录img_to_path save_path / split / k_split / imageslbl_to_path save_path / split / k_split / labelsshutil.copy(image, img_to_path / image.name)shutil.copy(label, lbl_to_path / label.name)if __name__ __main__:opt parse_opt()main(opt)model YOLO(yolov8n.pt, tasktrain)# 从文本文件中加载内容并存储到一个列表中ds_yamls []with open(Path(opt.data) / yaml_paths.txt, r) as f:for line in f:# 去除每行末尾的换行符line line.strip()ds_yamls.append(line)# 打印加载的文件路径列表print(ds_yamls)for k in range(opt.ksplit):dataset_yaml ds_yamls[k]name Path(dataset_yaml).stemmodel.train(datadataset_yaml,batch16,epochs100,imgsz640,device0,workers8,projectruns/train,namename,)print(**40)print(K-Fold Cross Validation Completed.)print(**40)
命令行运行
python k-fold-train.py --data ./data --ksplit 5data数据集所在目录数据集的分布如下- data- images- labelsimages存放图片文件labels存放txt标注文件。ksplit数据集拆分为ksplit个子集该值通常取5或者10某些情况下可取其他数值。