K折交叉验证python详解

火山方舟向量数据库大模型

前言

K折交叉验证(K-fold cross-validation)是一种常用的模型评估技术,用于评估模型在数据集上的性能,它通过将数据集分为K个相似大小的子集(折),然后对模型进行K次训练和测试,在每次迭代中,其中一个子集被用作测试集,其余的K-1个子集被用作训练集

整个过程重复K次,每个子集都会被用作一次测试集,每一次都会得到一个模型性能的评估指标,通常,这些指标的平均值被用来评估模型的性能

K折交叉验证的主要优势在于,它充分利用了数据集,尽可能多地用于训练和测试,对于小规模数据集特别有用,因为它可以提供更可靠的模型性能估计,减少由于数据集划分的随机性引起的评估结果的变化或不稳定性

步骤简述如下:

  1. 将数据集分为K个子集
  2. 对于每个子集,使用其余K-1个子集进行训练
  3. 使用当前子集进行测试,计算模型性能指标
  4. 重复步骤2和3,直到每个子集都被用作测试集
  5. 计算K次测试的平均性能指标,作为最终的模型性能估计

总体而言,通过对不同数据集划分的平均性能进行评估,使得更有信心地了解模型在整个数据分布上的表现,而不仅仅是在某个特定的数据划分上

python实现

Scikit-learn中各种交叉验证方案的实现:’sklearn.model_selection‘模块的 类为K折交叉验证的每个迭代创建了 和 , 的索引。默认情况下,它将数据 拆分为5个连续的折叠,不进行任何洗牌。但是,使用以下参数,可以更改其默认行为

  1. 'n_splits' 改变折叠的数量
  2. 将 'shufffle' 设置为 True 会在拆分为 'n_splits' 个折叠之前对数据进行洗牌
  3. 使用 'random_state' 参数,如果 'shuffle' 设置为 True,可以创建可重现的结果

接下来使用这个类在鸢尾花分类数据集上实现K折交叉验证。加载原始的鸢尾花数据集,就像在将数据集拆分为训练集和测试集之前一样(如果还需要测试集的话),然后仅在训练数据上应用交叉验证,从KFold类创建一个对象,并调用split方法来生成每次3折交叉验证迭代的训练(Str,n−Foldk)和测试(Foldk)集。此外,在第k次迭代中,在训练集(Str,n−Foldk)上训练一个分类器(这里使用5NN),并在Foldk上测试其准确性,即该迭代的测试集。最后但同样重要的是,通过取每次迭代获得的准确性估计的均值来获得准确性的整体K折交叉验证估计


          
import numpy as np
          
from sklearn import datasets
          
from sklearn.model_selection import KFold
          
from sklearn.model_selection import train_test_split
          
from sklearn.neighbors import KNeighborsClassifier as KNN
          
# 载入训练数据
          
iris = datasets.load_iris()
          
# 划分训练集和测试集
          
X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, random_state=100, test_size=0.2, stratify=iris.target)
          
# 输出数据集的形状
          
print('X_train_shape: ' + str(X_train.shape) + '\nX_test_shape: ' + str(X_test.shape) + '\ny_train_shape: ' + str(y_train.shape) + '\ny_test_shape: ' + str(y_test.shape) + '\n')
          
# 设置 K 折交叉验证的折数
          
K_fold = 3
          
kfold = KFold(n_splits=K_fold, shuffle=True, random_state=42)  # 使用 shuffle 进行数据集的随机洗牌
          
cv_scores = np.zeros(K_fold)  # 用于存储每次交叉验证的分数
          
# 创建 KNN 分类器
          
knn = KNN(n_neighbors=5)
      

          
for counter, (train_idx, test_idx) in enumerate(kfold.split(X_train, y_train)):
          
    # 输出当前 K 折交叉验证的迭代次数
          
    print("K-fold CV iteration " + str(counter+1))
          
    
          
    # 输出训练集和测试集的索引
          
    print("Train indices:", train_idx)
          
    print("Test indices:", test_idx, "\n")
          
    
          
    # 使用当前折的索引获取训练集和测试集
          
    X_train_kfold = X_train[train_idx,]
          
    y_train_kfold = y_train[train_idx,]
          
    X_test_kfold = X_train[test_idx,]
          
    y_test_kfold = y_train[test_idx,]
          
    
          
    # 训练 KNN 模型并计算测试集的准确率
          
    cv_scores[counter] = knn.fit(X_train_kfold, y_train_kfold).score(X_test_kfold, y_test_kfold)
          
    
          
    # 输出每一折的准确率
          
    print("the accuracy of folds are: ", cv_scores)
          
    
          
    # 输出整体的 3 折交叉验证准确率的均值
          
    print("the overall 3-fold CV accuracy is: {:.3f}".format(cv_scores.mean()))
      

