Xgboost簡易入門教程

  最近準備研究一下信貸風控中機器學習模型評分卡的製作。信貸評分卡分爲兩種,一種是用邏輯迴歸,稱爲評分卡;一種是用集成學習算法,稱爲機器學習模型。邏輯迴歸算法相對簡單,但是解釋性要求高;機器學習模型理論上效果要更好一點,但是無法解釋,而且模型容易不穩定。於是找了一下網上能找到的關於機器學習模型做評分卡的案例,主要有拍拍貸比賽實例、金融風控實戰、kaggle上的Home Credit Default Risk比賽,附上相應的課程或比賽鏈接。

  1. 拍拍貸比賽案例
    https://www.bilibili.com/video/BV1NE41157Ag?p=29
  2. 金融風控實戰
    https://www.bilibili.com/video/BV18J411R7ei?p=11
  3. Kaggle案例
    https://www.kaggle.com/fanzzz/understand-variables-in-chinese

  本篇文章是一篇簡單的xgboost快速上手的教程,不涉及算法推導,幫助自己回顧一下xgboost的基本用法,後續會再複習一下算法的推導過程以及優缺點。

一、讀取數據並指定參數建模

xgboost讀取數據有兩種方式:

  1. 使用xgboost自帶的數據集格式 + xgboost自帶的建模方式
  • 把數據讀取成xgb.DMatrix格式(libsvm/dataframe.values給定X和Y)
  • 準備好一個watch_list(觀測和評估的數據集)
  • xgb.train(dtrain)
  • xgb.predict(dtest)
  1. 使用pandas的DataFrame格式 + xgboost的sklearn接口
  • estimator = xgb.XGBClassifier()/xgb.XGBRegressor()
  • estimator.fit(df_train.values, df_target.values)
    先看一下第一種方式讀取數據和建模的方法。
import numpy as np
import pandas as pd
import pickle
import xgboost as xgb
from sklearn.model_selection import train_test_split

data = pd.read_csv('./data/Pima-Indians-Diabetes.csv')

train, test = train_test_split(data)

# 轉換成Dmatrix格式
feature_columns = ['Pregnancies', 'Glucose', 'BloodPressure', 'SkinThickness', 'Insulin', 'BMI', 'DiabetesPedigreeFunction', 'Age']
target_column = 'Outcome'
# 需要將dataframe格式的數據轉化爲矩陣形式
xgtrain = xgb.DMatrix(train[feature_columns].values, train[target_column].values)
xgtest = xgb.DMatrix(test[feature_columns].values, test[target_column].values)

#參數設定
param = {'max_depth':5, 'eta':0.1, 'silent':1, 'subsample':0.7, 'colsample_bytree':0.7, 'objective':'binary:logistic' }

# 設定watchlist用於查看模型狀態
watchlist  = [(xgtest,'eval'), (xgtrain,'train')]
num_round = 10
bst = xgb.train(param, xgtrain, num_round, watchlist)

# 使用模型預測
preds = bst.predict(xgtest)

# 判斷準確率
labels = xgtest.get_label()
print ('錯誤類爲%f' % \
       (sum(1 for i in range(len(preds)) if int(preds[i]>0.5)!=labels[i]) /float(len(preds))))

# 模型存儲
bst.save_model('./model/0002.model')

  第一點就是輸入數據形式要轉化成矩陣的形式,第二點就是watchlist參數用於查看模型的狀態,也就是爲了輸出eval-error和train-error。然後再解釋下幾個參數的含義:

‘max_depth’:設置樹的最大深度。默認爲6。
‘eta’:學習率。默認爲0.3。
‘silent’:0表示輸出信息, 1表示安靜模式。默認爲0。
‘subsample’:觀測的子樣本的比率,即對總體進行隨機抽樣的比例。默認爲1。
'colsample_bytree ':用於構造每棵樹時變量的子樣本比率.即特徵抽樣。默認爲1。
‘objective’:最小化的損失函數。

  xgboost的參數可以分爲三類,通用參數/general parameters, 集成(增強)參數/booster parameters 和 任務參數/task parameters。
以上silent是通用參數,objective是任務參數,其它的都是集成參數。

  再來看一下使用sklearn接口進行建模的例子。

#!/usr/bin/python
import warnings
warnings.filterwarnings("ignore")
import numpy as np
import pandas as pd
import pickle
import xgboost as xgb
from sklearn.model_selection import train_test_split
from sklearn.externals import joblib

data = pd.read_csv('./data/Pima-Indians-Diabetes.csv')

train, test = train_test_split(data)

# 取出特徵X和目標y的部分
feature_columns = ['Pregnancies', 'Glucose', 'BloodPressure', 'SkinThickness', 'Insulin', 'BMI', 'DiabetesPedigreeFunction', 'Age']
target_column = 'Outcome'
train_X = train[feature_columns].values
train_y = train[target_column].values
test_X = test[feature_columns].values
test_y = test[target_column].values

