決策樹演算法對平衡分類是有效的,但在不平衡資料集上卻表現不佳。
決策樹分裂點是為了能夠在最小混淆的情況下將所有例項分成兩組。當兩個組別分別都由其中一個類別的例項佔主導,那麼用於選擇分裂點設定的標準即為合理,而事實上,少數類中的例項將會被忽略。
透過修改評估分裂點的標準並將每一類別的重要性均納入考慮,即可解決這一問題,通常指的是加權的分裂點或者加權的決策樹。
在本指南中,你將看到的是不平衡分類的加權決策樹。
在學習完本指南之後,你將會了解:
標準決策樹演算法是怎樣不支援不平衡分類的。
當選擇分裂點時,決策樹演算法如何透過類權值對模型誤差進行加權。
如何配置決策樹演算法中類的權值以及如何對不同的類權值配置進行網格化搜尋。
SMOTE演算法,單類別分類,成本敏感學習,閾值移動,以及更多其他內容,請檢索我的新書,內含30個逐步教程以及完整的Python原始碼。
好的,我們開始。
指南概觀
本指南分為四部分,他們分別是:
一、不平衡分類資料集
二、不平衡分類決策樹
三、Scikit-Learn中使用加權決策樹
四、加權決策樹的網格化搜尋
一、不平衡分類資料集
在開始深入到不平衡分類的決策修正之前,我們先定義一個不平衡資料集。
我們可以使用 make_classification()函式來定義一個合成的不平衡兩類別分類資料集。我們將生成10000個例項,其中少數類和多數類的比例為1:100。
一旦生成之後,我們可以總結類的分佈來驗證生成資料集是我們所期望的。
最後,我們可以創造一個例項的散點圖並依據類標籤進行著色,來幫助我們理解該資料集中例項分類所面臨的挑戰。
將這些程式碼整合在一起,生成合成資料集和繪製例項的完整示例。
執行這個示例將會先創造一個資料集,然後彙總類的分佈。
我們可以看到這個資料集接近1:100的類的分佈,有比10000個稍微少一些的例項在多數類當中,100個例項在少數類中。
Counter({0: 9900, 1: 100})
接下來,是資料集的散點圖,該圖展示了大量多數類(藍色)的例項和少量少數類(橙色)的例項,其中有少許類的值重疊。
接下來,我們可以在此資料集上擬合一個標準決策樹模型。決策樹可以使用scikit-learn工具包中的決策樹分類器生成。
決策樹分類器:
https://machinelearningmastery.com/cost-sensitive-decision-trees-for-imbalanced-classification/
我們將使用重複交叉驗證來評估此模型,共需三次重複的10層交叉驗證。模型的效能將透過曲線下ROC面積(ROC AUC)在所有重複次以及全部層的均值獲得。
在不平衡分類問題上定義和評估一個標準決策樹模型的完整例項如下。
決策樹對二分類任務的有效模型,雖然他們本身對不平衡分類問題並不高效。
執行該例項可評估標準決策樹模型在不平衡資料集上的表現,並報告ROC AUC。
你的特定的結果可能會根據學習演算法的固有隨機性而變化。試著多執行幾次。
我們可以看到這個模型能夠實現ROC AUC大於0.5,並實現均值得分為0.746。
Mean ROC AUC: 0.746
這為任何標準決策樹演算法的改進提供了比較的基線。
二、不平衡分類決策樹
決策樹演算法也被叫做分類和迴歸樹(CART),包括生成樹以及從訓練集中分類例項。
樹可用於分離訓練集,例項可以經由樹的決策點到達葉節點並且被附上類標籤。
樹可以透過使用資料集中變數的值來分離訓練集從而得到建構。在每一個點上,資料的分離以最貪心的方式使得最純淨的(最少混合的)例項組被選出來。
在這裡,純度意味著例項得到純淨地分離,由只包含0和只包含1的例項組成的類是最純淨的,50-50混合的類是最不純的。常見的純度通常由基尼不純度來計算,雖然也可以透過資訊熵(entropy)來計算。
純度測量包括計算一個給定類的例項被誤分類的可能性。計算這些機率包括將每個組中每個類的例項數求和。
分離標準可以被更新,不僅是為了考慮分離的純度,也是為了對每個類的重要性進行加權。
“我們匯入成本敏感決策樹的目的是為了修正與某一例項誤分類的損失成比例的權重……”
-《一種匯入損失敏感決策樹的例項加權方法》,2002
https://machinelearningmastery.com/cost-sensitive-decision-trees-for-imbalanced-classification/
這可以透過加權和代替每一組別的例項數實現,這裡係數被用於加權和。
更大的權重被分配給更重要的類,更小的權重則賦給不那麼重要的類。
小權重:對節點純度不那麼重要,影響更低。
大權重:對節點純度更重要,影響更高。
小權重可被分配給多數類,能夠提升(降低)節點的純度分數,否則這個節點
可能會看起來排序不那麼好。這可能會使得更多來自多數類的例項被分到少數類裡,並更好地適應少數類裡的例項。
“更高的權值被分配給來自更高誤分類成本的類當中的例項。”
-《從不平衡資料集中學習》,2018,第71頁
https://machinelearningmastery.com/cost-sensitive-decision-trees-for-imbalanced-classification/
正因為如此,對決策樹演算法的這一修正被稱為加權決策樹,一個加權類的決策樹,或者是成本敏感決策樹。
分離點計算的修正是最常見的,雖然還有很多修正決策樹建構演算法以更好地適應類的不平衡的研究。
三、Scikit-Learn中使用加權決策樹
Scikit-Learn Python 機器學習工具包提供了支援類加權的決策樹演算法的實現方法。
決策樹演算法提供了可被指定為模型超引數的class_weight引數。class_weight是一個定義每個類標籤(例如,0和1)和應用到擬合模型時,決策樹中分離組純度計算權值的字典。
例如,一個對每個0和1類的1比1的權重可以作如下定義:
類權值可有多種定義方式,例如:
領域專長:透過與學科專家交談確定;
調參:透過例如網格化搜尋的超引數搜尋確定;
啟發式:使用一般最佳實踐確定。
使用類加權最好的實踐是使用與訓練集中的類分佈的倒數。
例如,測試集類分佈為少數類:多數類1:100的比例。該比例的倒數是1個多數類和100個少數類。例如:
我們也可以使用分數定義同樣的比例,並獲得相同的結果。例如:
啟發式可以透過直接設定class_weight為'balanced'。例如:
我們可以透過使用在之前的部分定義的評估程式來對類加權的決策樹演算法進行評估。
我們期待類加權決策樹的版本比沒有類加權的標準決策樹演算法表現得更好。
完整的例項如下:
執行這一例項可以準備好合成的不平衡分類資料集,然後使用重複交叉驗證評估類加權版的決策樹演算法。
你的結果可能會受到演算法隨機性的影響,嘗試多執行幾次。
ROC AUC的均值得分被報告,得到比未加權版本的決策樹演算法更好的得分:0.759比0.746。
Mean ROC AUC: 0.759
四、加權決策樹的網格化搜尋
使用訓練集的倒數比的類加權是啟發式的一種。
使用不同的類加權可能得到更好的表現,這也過分依賴於評估模型效能度量的選擇。
在這一部分,我們將為加權決策樹進行一系列不同類權重的網格化搜尋並探索可得到最佳ROC AUC的結果。
我們將嘗試下述對0類和1類的權重:
類0:100,類1:1;
類0:10,類1:1;
類0:1,類1:1;
類0:1,類1:100。
這些可被定義為GridSearchCV類的網格化搜尋引數如下:
我們可以使用重複交叉驗證對這些引數進行網格化搜尋,並使用ROC AUC估計模型的表現:
...
# define evaluation procedure
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
# define grid search
grid = GridSearchCV(estimator=model, param_
g
rid=param_grid, n_jobs=-1, cv=cv, scoring='roc_auc')
一旦執行後,我們可以總結最佳配置,以及所有的結果如下:
...
# report the best configuration
print("Best: %f using %s" % (grid_result.best_score_, grid_result.best_params_))
# report all configurations
means = grid_result.cv_results_['mean_test_score']
stds = grid_result.cv_results_['std_test_score']
params = grid_result.cv_results_['params']
for mean, stdev, param in zip(means, stds, params):
print("%f (%f) with: %r" % (mean, stdev, param))
以下例項為不平衡資料集上的決策樹演算法,對五種不同的類權重進行網格化搜尋。
我們可能會期待啟發式類權重是最好的配置。
# grid search class weights with decision tree for imbalance classification
from numpy import mean
from sklearn.datasets import make_classification
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.tree import DecisionTreeClassifier
# generate dataset
X, y = make_classification(n_samples=10000, n_features=2, n_redundant=0,
n_clusters_per_class=1, weights=[0.99], flip_y=0, random_state=3)
# define model
model = DecisionTreeClassifier()
# define grid
balance = [{0:100,1:1}, {0:10,1:1}, {0:1,1:1}, {0:1,1:10}, {0:1,1:100}]
param_grid = dict(class_weight=balance)
# define evaluation procedure
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
# define grid search
grid = GridSearchCV(estimator=model, param_grid=param_grid, n_jobs=-1, cv=cv, scoring='roc_auc')
# execute the grid search
grid_result = grid.fit(X, y)
# report the best configuration
print("Best: %f using %s" % (grid_result.best_score_, grid_result.best_params_))
# report all configurations
means = grid_result.cv_results_['mean_test_score']
stds = grid_result.cv_results_['std_test_score']
params = grid_result.cv_results_['params']
for mean, stdev, param in zip(means, stds, params):
print("%f (%f) with: %r" % (mean, stdev, param))
執行該例項使用重複k層交叉驗證來評估每一個類權重,並報告最佳配置以及相關的平均ROC AUC得分。
你的結果可能會隨著學習演算法的隨機性而變化,嘗試多執行幾次。
在這種情況下,我們可以看到1:100的多數:少數類比加權可以實現最佳的均值ROC得分。這與一般啟發式的配置相匹配。
探索更嚴格的類權值來看其對ROC AUC均值得分的影響可能會很有趣。
Best: 0.752643 using {'class_weight': {0: 1, 1: 100}}
0.737306 (0.080007) with: {'class_weight': {0: 100, 1: 1}}
0.747306 (0.075298) with: {'class_weight': {0: 10, 1: 1}}
0.740606 (0.074948) with: {'class_weight': {0: 1, 1: 1}}
0.747407 (0.068104) with: {'class_weight': {0: 1, 1: 10}}
0.752643 (0.073195) with: {'class_weight': {0: 1, 1: 100}}
更多閱讀
如果你想更深入瞭解,本部分提供了更多相關資源。
論文 《一種匯入成本敏感決策樹的例項加權方法》,2002. https://machinelearningmastery.com/cost-sensitive-decision-trees-for-imbalanced-classification/ 書籍 《從不平衡資料中學習》,2018 https://amzn.to/307Xlva 《不平衡學習:基礎,演算法和應用》,2013 https://amzn.to/32K9K6d API sklearn.utils.class_weight.compute_class_weight API: https://scikit-learn.org/stable/modules/generated/sklearn.utils.class_weight.compute_class_weight.html sklearn.tree.DecisionTreeClassifier API: https://scikit-learn.org/stable/modules/generated/sklearn.tree.DecisionTreeClassifier.html sklearn.model_selection.GridSearchCV API: https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.GridSearchCV.html
總結
在本指南中,你探索了不平衡分類的加權決策樹。特別地,你學到了:
標準決策樹演算法怎樣不支援不平衡分類;
當選擇分裂點時,決策樹演算法如何透過類權值對模型誤差進行加權;
如何配置決策樹演算法中類的權值以及如何對不同的類權值配置進行網格化搜尋。