Python中XGBoost的特性重要性和特性選擇

liuzh(少昊)發表於2019-03-27

使用像梯度增強這樣的決策樹方法的集合的一個好處是,它們可以從經過訓練的預測模型中自動提供特徵重要性的估計。

在這篇文章中,您將發現如何使用Python中的XGBoost庫估計特性對於預測建模問題的重要性。

讀完這篇文章你就會知道:

如何使用梯度增強演算法計算特徵的重要性。
如何在Python中繪製由XGBoost模型計算的特性重要性。
如何使用XGBoost計算的特性重要性來執行特性選擇。

讓我們開始吧。

特徵在梯度增強中的重要性

使用梯度增強的一個好處是,在構造了增強的樹之後,檢索每個屬性的重要性得分相對簡單。

一般來說,重要性提供了一個評分,它表明每個特性在模型中增強決策樹的構建中有多有用或多有價值。屬性用於使用決策樹做出關鍵決策的次數越多,其相對重要性就越高。

這個重要性是為資料集中的每個屬性顯式計算的,允許屬性之間進行排序和比較。

對於單個決策樹,重要性是通過每個屬性分割點改進效能度量的數量來計算的,權重是通過節點負責觀察的數量來計算的。效能指標可以是純度(基尼指數),用來選擇分割點或其他更具體的誤差函式。

然後,對模型中所有決策樹的特徵重要性進行平均。

手動繪製特性重要性

一個經過訓練的XGBoost模型會自動計算出預測建模問題中特性的重要性。

這些重要性評分可以在訓練模型的feature_importances_成員變數中獲得。例如,它們可以直接列印如下:

print(model.feature_importances_)

我們可以在柱狀圖上直接繪製這些分數,以直觀地顯示資料集中每個特性的相對重要性。例如:

# plot
pyplot.bar(range(len(model.feature_importances_)), model.feature_importances_)
pyplot.show()

我們可以通過在Pima indian onset of diabetes資料集上訓練一個XGBoost模型,並根據計算出的特徵重要性建立一個條形圖(更新:從這裡下載)來演示這一點。

# plot feature importance manually

from numpy import loadtxt
from xgboost import XGBClassifier
from matplotlib import pyplot

# load data
dataset = loadtxt('pima-indians-diabetes.csv', delimiter=",")

# split data into X and y
X = dataset[:,0:8]
y = dataset[:,8]

# fit model no training data
model = XGBClassifier()
model.fit(X, y)

# feature importance
print(model.feature_importances_)

# plot
pyplot.bar(range(len(model.feature_importances_)), model.feature_importances_)
pyplot.show()

執行這個例子首先輸出重要性得分:

[ 0.089701    0.17109634  0.08139535  0.04651163  0.10465116  0.2026578 0.1627907   0.14119601]

我們還得到了相對重要性的條形圖。
Manual Bar Chart of XGBoost Feature Importance
這個圖的一個缺點是,這些特性是根據它們的輸入索引而不是它們的重要性排序的。我們可以在繪圖之前對特性進行排序。

值得慶幸的是,plot中內建了一個函式來幫助我們。

使用內建的XGBoost功能的重要性圖

XGBoost庫提供了一個內建函式來繪製按重要性排序的特性。

該函式稱為plot_importance(),可以使用如下:

# plot feature importance
plot_importance(model)
pyplot.show()

例如,下面是一個完整的程式碼清單,它使用內建的plot_importance()函式繪製Pima Indians資料集的特性重要性。

# plot feature importance using built-in function

from numpy import loadtxt
from xgboost import XGBClassifier
from xgboost import plot_importance
from matplotlib import pyplot

# load data
dataset = loadtxt('pima-indians-diabetes.csv', delimiter=",")

# split data into X and y
X = dataset[:,0:8]
y = dataset[:,8]

# fit model no training data
model = XGBClassifier()
model.fit(X, y)

# plot feature importance
plot_importance(model)
pyplot.show()

執行這個例子可以得到一個更有用的柱狀圖。
XGBoost Feature Importance Bar Chart
您可以看到,特性是根據輸入陣列(X)中從F0到F7的索引自動命名的。

手動將這些指標對映到問題描述中的名稱,我們可以看到圖中顯示F5(身體質量指數)的重要性最高,F3(皮膚褶皺厚度)的重要性最低。

使用XGBoost特性重要性評分選擇特性

