1.介绍
当训练数据包含有关目标的信息时,会发生Data leakage(或leakage),但当模型用于预测时,类似的数据将不可用。这导致了训练集的高性能(甚至可能是验证数据),但是模型在生产中的性能很差。
换句话说,泄漏会导致模型看起来很精确,直到开始使用模型进行决策,然后模型变得非常不准确。
泄漏主要有两种类型:target leakage和train-test contamination。
(1)target leakage
target leakage发生时,当你做预测时,你的数据将不可用。重要的是要考虑目标泄漏的时间或时间顺序,数据变得可用,而不仅仅是一个功能是否有助于作出良好的预测。
举个例子会有帮助。想象一下你想预测谁会得肺炎。原始数据的前几行如下所示:
人们在肺炎后服用抗生素药物以恢复。原始数据显示,这些列之间有很强的关系,这儿在确定了肺炎后,服用抗生素的药物往往会发生变化。这是目标泄漏。
模型会发现,任何没有服用抗生素的人都没有肺炎。由于验证数据来自与培训数据相同的来源,因此模式在验证中会重复,并且模型将具有很好的验证(或交叉验证)分数。
但是,当我们随后在现实世界中部署时,这个模型将非常不准确,因为即使是那些患肺炎的患者,我们对他们做出预测时,也不会服用抗生素。
为了防止这种类型的数据泄漏,应排除目标值实现后更新(或创建)的任何变量。
(2)Train-Test Contamination
如果不小心区分训练数据和验证数据,则会发生另一种类型的泄漏。
回想一下,验证是用来衡量模型如何处理以前没有考虑过的数据的。如果验证数据影响预处理行为,则可以以微妙的方式破坏此过程。这有时被称为Train-Test Contamination。
例如,假设您在调用train_test_split()之前运行预处理(比如fitting or imputation)。最终结果如何?您的模型可能会得到很好的验证分数,使您对它有很大的信心,但是当您部署它来做决策时,它的性能很差。
毕竟,您将来自验证或测试数据的数据合并到了如何进行预测中,因此,即使不能推广到新数据,也可能在特定数据上表现良好。当您进行更复杂的特性工程时,这个问题变得更加微妙(并且更加危险)。
如果验证基于简单的训练测试拆分,不包括预处理。scikit-learn管道机制也会更容易。使用交叉验证时,在管道内部进行预处理也更重要!
2.例子
根据经验,你会发现很少有人能找到98%准确的模型。这种情况很少见,所以应该更仔细地检查数据,是否目标泄漏。
以下是数据的摘要:
- card: 1
- reports: Number of major derogatory reports
- age: Age n years plus twelfths of a year
- income: Yearly income (divided by 10,000)
- share: Ratio of monthly credit card expenditure to yearly income
- expenditure: Average monthly credit card expenditure
- owner: 1 if owns home, 0 if rents
- selfempl: 1 if self-employed, 0 if not
- dependents: 1 + number of dependents
- months: Months living at current address
- majorcards: Number of major credit cards held
- active
一些变量看起来可疑。例如,支出是指在这张卡上的支出还是在申请前使用的卡片上的支出?
此时,基本数据比较非常有用:
如上所示,所有没有收到卡的人都没有支出,而收到卡的人中只有2%没有支出。毫不奇怪,我们的模型似乎有很高的准确性。但这似乎也是一个目标泄漏的情况,支出可能意味着他们申请的卡的支出。
由于份额部分是由支出决定的,因此也应排除在外。活动变量和主要变量不太清楚,但从描述上看,它们听起来令人担忧。在大多数情况下,如果你无法找到创建数据的人以了解更多信息,那么安全总比抱歉好。
我们将运行一个没有目标泄漏的模型,如下所示:
这个准确度要低一些,这可能会令人失望。然而,我们可以预期,当在新应用程序中使用时,它大约80%的时间是正确的,而泄漏模型可能会做得更糟(尽管它在交叉验证中的明显得分更高)。
3.总结
在许多数据科学应用中,数据泄漏可能是数百万美元的错误。仔细分离训练和验证数据可以防止训练测试污染,管道机制可以帮助实现这种分离。同样,谨慎、常识和数据探索的结合更有助于识别目标泄漏。