1. 程式人生 > >用R語言實現對不平衡資料的四種處理方法

用R語言實現對不平衡資料的四種處理方法

https://www.weixin765.com/doc/gmlxlfqf.html

在對不平衡的分類資料集進行建模時,機器學**演算法可能並不穩定,其預測結果甚至可能是有偏的,而預測精度此時也變得帶有誤導性那麼,這種結果是為何發生的呢?到底是什麼因素影響了這些演算法的表現?

 

在不平衡的資料中,任一演算法都沒法從樣本量少的類中獲取足夠的資訊來進行精確預測因此,機器學**演算法常常被要求應用在平衡資料集上那我們該如何處理不平衡資料集?本文會介紹一些相關方法,它們並不複雜只是技巧性比較強

 

本文會介紹處理非平衡分類資料集的一些要點,並主要集中於非平衡二分類問題的處理一如既往,我會盡量精簡地敘述,在文末我會演示如何用R中的ROSE包來解決實際問題

 

什麼是不平衡分類

不平衡分類是一種有監督學**,但它處理的物件中有一個類所佔的比例遠遠大於其餘類比起多分類,這一問題在二分類中更為常見(注:下文中佔比較大的類稱為大類,佔比較小的類稱為小類)

不平衡一詞指代資料中響應變數(被解釋變數)的分佈不均衡,如果一個數據集的響應變數在不同類上的分佈差別較大我們就認為它不平衡

舉個例子,假設我們有一個觀測數為100****00的資料集,它包含了哈佛大學申請人的資訊眾所周知,哈佛大學以極低的錄取比例而聞名,那麼這個資料集的響應變數(即:該申請人是否被錄取,是為1,否為0)就很不平衡,大致98%的觀測響應變數為0,只有2%的幸運兒被錄取

在現實生活中,這類例子更是不勝列舉,我在下面列舉了一些例項,請注意他們的不平衡度是不一樣的

1.一個自動產品質量檢測機每天會檢測工廠生產的產品,你會發現次品率是遠遠低於合格率的

2.某地區進行了居民癌症普查,結果患有癌症的居民人數也是遠遠少於健康人群

3.在信用卡欺詐資料中,違規交易數比合規交易少不少

4.一個遵循6原則的生產車間每生產100萬個產品才會產出10個次品

生活中的例子還有太多,現在你可以發現獲取這些非平衡資料的可能性有多大,所以掌握這些資料集的處理方法也是每個資料分析師的必修課

為什麼大部分機器學**演算法在不平衡資料集上表現不佳?

我覺得這是一個很有意思的問題,你不妨自己先動手試試,然後你就會了解把不平衡資料再結構化的重要性,至於如何再結構化,我會在操作部分中講解

下面是機器學**演算法在不平衡資料上精度下降的原因:

  1. 響應變數的分佈不均勻使得演算法精度下降,對於小類的預測精度會很低

  2. 演算法本身是精度驅動的,即該模型的目標是最小化總體誤差,而小類對於總體誤差的貢獻很低

  3. 演算法本身假設資料集的類分佈均衡,同時它們也可能假定不同類別的誤差帶來相同的損失(下文會詳細敘述)

針對不平衡資料的處理方法

這類處理方法其實就是大名鼎鼎的取樣法,總的說來,應用這些方法都是為了把不平衡資料修正為平衡資料修正方法就是調整原始資料集的樣本量,使得不同類的資料比例一致

而在諸多學者研究得出基於平衡資料的模型整體更優的結論後,這一類方法越來越受到分析師們的青睞

下列是一些具體的處理方法名稱:

  1. 欠取樣法(Undersampling)

  2. 過取樣法(Oversampling)

  3. 人工資料合成法(Synthetic Data Generation)

  4. 代價敏感學**法(Cose Sensitive Learning)

讓我們逐一瞭解它們

1.欠取樣法

該方法主要是對大類進行處理它會減少大類的觀測數來使得資料集平衡這一辦法在資料集整體很大時較為適宜,它還可以通過降低訓練樣本量來減少計算時間和儲存開銷

欠取樣法共有兩類:隨機(Random)的和有資訊的(Informative)

隨機欠取樣法會隨機刪除大類的觀測直至資料集平衡有資訊的欠取樣法則會依照一個事先制定的準則來刪去觀測

有資訊的欠取樣中,利用簡易整合演算法(EasyEnsemble)和平衡級聯演算法(BalanceCascade)往往能得到比較好的結果這兩種演算法也都很直白易懂

簡易整合法:首先,它將從大類中有放回地抽取一些獨立樣本生成多個子集然後,將這些子集和小類的觀測合併,再基於合併後的資料集訓練多個分類器,以其中多數分類器的分類結果為預測結果如你所見,整個流程和無監督學**非常相似

平衡級聯法:它是一種有監督的學**法,首先將生成多個分類器,再基於一定規則系統地篩選哪些大類樣本應當被保留

但欠取樣法有一個顯而易見的缺陷,由於要刪去不少觀測,使用該方法會使得大類損失不少重要資訊

2.過取樣法

這一方法針對小類進行處理它會以重複小類的觀測的方式來平衡資料該方法也被稱作升取樣(Upsampling)和欠取樣類似,它也能分為隨機過取樣和有資訊的過取樣兩類

隨機過取樣會將小類觀測隨機重複有資訊過取樣也是遵循一定的準則來人工合成小類觀測

使用該方法的一大優勢是沒有任何資訊損失缺點則是由於增加了小類的重複樣本,很有可能導致過擬合(譯者注:計算時間和儲存開銷也增大不少)我們通過該方法可以在訓練集上得到非常高的擬合精度,但在測試集上預測的表現則可能變得愈發糟糕

3.人工資料合成法

簡單說來,人工資料合成法是利用生**工資料而不是重複原始觀測來解決不平衡性它也是一種過取樣技術

在這一領域,SMOTE法(Synthetic Minority Oversampling Technique)是有效而常用的方法該演算法基於特徵空間(而不是資料空間)生成與小類觀測相似的新資料(譯者注:總體是基於歐氏距離來度量相似性,在特徵空間生成一些人工樣本,更通俗地說是在樣本點和它近鄰點的連線上隨機投點作為生成的人工樣本,下文敘述了這一過程但有些晦澀)我們也可以說,它生成了小類觀測的隨機集合來降低分類器的誤差

為了生**工資料,我們需要利用自助法(Bootstrapping)和K近鄰法(K-neraest neighbors)詳細步驟如下:

  1. 計算樣本點間的距離並確定其近鄰

  2. 生成一個0到1上的均勻隨機數,並將其乘以距離

  3. 把第二步生成的值加到樣本點的特徵向量上

  4. 這一過程等價於在在兩個樣本的連線上隨機選擇了一個點

R中有一個包專門用來實現SMOTE過程,我們將在實踐部分做演示

4.代價敏感學**(CSL)

這是另一種常用且有意思的方法簡而言之,該方法會衡量誤分類觀測的代價來解決不平衡問題

這方法不會生成平衡的資料集,而是通過生成代價矩陣來解決不平衡問題代價矩陣是描述特定場景下誤分類觀測帶來的損失的工具近來已有研究表明,代價敏感學**法很多時候比取樣法更優,因此這種方法也值得一學

讓我們通過一個例子來了解該方法:給定一個有關行人的資料集,我們想要了解行人是否會攜帶炸彈資料集包含了所有的必要資訊,且攜帶炸彈的人會被標記為正類,不帶炸彈的就是負類現在問題來了,我們需要把行人都分好類讓我們先來設定下這一問題的代價矩陣

如果我們將行人正確分類了,我們不會蒙受任何損失但如果我們把一個恐怖分子歸為負類(False Negative),我們要付出的代價會比把和平分子歸為正類(False Positive)的代價大的多

代價矩陣和混淆矩陣類似,如下所示,我們更關心的是偽正類(FP)和偽負類(FN)只要觀測被正確分類,我們不會有任何代價損失

該方法的目標就是找到一個使得總代價最小的分類器

Total Cost = C(FN)xFN + C(FP)xFP

其中,

FN是被誤分類的正類樣本數

FP是被誤分類的負類樣本數

C(FN)和C(FP)分別代表FN和FP帶來的損失本例中C(FN) > C(FP)

除此之外,我們還有其他的比較前沿的方法來處理不平衡樣本比如基於聚類的取樣法(Cluster based sampling),自適應人工取樣法(adaptive synthetic sampling),邊界線SMOTE(border line SMOTE),SMOTEboost,DataBoost-IM,核方法等這些方法的基本思想和前文介紹的四類方法大同小異還有一些更直觀的方法可以幫助你提升預測效果:如利用聚類技術,把大類分為K個次類,每個此類的樣本不重疊再基於每個次類和小類的合併樣本來訓練分類器最後把各個分類結果平均作為預測值除此之外,也可以聚焦於獲取更多資料來提高小類的佔比

應當使用哪類評價測度來評判精度?

選擇合適的評價測度是不平衡資料分析的關鍵步驟大部分分類演算法僅僅通過正確分類率來衡量精度但在不平衡資料中,使用這種方法有很大的欺騙性,因為小類對於整體精度的影響太小

混淆矩陣

混淆矩陣和代價矩陣的差異就在於代價矩陣提供了跟多的誤分類損失資訊,其對角元素皆為0而混淆舉證只提供了TP,TN,FP,FN四類樣本的比例,它常用的統計量則為正確率和錯誤率:

Accuracy: (TP + TN)/(TP+TN+FP+FN)

Error Rate = 1 Accuracy = (FP+FN)/(TP+TN+FP+FN)

如前文所提,混淆矩陣可能會提供誤導性結果,並且它對資料變動非常敏感更進一步,我們可以從混淆矩陣衍生出很多統計量,其中如下測度就提供了關於不平衡資料精度的更好度量:

準確率(Preciosion):正類樣本分類準確性的度量,即被標記為正類的觀測中被正確分類的比例

Precision = TP / (TP + FP)

召回率(Recall):所有實際正類樣本被正確分類的比率也被稱作敏感度(Sensitivity)

Recall = TP / (TP + FN)

F測度(F measure):結合準確率和召回率作為分類有效性的測度具體公式如下(ß常取1):

F measure = ((1 + )² × Recall × Precision) / ( ² × Recall + Precision )

儘管這些測度比正確率和錯誤率更好,但總的說來對於衡量分類器而言還不夠有效比如,準確率無法刻畫負類樣本的正確率召回率只針對實際正類樣本的分類結果這也就是說,我們需要尋找更好的測度來評價分類器

謝天謝地!我們可以通過ROC(Receiver Operationg Characterstics)曲線來衡量分類預測精度這也是目前廣泛使用的評估方法ROC曲線是通過繪製TP率(Sensitivity)和FP率(Specificity)的關係得到的

Specificity = TN / (TN + FP)

ROC圖上的任意一點都代表了單個分類器在一個給定分佈上的表現ROC曲線之所以有用是因為它提供了分類資料收益(TP)和損失(FP)的視覺化資訊ROC曲線下方區域的面積(AUC)越大,整體分類精度就越高

但有時ROC曲線也會失效,它的不足包括:

  1. 對於偏態分佈的資料,可能會高估精度

  2. 沒有提供分類表現的置信區間

  3. 無法提供不同分類器表現差異的顯著性水平

作為一種替代方法,我們也可以選擇別的視覺化方式比如PR曲線和代價曲線特別地,代價曲線被認為有以圖形方式描述分類器誤分類代價的能力但在90%的場合中,ROC曲線已經足夠好

在R中進行不平衡資料分類

我們已經學**了不平衡分類的一些重要理論技術是時候來應用它們了!在R中,諸如ROSE包和EMwR包都可以幫助我們快速實現取樣過程我們將以一個二分類案例做演示

ROSE(Random Over Sampling Examples)包可以幫助我們基於取樣和平滑自助法(smoothed bootstrap)來生**工樣本這個包也提供了一些定義良好的函式來快速完成分類任務

讓我們開始吧

# 設定工作目錄
setwd("C:/Users/manish/desktop/Data)

# 安裝包
install.packages(ROSE)
library(ROSE)

ROSE包中內建了一個叫做hacide的不平衡資料集,它包括hacide.train和hacide.test兩個部分,讓我們把它讀入R環境:

data(hacide)
str(hacide.train)

'data.frame': 1000 obs. of 3 variables:
$ cls: Factor w/ 2 levels "0","1": 1 1 1 1 1 1 1 1 1 1 ...
$ x1 : num 0.2008 0.0166 0.2287 0.1264 0.6008 ...
$ x2 : num 0.678 1.5766 -0.5595 -0.0938 -0.2984 ...

 

如你所見,資料集有3個變數的1000個觀測cls是響應變數,x1和x2是解釋變數讓我們檢查下cls的不平衡程度:

# 檢查cls的不平衡度
table(hacide.train$cls)
0     1
980    20

# 檢查cls的分佈
prop.table(table(hacide.train$cls))
0      1
0.98   0.02

可以看到,資料集中只有2%的正樣本,其餘98%都屬於負類資料的不平衡性極其嚴重那麼,這對我們的分類精度會帶來多大影響?我們先建立一個簡單的決策樹模型:

library(rpart)
treeimb <- rpart(cls ~ ., data = hacide.train)
pred.treeimb <- predict(treeimb, newdata = hacide.test)

然我們看看這個模型的預測精度,ROSE包提供了名為accuracy.meas()的函式,它能用來計算準確率,召回率和F測度等統計量

accuracy.meas(hacide.test$cls, pred.treeimb[,2])
Call:
accuracy.meas(response = hacide.test$cls, predicted = pred.treeimb[, 2])
Examples are labelled as positive when predicted is greater than 0.5 

precision: 1.000
recall: 0.200
F: 0.167

這些測度值看上去很有意思如果我們設定閾值為0.5,準確率等於1說明沒有被誤分為正類的樣本召回率等於0.2意味著有很多樣本被誤分為負類0.167的F值也說明模型整體精度很低

我們再來看看模型的ROC曲線,它會給我們提供這個模型分類能力的直觀評價使用roc.curve()函式可以繪製該曲線:

roc.curve(hacide.test$cls, pred.treeimb[,2], plotit = F)
Area under the curve (AUC): 0.600

AUC值等於0.6是個很槽糕的結果因此我們很有必要在建模前將資料集修正平衡在本案例中,決策樹演算法對於小類樣本無能為力

我們將使用取樣技術來提升預測精度這個包提供了ovun.sample()的函式來實現過取樣和欠取樣

我們先試試過取樣

# 過取樣
data_balanced_over <- ovun.sample(cls ~ ., data = hacide.train, method = "over",N = 1960)$data


table(data_balanced_over$cls)

0    1
980 980

上述程式碼實現了過取樣方法N代表最終平衡資料集包含的樣本點,本例中我們有980個原始負類樣本,所以我們要通過過取樣法把正類樣本也補充到980個,資料集共有1960個觀測

與之類似,我們也能用欠取樣方法,請牢記欠取樣是無放回的

data_balanced_under <- ovun.sample(cls ~ ., data = hacide.train, method = "under", N = 40, seed = 1)$data


table(data_balanced_under$cls)

0    1
20  20

欠取樣後資料是平衡了,但由於只剩下了40個樣本,我們損失了太多資訊我們還可以同時採取這兩類方法,只需要把引數改為method = both這時,對小類樣本會進行有放回的過取樣而對大類樣本則進行無放回的欠取樣

data_balanced_both <- ovun.sample(cls ~ ., data = hacide.train, method = "both", p=0.5, N=1000, seed = 1)$data

table(data_balanced_both$cls)
0    1
520 480

函式的引數p代表新生成資料集中正類的比例

但前文已經提過兩類取樣法都有自身的缺陷,欠取樣會損失資訊,過取樣容易導致過擬合,因而ROSE包也提供了ROSE()函式來合**工資料,它能提供關於原始資料的更好估計

data.rose <- ROSE(cls ~ ., data = hacide.train, seed = 1)$data

table(data.rose$cls)
0    1
520 480

這裡生成的資料量和原始資料集相等(1000個觀測)現在,我們已經用4種方法平衡了資料,我們分別建模評評估精度

# 訓練決策樹
tree.rose <- rpart(cls ~ ., data = data.rose)
tree.over <- rpart(cls ~ ., data = data_balanced_over)
tree.under <- rpart(cls ~ ., data = data_balanced_under)
tree.both <- rpart(cls ~ ., data = data_balanced_both)

 

# 在測試集上做預測
pred.tree.rose <- predict(tree.rose, newdata = hacide.test)
pred.tree.over <- predict(tree.over, newdata = hacide.test)
pred.tree.under <- predict(tree.under, newdata = hacide.test)
pred.tree.both <- predict(tree.both, newdata = hacide.test)

 

是時候用roc.curve()函式來評估精度了!

# 人工資料合成AUC值
roc.curve(hacide.test$cls, pred.tree.rose[,2])
Area under the curve (AUC): 0.989

# 過取樣AUC值
roc.curve(hacide.test$cls, pred.tree.over[,2])
Area under the curve (AUC): 0.798

# 欠取樣AUC值
roc.curve(hacide.test$cls, pred.tree.under[,2])
Area under the curve (AUC): 0.867

# 雙取樣AUC值
roc.curve(hacide.test$cls, pred.tree.both[,2])
Area under the curve (AUC): 0.798

因此,我們發現利用人工資料合成法可以帶來最高的預測精度,它的表現比取樣法要好這一技術和更穩健的模型結合(隨機森林,提升法)可以得到更高的精度

這個包為我們提供了一些基於holdout和bagging的模型評估方法,這有助於我們判斷預測結果是否有太大的方差

ROSE.holdout <- ROSE.eval(cls ~ ., data = hacide.train, learner = rpart, method.assess = "holdout", extr.pred = function(obj)obj[,2], seed = 1)

 

ROSE.holdout

 

Call:
ROSE.eval(formula = cls ~ ., data = hacide.train, learner = rpart,
extr.pred = function(obj) obj[, 2], method.assess = holdout,
seed = 1)

Holdout estimate of auc: 0.985

可以發現預測精度維持在0.98附近,這意味著預測結果波動不大類似的,你可以用自助法來評估,只要把method.asses改為BOOTextr.pred引數是一個輸出預測結果為正類的列的函式

結語

當我們面對不平衡資料集時,我們常常發現利用取樣法修正的效果不錯但在本例中,人工資料合成比傳統的取樣法更好為了得到更好的結果,你可以使用一些更前沿的方法,諸如基於boosting 的人工資料合成

來源:R語言中文社群