Cell 子刊 | 避免常见的机器学习陷阱

图片

大背景

机器学习已经从一项小众追求转变为具有广泛吸引力的活动。得益于现代机器学习工具的易用性,现在很容易开启机器学习,但这种易用性掩盖了进行机器学习的底层复杂性。这一点,加上实践者群体相对经验不足,导致了有缺陷的实践,这反映在诸如基于机器学习的研究可重复性差等问题中。   

本教程旨在通过教育实践者了解应用机器学习时可能出错的许多问题,并提供如何避免这些陷阱的指导,来解决这个问题。然而,这只是改善实践所需长期过程的一部分,因为机器学习只有能够成为一个稳健且可信的应用学科,才能实现其雄心壮志。在此过程中发挥作用的其他因素包括更好的工具、标准化和监管。    

摘要

机器学习实践中的错误很常见,并可能导致人们对机器学习发现和产品失去信心。本教程概述了使用机器学习时发生的常见错误以及如何避免这些错误。虽然它应该对任何具备基本机器学习技术理解能力的人开放,但它重点关注学术研究中特别关注的问题,例如需要进行严格的比较并得出有效的结论。它涵盖了机器学习过程的五个阶段:模型构建前该做什么,如何可靠地构建模型,如何稳健地评估模型,如何公平地比较模型,以及如何报告结果。        

介绍

应用机器学习(ML)时很容易出错,这些错误可能导致 ML 模型在训练和测试期间面对未见过的数据时无法按预期工作。这对实践者来说是一个问题,因为它会导致 ML 项目的失败。然而,这对社会也是一个问题,因为它侵蚀了人们对 ML到来的发现和产品的信任。    

本指南旨在帮助初学者避免其中的一些错误。它由一位学者撰写,重点关注在学术界进行 ML 研究时获得的经验教训。虽然主要面向学生和科研人员,但任何人都可以理解并使用它,而且它仅假定使用者具备基本的机器学习技术知识。然而,与面向更广泛受众的类似指南不同,它包含了学术界特别关注的主题,例如需要严格评估和比较模型以便发表工作。    

为了提高可读性,指导是以非正式的 “应做与不应做” 的风格编写的。它并非详尽无遗,并提供了参考文献以供进一步阅读;对于有访问限制的出版物,在可能的情况下也包含了预印本的引用。由于它不涵盖特定学术科目的具体问题,建议读者在可能的情况下也查阅特定学科的指导,例如临床医学、基因组学、环境研究、材料科学、商业和营销、计算机安全和社会科学。   

本教程分为五个部分。

“在你开始构建模型之前” 涵盖了机器学习( ML) 过程早期可能出现的问题,并侧重于数据的正确使用以及充分考虑到应用 ML 的背景。

“如何可靠地构建模型” 接着涵盖了在模型及其组件的选择和训练期间发生的陷阱。

“如何稳健地评估模型” 介绍了可能导致对模型性能错误理解的陷阱。

“如何公平地比较模型” 然后将此扩展到模型比较的情况,讨论常见陷阱如何导致误导性的发现。

“如何报告你的结果” 侧重于可重复性以及可能导致报告不完整或具有欺骗性的因素。    

ML 陷阱并非一成不变,而是随着 ML 的发展而不断演变。为了解决这个问题,本教程的预印版自 2021 年首次发布以来每年更新,未来也将继续更新。   

在你开始构建模型之前

想要迅速开展模型的训练与评估工作是很正常的,但花时间思考项目的目标、充分理解将用于支持这些目标的数据、考虑需要解决的数据的任何限制,并了解你所在领域已经做了什么,这很重要。如果你不做这些事情,那么你可能会得到难以发表的结果或不适合其预期目的的模型。       

务必考虑你将如何以及在何处使用数据

数据对于大多数机器学习( ML) 项目至关重要,但往往供应不足。因此,仔细考虑你需要什么数据以及你将如何和在何处使用它们很重要。抽象地说,你需要数据做两件事:训练模型和测试模型。然而,由于各种原因,这并不一定意味着使用一个分成两部分的数据集。首先,模型开发通常涉及一个实验阶段:尝试不同的模型、不同的超参数,并以不同的方式预处理数据。为了避免过拟合(参见”务必避免过拟合”),这个过程需要一个单独的验证集,即一个额外的数据集,不直接用于训练或测试模型。如果你对要使用什么建模方法没有先验想法,那么这个实验阶段可能涉及大量的比较。由于多重性效应(参见”务必对多重比较进行校正”),你做的比较越多,你就越有可能过拟合验证数据,导致验证集在指导你建模决策方面的作用就会越小。所以,在实践中,你可能需要为此留出多个验证集。然后,还有一个问题是如何充分测试你选定的模型。因为与训练数据存在相同的偏差,一个从与训练数据相同的数据集中提取的测试集可能不足以衡量模型的普遍性——关于这方面的更多内容,请参见”务必使用适当的测试集”和”务必以多种方式报告性能”——这意味着,在实践中,你可能需要不止一个测试数据集来稳健地评估你的模型。另外,请注意,在使用交叉验证(CV)时,你通常需要额外的测试数据;参见”务必保留一些数据来评估你的最终模型实例”。    

务必花时间理解你的数据

最终,你会希望发表你的工作。如果你的数据来自可靠的来源,使用可靠的方法收集,并且质量良好,那么发表会容易得多。例如,如果你使用的是从互联网资源收集的数据,请确保你知道它们来自哪里。它们在某篇论文中描述过吗?如果是,看看那篇论文;确保它发表在某个声誉良好的地方,并检查作者是否提到了数据的任何局限性。不要以为因为一个数据集已经被许多论文使用过,它就是高质量的——有时数据被使用仅仅是因为它们容易获得,而且一些广泛使用的数据集已知有明显的局限性(Paulada 等人对此进行了讨论)。如果你使用糟糕的数据训练你的模型,那么你很可能会生成一个糟糕的模型:这个过程被称为”垃圾进,垃圾出”。避免糟糕数据集的一种方法是与生成数据的人建立直接关系,因为这增加了获得高质量数据集满足您需求的可能性。这也避免了过拟合社区基准测试的问题;参见”不要总是相信社区基准测试的结果”。然而,无论你的数据来自哪里,总是要从确保你的数据有意义开始。做一些探索性数据分析(参见 Cox 的建议)。查找缺失或不一致的记录。现在,在你训练模型之前做这件事要容易得多,而不是等到以后,当你试图向审稿人解释你为什么使用了糟糕的数据时。    

