XGBoost你真的懂嗎?我不信.....

在這篇文章中,我們將介紹一些技術以更好地理解 XGBoost 的預測過程。這允許我們在利用 gradient boosting 的威力的同時,仍然能理解模型的決策過程。

爲了解釋這些技術,我們將使用 Titanic 數據集。該數據集有每個泰坦尼克號乘客的信息(包括乘客是否生還)。我們的目標是預測一個乘客是否生還,並且理解做出該預測的過程。即使是使用這些數據,我們也能看到理解模型決策的重要性。想象一下,假如我們有一個關於最近發生的船難的乘客數據集。建立這樣的預測模型的目的實際上並不在於預測結果本身,但理解預測過程可以幫助我們學習如何最大化意外中的生還者。

import pandas as pd
from xgboost import XGBClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
import operator
import matplotlib.pyplot as plt
import seaborn as sns
import lime.lime_tabular
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import Imputer
import numpy as np
from sklearn.grid_search import GridSearchCV
%matplotlib inline

我們要做的首件事是觀察我們的數據,你可以在 Kaggle 上找到(https://www.kaggle.com/c/titanic/data)這個數據集。拿到數據集之後,我們會對數據進行簡單的清理。即:

  • 清除名字和乘客 ID

  • 把分類變量轉化爲虛擬變量

  • 用中位數填充和去除數據

這些清洗技巧非常簡單,本文的目標不是討論數據清洗,而是解釋 XGBoost,因此這些都是快速、合理的清洗以使模型獲得訓練。

data = pd.read_csv("./data/titantic/train.csv")
y = data.Survived
X = data.drop(["Survived", "Name", "PassengerId"], 1)
X = pd.get_dummies(X)

現在讓我們將數據集分爲訓練集和測試集。

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=42)

並通過少量的超參數測試構建一個訓練管道。

pipeline = Pipeline([( imputer , Imputer(strategy= median )), ( model , XGBClassifier())])
parameters = dict(model__max_depth=[3, 5, 7],
                  model__learning_rate=[.01, .1],
                  model__n_estimators=[100, 500])
cv = GridSearchCV(pipeline, param_grid=parameters)
cv.fit(X_train, y_train)

接着查看測試結果。爲簡單起見,我們將會使用與 Kaggle 相同的指標:準確率。

test_predictions = cv.predict(X_test)
print("Test Accuracy: {}".format(accuracy_score(y_test, test_predictions)))
Test Accuracy: 0.8101694915254237

至此我們得到了一個還不錯的準確率,在 Kaggle 的大約 9000 個競爭者中排到了前 500 名。因此我們還有進一步提升的空間,但在此將作爲留給讀者的練習。

我們繼續關於理解模型學習到什麼的討論。常用的方法是使用 XGBoost 提供的特徵重要性(feature importance)。特徵重要性的級別越高,表示該特徵對改善模型預測的貢獻越大。接下來我們將使用重要性參數對特徵進行分級,並比較相對重要性。

fi = list(zip(X.columns, cv.best_estimator_.named_steps[ model ].feature_importances_))
fi.sort(key = operator.itemgetter(1), reverse=True)
top_10 = fi[:10]
x = [x[0] for x in top_10]
y = [x[1] for x in top_10]

從上圖可以看出,票價和年齡是很重要的特徵。我們可以進一步查看生還/遇難與票價的相關分佈:

我們可以很清楚地看到,那些生還者相比遇難者的平均票價要高得多,因此把票價當成重要特徵可能是合理的。

特徵重要性可能是理解一般的特徵重要性的不錯方法。假如出現了這樣的特例,即模型預測一個高票價的乘客無法獲得生還,則我們可以得出高票價並不必然導致生還,接下來我們將分析可能導致模型得出該乘客無法生還的其它特徵。

這種個體層次上的分析對於生產式機器學習系統可能非常有用。考慮其它例子,使用模型預測是否可以某人一項貸款。我們知道信用評分將是模型的一個很重要的特徵,但是卻出現了一個擁有高信用評分卻被模型拒絕的客戶,這時我們將如何向客戶做出解釋?又該如何向管理者解釋?

幸運的是,近期出現了華盛頓大學關於解釋任意分類器的預測過程的研究。他們的方法稱爲 LIME,已經在 GitHub 上開源(https://github.com/marcotcr/lime)。本文不打算對此展開討論,可以參見論文(https://arxiv.org/pdf/1602.04938.pdf)

接下來我們嘗試在模型中應用 LIME。基本上,首先需要定義一個處理訓練數據的解釋器(我們需要確保傳遞給解釋器的估算訓練數據集正是將要訓練的數據集):

X_train_imputed = cv.best_estimator_.named_steps[ imputer ].transform(X_train)
explainer = lime.lime_tabular.LimeTabularExplainer(X_train_imputed,
    feature_names=X_train.columns.tolist(),
    class_names=["Not Survived", "Survived"],
    discretize_continuous=True)

隨後你必須定義一個函數,它以特徵數組爲變量,並返回一個數組和每個類的概率:

model = cv.best_estimator_.named_steps[ model ]
def xgb_prediction(X_array_in):
    if len(X_array_in.shape) < 2:
        X_array_in = np.expand_dims(X_array_in, 0)
    return model.predict_proba(X_array_in)

最後,我們傳遞一個示例,讓解釋器使用你的函數輸出特徵數和標籤:

X_test_imputed = cv.best_estimator_.named_steps[ imputer ].transform(X_test)
exp = explainer.explain_instance(X_test_imputed[1], xgb_prediction, num_features=5, top_labels=1)
exp.show_in_notebook(show_table=True, show_all=False)

在這裏我們有一個示例,76% 的可能性是不存活的。我們還想看看哪個特徵對於哪個類貢獻最大,重要性又如何。例如,在 Sex = Female 時,生存機率更大。讓我們看看柱狀圖:

所以這看起來很有道理。如果你是女性,這就大大提高了你在訓練數據中存活的機率。所以爲什麼預測結果是「未存活」?看起來 Pclass =2.0 大大降低了存活率。讓我們看看:

看起來 Pclass 等於 2 的存活率還是比較低的,所以我們對於自己的預測結果有了更多的理解。看看 LIME 上展示的 top5 特徵,看起來這個人似乎仍然能活下來,讓我們看看它的標籤:

y_test.values[0]
>>>1

這個人確實活下來了,所以我們的模型有錯!感謝 LIME,我們可以對問題原因有一些認識:看起來 Pclass 可能需要被拋棄。這種方式可以幫助我們,希望能夠找到一些改進模型的方法。

本文爲讀者提供了一個簡單有效理解 XGBoost 的方法。希望這些方法可以幫助你合理利用 XGBoost,讓你的模型能夠做出更好的推斷。

注:本文爲機器之心編譯,轉載請聯繫本公衆號獲得授權。

選自Ancestry

作者:Tyler Folkman

編譯:機器之心(almosthuman2014

原文:https://blogs.ancestry.com/ancestry/2017/12/18/understanding-machine-learning-xgboost/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章