使用数据验证技术来研究数据重采样的影响
回到博客主页

使用数据验证技术来研究数据重采样的影响

数据科学 2022年7月11日

在处理不平衡数据时,一种常用的方法是重新采样训练数据以减少类不平衡。这可能涉及到对多数阶层采样过少,对少数阶层采样过多,或者两者兼而有之。更有趣的是,对于上述三类方法,我们可以采用多种方法。

重采样训练数据的一个众所周知的缺点是,我们扭曲了特征的初始分布和它们之间的关系。当然,只要我们的模型的性能得到改善,我们可能会完全接受这种情况。然而,知道这个问题到底有多严重是很有趣的。有很多方法可以检查这一点,例如,使用简单的可视化(这在非常高维的数据集中是不可行的),或者检查相关矩阵。

在这篇文章中,我们将做一点不那么热闹接近和使用deepchecks库将原始数据集与重新采样的数据集进行比较。我们将使用流行的信用卡欺诈数据集来调查三个重新采样数据集之间的差异。让我们开始吧!

数据

我们将使用最流行的不平衡分类数据集之一,即信用卡欺诈数据集(可在Kaggle).我们将相关信息总结如下:

  • 该数据集包含欧洲持卡人在2013年9月的两天内进行的信用卡交易。
  • 数据集高度不平衡——在284,807笔交易中,有492笔被认定为欺诈。这相当于所有交易的0.173%。
  • 为了匿名化数据,数据集包含28个数字特征,这些特征是PCA转换的结果。唯一没有匿名的特征是时间(数据集中的每个事务与第一个事务之间的间隔时间为秒)和(事务的数量)。这就产生了总共30个特性。

考虑重采样技术

在本文中,我们将探讨三种流行的重采样技术最佳电子竞技即时竞猜平台。。有许多优秀的文章描述了算法的本质细节,例如SMOTE,因此我们只专注于提供一个简短的复习。

1.随机采样

随机过采样是现有过采样方法中最简单的一种。我们从多数类中抽取随机样本(默认情况下不进行替换),直到我们获得类的1:1比例。这种方法的最大问题是丢弃大部分训练集会导致信息丢失。

2.随机采样过密

过采样相当于随机欠采样。在这里,我们从少数群体中抽取有替换的样本,直到达到期望的群体比例。虽然它不会导致信息丢失,但它有过拟合的危险,这是由于复制来自少数群体的观察结果造成的。

3.击杀

打(年代进行inorityOversamplingTeChnique)是一种过采样技术,可以从少数群体中创建新的合成观察。这样,算法避免了随机过采样时的过拟合问题。

算法执行以下步骤:

  • 选择一个少数群体的观察。
  • 确定其k -最近的邻居。
  • 在将选定的观测点与最近的相邻点连接(插值)的直线上创建合成观测点。
  • 重复上述步骤,直到达到所需的类的比例。

虽然它不会导致信息丢失,并试图解释过拟合,但不幸的是,SMOTE并不是不平衡类的灵药。这种算法也有自己的缺点。最大的问题是,它会给数据带来更多的噪音,并导致少数类和多数类的重叠(观察结果之间臭名昭著的桥梁)。原因是SMOTE在创建新的观察结果时没有考虑到来自大多数阶层的观察结果。

Deepchecks

deepchecks是一个开源的Python库,允许测试和验证ML模型的数据和性能。它通过验证数据完整性、检查分布、验证其分割等方法来实现这一点。

在处理deepchecks,我们可以使用套件(检查集)的方便概念,这使得使用库非常轻松。对于表格数据,我们可以使用以下套件:

  • single_dataset_integrity这个套件的目的是探索一个单一的数据集(在任何分裂之前)。它的重点是验证数据的完整性,例如,检查重复观察的数量,类别特征是否存在任何问题,检测异常值等。
  • train_test_validation-此套件用于调查数据拆分(最常见的例子是train-test拆分)是否会产生有代表性的数据集。例子包括:调查类的分布/平衡,检查每个类的特征或标签之间的分布是否有显著的变化,查看潜在的数据泄漏,等等。
  • model_evaluation-此套件用于评估ML/DL模型的性能。使用它,我们可以检查几个性能指标,将性能与基准进行比较,等等。