不要查看所有数据

当你查看数据时,你很可能会发现模式并产生指导建模的见解。这是查看数据的另一个好理由。然而,重要的是你不要做出不可检验的假设,这些假设随后会输入到你的模型中。”不可检验”这一点在这里很重要;做出假设是可以的,但这些假设只应该输入到模型的训练中,而不是测试中。因此,为了确保这一点,你应该避免在初始探索性分析阶段查看任何测试数据。否则,你可能有意识或无意识地做出以不可检验的方式限制模型普遍性的假设。这是我将会多次回归的一个主题,因为信息从测试集泄漏到训练过程是 ML 模型无法泛化的常见原因。关于这方面的更多内容,请参见”不要让测试数据泄漏到训练过程中”。  

务必清理你的数据

即使是高质量的数据集也会有问题。其中一些问题源于数据收集过程中不可避免的噪声或遗漏,而另一些则是由于收集或整理过程中的人为错误。无论原因如何,重要的是识别所有问题,并在你开始构建模型之前完成。需要注意的一个常见问题是数据重复,即无意中包含一个数据点的多个副本。这在评估模型时会导致严重的问题(例如,参见”不要在对数据进行分割之前进行数据增强”),因此应尽早识别和删除。另一个常见的问题是缺失值。一些模型可以处理这些值,但许多不能,所以你必须在训练之前用其他东西替换缺失值。有多种形式的插补方法可用于实现这一点;参见 Emmanuel 等人的综述。如果你进行插补,请注意避免插补过程中的数据泄漏——参见”不要让测试数据泄漏到训练过程中”。你还应该检查数据中的异常值,但只有在它们可能是噪声或错误的结果,而不是底层数据生成过程的自然极端值时,才将其移除。例如,如果一个人的年龄大于 150,那可能是个错误;如果是 110,那可能是一个自然的异常值。一个相关的问题是无意义或不一致的数据,例如一个年龄为负的人。数据清理可能是一个耗时的过程,并且随着数据复杂性的增加而更具挑战性。因此,许多人探索了使用 ML 方法自动化数据清理;参见 Côté 等人的综述。    

务必确保你有足够的数据

如果你没有足够的数据,那么可能无法训练出能够泛化的模型。要确定这种情况是否属实可能会比较困难,并且可能直到你开始构建模型时才显现:这完全取决于数据集中的信噪比如果信号强,那么你可以用较少的数据应付;如果信号弱,那么你需要更多的数据。如果你无法获得更多数据——这是许多研究领域的常见问题——那么你可以尝试使用数据增强技术(参见 Wang 等人,以及针对时间序列数据的 Iglesias 等人)。这些方法对于提升小型数据集可能非常有效,但不要在对数据进行分割之前进行数据增强。数据增强在数据集中某些部分数据有限的情况下也很有用,例如,在分类问题中,某些类别的样本少于其他类别,这种情况称为类别不平衡。关于处理此问题的方法的综述,请参见 Haixiang 等人;另见”务必仔细选择指标”。处理小数据集的另一个选择是使用迁移学习——参见”务必跟上深度学习(及其陷阱)的进展”。使用小数据集的一个危险是不同的数据拆分可能存在偏差,例如在数据质量或难度方面。因此,建议考虑频繁的重新拆分。交叉验证(CV)(参见”务必多次评估模型”)是在小数据集中实现这一点的有效方法。如果你的数据有限,那么你可能还必须限制你使用的 ML 模型的复杂性,因为具有许多参数的模型,如深度神经网络,很容易过拟合小数据集(参见”不要假设深度学习将是最好的方法”)。无论你如何处理数据有限的问题,重要的是尽早识别这个问题并提出合适的策略来缓解它。     

务必与领域专家交流

领域专家非常有价值。他们可以帮助你理解哪些问题值得解决,选择最合适的特征集和 ML 模型来使用,并向最合适的受众发表成果。未能考虑领域专家的意见可能导致项目未能解决有用的问题,或者以不适当的方式解决有用的问题。后者的一个例子是使用不透明的 ML 模型来解决一个问题,而这个问题非常需要理解模型如何得出结果,例如,在做出医疗或财务决策时。在项目开始时,领域专家可以帮助你理解数据,并指出可能具有预测性的特征。在项目结束时,他们可以帮助你在特定领域的期刊上发表,从而让最可能从你的研究中受益的受众看到。    

务必进行文献调研

你可能不是第一个在特定问题领域应用 ML 的人,因此了解先前已经做了什么和没做什么很重要。其他人研究过同样的问题并不是坏事;学术进步通常是一个迭代过程,每项研究都提供可以指导下一步的信息。发现有人已经探索了你的好想法可能令人沮丧,但他们很可能留下了许多尚待研究的途径,而他们先前的工作可以作为你工作的理由。忽略先前的研究可能会错过有价值的信息。例如,可能之前有人尝试过你提出的方法,并发现了它行不通的根本原因(从而为你节省了几年的挫败感),或者他们可能以你可以借鉴的方式部分解决了问题。所以,在开始工作之前进行文献综述很重要;做得太晚可能意味着当你撰写论文时,你会手忙脚乱地解释为什么你在覆盖相同的内容或者没有基于现有知识。   

务必考虑你的模型将如何部署

你为什么要构建一个 ML 模型?这是一个重要的问题,答案应该影响你开发模型的过程。许多学术研究仅仅就是研究,并不真正旨在产生将在现实世界中使用的模型。这完全可以接受,因为构建和分析模型的过程本身就能为问题提供非常有用的见解。然而,对于许多学术研究来说,最终目标是产生一个可以在现实世界情况中部署的 ML 模型。如果是这种情况,那么值得尽早考虑它将如何部署。例如,如果它将在资源有限的环境中部署,例如传感器或机器人,那么这可能对模型的复杂性施加限制。如果有时间限制,例如需要在毫秒内对信号进行分类,那么在选择模型时也需要考虑到这一点。如果使用深度学习,那么能源成本和碳足迹可能需要考虑;如果使用大型语言模型(LLMs),托管或访问基础模型可能会有进一步的操作成本。另一个考虑因素是模型将如何集成到部署它的更广泛的软件系统中;这个过程通常远远不简单。然而,诸如 ML Ops 等新兴方法旨在解决其中一些困难;关于综述请参见 Kreuzberger 等人,关于在使 ML 模型付诸实践时常见挑战的讨论请参见 Shankar 等人。    

