交叉验证整理

交叉验证存在的原因:

在建模时,经常会遇到这样的情况:模型在训练样本集上拟合成功后的性能评价指标都表现较好,但在测试样本集上的验证效果却表现很差,这种偏差情况出现的原因,往往是模型出现了过拟合问题。

当然,这种现象在实际建模场景中是很常见的,但为了得到一个满足业务需求且性能效果可用的模型,我们必然会采取有效的措施来解决这类问题。在这种建模实际业务场景下,交叉验证的思想方法便发挥了很重要的作用,从本质上来讲,交叉验证可以充分使用所有的训练数据用于评估模型,这为模型最终的稳定输出设定了良好的条件。


0.先建立数据集

from sklearn import linear_model,datasets
import pandas as pd
iris=datasets.load_iris()#加载数据集

train=pd.DataFrame(iris.data,columns=iris.feature_names)#建立样本
target=pd.DataFrame(iris.target,columns=['target'])#设置样本标签

1.HoldOut交叉验证

HoldOut交叉验证,是将整个数据集按照一定比例随机划分为训练集和验证集。在实际情景中,训练集与验证集的拆分比例一般为7:3或8:2。

这种方法是最基础的也是最简单的交叉验证方法,由于在每次构建模型过程中,模型训练集上仅拟合一次,因此任务执行速度很快,但为了保证模型相对稳定,往往可以多次对数据进行拆分并训练模型,最后从中选择性能表现较优模型。

在Python语言中,HoldOut交叉验证可通过调用函数train_test_split( )来选取数据。

#方法1:HoldOut交叉验证
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score

model=LogisticRegression()#l逻辑回归模型
train_x,test_x,train_y,test_y=train_test_split(train,target,test_size=0.3,random_state=0)#训练集验证集7:3的比例划分

model.fit(train_x,train_y)

acc_train=accuracy_score(train_y,model.predict(train_x)) #accuracy_score():用于计算准确率
acc_test=accuracy_score(test_y,model.predict(test_x))

print('train score :{},test acore:{}'.format(acc_train,acc_test))

 2.K折交叉验证

K折交叉验证(K-Fold)的思想是将整个样本数据集拆分为K个相同大小的子样本,每个分区样本可以称为一个“折叠”,因此拆分后的样本数据可理解为K折。

其中,某任意1折数据作为验证集,而其余K-1折数据相应作为作训练集。在交叉验证过程中,训练集与验证集的交替会重复K次,也就是每个折叠的分区样本数据都会作为验证集,其他折叠的数据作为训练集。

模型训练后的最终精度评估,可以通过取K个模型在对应验证数据集上的平均精度。在Python语言中,K折交叉验证可通过调用函数cross_val_score( )与KFold( )来选取数据。

#方法1:K折交叉验证
from sklearn.model_selection import cross_val_score,KFold
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score

model=LogisticRegression()#l逻辑回归模型

#k折交叉验证
kf=KFold(n_splits=5)#5折交叉验证

model.fit(train_x,train_y)

score=cross_val_score(model,train,target,cv=kf)

print('kf score :{},kf acore mean:{}'.format(score,score.mean()))


3.分层K折交叉验证

分层K折交叉验证,主要原理逻辑与K折交叉验证是类似的,仍然是将整个样本数据集拆分为K个部分,最关键的区别是分层K折交叉验证通过对目标变量的分层抽样,使得每个折叠数据集的目标变量分布比例,与整个样本数据的目标比例保持一致,有效解决样本不均衡的情况,因此是K折交叉验证的优化版,且更能满足实际业务场景的需求。

分层的意思是说在每一折中都保持着原始数据中各个类别的比例关系,比如说:原始数据有A、B、C3类,比例为1:2:1,采用3折分层交叉验证,那么划分的3折中,每一折中A、B、C的数据类别保持着1:2:1的比例,这样的验证结果更加可信。

在Python语言中,分层K折交叉验证可通过调用函数cross_val_score( )StratifiedKFold( )来选取数据。

#方法3:分层K折交叉验证
from sklearn.model_selection import cross_val_score,StratifiedKFold
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score

model=LogisticRegression()#l逻辑回归模型

#k折交叉验证
kf=StratifiedKFold(n_splits=5)#5折交叉验证

model.fit(train_x,train_y)

score=cross_val_score(model,train,target,cv=kf)

print('kf score :{},kf acore mean:{}'.format(score,score.mean()))

 4.Shuffle-Split交叉验证

蒙特卡罗交叉验证,也称为Shuffle Split交叉验证,是一种非常灵活的交叉验证策略。在这种技术中,数据集被随机划分为训练集和验证集。

在数据随机拆分的过程中,可以指定训练集与验证集的样本占比大小,二者比例之和没有必须为100%的要求。如果训练集和验证集大小的增加百分比总和不是 100,则剩余的数据集不会用于训练集或验证集。假设我们有 100 个样本,其中 60% 的样本用作训练集,20% 的样本用作验证集,那么剩下的 20%( 100-(60+20)) 将不被使用。这种拆分将重复我们必须指定的“n”次。

