Python機器學習筆記:XgBoost算法


前言

1,Xgboost簡介

  Xgboost是Boosting算法的其中一種,Boosting算法的思想是將許多弱分類器集成在一起,形成一個強分類器。因為Xgboost是一種提升樹模型,所以它是將許多樹模型集成在一起,形成一個很強的分類器。而所用到的樹模型則是CART回歸樹模型。

  Xgboost是在GBDT的基礎上進行改進,使之更強大,適用於更大范圍。

  Xgboost一般和sklearn一起使用,但是由於sklearn中沒有集成Xgboost,所以才需要單獨下載安裝。

2,Xgboost的優點

  Xgboost算法可以給預測模型帶來能力的提升。當我們對其表現有更多了解的時候,我們會發現他有如下優勢:

2.1  正則化

  實際上,Xgboost是以“正則化提升(regularized boosting)” 技術而聞名。Xgboost在代價函數里加入了正則項,用於控制模型的復雜度。正則項里包含了樹的葉子節點個數,每個葉子節點上輸出的score的L2模的平方和。從Bias-variance tradeoff角度來講,正則項降低了模型的variance,使學習出來的模型更加簡單,防止過擬合,這也是Xgboost優於傳統GBDT的一個特征

2.2  並行處理

  Xgboost工具支持並行。眾所周知,Boosting算法是順序處理的,也是說Boosting不是一種串行的結構嗎?怎么並行的?注意Xgboost的並行不是tree粒度的並行。Xgboost也是一次迭代完才能進行下一次迭代的(第t次迭代的代價函數里包含)。Xgboost的並行式在特征粒度上的,也就是說每一顆樹的構造都依賴於前一顆樹。

  我們知道,決策樹的學習最耗時的一個步驟就是對特征的值進行排序(因為要確定最佳分割點),Xgboost在訓練之前,預先對數據進行了排序,然后保存為block結構,后面的迭代中重復使用這個結構,大大減小計算量。這個block結構也使得並行成為了可能,在進行節點的分類時,需要計算每個特征的增益,大大減少計算量。這個block結構也使得並行成為了可能,在進行節點的分裂的時候,需要計算每個特征的增益,最終選增益最大的那個特征去做分裂,那么各個特征的增益計算就可以開多線程進行。

2.3  靈活性

  Xgboost支持用戶自定義目標函數和評估函數,只要目標函數二階可導就行。它對模型增加了一個全新的維度,所以我們的處理不會受到任何限制。

2.4  缺失值處理

  對於特征的值有缺失的樣本,Xgboost可以自動學習出他的分裂方向。Xgboost內置處理缺失值的規則。用戶需要提供一個和其他樣本不同的值,然后把它作為一個參數穿進去,以此來作為缺失值的取值。Xgboost在不同節點遇到缺失值時采用不同的處理方法,並且會學習未來遇到缺失值時的處理方法。

2.5  剪枝

  Xgboost先從頂到底建立所有可以建立的子樹,再從底到頂反向機芯剪枝,比起GBM,這樣不容易陷入局部最優解

2.6  內置交叉驗證

  Xgboost允許在每一輪Boosting迭代中使用交叉驗證。因此可以方便的獲得最優Boosting迭代次數,而GBM使用網格搜索,只能檢測有限個值。

 

3,Xgboost的離線安裝

1,點擊此處,下載對應自己Python版本的網址。

2,輸入安裝的程式:

pip install xgboost-0.81-cp37-cp37m-win_amd64.whl

 

Xgboost模型詳解

1,Xgboost能加載的各種數據格式解析

  Xgboost可以加載多種數據格式的訓練數據:

libsvm 格式的文本數據;

Numpy 的二維數組;

XGBoost 的二進制的緩存文件。加載的數據存儲在對象 DMatrix 中。

   下面一一列舉:

  記載libsvm格式的數據

dtrain1 = xgb.DMatrix('train.svm.txt')

  記載二進制的緩存文件

dtrain2  = xgb.DMatrix('train.svm.buffer')

  加載numpy的數組

data = np.random.rand(5,10)                 # 5行10列數據集
label = np.random.randint(2,size=5)       # 二分類目標值
dtrain = xgb.DMatrix(data,label=label)    # 組成訓練集

  將scipy.sparse格式的數據轉化為Dmatrix格式

csr = scipy.sparse.csr_matrix((dat,(row,col)))
dtrain = xgb.DMatrix( csr )

  將Dmatrix格式的數據保存成Xgboost的二進制格式,在下次加載時可以提高加載速度,使用方法如下:

dtrain = xgb.DMatrix('train.svm.txt')
dtrain.save_binary("train.buffer")

  可以使用如下方式處理DMatrix中的缺失值

dtrain = xgb.DMatrix( data, label=label, missing = -999.0)

  當需要給樣本設置權重時,可以用如下方式:

w = np.random.rand(5,1)
dtrain = xgb.DMatrix( data, label=label, missing = -999.0, weight=w)

2,Xgboost的模型參數

  Xgboost使用key-value字典的方式存儲參數

# xgboost模型
params = {
    'booster':'gbtree',
    'objective':'multi:softmax',   # 多分類問題
    'num_class':10,  # 類別數,與multi softmax並用
    'gamma':0.1,    # 用於控制是否后剪枝的參數,越大越保守,一般0.1 0.2的樣子
    'max_depth':12,  # 構建樹的深度,越大越容易過擬合
    'lambda':2,  # 控制模型復雜度的權重值的L2 正則化項參數,參數越大,模型越不容易過擬合
    'subsample':0.7, # 隨機采樣訓練樣本
    'colsample_bytree':3,# 這個參數默認為1,是每個葉子里面h的和至少是多少
    # 對於正負樣本不均衡時的0-1分類而言,假設h在0.01附近,min_child_weight為1
    #意味着葉子節點中最少需要包含100個樣本。這個參數非常影響結果,
    # 控制葉子節點中二階導的和的最小值,該參數值越小,越容易過擬合
    'silent':0,  # 設置成1 則沒有運行信息輸入,最好是設置成0
    'eta':0.007,  # 如同學習率
    'seed':1000,
    'nthread':7,  #CPU線程數
    #'eval_metric':'auc'
}

  

  在運行Xgboost之前,必須設置三種類型成熟:general parameters,booster parameters和task parameters:

  通用參數(General Parameters):該參數控制在提升(boosting)過程中使用哪種booster,常用的booster有樹模型(tree)和線性模型(linear model)

  Booster參數(Booster Parameters):這取決於使用哪種booster

  學習目標參數(Task Parameters):控制學習的場景,例如在回歸問題中會使用不同的參數控制排序

