三招提高數據不平衡模型的性能(附python代碼)

對於深度學習而言,數據集很是重要,但在實際項目中,或多或少會遇見數據不平衡問題。什麼是數據不平衡呢?舉例來講,如今有一個任務是判斷西瓜是否成熟,這是一個二分類問題——西瓜是生的仍是熟的,該任務的數據集由兩部分數據組成,成熟西瓜與生西瓜,假設生西瓜的樣本數量遠遠大於成熟西瓜樣本的數量,針對這樣的數據集訓練出來的算法「偏向」於識別新樣本爲生西瓜,存心讓你買不到甜的西瓜以解夏天之苦,這就是一個數據不平衡問題。針對數據不平衡問題有相應的處理辦法,好比對多數樣本進行採樣使得其樣本數量級與少樣本數相近,或者是對少數樣本重複使用等。最近剛好在面試中遇到一個數據不平衡問題,這也是面試中常常會出現的問題之一,現向讀者分享這次解決問題的心得。html

clipboard.png

數據集

訓練數據中有三個標籤,分別標記爲[一、二、3],這意味着該問題是一個多分類問題。訓練數據集有17個特徵以及38829個獨立數據點。而在測試數據中,有16個沒有標籤的特徵和16641個數據點。該訓練數據集很是不平衡,大部分數據是1類(95%),而2類和3類分別有3.0%和0.87%的數據,以下圖所示。node

clipboard.png

算法

通過初步觀察,決定採用隨機森林(RF)算法,由於它優於支持向量機、Xgboost以及LightGBM算法。在這個項目中選擇RF還有幾個緣由:面試

1.機森林對過擬合具備很強的魯棒性;
2.參數化仍然很是直觀;
3.在這個項目中,有許多成功的用例將隨機森林算法用於高度不平衡的數據集;
4.我的有先前的算法實施經驗;算法

爲了找到最佳參數,使用scikit-sklearn實現的GridSearchCV對指定的參數值執行網格搜索,更多細節能夠在本人的Github上找到。bootstrap

爲了處理數據不平衡問題,使用瞭如下三種技術:

A.使用集成交叉驗證(CV)網絡

在這個項目中,使用交叉驗證來驗證模型的魯棒性。整個數據集被分紅五個子集。在每一個交叉驗證中,使用其中的四個子集用於訓練,剩餘的子集用於驗證模型,此外模型還對測試數據進行了預測。在交叉驗證結束時,會獲得五個測試預測機率。最後,對全部類別的機率取平均值。模型的訓練表現穩定,每一個交叉驗證上具備穩定的召回率和f1分數。這項技術也幫助我在Kaggle比賽中取得了很好的成績(前1%)。如下部分代碼片斷顯示了集成交叉驗證的實現:dom

for j, (train_idx, valid_idx) in enumerate(folds):
                
                X_train = X[train_idx]
                Y_train = y[train_idx]
                X_valid = X[valid_idx]
                Y_valid = y[valid_idx]
                
                clf.fit(X_train, Y_train)
                
                valid_pred = clf.predict(X_valid)
                recall  = recall_score(Y_valid, valid_pred, average='macro')
                f1 = f1_score(Y_valid, valid_pred, average='macro')
                
                recall_scores[i][j] = recall
                f1_scores[i][j] = f1
                
                train_pred[valid_idx, i] = valid_pred
                test_pred[:, test_col] = clf.predict(T)
                test_col += 1
                
                ## Probabilities
                valid_proba = clf.predict_proba(X_valid)
                train_proba[valid_idx, :] = valid_proba
                test_proba  += clf.predict_proba(T)
                
            test_proba /= self.n_splits

B.設置類別權重/重要性:性能

代價敏感學習是使隨機森林更適合從很是不平衡的數據中學習的方法之一。隨機森林有傾向於偏向大多數類別。所以,對少數羣體錯誤分類施加昂貴的懲罰多是有做用的。因爲這種技術能夠改善模型性能,因此我給少數羣體分配了很高的權重(即更高的錯誤分類成本)。而後將類別權重合併到隨機森林算法中。我根據類別1中數據集的數量與其它數據集的數量之間的比率來肯定類別權重。例如,類別1和類別3數據集的數目之間的比率約爲110,而類別1和類別2的比例約爲26。如今我稍微對數量進行修改以改善模型的性能,如下代碼片斷顯示了不一樣類權重的實現:學習

from sklearn.ensemble import RandomForestClassifier
class_weight = dict({1:1.9, 2:35, 3:180})

rdf = RandomForestClassifier(bootstrap=True,
            class_weight=class_weight, 
            criterion='gini',
            max_depth=8, max_features='auto', max_leaf_nodes=None,
            min_impurity_decrease=0.0, min_impurity_split=None,
            min_samples_leaf=4, min_samples_split=10,
            min_weight_fraction_leaf=0.0, n_estimators=300,
            oob_score=False,
            random_state=random_state,
            verbose=0, warm_start=False)

C.過大預測標籤而不是太小預測(Over-Predict a Label than Under-Predict):測試

這項技術是可選的,經過實踐發現,這種方法對提升少數類別的表現很是有效。簡而言之,若是將模型錯誤分類爲類別3,則該技術能最大限度地懲罰該模型,對於類別2和類別1懲罰力度稍差一些。 爲了實施該方法,我改變了每一個類別的機率閾值,將類別三、類別2和類別1的機率設置爲遞增順序(即,P3= 0.25,P2= 0.35,P1= 0.50),以便模型被迫過分預測類別。該算法的詳細實現能夠在Github上找到。

最終結果

如下結果代表,上述三種技術如何幫助改善模型性能:
1.使用集成交叉驗證的結果:

clipboard.png

2.使用集成交叉驗證+類別權重的結果:

clipboard.png

3.使用集成交叉驗證+類別權重+過大預測標籤的結果:

clipboard.png

結論

因爲在實施過大預測技術方面的經驗不多,所以最初的時候處理起來很是棘手。可是,研究該問題有助於提高我解決問題的能力。對於每一個任務而言,起初可能確實是陌生的,這個時候不要懼怕,一次次嘗試就好。因爲時間的限制(48小時),沒法將精力分散於模型的微調以及特徵工程,存在改進的地方還有不少,好比刪除沒必要要的功能並添加一些額外功能。此外,也嘗試過LightGBM和XgBoost算法,但在實踐過程當中發現,隨機森林的效果優於這兩個算法。在後面的研究中,能夠進一步嘗試一些其餘算法,好比神經網絡、稀疏編碼等。

數十款阿里雲產品限時折扣中,趕忙點擊領劵開始雲上實踐吧!

本文做者:【方向】
閱讀原文本文爲雲棲社區原創內容,未經容許不得轉載。

相關文章
相關標籤/搜索