如何在嵌套交叉验证中获取超级参数?


17

我已经阅读了以下有关嵌套交叉验证的文章,但仍然不确定100%如何使用嵌套交叉验证进行模型选择:

为了解释我的困惑,让我尝试逐步使用嵌套交叉验证方法进行模型选择。

  1. 使用K折创建外部CV循环。这将用于估计“赢得”每个内部CV循环的超参数的性能。
  2. 使用GridSearchCV创建一个内部CV循环,在每个内部循环中,GSCV都会遍历参数空间的所有可能组合,并提供最佳的参数集。
  3. GSCV在内部循环中找到最佳参数后,将使用外部循环中的测试集对其进行测试,以获得性能评估。
  4. 然后,外循环更新为测试集的下一个折叠,其余的更新为训练集,并重复1-3次。总共可能的“获胜”参数是在外循环中指定的折数。因此,如果外部循环是5倍,那么您将对具有5组不同的超参数的算法进行性能评估,而不是一组特定的超参数的性能。

SKLearn的示例页面上说明了这种方法:http ://scikit-learn.org/stable/auto_examples/model_selection/plot_nested_cross_validation_iris.html

问题:4 . 之后,您如何确定哪些超级参数效果最佳?我知道您想使用最后的COMPLETE数据来训练算法(例如逻辑回归,随机森林等)。但是,如何确定哪些超级参数在嵌套交叉验证中效果最好?我的理解是,对于每个内部循环,一组不同的超参数将获胜。对于外循环,您正在评估GridSearchCV的性能,但没有任何一组特定的超参数。因此,在最终的模型创建中,您如何知道要使用哪些超参数?那是我从其他方面难以理解的缺失逻辑。

预先感谢您提供任何提示,尤其是如果@Dikran Marsupial和@cbeleites可以发出提示音!

编辑:如果可以的话,请在回答中使用“算法”和“超级参数”之类的术语。我认为让我感到困惑的一个原因是人们使用术语“模型”或“模型选择”。无论他们是在谈论选择使用哪种算法还是使用哪些超级参数,我都感到困惑。

编辑2:我创建了一个笔记本,其中显示了两种进行嵌套交叉验证的方法。第一种方法是SKLearn示例中显示的方法,另一种较长的方法是我编写的方法。SKLearn中显示的方法没有公开“获胜”的超参数,但我的较长方法却没有。但是问题仍然是一样的。完成嵌套交叉验证后,即使暴露了超参数,我现在该怎么办?从笔记本末尾的超参数可以看出,它们之间的差异很大。


1
笔记本为+1。这个问题也让我感兴趣,并将继续。
阿诺德·克莱恩

Answers:


6

(我确定我已经在某个答案中写了大部分内容-但现在找不到它。如果有人偶然发现了该答案,请链接它)。我在这里看到2种略有不同的方法,我认为这都是明智的。

但是首先是一些术语:

  • 来自一个应用领域,对我来说(适合/训练过的)模型很容易使用。也就是说,模型包含生成新数据预测所需的所有信息。因此,模型包含超参数。您将看到,这种观点与下面的方法2密切相关。
  • OTOH,在我的经验中,训练算法在以下意义上没有得到很好的定义:为了获得(拟合的)模型,不仅需要“正常”模型参数的-我们称之为“主要拟合”,但是超参数也需要固定。从我的应用程序角度来看,参数和超参数之间并没有太大区别:两者都是模型的一部分,需要在训练期间进行估计/确定。
    我想它们之间的差异与开发新训练算法的人之间的差异有关,后者通常会描述一类训练算法以及一些转向参数(超参数))在没有应用/领域知识的情况下很难/不可能(或至少应该决定如何决定/估算)。

方法1:要求稳定的优化结果

通过这种方法,“模型训练”是“正常”模型参数的拟合,并给出了参数。内部例如交叉验证负责超参数优化。

