如何在深度神经网络中实施欠采样、过采样和SMOTE技术

282 阅读13分钟

在深度神经网络中实施欠采样、过采样和SMOTE技术

在深度神经网络(DNN)中,目标是实现各种机器学习技术,以便在使用数据集之前平衡各个类别。本教程将实现欠采样、过采样和SMOTE技术来平衡数据集。

深度神经网络是一种人工神经网络,在输入和输出层之间有许多隐藏层。它使用不同的数据集来产生一个深度学习模型。最终的模型可以进行图像分类、计算机视觉和自然语言处理。

它可以使用平衡或不平衡的数据集。平衡数据集是最好的,因为它将产生一个优化的深度学习模型。一个不平衡的数据集在数据集类别中的数据样本数量不相等,不会给出最佳模型。

我们的目标是在使用数据集之前实施各种机器学习技术来平衡类。我们将实施欠采样、过采样和SMOTE技术来平衡数据集。

我们将首先使用不平衡的数据集建立一个深度神经网络模型,并获得性能得分。然后我们将实施这三种技术来平衡数据集的类别,并比较平衡数据集前后模型的性能得分。

前提条件

为了更好地理解本教程中实现的技术,读者应该。

  • 具备[Python编程]知识。
  • 了解[深度学习](。
  • 知道一些[深度学习的算法]。
  • 理解[神经网络]。
  • 知道如何[用TensorFlow的Keras]实现一个简单的[神经网络]。
  • 使用[谷歌Colab]来实现技术。

使用不平衡的数据集建立深度神经网络模型

我们将建立一个客户流失分类模型。该模型将预测将关闭账户并离开银行的客户数量。我们将使用一个不平衡的数据集来建立这个模型。

下载数据集后,我们将使用Pandas将数据集加载到我们的项目中。

import pandas as pd

要加载数据集,请使用这段代码。

df = pd.read_csv("/content/customer_churn_final.csv")

我们还可以用这段代码显示一些数据点。

df.head()

该代码显示以下数据点。

Imbalanced dataset

让我们进一步探索我们的不平衡数据集,对数据集有一个详细的了解。

计算每个类中的数据样本

我们的数据集有两个类1 和一个0 类。1 类代表将离开银行的客户,而0 类代表将不离开银行的客户。计算每个类中的数据样本将使我们能够看到类的不平衡性。

df.Churn.value_counts()

该代码将显示以下输出。

Counting the data samples

0 类有5163个数据样本,而1 类有1869个数据样本。这表明我们有一个类的不平衡,我们将在以后实施三种技术时平衡这些类。0 类是不平衡数据集中的多数类,而1 类是少数类。

打印所有的列

要打印所有的列,请输入这段代码。

print(df.columns)

该代码将打印以下列。

Printing columns

这些是数据集的所有列。我们必须从这个列表中选择输入和输出列。

选择输入和输出列

我们选择输入列的方法如下。

X = df.drop('Churn',axis='columns')

输入列是所有的列,除了churn 列。我们将它们保存在X 变量中。我们选择输出列的方式如下。

y = testLabels = df.Churn.astype(np.float32)

输出列是Churn 列。我们把它保存在y 变量中。

培训和测试分割

我们将把不平衡的数据集分成训练和测试样本。我们将使用train_test_split 类来拆分不平衡数据集。要导入这个类,请执行这段代码。

from sklearn.model_selection import train_test_split

然后我们对数据样本进行如下分割。

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=15)

使用这段代码,80%的数据样本将用于深度神经网络训练,20%将用于测试。我们还检查了训练集的每个类中的数据样本数量,如下所示。

y_train.value_counts()

它给出的输出如下。

Train value count

我们还可以检查测试集的每一类数据样本的数量,如下所示。

y_test.value_counts()

它给出了以下数字。

Test value count

我们已经探索并准备好了不平衡数据集。让我们来实现深度神经网络。

实现深度神经网络

