交叉验证后如何使用“测试”数据集?

机器算法验证 机器学习 交叉验证 验证
2022-01-19 13:33:49

在我看过的一些讲座教程中,他们建议将您的数据分成三部分:训练、验证和测试。但目前尚不清楚应该如何使用测试数据集,也不清楚这种方法如何优于对整个数据集的交叉验证。

假设我们已将 20% 的数据保存为测试集。然后我们将剩下的部分分成 k 折,并使用交叉验证,我们找到对该数据集中的未知数据做出最佳预测的模型。假设我们找到的最佳模型给了我们75%的准确率。

各种问答网站上的各种教程和大量问题表明,现在我们可以在保存的(测试)数据集上验证我们的模型。但我仍然不知道它是如何完成的,也不知道它有什么意义。

假设我们在测试数据集上 的准确率为70% 。那么我们接下来要做什么呢?我们是否尝试另一个模型,然后另一个模型,直到我们在测试数据集上获得高分?但在这种情况下,看起来我们只会找到适合我们有限(仅 20%)测试集的模型这并不意味着我们会找到总体上最好的模型。

此外,如果仅在有限的数据集上计算该分数,我们如何将其视为对模型的一般评估?如果这个分数很低,可能是我们运气不好,选择了“坏”的测试数据。

另一方面,如果我们使用我们拥有的所有数据,然后使用 k 折交叉验证选择模型,我们将从我们拥有的整个数据集中找到对未知数据做出最佳预测的模型。

4个回答

这类似于我回答的关于交叉验证和测试集的另一个问题。这里要理解的关键概念是独立数据集只考虑两种情况:

  1. 如果你有很多资源,你最好收集一个数据集并通过交叉验证来训练你的模型。然后您将收集另一个完全独立的数据集并测试您的模型。然而,正如我之前所说,这对于许多研究人员来说通常是不可能的。

现在,如果我是一个不那么幸运的研究人员,我该怎么办?好吧,您可以尝试模仿那个确切的场景:

  1. 在您进行任何模型训练之前,您将拆分数据并将其放在一边(在交叉验证期间永远不要碰触)。这是为了模拟上面理想场景中提到的相同的独立数据集。即使它来自同一个数据集,模型训练也不会从这些样本中获取任何信息(通过交叉验证,所有数据都被使用)。一旦你训练了你的模型,你就可以将它应用到你的测试集上,这在训练中是从未见过的,并得到你的结果。这样做是为了确保您的模型更具通用性,而不仅仅是学习您的数据。

为了解决您的其他问题:

假设我们在测试数据集上的准确率达到了 70%,那么接下来我们要做什么?我们是否尝试其他模型,然后尝试其他模型,直到我们在测试数据集上获得高分?

某种程度上,这个想法是你正在从你的数据中创建最好的模型,然后在一些以前从未见过的数据上对其进行评估。您可以重新评估您的交叉验证方案,但是一旦您有了调整好的模型(即超参数),您就可以继续使用该模型,因为它是您可以做出的最好的。关键是永远不要使用您的测试数据进行调整。您从测试数据中得出的结果是您的模型在“一般”数据上的表现。复制此过程将消除数据集的独立性(这是重点)。这也在关于测试/验证数据的另一个问题中得到解决

而且,如果它是在有限的数据集上计算的,我们如何将这个分数视为对模型的一般评估?如果这个分数很低,也许我们不幸选择了“坏”的测试数据。

如果您正确拆分数据,这不太可能。您应该随机拆分数据(尽管可能为了类平衡而分层)。如果您的数据集足够大,以至于您将数据分成三个部分,那么您的测试子集应该足够大,以至于您选择错误数据的机会非常低。您的模型更有可能过度拟合。

如果您要做的只是在原始数据集或经过最少预处理的数据集上训练具有默认设置的模型(例如一次性编码和/或删除 NA),则不需要单独的测试集,您可以简单地在您的训练集并在您的验证集上进行测试,或者更好的是,使用交叉验证对整个集进行训练以估计您的性能。

但是,一旦您对数据的了解导致您对原始策略进行任何更改,您现在已经“污染”了您的结果。一些例子包括:

  • 模型选择:您测试了逻辑、套索、随机森林、XGBoost 和支持向量机并选择了最佳模型

  • 参数调整:您调整了 XGBoost 以找到最佳超参数

  • 特征选择:您使用后向选择、遗传算法、boruta 等来选择要包含在模型中的最优特征子集

  • 缺失插补:您使用均值或基于其他变量的简单模型来插补缺失变量

  • 特征转换:您将数字变量居中并缩放以用 z 分数(与平均值的标准偏差数)替换它们

在上述所有情况下,使用单个保持集,甚至交叉验证,都不会为您提供对现实世界性能的真实估计,因为您使用的信息是您在决策中不会获得的未来数据信息。相反,您正在为您的数据挑选最佳模型、最佳超参数、最佳特征集等,并且您可能会稍微“过度拟合”您的数据策略。为了得到真实世界性能的真实估计,您需要对根本没有进入决策过程的数据进行评分,因此使用独立于您的训练(建模)和验证的独立测试集的常见做法(选择模型、特征、超参数等)集。

作为保留测试集的替代方法,您可以使用一种称为嵌套交叉验证的技术。这需要您将整个建模策略(转换、插补、特征选择、模型选择、超参数调整)编码为非参数函数,然后对整个函数执行交叉验证,就好像它只是一个模型拟合函数一样。这在大多数 ML 包中很难做到,但可以在 R 中使用 mlr 包轻松实现,方法是使用包装器定义训练策略,然后对包装的学习器重新采样:

https://mlr.mlr-org.com/articles/tutorial/nested_resampling.html

我假设你正在做分类。

获取您的数据并将其 70/30 拆分为 trainingData/testData 子集。获取 trainingData 子集并再次将其 70/30 拆分为 trainingData/ validateData 子集。现在您有原始数据的 3 个子集 - trainingData(.7*.7)、validateData(.7*.3) 和 testData(.3)。

您使用 trainingData 训练模型。然后,您使用 validateData 检查该模型的性能,我们可以将其视为独立于 trainingData,因此可以很好地评估模型的泛化程度。让我们假设你达到了 75% 的准确率。

现在,您可以任意次数地重新训练您的模型。每次再训练,您都在评估一组不同的超参数(首先提供给您的模型的参数与您的模型正在优化的参数),但仍然使用 trainingData 子集。每次再训练,您还通过检查 validateData 的性能再次检查新模型的泛化程度。

一旦你检查了你想要评估的超参数的每一个组合,你就可以选择在 validateData 上为你提供最佳性能的一组超参数——让我们假设你在 validateData 上的最佳性能是 80% 的准确度。这些是您的最终超参数,由这些超参数定义的模型就是您将用于下一步的模型。

现在,您采用使用最终超参数的模型并评估 testData。这是自整个过程开始以来第一次接触到testData!如果您获得的 testData 性能与您在 validateData 上的性能相当(尽管通常会略低),那么您可以确信您的模型按预期工作并且泛化得很好!如果发生这种情况,这就是您的最终模型!

为什么要做这一切?你试图避免过度拟合。在训练和调整(也就是验证)模型时,总是存在过度拟合所使用数据的风险。如果您只使用一个数据集进行训练、调整(验证)和测试,那么您很有可能会过度拟合该数据并且无法很好地泛化。通过将训练和测试数据集分开(并假设您使用测试数据进行调整),您有机会在内部检查自己,但您现在仍有可能过度拟合测试数据。这就是为什么我们打破第三个数据集,验证,所以我们有一个额外的层来保持自己内部诚实。使用 validateData 进行调优可以防止我们过度拟合 trainingData。使用 testData 进行最终测试可以防止我们过度拟合到 validateData。

让我们看看下面的方式

  1. 常见做法

    a) 训练数据 - 用于选择模型参数。

     i) E.g., finding intercept and slope parameters for an ordinary linear 
        regression model. 
    
     ii) The noise in the training data-set is used in some extent 
         in over-fitting model parameters. 
    

    b) 验证数据 - 用于选择超参数。

     i)  E.g., we may want to test three different models at step 1.a, say 
         linear model with one, two or three variables.   
    
     ii) The validation data-set is independent from training data, and thus, they provide 
         'unbiased' evaluation to the models, which help to decide which 
         hyper-parameter to use. 
    
     iii) We note that, a model trained in 1.a, say y = b_0+b_1*x_1, does 
         not learn anything from this data-set. So, the noise in this data- 
         set is not used to over-fit the parameters (b_0, b_1), but, over- 
         fit exists in choosing which linear model to use (in terms of 
         number of variables). 
    

    c) 测试数据——用于获取上述两步输出的置信度

    i) Used once a model is completely trained
    
  2. 查看第 1 部分的另一种方式

    a) 我们的模型候选池是一个 5 维集,即

    i) Dimension 1: number of variables to keep in the regression model, 
       e.g., [1, 2, 3].
    
    ii) Dimension 2-5: (b_0, b_1, b_2, b_3). 
    

    b) 步骤 1a 将候选模型从 5 维减少到 1 维。

    c) 步骤 1b 将候选模型从 1 维减少到 0 维,即单个模型。

    d) 但是,OP 可能认为上面的“最终”输出在测试数据集上表现得不够好,因此再次重做整个过程,比如使用岭回归而不是普通的线性回归。然后测试数据集被多次使用,因此该数据中的噪声可能会在决定使用线性回归还是岭回归时产生一些过拟合。

    e) 为了处理具有参数、超参数、模型类型和预处理方法的高维模型池,对我们可用数据的任何拆分本质上是定义一个决策过程,该过程

    i)  Sequentially reducing the model pool to zero-dimension.
    
    ii) Allocating data noise overfitting to different steps of dimension 
        reductions (overfitting the noise in the data is not avoidable but 
        could be allocated smartly). 
    
  3. OP问题的结论和答案

    a) 二分(训练和测试)、三分(训练、验证和测试)或更高数量的分本质上是关于降低维数和分配数据(尤其是噪声和过度拟合的风险)。

    b) 在某个阶段,您可能会提出一个“最终”模型候选池,然后,您可以考虑如何设计顺序降维的过程,使得

    i) At each step of reducing the dimensions, the output is satisfactory, 
      e.g., not using just 10 data points with large noise to estimate a 
      six-parameter liner model. 
    
    ii) There are enough data for you to reduce the dimension to zero 
       finally. 
    

    c) 如果你不能达到 b

    i) Use model and data insight to reduce the overall dimensionality of 
      your model pool. E.g., liner regression is sensitive to outliers thus 
      not good for data with many large outliers. 
    
    ii) Choose robust non-parametric models or models with less number of 
       parameter if possible. 
    
    iii) Smartly allocating the data available at each step of reducing the 
        dimensionality. There is some goodness of fit tests to help us decide 
        whether the data we use to train the model is enough or not.