解决要选择其超参数集的困境的关键步骤/假设是要求优化过程稳定。出于验证目的的交叉验证假设所有替代模型都与最终模型足够相似(通过对整个数据集应用相同的训练算法获得),从而可以将它们(在最终模型之间)视为相等。如果这个假设失败了,

  1. 替代模型彼此之间仍然相等(或等效),但与最终模型不相等,我们谈论的是交叉验证的众所周知的悲观偏见。

  2. 如果替代模型也彼此不相等/相等,则存在不稳定的问题。

对于内循环的优化结果,这意味着如果优化是稳定的,则选择超参数不会有冲突。并且如果在内部交叉验证结果中观察到相当大的差异,则优化不稳定。不稳定的训练情况所带来的问题比仅仅决定选择哪个超参数要严重得多,我真的建议在这种情况下退一步并重新开始建模过程。

但是,这里有一个例外:优化中可能会有几个局部最小值,而实际应用中会产生相同的性能。也要求他们之间保持稳定的选择可能是不必要的强烈要求-但我不知道如何摆脱这一困境。

请注意,如果不是所有模型都产生相同的获胜参数集,则不应在此处使用外环估计作为泛化误差:

  • p
  • 但是,除非没有涉及所有分割产生相同参数的决策,否则这将破坏外部循环的独立性:每个分割的测试数据已经进入了决定哪个参数集获胜的决定,因为它是所有其他分割中的训练数据,因此可以使用优化参数。

方法2:将超参数调整作为模型训练的一部分

这种方法桥接了“训练算法开发人员”和训练算法的应用用户的观点。

训练算法开发人员提供了“裸”训练算法model = train_naked (trainingdata, hyperparameters)。由于应用用户的需求 tunedmodel = train_tuned (trainingdata),这也需要修复超参数。

train_tuned可以例如通过将基于交叉验证的优化器包装在裸训练算法周围来实现train_naked

train_tuned然后可以像不需要超参数输入的任何其他训练算法一样使用,例如tunedmodel可以对其输出进行交叉验证。现在,检查超参数的稳定性,就像在交叉验证评估中应检查“正常”参数的稳定性一样。

如果您对所有获胜模型的平均性能进行了评估,而不论它们各自的参数集如何,那么实际上这就是您在嵌套交叉验证中所做的评估。


有什么不同?

我们可能最终采用这两种方法得出不同的最终模型:

  • 方法1的最终模型将是 train_naked (all data, hyperparameters from optimization)
  • 而方法2将使用train_tuned (all data)和-从而在较大的数据集上再次运行超参数优化-最终可能会得到一组不同的超参数。

但是,同样的逻辑也适用:如果我们发现最终模型的参数与交叉验证代理模型的参数大不相同,那就是假设1被违反的征兆。所以恕我直言,我们没有冲突,而是要检查我们的(隐式)假设是否合理。如果不是这样,无论如何我们都不应该对最终模型的性能进行正确的估计。


我给人的印象(也是从CV上类似问题/困惑的数量中看到的),很多人认为嵌套交叉验证是在方法1上进行的。但是一般根据方法2来估计泛化误差,因此这就是方法最终模型。


虹膜示例

简介:优化基本上是没有意义的。可用的样本数量不允许在此处区分任何参数集的性能。

但是,从应用程序角度来看,得出的结论是,选择4个参数集中的哪一个都没有关系-并不是所有的坏消息:您发现了一个相对稳定的参数平台。这带来了对调整后的模型进行适当的嵌套验证的优势:虽然您不能断言它是最佳模型,但仍然可以断言使用方法2在整个数据上构建的模型将具有大约97%的准确度(150个测试案例中的145个正确案例的95%置信区间:92-99%)

请注意,方法1看起来也并非遥不可及-参见下文:由于关系的缘故,您的优化意外地错过了一个相对明确的“赢家”(这实际上是样本量问题的另一个非常明显的征兆)。

尽管我对SVM的了解还不够深,无法“看到” C = 1应该是一个不错的选择,但我会选择限制性更强的线性内核。此外,当你做了优化,没有什么不妥选择,即使你知道,所有参数集导致几乎相同的性能优胜参数集。