我们将使用Keras来创建深度神经网络的层。让我们导入TensorFlow,然后从TensorFlow导入Keras。

import tensorflow as tf
from tensorflow import keras

初始化顺序模型

一个Sequential Keras模型将使我们能够按顺序(逐层)建立深度神经网络的多个层。我们将初始化输入层、隐藏/中间层和输出层。这些层将产生最终的深度神经网络模型。让我们来初始化所有的层并解释它们的功能。

dnn_model = keras.Sequential([
    keras.layers.Dense(26, input_shape=(26,), activation='relu'),
    keras.layers.Dense(15, activation='relu'),
    keras.layers.Dense(1, activation='sigmoid')
])

Sequential 函数将初始化该模型。深度神经网络有多个Dense 层,如下所示。

  • 第一密集层。它作为输入层。它有26个神经元,因为这是输入列的数量。我们应用relu 作为激活函数,因为该层的输出将在0和正无穷值之间。

  • 第二密集层。它充当了隐藏/中间层。它有15个神经元,进一步提高了性能。我们还应用了relu 激活函数。

  • 第三密集层。它充当输出层。它有一个神经元,将输出神经网络的结果。我们可以应用sigmoid 作为激活函数,因为输出将在0和1之间。

编译深度神经网络

为了编译深度神经网络,在Google Colab中执行这段代码。

dnn_model.compile(optimizer='adam',
              loss='binary_crossentropy',
              metrics=['accuracy'])

我们使用compile 函数来编译深度神经网络架构。编译过程也有以下基本参数。

  • 优化器:它将改善和提高深度神经网络的性能。它还可以处理深度神经网络的错误。我们在编译过程中应用adam 作为深度神经网络的优化器。

  • 损失:它是一个函数,将计算和积累神经网络在训练过程开始时遇到的所有错误。我们使用binary_crossentropy ,因为不平衡的数据集有两个类。

  • 度量:这是一个函数,在训练过程结束后,它将获得整个深度神经网络的性能分数。我们将其值设置为accuracy

拟合编译后的深度神经网络

为了将编译好的深度神经网络拟合到训练样本上,在Google Colab中执行这段代码。

dnn_model.fit(X_train, y_train, epochs=100)

编译后的深度神经网络使用fit 函数,从训练样本中学习。深度神经网络将运行100个epochs,以提高整体性能分数。该代码将显示以下输出。

Fitting the deep neural network

深度神经网络产生的最终准确度分数为0.8064 。在评估一个使用不平衡数据集的模型的性能时,我们不能使用准确度分数,因为该模型会对多数类有偏见。即使模型有很高的准确率得分,它也会一直预测同一个类别。

因此,我们使用召回率精确度F1分数的性能分数。它们关注的是神经网络进行预测后各个类的表现。

性能分数

  • 精度。精度性能得分表示预测结果中的真阳性值除以所有预测值(包括真阳性和假阳性值)。

  • 召回率。召回率表示预测结果中的真阳性值除以测试样本中的实际值数量。它代表了深度神经网络在预测后未能识别的真阳性值。

  • F1-score。F1-score计算精度和召回性能分数的平均值。

让我们使用测试样本进行预测并获得性能分数。然后我们将打印一份分类报告,以显示这两个类别的性能分数。

使用测试样本进行预测

要使用测试样本进行预测,请执行这段代码。

dnn_pred = dnn_model.predict(X_test)

预测的输出是0和1之间的概率(可以是小数)。我们必须把结果四舍五入到最接近的整数。

我们使用NumPy的round 方法。

import numpy as np
dnn_pred = np.round(dnn_pred)

导入分类报告

让我们导入将打印性能分数的classification_report

from sklearn.metrics import confusion_matrix , classification_report

为了打印分类报告,执行这段代码。

print(classification_report(y_test,dnn_pred))

这段代码显示了以下分类报告。

Classification report

