机器学习 - 交叉验证
在此页面上,W3schools.com 与 纽约数据科学学院 合作,为我们的学生提供数字培训内容。
交叉验证
在调整模型时,我们的目标是提高模型在未见过数据上的整体性能。超参数调优可以显著提高在测试集上的性能。然而,对测试集进行参数优化可能会导致信息泄露,从而使模型在未见过的数据上表现更差。为了纠正这一点,我们可以执行交叉验证。
为了更好地理解 CV,我们将对鸢尾花数据集执行不同的方法。首先,让我们加载并分离数据。
来自 sklearn 的数据集
X, y = datasets.load_iris(return_X_y=True)
有许多交叉验证的方法,我们将从 K 折交叉验证开始。
K 折
模型所使用的训练数据被分割成 k 个较小的子集,用于验证模型。然后,模型在 k-1 折的训练集上进行训练。剩余的一折被用作验证集来评估模型。
由于我们将尝试对不同的鸢尾花品种进行分类,我们需要导入一个分类器模型。在本练习中,我们将使用 DecisionTreeClassifier
。我们还需要从 sklearn
导入 CV 模块。
来自 sklearn.tree 导入 DecisionTreeClassifier
from sklearn.model_selection import KFold, cross_val_score
数据加载完毕后,我们现在可以创建一个模型并进行拟合以进行评估。
clf = DecisionTreeClassifier(random_state=42)
现在让我们评估我们的模型,看看它在每一折上的表现如何。
k_folds = KFold(n_splits = 5)
scores = cross_val_score(clf, X, y, cv = k_folds)
通过对所有折的分数取平均值,来了解 CV 的整体表现,这是一种好的实践。
示例
运行 K 折 CV
来自 sklearn 的数据集
来自 sklearn.tree 导入 DecisionTreeClassifier
from sklearn.model_selection import KFold, cross_val_score
X, y = datasets.load_iris(return_X_y=True)
clf = DecisionTreeClassifier(random_state=42)
k_folds = KFold(n_splits = 5)
scores = cross_val_score(clf, X, y, cv = k_folds)
print("Cross Validation Scores: ", scores)
print("Average CV Score: ", scores.mean())
print("Number of CV Scores used in Average: ", len(scores))
运行示例 »
广告
分层 K 折
在类别不平衡的情况下,我们需要一种方法来同时考虑训练集和验证集中的不平衡。为此,我们可以对目标类别进行分层,这意味着每个集合都将具有所有类别的相等比例。
示例
来自 sklearn 的数据集
来自 sklearn.tree 导入 DecisionTreeClassifier
from sklearn.model_selection import StratifiedKFold, cross_val_score
X, y = datasets.load_iris(return_X_y=True)
clf = DecisionTreeClassifier(random_state=42)
sk_folds = StratifiedKFold(n_splits = 5)
scores = cross_val_score(clf, X, y, cv = sk_folds)
print("Cross Validation Scores: ", scores)
print("Average CV Score: ", scores.mean())
print("Number of CV Scores used in Average: ", len(scores))
运行示例 »
虽然折的数量相同,但在确保类别分层后,平均 CV 分数比基本的 K 折有所提高。
留一法 (LOO)
与 K 折交叉验证选择训练数据集中分割的数量不同,LeaveOneOut 使用 1 个观测值进行验证,n-1 个观测值进行训练。这种方法是一种穷举技术。
示例
运行 LOO CV
来自 sklearn 的数据集
来自 sklearn.tree 导入 DecisionTreeClassifier
from sklearn.model_selection import LeaveOneOut, cross_val_score
X, y = datasets.load_iris(return_X_y=True)
clf = DecisionTreeClassifier(random_state=42)
loo = LeaveOneOut()
scores = cross_val_score(clf, X, y, cv = loo)
print("Cross Validation Scores: ", scores)
print("Average CV Score: ", scores.mean())
print("Number of CV Scores used in Average: ", len(scores))
运行示例 »
我们可以看到,执行的交叉验证分数的数量等于数据集中观测值的数量。在这种情况下,鸢尾花数据集中有 150 个观测值。
平均 CV 分数为 94%。
留 P 法 (LPO)
Leave-P-Out 只是 Leave-One-Out 概念的一个细微差别,即我们可以选择 P 的数量来用于我们的验证集。
示例
运行 LPO CV
来自 sklearn 的数据集
来自 sklearn.tree 导入 DecisionTreeClassifier
from sklearn.model_selection import LeavePOut, cross_val_score
X, y = datasets.load_iris(return_X_y=True)
clf = DecisionTreeClassifier(random_state=42)
lpo = LeavePOut(p=2)
scores = cross_val_score(clf, X, y, cv = lpo)
print("Cross Validation Scores: ", scores)
print("Average CV Score: ", scores.mean())
print("Number of CV Scores used in Average: ", len(scores))
运行示例 »
正如我们所见,这是一种穷举方法,即使 P=2,计算出的分数也比 Leave-One-Out 多得多,但它实现了大致相同的平均 CV 分数。
Shuffle Split
与 KFold
不同,ShuffleSplit
会排除一部分数据,这些数据不会用于训练或验证集。为此,我们必须决定训练集和测试集的大小,以及拆分次数。
示例
运行 Shuffle Split CV
来自 sklearn 的数据集
来自 sklearn.tree 导入 DecisionTreeClassifier
from sklearn.model_selection import ShuffleSplit, cross_val_score
X, y = datasets.load_iris(return_X_y=True)
clf = DecisionTreeClassifier(random_state=42)
ss = ShuffleSplit(train_size=0.6, test_size=0.3, n_splits = 5)
scores = cross_val_score(clf, X, y, cv = ss)
print("Cross Validation Scores: ", scores)
print("Average CV Score: ", scores.mean())
print("Number of CV Scores used in Average: ", len(scores))
运行示例 »
结束语
这些只是可以应用于模型的一些 CV 方法。还有许多其他的交叉验证类,大多数模型都有自己的类。请查阅 sklearn 的交叉验证以获取更多 CV 选项。