如何可靠地构建模型

构建模型是 ML 中较有趣的部分之一。借助现代 ML 框架,很容易将各种方法应用于你的数据,看看哪些方法奏效。然而,这可能导致实验杂乱无章,难以论证和撰写报告。因此,以有条理的方式进行模型构建很重要,确保你正确使用数据,并在模型选择上给予充分考虑。   

不要让测试数据泄漏到训练过程中

拥有可以用来衡量模型泛化能力的数据是至关重要的。一个常见的问题在于,有关这些数据的信息会泄露到模型的配置、训练或选择过程中。(见图1)。当这种情况发生时,数据不再提供可靠的泛化度量,这是已发表的 ML 模型经常无法泛化到现实世界数据的常见原因。信息从测试集泄漏有多种方式。其中一些看似相当无害。例如,在数据准备期间,当使用整个数据集中变量的均值和范围信息来进行变量缩放或插补时——为了防止信息泄漏,这些统计数据应该仅使用训练数据计算。信息泄漏的其他常见例子包括:在划分数据之前进行特征选择(参见”务必小心在何处及如何进行特征选择”),使用相同的测试数据评估多个模型的泛化能力(参见”务必避免顺序过拟合”和”不要总是相信社区基准的结果”),以及在分割出测试数据之前应用数据增强(参见”不要在对数据进行分割之前进行数据增强”)。你能做的最好的事情来防止这些问题是在项目一开始就划分出数据的一个子集,并且仅在项目结束时使用这个独立的测试集一次来衡量单个模型的泛化能力(参见”务必保留一些数据来评估你的最终模型实例”)。还有特定于某些类型数据的数据泄漏形式。时间序列数据尤其成问题,因为样本的顺序很重要,随机划分很容易导致泄漏和过拟合——关于这方面的更多内容,请参见”不要忽视时间序列数据中的时间依赖性”。即使对于非时间序列数据,用于生成数据集的实验条件也可能导致时间依赖性或其他有问题的情况,如重复或相似的样本——一个例子参见”务必使用适当的测试集”。为了防止泄漏,在划分数据时需要识别并考虑这些类型的问题。关于数据泄漏的更广泛讨论,请参见 Kapoor 和 Narayanan。    

图片

务必尝试一系列不同的模型

一般来说,没有所谓单一的”最佳” ML 模型。事实上,有证据以”没有免费午餐”定理的形式证明了这一点,该定理表明,当考虑所有可能的问题时,没有任何 ML 方法比其他方法更好。所以,你的工作是找到对你的特定问题效果好的 ML 模型。对此有一些指导。例如,你可以考虑 ML 模型的归纳偏置,即它们能够建模的关系类型。例如,线性模型,如线性回归和逻辑回归,如果你知道数据特征之间没有重要的非线性关系,那么它们是一个好选择,否则就是一个糟糕的选择。关于密切相关问题的优质研究也可能指向效果特别好的模型。然而,很多时候,你仍然面临相当多的选择,而找出哪个模型最好的唯一方法就是尝试所有模型。幸运的是,现代 ML 库,如 Python 中的 scikit-learn、R 中的 tidymodels 和 Julia 中的 MLJ,允许你仅对代码进行少量更改就能尝试多种模型,因此没有理由不尝试所有模型并亲自找出哪一个效果最好。然而,不要使用不适当的模型,并使用验证集而不是测试集来评估它们(参见”务必避免顺序过拟合”)。在比较模型时,务必优化模型的超参数,多次评估模型以确保给它们所有人公平的机会,并在发表结果时对多重比较进行校正。   

不要使用不适当的模型

通过降低实现门槛,现代 ML 库也使得将不适当的模型应用于你的数据变得容易。反过来,当你试图发表结果时,这可能看起来很糟糕。一个简单的例子是将那些预期输入的是分类特征(categorical features)的模型应用于包含数值特征(numerical features)的数据集,反之亦然。一些 ML 库允许你这样做,但由于信息丢失,它可能会导致模型性能不佳。如果你真的想使用这样的模型,那么你应该首先转换特征;有多种方法可以做到这一点,从简单的独热编码到复杂的学习嵌入。其他不适当模型选择的例子包括:在回归模型更有意义的地方使用分类模型(反之亦然),试图将假设变量间无依赖关系的模型应用于时间序列数据,或者使用不必要的复杂模型(参见”不要假设深度学习将是最好的方法”)。此外,如果你计划在实践中使用你的模型,务必考虑你的模型将如何部署,不要使用不适合你的用例的模型。     

务必跟上深度学习(及其陷阱)的进展

虽然深度学习可能并不总是最佳解决方案(参见”不要假设深度学习将是最好的方法”),但如果你要使用深度学习,那么建议尝试跟上这个快速发展的领域的最新进展。图2 总结了一段时间以来的一些重要发展。多层感知机和循环神经网络(特别是长短期记忆 [LSTM])已经存在了一段时间,但很大程度上已经被更新的模型所取代,例如卷积神经网络(CNNs)和 Transformer。例如,Transformer 已成为处理序列数据(例如自然语言)的首选模型,并且越来越多地应用于其他数据类型,如图像。Transformer 和深度 CNN 的一个突出缺点是它们有很多参数,因此需要大量数据来训练它们。然而,对于小型数据集,一个选择是使用迁移学习,即模型在一个大型通用数据集上进行预训练,然后在感兴趣的数据集上进行微调。更大的预训练模型,其中许多在 Hugging Face 等网站上免费共享,被称为基础模型;参见 Zhou 等人的综述。虽然强大,但这些模型也伴随着自身的一系列陷阱。例如,它们完全记忆输入数据的能力是数据安全和隐私问题的原因。使用不透明、往往缺乏详细说明的训练数据集,在将其集成到更广泛的 ML 流程(更多信息参见”务必(小心地)组合模型”)以及公平地与其他 ML 模型进行比较(参见”不要认为更大的数字意味着更好的模型”和”不要总是相信社区基准的结果”)时也会导致陷阱。关于深度学习的广泛而易懂的指南,请参见 Zhang 等人。     

