我们将介绍几种处理不平衡数据集的替代方法,包括带有代码示例的不同重采样和组合方法。
分类是最常见的机器学习问题之一。接近任何分类问题的最佳方式是通过分析和探索我们所说的数据集开始Exploratory Data Analysis(EDA)此练习的唯一目的是生成有关数据的尽可能多的见解和信息。它还用于查找数据集中可能存在的任何问题。在用于分类的数据集中发现的常见问题之一是不平衡类问题。
什么是数据不平衡?
数据不平衡通常反映出数据集中类的不平等分布。例如,在信用卡欺诈检测数据集中,大多数信用卡交易不是欺诈,只有极少数类别是欺诈交易。这使我们在欺诈和非欺诈类之间的比率为50:1。在本文中,我将使用Kaggle的信用卡欺诈交易数据集,该数据集可从此处下载 。
首先,让我们绘制类分布以查看不平衡。
如您所见,非欺诈交易远远超过欺诈交易。如果我们在不解决此问题的情况下训练二进制分类模型,则该模型将完全有偏差。它还会影响要素之间的相关性,稍后我将向您展示如何以及为什么。
现在,让我们介绍一些解决类不平衡问题的技术。您可以在此处找到带有完整代码的笔记本
这听起来很直观。欠采样是您从多数类中随机删除一些观测值以使数字与少数类相匹配的过程。下面的代码显示了一种简单的方法:
# Shuffle the Dataset.
shuffled_df = credit_df.sample(frac=1,random_state=4)
# Put all the fraud class in a separate dataset.
fraud_df = shuffled_df.loc[shuffled_df['Class'] == 1]
#Randomly select 492 observations from the non-fraud (majority class)
non_fraud_df = shuffled_df.loc[shuffled_df['Class'] == 0].sample(n=492,random_state=42)
# Concatenate both dataframes again
normalized_df = pd.concat([fraud_df, non_fraud_df])
#plot the dataset after the undersampling
plt.figure(figsize=(8, 8))
sns.countplot('Class', data=normalized_df)
plt.title('Balanced Classes')
plt.show()
对多数阶层的采样不足
在对数据集进行欠采样之后,我再次对其进行了绘制,并显示了相等数量的类:
平衡数据集(欠采样)
第二种重采样技术称为过采样。这个过程比欠采样要复杂一些。生成合成数据的过程试图从少数类的观察中随机生成属性样本。对于典型的分类问题,有多种方法可以对数据集进行过采样。最常见的技术称为SMOTE(综合少数族裔过采样技术)。简单来说,它查看少数类数据点的特征空间,并考虑其 k个 最近的邻居。
为了用python编写代码,我使用了一个名为 imbalanced -learn或imblearn的库 。 下面的代码显示了如何实现SMOTE。
from imblearn.over_sampling import SMOTE
# Resample the minority class. You can change the strategy to 'auto' if you are not sure.
sm = SMOTE(sampling_strategy='minority', random_state=7)
# Fit the model to generate the data.
oversampled_trainX, oversampled_trainY = sm.fit_sample(credit_df.drop('Class', axis=1), credit_df['Class'])
oversampled_train = pd.concat([pd.DataFrame(oversampled_trainY), pd.DataFrame(oversampled_trainX)], axis=1)
oversampled_train.columns = normalized_df.columns
还记得我说过不平衡的数据将如何影响功能相关性吗?让我向您展示治疗不平衡班级前后的相关性。
下面的代码绘制了所有要素之间的相关矩阵。
# Sample figsize in inches
fig, ax = plt.subplots(figsize=(20,10))
# Imbalanced DataFrame Correlation
corr = credit_df.corr()
sns.heatmap(corr, cmap='YlGnBu', annot_kws={'size':30}, ax=ax)
ax.set_title("Imbalanced Correlation Matrix", fontsize=14)
plt.show()
注意,特征相关性现在更加明显。在解决不平衡问题之前,大多数功能都没有显示任何相关性,这些相关性肯定会影响模型的性能。由于 特征相关 对整个模型的性能确实很重要,因此修复不平衡很重要,因为它也会影响ML模型的性能。
在机器学习中,集成方法使用多种学习算法和技术来获得比仅从任何组成学习算法中获得的性能更好的性能。(是的,就像民主投票制度一样)。当使用集成分类器时,装袋方法变得很流行,并且它通过在不同的随机选择的数据子集上构建多个估计器来工作。在scikit-learn库中,有一个名为BaggingClassifier的整体分类器。但是,此分类器不允许平衡数据的每个子集。因此,在对不平衡数据集进行训练时,该分类器将偏爱多数类并创建有偏模型。
为了解决这个问题,我们可以用 BalancedBaggingClassifier 从 imblearn 库。它允许在训练集合的每个估计量之前对数据集的每个子集进行重采样。因此, 除了控制随机采样器行为的另外两个参数sample_strategy和replace之外,BalancedBaggingClassifier的参数与scikit-learn BaggingClassifier相同。这是一些代码,显示了如何执行此操作:
from imblearn.ensemble import BalancedBaggingClassifier
from sklearn.tree import DecisionTreeClassifier
#Create an object of the classifier.
bbc = BalancedBaggingClassifier(base_estimator=DecisionTreeClassifier(),
sampling_strategy='auto',
replacement=False,
random_state=0)
y_train = credit_df['Class']
X_train = credit_df.drop(['Class'], axis=1, inplace=False)
#Train the classifier.
bbc.fit(X_train, y_train)
preds = bbc.predict(X_train)
使用集成采样器训练不平衡数据集
这样,您可以训练一个可以处理不平衡的分类器,而无需在训练前手动进行过采样或过采样。
总之,每个人都应该知道,建立在不平衡数据集上的ML模型的整体性能将受到其预测稀有点和少数点的能力的限制。识别和解决这些问题的不平衡性对于所生成模型的质量和性能至关重要。