kaggleIntermediateMachineLearningDataLeakage
在本教程中,您将了解什么是数据泄漏以及如何预防它。如果您不知道如何预防,泄漏就会频繁发生,并会以微妙而危险的方式破坏您的模型。因此,这是实践数据科学家最重要的概念之一。
Introduction
数据泄漏(或泄漏)是指你的训练数据包含目标信息,但在使用模型进行预测时无法获得类似的数据。这会导致模型在训练集(甚至验证集)上表现出色,但在生产环境中表现不佳。
换句话说,泄漏会导致模型看起来很准确,直到你开始用它做决策,然后模型就会变得非常不准确。
泄漏主要有两种类型:目标泄漏和训练-测试污染。
目标泄漏
目标泄漏是指你的预测器包含在你进行预测时无法获得的数据。重要的是要从数据可用的时间或时间顺序来考虑目标泄漏,而不仅仅是某个特征是否有助于做出正确的预测。
举个例子会有所帮助。假设你想预测谁会患肺炎。你的原始数据的前几行如下所示:
| got_pneumonia | age | weight | male | took_antibiotic_medicine | … |
|---|---|---|---|---|---|
| False | 65 | 100 | False | False | … |
| False | 72 | 130 | True | False | … |
| True | 58 | 100 | False | True | … |
人们在患肺炎后会服用抗生素药物来康复。原始数据显示这些列之间存在很强的相关性,但“took_antibiotic_medicine”在“got_pneumonia”的值确定后经常发生变化。这就是目标泄漏。
该模型会认为“took_antibiotic_medicine”值为“False”的任何人都没有患肺炎。由于验证数据与训练数据来自同一来源,因此该模式将在验证中重复出现,并且该模型将获得很高的验证(或交叉验证)分数。
但是,该模型随后在现实世界中部署时会非常不准确,因为即使是那些即将患肺炎的患者,在我们需要预测他们未来健康状况时,他们也还没有接受抗生素治疗。
为了防止这种类型的数据泄漏,任何在目标值实现后更新(或创建)的变量都应排除在外。

Train-Test Contamination
当您没有仔细区分训练数据和验证数据时,就会发生另一种类型的泄漏。
回想一下,验证旨在衡量模型在之前未考虑过的数据上的表现。如果验证数据影响了预处理行为,您可能会以微妙的方式破坏此过程。这有时被称为训练-测试污染。
例如,假设您在调用 train_test_split() 之前运行了预处理(例如,使用插补器拟合缺失值)。最终结果如何?您的模型可能获得了良好的验证分数,让您对其充满信心,但在部署它进行决策时,其表现却很差。
毕竟,您将验证数据或测试数据中的数据融入了您的预测过程中,因此即使它无法推广到新数据,也可能在特定数据上表现良好。当您进行更复杂的特征工程时,这个问题会变得更加微妙(也更加危险)。
如果您的验证基于简单的训练-测试拆分,请将验证数据排除在任何类型的拟合之外,包括预处理步骤的拟合。如果您使用 scikit-learn 流程,这会更容易。使用交叉验证时,在流程内部进行预处理就显得尤为重要!
Example
在本例中,您将学习一种检测和消除目标泄漏的方法。
我们将使用一个关于信用卡申请的数据集,并跳过基本的数据设置代码。最终结果是,每个信用卡申请的信息都存储在 DataFrame“X”中。我们将使用它来预测 Series“y”中哪些申请被接受。
import pandas as pd |
| reports | age | income | share | expenditure | owner | selfemp | dependents | months | majorcards | active | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0 | 37.66667 | 4.5200 | 0.033270 | 124.983300 | True | False | 3 | 54 | 1 | 12 |
| 1 | 0 | 33.25000 | 2.4200 | 0.005217 | 9.854167 | False | False | 3 | 34 | 1 | 13 |
| 2 | 0 | 33.66667 | 4.5000 | 0.004156 | 15.000000 | True | False | 4 | 58 | 1 | 5 |
| 3 | 0 | 30.50000 | 2.5400 | 0.065214 | 137.869200 | False | False | 0 | 25 | 1 | 7 |
| 4 | 0 | 32.16667 | 9.7867 | 0.067051 | 546.503300 | True | False | 2 | 64 | 1 | 5 |
由于这是一个小数据集,我们将使用交叉验证来确保模型质量的准确测量。
from sklearn.pipeline import make_pipeline |
凭借经验,你会发现,准确率高达 98% 的模型非常罕见。这种情况确实存在,但并不常见,因此我们应该更仔细地检查数据,避免目标数据泄露。
以下是数据摘要,您也可以在数据选项卡下找到:
- **
card**:信用卡申请被接受,则为 1;未被接受,则为 0 - **
reports**:重大不良报告数量 - **
age**:年龄(n 岁加 1/12 岁) - **
income**:年收入(除以 10,000) - **
share**:每月信用卡支出占年收入的比例 - **
expenditure**:每月平均信用卡支出 - **
owner**:房屋自有,则为 1;租房,则为 0 - **
selfempl**:个体经营者,则为 1;非个体经营者,则为 0 - **
dependents**:1 + 受抚养人数量 - **
months**:在当前地址居住的月份 - **
majorcards**:持有的主要信用卡数量 - **
active**:活跃信用账户数量
一些变量看起来可疑。例如,“支出”是指这张卡的支出,还是申请前使用的卡的支出?
此时,基本数据比较会非常有帮助:
expenditures_cardholders = X.expenditure[y] |
如上所示,所有未收到信用卡的人都没有支出,而收到信用卡的人中只有 2% 没有支出。我们的模型似乎具有较高的准确率,这并不奇怪。但这似乎也存在目标泄漏的情况,其中支出可能指的是他们申请的信用卡上的支出。
由于**share部分由expenditure决定,因此也应将其排除。变量active和majorcards**不太明确,但从描述来看,它们听起来令人担忧。在大多数情况下,如果您无法找到创建数据的人来了解更多信息,最好谨慎行事。
我们将运行一个没有目标泄漏的模型,如下所示:
# Drop leaky predictors from dataset |
这个准确率相当低,可能令人失望。然而,我们可以预期它在新应用上的准确率大约为 80%,而有泄漏的模型的表现可能会更差(尽管它在交叉验证中得分更高)。
Conclusion
在许多数据科学应用中,数据泄露可能造成数百万美元的损失。仔细分离训练数据和验证数据可以防止训练测试数据污染,而管道可以帮助实现这种分离。同样,谨慎、常识和数据探索的结合可以帮助识别目标泄露。
