Sklearn 中的 K-Fold 交叉验证

2024 年 08 月 29 日 | 阅读 9 分钟

从数据收集开始,创建用于训练和验证模型的训练数据集是提高模型性能最常见的机器学习方法。数据集的划分比例可以是 70:30 或 80:20。留出法是最常见的交叉验证方法。

这种方法的问题在于,我们不确定模型良好的验证准确率是否真的代表一个好的模型。如果用于验证的数据集部分恰好表现良好,该怎么办?如果我们使用不同的数据集部分作为验证集,我们的模型是否仍然能给出高准确率?K 折交叉验证可以解决其中一些疑问。

什么是交叉验证?

当我们必须训练一个具有良好性能得分的机器学习模型时,将数据集划分为训练集和验证集是基本且重要的操作。我们必须在未见过的数据集(验证集)上测试我们的模型,以评估它是否过拟合。

如果模型在实际的实时数据上表现不佳,并且在验证集上也无法获得良好的准确率,那么它在实际应用中的性能就会很差。考虑到这一点,交叉验证可能是最重要的机器学习概念之一,它保证了我们模型的鲁棒性。

交叉验证本质上是一种过程,它将数据集的一部分用于模型的验证和测试,而其余的数据集则用于模型的训练。

使用交叉验证的好处

  • 它有助于我们评估模型并确定其准确性。
  • 对于确定模型是否能够成功泛化到数据至关重要。
  • 用于确定模型是过拟合还是欠拟合。
  • 最后,它使我们能够选择性能最好的模型。

多种交叉验证类型

  1. K 折交叉验证
  2. 分层 K 折交叉验证
  3. 留 P 折交叉验证
  4. 留一法交叉验证
  5. 时间序列交叉验证
  6. 随机分割交叉验证

什么是 K 折交叉验证?

K 折交叉验证方法广泛用于计算机器学习模型在验证数据集上的性能。

尽管 10 是 K 的一个常见选择,但我们如何确定这个折数适合给定的数据集和模型呢?

一种方法是研究不同 K 选择对模型性能估计的影响,并将其与理想测试条件进行比较。这有助于选择正确的折数。

一旦确定了 K 值,我们就可以用它来评估数据集上的各种模型。然后,我们可以将得分模式与同一模型在理想测试场景下的分析得分进行对比,看看它们是否高度相关。如果结果相关,就证实所选配置是理想测试场景的可靠近似。

本教程将教读者如何设置和评估 K 折交叉验证的配置。

K 折交叉验证方法的流程

总的来说,遵循以下步骤:

  1. 随机打乱完整的数据集。
  2. 然后算法将数据集分成 k 个组,即 k 个数据折。
  3. 对于每一个不同的组
  4. 使用该数据集作为留出数据集来验证模型。
  5. 其余组的数据集用于训练模型。
  6. 在训练数据集上拟合模型,然后对其进行评估,在留出集或验证集上进行测试。
  7. 保留评估结果,但丢弃生成的模型。
  8. 使用模型评估得分的结果,总结模型的性能。

值得注意的是,数据集中的每一项都被分配了一个唯一的组,并且在该过程的整个过程中都保持在该组中。这意味着每个数据样本都有 k 次机会成为训练集的一部分,并有 k 次机会成为留出集或验证集的一部分。

在拟合模型之前完成的所有数据准备都必须在 CV 分配的训练数据集的循环中完成,而不是在整个数据集上完成。这也适用于任何超参数调优。如果在循环之外进行这些过程,可能会导致数据泄露和模型能力评估的夸大。

K 折交叉验证测试示例

代码

输出

Accuracy score of each fold:  [0.9122807017543859, 0.9473684210526315, 0.9736842105263158, 0.9736842105263158, 0.9557522123893806]
Mean accuracy score:  0.952553951249806

使用 cross_val_score() 进行交叉验证

我们可以使用 cross_val_score 类方法来简化上述代码。

代码

输出

Accuracy score of each fold:  [0.9122807017543859, 0.9473684210526315, 0.9736842105263158, 0.9736842105263158, 0.9557522123893806]
Mean accuracy score:  0.952553951249806

K 折交叉验证方法有助于在较小的数据集上训练模型。如果我们的数据量很大,则可能不需要 K 折交叉验证。其原因是我们的验证数据集有足够多的记录,可以让我们验证机器学习模型的性能。在大型数据集上使用 K 折交叉验证测试会花费大量时间。