在Python语言中,Shuffle-Split交叉验证可通过调用函数cross_val_score( )与ShuffleSplit( )来选取数据。

#方法4:Shuffle-Split交叉验证
from sklearn.model_selection import cross_val_score,ShuffleSplit
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score

model=LogisticRegression()#l逻辑回归模型

model.fit(train_x,train_y)
shuffl=ShuffleSplit(train_size=0.6,test_size=0.2,n_splits=10) #重复n次
score=cross_val_score(model,train,target,cv=shuffl)

print('kf score :{},kf acore mean:{}'.format(score,score.mean()))


 5、Leave-P-Out交叉验证

Leave-P-Out交叉验证,是通过指定p值后,p个样本作为验证集,剩余n-p个样本作为训练集,然后不断重复这个过程,直到整个样本数据都作为验证集,这种方法的缺点是任务耗时较长,相比前几种方法应用相对较少。

假设我们在数据集中有 100 个样本。如果我们使用 p=10,那么在每次迭代中,10 个值将用作验证集,其余 90 个样本将用作训练集。

重复这个过程,直到整个数据集在 p 样本和 n-p 训练样本的验证集上被划分。

在Python语言中,Leave-P-Out交叉验证可通过调用函数cross_val_score( )LeavePOut( )来选取数据。

#方法5:Leave-P-Out交叉验证
from sklearn.model_selection import cross_val_score,LeavePOut
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score

model=LogisticRegression()#l逻辑回归模型
model.fit(train_x,train_y)

lpo=LeavePOut(p=20)  #指定p=20,即选取20个样本
lpo.get_n_splits(train_x)

score=cross_val_score(model,train,target,cv=lpo)

print('kf score :{},kf acore mean:{}'.format(score,score.mean()))

结果太慢了就不贴了

6.时间序列交叉验证

时间序列数据是在不同时间点收集的数据。由于数据点是在相邻时间段收集的,因此观测值之间可能存在相关性。这是区分时间序列数据与横截面数据的特征之一。

在时间序列数据的情况下如何进行交叉验证?

在时间序列数据的情况下,我们不能选择随机样本并将它们分配给训练集或验证集,因为使用未来数据中的值来预测过去数据的值是没有意义的。

由于数据的顺序对于时间序列相关问题非常重要,所以我们根据时间将数据拆分为训练集和验证集,也称为“前向链”方法或滚动交叉验证。

我们从一小部分数据作为训练集开始。基于该集合,我们预测稍后的数据点,然后检查准确性。

然后将预测样本作为下一个训练数据集的一部分包括在内,并对后续样本进行预测。

 

import numpy as np
from sklearn.model_selection import TimeSeriesSplit
X = np.array([[1, 2], [3, 4], [1, 2], [3, 4], [1, 2], [3, 4]])
y = np.array([1, 2, 3, 4, 5, 6])
time_series = TimeSeriesSplit()
print(time_series)
for train_index, test_index in time_series.split(X):
    print("TRAIN:", train_index, "TEST:", test_index)
    X_train, X_test = X[train_index], X[test_index]
    y_train, y_test = y[train_index], y[test_index]

整理写作不容易,看完的请点个赞呀!!!!