2.1, 通用參數

    • booster [default=gbtree] 
      • 有兩種模型可以選擇gbtree和gblinear。gbtree使用基於樹的模型進行提升計算,gblinear使用線性模型進行提升計算。缺省值為gbtree
    • silent [default=0] 
      • 取0時表示打印出運行時信息,取1時表示以緘默方式運行,不打印運行時的信息。缺省值為0
      • 建議取0,過程中的輸出數據有助於理解模型以及調參。另外實際上我設置其為1也通常無法緘默運行。。
    • nthread [default to maximum number of threads available if not set] 
      • XGBoost運行時的線程數。缺省值是當前系統可以獲得的最大線程數
      • 如果你希望以最大速度運行,建議不設置這個參數,模型將自動獲得最大線程
    • num_pbuffer [set automatically by xgboost, no need to be set by user] 
      • size of prediction buffer, normally set to number of training instances. The buffers are used to save the prediction results of last boosting step.
    • num_feature [set automatically by xgboost, no need to be set by user] 
      • boosting過程中用到的特征維數,設置為特征個數。XGBoost會自動設置,不需要手工設置

2.2,tree booster參數

    • eta [default=0.3] 
      • 為了防止過擬合,更新過程中用到的收縮步長。在每次提升計算之后,算法會直接獲得新特征的權重。 eta通過縮減特征的權重使提升計算過程更加保守。缺省值為0.3
      • 取值范圍為:[0,1]
      • 通常最后設置eta為0.01~0.2
    • gamma [default=0] 
      • minimum loss reduction required to make a further partition on a leaf node of the tree. the larger, the more conservative the algorithm will be.
      • range: [0,∞]
      • 模型在默認情況下,對於一個節點的划分只有在其loss function 得到結果大於0的情況下才進行,而gamma 給定了所需的最低loss function的值
      • gamma值使得算法更conservation,且其值依賴於loss function ,在模型中應該進行調參。
    • max_depth [default=6] 
      • 樹的最大深度。缺省值為6
      • 取值范圍為:[1,∞]
      • 指樹的最大深度
      • 樹的深度越大,則對數據的擬合程度越高(過擬合程度也越高)。即該參數也是控制過擬合
      • 建議通過交叉驗證(xgb.cv ) 進行調參
      • 通常取值:3-10
    • min_child_weight [default=1] 
      • 孩子節點中最小的樣本權重和。如果一個葉子節點的樣本權重和小於min_child_weight則拆分過程結束。在現行回歸模型中,這個參數是指建立每個模型所需要的最小樣本數。該成熟越大算法越conservative。即調大這個參數能夠控制過擬合。
      • 取值范圍為: [0,∞]
    • max_delta_step [default=0] 
      • Maximum delta step we allow each tree’s weight estimation to be. If the value is set to 0, it means there is no constraint. If it is set to a positive value, it can help making the update step more conservative. Usually this parameter is not needed, but it might help in logistic regression when class is extremely imbalanced. Set it to value of 1-10 might help control the update
      • 取值范圍為:[0,∞]
      • 如果取值為0,那么意味着無限制。如果取為正數,則其使得xgboost更新過程更加保守。
      • 通常不需要設置這個值,但在使用logistics 回歸時,若類別極度不平衡,則調整該參數可能有效果
    • subsample [default=1] 
      • 用於訓練模型的子樣本占整個樣本集合的比例。如果設置為0.5則意味着XGBoost將隨機的從整個樣本集合中抽取出50%的子樣本建立樹模型,這能夠防止過擬合。
      • 取值范圍為:(0,1]
    • colsample_bytree [default=1] 
      • 在建立樹時對特征隨機采樣的比例。缺省值為1
      • 取值范圍:(0,1]
    • colsample_bylevel[default=1]
      • 決定每次節點划分時子樣例的比例
      • 通常不使用,因為subsample和colsample_bytree已經可以起到相同的作用了
    • scale_pos_weight[default=0]
      • A value greater than 0 can be used in case of high class imbalance as it helps in faster convergence.
      • 大於0的取值可以處理類別不平衡的情況。幫助模型更快收斂

2.3,Linear Booster參數

    • lambda [default=0] 
      • L2 正則的懲罰系數
      • 用於處理XGBoost的正則化部分。通常不使用,但可以用來降低過擬合
    • alpha [default=0] 
      • L1 正則的懲罰系數
      • 當數據維度極高時可以使用,使得算法運行更快。
    • lambda_bias 
      • 在偏置上的L2正則。缺省值為0(在L1上沒有偏置項的正則,因為L1時偏置不重要)

 