图片

不要假设深度学习将是最好的方法

一个常见的陷阱是假设深度神经网络将为任何问题提供最佳解决方案,从而未能尝试其他可能更合适的模型。虽然深度学习对于某些任务非常出色,但它并不擅长一切;有很多例子表明它被”老式” ML 模型(如随机森林和支持向量机 [SVMs])超越。例如,参见 Grinsztajn 等人,他们表明基于树的模型在表格数据上通常优于深度学习模型。某些类型的深度神经网络架构也可能不适合某些类型的数据:例如,参见 Zeng 等人,他们认为 Transformer 不太适合时间序列预测。理论上也有理由说明为什么任何一种模型不会总是最佳选择(参见”务必尝试一系列不同的模型”)。特别是,如果你数据有限、领域知识表明底层模式相当简单,或者模型需要可解释,那么深度神经网络不太可能是一个好的选择。最后一点特别值得考虑:深度神经网络本质上是一个非常复杂的决策制定过程,它从大量非线性函数之间的相互作用中产生。非线性函数在最佳情况下也难以理解,但当你开始将它们连接在一起时,它们的行为会变得非常复杂,瞬息万变。虽然可解释人工智能(XAI)方法(参见”务必查看你的模型”)可以揭示深度神经网络的一些工作原理,但它们也可能通过消除决策空间的真实复杂性而误导你。因此,在使用深度学习或 XAI 进行高风险或安全关键决策的模型时,你应该谨慎;更多内容请参见 Rudin。     

务必小心在何处及如何进行特征选择

训练模型的一个常见阶段是进行特征选择(Cai 等人综述)。在做这件事时,重要的是将其视为模型训练的一部分,而不是在模型训练之前做的更一般的事情。一个特别常见的错误是在分割出测试集之前对整个数据集进行特征选择,这将导致信息从测试集泄漏到训练过程中(参见”不要让测试数据泄漏到训练过程中”)。相反,你应该只使用训练集来选择在训练集和测试集中都要使用的特征(见图3)。在进行降维时也是如此。例如,如果你使用主成分分析,那么成分权重应仅通过查看训练数据来确定;然后应将相同的权重应用于测试集。使用自动编码器进行降维时应特别小心——参见”务必(小心地)组合模型”。如果你在进行 CV(交叉验证时)(参见”务必多次评估模型”),那么重要的是在每次迭代中独立进行特征选择或降维,每次仅使用训练折 (训练集中用于当前模型训练的部分)(见图3,底部)。
图片

务必优化模型的超参数

许多模型都有超参数——即影响模型配置的数字或设置。例子包括 SVM 中使用的核函数、随机森林中树的数量以及神经网络的架构。这些超参数中有许多会显著影响模型的性能,并且在选择超参数时通常没有一种”一刀切”的方法。也就是说,它们需要适应你的特定数据集,以便充分发挥模型的潜力。虽然你可能很想摆弄超参数,直到找到有效的东西,但这不太可能是最优的方法。最好是使用某种超参数优化策略,并且在撰写报告时也更容易证明其合理性。基本策略包括随机搜索和网格搜索,但这些方法在处理大量超参数或训练成本高的模型时扩展性不佳,因此值得使用以更智能的方式搜索最优配置的工具。进一步指导参见 Bischl 等人。除了 ML 流程的其他部分外,还可以使用 AutoML 技术来优化模型的选择及其超参数——参见 Barbudo 等人的综述。   

务必避免学习虚假相关性

虚假相关性是数据中与目标变量相关但没有语义含义的特征。它们本质上属于干扰因素,而且在训练过程中,机器学习模型往往会受到这些因素的影响,从而导致其泛化能力不佳。这种情况并不少见。一个经典的例子是坦克问题。传说美军曾希望训练一个能够识别坦克的 ML 模型(尽管对于此事是否真的发生存在一些争议)。然而,由于训练中使用的坦克图片是在与”非坦克”图片不同的天气条件下拍摄的,模型最终根据天空中的蓝色像素数量等特征进行区分,而不是根据坦克的存在(见图4说明)。使用这种虚假相关性进行分类的 ML 模型,其度量分数看起来会非常好,但在实践中行不通。更复杂的数据往往包含更多此类虚假相关性,而更复杂的模型有更大的能力过拟合虚假相关性。这意味着虚假相关性对于深度学习来说是一个特别的问题,其中正则化(参见”务必跟上深度学习(及其陷阱)的进展”)和数据增强(参见”务必确保你有足够的数据”)等方法可以帮助缓解这个问题。然而,虚假相关性可能出现在所有数据集和模型中,因此总值得查看你训练好的模型,看它是否在响应你数据中的适当特征——参见”务必查看你的模型”。
图片

如何稳健地评估模型

为了对你所在领域的进步做出贡献,你需要有有效的结果,并可以从中得出可靠的结论。不幸的是,对机器学习模型进行不公平的评估是非常容易的,而且这样做还会扰乱学术研究的进展进程。因此,仔细考虑你将如何在实验中使用数据,衡量模型的真实性能,并以有意义和信息丰富的方式报告这个性能。   

务必使用适当的测试集

首先,总是使用测试集来衡量 ML 模型的泛化能力。模型在训练集上的表现如何几乎毫无意义,一个足够复杂的模型可以完全学会训练集,却没有捕捉到任何可泛化的知识。确保测试集中的数据是适当的也很重要。也就是说,它们不应与训练集重叠,并且应能代表更广泛的总体。例如,考虑一个物体的摄影数据集,其中训练集和测试集中的图像都是在晴天户外收集的。相同天气条件的存在意味着测试集不是独立的,并且由于没有捕捉到更广泛的天气条件变化,它也不具有代表性。当使用同一台设备收集训练和测试数据时,也可能发生类似情况;如果模型过度学习了该设备的特征,它可能无法泛化到其他设备,而这将无法通过测试集上的评估来检测。如果使用公共数据集测试模型,要警惕“Frankenstein”数据集,这些数据集是从其他公共数据集组装而成,存在与训练数据重叠的风险。此外,在处理包含每个受试者多个数据点的数据集时要小心;如果使用这些数据集,重要的是确保在分割出测试集或进行 CV 时,每个受试者的数据点被保持在同一个折中。参见 Roberts 等人的一项揭示性报告(Common pitfalls and recommendations for using  machine learning to detect and prognosticate for COVID-19 using chest  radiographs and CT scans),其中许多此类陷阱如何导致绝大多数 COVID-19 检测模型无法泛化到其测试集之外。    

