在 Kaggle 的很多比賽中,我們可以看到很多 winner 喜歡用 xgboost,而且獲得非常好的表現,今天就來看看 xgboost 到底是什么以及如何應用。
本文結構:
XGBoost :eXtreme Gradient Boosting
項目地址:https://github.com/dmlc/xgboost
是由 Tianqi Chen http://homes.cs.washington.edu/~tqchen/ 初開發的實現可擴展,便攜,分布式 gradient boosting (GBDT, GBRT or GBM) 算法的一個庫,可以下載安裝并應用于 C++,Python,R,Julia,Java,Scala,Hadoop,現在有很多協作者共同開發維護。
XGBoost 所應用的算法就是 gradient boosting decision tree,既可以用于分類也可以用于回歸問題中。
那什么是 Gradient Boosting?
Gradient boosting 是 boosting 的其中一種方法,所謂 Boosting ,就是將弱分離器 f_i(x) 組合起來形成強分類器 F(x) 的一種方法。
所以 Boosting 有三個要素:
A loss function to be optimized:
例如分類問題中用 cross entropy,回歸問題用 mean squared error。
A weak learner to make predictions:
例如決策樹。
An additive model:
將多個弱學習器累加起來組成強學習器,進而使目標損失函數達到極小。
Gradient boosting 就是通過加入新的弱學習器,來努力糾正前面所有弱學習器的殘差,終這樣多個學習器相加在一起用來進行終預測,準確率就會比單獨的一個要高。之所以稱為 Gradient,是因為在添加新模型時使用了梯度下降算法來小化的損失。
種 Gradient Boosting 的實現就是 AdaBoost(Adaptive Boosting)。
AdaBoost 就是將多個弱分類器,通過投票的手段來改變各個分類器的權值,使分錯的分類器獲得較大權值。同時在每一次循環中也改變樣本的分布,這樣被錯誤分類的樣本也會受到更多的關注。
前面已經知道,XGBoost 就是對 gradient boosting decision tree 的實現,但是一般來說,gradient boosting 的實現是比較慢的,因為每次都要先構造出一個樹并添加到整個模型序列中。
而 XGBoost 的特點就是計算速度快,模型表現好,這兩點也正是這個項目的目標。
表現快是因為它具有這樣的設計:
下圖就是 XGBoost 與其它 gradient boosting 和 bagged decision trees 實現的效果比較,可以看出它比 R, Python,Spark,H2O 中的基準配置要更快。
另外一個優點就是在預測問題中模型表現非常好,下面是幾個 kaggle winner 的賽后采訪鏈接,可以看出 XGBoost 的在實戰中的效果。
先來用 Xgboost 做一個簡單的二分類問題,以下面這個數據為例,來判斷病人是否會在 5 年內患糖尿病,這個數據前 8 列是變量,后一列是預測值為 0 或 1。
數據描述:
https://archive.ics.uci.edu/ml/datasets/Pima+Indians+Diabetes
下載數據集,并保存為 “pima-indians-diabetes.csv“ 文件:
https://archive.ics.uci.edu/ml/machine-learning-databases/pima-indians-diabetes/pima-indians-diabetes.data
1. 基礎應用
引入xgboost等包
from numpy import loadtxt from xgboost import XGBClassifier from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score
分出變量和標簽
dataset = loadtxt('pima-indians-diabetes.csv', delimiter=",") X = dataset[:,0:8] Y = dataset[:,8]
將數據分為訓練集和測試集,測試集用來預測,訓練集用來學習模型
seed = 7 test_size = 0.33 X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=test_size, random_state=seed)
xgboost 有封裝好的分類器和回歸器,可以直接用 XGBClassifier 建立模型,這里是 XGBClassifier 的文檔:
http://xgboost.readthedocs.io/en/latest/python/python_api.html#module-xgboost.sklearn
model = XGBClassifier()
model.fit(X_train, y_train)
xgboost 的結果是每個樣本屬于類的概率,需要用 round 將其轉換為 0 1 值
y_pred = model.predict(X_test)
predictions = [round(value) for value in y_pred]
得到 Accuracy: 77.95%
accuracy = accuracy_score(y_test, predictions) print("Accuracy: %.2f%%" % (accuracy * 100.0))
2. 監控模型表現
xgboost可以在模型訓練時,評價模型在測試集上的表現,也可以輸出每一步的分數,只需要將
model = XGBClassifier()
model.fit(X_train, y_train)
變為:
model = XGBClassifier() eval_set = [(X_test, y_test)]
model.fit(X_train, y_train, early_stopping_rounds=10, eval_metric="logloss", eval_set=eval_set, verbose=True)
那么它會在每加入一顆樹后打印出 logloss
[31] validation_0-logloss:0.487867 [32] validation_0-logloss:0.487297 [33] validation_0-logloss:0.487562
并打印出 Early Stopping 的點:
Stopping. Best iteration: [32] validation_0-logloss:0.487297
3. 輸出特征重要度
gradient boosting還有一個優點是可以給出訓練好的模型的特征重要性,
這樣就可以知道哪些變量需要被保留,哪些可以舍棄。
需要引入下面兩個類:
from xgboost import plot_importance from matplotlib import pyplot
和前面的代碼相比,就是在 fit 后面加入兩行畫出特征的重要性
model.fit(X, y) plot_importance(model) pyplot.show()
4. 調參
如何調參呢,下面是三個超參數的一般實踐佳值,可以先將它們設定為這個范圍,然后畫出 learning curves,再調解參數找到佳模型:
接下來我們用 GridSearchCV 來進行調參會更方便一些:
可以調的超參數組合有:
樹的個數和大小 (n_estimators and max_depth).
學習率和樹的個數 (learning_rate and n_estimators).
行列的 subsampling rates (subsample, colsample_bytree and colsample_bylevel).
下面以學習率為例:
先引入這兩個類
from sklearn.model_selection import GridSearchCV from sklearn.model_selection import StratifiedKFold
設定要調節的 learning_rate = [0.0001, 0.001, 0.01, 0.1, 0.2, 0.3],和原代碼相比就是在 model 后面加上 grid search 這幾行:
model = XGBClassifier() learning_rate = [0.0001, 0.001, 0.01, 0.1, 0.2, 0.3] param_grid = dict(learning_rate=learning_rate) kfold = StratifiedKFold(n_splits=10, shuffle=True, random_state=7) grid_search = GridSearchCV(model, param_grid, scoring="neg_log_loss", n_jobs=-1, cv=kfold) grid_result = grid_search.fit(X, Y)
后會給出佳的學習率為 0.1
Best: -0.483013 using {‘learning_rate’: 0.1}
print("Best: %f using %s" % (grid_result.best_score_, grid_result.best_params_))
我們還可以用下面的代碼打印出每一個學習率對應的分數:
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))
-0.689650 (0.000242) with: {'learning_rate': 0.0001} -0.661274 (0.001954) with: {'learning_rate': 0.001} -0.530747 (0.022961) with: {'learning_rate': 0.01} -0.483013 (0.060755) with: {'learning_rate': 0.1} -0.515440 (0.068974) with: {'learning_rate': 0.2} -0.557315 (0.081738) with: {'learning_rate': 0.3}
本站文章版權歸原作者及原出處所有 。內容為作者個人觀點, 并不代表本站贊同其觀點和對其真實性負責,本站只提供參考并不構成任何投資及應用建議。本站是一個個人學習交流的平臺,網站上部分文章為轉載,并不用于任何商業目的,我們已經盡可能的對作者和來源進行了通告,但是能力有限或疏忽,造成漏登,請及時聯系我們,我們將根據著作權人的要求,立即更正或者刪除有關內容。本站擁有對此聲明的最終解釋權。