我们也可以用full_suite,它结合了上面提到的三个套件。为了方便起见,库自动从三个套件中选择与我们的用例相关的测试。

对于我们的示例,我们最感兴趣的是train_test_validation套房,但我们会用full_suite还要检查一些数据完整性检查。

准备数据比较

在本节中,我们将描述如何使用所考虑的技术处理数据并对其进行重新采样。我们首先指定在各个步骤中存储数据的目录,以及数据验证报告的预期位置。

#目录RAW_DIR = "data/raw" PROCESSED_DIR = "data/processed" AUGMENTED_DIR = "data/augmented" REPORTS_DIR = "data_validation"

我们的数据位于三个目录中:

  • -在这里我们存储从下载的原始数据Kaggle
  • 加工过的-这里我们存储的是火车测试分离后的数据。
  • 增强-这里我们存储重采样的数据集。重要的是要记住,在重新采样时,我们只重新采样训练数据!

此外,我们跟踪数据使用".您可以阅读更多关于使用DVC设置数据版本的信息我的另一篇文章

在下面的脚本中,我们从目录,将特征与目标分离,然后将时间特性,将数据分割为训练集和测试集(使用80-20的比例),然后将其保存到加工过的目录中。在处理不平衡类时,应用分层的训练-测试分割是至关重要的,这样可以保留数据集中类的比例。

拆分之后,我们还应用了缩放功能使用scikit-learnRobustScaler.正如我们之前提到的,所有其他28个特征都是通过运行PCA获得的,所以我们假设在转换之前它们的值被适当缩放。

在这个项目中,我们将使用随机森林分类器,它不需要显式的特征缩放。然而,SMOTE等重采样算法在底层使用k-最近邻(kNN)。对于那些基于距离的算法来说,尺度确实很重要。

从配置导入RAW_DIR, PROCESSED_DIR导入os从sklearn。预处理从sklearn导入RobustScaler。model_selection import train_test_split #加载数据df = pd.read_csv(f"{RAW_DIR}/creditcard.csv") #分离目标X = df.copy() y = X.pop("Class") #删除不必要的特性X = X.drop(columns=["Time"]) #分层的火车测试分裂X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42, test_size=0.2,stratify=y) #健全检查打印(y_train.value_counts(normalize=True).values) print(y_test.value_counts(normalize=True).values) #缩放数量特性robust_scaler = RobustScaler() X_train[[" amount "]] = robust_scaler.fit_transform(X_train[[" amount "]]) X_test[[" amount "]] = robust_scaler.transform(X_test[[" amount "]]) #准备输出dir os. valuemakedirs(PROCESSED_DIR, exist_ok=True) #保存数据X_train.to_csv(f"{PROCESSED_DIR}/X_train.csv", index=None) X_test.to_csv(f"{PROCESSED_DIR}/X_test.csv", index=None) y_train.to_csv(f"{PROCESSED_DIR}/y_train.csv", index=None) y_test.to_csv(f"{PROCESSED_DIR}/y_test.csv", index=None)

在下一步中,我们应用各种重采样技术(可在imbalanced-learn库)的训练数据,并将结果存储在增强目录中。为了使代码易于扩展,我们定义了重采样技术的列表,脚本对其进行迭代。这样,我们就可以很容易地用其他方法进行重采样实验,例如ADASYN。或者,我们可以为算法使用不同的参数。在SMOTE的情况下,我们可以指定在创建合成数据点时要考虑的最近邻居的数量。

