Press "Enter" to skip to content

在交叉验证的帮助下,对你的机器学习模型要保持自信

交叉验证是一种常用的工具,用于检查您的机器学习模型是否足够可靠,能够在新数据上工作。本文将讨论交叉验证,从为什么需要它到如何在您的数据上执行它。

Photo by Diane Picchiottino on Unsplash

过拟合

在训练数据上评估训练好的机器学习模型是 fundamentally wrong 的。如果这样做,模型将只返回它在训练过程中学习到的值。这种评估总是会给出100%的准确率,无法提供关于训练好的模型在新数据上表现如何的任何见解。这种情况下,模型在训练数据上具有高准确率,但在新数据上表现非常差,被称为过拟合。

将数据分为训练数据和测试数据

通常,数据会被分成两部分来解决过拟合问题,并了解训练模型的实际准确性。这两个分割部分被称为训练数据和测试数据。测试数据的大小较小,约占原始数据的10%-20%。

这里的思路是在训练数据上训练数据,并在测试数据上评估训练好的模型。

但是,即使采用这种方法,过拟合的可能性仍然存在。以线性支持向量机算法为例。支持向量机算法有一个参数 ‘C’,用于正则化(即增加或减少模型的约束)。可以调整 ‘C’ 的值以在测试数据上获得训练模型的高准确率。然而,这可能会导致过拟合问题。这样的模型在实际部署后可能表现不佳,因为它已经被调整为在实验阶段的测试数据上实现高性能,而不是真正提高准确性。

为了更好地处理过拟合问题,我们可以将数据分为三个部分,即训练数据、验证数据和测试数据。

将数据分为训练、验证和测试数据

将数据分为三个部分可以防止我们在实验阶段调整模型以获得高准确率。

训练数据将是分割的最大部分(约占原始数据的80%)。验证数据和测试数据将各占原始数据的10%。请注意,这些百分比仅供参考,如果需要,可以进行更改。

机器学习模型将在训练数据上进行训练。使用验证数据对训练好的模型进行评估。最后,使用测试数据进行预测,以检查训练好的模型在实时环境中的表现如何。

即使尝试调整模型以在验证数据上获得高准确率,我们可以通过其在测试数据上的表现来判断训练好的模型是否可靠。

即使这种方法也不是没有缺点。

通过将数据分为三个部分,我们减少了本来可以用于训练的数据量。通过分割数据,我们可能会损失20%的数据。

这种方法的另一个缺点是模型的准确性将根据分割的方式而有所不同。可能有一种分割方式会给出很高的准确率,而另一种则会给出较低的准确率。

交叉验证方法用于在一定程度上解决这两个缺点。

交叉验证

在交叉验证中,仍然需要有测试数据,但不需要验证数据。

首先,我们将原始数据分为训练数据和测试数据。然后,按以下方式在训练数据上进行训练模型:

  1. 将训练数据分成 ‘n’ 个相等的部分。让我们将每个部分从第一个部分到第n个部分命名。
  2. 模型在每个可能的 ‘n-1’ 部分组合上进行训练。我们将得到 n 个这样的组合。
  3. 对于每个(n-1)部分的组合,使用剩余的部分来评估训练好的模型。

让我们通过一个例子来更清楚地理解这个。

Scikit-Learn文档中的图像

假设我们将训练数据分成5个部分。现在,我们将找出所有可能的4个分割的组合。这些组合在上面的图表中以绿色显示。并且上面的图表中蓝色表示每个四个分割组合中最后剩余的分割。

对于分割1,模型在组合(Fold2,Fold3,Fold4,Fold5)上进行训练。训练后,模型会在Fold1上进行评估。

对于分割2,模型在组合(Fold1,Fold3,Fold4,Fold5)上进行训练。训练后,模型会在Fold2上进行评估。

对于分割3,模型在组合(Fold1,Fold2,Fold4,Fold5)上进行训练。训练后,模型会在Fold3上进行评估。

对于分割4,模型在组合(Fold1,Fold2,Fold3,Fold5)上进行训练。训练后,模型会在Fold4上进行评估。

对于分割5,模型在组合(Fold1,Fold2,Fold3,Fold4)上进行训练。训练后,模型会在Fold5上进行评估。