2.4,學習目標參數

  這個參數是來控制理想的優化目標和每一步結果的度量方法。

    • objective [ default=reg:linear ] 
      • 定義學習任務及相應的學習目標,可選的目標函數如下:
      • “reg:linear” –線性回歸。
      • “reg:logistic” –邏輯回歸。
      • “binary:logistic” –二分類的邏輯回歸問題,輸出為概率。
      • “binary:logitraw” –二分類的邏輯回歸問題,輸出的結果為wTx。
      • “count:poisson” –計數問題的poisson回歸,輸出結果為poisson分布。
      • 在poisson回歸中,max_delta_step的缺省值為0.7。(used to safeguard optimization)
      • “multi:softmax” –讓XGBoost采用softmax目標函數處理多分類問題,同時需要設置參數num_class(類別個數)
      • “multi:softprob” –和softmax一樣,但是輸出的是ndata * nclass的向量,可以將該向量reshape成ndata行nclass列的矩陣。每行數據表示樣本所屬於每個類別的概率。
      • “rank:pairwise” –set XGBoost to do ranking task by minimizing the pairwise loss
    • base_score [ default=0.5 ] 
      • the initial prediction score of all instances, global bias
    • eval_metric [ default according to objective ] 
      • 校驗數據所需要的評價指標,不同的目標函數將會有缺省的評價指標(rmse for regression, and error for classification, mean average precision for ranking)
      • 用戶可以添加多種評價指標,對於Python用戶要以list傳遞參數對給程序,而不是map參數list參數不會覆蓋’eval_metric’
      • The choices are listed below:
      • “rmse”: root mean square error
      • “logloss”: negative log-likelihood
      • “error”: Binary classification error rate. It is calculated as #(wrong cases)/#(all cases). For the predictions, the evaluation will regard the instances with prediction value larger than 0.5 as positive instances, and the others as negative instances.
      • “merror”: Multiclass classification error rate. It is calculated as #(wrong cases)/#(all cases).
      • “mlogloss”: Multiclass logloss
      • auc”: Area under the curve for ranking evaluation.
      • “ndcg”:Normalized Discounted Cumulative Gain
      • “map”:Mean average precision
      • “ndcg@n”,”map@n”: n can be assigned as an integer to cut off the top positions in the lists for evaluation.
      • “ndcg-“,”map-“,”ndcg@n-“,”map@n-“: In XGBoost, NDCG and MAP will evaluate the score of a list without any positive samples as 1. By adding “-” in the evaluation metric XGBoost will evaluate these score as 0 to be consistent under some conditions. 
        training repeatively
    • seed [ default=0 ] 
      • 隨機數的種子。缺省值為0
      • 可以用於產生可重復的結果(每次取一樣的seed即可得到相同的隨機划分)

3,Xgboost基本方法和默認參數

xgboost.train(params,dtrain,num_boost_round=10,evals(),obj=None,
feval=None,maximize=False,early_stopping_rounds=None,evals_result=None,
verbose_eval=True,learning_rates=None,xgb_model=None)

  

  parms:這是一個字典,里面包含着訓練中的參數關鍵字和對應的值,形式是parms = {'booster':'gbtree','eta':0.1}

  dtrain:訓練的數據

  num_boost_round:這是指提升迭代的個數

  evals:這是一個列表,用於對訓練過程中進行評估列表中的元素。形式是evals = [(dtrain,'train'),(dval,'val')] 或者是 evals =[(dtrain,'train')] ,對於第一種情況,它使得我們可以在訓練過程中觀察驗證集的效果。

  obj :自定義目的函數

  feval:自定義評估函數

  maximize:是否對評估函數進行最大化

  early_stopping_rounds:早起停止次數,假設為100,驗證集的誤差迭代到一定程度在100次內不能再繼續降低,就停止迭代。這要求evals里至少有一個元素,如果有多個,按照最后一個去執行。返回的是最后的迭代次數(不是最好的)。如果early_stopping_rounds存在,則模型會生成三個屬性,bst.best_score ,bst.best_iteration和bst.best_ntree_limit

  evals_result:字典,存儲在watchlist中的元素的評估結果

  verbose_eval(可以輸入布爾型或者數值型):也要求evals里至少有一個元素,如果為True,則對evals中元素的評估結果會輸出在結果中;如果輸入數字,假設為5,則每隔5個迭代輸出一次。

  learning_rates:每一次提升的學習率的列表

  xgb_model:在訓練之前用於加載的xgb_model

4,模型訓練

  有了參數列表和數據就可以訓練模型了

num_round = 10
bst = xgb.train( plst, dtrain, num_round, evallist )

5,模型預測

# X_test類型可以是二維List,也可以是numpy的數組
dtest = DMatrix(X_test)
ans = model.predict(dtest)

  完整代碼如下:

xgb_model.get_booster().save_model('xgb.model')
tar = xgb.Booster(model_file='xgb.model')
x_test = xgb.DMatrix(x_test)
pre=tar.predict(x_test)
act=y_test
print(mean_squared_error(act, pre))

  

6,保存模型

  在訓練完成之后可以將模型保存下來,也可以查看模型內部的結構

bst.save_model('test.model')

  導出模型和特征映射(Map)

  你可以導出模型到txt文件並瀏覽模型的含義:

# 導出模型到文件
bst.dump_model('dump.raw.txt')
# 導出模型和特征映射
bst.dump_model('dump.raw.txt','featmap.txt')

7,加載模型

  通過如下方式可以加載模型

bst = xgb.Booster({'nthread':4}) # init model
bst.load_model("model.bin")      # load data

 

Xgboost實戰

  Xgboost有兩大類接口:Xgboost原生接口 和sklearn接口,並且Xgboost能夠實現分類回歸兩種任務。下面對這四種情況做以解析。

 1,基於Xgboost原生接口的分類

from sklearn.datasets import load_iris
import xgboost as xgb
from xgboost import plot_importance
import matplotlib.pyplot  as plt
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score  # 准確率

# 記載樣本數據集
iris = load_iris()
X,y = iris.data,iris.target
# 數據集分割
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.2,random_state=123457)

# 算法參數
params = {
    'booster':'gbtree',
    'objective':'multi:softmax',
    'num_class':3,
    'gamma':0.1,
    'max_depth':6,
    'lambda':2,
    'subsample':0.7,
    'colsample_bytree':0.7,
    'min_child_weight':3,
    'slient':1,
    'eta':0.1,
    'seed':1000,
    'nthread':4,
}

plst = params.items()

# 生成數據集格式
dtrain = xgb.DMatrix(X_train,y_train)
num_rounds = 500
# xgboost模型訓練
model = xgb.train(plst,dtrain,num_rounds)

