如何分割数据集以进行交叉验证,学习曲线和最终评估?


69

分割数据集的合适策略是什么?

我要求反馈对以下方法(不是像个别参数test_sizen_iter,但如果我用XyX_trainy_trainX_test,和y_test适当的,如果顺序是有道理的):

(从scikit-learn文档扩展示例)

1.加载数据集

from sklearn.datasets import load_digits
digits = load_digits()
X, y = digits.data, digits.target

2.分为训练和测试集(例如80/20)

from sklearn.cross_validation import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)

3.选择估算器

from sklearn.svm import SVC
estimator = SVC(kernel='linear')

4.选择交叉验证迭代器

from sklearn.cross_validation import ShuffleSplit
cv = ShuffleSplit(X_train.shape[0], n_iter=10, test_size=0.2, random_state=0)

5.调整超参数

训练集上应用交叉验证迭代器

from sklearn.grid_search import GridSearchCV
import numpy as np
gammas = np.logspace(-6, -1, 10)
classifier = GridSearchCV(estimator=estimator, cv=cv, param_grid=dict(gamma=gammas))
classifier.fit(X_train, y_train)

6.具有学习曲线的调试算法

X_train被随机分为训练和测试集10次(n_iter=10)。训练得分曲线上的每个点都是10个分数的平均值,在第一个i训练示例中对模型进行了训练和评估。交叉验证得分曲线上的每个点是10个得分的平均值,在该模型中,在前i个训练示例上对模型进行了训练,并在测试集的所有示例上进行了评估。

from sklearn.learning_curve import learning_curve
title = 'Learning Curves (SVM, linear kernel, $\gamma=%.6f$)' %classifier.best_estimator_.gamma
estimator = SVC(kernel='linear', gamma=classifier.best_estimator_.gamma)
plot_learning_curve(estimator, title, X_train, y_train, cv=cv)
plt.show()

学习曲线

在scikit-learn的当前开发版本(0.15-git)中可以找到plot_learning_curve()。

7.对测试集的最终评估

classifier.score(X_test, y_test)

7a。使用嵌套交叉验证(使用整个数据集)测试模型选择中的过拟合

from sklearn.cross_validation import cross_val_score
cross_val_score(classifier, X, y)

附加问题: 用嵌套交叉验证替换步骤7是否有意义?还是应该将嵌套的简历视为对步骤7的补充

(该代码似乎可以在scikit-learn中进行k倍交叉验证,但不能与shuffle和split一起使用。因此cv需要在上面进行更改以使代码起作用)

8.在整个数据集上训练最终模型

classifier.fit(X, y)

编辑:我现在同意cbeleites,步骤7a在此序列中没有多大意义。所以我不会采纳。


您使用哪种精度评分规则?如果是分类准确性,那么这种不正确的评分规则将使您去做的许多工作都无法完成。
Frank Harrell 2014年

我使用了默认值,即分类精度。我知道,例如F1会更合适。但是在这里我只是想知道是否可以使用拆分。
2014年

3
我几乎可以肯定F1是旧概念的新名称。我认为为旧事物发明新名称会适得其反。更重要的是,这是一个不正确的评分规则,将导致选择错误的功能,并在整个过程中增加大量噪音。
弗兰克·哈雷尔

3
...在任何情况下,F1都存在准确性问题@FrankHarrell暗示:这些源于对硬分类测试用例的分数进行计数。要获得Frank正确的评分规则之一,您需要切换到SVM的概率输出,然后例如使用Brier评分(均方误差)代替准确性。我想您也可以衍生出F1的MSE型版本。对于调音步骤,此类措施的确应该更好。为了传达最终表现,您可能还需要典型的方式(例如准确性,F1)来表达您所在社区的表现。
cbeleites

1
@ ta.ft:方法是否错误取决于您认为错误的原因:按比例进行格网搜索存在撇除方差的严重风险,除非您有大量的独立案例。因此,在许多情况下,网格搜索产生最佳模型的说法是错误的。但是,如果您执行适当的嵌套验证,则外部验证会诚实地衡量所选“最佳”模型的性能。因此,这没有错。您只是不能保证网格搜索得到了最佳模型。至于文学,我将更新答案。
cbeleites 2014年

Answers:


41

我不确定在步骤7a中要做什么。据我目前了解,这对我来说毫无意义。

这就是我对您的描述的理解方式:在第7步中,您要将保持性能与包含第4步至第6步的交叉验证的结果进行比较(是的,这将是嵌套设置)。

我认为这种比较没有意义的要点是:

  • 这种比较无法检测到我在实践中遇到的过乐观验证结果的两个主要来源:

    • 训练数据与测试数据之间的数据泄漏(依赖性),这是由分层(又称为群集)数据结构引起的,并且在拆分时未考虑在内。在我的领域,我们通常是同一患者或实验的生物学复制品的多个读数(有时是数千个)(数据矩阵中的行)。这些不是独立的,因此验证拆分需要在患者级别进行。但是,会发生这种数据泄漏,您将在保留集的拆分和交叉验证拆分中同时使用它。然后,与交叉验证一样,乐观的偏见也会出现。

    • 在整个数据矩阵上完成数据的预处理,其中计算不是针对每一行而是许多/所有行都用于计算预处理参数。典型示例将是例如“实际”分类之前的PCA投影。
      同样,这将影响您的保留和外部交叉验证,因此您无法检测到它。

    对于我使用的数据,两个错误都容易导致错误分类的比例被低估了一个数量级!

  • 如果您限于测试用例的这种类型的性能类型,则模型比较需要非常大量的测试用例或真实性能上的可笑的巨大差异。比较2个分类器和无限制的训练数据可能是进一步阅读的良好开端。

但是,将模型质量与“最佳”模型的内部交叉验证声明和外部交叉验证或坚持验证进行比较确实有意义:如果差异很大,则网格搜索优化是否有效就值得怀疑(您可能有由于绩效指标的高差异而产生的撇除差异)。这种比较比较容易,因为如果您的内部估算值比其他估算值要好得多,那么您就可以发现问题-如果不是,则不必担心优化。但是无论如何,如果您对性能的外部(7)度量是诚实和合理的,则无论是最佳模型还是非最佳模型,您至少都有一个有用的估计。

恕我直言,测量学习曲线仍然是另一个问题。我可能会分别处理,我认为您需要更清楚地定义学习曲线的用途(对于给定问题,数据和分类方法数据集还是学习曲线,是否需要学习曲线?对于这个数据集给定的问题,数据和分类mehtod),以及一堆的进一步决定(例如,如何处理作为训练样本大小的函数模型的复杂性?优化一遍,使用固定的超参数,决定根据训练集大小来修复超参数的功能?)

(我的数据通常只有很少的独立案例,无法获得足够精确的学习曲线测量结果以在实践中使用它-但如果您的1200行实际上是独立的,则可能会更好一些)


更新:scikit-learn示例的“错误”是什么?

首先,这里的嵌套交叉验证没有错。嵌套验证对于数据驱动的优化至关重要,而交叉验证是一种非常强大的方法(尤其是在重复/重复的情况下)。

然后,是否有任何问题完全取决于您的观点:只要您执行诚实的嵌套验证(严格保持外部测试数据独立),外部验证就可以正确衡量“最佳”模型的性能。没有错。

但是,对这些比例类型的性能度量进行网格搜索以支持SVM的超参数调整时,可能会发生某些事情并且确实会出错。基本上,它们意味着您可能(可能?)不能依靠优化。但是,只要外部拆分正确,即使模型不是最佳模型,您也可以诚实地估计所获得模型的性能。