特徵重要性評分可用於科學技術學習中的特徵選擇。

這是使用SelectFromModel類完成的,該類接受一個模型,可以將資料集轉換為具有所選特性的子集。

這個類可以使用一個預訓練的模型,例如一個在整個訓練資料集上訓練的模型。然後,它可以使用閾值來決定選擇哪些特性。當您在SelectFromModel例項上呼叫transform()方法以一致地在訓練資料集和測試資料集上選擇相同的特性時,將使用此閾值。

在下面的示例中,我們首先對整個訓練資料集和測試資料集分別訓練和評估XGBoost模型。

然後,使用從訓練資料集中計算的特性重要性,將模型封裝在SelectFromModel例項中。我們使用它來選擇訓練資料集中的特性,從所選的特性子集中訓練一個模型,然後根據相同的特性選擇方案在測試集中評估模型。

例如:

# select features using threshold
selection = SelectFromModel(model, threshold=thresh, prefit=True)
select_X_train = selection.transform(X_train)

# train model
selection_model = XGBClassifier()
selection_model.fit(select_X_train, y_train)

# eval model
select_X_test = selection.transform(X_test)
y_pred = selection_model.predict(select_X_test)

出於興趣,我們可以測試多個閾值來根據特性的重要性選擇特性。具體來說,每個輸入變數的特性重要性,本質上允許我們按重要性測試每個特性子集,從所有特性開始,以最重要特性的子集結束。

下面提供了完整的程式碼清單。

# use feature importance for feature selection

from numpy import loadtxt
from numpy import sort
from xgboost import XGBClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.feature_selection import SelectFromModel

# load data
dataset = loadtxt('pima-indians-diabetes.csv', delimiter=",")

# split data into X and y
X = dataset[:,0:8]
Y = dataset[:,8]

# split data into train and test sets
X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.33, random_state=7)

# fit model on all training data
model = XGBClassifier()
model.fit(X_train, y_train)

# make predictions for test data and evaluate
y_pred = model.predict(X_test)
predictions = [round(value) for value in y_pred]
accuracy = accuracy_score(y_test, predictions)
print("Accuracy: %.2f%%" % (accuracy * 100.0))

# Fit model using each importance as a threshold
thresholds = sort(model.feature_importances_)
for thresh in thresholds:
	# select features using threshold
	selection = SelectFromModel(model, threshold=thresh, prefit=True)
	select_X_train = selection.transform(X_train)
	
	# train model
	selection_model = XGBClassifier()
	selection_model.fit(select_X_train, y_train)
	
	# eval model
	select_X_test = selection.transform(X_test)
	y_pred = selection_model.predict(select_X_test)
	predictions = [round(value) for value in y_pred]
	accuracy = accuracy_score(y_test, predictions)
	print("Thresh=%.3f, n=%d, Accuracy: %.2f%%" % (thresh, select_X_train.shape[1], accuracy*100.0))

執行此示例將輸出以下輸出:

Accuracy: 77.95%
Thresh=0.071, n=8, Accuracy: 77.95%
Thresh=0.073, n=7, Accuracy: 76.38%
Thresh=0.084, n=6, Accuracy: 77.56%
Thresh=0.090, n=5, Accuracy: 76.38%
Thresh=0.128, n=4, Accuracy: 76.38%
Thresh=0.160, n=3, Accuracy: 74.80%
Thresh=0.186, n=2, Accuracy: 71.65%
Thresh=0.208, n=1, Accuracy: 63.78%

我們可以看到,模型的效能通常隨著所選特徵的數量而下降。

在這個問題上,為了測試集的精度,需要權衡一些特性,我們可以選擇一個不那麼複雜的模型(更少的屬性,比如n=4),並接受將估計精度從77.95%適度降低到76.38%。

總結

在這篇文章中,您發現瞭如何在一個經過訓練的XGBoost梯度增強模型中選擇特性和使用重要性。

具體來說,你學會了:

特性的重要性是什麼,以及在XGBoost中如何計算特性的重要性。
如何從XGBoost模型訪問和繪製功能的重要性評分。
如何使用XGBoost模型中的特性重要性進行特性選擇。對於這樣一個小的資料集,這可能是一種衝擊,但是對於更大的資料集,使用交叉驗證作為模型評估方案可能是一種更有用的策略。

原文出處

相關文章