但是,在将来,请考虑您的经验是否会粗略估计您可以预期的性能以及大致上哪种模型会是一个不错的选择。然后构建该模型(使用手动固定的超参数)并计算其性能的置信区间。使用它来确定尝试进行优化是否合理。(我可能会补充说,我主要是在处理不易获得10个独立案例的数据的情况下-如果您所在的领域具有大量独立样本,那么情况对您来说会好得多)

长版:

至于示例结果在iris数据集上。iris在150个案例中,考虑了具有2 x 2参数网格的SVM(2个内核,惩罚的数量级为2个数量级C)。

内部循环具有129(2x)和132(6x)情况的分割。“最好”的参数组是线性的或径向基核之间未定,都与C = 1然而,内测试精度是所有(包括始终松动C = 10)内94 - 98.5%观察到的精确度。对于C = 1 vs. 10的rbf,我们在拆分之一中的最大差异是3 vs. 8误差。

这根本不可能有很大的不同。我不知道如何提取CV中个别案例的预测,但是即使假设3个错误是共享的,并且C = 10模型又产生了5个错误:

> table (rbf1, rbf10)
         rbf10
rbf1      correct wrong
  correct     124     5
  wrong         0     3

> mcnemar.exact(rbf1, rbf10)

    Exact McNemar test (with central confidence intervals)

data:  rbf1 and rbf10
b = 5, c = 0, p-value = 0.0625
alternative hypothesis: true odds ratio is not equal to 1

请记住,在2 x 2网格中有6个成对比较,因此我们也需要校正多个比较。


方法1

在rbf在线性核中胜出的4个外部拆分中的3个中,它们实际上具有相同的估计准确性(我猜是在平局的情况下,min返回第一个合适的索引)。

将网格更改为 params = {'kernel':['linear', 'rbf'],'C':[1,10]} 收益

({'kernel': 'linear', 'C': 1}, 0.95238095238095233, 0.97674418604651159)
({'kernel': 'rbf', 'C': 1}, 0.95238095238095233, 0.98449612403100772)
({'kernel': 'linear', 'C': 1}, 1.0, 0.97727272727272729)
({'kernel': 'linear', 'C': 1}, 0.94444444444444442, 0.98484848484848486)
({'kernel': 'linear', 'C': 1}, 0.94444444444444442, 0.98484848484848486)
({'kernel': 'linear', 'C': 1}, 1.0, 0.98484848484848486)
({'kernel': 'linear', 'C': 1}, 1.0, 0.96212121212121215)

方法二:

clf是您的最终模型。使用random_state = 2,C = 1的rbf获胜:

In [310]: clf.grid_scores_
[...snip warning...]
Out[310]: 
[mean: 0.97333, std: 0.00897, params: {'kernel': 'linear', 'C': 1},
 mean: 0.98000, std: 0.02773, params: {'kernel': 'rbf', 'C': 1},
 mean: 0.96000, std: 0.03202, params: {'kernel': 'linear', 'C': 10},
 mean: 0.95333, std: 0.01791, params: {'kernel': 'rbf', 'C': 10}]

(在5次,1 6次发生约1 linearrbfC = 1被绑定于秩1)


4
谢谢@cbeleites!我也在其他主题中阅读了您的答案,希望您能回答我的问题。您的回答非常深入,但是我的问题真正关注的是如何分析嵌套CV的结果;对于“嵌套CV之后该怎么办”,我还是不太清楚。您能否看一下我创建的笔记本(在文章末尾附近),并用通俗易懂的方式解释该操作,因为在嵌套的CV中已确定两组不同的超参数是最佳的?我保证,这是一个非常短的笔记本!
沉重的呼吸2016年

@HeavyBreathing我已经阅读了答案,但对于“嵌套CV之后该怎么办”,我仍然不清楚。您清楚地知道了吗?
stackunderflow

0