# 對測試集進行預測
dtest = xgb.DMatrix(X_test)
y_pred = model.predict(dtest)

# 計算准確率
accuracy = accuracy_score(y_test,y_pred)
print('accuarcy:%.2f%%'%(accuracy*100))

# 顯示重要特征
plot_importance(model)
plt.show()

  輸出預測正確率以及特征重要性:

accuarcy:93.33%

  

 

 

2,基於Xgboost原生接口的回歸

import xgboost as xgb
from xgboost import plot_importance
from matplotlib import pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_boston
from sklearn.metrics import mean_squared_error

# 加載數據集,此數據集時做回歸的
boston = load_boston()
X,y = boston.data,boston.target

# Xgboost訓練過程
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.2,random_state=0)

# 算法參數
params = {
    'booster':'gbtree',
    'objective':'reg:gamma',
    'gamma':0.1,
    'max_depth':5,
    'lambda':3,
    'subsample':0.7,
    'colsample_bytree':0.7,
    'min_child_weight':3,
    'slient':1,
    'eta':0.1,
    'seed':1000,
    'nthread':4,
}

dtrain = xgb.DMatrix(X_train,y_train)
num_rounds = 300
plst = params.items()
model = xgb.train(plst,dtrain,num_rounds)

# 對測試集進行預測
dtest = xgb.DMatrix(X_test)
ans = model.predict(dtest)

# 顯示重要特征
plot_importance(model)
plt.show()

  

   重要特征(值越大,說明該特征越重要)顯示結果:

 3,Xgboost使用sklearn接口的分類(推薦)

XGBClassifier

from xgboost.sklearn import XGBClassifier

clf = XGBClassifier(
    silent=0,  # 設置成1則沒有運行信息輸出,最好是設置為0,是否在運行升級時打印消息
    # nthread = 4  # CPU 線程數 默認最大
    learning_rate=0.3 , # 如同學習率
    min_child_weight = 1,
    # 這個參數默認為1,是每個葉子里面h的和至少是多少,對正負樣本不均衡時的0-1分類而言
    # 假設h在0.01附近,min_child_weight為1 意味着葉子節點中最少需要包含100個樣本
    # 這個參數非常影響結果,控制葉子節點中二階導的和的最小值,該參數值越小,越容易過擬合
    max_depth=6, # 構建樹的深度,越大越容易過擬合
    gamma = 0,# 樹的葉子節點上做進一步分區所需的最小損失減少,越大越保守,一般0.1 0.2這樣子
    subsample=1, # 隨機采樣訓練樣本,訓練實例的子采樣比
    max_delta_step=0,  # 最大增量步長,我們允許每個樹的權重估計
    colsample_bytree=1, # 生成樹時進行的列采樣
    reg_lambda=1, #控制模型復雜度的權重值的L2正則化項參數,參數越大,模型越不容易過擬合
    # reg_alpha=0, # L1正則項參數
    # scale_pos_weight =1 # 如果取值大於0的話,在類別樣本不平衡的情況下有助於快速收斂,平衡正負權重
    # objective = 'multi:softmax', # 多分類問題,指定學習任務和響應的學習目標
    # num_class = 10,  # 類別數,多分類與multisoftmax並用
    n_estimators=100,  # 樹的個數
    seed = 1000,  # 隨機種子
    # eval_metric ='auc'
)

  

基於Sckit-learn接口的分類

from sklearn.datasets import load_iris
import xgboost as xgb
from xgboost import plot_importance
from matplotlib import pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

# 加載樣本數據集
iris = load_iris()
X,y = iris.data,iris.target
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.2,random_state=12343)

# 訓練模型
model = xgb.XGBClassifier(max_depth=5,learning_rate=0.1,n_estimators=160,silent=True,objective='multi:softmax')
model.fit(X_train,y_train)

# 對測試集進行預測
y_pred = model.predict(X_test)

#計算准確率
accuracy = accuracy_score(y_test,y_pred)
print('accuracy:%2.f%%'%(accuracy*100))

# 顯示重要特征
plot_importance(model)
plt.show()

  

  輸出結果:

accuracy:93%

4,基於Scikit-learn接口的回歸

import xgboost as xgb
from xgboost import plot_importance
from matplotlib import pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_boston

# 導入數據集
boston = load_boston()
X ,y = boston.data,boston.target

# Xgboost訓練過程
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.2,random_state=0)

model = xgb.XGBRegressor(max_depth=5,learning_rate=0.1,n_estimators=160,silent=True,objective='reg:gamma')
model.fit(X_train,y_train)

# 對測試集進行預測
ans = model.predict(X_test)

# 顯示重要特征
plot_importance(model)
plt.show()

  

 5,整理代碼1(原生XGB)

from sklearn.model_selection import train_test_split
from sklearn import metrics
from  sklearn.datasets  import  make_hastie_10_2
import xgboost as xgb
#記錄程序運行時間
import time 
start_time = time.time()
X, y = make_hastie_10_2(random_state=0)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5, random_state=0)##test_size測試集合所占比例
#xgb矩陣賦值
xgb_train = xgb.DMatrix(X_train, label=y_train)
xgb_test = xgb.DMatrix(X_test,label=y_test)
##參數
params={
'booster':'gbtree',
'silent':1 ,#設置成1則沒有運行信息輸出,最好是設置為0.
#'nthread':7,# cpu 線程數 默認最大
'eta': 0.007, # 如同學習率
'min_child_weight':3, 
# 這個參數默認是 1,是每個葉子里面 h 的和至少是多少,對正負樣本不均衡時的 0-1 分類而言
#,假設 h 在 0.01 附近,min_child_weight 為 1 意味着葉子節點中最少需要包含 100 個樣本。
#這個參數非常影響結果,控制葉子節點中二階導的和的最小值,該參數值越小,越容易 overfitting。
'max_depth':6, # 構建樹的深度,越大越容易過擬合
'gamma':0.1,  # 樹的葉子節點上作進一步分區所需的最小損失減少,越大越保守,一般0.1、0.2這樣子。
'subsample':0.7, # 隨機采樣訓練樣本
'colsample_bytree':0.7, # 生成樹時進行的列采樣 
'lambda':2,  # 控制模型復雜度的權重值的L2正則化項參數,參數越大,模型越不容易過擬合。
#'alpha':0, # L1 正則項參數
#'scale_pos_weight':1, #如果取值大於0的話,在類別樣本不平衡的情況下有助於快速收斂。
#'objective': 'multi:softmax', #多分類的問題
#'num_class':10, # 類別數,多分類與 multisoftmax 並用
'seed':1000, #隨機種子
#'eval_metric': 'auc'
}
plst = list(params.items())
num_rounds = 100 # 迭代次數
watchlist = [(xgb_train, 'train'),(xgb_test, 'val')]
 
