
☞ ░ 前往老猿Python博客 ░ https://blog.youkuaiyun.com/LaoYuanPython
一、概述
在机器学习中,数据预处理是非常重要的工作,常规执行顺序:数据分割 → 2. 数据清洗 → 3. 特征编码 → 4. 特征构造 → 5. 异常值处理 → 6. 特征缩放 → 7. 降维,可以看到数据分割是数据预处理的第一步。
任何基于统计的预处理(如均值填充、标准化)都应仅在训练集上计算参数,再应用到测试集,这样测试集才能起到评估训练后模型的效果。
Scikit-learn 提供了多种数据分割方法,适用于不同机器学习场景,包括简单随机分割train_test_split、标准K折交叉验证KFold、分层K折交叉验证StratifiedKFold、重复多次K折验证RepeatedKFold/RepeatedStratifiedKFold、时间序列分割TimeSeriesSplit、分组分割GroupKFold、LeaveOneGroupOut、留一法LeaveOneOut/LeavePOut。
这些方法一些使用上的建议:
- train_test_split:快速验证的简单随机数据分割
- KFold:适合回归任务,注意大数据集可减少n_splits
- StratifiedKFold:适合数据集不均衡分类 ,分类任务优先使用
- TimeSeriesSplit:适合时间序列
- GroupKFold:适合分组数据
- LeaveOneOut:适合小数据集
- RepeatedKFold:适合结果不稳定时使用
这些方法都可通过sklearn.model_selection导入,是模型评估的重要工具。根据数据特性和任务需求选择合适的分割方式,能显著提高模型评估的可靠性。
任何基于统计的预处理(如均值填充、标准化)都应仅在训练集上计算参数,再应用到测试集,这样测试集才能起到评估训练后模型的效果。
下面是老猿介绍sklearn中数据分割的相关方法的博文列表:
- 《Scikit-learn(sklearn)机器学习的数据分割方法–train_test_split和KFold https://blog.youkuaiyun.com/LaoYuanPython/article/details/149479366》介绍了简单数据分割train_test_split方法和K折交叉验证KFold类
- 《Scikit-learn(sklearn)机器学习的数据分割方法–分层K折交叉验证StratifiedKFold https://blog.youkuaiyun.com/LaoYuanPython/article/details/150060086》》介绍分层K折交叉验证StratifiedKFold的数据分割方法
- 《Scikit-learn(sklearn)机器学习的数据分割方法–重复 K 折RepeatedKFold https://blog.youkuaiyun.com/LaoYuanPython/article/details/149324637》介绍重复 K 折RepeatedKFold 的数据分割方法。
- …
二、重复 K 折交叉验证RepeatedKFold
2.1、背景
在机器学习的模型评估中,交叉验证(Cross-Validation, CV) 是衡量模型泛化能力的重要方法。传统的 KFold 将数据集划分为 K 个互斥的子集(“折”),进行 K 次训练和验证。然而,KFold 存在两个关键问题:
- 结果随机性:单次 KFold 的划分结果受随机种子 (random_state) 影响,可能导致评估指标(如准确率)波动较大
- 数据利用不充分:对于小数据集,单次 KFold 的评估可能无法充分反映模型性能。
为了解决这些问题,提出了重复 K 折交叉验证RepeatedKFold ,通过 重复多次独立 K 折划分 来提升评估的稳定性和可靠性。
2.2、原理
RepeatedKFold 的核心原理是多次独立采样,当数据量有限时,通过多次重复验证避免因单次划分巧合导致的过拟合或欠拟合误判。
RepeatedKFold首先将数据分成 K 个折叠,执行标准的 K-Fold 交叉验证,然后重复这个过程 n 次,每次使用不同的随机分割,每次都会重新随机划分 K 个折叠。
RepeatedKFold工作流程如下:
- 独立重复:执行 n_repeats 次独立的 KFold 划分,每次划分使用不同的随机种子(若 random_state 固定,则通过内部增量种子实现)。例如:n_splits=5(5折)、n_repeats=3,则共生成 5 × 3 = 15 个训练-测试集对
- 统计聚合:对多次重复的评估结果(如准确率)计算均值和标准差,均值反映模型的平均性能,标准差反映模型性能的稳定性。
假设单次 KFold 的评估指标为 θ i \theta_i θi (第 i 次的准确率),则 RepeatedKFold 的评估准确率为:
θ ^ = 1 n _ r e p e a t s ∑ i = 1 n _ repeats θ i \hat{\theta} = \frac{1}{n\_repeats} \sum_{i=1}^{n\_{\text{repeats}}} \theta_i θ^=n_repeats1i=1∑n_repeatsθi
方差(波动性)通过标准差 σ 衡量:
σ = 1 n _ repeats ∑ i = 1 n _ repeats ( θ i − θ ^ ) 2 σ = \sqrt{\frac{1}{n\_{\text{repeats}}} \sum_{i=1}^{n\_{\text{repeats}}} (\theta_i - \hat{\theta})^2} σ=n_repeats1i=1∑n_repeats(θi−θ^)2
2.3、scikit-learn 中重复 K 折交叉验证的实现
2.3.1、RepeatedKFold类的构造函数及属性
在scikit-learn 中,重复 K 折交叉验证使用类RepeatedKFold来实现,类的构造方法为:
__init__(self, *, n_splits=5, n_repeats=10, random_state=None)
其中n_splits是折数,n_repeats是重复次数,random_state是随机种子。
random_state取值除了整数(固定种子,确保结果可复现)和None(完全随机,每次运行结果不同)外,还可以取值为RandomState,表示使用一个已经初始化的随机数生成器(RNG)来控制数据划分的随机性,这样做的好处是:
- 直接控制随机性:该对象内部已经维护了随机状态,每次调用 split() 会更新其状态,但结果可预测(因为从同一对象初始化)
- 避免全局随机干扰:独立于 NumPy 的全局随机状态(np.random),适合需要隔离随机性的场景
- 共享随机状态:多个组件可以共享同一个 RandomState 对象,确保协同随机性
注:当多个组件(如数据划分、模型初始化、超参数采样)独立使用相同的整数种子时,可能导致意外的随机性重叠,不同种子时,随机数没有关联,各自独立。共享 RandomState 对象,只要一次初始化为固定随机种子,后续都使用该对象,每次调用按顺序更新状态,可以使得多个调用随机数的模块的随机性完全隔离,不会重叠,避免序列冲突,同时整个流程的随机性可复现。在数据划分的随机性需与模型初始化的随机性同步控制等需要协同随机性的场景下,建议共用一个随机对象。
注意:构造函数中的星号表示后面的参数都必须是关键字参数,不能通过位置传值。
RepeatedKFold的属性与KFold类似,就是构造函数中传递的参数n_splits、n_repeats、random_state。
2.3.2、RepeatedKFold类的方法
创建的RepeatedKFold类对象,其方法split用于获取生成的训练集和验证集的数据索引,get_n_splits返回总迭代次数(n_splits × n_repeats)。
三、案例
下面的按比例
def testRepeatedKFold():
from sklearn.model_selection import RepeatedKFold
from sklearn.datasets import make_classification
import numpy as np
rs = np.random.randint(20209)
X, y = make_classification(n_samples=100, n_features=20, random_state=rs)
rkf = RepeatedKFold(n_splits=5, n_repeats=3, random_state=rs)
for k,(train_index, test_index) in enumerate(rkf.split(X),1): # 训练和评估模型
print(f"第{ k }折的随机种子={rkf.random_state}训练集数据索引(top10):", train_index[:10], "验证集数据索引(top10):", test_index[:10])
X_train, X_test = X[train_index], X[test_index]
y_train, y_test = y[train_index], y[test_index]
testRepeatedKFold()
注:
- make_classification 是 scikit-learn 中一个用于生成模拟分类数据集的实用函数,特别适用于机器学习算法的测试、教学或实验场景。它可以快速创建一个具有可控特征的合成数据集,避免使用真实数据时的隐私或获取难度问题。其参数n_samples表示生成的总样本数,n_features表示数据的特征总数
- 该案例中使用了随机对象共享的方法,使得分类数据集创建和分割共用了一个随机数对象。
执行输出:
第1折的随机种子=11653训练集数据索引(top10): [ 0 3 4 5 6 8 9 10 11 12] 验证集数据索引(top10): [ 1 2 7 16 25 35 39 45 54 55]
第2折的随机种子=11653训练集数据索引(top10): [ 0 1 2 5 6 7 8 9 12 14] 验证集数据索引(top10): [ 3 4 10 11 13 19 26 33 34 37]
第3折的随机种子=11653训练集数据索引(top10): [ 0 1 2 3 4 6 7 8 9 10] 验证集数据索引(top10): [ 5 14 21 23 27 30 38 41 42 47]
第4折的随机种子=11653训练集数据索引(top10): [ 1 2 3 4 5 6 7 10 11 13] 验证集数据索引(top10): [ 0 8 9 12 17 22 29 31 36 44]
第5折的随机种子=11653训练集数据索引(top10): [ 0 1 2 3 4 5 7 8 9 10] 验证集数据索引(top10): [ 6 15 18 20 24 28 32 49 52 53]
第6折的随机种子=11653训练集数据索引(top10): [ 1 2 3 4 5 6 7 8 9 10] 验证集数据索引(top10): [ 0 15 16 19 24 25 30 36 37 48]
第7折的随机种子=11653训练集数据索引(top10): [ 0 1 2 3 4 6 8 10 11 12] 验证集数据索引(top10): [ 5 7 9 13 17 20 27 44 45 56]
第8折的随机种子=11653训练集数据索引(top10): [ 0 1 3 4 5 6 7 8 9 10] 验证集数据索引(top10): [ 2 11 21 33 34 38 40 41 52 54]
第9折的随机种子=11653训练集数据索引(top10): [ 0 2 3 5 6 7 8 9 11 12] 验证集数据索引(top10): [ 1 4 10 18 23 28 39 46 51 53]
第10折的随机种子=11653训练集数据索引(top10): [ 0 1 2 4 5 7 9 10 11 13] 验证集数据索引(top10): [ 3 6 8 12 14 22 26 29 31 32]
第11折的随机种子=11653训练集数据索引(top10): [ 0 4 6 7 9 10 11 12 13 14] 验证集数据索引(top10): [ 1 2 3 5 8 15 16 18 25 28]
第12折的随机种子=11653训练集数据索引(top10): [0 1 2 3 4 5 6 7 8 9] 验证集数据索引(top10): [10 12 13 17 23 29 34 41 46 47]
第13折的随机种子=11653训练集数据索引(top10): [ 0 1 2 3 4 5 6 8 9 10] 验证集数据索引(top10): [ 7 14 20 24 38 42 44 50 60 61]
第14折的随机种子=11653训练集数据索引(top10): [ 1 2 3 4 5 7 8 10 12 13] 验证集数据索引(top10): [ 0 6 9 11 21 22 26 27 33 39]
第15折的随机种子=11653训练集数据索引(top10): [ 0 1 2 3 5 6 7 8 9 10] 验证集数据索引(top10): [ 4 19 30 31 32 35 37 40 43 56]
四、小结
本文介绍了重复 K 折交RepeatedKFold数据分割的原理、算法以及在Scikit-learn(sklearn)中的实现,并提供了一个使用案例。RepeatedKFold首先将数据分成 K 个折叠,执行标准的 K-Fold 交叉验证,然后重复这个过程 n 次,每次使用不同的随机分割,每次都会重新随机划分 K 个折叠来提升评估的稳定性和可靠性。
更多人工智能知识学习过程中可能遇到的疑难问题及解决办法请关注专栏《零基础机器学习入门》及付费专栏《机器学习疑难问题集》后续的文章。
写博不易,敬请支持:
如果阅读本文于您有所获,敬请点赞、评论、收藏,谢谢大家的支持!
关于老猿的付费专栏
- 付费专栏《https://blog.youkuaiyun.com/laoyuanpython/category_9607725.html 使用PyQt开发图形界面Python应用》专门介绍基于Python的PyQt图形界面开发基础教程,对应文章目录为《 https://blog.youkuaiyun.com/LaoYuanPython/article/details/107580932 使用PyQt开发图形界面Python应用专栏目录》;
- 付费专栏《https://blog.youkuaiyun.com/laoyuanpython/category_10232926.html moviepy音视频开发专栏 )详细介绍moviepy音视频剪辑合成处理的类相关方法及使用相关方法进行相关剪辑合成场景的处理,对应文章目录为《https://blog.youkuaiyun.com/LaoYuanPython/article/details/107574583 moviepy音视频开发专栏文章目录》;
- 付费专栏《https://blog.youkuaiyun.com/laoyuanpython/category_10581071.html OpenCV-Python初学者疑难问题集》为《https://blog.youkuaiyun.com/laoyuanpython/category_9979286.html OpenCV-Python图形图像处理 》的伴生专栏,是笔者对OpenCV-Python图形图像处理学习中遇到的一些问题个人感悟的整合,相关资料基本上都是老猿反复研究的成果,有助于OpenCV-Python初学者比较深入地理解OpenCV,对应文章目录为《https://blog.youkuaiyun.com/LaoYuanPython/article/details/109713407 OpenCV-Python初学者疑难问题集专栏目录 》
- 付费专栏《https://blog.youkuaiyun.com/laoyuanpython/category_10762553.html Python爬虫入门 》站在一个互联网前端开发小白的角度介绍爬虫开发应知应会内容,包括爬虫入门的基础知识,以及爬取优快云文章信息、博主信息、给文章点赞、评论等实战内容。
前两个专栏都适合有一定Python基础但无相关知识的小白读者学习,第三个专栏请大家结合《https://blog.youkuaiyun.com/laoyuanpython/category_9979286.html OpenCV-Python图形图像处理 》的学习使用。
对于缺乏Python基础的同仁,可以通过老猿的免费专栏《https://blog.youkuaiyun.com/laoyuanpython/category_9831699.html 专栏:Python基础教程目录)从零开始学习Python。
如果有兴趣也愿意支持老猿的读者,欢迎购买付费专栏。

24

被折叠的 条评论
为什么被折叠?