我已经阅读了您的问题和答案超过2次(3个月前第一次)。我很感兴趣,也想找到一种绝对合适的方法对我的数据进行交叉验证。经过大量的思考和阅读,似乎我找到了漏洞,这是我的解决方法:

为了解释我的困惑,让我尝试逐步使用嵌套交叉验证方法进行模型选择。

  1. 使用K折创建外部CV循环。这将用于估计“赢得”每个内部CV循环的超参数的性能。
  2. 使用GridSearchCV创建一个内部CV循环,其中在每个内部循环中,GSCV都会遍历参数空间的所有可能组合,并提供最佳的参数集。(注意:这里我假设:内循环的数据=外循环的训练数据。您可能会问:为什么?答案:https//stackoverflow.com/questions/42228735/scikit-learn-gridsearchcv-with-multiple-repeats/ 42230764#42230764阅读Vivek Kumar步骤4的答案部分)
  3. 在GSCV在内部循环中找到“最佳参数”(我们称其为“内部优胜者”)后,将使用外部循环中的测试集对其进行测试,以评估性能(我们将其称为“ outer_fold_score1”)。
  4. 然后,外部循环将更新为测试集的下一个折叠,将其余部分更新为训练集(以评估外部循环的“内部获胜者”),再次使用新的测试集(outer_fold_score2)测试“内部获胜者”。然后,外循环再次更新到下一个折叠,直到循环完成。每个折叠的得分(outer_fold_score 1,2 ..)将取平均值,以获得外循环(outer_score)的“内部获胜者”得分
  5. 然后,外部循环将更新为测试集的下一个折叠,将其余部分更新为训练集(以查找下一个“内部获胜者”,并重复1-4次(请注意,当我们重复1次时,我们不会创建新的K-折叠,但我们每次都使用相同的外部Kfold)。在1-4个周期的每个周期中,我们会获得一个带有external_score的“最佳参数”(或“内部获胜者”)。优胜者

推理:

  • 基本上,您的问题涉及到外循环有许多“获胜参数”。问题是您没有完成评估和找到“外部优胜者”的外部循环。您的第4步仅在外部循环中以1倍的方式评估“内部获胜者”,但您没有“循环”。因此,我需要将其替换为我的第4步-在外部循环中“循环”评估步骤并获得外部得分(通过平均)
  • 您的第五步确实在外循环中完成了“循环”工作,但这仅是为了建立另一个“内在胜利者”。它没有在外部循环中循环此“内部获胜者”的“评估”

这真的回答了这个问题吗?
Michael R. Chernick

0


d 一组预处理转换,特征以及最后的超参数值。

Xÿ
XXÿ

XÿXÿ

所有数据以选择要使用的功能。因此,即使您在步骤2中进行了交叉验证,在每次交叉验证运行时,功能都已经看到并记住了测试折叠中的一些信息。结果将是对测试错误的过度乐观估计,这称为特征选择偏差。为了在您的估计中考虑到这一点,您需要将特征选择步骤放在步骤2的交叉验证循环中。
好,现在好了吗?在循环内与特征选择步骤进行交叉验证中发现的最佳错误是对泛化错误的合理估计吗?
从理论上讲答案仍然是,问题在于您已经选择了超级参数,以最大程度地减少对特定数据集的交叉验证错误,因此从某种意义上讲,您正在将超级参数与数据拟合,但存在过度拟合的风险,这称为模型选择偏差。但这在实践中是否值得关注?这取决于特定的应用:当数据集较小且要调整的超参数数量相对较大时,由于过度拟合训练,可能会变得更加严重。为了在估算泛化误差时考虑到这一点,您将按照您的描述应用嵌套的交叉验证,然后可以为您正确估计泛化误差。
最后回答最后一个问题,通过嵌套交叉验证对“模型构建过程”泛化错误进行合理估计后,您只需将过程(步骤1 + 2)应用于整个数据集即可获得具有固定集的模型并设置超参数值,但请记住,我们希望该模型在看不见的数据上出现的错误是嵌套的交叉验证估计值

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.