超参数调优和模型选择时如何避免过拟合偏差?

机器算法验证 交叉验证 模型选择 模型评估 过拟合 泛化错误
2022-04-01 21:27:41

假设我有 4 种或更多算法类型(逻辑、随机森林、神经网络、支持向量机等),每一种我都想在我的数据集上尝试,每一种我都需要调整超参数。

我通常会使用交叉验证来尝试调整我的超参数,但是一旦调整,我如何避免选择模型族的泛化错误?

在我看来,每个家庭的分数现在都会有信息泄漏,因为平均调整后的 cv 分数在某种程度上可以看到整个火车组。

那么这里有什么好的做法呢?在嵌套交叉验证运行或带有最终保留的简单交叉验证之间看起来会有什么不同?

谢谢!

2个回答

正如@DikranMarsupial 所说,您需要一个嵌套的验证程序。在内部例如交叉验证中,您对模型进行所有调整 - 包括选择超参数和模型系列。

原则上,你也可以有一个三重嵌套的验证结构,最里面的调整各自的模型族超参数,中间的选择模型族,外部的像往常一样获得最终模型的泛化误差估计。
然而,这样做的缺点是,不必要的分割意味着数据分区变得相当小,因此整个过程可能变得更加不稳定(小的优化/验证/测试集意味着不确定的性能估计)。


更新:

嵌套与交叉验证或保留

嵌套独立于您在嵌套设置的每个级别使用什么拆分方案的问题。您可以在每个级别进行交叉验证,在每个级别进行单独拆分或您认为适合您任务的任何混合。
2 个嵌套级别和两个 CV 就是通常所说的嵌套交叉验证,2 个嵌套级别和两个单独拆分相当于著名的训练 - 验证 [优化] - 测试 [验证] 设置。混合不太常见,但也是一种完全有效的设计选择。

如果您有足够的数据,因此单次拆分是一个明智的选择,那么您可能还有足够的数据来进行三个这样的拆分,即使用 4 个数据子集。

但是,您需要记住的一件事是:优化步骤中的单个拆分*您剥夺了自己检查优化是否稳定的一种非常简单且重要的方法,而交叉验证(或进行多次拆分)提供了这种方法。

* 是否将超参数与模型族组合或模型族选择加上“正常”超参数优化

三重嵌套与“正常”嵌套

这很方便,因为它很容易以防止意外数据泄漏的方式实现 - 我怀疑这是您最初提出问题的原因:

  • estimate_generalization_error()它将数据拆分为测试和训练以及在其训练数据调用中
  • choose_model_family()它采用另一个内部拆分来指导选择和调用,并在训练拆分上调用各种
  • optimize_model_*()它实现了另一个内部拆分以优化每个模型系列 (*) 的常用超参数,并在训练拆分上调用相应的低级模型拟合函数。

在这里,choose_model_family()optimize_model_*()是组合调整功能的替代方案,它可以在一个拆分中完成两者的工作。由于两者都是训练步骤,因此可以将它们结合起来。如果您为超参数调整进行网格搜索,您可以将其视为具有模型族 x 所有可能的超参数的稀疏网格,其中仅评估碰巧存在的组合(例如,跳过mtrySVM)。
或者您将搜索空间视为您检查的合理超参数组合的列表:

- logistic regression
- SVM with cost = 1, gamma = 10
- SVM with cost = 0.1, gamma = 100
...
- random forest with ...

找到跨模型族和模型族特定超参数的全局最优值。

没有什么特别的model_family- 它是最终模型的超参数,例如costSVM gamma

为了理解等价性,请考虑优化 SVM 的 gamma 和成本。

  • 方法一:建立一个网格或所有合理成本的清单;伽玛组合并搜索最佳值。这类似于“正常”的嵌套方法。

  • 方法二:

    1. 列出所有可能的成本值。
    2. 对于每个成本值,优化 gamma。
    3. 选择具有最佳优化 gamma 的成本

    这类似于三重嵌套方法。

在这两种情况下,我们都可以将嵌套结构“展平”为一个循环,遍历列表或网格(对不起,我缺乏正确的英文术语——也许有人可以帮忙?)。这也模糊地类似于将递归结构“展平”为迭代结构[尽管三重嵌套不是递归的,因为我们有不同的函数 f(g(h()))]。

这种扁平化方法可能具有进一步的优势,即它可能更适合高级优化启发式算法。例如,考虑从“选择观察到的最优值”转移到单一标准偏差规则。使用扁平化方法,您现在可以查看模型族,哪个模型的复杂度最低,比观察到的最优值差不超过 1 sd。

只是添加到@cbeleites 答案(我倾向于同意),嵌套交叉验证没有本质上的不同,它将停止 OP 中的问题。嵌套交叉验证只是对训练/测试拆分的交叉验证模拟,并在训练集上执行交叉验证。所有这些都是通过平均分割来减少您对泛化误差估计的方差。也就是说,显然减少估计中的方差是一件好事,如果时间允许,嵌套 CV 应该在单个训练/测试拆分中完成。

对于我所看到的 OP,有两种解决方案(我将在单个训练/测试拆分而不是嵌套 CV 下对其进行描述,但它显然也可以应用于嵌套 CV)。

第一个解决方案是执行训练/测试拆分,然后再次将训练集拆分为训练/测试。你现在有一个训练集和两个集。对于每个模型族,对训练集执行交叉验证以确定超参数。对于每个模型族,选择表现最好的超参数,并从测试集 1 中获得泛化误差的估计值。然后比较每个模型族的错误率以选择最佳的并获得其在测试集 2 上的泛化误差。这将消除由于使用用于训练的数据选择模型而导致的乐观偏差问题会增加更多的悲观偏差,因为您必须从测试集 2 的训练中删除数据。

cbeleites 描述的另一个解决方案是将模型选择简单地视为超参数。当您确定最佳超参数时,请在此选择中包含模型系列。也就是说,您不只是将 mtry = 1 的随机森林与 mtry = 2 的随机森林进行比较......您正在将 mtry = 1 的随机森林与 mtry = 2 以及成本 = 1 的 SVM 等进行比较。

最后,我想另一种选择是忍受 OP 中方法的乐观偏见。据我了解,导致需要测试集的主要原因之一是,随着超参数搜索空间的增长,选择过拟合模型的可能性也会增加。如果模型选择是使用测试集完成的,但仅在 3 或 4 个模型系列之间完成,我想知道这实际上会导致多少乐观偏差。事实上,如果这是在实践中主要使用的方法,我不会感到惊讶,特别是对于那些使用 la sci-kit learn 或 caret 的预构建功能的人。毕竟这些包允许对单个模型系列进行网格搜索,而不是同时搜索多个。