sklearn中的xgboost_xgboost来了
一.xgboost前奏
1,介紹一下啥是xgboost
XGBoost全稱是eXtreme Gradient Boosting,即極限梯度提升算法。它由陳天奇所設計,致力于讓提升樹突破自身的計算極限,以實現運算快速,性能優秀的工程目標。2,XGBoost的三大構件
XGBoost本身的核心是基于梯度提升樹實現的集成算法,整體來說可以有三個核心部分:集成算法本身,用于集成的弱評估器,以及應用中的其他過程。三個部分中,前兩個部分包含了XGBoost的核心原理以及數學過程,最后的部分主要是在XGBoost應用中占有一席之地。二.梯度提升樹:xgboost的基礎
1,核心參數:n_estimators
集成算法通過在數據上構建多個弱評估器,匯總所有弱評估器的建模結果以獲取比單個模型更好的回歸或分類表現。n_estimators就是弱分類器的個數:n_estimators越大,模型的學習能力就會越強,模型也越容易過擬合。1),首先XGB中的樹的數量決定了模型的學習能力,樹的數量越多,模型的學習能力越強。只要XGB中樹的數量足夠了,即便只有很少的數據,模型也能夠學到訓練數據100%的信息,所以XGB也是天生過擬合的模型。但在這種情況 下,模型會變得非常不穩定。
2),XGB中樹的數量很少的時候,對模型的影響較大,當樹的數量已經很多的時候,對模型的影響比較小,只能有 微弱的變化。當數據本身就處于過擬合的時候,再使用過多的樹能達到的效果甚微,反而浪費計算資源。當唯一指標
或者準確率給出的n_estimators看起來不太可靠的時候,我們可以改造學習曲線來幫助我們。
3),第三,樹的數量提升對模型的影響有極限,最開始,模型的表現會隨著XGB的樹的數量一起提升,但到達某個點之后,樹的數量越多,模型的效果會逐步下降,這也說明了暴力增加n_estimators不一定有效果。
這些都和隨機森林中的參數n_estimators表現出一致的狀態。在隨機森林中我們總是先調整n_estimators,當n_estimators的極限已達到,我們才考慮其他參數,但XGB中的狀況明顯更加復雜,當數據集不太尋常的時候會更加 復雜。這是我們要給出的第一個超參數,因此還是建議優先調整n_estimators,一般都不會建議一個太大的數目, 300以下為佳。2,有放回隨機抽樣:重要參數subsample
隨機抽樣的時候抽取的樣本比例,范圍(0,1],在sklearn中,我們使用參數subsample來控制我們的隨機抽樣。在xgb和sklearn中,這個參數都默認為1且不能取到0,這說明我們無法控制模型是否進行隨機有放回抽樣,只能控制抽樣抽出來的樣本量大概是多少。采樣還對模型造成了什么樣的影響呢?采樣會減少樣本數量,而從學習曲線來看樣本數量越少模型的過擬合會越嚴重,因為對模型來說數據量越少模型學習越容易,學到的規則也會越具體越不適用于測試樣本。所以subsample參數通常是在樣本量本身很大的時候來調整和使用。一般保持默認就好。3,迭代決策樹:重要參數eta
在sklearn中,我們使用參數learning_rate來干涉我們的學習速率:
集成中的學習率,又稱為步長,以控制迭代速率,常用于防止過擬合。
xgb.train():eta,默認0.3 取值范圍[0,1]
xgb.XGBRegressor():learning_rate,默認0.1 取值范圍[0,1]
現在來看,我們的梯度提升樹可是說是由三個重要的部分組成:
?一個能夠衡量集成算法效果的,能夠被最優化的損失函數
?一個能夠實現預測的弱評估器
?一種能夠讓弱評估器集成的手段,包括我們講解的迭代方法,抽樣手段,樣本加權等等過程
三.XGBoost
1,選擇弱評估器:重要參數booster
參數“booster"來控制我們究竟使用怎樣的弱評估器。可供選擇的有這些:"gbtree", "gblinear", "dart"2.XGB的目標函數:重要參數objective
XGB的損失函數實現了模型表現和運算速度的平衡。普通的損失函數,比如錯誤率,均方誤差等,都只能夠衡量模型的表現無法衡量模型的運算速度。我們曾在許多模型中使用空間復雜度和時間復雜度來衡量模型的運算效率。XGB因此引入了模型復雜度來衡量算法的運算效率。因此XGB的目標函數被寫作:傳統損失函數 + 模型復雜度。常見的選擇有
輸入 | 選用的損失函數 |
reg:linear | 使用線性回歸的損失函數,均方誤差,回歸時使用 |
binary:logistic | 使用邏輯回歸的損失函數,對數損失log_loss,二分類時使用 |
binary:hinge | 使用支持向量機的損失函數,Hinge Loss,二分類時使用 |
multi:softmax | 使用softmax損失函數,多分類時使用 |
xgb自身的調用方式
# encoding=utf-8from sklearn.metrics import r2_score# 默認reg:linearreg = XGBR(n_estimators=180, random_state=420).fit(Xtrain, Ytrain)reg.score(Xtest, Ytest)MSE(Ytest, reg.predict(Xtest))# xgb實現法import xgboost as xgb# 1,使用類Dmatrix讀取數據dtrain = xgb.DMatrix(Xtrain, Ytrain)dtest = xgb.DMatrix(Xtest, Ytest)# 2,寫明參數,silent默認為False,通常需要手動將它關閉param = {'silent': False, 'objective': 'reg:linear', "eta": 0.1}num_round = 180# 3,類train,可以直接導入的參數是訓練數據,樹的數量,其他參數都需要通過params來導入bst = xgb.train(param, dtrain, num_round)# 4,接口predictr2_score(Ytest, bst.predict(dtest))MSE(Ytest, bst.predict(dtest))3,尋找最佳分枝:結構分數之差
貪婪算法指的是控制局部最優來達到全局最優的算法,決策樹算法本身就是一種使用貪婪算法的方法。XGB作為樹的集成模型,自然也想到采用這樣的方法來進行計算,所以我們認為,如果每片葉子都是最優,則整體生成的樹結構就是最優,如此就可以避免去枚舉所有可能的樹結構。決策樹中我們使用基尼系數或信息熵來衡量分枝之后葉子節點的不純度,分枝前的信息熵與分枝后的信息熵之差叫做信息增益,信息增益最大的特征上的分枝就被我們選中。當信息增益低于某個閾值時就讓樹停止生長。在XGB中我們使用的方式是類似的:我們首先使用目標函數來衡量樹的結構的優劣,然后讓樹從深度0開始生長,每進行一次分枝,我們就計算目標函數減少了多少,當目標函數的降低低于我們設定的某個閾 值時,就讓樹停止生長。4,讓樹停止生長:重要參數gamma
從目標函數和結構分數之差的式子中來看,它是我們每增加一片葉子就會被剪去的懲罰項。增加的葉子越多,結構分數之差會被懲罰越重,所以它又被稱之為是“復雜性控制”.所以 是我們用來防止過擬合的重要參數。實踐證明,它是對梯度提升樹影響最大的參數之一,其效果絲毫不遜色于n_estimators和防止過擬合的神器max_depth。同時,它還是我們讓樹停止生長的重要參數。在XGB中,我們規定只要結構分數之差Gain是大于0的,即只要目標函數還能夠繼續減小,我們就允許樹繼續進行分枝。我們可以直接通過設定γ的大小來讓XGB中的樹停止生長。γ因此被定義為:在樹的葉節點上進行進一步分枝所需的最小目標函數減少量,在決策樹和隨機森林中也有類似的參數(min_split_loss,min_samples_split)。設定 越大,算法就越保守,樹的葉子數量就越少,模型的復雜度就越低。四. XGBoost應用中的其他問題
1,過擬合:剪枝參數與回歸模型調參
作為天生過擬合的模型,XGBoost應用的核心之一就是減輕過擬合帶來的影響。作為樹模型,減輕過擬合的方式主要是靠對決策樹剪枝來降低模型的復雜度,以求降低方差。在之前的講解中,我們已經學習了好幾個可以用來防止過擬合的參數,包括復雜度控制γ ,正則化的兩個參數λ和α,控制迭代速度的參數η 以及管理每次迭代前進行的隨機有放回抽樣的參數subsample。所有的這些參數都可以用來減輕過擬合。但除此之外,我們還有幾個影響重大的,專用于剪枝的參數:參數含義 | xgb.train() | xgb.XGBRegressor() |
樹的最大深度 | max_depth,默認為6 | max_depth,默認為6 |
每次生成樹時隨機抽樣特征的比例 | colsample_bytree,默認1 | colsample_bytree,默認1 |
每次生成樹的一層時隨機抽樣特征的比例 | colsample_bylevel,默認1 | colsample_bylevel,默認1 |
每次生成一個葉子節點時隨機抽樣特征的比例 | colsample_bynode,默認1 | N.A. |
i,樹的最大深度是決策樹中的剪枝法寶,算是最常用的剪枝參數,不過在XGBoost中,最大深度的功能與參數λ相似,因此如果先調節了λ ,則最大深度可能無法展示出巨大的效果。當然,如果先調整了最大深度,則λ也有 可能無法顯示明顯的效果。通常來說,這兩個參數中我們只使用一個。
ii,在建立樹時對特征進行抽樣其實是決策樹和隨機森林中比較常見的一種方法,但是在XGBoost之前,這種方法并沒有被使用到boosting算法當中過。Boosting算法一直以抽取樣本(橫向抽樣)來調整模型過擬合的程度,而實踐證明其實縱向抽樣(抽取特征)更能夠防止過擬合。
iii,通常當我們獲得了一個數據集后,我們先使用網格搜索找出比較合適的n_estimators和eta組合,然后使用gamma或 者max_depth觀察模型處于什么樣的狀態(過擬合還是欠擬合,處于方差-偏差圖像的左邊還是右邊?),最后再決定是否要進行剪枝。通常來說,對于XGB模型,大多數時候都是需要剪枝的。
讓我們先從最原始的,設定默認參數開始,先觀察一下默認參數下,我們的交叉驗證曲線長什么樣:# encoding=utf-8import datetimeimport timeimport matplotlib.pyplot as pltimport pandas as pdimport xgboost as xgbfrom sklearn.datasets import fetch_california_housing as fchhousevalue = fch()X = pd.DataFrame(housevalue.data)y = housevalue.targetdfull = xgb.DMatrix(X, y)param1 = {'silent': True # 并非默認 , 'obj': 'reg:linear' # 并非默認 , "subsample": 1, "max_depth": 6, "eta": 0.3 , "gamma": 0 , "lambda": 1 , "alpha": 0, "colsample_bytree": 1, "colsample_bylevel": 1, "colsample_bynode": 1, "nfold": 5}num_round = 200time0 = time()cvresult1 = xgb.cv(param1, dfull, num_round)print(datetime.datetime.fromtimestamp(time() - time0).strftime("%M:%S:%f"))fig, ax = plt.subplots(1, figsize=(15, 10))# ax.set_ylim(top=5)ax.grid()ax.plot(range(1, 201), cvresult1.iloc[:, 0], c="red", label="train,original")ax.plot(range(1, 201), cvresult1.iloc[:, 2], c="orange", label="test,original")ax.legend(fontsize="xx-large")plt.show()2,在調參過程中可能會遇到這些問題:
i.一個個參數調整太麻煩,可不可以使用網格搜索呢?
當然可以!只要電腦有足夠的計算資源,并且你信任網格搜索,那任何時候我們都可以使用網格搜索。只是使用的時候要注意,首先XGB的參數非常多,參數可取的范圍也很廣,究竟是使用np.linspace或者np.arange作為參數的備選值也會影響結果,而且網格搜索的運行速度往往不容樂觀,因此建議至少先使用xgboost.cv來確認參數的范圍,否則很可能花很長的時間做了無用功。并且,在使用網格搜索的時候,最好不要一次性將所有的參數都放入進行搜索,最多一次兩三個。有一些互相影響的參數需要放在一起使用,比如學習率eta和樹的數量n_estimators。另外,如果網格搜索的結果與你的理解相違背,與你手動調參的結果相違背,選擇模型效果較好的一個。如果兩者效果差不多,那選擇相信手動調參的結果。網格畢竟是枚舉出結果,很多時候得出的結果可能會是具體到數據的巧合,我們無法去一一解釋網格搜索得出的結論為何是這樣。如果你感覺都無法解釋,那就不要去在意,直接選擇結果較好的一個。ii. 調參的時候參數的順序會影響調參結果嗎?
會影響,因此在現實中,我們會優先調整那些對模型影響巨大的參數。在這里,我建議的剪枝上的調參順序是: n_estimators與eta共同調節,gamma或者max_depth,采樣和抽樣參數(縱向抽樣影響更大),最后才是正則化 的兩個參數。當然,可以根據自己的需求來進行調整。iii. 調參之后測試集上的效果還沒有原始設定上的效果好怎么辦?
如果調參之后,交叉驗證曲線確實顯示測試集和訓練集上的模型評估效果是更加接近的,推薦使用調參之后的效果。我們希望增強模型的泛化能力,然而泛化能力的增強并不代表著在新數據集上模型的結果一定優秀,因為未知數據集 并非一定符合全數據的分布,在一組未知數據上表現十分優秀,也不一定就能夠在其他的未知數據集上表現優秀。因 此不必過于糾結在現有的測試集上是否表現優秀。當然了,在現有數據上如果能夠實現訓練集和測試集都非常優秀, 那模型的泛化能力自然也會是很強的。五,XGBoost模型的保存和調用
1,使用 pickle保存和調用模型
pickle是python編程中比較標準的一個保存和調用模型的庫,我們可以使用pickle和open函數的連用,來將我們的模型保存到本地。以剛才我們已經調整好的參數和訓練好的模型為例,我們可以這樣來使用pickle:# encoding=utf-8import pickleimport pandas as pdimport xgboost as xgbfrom sklearn.datasets import fetch_california_housing as fchfrom sklearn.datasets import load_bostonfrom sklearn.metrics import mean_squared_error as MSE, r2_scorefrom sklearn.model_selection import train_test_split as TTShousevalue = fch()X = pd.DataFrame(housevalue.data)y = housevalue.targetX.columns = ["住戶收入中位數", "房屋使用年代中位數", "平均房間數目" , "平均臥室數目", "街區人口", "平均入住率", "街區的緯度", "街區的經度"]X.head()Xtrain, Xtest, Ytrain, Ytest = TTS(X, y, test_size=0.3, random_state=420)dtrain = xgb.DMatrix(Xtrain, Ytrain)# 設定參數,對模型進行訓練param = {'silent': True , 'obj': 'reg:linear', "subsample": 1, "eta": 0.05 , "gamma": 20, "lambda": 3.5, "alpha": 0.2, "max_depth": 4, "colsample_bytree": 0.4, "colsample_bylevel": 0.6, "colsample_bynode": 1}num_round = 180bst = xgb.train(param, dtrain, num_round)# 保存模型# 注意,open中我們往往使用w或者r作為讀取的模式,但其實w與r只能用于文本文件,當我們希望導入的不是文本文件,而 是模型本身的時候,我們使用"wb"和"rb"作為讀取的模式。其中wb表示以二進制寫入,rb表示以二進制讀入pickle.dump(bst, open("xgboostonboston.dat", "wb"))data = load_boston()X = data.datay = data.targetXtrain, Xtest, Ytrain, Ytest = TTS(X, y, test_size=0.3, random_state=420)dtest = xgb.DMatrix(Xtest, Ytest)# 導入模型loaded_model = pickle.load(open("xgboostonboston.dat", "rb"))ypreds = loaded_model.predict(dtest)MSE(Ytest, ypreds)r2_score(Ytest, ypreds)2,使用Joblib保存和調用模型
Joblib是SciPy生態系統中的一部分,它為Python提供保存和調用管道和對象的功能,處理NumPy結構的數據尤其高效,對于很大的數據集和巨大的模型非常有用。Joblib與pickle API非常相似bst = xgb.train(param, dtrain, num_round)import joblibjoblib.dump(bst,"xgboost-boston.dat")loaded_model = joblib.load("xgboost-boston.dat")ypreds = loaded_model.predict(dtest)MSE(Ytest, ypreds)r2_score(Ytest,ypreds)
總結
以上是生活随笔為你收集整理的sklearn中的xgboost_xgboost来了的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: bmp文件头_「正点原子FPGA连载」第
- 下一篇: python标准函数有哪些_python