终于把机器学习中的交叉验证搞懂了!!
今天给大家分享机器学习中的一个关键概念,交叉验证。交叉验证(Cross-Validation)是机器学习中一种广泛使用的模型评估方法,用于评估预测模型在未见数据上的表现。
它通过将数据集划分为多个子集,重复训练和验证模型,以减少评估结果的方差并提供更稳定、可靠的性能估计。交叉验证能够更可靠地估计模型的泛化能力,减少由于数据分割方式不同带来的评估偏差。
基本原理
1.数据划分
将原始数据集划分为多个部分,通常称为“折”(folds)。
2.循环验证
每次迭代中,将一个折作为验证集(测试集),其余折作为训练集。模型在训练集上训练后,在验证集上评估性能。
3.综合结果
对所有迭代的评估结果(例如准确率、精度、召回率等)取平均值,作为模型的整体性能。
通过这种方式,可以减少因单一训练/测试分割可能带来的随机性和偏差,提供对模型性能更稳健的估计。
交叉验证的应用
模型选择
通过交叉验证评估不同模型的性能,从而选择最优的模型。
例如,在分类问题中,可以通过K折交叉验证比较逻辑回归、支持向量机和随机森林等模型的准确率,选择表现最佳的模型。
超参数调优
许多机器学习模型具有超参数,需要通过调优来优化模型性能。
交叉验证可以用于评估不同超参数组合下的模型表现,从而选择最佳的超参数。
例如,支持向量机中的核函数参数和正则化参数,可以通过交叉验证找到最佳组合。
特征选择
在高维数据中,选择相关特征对于提高模型性能至关重要。
交叉验证可以用于评估不同特征子集下的模型表现,帮助选择最具预测能力的特征组合。
常见的交叉验证技术
1.k 折交叉验证
k 折交叉验证是最常用的交叉验证方法之一,通过将数据集分成 k 个相等或近似相等的子集(folds,折),并进行 k 次训练和验证,以评估模型的性能。
步骤:
[*]将数据随机划分为 K 个非重叠子集。
[*]在第 i 次迭代中
[*]使用第 i 个子集作为验证集。
[*]使用其他 K-1 个子集作为训练集。
[*]计算每次迭代的性能指标。
[*]取所有迭代的性能指标的平均值作为最终评估结果。
适用场景
适用于大多数机器学习任务,尤其是数据量中等且对计算效率要求不苛刻的场景。
优缺点:
优点
[*]实现简单,广泛支持于各类机器学习框架。
[*]每个样本都被用作训练集和验证集,充分利用了数据。
缺点
[*]计算成本较高,尤其当 K 较大时。
from sklearn.model_selection import KFoldfrom sklearn.datasets import make_classificationfrom sklearn.ensemble import RandomForestClassifierfrom sklearn.metrics import accuracy_scoreimport numpy as np# 创建示例数据X, y = make_classification(n_samples=1000, n_features=20, random_state=42)# 初始化模型model = RandomForestClassifier()# K-Fold Cross Validationkf = KFold(n_splits=5)accuracies = []for train_index, test_index in kf.split(X): X_train, X_test = X, X y_train, y_test = y, y model.fit(X_train, y_train) y_pred = model.predict(X_test) accuracies.append(accuracy_score(y_test, y_pred))print("K-Fold Accuracies:", accuracies)print("Mean Accuracy:", np.mean(accuracies))
[*]1.
[*]2.
[*]3.
[*]4.
[*]5.
[*]6.
[*]7.
[*]8.
[*]9.
[*]10.
[*]11.
[*]12.
[*]13.
[*]14.
[*]15.
[*]16.
[*]17.
[*]18.
[*]19.
[*]20.
[*]21.
[*]22.
[*]23.
[*]24.
[*]25.
2.留一法交叉验证
留一法交叉验证是 k 折交叉验证的极端情况,其中 k 等于样本数量。
每次迭代中,选择一个样本作为验证集,其余所有样本作为训练集。
步骤:
[*]数据集中有 N 个样本。
[*]每次迭代中:
[*]使用 N-1 个样本作为训练集。
[*]剩余 1 个样本作为验证集。
[*]计算 N 次迭代的性能指标,并取平均值作为最终评估结果。
适用场景
适用于数据量较小的场景,尤其是在希望最大限度利用训练数据时。
优缺点
优点
[*]理论上提供模型的无偏估计。
[*]最大限度地利用了训练数据,每次训练使用 n-1 个样本,特别适用于小数据集。
缺点
[*]计算成本非常高(N 次模型训练)。
[*]对异常值非常敏感,可能导致性能波动。
from sklearn.model_selection import LeaveOneOut# Leave-One-Out Cross Validationloo = LeaveOneOut()accuracies = []for train_index, test_index in loo.split(X): X_train, X_test = X, X y_train, y_test = y, y model.fit(X_train, y_train) y_pred = model.predict(X_test) accuracies.append(accuracy_score(y_test, y_pred))print("LOOCV Mean Accuracy:", np.mean(accuracies))
[*]1.
[*]2.
[*]3.
[*]4.
[*]5.
[*]6.
[*]7.
[*]8.
[*]9.
[*]10.
[*]11.
[*]12.
[*]13.
[*]14.
3.分层 K 折交叉验证
分层 k 折交叉验证是 k 折交叉验证的一个变种,特别适用于分类任务,
通过保持每个折中各类别的比例与整个数据集一致,确保模型在训练和验证过程中能够见到各类别的代表性样本。
步骤
[*]根据数据的类别分布,将数据分为 K 个子集,保证每个子集的类别分布与原始数据集一致。
[*]像普通 K折交叉验证一样进行模型训练和验证。
适用场景
适用于分类任务,尤其是当目标变量类别分布不平衡时。
优缺点
优点:
[*]提供更公正的性能估计。
[*]避免因类别不平衡而导致性能评估偏差。
缺点:
[*]需要额外的分层处理,复杂性稍高。
from sklearn.model_selection import StratifiedKFold# Stratified K-Foldskf = StratifiedKFold(n_splits=5)accuracies = []for train_index, test_index in skf.split(X, y): X_train, X_test = X, X y_train, y_test = y, y model.fit(X_train, y_train) y_pred = model.predict(X_test) accuracies.append(accuracy_score(y_test, y_pred))print("Stratified K-Fold Accuracies:", accuracies)print("Mean Accuracy:", np.mean(accuracies))
[*]1.
[*]2.
[*]3.
[*]4.
[*]5.
[*]6.
[*]7.
[*]8.
[*]9.
[*]10.
[*]11.
[*]12.
[*]13.
[*]14.
[*]15.
4.重复k折交叉验证
重复 k 折交叉验证通过多次随机划分k折交叉验证,提高评估结果的稳定性和可靠性。每次重复都会随机打乱数据集并重新划分 k 折。
步骤
1.设定重复次数
选择重复的次数(如重复10次)。
2.多次k折划分
对于每次重复,随机打乱数据集并进行 k 折交叉验证。
3.汇总结果
收集所有重复的 k 次评估结果,计算总体的平均性能和方差。
适用场景
当需要更精确和稳健的模型评估,且计算资源允许时。
优缺点
优点
[*]通过多次不同的划分,减少单次 k 折交叉验证可能引入的偏差和方差。
[*]多次重复提供了更稳健的性能估计。
缺点
[*]相对于单次 k 折交叉验证,重复 k 折需要更多的计算资源和时间。
from sklearn.model_selection import RepeatedKFoldfrom sklearn.datasets import make_classificationfrom sklearn.ensemble import RandomForestClassifierfrom sklearn.metrics import accuracy_scoreimport numpy as np# 创建示例数据X, y = make_classification(n_samples=1000, n_features=20, random_state=42)# 初始化模型model = RandomForestClassifier()# Repeated K-Fold Cross Validationrkf = RepeatedKFold(n_splits=5, n_repeats=3, random_state=42)# 5 折,重复 3 次accuracies = []for train_index, test_index in rkf.split(X): X_train, X_test = X, X y_train, y_test = y, y model.fit(X_train, y_train) y_pred = model.predict(X_test) accuracies.append(accuracy_score(y_test, y_pred))print("Repeated K-Fold Accuracies:", accuracies)print("Mean Accuracy:", np.mean(accuracies))
[*]1.
[*]2.
[*]3.
[*]4.
[*]5.
[*]6.
[*]7.
[*]8.
[*]9.
[*]10.
[*]11.
[*]12.
[*]13.
[*]14.
[*]15.
[*]16.
[*]17.
[*]18.
[*]19.
[*]20.
[*]21.
[*]22.
[*]23.
[*]24.
[*]25.
5.时间序列交叉验证
时间序列交叉验证专门用于时间序列数据,保持时间顺序,避免未来信息泄露到训练集中。
常见的方法包括滚动窗口(Rolling Window)和扩展窗口(Expanding Window)。
滚动窗口交叉验证
滚动窗口法通过固定大小的训练集窗口,随着时间的推进,窗口向前滑动,包含最新的数据,同时排除最早的数据。
1.初始划分
选择一个固定长度的训练集(例如前 60 个月的数据)和一个固定长度的验证集(例如接下来的1个月)。
2.训练与验证
[*]使用初始训练集训练模型。
[*]在验证集上评估模型性能。
[*]滚动窗口:将训练集窗口向前滑动一个时间步长(例如一个月),包含最新的数据,排除最早的数据。
[*]重复训练与验证过程,直到覆盖整个数据集。
3.结果汇总
计算所有验证阶段的性能指标的平均值,作为模型的最终评估结果。
扩展窗口交叉验证
扩展窗口法从固定的初始训练集开始,随着时间的推进,训练集不断扩大,包含所有之前的历史数据。
[*]初始划分
选择一个初始长度的训练集(例如前60个月的数据)和一个固定长度的验证集(例如接下来的1个月)。
[*]训练与验证
[*]使用初始训练集训练模型。
[*]在验证集上评估模型性能。
[*]扩展训练集:将验证集的数据加入训练集。
[*]选择下一个时间步长作为新的验证集。
[*]重复训练与验证过程,直到覆盖整个数据集。
[*]结果汇总
计算所有验证阶段的性能指标的平均值,作为模型的最终评估结果。
适用场景
时间序列预测、金融数据分析、任何需要考虑时间依赖性的任务。
优缺点
优点
[*]保持时间顺序:防止未来数据泄露,提高评估的真实性。
缺点
[*]实现复杂:需要根据具体的时间序列特性设计窗口策略。
[*]参数选择敏感:窗口大小和步长等参数选择对结果影响较大。
from sklearn.model_selection import TimeSeriesSplitimport numpy as np# 创建示例数据X = np.arange(1000).reshape(-1, 1)# 示例特征数据y = np.arange(1000)# 示例目标值# 初始化模型model = RandomForestClassifier()# Time Series Splittscv = TimeSeriesSplit(n_splits=5)# 5 个时间序列划分accuracies = []for train_index, test_index in tscv.split(X): X_train, X_test = X, X y_train, y_test = y, y model.fit(X_train, y_train) y_pred = model.predict(X_test) accuracies.append(accuracy_score(y_test, y_pred))print("Time Series Split Accuracies:", accuracies)print("Mean Accuracy:", np.mean(accuracies))
[*]1.
[*]2.
[*]3.
[*]4.
[*]5.
[*]6.
[*]7.
[*]8.
[*]9.
[*]10.
[*]11.
[*]12.
[*]13.
[*]14.
[*]15.
[*]16.
[*]17.
[*]18.
[*]19.
[*]20.
[*]21.
[*]22.
[*]23.
6.嵌套交叉验证
嵌套交叉验证用于同时进行模型评估和超参数调优,避免在调参过程中引入评估偏差。
其结构包含内层交叉验证用于超参数选择,外层交叉验证用于模型性能评估。
嵌套交叉验证的工作流程
[*]外层交叉验证
[*]用途:用于评估模型的泛化能力。
[*]过程:将数据划分为 K 个折,依次将每个折作为验证集,其余折作为训练集。
[*]结果:每个折计算一个性能指标(如准确率、均方误差等),最终对 K 个性能指标求平均值,作为模型的总体性能。
[*]内层交叉验证
[*]用途:用于超参数调优。
[*]过程:在外层训练集的基础上再次划分为 M 个折,依次将每个折作为验证集,其余折作为训练集。
[*]结果:对所有超参数组合进行测试,选择在内层验证集上性能最优的超参数。
步骤
假设使用 K 折外层交叉验证和 M 折内层交叉验证。
1.将数据划分为 K 个外层折。
2.在第 i 个外层折中
[*]将外层训练集划分为 M 个内层折。
[*]在每个内层折上,调整模型超参数,选择最佳参数组合。
[*]将第 i 折作为验证集,其他 K-1 折作为外层训练集。
[*]对外层训练集进行内层交叉验证
[*]用内层交叉验证得到的最佳参数,在外层训练集上训练模型。
[*]在外层验证集上评估模型性能。
3.重复 K 次外层交叉验证。
4.对 K 次外层验证集的性能结果求平均,得到模型的最终评估指标。
适用场景
需要同时进行模型选择、超参数调优和性能评估的复杂任务。
from sklearn.model_selection import KFold, GridSearchCV, cross_val_scorefrom sklearn.datasets import make_classificationfrom sklearn.svm import SVC# 创建示例数据X, y = make_classification(n_samples=500, n_features=20, random_state=42)# 定义超参数搜索范围param_grid = { 'C': , 'kernel': ['linear', 'rbf']}# 外层交叉验证 (用于评估模型性能)outer_cv = KFold(n_splits=5, shuffle=True, random_state=42)# 初始化模型和内层 Grid Searchmodel = SVC()inner_cv = KFold(n_splits=3, shuffle=True, random_state=42)grid_search = GridSearchCV(estimator=model, param_grid=param_grid, cv=inner_cv)# 嵌套交叉验证nested_scores = cross_val_score(grid_search, X, y, cv=outer_cv)print("Nested Cross-Validation Scores:", nested_scores)print("Mean Nested CV Accuracy:", nested_scores.mean())
[*]1.
[*]2.
[*]3.
[*]4.
[*]5.
[*]6.
[*]7.
[*]8.
[*]9.
[*]10.
[*]11.
[*]12.
[*]13.
[*]14.
[*]15.
[*]16.
[*]17.
[*]18.
[*]19.
[*]20.
[*]21.
[*]22.
[*]23.
[*]24.
[*]25.
[*]26.
交叉验证的优缺点
优点
[*]提供更稳定和可靠的性能评估,减少因数据划分带来的偏差。
[*]有效利用有限的数据,特别适用于小数据集。
[*]可以用于模型选择、超参数调优和特征选择,提升模型性能。
缺点
[*]计算成本较高,尤其是数据量大或 K 值较大时。
[*]可能对模型的训练时间要求较高,不适用于实时或大规模数据场景。
[*]不同的交叉验证方法适用的场景不同,选择不当可能影响评估结果的有效性。
页:
[1]