[翻译]TabNet-用于结构化表格数据的深层神经网络

  • by

原文链接:https://towardsdatascience.com/tabnet-deep-neural-network-for-structured-tabular-data-39eb4b27a9e4

在这篇文章中,我将向您介绍一个使用Google的TabNet解决分类问题的示例。

尽管最近针对图像、音频和文本的深度神经网络(DNN)出现了爆炸式增长,但使用良好的结构表格数据的任务似乎在某种程度上被忽略了。

虽然今天的许多数据确实是非结构化的(大约80%),但重要的是要正确认识到,用到行和列的数据中仅有20%仍然代表着巨大的数据量。事实上,在2020年,IBM估计全世界的数据收集量为35 zettabytes(或350亿TB)。

这意味着700000000000000字节的数据需要神经网络模型的关注!

平心而论,正如TabNet的原著所指出的,这是因为当前的集成决策树(DT)变体(XGBoost、LightGBM、CatBoost等)在表格数据方面比DNN有一些优势。

然而,自从TabNet发布以来,所有这些都消失了,它在多个基准数据集中的表现优于基于DT的模型。

弗雷明翰心脏研究 Framingham Heart Study

今天,我将介绍一个如何使用TabNet进行分类任务的示例。该数据集包含弗雷明翰心脏研究的结果,该研究始于1948年,对心血管疾病的风险因素提供了(现在仍然提供)重要的见解。对于那些有兴趣了解更多关于这项研究的人,请查看此链接

如果您有兴趣了解更多关于TabNet架构的信息,我鼓励您查看我上面链接的原始文件。其他资源包括这个repo,您可以在这里看到原始的TabNet代码。最后,在我们深入讨论之前,您可以使用我的Notebook

数据

该分析使用的数据由16个变量组成,包括目标变量ANYCHD。下面可以找到每种变量的说明。

表1-数据集中变量的说明
表2-表格格式的数据视图

调查缺失值

接下来,我想看看有多少数据丢失了。使用df.isnull().sum()很容易做到这一点,它将告诉我们每个变量缺少多少数据。另一种方法是使用missingno包,它允许我们非常快速地可视化缺失数据之间的关系。

在图1中,用变量表示缺失值(白色)的矩阵表示。这是按行垂直组织的,这允许我们查看缺少的值之间是否存在任何关系。例如,高密度脂蛋白胆固醇(HDLC)和低密度脂蛋白胆固醇(LDLC)的缺失值是相同的,这表明这些值并不是为该数据集中的一部分患者收集的。

图1-按变量列出的缺失数据矩阵

我们也可以用不同的方法来观察缺失值之间的关系,如图2所示。在这里,我们更容易看到HDLC和LDLC与TOTCHOL之间的关系。值<1意味着它略小于1。由于这些变量中的al 3是胆固醇的测量值,这表明数据集中的某些患者没有收集胆固醇数据。

图2-显示缺失值之间关系的热图

插补缺失值

现在我们已经收集了关于缺失值的信息,我们需要决定如何处理它们。根据您的数据,有许多选项,您可以在sklearn的网页上阅读更多有关各种插补算法的信息

我选择了KNN插补器,您可以使用以下代码实现它。总之,在第一块中,我简单地将数据划分为特征和目标。第二个块使用KNN插补器变换特征。从print语句中可以看出,最初估算的缺失值为1812个。

图3-使用KNN插补器处理数据集中的缺失值

最后一步是分割数据。使用下面的代码,我最初将数据分为70%用于训练集,30%用于验证集。然后,我将验证集分成两个相等的部分,分别用于验证集和测试集。print语句为我们提供了有关拆分后的数据维度

图4-将数据分为训练集、验证集和测试集

TabNet

您可以在几行简单的代码中运行TabNet,如下所示。这是TabNet的pytorch实现,因此您必须导入(或安装,如果尚未安装)torch、pytorch_TabNet和您希望使用的模型(二进制分类器、多分类器、回归器)