#訓練模型並保存
# early_stopping_rounds 當設置的迭代次數較大時,early_stopping_rounds 可在一定的迭代次數內准確率沒有提升就停止訓練
model = xgb.train(plst, xgb_train, num_rounds, watchlist,early_stopping_rounds=100,pred_margin=1)
#model.save_model('./model/xgb.model') # 用於存儲訓練出的模型
print "best best_ntree_limit",model.best_ntree_limit 
y_pred = model.predict(xgb_test,ntree_limit=model.best_ntree_limit)
print ('error=%f' % (  sum(1 for i in range(len(y_pred)) if int(y_pred[i]>0.5)!=y_test[i]) /float(len(y_pred))))  
#輸出運行時長
cost_time = time.time()-start_time
print "xgboost success!",'\n',"cost time:",cost_time,"(s)......"

  

6,整理代碼2(XGB使用sklearn)

from sklearn.model_selection import train_test_split
from sklearn import metrics
from  sklearn.datasets  import  make_hastie_10_2
from xgboost.sklearn import XGBClassifier
X, y = make_hastie_10_2(random_state=0)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5, random_state=0)##test_size測試集合所占比例
clf = XGBClassifier(
silent=0 ,#設置成1則沒有運行信息輸出,最好是設置為0.是否在運行升級時打印消息。
#nthread=4,# cpu 線程數 默認最大
learning_rate= 0.3, # 如同學習率
min_child_weight=1, 
# 這個參數默認是 1,是每個葉子里面 h 的和至少是多少,對正負樣本不均衡時的 0-1 分類而言
#,假設 h 在 0.01 附近,min_child_weight 為 1 意味着葉子節點中最少需要包含 100 個樣本。
#這個參數非常影響結果,控制葉子節點中二階導的和的最小值,該參數值越小,越容易 overfitting。
max_depth=6, # 構建樹的深度,越大越容易過擬合
gamma=0,  # 樹的葉子節點上作進一步分區所需的最小損失減少,越大越保守,一般0.1、0.2這樣子。
subsample=1, # 隨機采樣訓練樣本 訓練實例的子采樣比
max_delta_step=0,#最大增量步長,我們允許每個樹的權重估計。
colsample_bytree=1, # 生成樹時進行的列采樣 
reg_lambda=1,  # 控制模型復雜度的權重值的L2正則化項參數,參數越大,模型越不容易過擬合。
#reg_alpha=0, # L1 正則項參數
#scale_pos_weight=1, #如果取值大於0的話,在類別樣本不平衡的情況下有助於快速收斂。平衡正負權重
#objective= 'multi:softmax', #多分類的問題 指定學習任務和相應的學習目標
#num_class=10, # 類別數,多分類與 multisoftmax 並用
n_estimators=100, #樹的個數
seed=1000 #隨機種子
#eval_metric= 'auc'
)
clf.fit(X_train,y_train,eval_metric='auc')
#設置驗證集合 verbose=False不打印過程
clf.fit(X_train, y_train,eval_set=[(X_train, y_train), (X_val, y_val)],eval_metric='auc',verbose=False)
#獲取驗證集合結果
evals_result = clf.evals_result()
y_true, y_pred = y_test, clf.predict(X_test)
print"Accuracy : %.4g" % metrics.accuracy_score(y_true, y_pred)
#回歸
#m_regress = xgb.XGBRegressor(n_estimators=1000,seed=0)

  

Xgboost參數調優的一般方法

調參步驟:

  1,選擇較高的學習速率(learning rate)。一般情況下,學習速率的值為0.1.但是,對於不同的問題,理想的學習速率有時候會在0.05~0.3之間波動。選擇對應於此學習速率的理想決策樹數量。Xgboost有一個很有用的函數“cv”,這個函數可以在每一次迭代中使用交叉驗證,並返回理想的決策樹數量。

  2,對於給定的學習速率和決策樹數量,進行決策樹特定參數調優(max_depth , min_child_weight , gamma , subsample,colsample_bytree)在確定一棵樹的過程中,我們可以選擇不同的參數。

  3,Xgboost的正則化參數的調優。(lambda , alpha)。這些參數可以降低模型的復雜度,從而提高模型的表現。

  4,降低學習速率,確定理想參數。

  下面詳細的進行這些操作。

第一步:確定學習速率和tree_based參數調優的估計器數目

  為了確定Boosting參數,我們要先給其他參數一個初始值。咱們先按照如下方法取值:

  • 1,max_depth = 5:這個參數的取值最好在3-10之間,我選的起始值為5,但是你可以選擇其他的值。起始值在4-6之間都是不錯的選擇。
  • 2,min_child_weight = 1 :這里選擇了一個比較小的值,因為這是一個極不平衡的分類問題。因此,某些葉子節點下的值會比較小。
  • 3,gamma = 0 :起始值也可以選擇其它比較小的值,在0.1到0.2之間就可以,這個參數后繼也是要調整的。
  • 4,subsample,colsample_bytree = 0.8  這個是最常見的初始值了。典型值的范圍在0.5-0.9之間。
  • 5,scale_pos_weight =1 這個值時因為類別十分不平衡。

  注意,上面這些參數的值知識一個初始的估計值,后繼需要調優。這里把學習速率就設成默認的0.1。然后用Xgboost中的cv函數來確定最佳的決策樹數量。