此外,使用更多的折数来验证我们的模型会消耗更多的计算能力。对于较大的 K 值,模型将花费更多时间进行训练。如果 K 为 5,则模型将使用五个不同的验证数据集折进行五次独立的训练。如果 K=10,模型则运行十次。

K 的敏感性分析

K 折交叉验证测试最重要的调优参数是 K 值,它指定了将给定数据集划分为多少个折。

对于平均大小的数据集,通常选择 K=3、K=5 和 K=10。据观察,K=10 在所有值中被最广泛地用于评估我们训练的模型性能。选择这个特定值的原因是,研究表明 K=10 在计算成本低和模型性能评估偏差适中之间提供了合理的平衡。

在我们的数据集样本上测试模型时,我们如何确定 K 的值?

虽然 K=10 是一个选择,但我们如何确保它能充分代表我们的数据集?

一种应对此问题的方法是运行不同 K 数量的敏感性分析。换句话说,比较在相同数据集上训练但 K 值不同的同一模型的测试结果。

假定 K 值较小会导致模型性能预测出现较大噪声,而 K 值较大则会产生较少噪声的预测。

然而,与什么相比才算噪声?

当我们使用未见过的数据时,我们无法获得模型真正的性能。如果我们知道它,就可以将其应用于模型的评估。

但是,我们可以选择一个测试条件作为“理想”的或尽可能接近理想的估计,来预测模型的性能。

一种策略是使用所有可访问的数据训练模型,然后使用另一个大型样本留出数据集来估计其性能。留出数据上的性能将指示模型的“实际”性能。相比之下,训练数据集上的任何交叉验证得分将是对这个真实分数的估计。我们提到的方法很少可行,因为我们通常没有足够的数据来将主数据集的一部分留作测试集。

留一法交叉验证(LOOCV)过程是交叉验证的一种计算密集型修改,其中 K=N,N 是训练数据集中的样本总数。我们可以用它来模拟这种情况。换句话说,在每个用于验证的数据集样本中,只使用训练数据集中的一个样本。如果数据合适,它可以生成模型性能的良好估计,但由于计算成本高,很少用于大型数据集。

然后,使用与 LOOCV 相同的训练数据集,我们可以评估 LOOCV 过程的平均分类准确率与各种 K 值的平均分类准确率。得分之间的差异提供了对 K 值与理想模型性能测试条件有多接近的粗略近似。

让我们看看如何执行 K 折交叉验证过程的敏感性分析。

  1. 首先,我们来创建一个函数来构建数据集。这使我们有机会,如果我们愿意,可以用任何数据集替换它。
  2. 然后,我们可以定义用于构建要评估的模型的数据集。同样,这种区分使我们能够根据需要自定义模型。
  3. 之后,我们可以创建一个函数,使用测试条件在验证数据集上验证模型。测试条件可以是 LeaveOneOut 的一个示例,它代表了我们的理想测试条件,或者它可以是 KFold 对象,参数化为特定的 K 值。该函数除了给出平均分类准确率外,还给出折的最小和最大分类准确率。分数的范围可以通过最小值和最大值来概括。
  4. 然后,我们将使用 LOOCV 方法来计算模型性能。
  5. 然后,我们可以定义分析的 K 值。在本例中,我们将测试 2 到 20 之间的数字。然后,我们可以单独分析每个值并记录结果。

代码

输出

Ideal score:  0.83
Folds=2, accuracy=0.81 (0.81,0.81)
Folds=3, accuracy=0.83 (0.79,0.85)
Folds=4, accuracy=0.84 (0.8,0.86)
Folds=5, accuracy=0.83 (0.78,0.88)
Folds=6, accuracy=0.83 (0.77,0.88)
Folds=7, accuracy=0.83 (0.76,0.89)
Folds=8, accuracy=0.83 (0.77,0.88)
Folds=9, accuracy=0.83 (0.75,0.9)
Folds=10, accuracy=0.82 (0.74,0.9)
Folds=11, accuracy=0.83 (0.77,0.9)
Folds=12, accuracy=0.83 (0.7,0.9)
Folds=13, accuracy=0.82 (0.77,0.91)
Folds=14, accuracy=0.82 (0.66,0.93)
Folds=15, accuracy=0.82 (0.76,0.92)
Folds=16, accuracy=0.83 (0.67,0.92)
Folds=17, accuracy=0.83 (0.73,0.93)
Folds=18, accuracy=0.83 (0.68,0.93)
Folds=19, accuracy=0.82 (0.68,0.92)
Folds=20, accuracy=0.82 (0.66,0.96)