您还需要某种指标来评估您的模型。以下是可从sklearn获得的列表。我还包括了一个标签编码,以防您的数据与我的数据略有不同。我的分类变量都是二进制整数,但是如果您将分类存储为字符串,那么您将首先使用它(或者一种替代方法,例如one-hot编码)

图5-导入必要的库

接下来,我们必须定义我们的模型,您可以在下面的第一段代码中看到。在第一行中,我们定义了优化器Adam。接下来的几行将逐步降低我们的学习率。让我们把它说的话拆开:

  • 学习率最初设置为,lr=0.020
  • 10个epoch之后,我们将使用0.9的衰减率
  • 结果就是在学习率0.9上乘上衰减率0.02,这意味着在第10个epoch它将降低到0.018

在下一段代码中,我们将模型与数据相匹配。基本上,它表示将使用auc(曲线下面积)和精度作为总共1000次迭代(历次)的度量来评估训练集和验证集。

patience参数表示,如果在连续50个epoch后未观察到精度的改进,则模型将停止运行,并加载来自最佳epoch的最佳权重。

256的批量大小是根据TabNet论文中的建议选择的,其中他们建议批量大小最多为总数据的10%。他们还建议虚拟批大小(virtual batch size)小于批大小(batch size),并且可以均匀地划分为批大小。

worker数量保留为零,这意味着将根据需要加载批量大小。增加这个数字会非常消耗内存。

权重可以是0(无采样)或1(自动采样)。最后,如果训练期间未完成,则丢弃最后一批。

需要注意的是,其中许多都是默认参数。您可以在此处查看完整的参数列表。

图6-定义和拟合TabNet分类器

该分析的结果如图8所示,可以使用下面的代码进行复制。前三个代码块绘制了损失分数、准确性(针对训练集和验证集)和特征重要性(针对测试集)。

最后的模块只计算验证集和测试集的最佳精度,分别为68%和63%。

图7-绘制损失分数、准确性和特征重要性
图8-(左)损失分数(中等)训练(蓝色)和验证(橙色)集的准确性(右)相对特征重要性

无监督预训练

TabNet也可以作为无监督模型进行预训练。预训练包括故意屏蔽某些神经元,并通过预测屏蔽值来学习这些神经元与相邻列之间的关系。然后,可以保存所学习的权重,并将其用于监督任务。

让我们看看使用无监督预训练如何影响我们的模型准确性!

虽然类似,但代码有一些差异,因此我在下面将其包括在内。具体来说,您必须导入TabNetPretrainer。您可以在第一段代码中看到,TabNetClassifier被TabNetPretrainer替换。

拟合模型时,请注意最后一行pretraining_ratio,它是预训练期间遮罩的特征的百分比。值为0.8表示80%的特征被遮罩。

下一个代码块是指从TabNet的编码表示生成的重构特征。这些文件将被保存,然后可用于单独的受监督任务。

图9-使用TabNet的无监督表示学习

当对该数据集使用预训练时,验证集和测试集的结果准确率分别为76%和71%。这是一个显著的进步!下面,您可以看到损失分数、训练集(蓝色)和验证集(橙色)的准确性,以及测试集确定的特征重要性。

图10-(左)损失分数(中等)训练(蓝色)和验证(橙色)集的准确性(右)相对特征重要性

总结

在这篇文章中,我们介绍了一个如何为分类任务实现TabNet的示例。我们发现,使用TabNet进行无监督预训练显著提高了模型的准确性。

在下面的图11中,我绘制了有监督(左)和无监督(右)模型的特征重要性。有趣的是,无监督的预训练能够提高模型的准确性,同时减少特征的数量。

当我们考虑特征之间的关系时,这是有意义的。例如,使用TabNet进行预训练可以了解到,血压药物(BPMED)、收缩压(SYSBP)和舒张压(DIBP)是相关的。因此,无监督表示学习作为有监督学习任务的高级编码模型,具有更清晰和更可解释的结果。

图11-有监督(左)和无监督(右)选项卡网络模型的特征重要性值

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.