Path: blob/master/site/zh-cn/tutorials/structured_data/imbalanced_data.ipynb
25118 views
Copyright 2019 The TensorFlow Authors.
不平衡数据的分类
本教程演示了如何对高度不平衡的数据集进行分类,在此类数据集中,一类中的样本数量远多于另一类中的样本数量。您将使用 Kaggle 上托管的 Credit Card Fraud Detection 数据集,目的是从总共 284,807 笔交易中检测出仅有的 492 笔欺诈交易。您将使用 Keras 来定义模型和类权重,从而帮助模型从不平衡数据中学习。
本教程包含下列操作的完整代码:
使用 Pandas 加载 CSV 文件。
创建训练、验证和测试集。
使用 Keras 定义并训练模型(包括设置类权重)。
使用各种指标(包括精确率和召回率)评估模型。
尝试使用常见技术来处理不平衡数据,例如:
类加权
过采样
设置
数据处理与浏览
下载 Kaggle Credit Card Fraud 数据集
Pandas 是一个 Python 库,其中包含许多有用的实用工具,用于加载和使用结构化数据,并可用于将 CSV 下载到数据帧中。
注:Worldline 和 ULB(布鲁塞尔自由大学)机器学习小组在大数据挖掘和欺诈检测的合作研究期间,已对此数据集进行了收集和分析。与相关主题当前和过去项目有关的详细信息,请访问这里和 DefeatFraud 项目页面。
检查类标签的不平衡
让我们看一下数据集的不平衡情况:
这表明正样本的比例很小。
清理、拆分和归一化数据
原始数据有一些问题。首先,Time
和 Amount
列变化太大,无法直接使用。删除 Time
列(因为不清楚其含义),并获取 Amount
列的日志以缩小其范围。
将数据集拆分为训练、验证和测试集。验证集在模型拟合期间使用,用于评估损失和任何指标,判断模型与数据的拟合程度。测试集在训练阶段完全不使用,仅在最后用于评估模型泛化到新数据的能力。这对于不平衡的数据集尤为重要,因为过拟合是缺乏训练数据造成的一个重大问题。
使用 sklearn StandardScaler 将输入特征归一化。这会将平均值设置为 0,标准偏差设置为 1。
注:StandardScaler
只能使用 train_features
进行拟合,以确保模型不会窥视验证集或测试集。
小心:如果要部署模型,保留预处理计算至关重要。这是将它们实现为层并在导出之前将它们附加到模型最简单的方法。
查看数据分布
接下来通过一些特征比较一下正样本和负样本的分布。此时,建议您问自己如下问题:
这些分布是否有意义?
是。您已对输入进行了归一化处理,而它们大多集中在
+/- 2
范围内。
您是否能看出分布之间的差异?
是。正样本包含极值的比率高得多 。
定义模型和指标
定义一个函数,该函数会创建一个简单的神经网络,其中包含一个密集连接的隐藏层、一个用于减少过拟合的随机失活层,以及一个返回欺诈交易概率的输出 Sigmoid 层:
了解有用的指标
请注意,上面定义的一些指标可以由模型计算得出,这对评估性能很有帮助。
假负例和假正例是被错误分类的样本
真负例和真正例是被正确分类的样本
准确率是被正确分类的样本的百分比
精确率是被正确分类的预测正例的百分比
召回率是被正确分类的实际正例的百分比
AUC 是指接收器操作特征曲线中的曲线下方面积 (ROC-AUC)。此指标等于分类器对随机正样本的排序高于随机负样本的概率。
AUPRC 是指精确率-召回率曲线下方面积。该指标计算不同概率阈值的精度率-召回率对。
注:准确率在此任务中不是一个有用的指标。只要始终预测“False”,您就可以在此任务中达到 99.8%+ 的准确率。
延伸阅读:
基线模型
构建模型
现在,使用先前定义的函数创建并训练模型。请注意,该模型使用大于默认的批次大小 (2048) 来进行拟合,这一点很重要,有助于确保每个批次都有一定机会包含少量正样本。如果批次过小,它们可能会没有可供学习的欺诈交易。
注:此模型无法很好地处理类不平衡问题。我们将在本教程的后面部分对此进行改进。
试运行模型:
可选:设置正确的初始偏差。
模型最初的猜测不太理想。您知道数据集不平衡,因此需要设置输出层的偏差以反映这种不平衡(请参阅:训练神经网络的秘诀:“好好初始化”)。这样做有助于初始收敛。
使用默认偏差初始化时,损失应约为 math.log(2) = 0.69314
。
可以用以下代码推导出要设置的正确偏差:
将其设置为初始偏差,模型将给出合理得多的初始猜测。
结果应该接近:pos/total = 0.0018
使用此初始化,初始损失应约为:
此初始损失大约是使用朴素初始化时损失的 50 倍。
这样,模型就不需要花费前几个周期去仅仅了解不可能有正样本。这也使得在训练过程中更容易读取损失图。
为初始权重设置检查点
为了使各种训练运行更具可比性,请将这个初始模型的权重保存在检查点文件中,并在训练前将它们加载到每个模型中:
确认偏差修正有帮助
在继续之前,迅速确认这一细致偏差初始化是否确实起了作用。
在使用和不使用此细致初始化的情况下,将模型训练 20 个周期,并比较损失:
上图清楚表明:就验证损失而言,在这个问题上,此细致初始化具有明显优势。
训练模型
查看训练历史记录
在本部分,您将针对训练集和验证集生成模型的准确率和损失绘图。这些对于检查过拟合十分有用,您可以在此教程中了解更多信息。
此外,您还可以为您在上面创建的任何指标生成上述绘图。假负例包含在以下示例中。
注:验证曲线通常比训练曲线表现更好。这主要是由于在评估模型时,随机失活层处于非活动状态。
评估指标
您可以使用混淆矩阵来汇总实际标签与预测标签,其中 X 轴是预测标签,Y 轴是实际标签:
在测试数据集上评估您的模型并显示您在上面创建的指标的结果:
如果模型完美地预测了所有内容,则这是一个对角矩阵,其中偏离主对角线的值(表示不正确的预测)将为零。在这种情况下,矩阵会显示您的假正例相对较少,这意味着被错误标记的合法交易相对较少。但是,您可能希望得到更少的假负例,即使这会增加假正例的数量。这种权衡可能更加可取,因为假负例允许进行欺诈交易,而假正例可能导致向客户发送电子邮件,要求他们验证自己的信用卡活动。
绘制 ROC
现在绘制 ROC。此绘图非常有用,因为它一目了然地显示了模型只需通过调整输出阈值就能达到的性能范围。
绘制 AUPRC
现在绘制 AUPRC。内插精确率-召回率曲线的下方面积,通过为分类阈值的不同值绘制(召回率、精确率)点获得。根据计算方式,PR AUC 可能相当于模型的平均精确率。
看起来精确率相对较高,但是召回率和 ROC 曲线下方面积 (AUC) 可能并没有您期望的那么高。当试图同时最大限度地提高精确率和召回率时,分类器通常会面临挑战,在处理不平衡数据集时尤其如此。请务必根据您所关心的问题来考虑不同类型错误的代价。在此示例中,假负例(漏掉欺诈交易)可能造成财务损失,而假正例(将交易错误地标记为欺诈)则可能降低用户满意度。
类权重
计算类权重
我们的目标是识别欺诈交易,但您没有很多可以使用的此类正样本,因此您希望分类器提高可用的少数样本的权重。为此,您可以使用参数将 Keras 权重传递给每个类。这些权重将使模型“更加关注”来自代表不足的类的样本。
使用类权重训练模型
现在,尝试使用类权重对模型进行重新训练和评估,以了解其对预测的影响。
注:使用 class_weights
会改变损失范围。这可能会影响训练的稳定性,具体取决于优化器。步长取决于梯度大小的优化器(如 optimizers.SGD
)可能会失效。此处使用的优化器(optimizers.Adam
)不受缩放更改的影响。还要注意,由于加权,两个模型之间的总损失不具可比性。
查看训练历史记录
评估指标
在这里,您可以看到,使用类权重时,由于存在更多假正例,准确率和精确率较低,但是相反,由于模型也找到了更多真正例,召回率和 AUC 较高。尽管准确率较低,但是此模型具有较高的召回率(且识别出了更多欺诈交易)。当然,两种类型的错误都有代价(您也不希望因将过多合法交易标记为欺诈来打扰客户)。请在应用时认真权衡这些不同类型的错误。
绘制 ROC
绘制 AUPRC
过采样
对占少数的类进行过采样
一种相关方法是通过对占少数的类进行过采样来对数据集进行重新采样。
使用 NumPy
您可以通过从正样本中选择正确数量的随机索引来手动平衡数据集:
使用 tf.data
如果您使用的是 tf.data
,则生成平衡样本最简单的方法是从 positive
和 negative
数据集开始,然后将它们合并。有关更多示例,请参阅 tf.data 指南。
每个数据集都会提供 (feature, label)
对:
使用 experimental.sample_from_datasets
将二者合并起来:
要使用此数据集,您需要每个周期的步骤数。
在这种情况下,“周期”的定义就不那么明确了。假设它是遍历一次所有负样本所需的批次数量:
在过采样数据上进行训练
现在尝试使用重新采样后的数据集(而非使用类权重)来训练模型,对比一下这两种方法有何区别。
注:因为数据平衡是通过复制正样本实现的,所以数据集的总大小变大了,且每个周期运行的训练步骤也增加了。
如果训练过程在每次梯度更新时都考虑整个数据集,那么这种过采样将与类加权基本相同。
但是,当按批次训练模型时(如您在上面所做的那样),过采样的数据将提供更加平滑的梯度信号:不在一个权重较大的批次中显示每个正样本,而是在许多具有较小权重的不同批次中分别显示。
这种更平滑的梯度信号使训练模型变得更加容易。
查看训练历史记录
请注意,此处的指标分布将有所不同,因为训练数据与验证和测试数据的分布完全不同。
重新训练
由于在平衡数据上训练更加容易,上面的训练过程可能很快就会过拟合。
因此,请打破周期,使 callbacks.EarlyStopping
能够更好地控制停止训练的时间。
重新查看训练历史记录
评估指标
绘制 ROC
绘制 AUPRC
使用本教程解决您的问题
由于可供学习的样本过少,不平衡数据的分类是固有难题。您应该始终先从数据开始,尽可能多地收集样本,并充分考虑可能相关的特征,以便模型能够充分利用占少数的类。有时您的模型可能难以改善且无法获得想要的结果,因此请务必牢记问题的上下文,并在不同类型的错误之间进行权衡。