python学习13之数据泄密

  在本教程中,您将了解什么是数据泄漏以及如何防止数据泄漏。如果你不知道如何防止它,泄漏将经常出现,它将破坏您的模型在微妙和危险的方式。因此,对于实践数据科学家来说,这是最重要的概念之一。

  1、摘要

    数据泄漏(或泄漏)发生在您的训练数据包含关于目标的信息时,但是当使用模型进行预测时,将无法获得类似的数据。

    这将导致训练集上的高性能(甚至可能是验证数据),但是模型在生产中表现很差。

    换句话说,泄漏导致模型看起来很精确,直到您开始使用模型做出决策,然后模型变得非常不准确。

      泄漏主要有两种类型:

        target leakage 和 train-test contamination.

  2、两种泄密类型

    1)、目标泄漏

      当预测器包含在进行预测时不可用的数据时,就会发生目标泄漏。

      从数据可用的时间或时间顺序来考虑目标泄漏是很重要的,而不仅仅是某个特性是否有助于做出良好的预测。

      举个例子会很有帮助。假设您想要预测谁会感染肺炎。

        原始数据的前几行是这样的:

        

      人们在患肺炎后服用抗生素药物是为了恢复健康。

      原始数据显示这些列之间有很强的关系,但是在确定got_pneumonia的值之后,took_antibiotic_medicine经常被更改。

      这是目标泄漏。该模型将看到,任何对took_tic_medicine值为False的人都没有患肺炎。

      由于验证数据与培训数据来自同一个源,因此模式将在验证中重复,并且模型将具有良好的验证(或交叉验证)得分。

      但这个模型在随后的实际应用中会非常不准确,因为即使是肺炎患者,在我们需要对他们未来的健康状况做出预测时,他们也不会使用抗生素。

      为了防止这种类型的数据泄漏,应该排除在实现目标值之后更新(或创建)的任何变量。

    2)、train-test contamination

      当我们不小心将培训数据与验证数据区分开来时,就会发生另一种类型的泄漏。

      回想一下,验证意味着度量模型如何处理它以前没有考虑过的数据。如果验证数据影响预处理行为,则可以以微妙的方式破坏此过程。

      这有时被称为train-test contamination。

      例如,假设在调用train_test_split()之前运行预处理(比如为缺失的值拟合一个灌输器)。

      最终的结果可能是我们的模型可能得到很好的验证分数,这给了您很大的信心,但是当您部署它来做决策时,它的性能很差。

      毕竟,我们将来自验证或测试数据的数据合并到如何进行预测中,所以即使不能泛化到新数据,也可以很好地处理特定的数据。

      当我们进行更复杂的特性工程时,这个问题会变得更加微妙(也更加危险)。如果您的验证基于简单的训练-测试分割,则将验证数据排除在任何类型的拟合之外,包括预处理步骤的拟合。

      如果我们使用scikit-learn管道,这将更加容易。在使用交叉验证时,在管道中进行预处理更为重要。

  3、举例说明

      在本例中,我们将学习一种检测和删除目标泄漏的方法。

      我们将使用一个关于信用卡应用程序的数据集,跳过基本的数据设置代码。最终的结果是,关于每个信用卡应用程序的信息存储在一个DataFrame x中。   

import pandas as pd
import csv

data = pd.read_csv('E:/data_handle/AER_credit_card_data.csv',
                   true_values=['yes'],false_values=['no'])
y = data.card

X = data.drop(['card'], axis=1)