不要在分割数据之前进行数据增强

数据增强(参见”务必确保你有足够的数据”)可以是平衡数据集、提升 ML 模型泛化能力和鲁棒性的有用技术。然而,重要的是只对训练集进行数据增强,而不是对将用于测试的数据进行数据增强。在测试集中包含增强数据会导致一些问题。一个问题可能是模型过拟合了增强数据的特征,而不是原始样本的特征,而如果你的测试集也包含增强数据,你将无法检测到这一点。一个更关键的问题发生在将数据增强应用于整个数据集,然后才将其分割为训练集和测试集的情况下。在这种情况下,训练样本的增强版本最终可能进入测试集,在最坏的情况下,这可能导致一种特别有害的数据泄漏形式,其中测试样本主要是训练样本的变体。关于这个问题如何影响整个研究领域的有趣研究,请参见 Vandevelde 等人。   

务必避免顺序过拟合   (sequential overfitting)

奇怪的是,最具危害性的数据泄漏形式之一没有一个普遍认同的名称(尽管 Hosseini 等人 建议称其为”过度炒作”,源自超参数的过拟合),所以我将称之为顺序过拟合。当你连续训练多个模型,并使用所获得的关于每个模型性能的知识来指导下一个模型的配置,并且使用相同的测试集来评估每个模型时,就会发生这种情况。通常,这是作为一个非正式的过程完成的,尝试不同的模型和不同的超参数,直到在测试集上获得良好的性能。因此,它很少被记录下来,这也是它如此有害的原因之一。具体来说,问题在于在整个过程中使用测试集,因为使用测试集在模型之间进行选择意味着关于测试集的信息隐含地泄漏到训练过程中。该想法的图示见图5。后果是模型逐渐过拟合测试集;你使用测试集的次数越多,发生的过拟合就越严重。解决方案是使用验证集(即一组不直接用于训练但用于指导训练的单独样本),或者使用一个预留数据集来测试最终模型。更多信息参见 Cawley 和 Talbot51 以及 Hosseini 等人。
图片

务必多次评估模型

许多 ML 模型是随机的或不稳定的。也就是说,如果你多次训练它们,或者如果你对训练数据进行小的更改,那么它们的性能会有显著差异。在推理时使用 LLMs 也是如此。这意味着对模型的一次评估可能是不可靠的,可能会低估或高估模型的真实潜力。因此,通常进行多次评估。在训练时,有多种方法可以做到这一点。对于随机模型,最简单的方法是使用不同的随机种子多次训练相同的模型,然后查看平均性能。一种更稳健的方法是还要为每个训练的模型改变数据。交叉验证(CV) 是特别流行的方式,并且有多种变体,其中大多数涉及将数据分割成多个折。在进行 CV 时,重要的是要注意数据内的任何依赖关系并加以考虑。未能做到这一点可能导致数据泄漏。例如,在医学数据集中,单个受试者拥有多个数据点很常见;为了避免数据泄漏,这些数据点应保持在同一个折内。时间序列数据对于 CV 尤其成问题;如何处理这个问题的讨论参见”不要忽视时间序列数据中的时间依赖性”。如果你正在进行超参数优化,那么你应该使用嵌套 CV(也称为双重 CV),它在主 CV 循环内使用一个额外的循环来避免过拟合测试折。如果你的某些数据类别很小,那么你可能需要进行分层,确保每个类别在每个折中都有足够的代表性。除了查看多次评估的平均性能外,提供一些离散度或置信度的度量也是标准做法,例如标准差或 95% 置信区间。    

务必保留一些数据来评估你的最终模型实例

我相当宽松地使用了术语”模型”,但评估通用模型的潜力(例如,神经网络能多好地解决你的问题)和评估特定模型实例(例如,通过一次反向传播产生的特定神经网络)的性能之间存在重要区别。交叉验证(CV)(参见”务必多次评估模型”)擅长前者,但对后者不太有用。例如,假设你进行了 10 折 CV。这将产生十个模型实例。然后你选择测试折分数最高的实例作为你将在实践中使用的模型。你如何报告它的性能?你可能认为它的测试折分数是其性能的可靠度量,但很可能不是。首先,单个折中的数据量相对较小。其次,分数最高的实例很可能是测试折最简单的那个,因此它所包含的评估数据可能没有代表性。因此,获得模型实例泛化能力的可靠估计的唯一方法可能是使用另一个测试集。在现有测试集的独立性可能受到损害的情况下也是如此,例如,由于多次使用它(参见”务必避免顺序过拟合”)。所以,如果你有足够的数据,最好保留一些数据,并且只使用一次来提供对最终选定模型实例的无偏估计。然而,值得注意的是,在使用 CV 时还有另一个选项:集成模型实例(参见”务必(小心地)组合模型”)。产生的集成模型的性能将与通过 CV 测量的平均值一致,因此不需要另一个测试集来衡量其性能。不利的一面是,它的推理时间、效率和可解释性可能比单个模型实例差,所以这种方法通常只有在数据非常少时才值得考虑。     

务必仔细选择指标

在评估机器学习模型时,请务必谨慎选择所使用的评估指标。例如,对于分类模型,最常用的指标是准确率,即模型对数据集中样本正确分类的比例。如果你的类别是平衡的,即每个类别在数据集中由相似数量的样本表示,那么这没问题。但许多数据集并不平衡,在这种情况下,准确率可能是一个非常误导性的指标。例如,考虑一个数据集,其中 90%的样本代表一个类别,10%的样本代表另一个类别。一个无论输入如何总是输出第一个类别的二分类器,其准确率将达到90%,尽管它毫无实际意义(见图6)。在这种情况下,使用诸如F~1分数、Cohen’s kappa 系数或 Matthew’s 相关系数等指标会更可取,所有这些指标对类别大小不平衡都相对不敏感。关于处理不平衡数据方法的更广泛综述,请参见 Haixiang 等人。回归指标也存在各种陷阱,特别是在时间序列预测的背景下;参见 Hewamalage 等人对这些的讨论。一个众所周知的例子是仅依赖均方根误差,它(有点像准确率)容易将那些总是预测无变化的模型赋予过高的评价分数。参见“务必采用多种方式来报告性能”。
图片

