在机器学习中,常见有的交叉验证方法有留出法(Holdout cross validation)和k 折交叉验证(k-fold cross validation)等,除此之外还有留一法(Leave-One-Out,LOO)、留P法(Leave-P-Out,LPO)等,抽时间做了一些简单的整理。
留出法(Holdout cross validation)
留出法是将原始数据随机分为两个互斥的集合,一个作为训练集,另一个作为测试集。在对训练集进行训练后,用测试集来评估模型的性能。
优点:
- 简单易用,计算量较小。
- 对于大规模数据集,可以快速构建并验证模型。
缺点:
- 训练集和测试集的划分可能不够随机或不够充分,导致结果偏差。
- 只进行一次划分,对于数据量较小时可能无法保证模型稳定性。
- 数据集划分后会浪费部分数据,尤其是当数据集非常小的时候。
有些场景下,留出法还会额外增加一个验证集,具体的功能划分为:
- 训练集:训练模型
- 验证集:调参
- 测试集:评估模型的泛化能力
Scikit-Learn中的数据集拆分train_test_split()方法可以用于留出法。由于先前已经介绍过这里就不再做重复介绍了。
k 折交叉验证(k-fold cross validation)
k折交叉验证首先将原始数据随机分成k个互斥的子集,然后利用其中的k-1个子集作为训练集,剩下的1个子集作为验证集。对于这k种划分情况,分别进行k次训练和测试,最终返回平均测试结果。
优点:
- 数据集的每个子集都有机会作为验证集和训练集,增加了模型的稳定性和精度。
- 能够更好地利用数据,相对于留出法和留一法更加可靠。
缺点:
- 计算量相对于留出法和留一法略大。
- 在某些特殊情况(如数据分布不均衡、数据中存在噪声等)下,结果可能不太可靠。
Scikit-learn中的k 折交叉验证
KFold、cross_val_score和cross_validate都是Scikit-learn中用于K折交叉验证的工具,它们的主要区别在于使用方式、返回结果和功能。
- 使用方式:
- KFold是一个交叉验证器,用于生成训练/测试集的索引,让我们可以采用自己的算法进行交叉验证。KFold提供了比较灵活的交叉验证功能,可以通过设置参数来控制分割数据集的方式,并可以将其与任何Scikit-learn估计器结合使用。
- cross_val_score是一种更为高级的接口,它封装了交叉验证中重复和平均化得分的过程,同时也可以和任何Scikit-learn估计器结合使用。因此,我们可以非常方便地进行模型评估、选择和调参。
- cross_validate相对于cross_val_score更加灵活,可以支持多种评价指标,包括准确率、F1值、精确率、召回率等,并且可以通过设置return_estimator参数来返回评估过程中生成的全部模型实例,方便进一步分析和调整模型。
- 返回结果:
- KFold只返回交叉验证的划分结果,不进行评估得分。
- cross_val_score函数仅返回交叉验证的得分。cross_validate函数除了交叉验证得分外,还可返回每个测试集上的训练时间和预测时间等信息,这对于模型评估和性能分析更加有帮助。
- 功能:
- KFold提供了比较灵活的交叉验证功能,可以通过设置参数来控制分割数据集的方式,并可以将其与任何Scikit-learn估计器结合使用。
- cross_val_score函数相对于KFold更为简单,只需传入分类器、特征矩阵X、标签y、交叉验证折数cv等参数即可。而cross_validate的使用方式则多了一些参数,如待评估的指标 scoring、是否返回拟合时间 return_train_score 等。
- cross_validate相较于cross_val_score函数更为灵活,可以支持多种评价指标,包括准确率、F1值、精确率、召回率等,并且可以通过设置return_estimator参数来返回评估过程中生成的全部模型实例,方便进一步分析和调整模型。
总之,当我们需要获取更全面的交叉验证信息、支持多种评价指标或返回全部生成的模型实例时,应该选择使用cross_validate函数;而当我们只需要获得交叉验证得分时,cross_val_score则更为简便。KFold则更适用于用户定义交叉验证方法的情况。
下面是KFold、cross_val_score和cross_validate的使用示例:
KFold的使用
from sklearn.datasets import load_iris from sklearn.model_selection import KFold from sklearn.linear_model import LogisticRegression # 加载鸢尾花数据集 iris = load_iris() X, y = iris.data, iris.target # 定义5折交叉验证器 kf = KFold(n_splits=5, shuffle=True, random_state=42) # 创建逻辑回归模型 lr = LogisticRegression() # 对于每个训练集和测试集进行训练和评估 for train_index, test_index in kf.split(X): X_train, X_test = X[train_index], X[test_index] y_train, y_test = y[train_index], y[test_index] # 训练模型 lr.fit(X_train, y_train) # 评估模型 score = lr.score(X_test, y_test) print("Accuracy:", score)
cross_val_score的使用
from sklearn.datasets import load_iris from sklearn.model_selection import cross_val_score from sklearn.linear_model import LogisticRegression # 加载鸢尾花数据集 iris = load_iris() X, y = iris.data, iris.target # 创建逻辑回归模型 lr = LogisticRegression() # 进行5折交叉验证 scores = cross_val_score(lr, X, y, cv=5, scoring="accuracy") # 输出所有测试集得分的平均值和标准差 print("Accuracy: %0.2f (+/- %0.2f)" % (scores.mean(), scores.std() * 2))
cross_validate的使用
rom sklearn.datasets import load_iris from sklearn.model_selection import cross_validate from sklearn.linear_model import LogisticRegression # 加载鸢尾花数据集 iris = load_iris() X, y = iris.data, iris.target # 创建逻辑回归模型 lr = LogisticRegression() # 进行5折交叉验证,计算准确率和训练时间 scoring = ["accuracy", "neg_mean_squared_error"] results = cross_validate(lr, X, y, cv=5, scoring=scoring, return_train_score=True) # 输出所有测试集得分的平均值和标准差 print("Test accuracy: %0.2f (+/- %0.2f)" % (results["test_accuracy"].mean(), results["test_accuracy"].std() * 2)) # 输出所有训练集得分的平均值和标准差 print("Train accuracy: %0.2f (+/- %0.2f)" % (results["train_accuracy"].mean(), results["train_accuracy"].std() * 2)) # 输出拟合时间和评估时间的平均值和标准差 print("Fit time: %0.2f (+/- %0.2f)" % (results["fit_time"].mean(), results["fit_time"].std() * 2)) print("Score time: %0.2f (+/- %0.2f)" % (results["score_time"].mean(), results["score_time"].std() * 2))
在上述代码中,我们首先加载了鸢尾花数据集,然后分别使用KFold、cross_val_score和cross_validate对逻辑回归模型进行了5折交叉验证。其中KFold提供了更灵活的交叉验证功能,而cross_val_score和cross_validate则提供了更为简便和全面的评估功能。
GroupKFold、RepeatedKFold、StratifiedKFold和RepeatedStratifiedKFold
GroupKFold
GroupKFold是一种交叉验证的策略,它将数据集按照分组信息进行划分,保证同一组中的样本要么全部在训练集中,要么全部在测试集中。
具体来说,GroupKFold会将数据集分为K份,其中每份保持同一组中的样本比例相同。然后,依次选取其中一份作为测试集,其余的K-1份作为训练集,进行模型训练和测试。这个过程会重复K次,每次选取不同的测试集和训练集,最终得到K个模型性能评估结果的平均值。
GroupKFold的主要参数包括:
- n_splits:表示将数据集拆分成几份,默认为5。
GroupKFold的优点是能够确保同一组中的样本要么全部在训练集中,要么全部在测试集中,从而更好地反映模型的实际表现。缺点是对于某些数据集和模型,可能需要更多的训练时间和计算资源。
下面是一个使用GroupKFold进行交叉验证的示例代码:
from sklearn.datasets import make_classification from sklearn.model_selection import GroupKFold from sklearn.linear_model import LogisticRegression from sklearn.metrics import accuracy_score # 生成分类数据集和分组信息 X, y = make_classification(n_samples=1000, n_features=10, random_state=42) groups = [i % 3 for i in range(len(X))] # 定义GroupKFold对象 gkf = GroupKFold(n_splits=3) # 定义模型 model = LogisticRegression() # 用GroupKFold进行交叉验证 scores = [] for train_index, test_index in gkf.split(X, y, groups): X_train, X_test = X[train_index], X[test_index] y_train, y_test = y[train_index], y[test_index] model.fit(X_train, y_train) y_pred = model.predict(X_test) score = accuracy_score(y_test, y_pred) scores.append(score) # 输出结果 print("Accuracy: {:.3f} (+/- {:.3f})".format(np.mean(scores), np.std(scores)))
在这个例子中,我们首先生成了一个分类数据集和分组信息,然后定义了一个GroupKFold对象,将数据集拆分为3份,保持同一组中的样本比例相同。接着定义了一个LogisticRegression模型,并用GroupKFold进行交叉验证,最后输出了模型的平均准确率和标准差。
RepeatedKFold
RepeatedKFold是一种交叉验证的策略,它将数据集随机拆分为训练集和测试集,可以用于评估模型的性能和选择最优参数。与KFold不同的是,RepeatedKFold会重复运行K次,每次生成不同的随机拆分结果。
具体来说,RepeatedKFold会将数据集分为K份,然后依次选取其中一份作为测试集,其余的K-1份作为训练集,进行模型训练和测试。这个过程会重复R次,每次选取不同的随机拆分结果,最终得到R*K个模型性能评估结果。
RepeatedKFold的主要参数包括:
- n_splits:表示将数据集拆分成几份,默认为5。
- n_repeats:表示重复运行几次交叉验证,默认为10。
RepeatedKFold的优点是能够生成多个随机拆分结果,从而减小误差和提高可靠性。缺点是由于每次随机拆分都需要重新生成,因此计算代价较大,适合数据量较小的场景。
下面是一个使用RepeatedKFold进行交叉验证的示例代码:
from sklearn.datasets import load_iris from sklearn.model_selection import RepeatedKFold from sklearn.tree import DecisionTreeClassifier from sklearn.metrics import accuracy_score # 加载鸢尾花数据集 X, y = load_iris(return_X_y=True) # 定义RepeatedKFold对象 rkf = RepeatedKFold(n_splits=5, n_repeats=3, random_state=42) # 定义模型 model = DecisionTreeClassifier() # 用RepeatedKFold进行交叉验证 scores = [] for train_index, test_index in rkf.split(X): X_train, X_test = X[train_index], X[test_index] y_train, y_test = y[train_index], y[test_index] model.fit(X_train, y_train) y_pred = model.predict(X_test) score = accuracy_score(y_test, y_pred) scores.append(score) # 输出结果 print("Accuracy: {:.3f} (+/- {:.3f})".format(np.mean(scores), np.std(scores)))
在这个例子中,我们首先加载了鸢尾花数据集,然后定义了一个RepeatedKFold对象,将数据集拆分为5份,重复运行3次。接着定义了一个DecisionTreeClassifier模型,并用RepeatedKFold进行交叉验证,最后输出了模型的平均准确率和标准差。
StratifiedKFold
StratifiedKFold是一种交叉验证的策略,它将数据集按照类别信息进行分层划分,可以确保每个类别在训练集和测试集中的比例相同。
具体来说,StratifiedKFold会将数据集分为K份,其中每份保持不同类别的样本比例相同。然后,依次选取其中一份作为测试集,其余的K-1份作为训练集,进行模型训练和测试。这个过程会重复K次,每次选取不同的测试集和训练集,最终得到K个模型性能评估结果的平均值。
StratifiedKFold的主要参数包括:
- n_splits:表示将数据集拆分成几份,默认为5。
StratifiedKFold的优点是能够确保每个类别在训练集和测试集中的比例相同,从而更好地反映模型的实际表现。缺点是对于某些数据集和模型,可能需要更多的训练时间和计算资源。
下面是一个使用StratifiedKFold进行交叉验证的示例代码:
from sklearn.datasets import load_iris from sklearn.model_selection import StratifiedKFold from sklearn.tree import DecisionTreeClassifier from sklearn.metrics import accuracy_score # 加载鸢尾花数据集 X, y = load_iris(return_X_y=True) # 定义StratifiedKFold对象 skf = StratifiedKFold(n_splits=5) # 定义模型 model = DecisionTreeClassifier() # 用StratifiedKFold进行交叉验证 scores = [] for train_index, test_index in skf.split(X, y): X_train, X_test = X[train_index], X[test_index] y_train, y_test = y[train_index], y[test_index] model.fit(X_train, y_train) y_pred = model.predict(X_test) score = accuracy_score(y_test, y_pred) scores.append(score) # 输出结果 print("Accuracy: {:.3f} (+/- {:.3f})".format(np.mean(scores), np.std(scores)))
在这个例子中,我们首先加载了鸢尾花数据集,然后定义了一个StratifiedKFold对象,将数据集拆分为5份,保持不同类别的样本比例相同。接着定义了一个DecisionTreeClassifier模型,并用StratifiedKFold进行交叉验证,最后输出了模型的平均准确率和标准差。
RepeatedStratifiedKFold
RepeatedStratifiedKFold是一种交叉验证的策略,它将数据集按照类别信息进行分层划分,可以确保每个类别在训练集和测试集中的比例相同。与StratifiedKFold不同的是,RepeatedStratifiedKFold会重复运行K次,每次生成不同的随机拆分结果。
具体来说,RepeatedStratifiedKFold会将数据集分为K份,其中每份保持不同类别的样本比例相同。然后,依次选取其中一份作为测试集,其余的K-1份作为训练集,进行模型训练和测试。这个过程会重复R次,每次选取不同的随机拆分结果,最终得到R*K个模型性能评估结果。
RepeatedStratifiedKFold的主要参数包括:
- n_splits:表示将数据集拆分成几份,默认为5。
- n_repeats:表示重复运行几次交叉验证,默认为10。
RepeatedStratifiedKFold的优点是能够确保每个类别在训练集和测试集中的比例相同,从而更好地反映模型的实际表现。缺点是由于每次随机拆分都需要重新生成,因此计算代价较大,适合数据量较小的场景。
下面是一个使用RepeatedStratifiedKFold进行交叉验证的示例代码:
from sklearn.datasets import load_digits from sklearn.model_selection import RepeatedStratifiedKFold from sklearn.linear_model import LogisticRegression from sklearn.metrics import accuracy_score # 加载手写数字数据集 X, y = load_digits(return_X_y=True) # 定义RepeatedStratifiedKFold对象 rskf = RepeatedStratifiedKFold(n_splits=5, n_repeats=3, random_state=42) # 定义模型 model = LogisticRegression() # 用RepeatedStratifiedKFold进行交叉验证 scores = [] for train_index, test_index in rskf.split(X, y): X_train, X_test = X[train_index], X[test_index] y_train, y_test = y[train_index], y[test_index] model.fit(X_train, y_train) y_pred = model.predict(X_test) score = accuracy_score(y_test, y_pred) scores.append(score) # 输出结果 print("Accuracy: {:.3f} (+/- {:.3f})".format(np.mean(scores), np.std(scores)))
在这个例子中,我们首先加载了手写数字数据集,然后定义了一个RepeatedStratifiedKFold对象,将数据集拆分为5份,重复运行3次。接着定义了一个LogisticRegression模型,并用RepeatedStratifiedKFold进行交叉验证,最后输出了模型的平均准确率和标准差。
留一法(Leave one out cross validation)
留一法是k折交叉验证的特例。在留一法中,每个样本依次被作为测试集,其余所有样本作为训练集,进行模型训练和测试。
优点:
- 将原始数据集的全部信息都用于训练模型,从而得到最准确的模型评估结果。
- 对于小数据集比较适用。
缺点:
- 运算开销较大,需要训练n个模型,其中n为数据集大小。
- 对于大数据集,由于需要进行大量的重复实验,留一法计算成本很高。
Scikit-learn中可以使用LeaveOneOut类来进行留一法交叉验证(Leave-One-Out Cross Validation)。留一法交叉验证是将每个样本都作为测试数据,其余样本作为训练数据,这样得到n个分类器的评估结果,最后计算平均值。对于小规模数据集(如当样本数量小于20时),留一法交叉验证是一种很好的验证方法。
下面是一个使用留一法交叉验证进行模型评估的范例:
from sklearn.datasets import load_iris from sklearn.model_selection import LeaveOneOut from sklearn.linear_model import LogisticRegression # 加载鸢尾花数据集 iris = load_iris() X, y = iris.data, iris.target # 创建逻辑回归模型 lr = LogisticRegression() # 定义留一法交叉验证器 loo = LeaveOneOut() # 初始化正确分类数和总样本数 correct = 0 total = 0 # 对于每个训练集和测试集进行训练和评估 for train_index, test_index in loo.split(X): X_train, X_test = X[train_index], X[test_index] y_train, y_test = y[train_index], y[test_index] # 训练模型 lr.fit(X_train, y_train) # 预测测试集并计算准确率 y_pred = lr.predict(X_test) if y_pred == y_test: correct += 1 total += 1 # 输出模型在所有测试集上的准确率 print("Accuracy:", correct / total)
在上述代码中,我们首先加载了鸢尾花数据集,然后创建了一个逻辑回归模型,并定义了一个留一法交叉验证器。接着,我们对于每个训练集和测试集进行训练和评估,并记录了模型在所有测试集上的正确分类数和总样本数。最后,我们输出了模型在所有测试集上的准确率。
留P法(Leave-P-Out,LPO)交叉验证
留P法交叉验证(Leave-P-Out Cross Validation,简称LPO)是一种K折交叉验证的特例。在LPO中,每次将P个样本作为测试集,其余的样本作为训练集,重复这个过程直到所有的组合都被尝试一遍,即共有nCp种情况。
相对于其他的交叉验证方法,LPO更加严格和耗时,但由于考虑了全部的nCp种情况,因此能给出非常准确的模型评估结果,而且可以充分利用小数据集中的所有样本。因此,在样本数量较少或使用机器学习算法比较困难的情况下,LPO可以作为一种有效的交叉验证策略。
Scikit-learn中可以使用LeavePOut类来实现LPO交叉验证。下面是一个使用留P法交叉验证进行模型评估的示例:
from sklearn.datasets import load_iris from sklearn.model_selection import LeavePOut from sklearn.linear_model import LogisticRegression # 加载鸢尾花数据集 iris = load_iris() X, y = iris.data, iris.target # 创建逻辑回归模型 lr = LogisticRegression() # 定义留P法交叉验证器 lpo = LeavePOut(p=2) # 初始化正确分类数和总样本数 correct = 0 total = 0 # 对于每个训练集和测试集进行训练和评估 for train_index, test_index in lpo.split(X): X_train, X_test = X[train_index], X[test_index] y_train, y_test = y[train_index], y[test_index] # 训练模型 lr.fit(X_train, y_train) # 预测测试集并计算准确率 y_pred = lr.predict(X_test) if y_pred == y_test: correct += 1 total += 1 # 输出模型在所有测试集上的准确率 print("Accuracy:", correct / total)
在上述代码中,我们首先加载了鸢尾花数据集,然后创建了一个逻辑回归模型,并定义了一个留P法交叉验证器。接着,我们对于每个训练集和测试集进行训练和评估,并记录了模型在所有测试集上的正确分类数和总样本数。最后,我们输出了模型在所有测试集上的准确率。
总的来说,留P法交叉验证是一种严格和耗时的验证方法,但对于小规模数据集来说是一种很好的验证方法。在样本数量较少或机器学习算法比较困难的情况下,可以使用LPO来进行模型评估。
随机排列交叉验证ShuffleSplit
ShuffleSplit是一种交叉验证的策略,它将数据随机拆分为训练集和测试集,可以用于评估模型的性能和选择最优参数。
具体来说,ShuffleSplit会对整个数据集进行多次随机划分,每次划分都会按照指定比例生成训练集和测试集。这些划分是互相独立的,可以用来对同一个模型进行多次评估,从而减小误差和提高可靠性。
ShuffleSplit的主要参数包括:
- n_splits:表示拆分成几份,默认为10。
- test_size:表示每次拆分中测试集的大小,可以是一个浮点数(表示占总数据量的比例)或整数(表示具体数量),默认为1。
- train_size:表示每次拆分中训练集的大小,如果不设置,则默认为1-test_size。
- random_state:表示随机数种子,用于确保每次拆分结果的可重复性。
ShuffleSplit的优点是可以利用全部数据对模型进行训练和测试,并且每次划分的结果都是随机的,能够更好地反映模型的实际表现。缺点是由于每次随机划分都需要重新生成,因此计算代价较大,适合数据量较小的场景。
下面是一个使用ShuffleSplit进行交叉验证的示例代码:
from sklearn.datasets import load_digits from sklearn.model_selection import ShuffleSplit from sklearn.linear_model import LogisticRegression from sklearn.metrics import accuracy_score # 加载手写数字数据集 X, y = load_digits(return_X_y=True) # 定义ShuffleSplit对象 ss = ShuffleSplit(n_splits=5, test_size=0.2, random_state=42) # 定义模型 model = LogisticRegression() # 用ShuffleSplit进行交叉验证 scores = [] for train_index, test_index in ss.split(X): X_train, X_test = X[train_index], X[test_index] y_train, y_test = y[train_index], y[test_index] model.fit(X_train, y_train) y_pred = model.predict(X_test) score = accuracy_score(y_test, y_pred) scores.append(score) # 输出结果 print("Accuracy: {:.3f} (+/- {:.3f})".format(np.mean(scores), np.std(scores)))
在这个例子中,我们首先加载了手写数字数据集,然后定义了一个ShuffleSplit对象,将数据集拆分为5份,每次测试集占比20%。接着定义了一个LogisticRegression模型,并用ShuffleSplit进行交叉验证,最后输出了模型的平均准确率和标准差。
需要注意的是,由于ShuffleSplit划分结果是随机的,因此每次运行代码得到的结果可能会略有不同。
分层K折交叉验证StratifiedKFold
分层K折交叉验证(StratifiedKFold)是一种交叉验证的策略,它可以确保每个类别在训练集和测试集中的比例相同。这种交叉验证方法适用于有不同类别或标签的分类问题。
具体来说,StratifiedKFold会将数据集分为K份,其中每份保持原始数据集中各类别样本的比例。然后,依次选取其中一份作为测试集,其余的K-1份作为训练集,进行模型训练和测试。这个过程会重复K次,每次选取不同的测试集和训练集,最终得到K个模型性能评估结果的平均值。
StratifiedKFold的主要参数包括:
- n_splits:表示将数据集拆分成几份,默认为5。
- shuffle:表示是否对数据集进行随机打乱,默认为True。
- random_state:表示随机数种子,用于确保每次拆分结果的可重复性。
StratifiedKFold的优点是能够确保不同类别的样本在训练集和测试集中的比例相同,从而更好地反映模型的实际表现。缺点是对于某些数据集和模型,可能需要更多的训练时间和计算资源。
下面是一个使用StratifiedKFold进行交叉验证的示例代码:
from sklearn.datasets import load_digits from sklearn.model_selection import StratifiedKFold from sklearn.linear_model import LogisticRegression from sklearn.metrics import accuracy_score # 加载手写数字数据集 X, y = load_digits(return_X_y=True) # 定义StratifiedKFold对象 skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42) # 定义模型 model = LogisticRegression() # 用StratifiedKFold进行交叉验证 scores = [] for train_index, test_index in skf.split(X, y): X_train, X_test = X[train_index], X[test_index] y_train, y_test = y[train_index], y[test_index] model.fit(X_train, y_train) y_pred = model.predict(X_test) score = accuracy_score(y_test, y_pred) scores.append(score) # 输出结果 print("Accuracy: {:.3f} (+/- {:.3f})".format(np.mean(scores), np.std(scores)))
在这个例子中,我们首先加载了手写数字数据集,然后定义了一个StratifiedKFold对象,将数据集拆分为5份,并对每份进行随机打乱。接着定义了一个LogisticRegression模型,并用StratifiedKFold进行交叉验证,最后输出了模型的平均准确率和标准差。
分层随机排列交叉验证StratifiedShuffleSplit
分层随机排列交叉验证(StratifiedShuffleSplit)是一种交叉验证的策略,它将数据集随机拆分为训练集和测试集,同时保持每个类别在训练集和测试集中的比例相同。
具体来说,StratifiedShuffleSplit会对整个数据集进行多次随机划分,每次划分都会按照指定比例生成训练集和测试集,并且保持每个类别在训练集和测试集中的比例相同。这些划分是互相独立的,可以用来对同一个模型进行多次评估,从而减小误差和提高可靠性。
StratifiedShuffleSplit的主要参数包括:
- n_splits:表示拆分成几份,默认为10。
- test_size:表示每次拆分中测试集的大小,可以是一个浮点数(表示占总数据量的比例)或整数(表示具体数量),默认为1。
- train_size:表示每次拆分中训练集的大小,如果不设置,则默认为1-test_size。
- random_state:表示随机数种子,用于确保每次拆分结果的可重复性。
StratifiedShuffleSplit的优点是能够确保不同类别的样本在训练集和测试集中的比例相同,从而更好地反映模型的实际表现。缺点是由于每次随机划分都需要重新生成,因此计算代价较大,适合数据量较小的场景。
下面是一个使用StratifiedShuffleSplit进行交叉验证的示例代码:
from sklearn.datasets import load_digits from sklearn.model_selection import StratifiedShuffleSplit from sklearn.linear_model import LogisticRegression from sklearn.metrics import accuracy_score # 加载手写数字数据集 X, y = load_digits(return_X_y=True) # 定义StratifiedShuffleSplit对象 sss = StratifiedShuffleSplit(n_splits=5, test_size=0.2, random_state=42) # 定义模型 model = LogisticRegression() # 用StratifiedShuffleSplit进行交叉验证 scores = [] for train_index, test_index in sss.split(X, y): X_train, X_test = X[train_index], X[test_index] y_train, y_test = y[train_index], y[test_index] model.fit(X_train, y_train) y_pred = model.predict(X_test) score = accuracy_score(y_test, y_pred) scores.append(score) # 输出结果 print("Accuracy: {:.3f} (+/- {:.3f})".format(np.mean(scores), np.std(scores)))
在这个例子中,我们首先加载了手写数字数据集,然后定义了一个StratifiedShuffleSplit对象,将数据集拆分为5份,每次测试集占比20%。接着定义了一个LogisticRegression模型,并用StratifiedShuffleSplit进行交叉验证,最后输出了模型的平均准确率和标准差。
时间序列分割法TimeSeriesSplit
时间序列分割法(TimeSeriesSplit)是一种交叉验证的策略,它将数据集按照时间顺序进行划分,保证训练集和测试集之间不存在时间上的重叠。
具体来说,TimeSeriesSplit会将时间序列数据集划分为K份,其中每份都包含相同数量的连续时间窗口。然后,依次选取其中一份作为测试集,其余的K-1份作为训练集,进行模型训练和测试。这个过程会重复K次,每次选取不同的测试集和训练集,最终得到K个模型性能评估结果的平均值。
TimeSeriesSplit的主要参数包括:
- n_splits:表示将时间序列数据集拆分成几份,默认为5。
- TimeSeriesSplit的优点是能够确保训练集和测试集之间不存在时间上的重叠,从而更好地反映模型在未来的实际表现。缺点是对于某些数据集和模型,可能需要更多的训练时间和计算资源。
下面是一个使用TimeSeriesSplit进行交叉验证的示例代码:
from sklearn.datasets import load_boston from sklearn.model_selection import TimeSeriesSplit from sklearn.linear_model import LinearRegression from sklearn.metrics import mean_squared_error # 加载波士顿房价数据集 X, y = load_boston(return_X_y=True) # 定义TimeSeriesSplit对象 tss = TimeSeriesSplit(n_splits=5) # 定义模型 model = LinearRegression() # 用TimeSeriesSplit进行交叉验证 scores = [] for train_index, test_index in tss.split(X): X_train, X_test = X[train_index], X[test_index] y_train, y_test = y[train_index], y[test_index] model.fit(X_train, y_train) y_pred = model.predict(X_test) score = mean_squared_error(y_test, y_pred) scores.append(score) # 输出结果 print("MSE: {:.3f} (+/- {:.3f})".format(np.mean(scores), np.std(scores)))
在这个例子中,我们首先加载了波士顿房价数据集,然后定义了一个TimeSeriesSplit对象,将数据集划分为5份。接着定义了一个LinearRegression模型,并用TimeSeriesSplit进行交叉验证,最后输出了模型的平均MSE和标准差。
参考链接: