Machine learning 特征选择应该在列车测试拆分之前还是之后进行?

Machine learning 特征选择应该在列车测试拆分之前还是之后进行?,machine-learning,feature-selection,train-test-split,Machine Learning,Feature Selection,Train Test Split,事实上,有两个事实相互矛盾,这两个事实是问题的可能答案: 传统的解决方法是在分割之后进行,因为如果在分割之前进行,可能会从测试集中泄漏信息 相反的答案是,如果只使用从整个数据集中选择的训练集进行特征选择,那么特征选择或特征重要性得分顺序可能会随着训练测试分割的随机状态的变化而动态变化。如果任何特定工作的特征选择发生变化,则无法对特征重要性进行概括,这是不可取的。其次,如果仅使用训练集进行特征选择,则测试集可能包含某些实例集,这些实例集与仅在训练集上进行的特征选择相矛盾,因为未分析总体历史数据。此

事实上,有两个事实相互矛盾,这两个事实是问题的可能答案:

  • 传统的解决方法是在分割之后进行,因为如果在分割之前进行,可能会从测试集中泄漏信息

  • 相反的答案是,如果只使用从整个数据集中选择的训练集进行特征选择,那么特征选择或特征重要性得分顺序可能会随着训练测试分割的随机状态的变化而动态变化。如果任何特定工作的特征选择发生变化,则无法对特征重要性进行概括,这是不可取的。其次,如果仅使用训练集进行特征选择,则测试集可能包含某些实例集,这些实例集与仅在训练集上进行的特征选择相矛盾,因为未分析总体历史数据。此外,仅当给定一组实例而不是单个测试/未知实例时,才能评估特征重要性分数

  • 传统的答案#1在这里是正确的;自相矛盾的答案2中的论点实际上并不成立

    当有这样的疑问时,可以想象在模型拟合过程中,您在任何测试集中都没有任何访问权限(包括特征重要性);您应该将测试集视为字面上看不见的数据(而且,因为看不见,所以它们不能用于特征重要性分数)

    Hastine和Tibshirani很久以前就明确提出了执行此类流程的正确和错误方法;我在一篇博客文章中总结了这个问题,虽然讨论的是交叉验证,但可以很容易地看出,这些论点也适用于训练/测试分离的情况

    在你自相矛盾的答案2中,唯一的论点是

    未对总体历史数据进行分析

    然而,这是为了有一个独立的测试集进行性能评估而必须付出的代价,否则,按照同样的逻辑,我们也应该使用测试集进行培训,不是吗


    总结:测试集仅用于模型的性能评估,不应用于模型构建的任何阶段,包括特征选择

    更新(评论后):

    测试集的趋势可能不同

    这里的一个标准(但通常是隐含的)假设是,训练集和测试集在质量上是相似的;正是由于这个假设,我们觉得可以使用简单的随机拆分来获得它们。如果我们有理由相信我们的数据在很大程度上发生了变化(不仅在训练和测试之间,而且在模型部署过程中),那么整个理论基础就会崩溃,需要完全不同的方法

    此外,在这样做时,可能存在过拟合的高概率

    唯一的特定的过拟合方法是在管道过程中以任何方式使用测试集(包括您建议的特征选择)。可以说,链接的博客文章有足够的理由(包括引用和链接)令人信服。经典例子,证词如下:

    随着比赛的进行,我开始使用更多的特征选择和预处理。然而,我在交叉验证方法中犯了一个典型错误,没有将其包括在交叉验证折叠中(有关此错误的更多信息,请参阅或中的第7.10.2节)。这导致交叉验证估计越来越乐观

    正如我已经说过的,尽管这里的讨论是关于交叉验证的,但要说服自己它也完全适用于列车/测试用例应该不难

    特征选择应以增强模型性能的方式进行

    当然,没有人能反驳这一点!关键是——我们谈论的是哪种准确的表现?因为上面引用的Kaggler在进行过程中确实获得了更好的“性能”(应用了一个错误的程序),直到他的模型面对真实的、看不见的数据(真相时刻!),并且不出所料地失败了


    诚然,这不是一件小事,可能需要一段时间才能将其内化(正如黑斯蒂和蒂布什拉尼所证明的,甚至有研究论文错误地执行了这一过程,这并非巧合)。在那之前,我的安全建议是:在模型构建的所有阶段(包括特征选择),假装你根本无法访问测试集,只有当您需要评估您的最终模型的性能时,它才可用。

    事实上,不难证明为什么使用整个数据集(即,在分割到训练/测试之前)来选择功能会让您误入歧途。下面是一个使用Python和scikit learn的随机虚拟数据的演示:

    将numpy导入为np
    从sklearn.feature\u选择导入SelectKBest
    从sklearn.model\u选择导入列车\u测试\u拆分
    从sklearn.linear_模型导入逻辑回归
    从sklearn.metrics导入准确性\u分数
    #随机数据:
    X=np.random.randn(50010000)
    y=np.随机选择(2,尺寸=500)
    
    由于我们的数据
    X
    是随机的(500个样本,10000个特征),并且我们的标签
    y
    是二进制的,因此我们预计我们永远不能超过这种设置的基线精度,即约0.5,或约50%。让我们看看在分割之前,当我们使用整个数据集进行特征选择的错误的过程时会发生什么:

    selector=SelectKBest(k=25)
    #首先选择功能
    X_selected=选择器。拟合_变换(X,y)
    #然后分开
    X_选择_序列,X_选择_测试,y_序列,y_测试=序列测试_分割(X_选择,y,测试_大小=0.25,随机_状态=42)