Vinod Chugani 2024-06-21
想象一下,你正在训练一个机器学习模型,但不确定它在新的、未见过的数据上表现如何。这时,K折交叉验证(K-Fold Cross-Validation)就派上用场了。它能让你提前一窥模型在现实世界中的可能表现。这项技术有助于确保你的预测结果并非“昙花一现”,而是在面对新数据时始终可靠。
在本指南中,我们将深入解析K折交叉验证的基本原理,并将其与更简单的方法(如训练-测试集划分)进行比较。你将通过Python探索多种交叉验证方法,并理解为何选择合适的方法会对你的项目产生重大影响。最后,你将掌握如何使用scikit-learn应用这些策略。
让我们开始学习,让你的机器学习成果真正值得信赖!
什么是K折交叉验证?
K折交叉验证是一种用于评估机器学习模型性能的稳健技术。它通过在多次迭代中使用数据集的不同部分进行训练和测试,帮助确保模型能够很好地泛化到未见过的数据。
K折交叉验证 vs. 训练-测试集划分
K折交叉验证将数据集划分为多个子集,在多次迭代中交替用于训练和测试模型;而训练-测试集划分方法仅将数据集分为两部分:一部分用于训练,另一部分用于测试。训练-测试集划分方法简单且易于实现,但其性能估计高度依赖于具体的划分方式,可能导致结果方差较大。
下图展示了这两种方法在结构上的差异。第一张图展示了训练-测试集划分方法,其中数据集被划分为80%的训练集和20%的测试集。
训练/测试集划分示意图。作者供图
第二张图描绘了5折交叉验证:数据集被分为五个部分,每个部分在五次迭代中轮流作为测试集,确保每个数据段都被用于训练和测试。
5折交叉验证示意图。作者供图
我们可以看到,K折交叉验证提供了更稳健、更可靠的性能估计,因为它降低了数据变异性的影响。通过多次训练和测试循环,它减少了对特定数据划分过拟合的风险。这种方法还确保每个数据点都被用于训练和验证,从而对模型性能进行更全面的评估。
使用Python和scikit-learn实现K折交叉验证
现在,我们以加州房价数据集为例,演示如何使用K折交叉验证来评估线性回归模型的性能。该方法通过在数据集的不同子集上迭代测试,提供对模型准确性的稳健估计,从而实现对模型性能的全面评估。
加州房价数据集概览
加州房价数据集由Pace和Barry(1997年)整理,包含1990年美国人口普查中关于加州住房的数据。该数据集包含20,640个观测样本,特征包括地理位置、房屋年龄和人口等,目标变量是加州各地区的中位房价。
该数据集提供了多样化的地理、人口统计和经济特征,非常适合数据科学和机器学习应用。我们将从scikit-learn库直接下载该数据集开始我们的代码示例。
加载数据集
在开始模型训练和评估之前,我们需要先加载数据集。
from sklearn.datasets import fetch_california_housing
data = fetch_california_housing()
这段代码从sklearn.datasets导入fetch_california_housing函数,并调用它来加载加州房价数据集。该数据集存储在变量data中,其中包含特征和目标变量。
准备数据
数据集加载完成后,下一步是为分析准备数据。
import pandas as pd
X = pd.DataFrame(data.data, columns=data.feature_names)
y = data.target
这里,我们使用pandas库创建一个DataFrame X,其中包含来自data.data的特征数据。DataFrame的列名使用data.feature_names进行标注。目标变量(即中位房价)单独存储在y中。
设置K折交叉验证
现在是时候设置我们的模型了,包括选择K值。如何选择合适的K值是一个重要步骤,我们将在下文详细讨论。
from sklearn.model_selection import KFold
k = 5
kf = KFold(n_splits=k, shuffle=True, random_state=42)
这段代码使用sklearn.model_selection中的KFold类初始化K折交叉验证。我们设置了5个划分(即5折)。shuffle=True选项会随机打乱数据点的顺序,而random_state=42确保这种打乱在多次运行中保持一致。这种设置通常足以开始使用交叉验证评估模型性能。
初始化模型
数据准备就绪、交叉验证设置完成后,下一步是选择并初始化模型。
from sklearn.linear_model import LinearRegression
model = LinearRegression()
我们从sklearn.linear_model导入LinearRegression类,并创建一个实例model。该模型将用于在数据集上执行线性回归。
执行交叉验证
模型初始化后,我们就可以进入有趣的部分——执行交叉验证,以评估模型在不同数据子集上的性能。
from sklearn.model_selection import cross_val_score
scores = cross_val_score(model, X, y, cv=kf, scoring='r2')
这行代码使用cross_val_score函数,利用数据集X和目标变量y对模型进行评估。交叉验证使用前面定义的KFold实例kf进行,模型性能通过R²分数衡量。
计算平均R²分数
我们可以使用R²(决定系数)作为评估指标,衡量因变量中可由自变量解释的方差比例,从而洞察回归模型的拟合优度。
import numpy as np
average_r2 = np.mean(scores)
print(f"R² Score for each fold: {[round(score, 4) for score in scores]}")
print(f"Average R² across {k} folds: {average_r2:.2f}")
这部分代码计算所有折的平均R²分数。首先打印每一折的分数,然后输出平均分数。np.mean()用于计算交叉验证过程中收集到的分数的均值。
展示最终结果
我们现在汇总结果,以全面了解模型的性能。平均R²分数提供了一个单一指标,反映模型的有效性。
R² Score for each fold: [0.5758, 0.6137, 0.6086, 0.6213, 0.5875]
Average R² across 5 folds: 0.60
这是上一步代码的输出结果,显示了每一折的R²分数以及平均R²分数。
K折交叉验证中的“K”代表什么?
在K折交叉验证中,“K”表示将数据集划分为的组数。这个数字决定了模型要经历多少轮测试,确保每个数据段都恰好被用作一次测试集。
以下是一些经验法则:
- K = 2 或 3:当计算资源有限或需要快速评估时,这些选择可能更有利。它们减少了训练轮次,从而节省时间和计算资源,同时仍能提供合理的模型性能估计。
- K = 5 或 10:选择K=5或K=10是常见做法,因为它们在计算效率和模型性能估计之间取得了良好平衡。
- K = 20:使用更大的K值可以提供更细致的性能评估,但会增加计算负担,如果子集过小,还可能导致更高的方差。
使用K折交叉验证的关键注意事项
“K”值对K折交叉验证的影响
K折交叉验证中的折数“K”既影响验证过程的精细程度,也影响计算负载。较小的K值(例如3–5)可能更快,但可能产生不太可靠的估计,因为每折代表数据集中较大的一部分,可能会遗漏多样化的数据场景。较大的K值(例如10)能提供更详细的评估,但代价是更高的计算开销。通常,K=5或K=10是一个不错的起点,足以在不过度计算的前提下获得可靠的估计。
在K折交叉验证中打乱数据的重要性
在K折交叉验证中打乱数据强烈推荐,以增强模型评估的有效性。通过设置shuffle=True,打乱操作可以打破数据集中可能存在的固有顺序,避免在验证过程中引入偏差。这确保了每一折都能代表整个数据集,对于评估模型在新数据上的泛化能力至关重要。然而,在时间序列等数据中,若数据点的顺序具有实际意义,则应避免打乱,以保持学习过程的完整性。
确保K折交叉验证的可复现性
确保K折交叉验证结果的可复现性对于验证模型的稳定性和性能至关重要。这可以通过设置random_state参数来实现,该参数确保在不同运行中数据打乱方式一致,从而产生相同的数据划分,最终获得可复现的结果。
标准K折交叉验证与其他交叉验证方法的比较
选择合适的交叉验证技术对于构建可靠的机器学习模型至关重要。选择很大程度上取决于数据集的具体特征和机器学习任务的类型。不同的技术旨在应对各种挑战,如类别不平衡或具有分组结构的数据。
下表全面比较了最常用的几种交叉验证方法,突出其独特特点和最佳使用场景,帮助你为特定建模需求选择最有效的技术。
| 交叉验证类型 | 适用任务 | 描述 | 适用场景 |
|---|---|---|---|
| 标准K折交叉验证 | 回归和分类 | 将数据集划分为K个等大小的折,每折轮流作为测试集一次。 | 适用于类别平衡的数据集,以确保全面的模型评估。 |
| 分层K折交叉验证(Stratified K-Fold) | 主要用于分类 | 保持每折中各类别标签的比例与原始数据集一致。 | 适用于类别不平衡的分类任务,以维持各类别比例。 |
| 留一法交叉验证(LOOCV) | 回归和分类 | 每个数据点依次作为测试集,其余作为训练集。 | 适用于小型数据集,以最大化训练数据量,但计算成本高。 |
| 留P法交叉验证(Leave-P-Out) | 回归和分类 | 类似于LOOCV,但每次留出P个数据点作为测试集。 | 适用于小型数据集,用于测试数据样本变化对模型稳定性的影响。 |
| 分组K折交叉验证(Group K-Fold) | 带分组结构的回归和分类 | 确保同一组的数据不会同时出现在训练集和测试集中,适用于数据点非独立的情况。 | 适用于具有逻辑分组的数据集,用于在独立分组上测试性能。 |
| 分层分组K折交叉验证(Stratified Group K-Fold) | 带分组结构的分类任务 | 结合分层抽样和分组完整性,确保分组不会跨折拆分。 | 适用于既分组又类别不平衡的数据集,以同时保持类别和分组完整性。 |
结论
本指南向你展示了K折交叉验证是如何成为评估机器学习模型的强大工具。它优于简单的训练-测试集划分,因为它在数据的多个部分上测试模型,帮助你确信模型在面对未见数据时也能表现良好。