最后,我们对所有分割的准确率取平均值,得到最终的准确率。这个平均准确率将是我们的验证性能。由于我们可以得到每个分割的准确率,我们还可以得到这些准确率的标准差。

然后,我们可以使用测试数据来检查在交叉验证中使用的参数训练的模型的性能。我们称之为准确性测试性能。

如果模型的验证性能和测试性能都很好且可比较,那么我们可以认为我们的模型可靠地用于实时使用。

使用scikit-learn的cross_val_score方法在数据上进行交叉验证

让我们使用鸢尾花数据集进行演示。

## 导入所需的库import warningswarnings.filterwarnings('ignore')import numpy as npimport pandas as pdfrom sklearn.datasets import load_irisfrom sklearn.model_selection import train_test_split, cross_val_score, cross_val_predictfrom sklearn.ensemble import RandomForestClassifier## 执行加载数据data = load_iris()df = pd.DataFrame()df[data.feature_names] = data.datadf['target'] = data.target## 将数据分为独立特征和依赖特征X, y = df.drop('target', axis=1), df['target']## 将数据分为训练数据和测试数据X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=123)## 使用交叉验证评估随机森林分类器模型rfc = RandomForestClassifier(max_depth=3)cross_validation_score = cross_val_score(rfc, X_train.values, y_train.values, cv=5, scoring = 'accuracy')print(f"随机森林分类器的交叉验证得分为 {round(cross_validation_score.mean(), 2)} +/- {round(cross_validation_score.std(),2)}.")

在交叉验证的帮助下,对你的机器学习模型要保持自信 四海 第3张

这里,’cv’的值是一个整数。我们可以使用交叉验证迭代器(如KFold和StratifiedKFold)为’cv’参数提供值。

## 使用KFold交叉验证迭代器from sklearn.model_selection import KFoldrfc = RandomForestClassifier(max_depth=3)kf = KFold(n_splits=5)cross_validation_score = cross_val_score(rfc, X_train, y_train, cv=kf, scoring = 'accuracy')print(f"随机森林分类器的交叉验证得分为 {round(cross_validation_score.mean(), 2)} +/- {round(cross_validation_score.std(),2)}.")

在交叉验证的帮助下,对你的机器学习模型要保持自信 四海 第4张

## 使用StratifiedKFold交叉验证迭代器from sklearn.model_selection import StratifiedKFoldrfc = RandomForestClassifier(max_depth=3)skf = StratifiedKFold(n_splits=5)cross_validation_score = cross_val_score(rfc, X_train, y_train, cv=skf, scoring = 'accuracy')print(f"随机森林分类器的交叉验证得分为 {round(cross_validation_score.mean(), 2)} +/- {round(cross_validation_score.std(),2)}.")

在交叉验证的帮助下,对你的机器学习模型要保持自信 四海 第5张

当我们使用StratifiedKFold迭代器时,根据目标类将数据按相等比例分成训练数据和测试数据。

我们甚至可以在执行交叉验证时使用训练的模型进行预测。

## 使用交叉验证进行预测
from sklearn.model_selection import cross_val_predict
rfc = RandomForestClassifier(max_depth=3)
cv_predictions = cross_val_predict(rfc, X, y, cv=5)
print(f"测试数据的预测结果为: {cv_predictions} (形状: {cv_predictions.shape})")

在交叉验证的帮助下,对你的机器学习模型要保持自信 四海 第6张

使用scikit-learn管道进行交叉验证

在对数据进行训练之前,我们将对数据进行一个预处理步骤。让我们创建一个管道,然后找出交叉验证得分。

from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
pipe = Pipeline([
    ('standardization', StandardScaler()),
    ('model', RandomForestClassifier(max_depth=3))
])
cross_validation_score = cross_val_score(pipe, X_train, y_train, cv=5, scoring = 'accuracy')
print(f"随机森林分类器的交叉验证得分为 {round(cross_validation_score.mean(), 2)} +/- {round(cross_validation_score.std(),2)}.")

希望您喜欢这篇文章。如果对此文章有任何想法,请告诉我。非常感谢您的建设性反馈。欢迎在LinkedIn上与我联系。祝您有美好的一天!

Leave a Reply

Your email address will not be published. Required fields are marked *