# 初始化模型
xgb_classifier = xgb.XGBClassifier(n_estimators=20,max_depth=4,learning_rate=0.1, subsample=0.7, colsample_bytree=0.7)

# 擬合模型
xgb_classifier.fit(train_X, train_y)

# 使用模型預測
preds = xgb_classifier.predict(test_X)

# 判斷準確率
print ('錯誤類爲%f' %((preds!=test_y).sum()/float(test_y.shape[0])))

# 模型存儲
joblib.dump(xgb_classifier, './model/0003.model')

  讀取數據和建模的大致流程就這麼兩種,下面結合xgb建模的方式進行深入地瞭解。
  利用xgb進行交叉驗證。

param = {'max_depth':5, 'eta':0.1, 'silent':0, 'subsample':0.7, 'colsample_bytree':0.7, 'objective':'binary:logistic' }
num_round = 10
dtrain = xgb.DMatrix(train[feature_columns].values, train[target_column].values)

xgb.cv(param, dtrain, num_round, nfold=5,metrics={'error'}, seed = 0)

xgb.cv的參數的含義如下:

‘num_round’:最大迭代次數。
‘metric’:評價指標,一般用AUC。

  除了xgb自帶的驗證方法以外還有GridSearchCV交叉驗證方法,後面會提到。然後進行添加預處理的交叉驗證,即通過計算正負樣本比調整樣本的權重。

# 計算正負樣本比,調整樣本權重
def fpreproc(dtrain, dtest, param):
    label = dtrain.get_label()
    ratio = float(np.sum(label == 0)) / np.sum(label==1)
    param['scale_pos_weight'] = ratio
    return (dtrain, dtest, param)

# 先做預處理,計算樣本權重,再做交叉驗證
xgb.cv(param, dtrain, num_round, nfold=5,
       metrics={'auc'}, seed = 0, fpreproc = fpreproc)

  在參數裏面加了一個’scale_pos_weight’,可以在樣本類別不平衡的時候加速收斂。
  下面再進行自定義損失函數與評估準則,這也是xgb的優勢所在。

print ('running cross validation, with cutomsized loss function')
# 自定義損失函數,需要提供損失函數的一階導和二階導
def logregobj(preds, dtrain):
    labels = dtrain.get_label()
    preds = 1.0 / (1.0 + np.exp(-preds))
    grad = preds - labels
    hess = preds * (1.0-preds)
    return grad, hess

# 自定義評估準則,評估預估值和標準答案之間的差距
def evalerror(preds, dtrain):
    labels = dtrain.get_label()
    return 'error', float(sum(labels != (preds > 0.0))) / len(labels)

watchlist  = [(dtest,'eval'), (dtrain,'train')]
param = {'max_depth':3, 'eta':0.1, 'silent':1}
num_round = 5
# 自定義損失函數訓練
bst = xgb.train(param, dtrain, num_round, watchlist, logregobj, evalerror)
# 交叉驗證
xgb.cv(param, dtrain, num_round, nfold = 5, seed = 0,
       obj = logregobj, feval=evalerror)

  針對業務改寫評價函數,這裏的要求是要保證損失函數二階可導,原因只要推導一遍xgboost公式就理解了,因爲其中有一步用到泰勒展開的二階項。
  此外,xgb還可以只用前n棵樹進行預測,用到的參數是ntree_limit,不再贅述。

  瞭解完xgb進行建模之後,再看一下使用sklearn進行xgb建模的實例。這裏使用了鳶尾花數據集合波士頓房價預測數據集分別進行分類和迴歸的學習。

import pickle
import xgboost as xgb

import numpy as np
from sklearn.model_selection import KFold, train_test_split, GridSearchCV
from sklearn.metrics import confusion_matrix, mean_squared_error
from sklearn.datasets import load_iris, load_digits, load_boston

rng = np.random.RandomState(31337)

分類:

#二分類:混淆矩陣
print("數字0和1的二分類問題")
digits = load_digits(2)
y = digits['target']
X = digits['data']
kf = KFold(n_splits=2, shuffle=True, random_state=rng)
print("在2折數據上的交叉驗證")
for train_index, test_index in kf.split(X):
    xgb_model = xgb.XGBClassifier().fit(X[train_index],y[train_index])
    predictions = xgb_model.predict(X[test_index])
    actuals = y[test_index]
    print("混淆矩陣:")
    print(confusion_matrix(actuals, predictions))