务必考虑模型公平性

总体性能指标并非衡量模型优劣的唯一重要标准。若要将模型应用于现实世界中,另一个重要的衡量标准便是公平性。公平性的定义多种多样,但大致来说,它指的是确保模型在对待人类对象时不会因诸如性别、种族、收入或个人政治立场等特征而出现不平等对待。这也被称为算法偏见,有许多模型因偏向或排斥特定人群而存在偏见的情况。不公平的常见根源之一是使用不具代表性的数据集来训练机器学习模型。例如,如果一个医疗诊断模型是基于单一国家的数据进行训练的,那么这些数据可能偏向于主要种族,而当该模型面对来自其他种族的用户时,可能无法公平地运行。然而,不公平也可能来自其他方面,包括数据准备过程中的潜意识偏见以及模型的归纳偏见。无论数据来源如何,都必须了解由此产生的任何偏见,并且最好采取措施来减轻这些偏见(例如,对少数样本应用数据增强——参见“请务必确保有足够的数据”)。公平性评估指标有很多种,因此解决的一个难题是确定哪些指标与您的建模环境最为相关;有关此方面的综述,请参阅Caton和Haas54等人。   

在时间序列数据中,切勿忽视时间上的相关性

时间序列数据与许多其他类型的数据不同,因为其数据点的顺序至关重要。处理时间序列数据时的许多问题都是由于忽略了这一事实而产生的。其中最显著的问题是,时间序列数据会受到一种特定的数据泄露现象的影响(参见“不要让测试数据泄漏到训练过程中”),这种现象被称为前瞻偏差。这种情况发生在用于训练模型的数据点中,有部分或全部的数据点出现在时间序列中的较晚阶段,而用于测试模型的数据点则出现在较早阶段。实际上,这可能会对未来的了解渗透到训练过程中,从而导致测试性能出现偏差。这种情况通常会在对时间序列数据应用标准交叉验证(CV)(参见“务必多次评估模型”)时发生,因为除了一个交叉验证迭代之外,所有交叉验证迭代中的训练数据集都包含了相对于测试数据集处于未来阶段的数据。可以通过使用尊重时间依赖性的特殊形式的交叉验证(如分块交叉验证)来避免这种情况,不过是否有必要这样做在一定程度上取决于时间序列数据的性质,例如它是否是平稳的还是非平稳的。有关此内容的更多详细信息,请参阅 Cerqueira 等人55 和 Wang 和 Ruf56 的文章。数据依赖型预处理操作在拆分测试数据之前执行也可能导致提前偏见;请参见图 7 以获取一个简单的示例,也参见“务必小心在何处及如何进行特征选择”。
图片

如何公平地比较模型

模型比较是学术研究的基础,但要正确进行比较却出乎意料地困难。 如果您进行了不公正的比较并发表了结果,那么其他研究人员随后可能会被引入歧途。因此,务必确保在相同的背景下评估不同的模型,探索多种视角,并正确使用统计检验。   

切勿认为数值越大代表模型越好

论文中常出现这样的表述:”先前研究报道的最高准确率为94%,我们的模型达到了95%,因此表现更优”。然而,数值更高并不一定意味着模型更好,这背后有多种原因。例如,如果模型是在同一数据集的不同划分上进行训练或评估的,那么性能上的微小差异可能源于划分方式本身。如果数据集的类别不平衡程度不同,准确率的差异可能仅仅反映了这一点(参见”务必仔细选择指标”)。如果它们完全使用了不同的数据集,那么即使是较大的性能差异也可能由此导致。另一个导致不公平比较的原因是,在比较模型时未能进行同等程度的超参数优化(参见”务必优化模型的超参数”)。例如,如果一个模型使用默认设置,而另一个经过优化,这种比较就不具备公平性。因此,对于基于已发表数据的比较,务必保持谨慎态度。为确保两种方法的公平比较,您应当重新实现所有待比较的模型,对每个模型进行同等程度的优化,执行多次评估(参见”务必多次评估模型”),然后运用统计检验方法(参见”在比较模型时使用统计检验”)来判断性能差异是否显著。比较基础模型时(参见”务必跟上深度学习(及其陷阱)的进展”)还存在一个额外的复杂因素:原始训练数据往往未知。因此,可能无法确保测试集独立于训练数据,从而难以建立公平的比较基础。  

务必采用有意义的基线模型

当引入一种新的建模方法时,与已有的成熟方法进行比较至关重要。这些参照方法通常被称为基线模型或简称为基线。选择合适的基线对于建立有效的比较基础极为重要。基线模型通常比新方法更简单,其作用在于证明新模型中增加的复杂性是必要的。例如,如果您正在对模型X进行拓展,那么将模型X作为基线是合理的。但同样,也可以使用其他更简单的模型作为参照。举例来说,如果您正在开发一种针对表格数据的深度学习方法,那么也应将其与决策树、支持向量机(SVM)等更简单的模型进行比较,以证明采用更复杂的方法是合理的。如果解决的是回归问题,则可以考虑使用逻辑回归等简单模型作为基线。最简单的基线被称为朴素基线,其目的是证明您提出的模型并非仅实现了某种简单的功能。Hewamalage等人研究中有一个很好的示例说明了为什么需要这种基线:一个为时间序列预测设计的复杂Transformer模型,其表现甚至不如一个朴素的基线——该基线始终将时间序列中的下一个值预测为与前一个值相同。这类没有实际决策过程的朴素基线也被称为虚拟模型。另一个例子是那种始终输出最常见类别标签的分类器(如“务必仔细选择指标”中所述)。除了简单基线之外,与最先进的模型进行比较同样重要。否则,您可能会面临类似这样的质疑:“既然已知模型Y优于模型X,为什么您还要继续拓展模型X?”      

在比较模型时使用统计检验

