交叉验证stratified k-fold cv与shuffle等常用cv方法

本文深入探讨了交叉验证(CV)在机器学习中的应用,重点介绍了k折交叉验证和分层k折交叉验证(stratified k-fold CV)的概念及其实现。通过对比分析,阐述了分层k折交叉验证在确保数据分布均衡方面的重要性,特别是在处理分类任务时。同时,文章还提到了ShuffleSplit作为一种随机采样方法的优缺点,以及在回归问题中使用分层k折交叉验证的可能性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文参考:
https://scikit-learn.org/stable/modules/cross_validation.html#stratified-k-fold
与《python机器学习基础教程》
好,开始今天的cv学习!
本文需要有一些CV的基础概念之后看会更有收获。
在开始之前,我们要先明确一点:
交叉验证不是一种构建可应用于新数据的模型的方法。交叉验证不会返回一个模型。在调用cv时,内部虽然会构建多个模型,但交叉验证的目的只是评估在给定算法在特定数据集上训练后的泛化性能好坏。
补充:上面的话没有问题,但是在一些ML比赛中会用CV的内部模型来预测,也就是说内部模型有被用到的可能。

我认为CV的学习路线应该是这样的:
要知道k-folds(k层交叉验证)与stratified k-folds cv(分层k折cv)两种重要的方式,然后至于shufflesplit只是一种采用方式,即随机采样的方式,或者叫上面那两种基本方式的点缀。当然,还有留一法,分组cv的方式,但在这里我只讨论上面的k-folds(k层交叉验证)与stratified k-folds cv(分层k折cv)。

最最基本的k折交叉验证:
在这里插入图片描述
可以看到。对于训练集,它做了5等分,注意是按顺序分的。强调这个,就是因为这样分有不妥的时候,后面会提及。之后对于每一次,都会有4份做训练集,剩下一分做验证集或者叫训练集。
所以5个模型就会有5个结果:

>>> from sklearn.model_selection import cross_val_score
>>> clf = svm.SVC(kernel='linear', C=1)
>>> scores = cross_val_score(clf, iris.data, iris.target, cv=5)
>>> scores                                              
array([0.96..., 1.  ..., 0.96..., 0.96..., 1.        ])

看起来这样做CV挺好的,问题是什么呢?
问题就在于它是按顺序划分的。或者看这张图:
在这里插入图片描述
这是sklearn官网的一张图,从图中可以看到,很可能一折中的每等分都是同样的种类,也就是说没有意义了。所以有了shufflesplit与分层stratified交叉验证两种方式。先看shuffle:

from sklearn.model_selection import ShuffleSplit
X = np.arange(10)
ss = ShuffleSplit(n_splits=5, test_size=0.25,
    random_state=0)
for train_index, test_index in ss.split(X):
    print("%s %s" % (train_index, test_index))

输出:

[9 1 6 7 3 0 5] [2 8 4]
[2 9 8 0 6 7 4] [3 5 1]
[4 5 1 0 6 9 7] [2 3 8]
[2 7 5 8 0 3 4] [6 1 9]
[4 1 0 6 8 9 3] [5 2 7]

可以看到这次的分组绝无顺序可言,是打乱顺序的5次cv。
在这里插入图片描述
官网也说ss是传统k折的一个很好的替代。同时,他可避免种类的干扰,但是因为他是随机的,也完全有可能产生与k折类似的结果,那怎么办?假如说我就要求k折里面的训练集测试集种类class要尽量均匀呢?
stratified来了。stratified直译也就是分层的意思。
在这里插入图片描述
这张图清楚地说明了标准K折的不足,可以看到,每次训练集都只有一个种类,而测试集都是另外两种,这怎么可能预测的出来呢?
反观stratified。就不会出现这个问题,它保证了每个折中类别之间的比例与整个数据集中的比例相同。
再给出官网关于stratified的代码与图:
在这里插入图片描述
当然这个图的意思和我上个图意思一样的,我认为上一张更容易理解一些。
代码:

from sklearn.model_selection import StratifiedKFold
X = np.ones(10)
y = [0, 0, 0, 0, 1, 1, 1, 1, 1, 1]
skf = StratifiedKFold(n_splits=3)
for train, test in skf.split(X, y):
    print("%s %s" % (train, test))
[2 3 6 7 8 9] [0 1 4 5]
[0 1 3 4 5 8 9] [2 6 7]
[0 1 2 4 5 6 7] [3 8 9]

最后的最后。用书中一句话作为总结:
使用分层k折交叉验证而不是普通k折交叉验证来评估一个分类器,通常是一个好主意(可以在stratified的基础上再用用shufflesplit)。
对于回归问题,scikit-learn默认使用标准k折交叉验证。关于回归问题,有些也是需要使用stratified的,看具体要求而定吧。例如,我最近在参加的一个比赛中发现,对于这个竞赛,stratified是一种绝佳的选择,并且这个比赛是一个回归问题。

### 使用鸢尾花数据集实现K-交叉验证 在机器学习中,K-交叉验证是一种评估模型性能的常用方法。它通过将数据集划分为K个子集(或称为“折”),每次用其中的一个子集作为验证集,其余K-1个子集作为训练集,从而进行多次训练和验证[^1]。以下是使用Python中的`scikit-learn`库,在鸢尾花数据集上实现K-交叉验证的具体方法。 #### 数据准备 首先加载鸢尾花数据集,并将其特征矩阵`X`和目标向量`y`分离出来。 ```python from sklearn.datasets import load_iris # 加载鸢尾花数据集 data = load_iris() X = data.data # 特征矩阵 y = data.target # 目标向量 ``` #### 定义模型 选择一个机器学习模型进行训练和验证。以下以K近邻(KNN)算法为例。 ```python from sklearn.neighbors import KNeighborsClassifier # 定义KNN模型 knn = KNeighborsClassifier(n_neighbors=5, weights="distance") ``` #### 设置K-交叉验证 使用`KFold`类定义K-交叉验证的参数,例如折数、是否打乱数据等。 ```python from sklearn.model_selection import KFold # 定义5折交叉验证 kf = KFold(n_splits=5, shuffle=True, random_state=0) ``` #### 执行交叉验证 使用`cross_val_score`函数执行K-交叉验证,并计算模型的平均得分。 ```python from sklearn.model_selection import cross_val_score # 执行5折交叉验证 scores = cross_val_score(knn, X, y, cv=kf) # 输出每折的得分 print("每折交叉验证得分: ", scores) # 输出平均得分 print("平均得分: ", scores.mean()) ``` #### 示例输出 运行上述代码后,程序将输出每折的交叉验证得分以及所有折的平均得分。例如: ``` 每折交叉验证得分: [0.96666667 1. 1. 0.93333333 1. ] 平均得分: 0.98 ``` #### 参数优化(可选) 如果需要进一步优化模型参数,可以结合`GridSearchCV`进行网格搜索。以下是一个简单的示例: ```python from sklearn.model_selection import GridSearchCV # 定义参数网格 param_grid = {'n_neighbors': [3, 5, 7, 9], 'weights': ['uniform', 'distance']} # 定义GridSearchCV grid_search = GridSearchCV(KNeighborsClassifier(), param_grid, cv=5) # 执行网格搜索 grid_search.fit(X, y) # 输出最佳参数和最佳得分 print("最佳参数: ", grid_search.best_params_) print("最佳得分: ", grid_search.best_score_) ``` ### 注意事项 - 在分类问题中,建议使用分层K-交叉验证Stratified K-Fold),以确保每个折中的类别分布整体数据集一致[^2]。 - 对于二分类任务,可以使用更多评价指标(如精确率、召回率、F1-score等)来全面评估模型性能[^3]。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值