#多分類:混淆矩陣
print("\nIris: 多分類")
iris = load_iris()
y = iris['target']
X = iris['data']
kf = KFold(n_splits=2, shuffle=True, random_state=rng)
print("在2折數據上的交叉驗證")
for train_index, test_index in kf.split(X):
    xgb_model = xgb.XGBClassifier().fit(X[train_index],y[train_index])
    predictions = xgb_model.predict(X[test_index])
    actuals = y[test_index]
    print("混淆矩陣:")
    print(confusion_matrix(actuals, predictions))

迴歸:


#迴歸問題:MSE
print("\n波士頓房價迴歸預測問題")
boston = load_boston()
y = boston['target']
X = boston['data']
kf = KFold(n_splits=2, shuffle=True, random_state=rng)
print("在2折數據上的交叉驗證")
for train_index, test_index in kf.split(X):
    xgb_model = xgb.XGBRegressor().fit(X[train_index],y[train_index])
    predictions = xgb_model.predict(X[test_index])
    actuals = y[test_index]
    print("MSE:",mean_squared_error(actuals, predictions))

  接下來看一下如何利用網格搜索查找最優超參數。這種方法僅適用於使用sklearn接口建模,採用GridSearchCV方法。

#調參方法:使用sklearn接口的regressor + GridSearchCV
print("參數最優化:")
y = boston['target']
X = boston['data']
xgb_model = xgb.XGBRegressor()
param_dict = {'max_depth': [2,4,6],
              'n_estimators': [50,100,200]}

clf = GridSearchCV(xgb_model, param_dict, verbose=1)
clf.fit(X,y)
print(clf.best_score_)
print(clf.best_params_)

  可以看到網格搜索結果,最大深度爲2,100個估計器。網格調參的方法就是將參數及參數的取值放入一個字典中,然後作爲GridSearchCV這個方法的參數。
  再看一下xgboost如何採用早停的參數停止樹的增長。早停參數的調整適用於兩種xgb建模方法。

# 第1/2種訓練方法的 調參方法:early stopping
X = digits['data']
y = digits['target']
X_train, X_val, y_train, y_val = train_test_split(X, y, random_state=0)
clf = xgb.XGBClassifier()
clf.fit(X_train, y_train, early_stopping_rounds=20, eval_metric="auc",
        eval_set=[(X_val, y_val)])

  該方法在訓練集上學習模型,一顆一顆樹添加,在驗證集上看效果,當驗證集效果不再提升,停止樹的添加與生長。可以看到第10棵樹時就不再提高,所以early_stopping_rounds的最佳值爲10。關於xgboost調參的方法可以網上找一篇教程看一下,方法都是一樣的,看一遍就懂了,附上很久之前整理的調參的基本思路。

  最後再畫圖看一下特徵的重要性。

iris = load_iris()
y = iris['target']
X = iris['data']
xgb_model = xgb.XGBClassifier().fit(X,y)

print('特徵排序:')
feature_names=['sepal_length', 'sepal_width', 'petal_length', 'petal_width']
feature_importances = xgb_model.feature_importances_
indices = np.argsort(feature_importances)[::-1]

for index in indices:
    print("特徵 %s 重要度爲 %f" %(feature_names[index], feature_importances[index]))

%matplotlib inline
import matplotlib.pyplot as plt
plt.figure(figsize=(16,8))
plt.title("feature importances")
plt.bar(range(len(feature_importances)), feature_importances[indices], color='b')
plt.xticks(range(len(feature_importances)), np.array(feature_names)[indices], color='b')

  xgboost特徵重要性指標: weight, gain, cover,可以通過xgb_model.get_booster().get_score(importance_type=importance_type))中的importance進行設置。
  最後附上一個並行訓練加速的代碼,需要用到的時候再來看。

import os

if __name__ == "__main__":
    try:
        from multiprocessing import set_start_method
    except ImportError:
        raise ImportError("Unable to import multiprocessing.set_start_method."
                          " This example only runs on Python 3.4")
    # set_start_method("forkserver")

    import numpy as np
    from sklearn.model_selection import GridSearchCV
    from sklearn.datasets import load_boston
    import xgboost as xgb

    rng = np.random.RandomState(31337)

    print("Parallel Parameter optimization")
    boston = load_boston()

    os.environ["OMP_NUM_THREADS"] = "2"  # or to whatever you want
    y = boston['target']
    X = boston['data']
    xgb_model = xgb.XGBRegressor()
    clf = GridSearchCV(xgb_model, {'max_depth': [2, 4, 6],
                                   'n_estimators': [50, 100, 200]}, verbose=1,
                       n_jobs=2)
    clf.fit(X, y)
    print(clf.best_score_)
    print(clf.best_params_)

【作者】:Labryant
【原創公衆號】:風控獵人
【簡介】:某創業公司策略分析師,積極上進,努力提升。乾坤未定,你我都是黑馬。
【轉載說明】:轉載請說明出處,謝謝合作!~

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