我将尝试给出直观的解释,说明为什么优化可能会遇到麻烦:

  • p^ñp
    V一种[Rp^=p1个-pñ

    您需要大量的案例(至少与我通常可以处理的案例数量相比),以达到估计召回率所需的精度(偏差/方差意义)(精度/机器学习性能意义)。当然,这也适用于从这些比例计算出的比例。看看二项式比例的置信区间。它们大得惊人!通常比在超参数网格上的性能真正提高要大。从统计学上讲,网格搜索是一个巨大的多重比较问题:您评估的网格点越多,找到一些超参数组合的风险就越高,而这些组合对于您正在评估的火车/测试区意外看起来非常好。这就是我所说的略读差异。

  • 凭直觉考虑一下超参数的假设变化,该变化缓慢地导致模型恶化:一个测试用例向决策边界移动。除非案例越过边界并站在错误的一侧,否则“硬性”比例性能度量不会检测到此情况。然后,他们立即为超参数中的无限小变化分配一个完全错误。
    为了进行数值优化,您需要性能表现良好。这意味着:比例类型的性能度量的跃变(不可连续微分)部分或除跃变以外未检测到实际发生的变化的事实都不适合优化。
    以特别适合优化的方式定义正确的评分规则。当预测概率与每个案例属于所讨论类别的真实概率匹配时,它们具有全局最大值。

  • 对于SVM,您还有一个额外的问题,即不仅性能指标而且模型都以这种快速的方式做出反应:超参数的微小变化不会改变任何东西。仅当超参数的更改足以导致某种情况停止成为支持向量或成为支持向量时,模型才会更改。同样,这种模型很难优化。

文献:


更新二:略读差异

在模型比较方面您可以负担的费用显然取决于独立案例的数量。让我们在这里对撇取差异的风险进行一些快速而肮脏的仿真:

scikit.learn说他们有1797个digits数据。

  • 10×10
  • 假设两个参数(范围)完全不影响模型,
  • 也就是说,所有模型都具有相同的真实性能,例如97%(digits数据集的典型性能)。

  • 104digits

    p.true = 0.97 # hypothetical true performance for all models
    n.models = 100 # 10 x 10 grid
    
    n.rows = 1797 # rows in scikit digits data
    
    sim.test <- replicate (expr= rbinom (n= nmodels, size= n.rows, prob= p.true), 
                           n = 1e4)
    sim.test <- colMaxs (sim.test) # take best model
    
    hist (sim.test / n.rows, 
          breaks = (round (p.true * n.rows) : n.rows) / n.rows + 1 / 2 / n.rows, 
          col = "black", main = 'Distribution max. observed performance',
          xlab = "max. observed performance", ylab = "n runs")
    abline (v = p.outer, col = "red")

这是获得最佳观察性能的分布:

撇除方差模拟

红线表示我们所有假设模型的真实性能。平均而言,对于100个比较模型中看似最好的模型,我们仅观察到真实错误率的2/3(对于仿真,我们知道它们在97%正确的预测下均表现相同)。

该模拟显然已大大简化:

  • 除了测试样本大小的差异外,至少还有由于模型不稳定性引起的差异,因此我们在这里低估了差异
  • 影响模型复杂度的调整参数通常将覆盖模型不稳定且因此具有较高方差的参数集。
  • 对于该示例中的UCI数字,原始数据库的ca为。由44个人书写的11000位数字。如果数据是根据编写者聚类的,该怎么办?(即,如果您知道某人写的8,则更容易识别该人写的数字,例如3?)。那么有效样本量可能低至44。
  • 调整模型的超参数可能会导致模型之间的相关性(实际上,从数值优化的角度来看,这将被认为表现良好)。很难预测其影响(并且我怀疑如果不考虑分类器的实际类型,这是不可能的)。

但是,总的来说,独立测试用例数量少和模型比较多都会增加偏差。同样,Cawley和Talbot的论文给出了经验观察到的行为。


@cbleites:如果网格搜索可能不是寻找最佳模型的合适方法,那我应该选择哪种方法?
tobip

1
@ ta.ft:两种方法是:a)将与您的应用程序和数据有关的大量外部知识整合到建模中,以大幅度减少需要比较的模型数量(=确定超参数而不是优化)。总体上,最好改用具有本质上有意义的超参数的分类器,即从应用程序和数据类型中可以知道(大概)超参数应该是什么。b)通过适当的评分规则比较剩余的几个模型。例如,对于许多分类器,Briers分数具有更好的方差属性。
cbeleites 2014年

1
您也可以完全拒绝优化(通过决策(a))。如果您获得了足够好的分类器,并且可以说在给定可用样本量的情况下没有机会证明另一个分类器的优越性(例如,进行一些麦克尼玛演示计算,请查找必要的样本量以进行假设比较更好的分类器进行比例比较-有即使对于相当大的假设性改进,这些可能性也将非常大),您可以辩称优化没有任何意义,只会带来过度拟合的风险。
cbeleites 2014年

我不同意“略读差异”。如果您在网格中有很多要进行超参数优化的点,那么一个点可能会在CV的一倍之内时机获得幸运;但是,如果您拥有10折CV,那么仍然不可能在所有10折CV上偶然获得一组参数。
2014年

1
@RNA:在所有倍数中“幸运”的概率与病例总数(在所有10倍数中)直接相关,通常仅考虑所有这些倍数的平均值。我通过对100个模型中最好的模型进行了模拟(例如,2个超参数,每个10个步骤)进行了模拟,从而更新了答案,这已经与示例场景中的偏差有关(错误率太低了1/3) 。这里的许多人很少手头有几千个独立案例-例如,我什至没有44个为完整的UCI数字数据集写数字的人。
cbeleites 2014年
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.