仔细观察两个类(0和1)的精度、召回率和f1分数值。你会注意到,0 类的分数值比1 类高。这两个类的分数需要几乎一致,以确保我们可以信任这个模型。

使用三种技术实现数据集的平衡将确保我们对两个类都给予公平的对待。它将提高少数群体的性能得分。

在实施这三种技术后,我们将比较精度、召回率和f1分数,以查看任何改进。让我们从实施欠抽样技术开始。

实施低取样技术

下采样技术将减少多数类(0)的数据样本,使其与少数类的样本数量相同。我们将使用Pandas的sample 方法来执行欠采样。让我们执行这段代码来记录每个类中数据样本的数量。

count_majority_class, count_minority_class = df.Churn.value_counts()

然后我们在新的变量中保存多数类和少数类,如下所示。

df_majority_class = df[df['Churn'] == 0]
df_minority_class = df[df['Churn'] == 1]

现在让我们应用sample 方法,如下所示。

df_class_undersample = df_majority_class.sample(count_minority_class)

我们将未采样的多数派类与少数派类连接起来。这将形成一个单一的数据框。

df_balanced = pd.concat([df_class_undersample, df_minority_class], axis=0)

然后我们打印新的平衡数据集中的数据样本数。

print('Number of data samples after under-sampling:')
print(df_balanced.Churn.value_counts())

它打印的输出结果如下。

Data samples after undersampling

我们可以看到,这两个班级有相同的数据样本。我们已经实现了一个平衡的数据集。让我们从平衡数据集中选择输入和输出列,如下所示。

X = df_balanced.drop('Churn',axis='columns')
y = df_balanced['Churn']

我们还需要得到训练和测试分片,如下所示。

X_train_bus, X_test_bus, y_train_bus, y_test_bus = train_test_split(X, y, test_size=0.2, random_state=15, stratify=y)

stratify 参数将确保拆分后的类别保持平衡。我们也使用相同的分割比例。我们再次将数据集送入我们的深度神经网络,如下所示。

dnn_model.fit(X_train_bus, y_train_bus, epochs=100)

该代码将使用平衡的数据集训练深度神经网络,并显示以下输出。

Training after undersampling

我们也不会使用准确性来衡量深度神经网络的性能。让我们进行预测并得到分类报告。

实施低采样后进行预测

我们执行这段代码。

dnn_preds_bus = dnn_model.predict(X_test_bus)

然后我们执行这段代码,对预测概率进行舍入。

dnn_preds_bus = np.round(dnn_preds_bus)

实施欠抽样后的分类报告

要打印分类报告,执行这段代码。

print(classification_report(y_test_bus,dnn_preds_bus))

Classification report after undersampling

从分类报告中,观察1 类别的精度、召回率和f1分数值。我们可以看到,与使用不平衡的数据集相比,分数有所提高。

  • 精度从0.64提高到0.73。
  • 召回率从0.40提高到0.76。
  • f-score从0.49提高到0.75。

这些分数对两类来说也几乎是统一的。它确保了在分类过程中对两个数据集类别的公平对待。

让我们转到超采样技术。

实施超量取样技术

过度取样技术将增加少数类(1)的数据样本,使其与多数类的数据样本数量相同。它将会重复少数类中的数据样本。我们还将使用Pandassample 方法来进行超量取样。

df_class_oversample = df_minority_class.sample(count_majority_class, replace=True)

在应用sample 方法后,我们将超额取样的少数群体类与多数群体类连接起来。这将形成一个单一的数据框。

df_balanced_os = pd.concat([df_class_oversample, df_majority_class], axis=0))

然后我们打印新的平衡数据集中的数据样本数。

print('Number of data samples after over-sampling:')
print(df_balanced_os.Churn.value_counts())

它打印的输出结果如下。

Data samples after oversampling

我们可以看到,两个班级有相同的数据样本。我们已经实现了一个平衡的数据集。让我们也从平衡数据集中选择输入和输出列,如下所示。