<think>好的,用户现在想了解如何在YOLOv8中实现交叉验证。我需要结合之前提供的引用内容以及之前的回答来给出详细步骤。 首先,用户之前询问过验证集和测试集的使用方法,现在转向交叉验证,可能是因为他们遇到了数据集较小或类别不平衡的问题,想通过交叉验证提高模型评估的稳健性。根据引用[1],YOLOv8实现K折交叉验证可以解决这些问题,所以需要重点讲解K折交叉验证的步骤。 接下来,引用[3]提到了具体的代码实现,比如划分数据集、训练配置等。我需要将这些信息整理成步骤,可能包括数据集准备、生成K折划分、训练循环等。同时,用户可能需要知道如何修改YAML文件和调整参数。 需要注意的是,用户可能对交叉验证的概念不熟悉,可能需要简要说明其优势,比如充分利用小数据集,减少过拟合风险。另外,确保代码示例正确,比如使用YOLO库中的方法,调整batch size和设备设置,避免运行错误。 还要参考之前的回答结构,保持清晰的步骤和参数解释,可能包括注意事项,比如确保数据分布一致、避免信息泄露等。最后,生成相关问题,帮助用户深入理解,比如如何选择K值,处理类别不平衡,以及交叉验证后的模型选择方法。 需要检查引用内容是否有其他要点,比如交叉验证后的性能对比,如何保存最佳模型等,确保回答全面。同时,提醒用户交叉验证的计算成本较高,需合理分配资源。最后,确保所有代码示例正确,参数如ksplit、batch与设备匹配,避免用户运行时出错。</think>### YOLOv8中K折交叉验证的完整实现方法 在YOLOv8中实施交叉验证需要结合数据划分策略与训练配置的特殊处理,以下是详细操作流程(基于最新官方文档和实践经验): #### 一、交叉验证核心优势 1. **小数据集优化**:通过重复利用数据提升评估可靠性 2. **过拟合检测**:识别模型对特定数据划分的敏感性 3. **参数调优**:更准确地选择超参数组合[^1] #### 二、具体实现步骤 1. **数据集准备** ```yaml # data.yaml 基础配置 path: /datasets/custom train: images/train # 原始训练集路径 val: images/val # 临时验证路径(将被覆盖) nc: 10 # 类别数 names: [class0,...,class9] ``` 2. **生成K折划分** ```python from sklearn.model_selection import KFold import yaml # 加载原始数据索引 with open('data/file_paths.txt') as f: all_samples = [line.strip() for line in f] ksplit = 5 kf = KFold(n_splits=ksplit, shuffle=True, random_state=42) # 生成K个数据集配置 for fold, (train_idx, val_idx) in enumerate(kf.split(all_samples)): fold_dir = f'folds/fold_{fold}' os.makedirs(fold_dir, exist_ok=True) # 创建子数据集配置 fold_data = { 'path': '/datasets/custom', 'train': [all_samples[i] for i in train_idx], 'val': [all_samples[i] for i in val_idx], 'nc': 10, 'names': [...]} with open(f'{fold_dir}/data_fold{fold}.yaml', 'w') as f: yaml.dump(fold_data, f) ``` 3. **交叉验证训练循环** ```python from ultralytics import YOLO model = YOLO('yolov8s.pt') results = {} for fold in range(ksplit): print(f'Training fold {fold+1}/{ksplit}') # 关键训练参数配置 model.train( data=f'folds/fold_{fold}/data_fold{fold}.yaml', epochs=100, batch=16, # 根据GPU显存调整 imgsz=640, device=0, # 指定GPU设备 workers=8, single_cls=False, project='cv_results', name=f'fold_{fold}', save_period=10 ) # 记录评估结果 val_results = model.val(split='val') results[f'fold_{fold}'] = { 'mAP50': val_results.box.map50, 'mAP50-95': val_results.box.map } ``` #### 三、关键参数说明 | 参数 | 推荐设置 | 作用说明 | |------------|---------------|----------------------------| | batch | 8-64 | 与GPU显存正相关 | | imgsz | 640 | 输入图像尺寸 | | workers | CPU核心数×0.8 | 数据加载并行度 | | patience | 50 | 早停等待轮数 | | save_json | True | 保存评估结果文件 | #### 四、结果整合与分析 ```python # 计算平均性能指标 avg_mAP50 = sum(v['mAP50'] for v in results.values()) / ksplit avg_mAP50_95 = sum(v['mAP50-95'] for v in results.values()) / ksplit print(f'Cross-Validation Results (k={ksplit}):') print(f'mAP50平均值: {avg_mAP50:.3f}') print(f'mAP50-95平均值: {avg_mAP50_95:.3f}') ``` #### 五、注意事项 1. **硬件配置**:单卡训练时建议`batch=2`, 多卡按比例增加 2. **数据泄露**:确保每个fold的验证集完全独立 3. **类别平衡**:使用`stratified=True`参数保持类别分布 4. **最终模型**:建议用全部数据重新训练最佳配置模型[^3] #### 六、完整工作流示例 ```python # 初始化环境 import os import shutil from sklearn.model_selection import StratifiedKFold # 创建K折数据集 def create_kfold_splits(ksplit=5): # 实现带分层抽样的数据划分 skf = StratifiedKFold(n_splits=ksplit) # ...具体实现参考步骤二... # 执行交叉验证 def run_cross_validation(): model = YOLO('yolov8n.pt') for fold in range(ksplit): # 动态修改数据集路径 data_cfg = f'folds/fold_{fold}/data.yaml' model.train(data=data_cfg, **train_params) # 保存最佳权重 shutil.copy('runs/train/weights/best.pt', f'cv_models/fold_{fold}_best.pt') # 性能对比分析 def analyze_results(): # 对比各fold模型在独立测试集的表现 test_metrics = [] for fold in range(ksplit): model = YOLO(f'cv_models/fold_{fold}_best.pt') metrics = model.val(data='data_test.yaml') test_metrics.append(metrics.box.map50) print(f'测试集平均mAP50: {np.mean(test_metrics):.2f}') ``` --相关问题-- 1. 如何选择最优的K值进行交叉验证? 2. 交叉验证中发现各fold性能差异较大说明什么问题? 3. YOLOv8交叉验证后如何选择最终部署模型? 4. 如何结合交叉验证结果进行超参数调优?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值