import os导入熊猫作为pd从配置导入RAW_DIR, PROCESSED_DIR, AUGMENTED_DIR从imblearn从imblearn导入randomoverample, SMOTE, ADASYN。RESAMPLE_CONFIG = [{"name": "undersampling", "sampler": RandomUnderSampler(RANDOM_STATE =RANDOM_STATE)}, {"name": "oversampling", "sampler": randomoveramplpler (RANDOM_STATE =RANDOM_STATE)}, {"name": "smote", "sampler": smote (RANDOM_STATE =RANDOM_STATE)},] #准备输出目录os。makedirs(AUGMENTED_DIR, exist_ok=True) # loading data X_train = pd.read_csv(f"{PROCESSED_DIR}/X_train.csv", index_col=None) y_train = pd.read_csv(f"{PROCESSED_DIR}/y_train.csv", index_col=None) #在RESAMPLE_CONFIG中运行resample_spec的所有增强:augmenter = resample_spec["sampler"] X_res, y_res = augmenter. csv:fit_resample(X_train, y_train) print(f"{resample_spec['name']} results ----") print(f"Shape before: {X_train. Shape}") print(f"Shape after: {X_res.shape}") print(f"Class distribution before: {y_train.value_counts(normalize=True).values}") print(f"Class distribution after:y_res.to_csv(f"{AUGMENTED_DIR}/ X_train_{resample_spec['name']}.csv", index=None) y_res.to_csv(f"{AUGMENTED_DIR}/y_train_{resample_spec['name']}.csv", index=None)

在下面的日志节选中,我们可以看到重新采样如何影响数据集的大小和类分布。使用默认设置,所有方法的目标都是类的1:1比例。

不足采样结果----前形:(227845,29)后形:(788,29)前类分布:[0.99827075 0.00172925]后类分布:[0.5 0.5]过采样结果----前形:(227845,29)后形:(454902,29)前类分布:[0.99827075 0.00172925]前类分布:[0.5 0.5]击打结果----前形:(227845,29)后形:(454902,29)前类分布:[0.99827075 0.00172925]前类分布:[0.5 0.5]

在最后一个脚本中,我们生成数据验证报告。我们识别所有不同的重采样数据集增强目录,并生成将这些数据集与原始数据集进行比较的报告。为了使用deepchecks,假设训练数据为原始数据集,测试数据为重采样数据。

import glob import os from config import RAW_DIR, PROCESSED_DIR, REPORTS_DIR, AUGMENTED_DIR from deepcheckstabular import数据集来自deepcheck .tabular.suites import full_suite #准备数据验证报告的输出目录makedirs(REPORTS_DIR, exist_ok=True) #获取重采样数据集的名称data_files = glob.glob(f"{AUGMENTED_DIR}/*.csv") resampled_names = [file_name. csv]。替换(f“{AUGMENTED_DIR} /”,“”)。取代(“X_train_”、“”).replace (file_name . csv, " ")在data_file如果“X_train_”file_name] resampled_names =[名字名字resampled_names如果len(名字)> 0)#加载原始数据X_train = pd.read_csv (f“{PROCESSED_DIR} / X_train.csv”,index_col = None) y_train = pd.read_csv (f“{PROCESSED_DIR} / y_train.csv”,index_col = None) #从原始数据集deepchecks ds_train =数据集(X_train、标签= y_train cat_features =[])在resampled_names resampled_data:print(f" valididating {resampled_data} dataset ----") X_res = pd.read_csv(f"{AUGMENTED_DIR}/X_train_{resampled_data}.csv", index_col=None) y_res = pd.read_csv(f"{AUGMENTED_DIR}/y_train_{resampled_data}.csv", index_col=None) #从重采样数据创建深度检查数据集ds_train_res = dataset (X_res, label=y_res, cat_features=[]) #生成深度检查报告suite = full_suite() suite = suite.run(train_dataset=ds_train,test_dataset = ds_train_res) suite.save_as_html (f“{REPORTS_DIR} / {resampled_data} _report.html”)