如果您想说服人们您的模型比别人的更好,那么统计检验可以是一个有用的工具。广义上说,用于比较单个 ML 模型的检验分为两类。第一类用于比较单个模型实例,例如两个训练好的决策树。例如,McNemar 检验是用于比较两个分类器的相当常见的选择,它通过比较两个分类器在测试集中每个样本上的输出标签来工作(所以一定要记得记录这些标签)。第二类是用于更普遍地比较两个模型的检验,例如决策树还是神经网络更适合该数据。这些需要对每个模型进行多次评估(参见“要对模型进行多次评估”),您可以通过使用 CV 或重复重采样(或者,如果您的训练算法是随机的,使用相同数据进行多次重复)来获得。然后,检验比较两个结果分布。Student’s t 检验是这类比较的常见选择,但仅在分布呈正态分布时才可靠,而这往往并非如此。更稳妥的选择是 Mann-Whitney’s U 检验,因为它不假设分布是正态的。更多信息,参见 Raschka 和 Carrasco 等人。另见“要对多重比较进行校正”和“报告统计显著性时要小心”。    

要对多重比较进行校正

当您想使用统计检验比较两个以上的模型时,事情会变得有点复杂,因为进行多个成对检验有点像多次使用测试集——它可能导致对显著性的过度乐观解释。基本上,每次您使用统计检验在两个模型之间进行比较时,它会发现实际上并不存在的显著差异。这由检验的置信水平表示,通常设置为 95%:意味着每 20 次中,有 1 次会给出假阳性。对于单次比较,这可能是您可以接受的某种程度的不确定性。然而,它会累积。也就是说,如果您进行 20 次置信水平为 95% 的成对检验,那么其中一次很可能给出错误答案。这被称为多重性效应,是数据科学中一个更广泛问题(至少在有意进行时)的一个例子,被称为数据疏浚或 p 值操纵。为了解决这个问题,您可以应用多重检验校正。最常见的方法是 Bonferroni 校正,这是一种非常简单的方法,它根据所进行的测试数量降低显著性阈值;简单的介绍可参见 Salzberg。然而,还有许多其他方法,并且关于这些校正应该在何时何地应用也存在一些争论;可理解的概述可参见 Streiner。     

不要总是相信社区基准的结果

在某些问题领域,使用基准数据集评估新的 ML 模型已成为常态。其想法是,因为每个人都使用相同的数据来训练和测试他们的模型,所以比较将更加透明。不幸的是,这种方法有一些主要缺点。首先,如果对测试集的访问不受限制,那么您不能假设人们没有将其作为训练过程的一部分。这被称为“针对测试集训练”,并导致结果严重过于乐观。一个更微妙的问题是,即使每个使用数据的人都只使用测试集一次,但集体来看,测试集被社区使用了多次。实际上,通过在相同的测试集上比较大量模型,最佳模型恰好过拟合测试集的可能性越来越大,并不一定比其他模型泛化得更好(参见“要对多重比较进行校正”和“要避免顺序过拟合”)。由于这些及其他原因,您应该谨慎对待从基准数据集结果中解读出多少信息,并且不要假设性能的小幅提升是显著的。在使用基础模型(参见“要跟上深度学习(及其陷阱)的进展”)的情况下尤其如此,因为它们的训练数据可能包含了社区基准的测试集。关于使用共享数据集相关问题的更广泛讨论,参见 Paulada 等人。另见“要以多种方式报告性能”。    

要(小心地)组合模型

虽然本节侧重于比较模型,但最好意识到 ML 并不总是关于在模型之间做出选择。通常,使用模型的组合是有意义的。不同的 ML 模型探索不同的权衡;通过组合它们,有时可以用一个模型的优势来补偿另一个模型的弱点,反之亦然。集成是一组成熟且已建立的组合模型。有很多集成学习方法——综述可参见 Dong 等人——但它们大致可以分为两类:一类由相同的基础模型类型形成集成(例子包括随机森林、Bagging 和 Boosting),另一类组合不同类型的 ML 模型。后者的一个例子是堆叠泛化(或堆叠),其中训练一个模型来聚合一组基础模型的输出。然而,集成并不是唯一的组合形式。另一种越来越常见的组合形式是,当嵌入模型(如自编码器或基础模型如 BERT)用于向其他模型提供输入。使用堆叠或嵌入时,重要的是确保没有数据泄露(参见“不要让测试数据泄露到训练过程中”)发生,即,用于衡量组合模型性能的测试数据不能用于其任何组件的训练。这是一个常见的陷阱,特别是当模型组件在重叠的数据上训练时。为了降低顺序过拟合的可能性(参见“要避免顺序过拟合”),也建议使用单独的测试集来评估组合模型。  

如何报告您的结果

学术研究的目的不是自我吹嘘,而是有机会为知识做出贡献。为了有效地为知识做出贡献,您需要提供您工作的完整情况,包括什么有效和什么无效。ML 常常涉及权衡——一个模型在所有重要方面都优于另一个模型的情况非常罕见——您应该尝试通过细致周到的方式来报告结果和结论,以反映这一点。   

要保持透明

首先,始终尝试对您所做和所发现的事情保持透明,因为这将使其他人更容易在您的工作基础上进行构建。特别是,以一种可访问的方式分享您的模型是很好的实践。例如,如果您使用脚本来实现所有实验,那么在发表结果时分享该脚本。这意味着其他人可以轻松重复您的实验,这给您的工作增加了信心。这也使得人们更容易比较模型,因为他们不再需要为了确保公平比较而从头开始重新实现所有内容。知道您将分享您的工作也会鼓励您更加小心,很好地记录您的实验,并编写干净的代码,这对您自己和他人都有好处。还需要注意的是,围绕可重复性的问题在 ML 社区中日益突出,因此在未来,如果您的流程没有得到充分记录和共享,您可能无法发表工作——例如,参见 Pineau 等人。检查清单(要使用 ML 检查清单)对于知道在流程中应包含哪些内容非常有用。您可能还会发现实验跟踪框架(如 MLflow)对于记录您的工作流程很有用。    

要以多种方式报告性能