picture.image

与其像上面展示的那样在每次迭代中实现一个for循环来训练和测试替代分类器,scikit-learn提供了使用 'sklearn.model_selection' 模块中的 'cross_val_score' 函数来获取交叉验证分数的便捷方式。该类有多个参数,以下是其中一些特别有用的参数:

  1. ‘estimator’ 用于指定CV中使用的估计器(例如,分类器或回归器)
  2. ‘X’ 是训练数据
  3. ‘y’ 是目标变量的值
  4. ‘cv’ 决定了CV的策略,具体解释如下:

将 ‘cv’ 设置为分类问题中的整数 ‘K’,将使用无洗牌的分层 ‘K’ 折交叉验证。为了实现分类的 ‘K’ 折交叉验证,也可以将 ’cv‘ 参数设置为 ‘KFold’ 类的对象,如果需要洗牌,则应将 ‘KFold’ 的 ‘shuffle’ 参数设置为 ‘True’

将 cv 设置为回归问题中的整数 ‘K’,将使用无洗牌的标准 ‘K’ 折交叉验证(请注意,回归问题没有定义分层 K 折交叉验证)。如果需要洗牌,则应将 KFold 的 ‘shuffle’ 参数设置为 ‘True’,并将 ‘cv’ 设置为 ‘KFold’ 的对象 5. ‘n_jobs’ 用于指定在计算CV估计时可以并行使用的CPU核心数。将 ‘n_jobs=-1’ 设置为使用所有处理器

  1. ‘scoring’:该参数的默认值 ‘None’ 导致使用估计器评分方法的默认度量,例如,在使用 ‘DecisionTreeRegressor’ 估计器的情况下 是默认的评分器,在使用 'DecisionTreeClassifier' 估计器的情况下,默认的评分器是准确度评估器

          
from sklearn.model_selection import cross_val_score
          
knn = KNN(n_neighbors=5)
          
cv_scores = cross_val_score(knn, X_train, y_train, cv=kfold)
          
print("the accuracy of folds are: ", cv_scores)
          
print("the overall 3-fold CV accuracy is: {:.3f}".format(cv_scores.mean()))
      

picture.image

接下来,使用 ‘cross_val_score‘ 来实现分层 K 折交叉验证。正如之前所说,将 cv 参数默认设置为整数时,对于分类问题,会使用分层 K 折交叉验证


          
cv_scores = cross_val_score(knn, X_train, y_train, cv=3)
          
print("the accuracy of folds are: ", cv_scores)
          
print("the overall 3-fold CV accuracy is: {:.3f}".format(cv_scores.mean()))
      

picture.image

与 ’KFold‘ 类类似,该类可用于在每个CV迭代中创建训练和测试的索引,我们还有来自 ’sklearn.model_selection‘ 模块的 ’StratifiedKFold‘ 类,可用于创建这些索引。因此,另一种更灵活控制分层K折交叉验证的方法是将 ’cross_val_score‘ 的 ’cv‘ 参数设置为 ’StratifiedKFold‘ 类的对象


          
from sklearn.model_selection import StratifiedKFold, cross_val_score
          
# 创建 StratifiedKFold 对象,进行分层 K 折交叉验证
          
strkfold = StratifiedKFold(n_splits=K_fold, shuffle=True, random_state=42)
          
cv_scores = cross_val_score(knn, X_train, y_train, cv=strkfold)
          
print("每折的准确性:", cv_scores)
          
print("整体 3 折交叉验证准确性:{:.3f}".format(cv_scores.mean()))
      

picture.image

如果你对类似于这样的文章感兴趣。

欢迎关注、点赞、转发~

0
0
0
0
关于作者

文章

0

获赞

0

收藏

0

相关资源
DevOps 在字节移动研发中的探索和实践
在日益复杂的APP工程架构下,如何保证APP能高效开发,保障团队效能和工程质量?本次将结合字节内部应用的事件案例,介绍DevOps团队对移动研发效能建设的探索和思考。
相关产品
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论