我们应该记住,当我们创建一个数据集使用deepchecks,我们需要分别提供重采样的特征和标签。

在运行完整的检查套件之后,我们将报告保存到项目中的指定目录中。由于报告以HTML文件的形式存储,因此它们很容易进行版本化,我们可以与没有安装Python(和所有依赖项)的涉众共享它们。

在下一节中,我们将探讨这些报告的一些部分。最佳电子竞技即时竞猜平台。

深入研究重采样的含义

在本节中,我们将研究数据有效性检查的输出。由于检查非常全面,报告也很长,我们将重点放在最重要/相关的部分。但是,我强烈建议您花些时间来研究完整的报告。最佳电子竞技即时竞猜平台。所考虑的度量以及测试的逻辑和它们潜在的含义都得到了清楚的描述。

通常,运行该套件会得到以下报告:

我们将只探讨报告最佳电子竞技即时竞猜平台。的部分内容,主要在没有通过类别。我们看结果的顺序,我们提出了重采样技术。

1.随机采样

在下表中,我们看到有相当多的检查失败了。

在深入研究其中一些问题之前,我们可以先解决一些简单的问题:

  • 数据集的大小比较-这显然是失败的,因为采样不足的数据集有788个观测值,而完整的数据集有227845个
  • 数据副本-训练数据集而且数据副本-测试数据集-数据集中似乎有重复的数据。我们应该在EDA期间发现这个问题,但数据集中确实有重复的观察结果。然而,这与重采样无关,它们从一开始就在那里。在报告中,我们可以看到哪些行(由它们的索引标识)是重复的。
  • 列车测试样品混合这个检查会调查测试数据中的观察结果是否也出现在训练数据中。由于“测试”数据集是一个重新采样的数据集,很明显,观察结果完全重叠。
  • 列车测试标签漂移这个检查验证两个数据集中类的分布是否相似。为了做到这一点,它使用克莱姆V.这种检查自然失败了,因为在原始数据集中,阳性类只在0.173%的观察中被观察到,而在重新采样的数据集中,这一比例是50-50。

就我们的目的而言,最有趣的检查是关于特性/数据漂移的检查。正如我们所提到的,重采样技术的最大缺点是扭曲了数据集中特征的分布。此外,重采样不仅可以模糊/改变特征本身之间的关系,还可以模糊/改变与目标的关系。我们可以(在某种程度上)在以下测试中观察到这一点。

列车测试特征漂移测试,我们可以观察到两个数据集之间数值特征的分布是如何不同的。所附的漂移分雷竞技网址是数只是对两个分布之间差异的度量。在下面的图中,我们可以看到原始数据集和样本数据集之间差异最大的两个特征。由于使用PCA对特征进行了匿名处理,因此很难对这些差异进行进一步的解释。

为了评估特征漂移是否存在,deepchecks使用土方的距离(瓦瑟斯坦规)的数字特征和克莱姆V为分类特征。我们不会深入讨论指标的细节,因为这可以作为单独文章的主题。值得一提的是,特征漂移是使用100000个观测样本计算的。我们可以通过传入n_samples论点。

第二个测试被调用整个数据集漂移在它中,一个单独的分类器被训练来区分两个数据集。下图中给出的特征是对域分类器最重要的特征。被解释数据集差异的相应百分比是使用排列重要性计算的特征重要性值。你可以阅读更多关于排列重要性的内容在这里

最后一个有趣的测试是特征标签相关性变化,它使用预测能力得分估计每个特征预测目标标签的能力。

使用图表和测试摘要(也在本节的开头给出),我们可以得出以下结论:

  • 训练集中一些特征的PPS高于确定的阈值——通常这是数据泄漏的迹象,因为这样的特征可能包含基于目标标签的信息。
  • 两个数据集的PPS差异很大——在传统的训练-测试分割上下文中,训练PPS显著较大可能表明数据泄漏。特别是,较大的测试PPS可以表示测试集中的漂移,这会导致与目标的巧合相关。