在评估和比较模型时实现更好严谨性的一种方法是使用多个数据集。这有助于克服与单个数据集相关的任何缺陷(参见“不要总是相信社区基准的结果”),并允许您更完整地呈现模型的性能。为每个数据集报告多个指标也是很好的实践,因为不同的指标可以从不同角度呈现结果,并增加您工作的透明度。例如,如果您使用准确率,最好也包含一些对类别不平衡不那么敏感的指标(参见“要仔细选择指标”)。在医学和安全等领域,了解错误发生在哪里很重要;例如,当您的模型出错时,它是更倾向于假阳性还是假阴性?将所有内容汇总为一个数字的指标,如准确率,无法洞察这一点。因此,重要的是也包含部分指标,如精确率和召回率,或敏感性和特异性,因为这些确实能洞察您的模型产生的错误类型。并确保清楚您使用的是哪些指标。例如,如果您报告 F分数,请清楚这是F~1还是精确率和召回率之间的其他平衡点。如果您报告 AUC,请说明这是 ROC 曲线下面积还是 PR 曲线下面积。更广泛的讨论参见 Blagec 等人。     

不要过度推广超出数据范围

重要的是不要提出无效的结论,因为这可能误导其他研究人员。一个常见的错误是做出不受用于训练和评估模型的数据支持的概括性陈述。例如,如果您的模型在一个数据集上表现得非常好,这并不意味着它在其他数据集上也会表现得好。虽然通过使用多个数据集可以获得更稳健的见解(参见“要以多种方式报告性能”),但从任何实验研究中可以推断的东西总是有限的。这有很多原因,其中许多与数据集的构建方式有关。一个常见的问题是偏差或抽样误差:数据不能充分代表现实世界。另一个是重叠:多个数据集可能不是独立的,并且可能有相似的偏差。还有质量问题,这在深度学习数据集中是一个特别的问题,其中对数据数量的需求限制了可以进行的质量检查数量。所以,简而言之,不要过度推广您的发现,并意识到它们的局限性。    

报告统计显著性时要小心

我已经讨论过统计检验(参见“在比较模型时要使用统计检验”)以及它们如何用于确定 ML 模型之间的差异。然而,统计检验并不完美。有些是保守的,倾向于低估显著性;另一些是宽松的,倾向于高估显著性。这意味着阳性检验并不总是表明某事是显著的,而阴性检验也不一定意味着某事不显著。然后,还有使用阈值来确定显著性的问题;例如,95% 的置信阈值(即,当 p<0.05 时)意味着,每 20 次中被标记为显著的一次差异,实际上并不显著。事实上,统计学家越来越多地认为最好不要使用阈值,而只是报告p值,并让读者自己去解释。除了统计显著性之外,另一件需要考虑的事情是两个模型之间的差异是否真的具有实际意义。如果您有足够的样本,您总能找到显著的差异,即使实际性能差异微乎其微。为了更好地指示某事是否重要,您可以测量效应量。有多种方法用于此:Cohen’s d统计量可能是最常见的,但更稳健的方法(如 Kolmogorov-Smirnov)更可取。关于效应量和报告统计显著性的更多信息,参见 Aguinis 等人。您也可以考虑使用贝叶斯统计;尽管可用的指导和工具支持较少,但从理论上讲,它们有很多优点,并且避免了与传统统计检验相关的许多陷阱——更多信息参见 Benavoli 等人。    

要查看您的模型

训练好的模型包含大量有用信息。不幸的是,许多作者只报告训练好模型的性能指标,却并未对模型实际学习的内容进行任何阐述。请记住,研究的目的不是为了获得比其他所有人略高的准确率。相反,是为了产生知识和理解,并与研究社区分享这些。如果您能做到这一点,那么您的工作更有可能获得像样的发表成果。所以,要查看您的模型内部,尝试理解它们如何做出决策。对于像决策树这样相对简单的模型,提供模型的可视化也可能是有益的,大多数库都有可以为您做到这一点的功能。对于更复杂的模型,有一系列 XAI 技术可以使用。其中一些是模型特定的,另一些是与模型无关的。后者的成熟例子是独立于模型的局部可解释性(LIME)和 Shapley 加性解释(SHAP);两者都能洞察哪些特征对模型很重要。对于 CNN 和视觉 Transformer,一种常见的方法是使用显著性图,它显示输入图像不同部分的重要性——说明性示例见图 8。Grad-CAM 是生成这些的流行技术,但也有很多其他方法。对于非视觉 Transformer,一种常见的方法是可视化注意力权重。XAI 技术的综述参见 Dwivedi 等人,当前方法局限性的讨论参见 Ali 等人。虽然 XAI 技术可以为您提供关于模型行为的有用见解,但重要的是要记住,它们不太可能准确地告诉您模型在做什么。对于深度学习模型(参见“不要假设深度学习将是最好的方法”)尤其如此,其复杂性使得其行为本质上难以分析。对于复杂模型,消融研究也可能有用。这涉及逐步移除模型的部分,以查看哪些是重要的,并可能产生一个更简单、更易于分析的模型。
图片

要使用机器学习检查清单

本指南旨在让您了解 机器学习(ML) 过程中可能出现的主要问题,并提供一些关于如何避免这些问题发生的指导。另一方面,检查清单旨在更正式地引导您完成 ML 流程,并鼓励您记录(更重要的是思考)您的实现决策如何支持有意义的结果。在某些领域,例如某些医学领域,在提交论文发表之前必须完成检查清单。然而,除了它们的质量保证作用之外,检查清单在规划 ML 流程时研究开始阶段可以说最有用。由于我是作者之一,我特别鼓励您看看 REFORMS,它是一份结合了检查清单和基于共识的建议集,用于进行基于 ML 的科学(尽管其中大部分也适用于更一般的 ML 实践)。还有其他更特定领域的检查清单可用。    

结论

ML 正在成为人们生活的重要组成部分,然而 ML 的实践可以说仍处于起步阶段。有许多容易犯的错误,这些错误可能导致 ML 模型表面上看起来表现良好,但实际上并非如此。反过来,当这些模型发表时,这有可能误导他人;如果这些模型被部署,则有可能造成伤害。本指南描述了这些错误中最常见的一些,也触及了 ML 良好实践的更一般性问题,例如公平性、透明度和避免偏见。它还提供了关于如何避免这些陷阱的建议。然而,随着新的 ML 方法的发展,新的威胁不断出现,因此 ML 用户保持警惕非常重要。这是一个快速发展的研究领域的本质——如何进行 ML 的理论几乎总是滞后于实践,从业者对于最佳实践方式总是会有不同意见,我们今天认为正确的,明天可能就不正确了。