print("Number of rows in the dataset:",X.shape[0],"
",X.head())

      接着我们开始进行验证处理,由于这是一个小数据集,我们将使用交叉验证来确保模型质量的准确度量。

from sklearn.pipeline import make_pipeline
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score

#由于没有预处理,所以我们不需要管道(无论如何,作为最佳实践使用!)
my_pipeline = make_pipeline(RandomForestClassifier(n_estimators=100))
cv_scores = cross_val_score(my_pipeline, X, y, cv=5, scoring= 'accuracy')
print("Cross-validation accuracy: %f" % cv_scores.mean())

      有了经验,你会发现很难找到准确率高达98%的模型。

      这种情况时有发生,但我们应该更仔细地检查数据以发现目标泄漏的情况非常少见。

      这是一个汇总的数据,你也可以找到在数据选项卡:

        信用卡:接受信用卡申请1张,不接受0张

        报告:主要贬损性报告的数量

        年龄:n岁加12岁

        收入:年收入(除以10000)

        份额:每月信用卡支出与年收入之比

        支出:平均每月信用卡支出

        业主:1(如果拥有房产),0(如果出租)

        selfempl: 1(如果是个体经营者),0(如果不是)

        受养人:1 +受养人人数

        月份:住在当前地址的月份

        主卡:持有的主卡数量

        活跃的:活跃的信用帐户的数量

      有几个变量看起来可疑。

      例如,支出是指此卡上的支出还是应用前使用的卡上的支出?

        在这一点上,基本数据比较是非常有用的:
expenditures_cardholders = X.expenditure[y]
expenditures_noncardholders = X.expenditure[~y]

#打印那些没有收到信用卡且没有消费的人的比例
print('Fraction of those who did not receive a card and had no expenditures: %.2f' 
      %((expenditures_noncardholders == 0).mean()))
#打印而那些收到信用卡却没有消费的人则只占了一小部分
print('Fraction of those who received a card and had no expenditures: %.2f' 
      %(( expenditures_cardholders == 0).mean()))     

      如上图所示,没有收到卡片的人没有支出,而收到卡片的人中只有2%没有支出。

      我们的模型似乎有很高的精确度,这并不奇怪。  

      但这似乎也是目标泄漏的一个例子,其中支出可能意味着他们申请的卡上的支出。    

      由于份额部分由支出决定,因此也应排除在外。活动变量和主卡不太清楚,但是从描述来看,它们听起来令人担忧。

      在大多数情况下,如果您无法找到创建数据的人以了解更多信息,那么安全总比遗憾好。

      我们将运行一个没有目标泄漏的模型,如下所示:

#从dataset中删除泄漏的预测器
potential_leaks = ['expenditure', 'share', 'active', 'majorcards']
X2 = X.drop(potential_leaks, axis= 1)
#删除泄漏预测器后评估模型
cv_scores = cross_val_score(my_pipeline, X2, y, cv=5, scoring='accuracy')
print("Cross-val accuracy: %f" % cv_scores.mean())

      这个精度要低一些,这可能会令人失望。

      然而,在新应用程序中使用它时,我们可以期望它在80%的情况下是正确的,而泄漏模型可能会做得比这糟糕得多(尽管它在交叉验证中明显得分更高)。

   4、总结

    在许多数据科学应用中,数据泄漏可能是数百万美元的错误。

    仔细分离培训和验证数据可以防止培训测试污染,管道可以帮助实现这种分离。

    同样,结合谨慎、常识和数据探索可以帮助识别目标泄漏。

  5、代码总结

    

import pandas as pd

from sklearn.pipeline import make_pipeline
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score

data = pd.read_csv('E:/data_handle/AER_credit_card_data.csv',
                   true_values=['yes'],false_values=['no'])
y = data.card

X = data.drop(['card'], axis=1)

print("Number of rows in the dataset:",X.shape[0],"
",X.head())

#由于没有预处理,所以我们不需要管道(无论如何,作为最佳实践使用!)
my_pipeline = make_pipeline(RandomForestClassifier(n_estimators=100))
cv_scores = cross_val_score(my_pipeline, X, y, cv=5, scoring= 'accuracy')
print("Cross-validation accuracy: %f" % cv_scores.mean())

expenditures_cardholders = X.expenditure[y]
expenditures_noncardholders = X.expenditure[~y]

#打印那些没有收到信用卡且没有消费的人的比例
print('Fraction of those who did not receive a card and had no expenditures: %.2f' 
      %((expenditures_noncardholders == 0).mean()))
#打印而那些收到信用卡却没有消费的人则只占了一小部分
print('Fraction of those who received a card and had no expenditures: %.2f' 
      %(( expenditures_cardholders == 0).mean()))

#从dataset中删除泄漏的预测器
potential_leaks = ['expenditure', 'share', 'active', 'majorcards']
X2 = X.drop(potential_leaks, axis= 1)
#删除泄漏预测器后评估模型
cv_scores = cross_val_score(my_pipeline, X2, y, cv=5, scoring='accuracy')
print("Cross-val accuracy: %f" % cv_scores.mean())

    本次得学习还是缺少很多理解,只是看了个大概,很多东西都不是很懂,还需要继续研究、理解,这些内容都会都很多的变动的。

本次学习到此结束!!!!!

原文地址:https://www.cnblogs.com/fb1704011013/p/11203906.html