从图中可以看出,对于哪5个特征,原始PPS和重采样PPS的差异最大。这可以清楚地表明我们前面提到的缺点——在特征和目标之间创建虚假的关系。

2.随机采样过密

过采样的数据集也面临着几乎相同的问题。您可以在下面的图中看到摘要。

由于问题非常相似,我们将只分析选定的测试。我们首先要研究的是特征标签相关性变化.与随机欠采样相比,这一次所有特征都违反了“Train-Test特征的预测能力得分差异小于0.2”的准则。正如我们所看到的,PPS值对于过采样的数据集来说更加极端。有趣的是,对于这两种重采样方法,V14和V3特性都在受影响最大的5个特性之列。

过采样数据集未能通过新测试,这也与PPS有关。的特征标签相关性-测试数据集test返回与目标相关的所有特征的PPS。因此,它可以用作数据泄漏的指示。对于这个重新采样的数据集,29个特征中有28个受到了影响。

3.击杀

使用SMOTE重新采样的数据集也存在大多数已经讨论过的问题。因此,我们不会花更多的时间来解释它们的含义。

不过,我们将提及以下不同点:

  • 用SMOTE重新采样的数据集受到的问题最少deepchecks
  • 列车测试样品混合Test的值与前面的例子有很大的不同。以前,我们处理的数据集几乎100%重叠,因为我们要么是重复观测,要么是从已有的观测中随机选择一些观测。使用SMOTE,该值接近50%,这直观上是有意义的,因为大约一半的观察结果应该是由算法生成的新的综合观察结果。

使用GitHub Actions自动化数据验证

每次更改数据时,手动运行数据验证检查可能有点繁琐且容易出错。多亏了GitHub Actions,我们可以很容易地将这一点和工作流程的许多其他部分自动化。例如,我们可以创建一个操作,该操作在每次修改CSV文件(原始的或重新采样的)或用于生成它们的数据或脚本时运行。一旦被触发,该操作将加载带有DVC版本的数据,运行数据验证脚本,提交新的数据验证报告,并将更改推入存储库。所有这些都通过一个简短的YAML脚本自动完成。

您可以找到我用于创建这样一个操作的代码在这里.在我的另一篇文章,我已经提供了详细的描述的过程。

用各种重采样技术评估随机森林模型的性能

为了完成分析,我们还使用原始数据及其重采样对应数据训练了一个随机森林模型(使用默认设置)。下面我们给出了评估结果。

当我们处理不平衡的类时,我们关注的是精度、召回率和F1-Score(前两个指标的调和平均值)等指标。在分析结果后,我们可以声明:

  • 不使用任何重采样方法会导致测试集中的最高f1得分。
  • 采样不足导致召回率最高,代价是精确度非常低。
  • 在过采样方法中,随机过采样的精度和f1得分均高于SMOTE。另一方面,来自少数民族班级的综合观察有助于提高回忆,但代价是精度略低。

外卖

在本文中,我们提出了一种可能的方法来研究各种重采样技术如何影响数据中存在的模式。正如我们所看到的,在处理高度不平衡的类时,重新采样可以提高模型的性能。然而,这种方法也伴随着一些问题,我们一定要意识到。

对于我们的分析,我们使用了可用的默认检查deepchecks图书馆。该库还提供了添加自定义检查和修改用于识别问题的阈值的可能性。当我们想要创建适合我们需求的定制数据验证管道时,这绝对可以派上用场。

一如既往,任何建设性的反馈都是非常欢迎的。你可以在推特.您可以在中找到本文使用的所有代码这个存储库

参考文献

标签

Eryk Lewinson

高级数据科学家,书籍作者,技术作家

太棒了!您已经成功订阅。
太棒了!接下来,完成签出以获得完全访问权限。
欢迎回来!您已经成功登录。
成功!您的帐户已完全激活,您现在可以访问所有内容。