1. 程式人生 > >不平衡資料集的處理

不平衡資料集的處理

一、不平衡資料集的定義

 所謂的不平衡資料集指的是資料集各個類別的樣本量極不均衡。以二分類問題為例,假設正類的樣本數量遠大於負類的樣本數量,通常情況下通常情況下把多數類樣本的比例接近100:1這種情況下的資料稱為不平衡資料。不平衡資料的學習即需要在分佈不均勻的資料集中學習到有用的資訊。

不平衡資料集的處理方法主要分為兩個方面:

1、從資料的角度出發,主要方法為取樣,分為欠取樣和過取樣以及對應的一些改進方法。

2、從演算法的角度出發,考慮不同誤分類情況代價的差異性對演算法進行優化,主要是基於代價敏感學習演算法(Cost-Sensitive Learning),代表的演算法有adacost;

另外可以將不平衡資料集的問題考慮為一分類(One Class Learning)或者異常檢測(Novelty Detection)問題,代表的演算法有One-class SVM。

本文主要介紹從資料角度出發的不平衡資料集的處理方法以及對應的python庫(imblearn)。

二、從資料角度出發的不平衡資料集的處理方法

2-1、隨機取樣

2-1-1、樸素隨機過取樣(上取樣)

針對不平衡資料, 最簡單的一種方法就是生成少數類的樣本, 這其中最基本的一種方法就是: 從少數類的樣本中進行隨機取樣來增加新的樣本,對應Python庫中函式為RandomOverSampler:

from imblearn.over_sampling

import RandomOverSampler

ros = RandomOverSampler(random_state=0)

X_resampled, y_resampled = ros.fit_sample(X, y)

2-1-2、樸素隨機欠取樣(下采樣)

與過取樣相反,欠取樣是從多數類樣本中隨機選擇少量樣本,再合併原有少數類樣本作為新的訓練資料集。

隨機欠取樣有兩種型別分別為有放回和無放回兩種,無放回欠取樣在對多數類某樣本被取樣後不會再被重複取樣,有放回取樣則有可能。

對應Python庫中函式為RandomUnderSampler,通過設定RandomUnderSampler中的replacement=True引數, 可以實現自助法(boostrap)抽樣。

2-1-3、隨機取樣的優缺點

隨機取樣最大的優點是簡單,但缺點也很明顯。上取樣後的資料集中會反覆出現一些樣本,訓練出來的模型會有一定的過擬合;而下采樣的缺點顯而易見,那就是最終的訓練集丟失了資料,模型只學到了總體模式的一部分。

上取樣會把小眾樣本複製多份,一個點會在高維空間中反覆出現,這會導致一個問題,那就是運氣好就能分對很多點,否則分錯很多點。

為了解決這一問題,可以在每次生成新資料點時加入輕微的隨機擾動,經驗表明這種做法非常有效,但是這一方式會加重過擬合。

2-2、過取樣的改進:SMOTE與ADASYN

相對於取樣隨機的方法進行過取樣, 還有兩種比較流行的過取樣的改進方式: 

(1)、Synthetic Minority Oversampling Technique(SMOTE)

(2)、Adaptive Synthetic (ADASYN) 

2-2-1、SMOTE

SMOTE演算法的基本思想是對少數類樣本進行分析並根據少數類樣本人工合成新樣本新增到資料集中,具體下圖所示,演算法流程如下:

1、對於少數類中每一個樣本x,計算該點與少數類中其他樣本點的距離,得到最近的k個近鄰(即對少數類點進行KNN演算法)。
2、根據樣本不平衡比例設定一個取樣比例以確定取樣倍率,對於每一個少數類樣本x,從其k近鄰中隨機選擇若干個樣本,假設選擇的近鄰為x'。
3、對於每一個隨機選出的近鄰x',分別與原樣本按照如下的公式構建新的樣本:

                    xnew=x+rand(0,1∗ (xx)

但是SMOTE演算法缺點也十分明顯:一方面是增加了類之間重疊的可能性(由於對每個少數類樣本都生成新樣本,因此容易發生生成樣本重疊(Overlapping)的問題),

另一方面是生成一些沒有提供有益資訊的樣本。

                        SMOTE演算法圖

對應Python庫中函式為SMOTE:

from imblearn.over_sampling import SMOTE

X_resampled_smote, y_resampled_smote = SMOTE().fit_sample(X, y)

2-2-2、SMOTE的改進:Borderline-SMOTE

Borderline-SMOTE與原始SMOTE不同的地方在於,原始的SMOTE是對所有少數類樣本生成新樣本。而改進的方法則是先根據規則判斷出少數類的邊界樣本,再對這些樣本生成新樣本。

判斷邊界的一個簡單的規則為:K近鄰中有一半以上多數類樣本的少數類為邊界樣本。直觀地講,只為那些周圍大部分是多數類樣本的少數類樣本生成新樣本。

假設a為少數類中的一個樣本,此時少數類的樣本分為三類,如下圖所示:

(i) 噪音樣本(noise), 該少數類的所有最近鄰樣本都來自於不同於樣本a的其他類別:

(ii) 危險樣本(in danger), 至少一半的最近鄰樣本來自於同一類(不同於a的類別);

(iii) 安全樣本(safe), 所有的最近鄰樣本都來自於同一個類。

                     Borderline-SMOTE演算法

對應的Python庫中的實現有三種可以選擇的規則:

SMOTE函式中的kind引數控制了選擇哪種規則:

borderline1:最近鄰中的隨機樣本與該少數類樣本a來自於不同的類;

borderline2:最近鄰中的隨機樣本可以是屬於任何一個類的樣本;

svm:使用支援向量機分類器產生支援向量然後再生成新的少數類樣本。

具體實現如下:

from imblearn.under_sampling

import ClusterCentroids

cc = ClusterCentroids(random_state=0)

X_resampled, y_resampled = cc.fit_sample(X, y)

2-2-3、ADASYN

這種改進方法的主要思想是根據資料分佈情況為不同的少數類樣本生成不同數量的新樣本。首先根據最終的平衡程度設定總共需要生成的新少數類樣本數量 ,然後為每個少數類樣本x計算分佈比例。

對應Python庫中函式為ADASYN:

from imblearn.over_sampling import ADASYN

X_resampled_adasyn, y_resampled_adasyn = ADASYN().fit_sample(X, y)

2-2-4、基於聚類的過取樣方法

以二分類為例,該方法是首先分別對正負例進行聚類,在聚類之後進行再進行上述的過取樣方法。例如:有一個二分類資料集,其正負類比例為:1000:50。首先通過kmeans演算法對正負類分別聚類,

得到正類:600,300,100;負類:30,20。然後使用過取樣的方法分別對所有類別進行過取樣得到正類:600,600,600;對於負類的上取樣個數為:(600+600+600)/2 = 900,即負類為:900,900。

最終得到的資料集為正類1800,負類1800。基於聚類的過取樣方法的優點是不僅可以解決類間不平衡問題,而且還能解決類內部不平衡問題。 

2-3、欠取樣的改進:EasyEnsemble、BalanceCascade與NearMiss

隨機欠取樣的問題主要是資訊丟失,為了解決資訊丟失的問題提出了以下幾種改進的方式:

1、EasyEnsemble,利用模型融合的方法(Ensemble):

多次過取樣(放回取樣,這樣產生的訓練集才相互獨立)產生多個不同的訓練集,進而訓練多個不同的分類器,通過組合多個分類器的結果得到最終的結果。簡單的最佳實踐是建立n個模型,每個模型使用少數類的所有樣本和多數類的n個不同樣本。假設二分類資料集的正負類比例為50000:1000,最後要得到10個模型,那麼將保留負類的1000個樣本,並隨機取樣得到10000個正類樣本。

然後,將10000個樣本成10份,每一份與負類樣本組合得到新的子訓練集,訓練10個不同的模型。

 

2、BalanceCascade,利用增量訓練的思想(Boosting):

先通過一次下采樣產生訓練集,訓練一個分類器,對於那些分類正確的多數類樣本不放回,然後對這個更小的多數類樣本下采樣產生訓練集,訓練第二個分類器,以此類推,最終組合所有分類器的結果得到最終結果。

 

3、NearMiss,利用KNN試圖挑選那些最具代表性的多數類樣本:

首先計算出每個樣本點之間的距離,通過一定規則來選取保留的多數類樣本點。因此該方法的計算量通常很大。

2-3-1、上述方法的Python實現

EasyEnsemble:

EasyEnsemble方法對應Python庫中函式為EasyEnsemble,有兩個很重要的引數: (i) n_subsets控制的是子集的個數 ;(ii) replacement決定是有放回還是無放回的隨機取樣。

 

from imblearn.ensemble

import EasyEnsemble

ee = EasyEnsemble(random_state=0, n_subsets=10)

X_resampled, y_resampled = ee.fit_sample(X, y)

 

BalanceCascade:

BalanceCascade方法對應Python庫中函式為BalanceCascade,有三個很重要的引數: (i) estimator是選擇使用的分類器;(ii) n_max_subset控制的是子集的個數;(iii)  bootstrap決定是有放回還是無放回的隨機取樣。

 

from imblearn.ensemble

import BalanceCascade

from sklearn.linear_model

import LogisticRegression

bc = BalanceCascade(random_state=0,

          estimator=LogisticRegression(random_state=0),

          n_max_subset=4)

X_resampled, y_resampled = bc.fit_sample(X, y)

 

NearMiss:

NearMiss方法對應Python庫中函式為NearMiss,通過version來選擇使用的規則:

NearMiss-1:選擇離N個近鄰的負樣本的平均距離最小的正樣本;

NearMiss-2:選擇離N個負樣本最遠的平均距離最小的正樣本;

NearMiss-3:是一個兩段式的演算法。 首先,對於每一個負樣本, 保留它們的M個近鄰樣本;接著, 那些到N個近鄰樣本平均距離最大的正樣本將被選擇。

 

from imblearn.under_sampling

import NearMiss nm1 = NearMiss(random_state=0, version=1)

X_resampled_nm1, y_resampled = nm1.fit_sample(X, y)

 

所有方法的簡單實驗效果可以見:不平衡資料分類演算法介紹與比較

2-4、不平衡問題其他的處理方式

除了上述提到的過取樣與欠取樣的方法之外,還可以將多種方法進行組合使用。

另外還可以通過為不同的樣本點賦予不同的權重的方式來處理不平衡問題(與改進損失函式的方式有所類似)。

在演算法層面除了對演算法本身的改進之外,還需要關注模型的評價指標,來確認使用的方法是否有效。

參考文獻:

[1].不均衡學習的抽樣方法

[2].機器學習︱非平衡資料處理方式與評估

[3].資料不平衡問題的處理

[4].不平衡資料的機器學習

[5].資料不平衡imblearn演算法彙總

[6].不平衡資料分類演算法介紹與比較