介绍
在机器学习中,我们通常将数据划分为训练集和测试集来评估模型的性能。然而,这种评估可能很大程度上取决于哪些数据点最终进入训练集,哪些进入测试集。一种更稳健的方法是交叉验证 (CV)。
为什么使用交叉验证?
- 降低过拟合风险: 在多个数据划分上测试模型
- 更好的泛化能力估计: 在未见过的数据上表现更可靠
- 最大化数据利用: 每个样本都用于训练和测试
交叉验证涉及将数据集划分为多个“折 (folds)”,然后多次训练和评估模型,每次使用不同的折进行测试。这能为我们提供模型在未见过数据上性能的更可靠估计。
在本实验 (lab) 中,你将学习如何使用 scikit-learn 强大而便捷的函数,在著名的 Iris 数据集上对分类器执行交叉验证。你将学习使用 cross_val_score 获取性能得分,然后计算其均值和标准差,以更好地理解模型的稳定性和整体准确性。
从 sklearn.model_selection 导入 cross_val_score
在此步骤中,你将开始导入执行交叉验证所需的函数。cross_val_score 函数是 scikit-learn 中用于此目的的主要工具。它简化了数据划分、模型训练以及在多个折上进行评分的过程。
首先,使用 IDE 左侧的文件浏览器打开位于 ~/project 目录下的 main.py 文件。
现在,将 cross_val_score 的导入语句添加到你的 main.py 脚本中。将其放在文件顶部的其他导入语句旁边。
from sklearn.model_selection import cross_val_score
你的 main.py 文件现在应该如下所示:
import numpy as np
from sklearn import datasets
from sklearn.svm import SVC
from sklearn.model_selection import cross_val_score
## Load the iris dataset
iris = datasets.load_iris()
X, y = iris.data, iris.target
## Initialize a Support Vector Classifier (SVC)
## Parameters explained:
## - kernel='linear': Uses a linear kernel for linearly separable data like Iris
## - C=1: Regularization parameter (higher values = less regularization)
## - random_state=42: Ensures reproducible results across runs
clf = SVC(kernel='linear', C=1, random_state=42)
## --- Your code will go below this line ---
你可以运行脚本以确保没有语法错误。在 IDE 中打开一个终端并执行以下命令:
python3 main.py
你应该看不到任何输出,这是预期的,因为我们还没有添加任何产生输出的代码。
使用 sklearn.model_selection 的 n_splits=5 初始化 KFold
虽然 cross_val_score 可以自动处理数据划分,但了解其底层机制是很好的实践。最常见的交叉验证策略是 K-Fold,即将数据集划分为 'k' 个折。模型在 k-1 个折上训练,并在剩余的折上进行测试,这个过程重复 k 次。
KFold 参数:
n_splits=5: 将数据划分为 5 个相等的份(折)shuffle=False(默认): 保持原始数据顺序random_state: 如果shuffle=True,则控制随机化
scikit-learn 中的 KFold 类是一个交叉验证迭代器,它提供用于划分数据的训练/测试索引。虽然我们将在下一步中使用更简单的快捷方式,但理解 KFold 是基础。
让我们导入 KFold 并了解如何初始化它。将以下行添加到你的 main.py 文件中。
首先,在顶部添加导入语句:
from sklearn.model_selection import KFold
然后,你可以初始化它。但是,在本实验 (lab) 中,我们将依赖 cross_val_score 的 cv 参数,这是一种更直接的方法。此步骤的目的是向你介绍 KFold 的概念。为了简单起见并遵循实验 (lab) 的流程,我们不会将 KFold 初始化代码添加到我们的脚本中。我们将在下一步直接使用 cv=5,它内部会使用 K-Fold 策略。这是执行交叉验证最常见和最直接的方式。
让我们继续下一步,在那里我们将实践这个概念。由于此步骤没有添加任何代码,你可以点击“Continue”继续。
使用 cross_val_score(clf, X, y, cv=5) 执行交叉验证
现在是时候执行交叉验证了。我们将使用之前导入的 cross_val_score 函数。此函数接受几个参数:
cross_val_score 参数:
estimator: 要评估的模型(我们的clf分类器)X: 特征数据矩阵y: 目标标签数组cv=5: 交叉验证策略(整数表示 k-fold,或 CV 分割器对象)scoring: 评估指标(默认使用估计器的 score 方法)n_jobs: 要使用的 CPU 核心数(默认值=1,-1 表示所有核心)
通过设置 cv=5,我们告诉 scikit-learn 执行 5 折交叉验证。它将自动将数据划分为 5 个折,然后训练和测试模型 5 次,返回一个包含每次运行得分的数组。
将以下代码添加到你的 main.py 文件末尾,位于注释行下方:
## Perform 5-fold cross-validation
scores = cross_val_score(clf, X, y, cv=5)
## Print the array of scores
print("Scores:", scores)
你的完整的 main.py 文件现在应该如下所示:
import numpy as np
from sklearn import datasets
from sklearn.svm import SVC
from sklearn.model_selection import cross_val_score
## Load the iris dataset
iris = datasets.load_iris()
X, y = iris.data, iris.target
## Initialize a Support Vector Classifier (SVC)
## Parameters explained:
## - kernel='linear': Uses a linear kernel for linearly separable data like Iris
## - C=1: Regularization parameter (higher values = less regularization)
## - random_state=42: Ensures reproducible results across runs
clf = SVC(kernel='linear', C=1, random_state=42)
## --- Your code will go below this line ---
## Perform 5-fold cross-validation
scores = cross_val_score(clf, X, y, cv=5)
## Print the array of scores
print("Scores:", scores)
现在,从你的终端运行脚本:
python3 main.py
你将看到输出显示一个包含 5 个得分的数组,每个得分对应交叉验证的一个折。
Scores: [0.96666667 1. 0.96666667 0.96666667 1. ]
Mean score: 0.9800000000000001
Standard deviation: 0.016329931618554516
你的得分可能因具体的数据划分而略有不同,但应该相似。这个数组让你能够详细了解模型在不同数据子集上的表现。
使用 scores.mean() 计算平均交叉验证得分
拥有一个得分数组是很有信息量的,但为了快速总结模型的性能,我们通常会计算这些得分的平均值。这个单一的数值能让我们对模型的准确性有一个大致的了解。
cross_val_score 函数返回一个 NumPy 数组,该数组带有很多有用的方法,包括 .mean()。我们可以直接在我们的 scores 变量上调用此方法。
将以下行添加到你的 main.py 脚本末尾,以计算并打印平均得分:
## Compute and print the mean of the scores
mean_score = scores.mean()
print("Mean score:", mean_score)
你的 main.py 文件现在应该包含以下代码:
import numpy as np
from sklearn import datasets
from sklearn.svm import SVC
from sklearn.model_selection import cross_val_score
## Load the iris dataset
iris = datasets.load_iris()
X, y = iris.data, iris.target
## Initialize a Support Vector Classifier (SVC)
## Parameters explained:
## - kernel='linear': Uses a linear kernel for linearly separable data like Iris
## - C=1: Regularization parameter (higher values = less regularization)
## - random_state=42: Ensures reproducible results across runs
clf = SVC(kernel='linear', C=1, random_state=42)
## --- Your code will go below this line ---
## Perform 5-fold cross-validation
scores = cross_val_score(clf, X, y, cv=5)
## Print the array of scores
print("Scores:", scores)
## Compute and print the mean of the scores
mean_score = scores.mean()
print("Mean score:", mean_score)
再次执行脚本:
python3 main.py
输出现在将包含 5 个得分的平均值,为你提供一个单一的、有代表性的性能指标。
Scores: [0.96666667 1. 0.96666667 0.96666667 1. ]
Mean score: 0.9800000000000001
使用 scores.std() 计算交叉验证得分的标准差
平均得分告诉我们模型的平均性能,但它并没有告诉我们这种性能有多稳定。得分的标准差为我们提供了这种方差的度量。
解释标准差:
- **低标准差 (< 0.05)**:模型在所有数据子集上的表现一致
- **中等标准差 (0.05-0.15)**:中度变化,在大多数情况下可接受
- **高标准差 (> 0.15)**:性能变化大,可能表明数据问题或模型不稳定
低标准差表明模型在不同数据子集上的性能是稳定的,而高标准差则表明性能变化更大。
与 .mean() 类似,NumPy 数组也有一个 .std() 方法来计算标准差。
将最后一段代码添加到你的 main.py 脚本中,以计算并打印标准差:
## Compute and print the standard deviation of the scores
std_dev = scores.std()
print("Standard deviation:", std_dev)
你的最终 main.py 脚本现已完成,应如下所示:
import numpy as np
from sklearn import datasets
from sklearn.svm import SVC
from sklearn.model_selection import cross_val_score
## Load the iris dataset
iris = datasets.load_iris()
X, y = iris.data, iris.target
## Initialize a Support Vector Classifier (SVC)
## Parameters explained:
## - kernel='linear': Uses a linear kernel for linearly separable data like Iris
## - C=1: Regularization parameter (higher values = less regularization)
## - random_state=42: Ensures reproducible results across runs
clf = SVC(kernel='linear', C=1, random_state=42)
## --- Your code will go below this line ---
## Perform 5-fold cross-validation
scores = cross_val_score(clf, X, y, cv=5)
## Print the array of scores
print("Scores:", scores)
## Compute and print the mean of the scores
mean_score = scores.mean()
print("Mean score:", mean_score)
## Compute and print the standard deviation of the scores
std_dev = scores.std()
print("Standard deviation:", std_dev)
最后一次运行脚本:
python3 main.py
最终输出将显示得分数组、它们的平均值以及它们的标准差,为你提供模型性能的全面评估。
Scores: [0.96666667 1. 0.96666667 0.96666667 1. ]
Mean score: 0.9800000000000001
Standard deviation: 0.016329931618554516
总结
恭喜你完成了本次实验!你已成功学会如何使用 scikit-learn 执行和解释 k-fold 交叉验证。
在本次实验中,你:
- 理解了交叉验证对于稳健模型评估的重要性。
- 使用
cross_val_score函数轻松地对支持向量分类器执行了 5-fold 交叉验证。 - 通过计算和打印交叉验证得分的平均值和标准差来分析结果。
交叉验证的实用技巧:
- 在大多数场景下使用 5-fold 或 10-fold CV
- 对于不平衡数据集,考虑使用分层交叉验证 (stratified CV)
- 对于多个指标,使用
cross_validate而不是cross_val_score - 始终设置
random_state以获得可复现的结果
这项技术是机器学习工作流程的一个基本组成部分,它确保了你的模型性能是可靠的,而不仅仅是幸运的训练 - 测试划分的结果。现在,你可以运用这些知识,更有信心地评估你自己的机器学习模型。



