当前位置:   article > 正文

深入解析K折交叉验证:原理、应用及优化策略(python实现 代码详解)

k折交叉验证

目录

一、K折交叉验证介绍

二、K折交叉验证的作用

三、在K折交叉验证中,每次模型的训练都是独立于上一次的

四、K折交叉验证用于比较不同模型的性能(python实现)

 五、K折交叉验证用于超参数调优

六、K折交叉验证用于选择最优训练集和验证集,从而训练模型 

 试想:

如果我想获得每次迭代的训练数据和测试数据,会在整个交叉验证过程中记录所有得分达到最高得分的训练集和测试集,并在最后输出这些数据或者索引,怎么办呢?

如下:

 获得得分最高时的训练集和测试集

七、补充:

一、K折交叉验证介绍

K折交叉验证(K-fold cross-validation)是一种常用的模型评估技术,用于评估机器学习模型在训练数据上的性能。它将原始数据集分成K个子集,称为折(fold)。然后,模型在K个不同的训练集上进行K次训练和验证,在每次训练中,其中一个折被作为验证集,而剩下的K-1个折被用作训练集。这样就产生了K个模型和对应的K个验证分数。

K折交叉验证的步骤如下:

  1. 将原始数据集分成K个子集。
  2. 对于每个子集i,将其作为验证集,其余的K-1个子集作为训练集。
  3. 训练模型,并在验证集上进行评估,记录评估指标(如准确率、精确度、召回率等)。
  4. 重复步骤2和3,直到每个子集都充当一次验证集,从而产生了K个评估指标。
  5. 对K个评估指标取平均值作为最终的模型性能评估指标。

K折交叉验证的优点包括:

  • 有效利用数据:每个样本都有机会被训练和验证,提高了数据的利用率。
  • 减少过拟合:由于每个样本都会被验证,因此模型的性能评估更具代表性,有助于减少过拟合。
  • 对模型泛化能力的评估更可靠:通过多次验证可以更准确地评估模型在未见数据上的泛化能力。

K折交叉验证的缺点包括:

  • 计算成本较高:需要训练和验证K次模型,因此需要更多的计算资源和时间。
  • 结果可能不稳定:由于每次划分的训练集和验证集都不同,因此模型评估的结果可能会有一定的波动性。

二、K折交叉验证的作用

  1. 比较不同模型的性能:通过比较不同模型在相同数据集上的性能表现,可以帮助您选择最适合特定任务的模型。通过绘制ROC曲线、计算AUC值、精确度、召回率等指标,可以更全面地评估不同模型的性能优劣。

  2. 选择最优训练集和验证集训练模型:K折交叉验证可以帮助您更充分地利用有限的数据集,减少因数据划分不合理而引入的偶然性。通过将数据集分成K个子集,依次将每个子集作为验证集,其余作为训练集,可以得到K个模型,进而对模型性能进行更准确的评估。

  3. 超参数调优:通过交叉验证,可以帮助您在训练过程中调整模型的超参数,以提高模型的泛化能力和性能。

  4. 防止过拟合:K折交叉验证可以减少过拟合的风险,因为模型在多个不同的训练集上进行训练,有助于更好地泛化到未见过的数据。

  5. 评估模型的稳定性:通过多次重复K折交叉验证,可以评估模型在不同数据集上的稳定性,从而更全面地了解模型的性能表现。

综上所述,比较不同模型的性能和K折交叉验证是机器学习中常用的重要技术,除了帮助选择最佳模型和训练集外,还有助于超参数调优、防止过拟合、评估模型稳定性等方面的作用。

三、在K折交叉验证中,每次模型的训练都是独立于上一次的

如五折交叉验证

在K折交叉验证中,每次模型的训练都是独立于上一次的。在五折交叉验证的过程中,首先将整个数据集平均分成五个部分,然后进行五次训练和测试的迭代。在每一次迭代中,使用其中的一部分数据作为测试集,其余的四部分数据合并起来作为训练集。这样保证了每个样本都有一次机会作为测试集出现,而同时在训练集中则不会出现。

以下是该过程的关键要点:

  1. 独立性:在第二次以及后续的迭代中,模型从头开始训练,不会保留第一次迭代训练中的任何参数或“记忆”。
  2. 评价指标:每次迭代完成后都会得到一个模型的性能评估。通过比较五次迭代得到的评估结果,可以选择最佳模型或者计算模型的平均性能。
  3. 模型选择:最终选择的模型通常是在所有迭代中表现最好的那一个
  4. 数据划分:为了确保每次迭代的训练和测试都是独立的,需要在每次迭代之前重新划分数据集。

