歡迎光臨
每天分享高質量文章

學習| 如何處理不平衡資料集

編者按:資料集的標的變數分佈不平衡問題是一個常見問題,它對特征集的相關性和模型的質量與性能都有影響。因此,在做有監督學習的時候,處理類別不平衡資料集問題是必要的。我創建了Python語言微信群,定位:Python語言學習與實踐,若是想入群,請添加我的微信luqin360,備註:Python語言入群。

分類是機器學習中最常見的問題之一。處理任何分類問題的最佳方法是從分析和探索資料集開始,我們稱之為探索性資料分析(EDA)。唯一目的是生成盡可能多的關於資料的見解和信息。它還用於查找資料集中可能存在的任何問題。在用於分類的資料集中發現的一個常見問題是不平衡類問題。

什麼是資料不平衡?

資料不平衡通常反映資料集中類的不均勻分佈。例如,在信用卡欺詐檢測資料集中,大多數信用卡交易都不是欺詐,只有很少的類是欺詐交易。這使得我們在欺詐類和非欺詐類之間的比例約為50:1。在本文中,我將使用Kaggle中的信用卡欺詐交易資料集,可以從這裡下載。

首先,讓我們繪製類分佈以查看不平衡。

如您所見,非欺詐交易遠遠超過欺詐交易。如果我們訓練一個二分類模型而不解決這個問題,這個模型將會完全有偏差。它還影響特性之間的相關性,稍後我將向您介紹How 和 Why。

現在,讓我們討論一些解決類不平衡問題的技術。在這裡可以找到一個完整代碼的筆記本。

1-重採樣(過採樣和欠採樣)

這聽起來很直觀。欠採樣是一個過程,在這個過程中,您從多數類中隨機刪除一些觀察結果,以便與少數類中的數字匹配。一種簡單的方法如下麵的代碼所示:

# 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(Synthetic Minority Over-sampling Technique)。簡單地說,它查看少數類資料點的特征空間,並考慮它的k個最近鄰。

來源:https://imbalanced-learn.readthedocs.io/en/stable/over_sampling.html

要用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模型的性能。

2-集成方法(採樣器集成)

在機器學習中,集成方法使用多種學習演算法和技術來獲得比單獨使用任何一種組成學習演算法更好的性能。(是的,就像民主黨的投票制度一樣)。當使用集成分類器時,bagging方法變得流行起來,它通過在不同隨機選擇的資料子集上構建多個估計器來工作。在scikit-learn庫中,有一個名為baggingclassifier的集成分類器。但是,這個分類器不會平衡資料的每個子集。因此,當對不平衡資料集進行訓練時,該分類器將有利於大多數類,並創建一個有偏差的模型。

為瞭解決這個問題,我們可以使用imblearn庫中的BalancedBaggingClassifier。它允許在訓練集合的每個估計器之前對資料集的每個子集進行重新採樣。因此,BalancedBaggingClassifier除了使用sampling_strategy和replace這兩個控制隨機採樣器行為的引數外,還使用了與scikit-learn baggingclassifierwith相同的引數。下麵是一些代碼,展示瞭如何做到這一點:

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模型的總體性能將受到其預測罕見點和少數點的能力的限制。識別和解決這些點之間的不平衡對生成模型的質量和性能至關重要。

原文鏈接:
https://www.kdnuggets.com/2019/05/fix-unbalanced-dataset.html

你若是覺得有用,清點贊並分享給其它朋友。更多資料知識,請點擊閱讀原文。您有任何問題,請留言。

赞(0)

分享創造快樂