X = df_balanced.drop('Churn',axis='columns')
y = df_balanced['Churn']

我们还需要得到训练和测试分片,如下所示。

X_train_bos, X_test_bos, y_train_bos, y_test_bos = train_test_split(X, y, test_size=0.2, random_state=15, stratify=y)

我们将数据集送入我们的深度神经网络,如下所示。

dnn_model.fit(X_train_bos, y_train_bos, epochs=100)

该代码将使用平衡数据集训练深度神经网络,并显示以下输出。

Training after undersampling

我们也不会使用准确性来衡量深度神经网络的性能。让我们进行预测并得到分类报告。

实施超采样后进行预测

我们执行这段代码。

dnn_preds_bos = dnn_model.predict(X_test_bos)

然后我们执行这段代码,对预测概率进行舍入。

dnn_preds_bos = np.round(dnn_preds_bos)

实施超抽样后的分类报告

要打印分类报告,执行这段代码。

print(classification_report(y_test_bos,dnn_preds_bos))

Classification report after oversampling

从分类报告中,观察1 类别的精度、召回率和f1分数。我们可以看到,这些分数也得到了改善。

这项技术的表现要好得多。

  • 精度从0.64提高到0.75。
  • 召回率从0.40提高到0.86。
  • f-score从0.49提高到0.80。

让我们来看看SMOTE技术。

实施SMOTE技术

合成少数人过量取样技术(SMOTE)是一种机器学习技术,可以平衡数据集的类别。它为少数人类别生成合成和独特的数据样本,以实现平衡的数据集。我们将从Imbalanced-learn 中导入SMOTE。要安装Imbalanced-learn ,在Google Colab中执行此命令。

! pip install imbalanced-learn

要导入SMOTE,执行此命令。

from imblearn.over_sampling import SMOTE

然后我们选择输入和输出列,如下所示。

X = df.drop('Churn',axis='columns')
y = df['Churn']

为了平衡数据集,执行这个代码。

smote_technique = SMOTE(sampling_strategy='minority')
X_smt, y_smt = smote_technique.fit_resample(X, y)

SMOTE 函数使用sampling_strategy 参数来平衡类。要显示新的平衡数据集中的数据样本的数量,执行这段代码。

y_smt.value_counts()

它显示如下。

Data samples after SMOTE

我们可以看到,两个类有相同的数据样本。让我们得到训练和测试的分割,如下所示。

X_train_smt, X_test_smt, y_train_smt, y_test_smt = train_test_split(X_smt, y_smt, test_size=0.2, random_state=15, stratify=y_smt)

然后我们将数据集送入深度神经网络。

dnn_model.fit(X_train_smt, y_train_smt, epochs=100)

Training using SMOTE

我们不会用准确性来衡量深度神经网络的性能。让我们进行预测并得到分类报告。

实施SMOTE后进行预测

要在应用SMOTE后进行预测,请执行此代码。

dnn_preds_smt = dnn_model.predict(X_test_smt)
dnn_preds_smt = np.round(dnn_preds_smt)

实施SMOTE后的分类报告

要在应用SMOTE后获得分类报告,请执行此代码。

print(classification_report(y_test_smt,dnn_preds_smt))

Classification report after applying SMOTE

从分类报告中,观察1 类的精度、召回率和f1-score。

我们可以看到分数也有提高。

  • 精度从0.64提高到0.75。
  • 召回率从0.40提高到0.89。
  • f1分数从0.49增加到0.82。

使用这三种技术,我们已经平衡了数据集并提高了性能分数。

总结

我们已经学会了如何在深度神经网络中处理不平衡的数据集。我们实现了欠采样、过采样和SMOTE技术。我们首先使用不平衡的数据集建立了深度神经网络模型,并得到了性能得分。我们正在建立一个客户流失分类模型。然后我们实施了这三种技术来平衡数据集,也得到了性能分数。