from xgboost import XGBClassifier
xgb1 = XGBClassifier(
 learning_rate =0.1,
 n_estimators=1000,
 max_depth=5,
 min_child_weight=1,
 gamma=0,
 subsample=0.8,
 colsample_bytree=0.8,
 objective= 'binary:logistic',
 nthread=4,
 scale_pos_weight=1,
 seed=27)

  

第二步:max_depth和min_weight參數調優

  我們先對這兩個參數調優,是因為他們對最終結果有很大的影響。首先,我們先大范圍地粗略參數,然后再小范圍的微調。

  注意:在這一節我會進行高負荷的柵格搜索(grid search),這個過程大約需要15-30分鍾甚至更久,具體取決於你系統的性能,你也可以根據自己系統的性能選擇不同的值。

  網格搜索scoring = 'roc_auc' 只支持二分類,多分類需要修改scoring(默認支持多分類)

param_test1 = {
 'max_depth':range(3,10,2),
 'min_child_weight':range(1,6,2)
}
#param_test2 = {
 'max_depth':[4,5,6],
 'min_child_weight':[4,5,6]
}
from sklearn import svm, grid_search, datasets
from sklearn import grid_search
gsearch1 = grid_search.GridSearchCV(
estimator = XGBClassifier(
learning_rate =0.1,
n_estimators=140, max_depth=5,
min_child_weight=1,
gamma=0,
subsample=0.8,
colsample_bytree=0.8,
objective= 'binary:logistic',
nthread=4,
scale_pos_weight=1,
seed=27),
param_grid = param_test1,
scoring='roc_auc',
n_jobs=4,
iid=False,
cv=5)
gsearch1.fit(train[predictors],train[target])
gsearch1.grid_scores_, gsearch1.best_params_,gsearch1.best_score_
#網格搜索scoring='roc_auc'只支持二分類,多分類需要修改scoring(默認支持多分類)

  

第三步:gamma參數調優

  在已經調整好其他參數的基礎上,我們可以進行gamma參數的調優了。Gamma參數取值范圍很大,這里我們設置為5,其實你也可以取更精確的gamma值。

param_test3 = {
 'gamma':[i/10.0 for i in range(0,5)]
}

gsearch3 = GridSearchCV(estimator = XGBClassifier( learning_rate =0.1,
 n_estimators=140, max_depth=4,min_child_weight=6, gamma=0, 
subsample=0.8, colsample_bytree=0.8,objective= 'binary:logistic', 
nthread=4, scale_pos_weight=1,seed=27),  param_grid = param_test3, scoring='roc_auc',n_jobs=4,iid=False, cv=5)

gsearch3.fit(train[predictors],train[target])

gsearch3.grid_scores_, gsearch3.best_params_, gsearch3.best_score_

  

param_test3 = {
 'gamma':[i/10.0 for i in range(0,5)]
}
gsearch3 = GridSearchCV(
estimator = XGBClassifier( 
learning_rate =0.1, 
n_estimators=140, 
max_depth=4, 
min_child_weight=6, 
gamma=0, 
subsample=0.8, 
colsample_bytree=0.8, 
objective= 'binary:logistic', 
nthread=4, 
scale_pos_weight=1,
seed=27), 
param_grid = param_test3, 
scoring='roc_auc',
n_jobs=4,
iid=False, 
cv=5)
gsearch3.fit(train[predictors],train[target])
gsearch3.grid_scores_, gsearch3.best_params_, gsearch3.best_score_

  

第四步:調整subsample 和 colsample_bytree參數

  嘗試不同的subsample 和 colsample_bytree 參數。我們分兩個階段來進行這個步驟。這兩個步驟都取0.6,0.7,0.8,0.9作為起始值。

#取0.6,0.7,0.8,0.9作為起始值
param_test4 = {
 'subsample':[i/10.0 for i in range(6,10)],
 'colsample_bytree':[i/10.0 for i in range(6,10)]
}
 
gsearch4 = GridSearchCV(
estimator = XGBClassifier(
learning_rate =0.1,
n_estimators=177,
max_depth=3,
min_child_weight=4,
gamma=0.1,
subsample=0.8,
colsample_bytree=0.8,
objective= 'binary:logistic',
nthread=4,
scale_pos_weight=1,
seed=27),
param_grid = param_test4,
scoring='roc_auc',
n_jobs=4,
iid=False,
cv=5)
gsearch4.fit(train[predictors],train[target])
gsearch4.grid_scores_, gsearch4.best_params_, gsearch4.best_score_

  

第五步:正則化參數調優

  由於gamma函數提供了一種更加有效的降低過擬合的方法,大部分人很少會用到這個參數,但是我們可以嘗試用一下這個參數。

param_test6 = {
 'reg_alpha':[1e-5, 1e-2, 0.1, 1, 100]
}
gsearch6 = GridSearchCV(
estimator = XGBClassifier(
learning_rate =0.1,
n_estimators=177,
max_depth=4,
min_child_weight=6,
gamma=0.1,
subsample=0.8,
colsample_bytree=0.8,
objective= 'binary:logistic',
nthread=4,
scale_pos_weight=1,
seed=27),
param_grid = param_test6,
scoring='roc_auc',
n_jobs=4,
iid=False,
cv=5)
gsearch6.fit(train[predictors],train[target])
gsearch6.grid_scores_, gsearch6.best_params_, gsearch6.best_score_

  

第六步:降低學習速率

  最后,我們使用較低的學習速率,以及使用更多的決策樹,我們可以用Xgboost中CV函數來進行這一步工作。

xgb4 = XGBClassifier(
 learning_rate =0.01,
 n_estimators=5000,
 max_depth=4,
 min_child_weight=6,
 gamma=0,
 subsample=0.8,
 colsample_bytree=0.8,
 reg_alpha=0.005,
 objective= 'binary:logistic',
 nthread=4,
 scale_pos_weight=1,
 seed=27)
