机器学习 - 交叉验证
在本页,W3schools.com 与 纽约数据科学学院 合作,为我们的学生提供数字培训内容。
交叉验证
在调整模型时,我们的目标是提高模型在未见过的数据上的整体性能。超参数调整可以显著提高测试集上的性能。然而,对测试集进行参数优化可能会导致信息泄露,从而导致模型在未见过的数据上的性能更差。为了纠正这一点,我们可以进行交叉验证。
为了更好地理解 CV,我们将对鸢尾花数据集执行不同的方法。首先让我们加载并分离数据。
from sklearn import datasets
X, y = datasets.load_iris(return_X_y=True)
交叉验证有许多方法,我们将从 k 折交叉验证开始。
K 折交叉验证
用于模型训练的训练数据被分成 k 个较小的子集,用于验证模型。然后在 k-1 个训练集折叠上训练模型。剩余的折叠作为验证集用于评估模型。
由于我们将尝试对不同种类的鸢尾花进行分类,因此我们需要导入一个分类器模型,在本练习中,我们将使用 DecisionTreeClassifier
。我们还需要从 sklearn
导入 CV 模块。
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import KFold, cross_val_score
数据加载完成后,我们可以创建并拟合一个模型进行评估。
clf = DecisionTreeClassifier(random_state=42)
现在让我们评估我们的模型,看看它在每个k折上的表现。
k_folds = KFold(n_splits = 5)
scores = cross_val_score(clf, X, y, cv = k_folds)
将所有折的得分平均起来查看CV的整体表现也是一个好习惯。
示例
运行k折交叉验证
from sklearn import datasets
from sklearn.tree import 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("交叉验证得分: ", scores)
print("平均CV得分: ", scores.mean())
print("用于平均的CV得分数量: ", len(scores))
运行示例 »
广告
分层k折交叉验证
在类不平衡的情况下,我们需要一种方法来解决训练集和验证集中的不平衡问题。为此,我们可以对目标类进行分层,这意味着两组将包含所有类的相等比例。
示例
from sklearn import datasets
from sklearn.tree import 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("交叉验证得分: ", scores)
print("平均CV得分: ", scores.mean())
print("用于平均的CV得分数量: ", len(scores))
运行示例 »
虽然折数相同,但确保分层类后,基本k折的平均CV会增加。
留一法 (LOO)
与在训练数据集中选择拆分数量的k折交叉验证不同,留一法使用1个观察值进行验证,并使用n-1个观察值进行训练。这种方法是一种穷举技术。
示例
运行留一法交叉验证
from sklearn import datasets
from sklearn.tree import 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("交叉验证得分: ", scores)
print("平均CV得分: ", scores.mean())
print("用于平均的CV得分数量: ", len(scores))
运行示例 »
我们可以观察到,执行的交叉验证得分数量等于数据集中观察值的数量。在本例中,虹膜数据集中有150个观察值。
平均CV得分是94%。
留p法 (LPO)
留p法只是留一法的细微差异,我们可以选择验证集中使用的p的数量。
示例
运行留p法交叉验证
from sklearn import datasets
from sklearn.tree import 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("交叉验证得分: ", scores)
print("平均CV得分: ", scores.mean())
print("用于平均的CV得分数量: ", len(scores))
运行示例 »
正如我们所见,这是一种穷举方法,我们计算的得分比留一法要多得多,即使p=2,但它仍然获得了大致相同的平均CV得分。
随机拆分
与KFold
不同,ShuffleSplit
会省略一部分数据,这些数据不会用于训练集或验证集。为此,我们必须决定训练集和测试集的大小,以及拆分数量。
示例
运行随机拆分交叉验证
from sklearn import datasets
from sklearn.tree import 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("交叉验证得分: ", scores)
print("平均CV得分: ", scores.mean())
print("用于平均的CV得分数量: ", len(scores))
运行示例 »
结束说明
这些只是可以应用于模型的几种CV方法。还有很多其他的交叉验证类,大多数模型都有自己的类。查看sklearn的交叉验证以了解更多CV选项。