总的来说,五折交叉验证是一种模型验证技术,它通过重复的训练和测试来评估模型的性能,并尽量减小了数据划分带来的偏差。在实际应用中,这种方法有助于更精确地估计模型在未知数据上的表现。

四、K折交叉验证用于比较不同模型的性能(python实现)

下面是一个简单的Python代码示例,用于比较KNN(K最近邻)和决策树两种模型在K折交叉验证下的性能表现。

首先加载了鸢尾花数据集,然后初始化了K最近邻(KNN)和决策树两种分类模型。接着使用cross_val_score函数进行5折交叉验证,分别得到KNN和决策树在每次验证中的准确率,最后计算并输出它们的平均准确率。通过比较这两个模型的性能表现,可以帮助我们选择更适合的模型用于实际应用。

  1. from sklearn.datasets import load_iris
  2. from sklearn.model_selection import cross_val_score
  3. from sklearn.neighbors import KNeighborsClassifier
  4. from sklearn.tree import DecisionTreeClassifier
  5. from sklearn.model_selection import KFold
  6. # 加载鸢尾花数据集
  7. iris = load_iris()
  8. X = iris.data
  9. y = iris.target
  10. # 初始化KNN和决策树模型
  11. knn_model = KNeighborsClassifier()
  12. dt_model = DecisionTreeClassifier()
  13. #将数据集划分为5个折叠,对数据进行洗牌,并设置随机种子为0
  14. kf = KFold(n_splits=5, shuffle=True, random_state=0)
  15. # 使用5折交叉验证比较两个模型的性能
  16. knn_scores = cross_val_score(knn_model, X, y, cv=kf)
  17. dt_scores = cross_val_score(dt_model, X, y, cv=kf)
  18. print("KNN模型准确率:", knn_scores.mean())
  19. print("决策树模型准确率:", dt_scores.mean())

 五、K折交叉验证用于超参数调优

通过这段代码,可以找到在给定参数网格下,K最近邻模型在鸢尾花数据集上的最佳参数组合以及对应的最佳得分(准确率)。这有助于优化模型的性能和泛化能力。

  1. from sklearn.neighbors import KNeighborsClassifier
  2. from sklearn.model_selection import GridSearchCV, KFold
  3. from sklearn.datasets import load_iris
  4. # 加载示例数据集(这里以鸢尾花数据集为例)
  5. data = load_iris()
  6. X = data.data
  7. y = data.target
  8. # 定义K最近邻模型
  9. knn = KNeighborsClassifier()
  10. # 定义参数网格
  11. param_grid = {
  12. 'n_neighbors': [3, 5, 7],
  13. 'weights': ['uniform', 'distance']
  14. }
  15. #weights:指定在预测时如何对邻居的权重进行加权,常见取值有uniform(所有邻居权重相等)和distance(权重与距离成反比)。
  16. # 使用GridSearchCV和KFold进行交叉验证
  17. kf = KFold(n_splits=5, shuffle=True, random_state=0)
  18. grid_search = GridSearchCV(knn, param_grid, cv=kf, scoring='accuracy')
  19. grid_search.fit(X, y)
  20. # 输出最佳参数和最佳得分
  21. print("最佳参数:", grid_search.best_params_)
  22. print("最佳得分:", grid_search.best_score_)

 

六、K折交叉验证用于选择最优训练集和验证集,从而训练模型 

  1. from sklearn.neighbors import KNeighborsClassifier
  2. from sklearn.model_selection import GridSearchCV, KFold
  3. from sklearn.datasets import load_iris
  4. from sklearn.model_selection import cross_val_score
  5. # 加载示例数据集(这里以鸢尾花数据集为例)
  6. data = load_iris()
  7. X = data.data
  8. y = data.target
  9. # 定义K最近邻模型
  10. knn = KNeighborsClassifier(n_neighbors=5,weights="distance")
  11. kf = KFold(n_splits=5, shuffle=True, random_state=0)
  12. # 使用cross_val_score进行五折交叉验证
  13. scores = cross_val_score(knn, X, y, cv=kf)
  14. # 输出每折交叉验证的得分
  15. print("每折交叉验证得分: ", scores)
  16. # 输出平均得分
  17. print("平均得分: ", scores.mean())

 试想:

如果我想获得每次迭代的训练数据和测试数据,会在整个交叉验证过程中记录所有得分达到最高得分的训练集和测试集,并在最后输出这些数据或者索引,怎么办呢?

如下:

  1. from sklearn.neighbors import KNeighborsClassifier
  2. from sklearn.model_selection import KFold
  3. from sklearn.datasets import load_iris
  4. import numpy as np
  5. # 加载示例数据集(这里以鸢尾花数据集为例)
  6. data = load_iris()
  7. X = data.data
  8. y = data.target
  9. # 定义K最近邻模型
  10. knn = KNeighborsClassifier(n_neighbors=5, weights="distance")
  11. kf = KFold(n_splits=5, shuffle=True, random_state=0)
  12. train_data_indices = []
  13. test_data_indices = []
  14. scores = [] # 存储每折的得分
  15. max_score = float('-inf')
  16. best_train_indices = []
  17. best_test_indices = []
  18. # 使用KFold的split方法进行五折交叉验证
  19. i = 1 # 计数器
  20. for train_index, test_index in kf.split(X):
  21. train_data_indices.append(train_index)
  22. test_data_indices.append(test_index)
  23. X_train, X_test = X[train_index], X[test_index]
  24. y_train, y_test = y[train_index], y[test_index]
  25. # 训练模型
  26. knn.fit(X_train, y_train)
  27. # 在测试集上评估模型
  28. score = knn.score(X_test, y_test)
  29. # 存储得分
  30. scores.append(score)
  31. # 如果得分大于或等于最高得分,则更新最高得分及其对应的训练数据和测试数据
  32. if score >= max_score:
  33. if score > max_score:
  34. best_train_indices = []
  35. best_test_indices = []
  36. max_score = score
  37. best_train_indices.append(train_index)
  38. best_test_indices.append(test_index)
  39. print("第{}次训练数据索引: ".format(i), train_index)
  40. print("第{}次测试数据索引: ".format(i), test_index)
  41. print("得分: ", score)
  42. print("-----------------------------------------")
  43. i += 1
  44. # 输出每折交叉验证的得分
  45. print("每折交叉验证得分: ", scores)
  46. # 输出平均得分
  47. print("平均得分: ", np.mean(scores))
  48. # 输出最高得分对应的训练数据和测试数据索引
  49. print("最高得分对应的训练数据索引: ", best_train_indices)
  50. print("最高得分对应的测试数据索引: ", best_test_indices)

这段代码实现了使用KFold进行五折交叉验证,并在每一折中训练K最近邻模型,并记录每折的得分。最后输出了每折交叉验证的得分、平均得分以及最高得分对应的训练数据和测试数据索引。

结果如下:

  1. train_num_sublists = len(best_train_indices)
  2. print("储存train的列表中包含的子列表数量为:", train_num_sublists)
  3. test_num_sublists = len(best_test_indices)
  4. print("储存test的列表中包含的子列表数量为:", test_num_sublists)

 其中最高得分最应的训练集和测试集一共输出了三组,是因为在五折交叉验证中,第一个flod、第三个flod、第四个flod都得到了最高分1.0

 获得得分最高时的训练集和测试集

那么我们选择得到最高分中对应的的任意一组测试集和训练集即可,这里我们选第一个fold对应的训练集和测试集。

  1. X_train, X_test = X[best_train_indices[1]], X[best_test_indices[1]]
  2. y_train, y_test = y[best_train_indices[1]], y[best_test_indices[1]]
  1. print(X_train.shape)
  2. print(X_test.shape)
  3. print(y_train.shape)
  4. print(y_test.shape)

七、补充:

使用K折交叉交叉验证后,是不是选择最优模型,然后再依照选择的最优模型,将数据按照比例划分为训练集和测试集,然后将数据将训练集和测试集应用到最优模型上。再K折交叉验证时,是不是并没有拟合模型,所以交叉验证之后并不能进行预测。

交叉验证主要用于模型选择和参数调优,完成后会选择最优模型并在全部训练集上进行训练,最后使用测试集评估模型的泛化能力。交叉验证过程中虽然不直接产出可用于预测的模型,但它是指导我们得到最终可用模型的重要步骤。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/629065
推荐阅读
相关标签
  

闽ICP备14008679号