modelfit(xgb4, train, predictors)

  

   總結一下,要想模型的表現有大幅的提升,調整每個參數帶來的影響也必須清楚,僅僅靠着參數的調整和模型的小幅優化,想要讓模型的表現有個大幅度提升是不可能的。要想模型的表現有質的飛躍,需要依靠其他的手段。諸如,特征工程(feature egineering) ,模型組合(ensemble of model),以及堆疊(stacking)等。

 第七步:Python示例

import xgboost as xgb
import pandas as pd
#獲取數據
from sklearn import cross_validation
from sklearn.datasets import load_iris
iris = load_iris()
#切分數據集
X_train, X_test, y_train, y_test = cross_validation.train_test_split(iris.data, iris.target, test_size=0.33, random_state=42)
#設置參數
m_class = xgb.XGBClassifier(
 learning_rate =0.1,
 n_estimators=1000,
 max_depth=5,
 gamma=0,
 subsample=0.8,
 colsample_bytree=0.8,
 objective= 'binary:logistic',
 nthread=4,
 seed=27)
#訓練
m_class.fit(X_train, y_train)
test_21 = m_class.predict(X_test)
print "Accuracy : %.2f" % metrics.accuracy_score(y_test, test_21)
#預測概率
#test_2 = m_class.predict_proba(X_test)
#查看AUC評價標准
from sklearn import metrics
print "Accuracy : %.2f" % metrics.accuracy_score(y_test, test_21)
##必須二分類才能計算
##print "AUC Score (Train): %f" % metrics.roc_auc_score(y_test, test_2)
#查看重要程度
feat_imp = pd.Series(m_class.booster().get_fscore()).sort_values(ascending=False)
feat_imp.plot(kind='bar', title='Feature Importances')
import matplotlib.pyplot as plt
plt.show()
#回歸
#m_regress = xgb.XGBRegressor(n_estimators=1000,seed=0)
#m_regress.fit(X_train, y_train)
#test_1 = m_regress.predict(X_test)

  

XGBoost輸出特征重要性以及篩選特征

1,梯度提升算法是如何計算特征重要性的?

  使用梯度提升算法的好處是在提升樹被創建后,可以相對直接地得到每個屬性的重要性得分。一般來說,重要性分數,衡量了特征在模型中的提升決策樹構建中的價值。一個屬性越多的被用來在模型中構建決策樹,它的重要性就相對越高。

  屬性重要性是通過對數據集中的每個屬性進行計算,並進行排序得到。在單個決策樹中通過每個屬性分裂點改進性能度量的量來計算屬性重要性。由節點負責加權和記錄次數,也就是說一個屬性對分裂點改進性能度量越大(越靠近根節點),權值越大;被越多提升樹所選擇,屬性越重要。性能度量可以是選擇分裂節點的Gini純度,也可以是其他度量函數。

  最終將一個屬性在所有提升樹中的結果進行加權求和后然后平均,得到重要性得分。

2,繪制特征重要性

  一個已訓練的Xgboost模型能夠自動計算特征重要性,這些重要性得分可以通過成員變量feature_importances_得到。可以通過如下命令打印:

print(model.feature_importances_)

  我們可以直接在條形圖上繪制這些分數,以便獲得數據集中每個特征的相對重要性的直觀顯示,例如:

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

  我們可以通過在the Pima Indians onset of diabetes 數據集上訓練XGBoost模型來演示,並從計算的特征重要性中繪制條形圖。

# plot feature importance manually
from numpy import loadtxt
from xgboost import XGBClassifier
from matplotlib import pyplot
from sklearn.datasets import load_iris
# load data
dataset = load_iris()
# split data into X and y
X = dataset.data
y = dataset.target
# 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.17941953 0.11345647 0.41556728 0.29155672]

  相對重要性條形圖:

  這種繪制的缺點在於,只顯示了特征重要性而沒有排序,可以在繪制之前對特征重要性得分進行排序。

  通過內建的繪制函數進行特征重要性得分排序后的繪制,這個函數就是plot_importance(),示例如下:

# plot feature importance manually
from numpy import loadtxt
from xgboost import XGBClassifier
from matplotlib import pyplot
from sklearn.datasets import load_iris
from xgboost import plot_importance

# load data
dataset = load_iris()
# split data into X and y
X = dataset.data
y = dataset.target
# fit model no training data
model = XGBClassifier()
model.fit(X, y)
# feature importance
print(model.feature_importances_)
# plot feature importance

plot_importance(model)
pyplot.show()

  示例得到條形圖:

  根據其在輸入數組的索引,特征被自動命名為f0~f3,在問題描述中手動的將這些索引映射到名稱,我們可以看到,f2具有最高的重要性,f1具有最低的重要性。

3,根據Xgboost特征重要性得分進行特征選擇

  特征重要性得分,可以用於在scikit-learn中進行特征選擇。通過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)

  我們可以通過測試多個閾值,來從特征重要性中選擇特征。具體而言,每個輸入變量的特征重要性,本質上允許我們通過重要性來測試每個特征子集。

完整代碼如下:

# plot feature importance manually
import numpy as np
from xgboost import XGBClassifier
from matplotlib import pyplot
from sklearn.datasets import load_iris
from xgboost import plot_importance
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.feature_selection import SelectFromModel

# load data
dataset = load_iris()
# split data into X and y
X = dataset.data
y = dataset.target

# 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 no training data
model = XGBClassifier()
model.fit(X_train, y_train)
# feature importance
print(model.feature_importances_)

# 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 = np.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))

  運行示例,得到輸出:

[0.20993228 0.09029345 0.54176074 0.15801354]
Accuracy:92.00%
Thresh=0.090, n=4, Accuracy: 92.00%
Thresh=0.158, n=3, Accuracy: 92.00%
Thresh=0.210, n=2, Accuracy: 86.00%
Thresh=0.542, n=1, Accuracy: 90.00%

  我們可以看到,模型的性能通常隨着所選擇的特征的數量減少,在這一問題上,可以對測試集准確率和模型復雜度做一個權衡,例如選擇三個特征,接受准確率為92%,這可能是對這樣一個小數據集的清洗,但是對於更大的數據集和使用交叉驗證作為模型評估方案可能是更有用的策略。

4,網格搜索

代碼1:

from sklearn.model_selection import GridSearchCV
tuned_parameters= [{'n_estimators':[100,200,500],
                  'max_depth':[3,5,7], ##range(3,10,2)
                  'learning_rate':[0.5, 1.0],
                  'subsample':[0.75,0.8,0.85,0.9]
                  }]
tuned_parameters= [{'n_estimators':[100,200,500,1000]
                  }]
clf = GridSearchCV(XGBClassifier(silent=0,nthread=4,learning_rate= 0.5,min_child_weight=1, max_depth=3,gamma=0,subsample=1,colsample_bytree=1,reg_lambda=1,seed=1000), param_grid=tuned_parameters,scoring='roc_auc',n_jobs=4,iid=False,cv=5)  
clf.fit(X_train, y_train)
##clf.grid_scores_, clf.best_params_, clf.best_score_
print(clf.best_params_)
y_true, y_pred = y_test, clf.predict(X_test)
print"Accuracy : %.4g" % metrics.accuracy_score(y_true, y_pred) 
y_proba=clf.predict_proba(X_test)[:,1]
print "AUC Score (Train): %f" % metrics.roc_auc_score(y_true, y_proba)               

  

代碼2:

from sklearn.model_selection import GridSearchCV
parameters= [{'learning_rate':[0.01,0.1,0.3],'n_estimators':[1000,1200,1500,2000,2500]}]
clf = GridSearchCV(XGBClassifier(
             max_depth=3,
             min_child_weight=1,
             gamma=0.5,
             subsample=0.6,
             colsample_bytree=0.6,
             objective= 'binary:logistic', #邏輯回歸損失函數
             scale_pos_weight=1,
             reg_alpha=0,
             reg_lambda=1,
             seed=27
            ), 
            param_grid=parameters,scoring='roc_auc')  
clf.fit(X_train, y_train)
print(clf.best_params_)  
y_pre= clf.predict(X_test)
y_pro= clf.predict_proba(X_test)[:,1] 
print "AUC Score : %f" % metrics.roc_auc_score(y_test, y_pro) 
print"Accuracy : %.4g" % metrics.accuracy_score(y_test, y_pre) 

  

輸出特征重要性:

import pandas as pd
import matplotlib.pylab as plt
feat_imp = pd.Series(clf.booster().get_fscore()).sort_values(ascending=False)
feat_imp.plot(kind='bar', title='Feature Importances')
plt.ylabel('Feature Importance Score')
plt.show()

  

補充:關於隨機種子——random_state

  random_state是一個隨機種子,是在任意帶有隨機性的類或者函數里作為參數來控制隨機模式。random_state取某一個值的時候,也就確定了一種規則。

  random_state可以用於很多函數,比如訓練集測試集的划分;構建決策樹;構建隨機森林

1,划分訓練集和測試集的類train_test_split

  隨機數種子控制每次划分訓練集和測試集的模式,其取值不變時划分得到的結果一模一樣,其值改變時,划分得到的結果不同。若不設置此參數,則函數會自動選擇一種隨機模式,得到的結果也就不同。

2,構建決策樹的函數

clf = tree.DecisionTreeClassifier(criterion="entropy",random_state=30,splitter="random")

  其取值不變時,用相同的訓練集建樹得到的結果一模一樣,對測試集的預測結果也是一樣的

  其取值改變時,得到的結果不同;

  若不設置此參數(即設置為None),則函數會自動選擇一種隨機模式,每次得到的結果也就不同,可能稍微有所波動。

3,構建隨機森林

clf = RandomForestClassifier(random_state=0)

  其取值不變時,用相同的訓練集建樹得到的結果一模一樣,對測試集的預測結果也是一樣的

  其取值改變時,得到的結果不同;

  若不設置此參數(即設置為None),則函數會自動選擇一種隨機模式,每次得到的結果也就不同,可能稍微有所波動。

4,總結

  在需要設置random_state的地方給其賦值,當多次運行此段代碼得到完全一樣的結果,別人運行代碼也可以復現你的過程。若不設置此參數則會隨機選擇一個種子,執行結果也會因此不同。雖然可以對random_state進行調參,但是調參后再訓練集上表現好的模型未必在陌生訓練集上表現好,所以一般會隨便選擇一個random_state的值作為參數。

  對於那些本質上是隨機的過程,我們有必要控制隨機的狀態,這樣才能重復的展現相同的結果。如果對隨機狀態不加控制,那么實驗的結果就無法固定,而是隨機的顯示。

  其實random_state 與 random  seed作用是相同的,下面我們通過 random seed來學習一下 random_state:

 

  第一段代碼和第二段代碼完全相同,在1~100中取10個隨機數,都沒有設置 random seed,它每次取的結果就不太,它的隨機數種子與當前系統的時間有關。

  第三段代碼和第四段代碼設置了相同的 random seed(123),他們取的隨機數就完全相同,你多運行幾次也是這樣。

  第五段代碼設置了 random seed(456),但是與之前設置的不同,於是運行取隨機數的結果也不同。

 

完整代碼及其數據,請移步小編的GitHub

  傳送門:請點擊我

  如果點擊有誤:https://github.com/LeBron-Jian/MachineLearningNote

 

 

參考文獻:

https://blog.csdn.net/waitingzby/article/details/81610495

https://blog.csdn.net/u011089523/article/details/72812019

 https://blog.csdn.net/luanpeng825485697/article/details/79907149

https://xgboost.readthedocs.io/en/latest/parameter.html#general-parameters


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM