當前位置:
首頁 > 知識 > 用R語言實現對不平衡數據的四種處理方法

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

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

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

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

什麼是不平衡分類

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

針對不平衡數據的處理方法

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

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

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

欠採樣法(Undersampling)

過採樣法(Oversampling)

人工數據合成法(Synthetic Data Generation)

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

讓我們逐一了解它們

1.欠採樣法

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

欠採樣法共有兩類:隨機(Random)的和有信息的(Informative)

隨機欠採樣法會隨機刪除大類的觀測直至數據集平衡有信息的欠採樣法則會依照一個事先制定的準則來刪去觀測

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

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

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

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

2.過採樣法

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

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

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

3.人工數據合成法

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

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

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

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

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

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

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

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 + )2 × Recall × Precision) / ( 2 × Recall + Precision )

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

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

Specificity = TN / (TN + FP)

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

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

對於偏態分布的數據,可能會高估精度

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

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

作為一種替代方法,我們也可以選擇別的可視化方式比如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 的人工數據合成

---------------------

作者:蔡軍帥

原文:https://blog.csdn.net/qq_40875849/article/details/85013973

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

打開今日頭條,查看更多圖片
喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 程序員小新人學習 的精彩文章:

非常迷你的純CSS3時間軸切換焦點圖
9個絢麗多彩的HTML5進度條動畫賞析

TAG:程序員小新人學習 |