機器學習基礎之模型集成

集成(ensemble)是合併多個機器學習模型來構建更強大的模型的方法。主要須要解決兩個問題:node

  • 如何得到個體學習器
  • 使用什麼樣的結合規則

下載.png

個體學習器

  個體學習器能夠分爲同質和異質兩種:python

  • 同質指的是不一樣個體學習器屬於同一種類,好比都是決策樹。
  • 異質指的是個體學習器屬於不一樣種類,好比既有決策樹又有SVM。

  目前來講,同質個體學習器的應用是最普遍的,通常咱們常說的集成學習的方法都是指的同質個體學習器,而同質個體學習器使用最多的模型是CART決策樹和神經網絡。算法

  同質學習器按照個體學習器之間是否存在依賴關係可分爲兩類:緩存

  • 存在強依賴關係:學習器串行生成,即新學習器是在上一個學習器基礎上生成的,表明就是boosting系列
  • 不存在強依賴關係:學習器並行生成,各個學習器之間沒有太大的依賴關係,表明就是bagging系列

集成策略

  • 平均值:針對迴歸問題,對多個個體學習器的結果計算平均值做爲最終結果,可使用算數平均值、加權平均值等。
  • 投票法:針對分類問題,對多個個體分類器的結果使用投票做爲最終結果,可使用少數服從多數、絕對多數、加權投票等。
  • 學習法:對個體學習器結果再使用一個學習器來處理,即stacking

Bagging

Bagging原理

  以下圖所示,bagging的個體學習器使用的訓練集由隨機採樣得到,分別訓練後集成。網絡

  隨機採樣最經常使用的方法是自助採樣,其方法是在m個樣本中有放回的隨機採樣m次以得到m個樣本的訓練集。其中,某個樣本沒有被使用的機率是$$P=(1-\frac1m)^m$$令m趨向於正無窮可得$$\lim _{m\rightarrow+\infty}P=\frac 1e$$即大約36.8%的數據不會被取到。併發

  bagging的結合策略是簡單的投票法和算術平均值,因爲Bagging算法每次都進行採樣來訓練模型,所以泛化能力很強,對於下降模型的方差頗有做用。固然對於訓練集的擬合程度就會差一些,也就是模型的偏倚會大一些。app

下載 (1).png

隨機森林(Random Forest)

  隨機森林是使用cart決策樹做爲弱學習器的使用bagging方法的集成模型,可是對cart決策樹進了改進以加強泛化能力。Cart樹在每一個節點進行二分時,選擇的是最優的特徵,即劃分後基尼係數最小或方差最小的特徵,決策樹中的弱學習器在選擇特徵時,先隨機選擇k個特徵,而後在這k個特徵中選擇最優特徵。框架

import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
import warnings
warnings.filterwarnings('ignore')
#在two_moon數據集上構造5棵樹組成的隨機森林
import seaborn as sns
import mglearn

from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import make_moons
from sklearn.model_selection import train_test_split

X,y = make_moons(n_samples=100,noise=0.25,random_state=3)
X_train,X_test,y_train,y_test = train_test_split(X,y,stratify=y,random_state=42)

RFC = RandomForestClassifier(n_estimators=5,random_state=2).fit(X_train,y_train)

#將每棵樹及總預測可視化
fig,axes = plt.subplots(2,3,figsize=(20,10))
for i,(ax,tree) in enumerate(zip(axes.ravel(),RFC.estimators_)):
    ax.set_title('Tree{}'.format(i))
    mglearn.plots.plot_tree_partition(X_train,y_train,tree,ax=ax)
mglearn.plots.plot_2d_separator(RFC,X_train,fill=True,ax=axes[-1,-1],alpha=.4)
axes[-1,-1].set_title('Random Forest')
mglearn.discrete_scatter(X_train[:,0],X_train[:,1],y_train)

output_12_1.png

  能夠看出,5棵決策樹結果徹底不一樣,綜合後獲得隨機森林。dom

#在乳腺癌數據上構建隨機森林
from sklearn.datasets import load_breast_cancer

cancer = load_breast_cancer()
X_train,X_test,y_train,y_test=train_test_split(cancer.data,cancer.target,stratify=cancer.target,random_state=0)

RFC = RandomForestClassifier(n_estimators=100,max_features=5,oob_score=True,random_state=88).fit(X_train,y_train)
print('訓練精度:{}'.format(RFC.score(X_train,y_train)))
print('測試精度:{}'.format(RFC.score(X_test,y_test)))
print('袋外分數:{}'.format(RFC.oob_score_))
訓練精度:1.0
測試精度:0.958041958041958
袋外分數:0.9624413145539906

  隨機森林的特徵重要性:機器學習

fig = plt.figure(dpi=100)
plt.barh(range(len(RFC.feature_importances_)),RFC.feature_importances_)
plt.yticks(range(len(RFC.feature_importances_)),cancer.feature_names)
plt.xlabel("Feature Importance")
plt.show()

output_16_0.png

參數

Bagging框架參數

  • n_estimators:弱學習器個數,默認是100。通常來講n_estimators過小,容易欠擬合,n_estimators太大,計算量會太大,而且n_estimators到必定的數量後,再增大n_estimators得到的模型提高會很小,因此通常選擇一個適中的數值。
  • oob_score:是否使用袋外數據(Out of bag,重採樣剩下的數據)來評價模型,默認False。

決策樹參數

  • max_features:隨機選擇特徵的最大特徵數,默認是auto,即便用N的算數平方根個特徵,N爲特徵數。
  • max_depth:樹的最大深度,默認是不限制,特徵過多時容易過擬合。
  • min_samples_split:最小劃分值,默認爲2,節點樣本數小於該數值不會繼續劃分,預剪枝方法。
  • min_samples_leaf: 最小葉片數據量,默認爲1,小於該值則會被與兄弟節點合併,後剪枝方法。
  • min_weight_fraction_leaf:葉節點樣本權重的最小值,默認爲0,小於該值會被剪枝。
  • max_leaf_nodes:最大葉節點個數,默認None。
  • min_impurity_split:最小不純度,小於該值會被剪枝。

  決策樹參數中最重要的是前四個,後三個通常不會使用。

優勢與缺點

優勢

  • 訓練能夠高度並行化,對於大數據時代的大樣本訓練速度有優點。
  • 因爲能夠隨機選擇決策樹節點劃分特徵,這樣在樣本特徵維度很高的時候,仍然能高效的訓練模型。
  • 在訓練後,能夠給出各個特徵對於輸出的重要性。
  • 因爲採用了隨機採樣,訓練出的模型的方差小,泛化能力強。
  • 相對於Boosting系列的Adaboost和GBDT, RF實現比較簡單。
  • 對部分特徵缺失不敏感。

缺點

  • 在某些噪音比較大的樣本集上,RF模型容易陷入過擬合。
  • 取值劃分比較多的特徵容易對RF的決策產生更大的影響,從而影響擬合的模型的效果。

Boosting

  以下圖所示,boosting的基本思想是,先訓練出一個模型1,此時,每一個樣本的權重是相同的,都是樣本個數的倒數,計算學習偏差率e1,而後根據學習結果來更新樣本權重,增長被錯誤分類的樣本的權重,訓練模型2,計算學習偏差率e2。重複該過程以得到T個個體學習器,而後使用結合策略結合成強學習器。所以,boosting系列算法須要解決如下四個問題:

  • 如何計算學習偏差率e?
  • 如何獲得弱學習器權重係數α?
  • 如何更新樣本權重D?
  • 使用何種結合策略?

Adaboost

  Adaboost迴歸有不少種方法,這裏只介紹分類。

Adaboost分類原理

  Adaboost二分類中標籤y取值爲1,-1

  • 偏差率e,即分類錯誤的比率:$$e_k = P(G_k(x_i) \neq y_i) = \sum\limits_{i=1}^{m}w_{ki}I(G_k(x_i) \neq y_i)$$
  • 學習器權重係數,能夠看出,偏差率e越大,權重係數越小:$$\alpha_k = \frac{1}{2}log\frac{1-e_k}{e_k}$$
  • 樣本權重:$$w_{k+1,i} = \frac{w_{ki}}{Z_K}exp(-\alpha_ky_iG_k(x_i))$$其中$$\alpha_k = \frac{1}{2}log\frac{1-e_k}{e_k}$$
  • 集合策略,加權表決法:$$f(x) = sign(\sum\limits_{k=1}^{K}\alpha_kG_k(x))$$

Adaboost分類實現

Adaboost框架參數

  • base_estimator:弱學習器,默認爲決策樹,通常使用Cart樹或神經網絡。
  • n_estimators:最大迭代次數,默認50。
  • learning_rate: :學習率,默認爲1,取值大於0小於1。
  • algorithm:scikit-learn實現了兩種Adaboost分類算法,SAMME和SAMME.R。二者的主要區別是弱學習器權重的度量,SAMME使用了和咱們的原理篇裏二元分類Adaboost算法的擴展,即用對樣本集分類效果做爲弱學習器權重,而SAMME.R使用了對樣本集分類的預測機率大小來做爲弱學習器權重。因爲SAMME.R使用了機率度量的連續值,迭代通常比SAMME快,所以AdaBoostClassifier的默認算法algorithm的值也是SAMME.R。咱們通常使用默認的SAMME.R就夠了,可是要注意的是使用了SAMME.R, 則弱分類學習器參數base_estimator必須限制使用支持機率預測的分類器。SAMME算法則沒有這個限制。

Adaboost分類器調參較爲簡單,框架參數基本上只須要調節學習率和最大迭代次數。

  下面是sklearn實現分類,首先導入相關包並建立數據,數據是二維數據,分佈如圖所示:

from sklearn.ensemble import AdaBoostClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import make_gaussian_quantiles

# 生成2維正態分佈,生成的數據按分位數分爲兩類,500個樣本,2個樣本特徵,協方差係數爲2
X1, y1 = make_gaussian_quantiles(cov=2.0,n_samples=500, n_features=2,n_classes=2, random_state=1)
# 生成2維正態分佈,生成的數據按分位數分爲兩類,400個樣本,2個樣本特徵均值都爲3,協方差係數爲2
X2, y2 = make_gaussian_quantiles(mean=(3, 3), cov=1.5,n_samples=400, n_features=2, n_classes=2, random_state=1)
#將兩組數據合成一組數據
X = np.concatenate((X1, X2))
y = np.concatenate((y1, - y2 + 1))
plt.scatter(X[:, 0], X[:, 1], marker='o', c=y)
plt.show()

output_30_0.png

#訓練模型
ada = AdaBoostClassifier(DecisionTreeClassifier(max_depth=10,min_samples_leaf=5),n_estimators=600,learning_rate=0.7).fit(X,y)
print(ada.score(X,y))
#繪圖
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02),
                     np.arange(y_min, y_max, 0.02))

Z = ada.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
cs = plt.contourf(xx, yy, Z, cmap=plt.cm.Paired)
plt.scatter(X[:, 0], X[:, 1], marker='o', c=y)
plt.show()
1.0

output_31_1.png

優勢:

  • Adaboost做爲分類器時,分類精度很高
  • 在Adaboost的框架下,可使用各類迴歸分類模型來構建弱學習器,很是靈活。
  • 做爲簡單的二元分類器時,構造簡單,結果可理解。
  • 不容易發生過擬合

缺點:

  • 對異常樣本敏感,異常樣本在迭代中可能會得到較高的權重,影響最終的強學習器的預測準確性

梯度提高樹(Gradient Boosting Decision Tree,GBDT)

  梯度提高樹的原理是,構造一系列決策樹,每一棵樹在前一棵基礎上進行修正,以此來得到效果較好的決策樹。舉個例子,一我的150kg,先訓練一個模型,該模型爲第T個模型,用這個模型估計他的體重爲140kg,誤差爲10kg,而後再訓練一個模型t,用於估計誤差,誤差的估計值爲8kg,而後將這兩個模型加起來做爲T+1個模型,來估計體重。

迴歸樹

  首先訓練一個Cart樹$$f_0(x) = \underbrace{arg\; min}_{c}\sum\limits_{i=1}^{m}L(y_i, c)$$其損失函數爲$$L=\sum \frac12[f(x_i)-y_i]^2$$其負梯度爲$$r_{ti} = -\bigg[\frac{\partial L(y_i, f(x_i)))}{\partial f(x_i)}\bigg]_{f(x) = f_{t-1}\;\; (x)}=y_i-f(x_i)$$計算每條數據的負梯度,獲得數據集$$(x_i,r_{ti})\;\; (i=1,2,..m)$$負梯度恰好是實際值與模型擬合值之間的誤差,再訓練一個模型用於擬合這個誤差$$c_{tj} = \underbrace{arg\; min}_{c}\sum\limits_{x_i \in R_{tj}} L(y_i,f_{t-1}(x_i) +c)$$而後更新學習器$$f_{t}(x) = f_{t-1}(x) + \sum\limits_{j=1}^{J}c_{tj}I(x \in R_{tj})$$
獲得學習器t,重複此過程直到結束,最終預測值爲$$f(x) = f_T(x) =f_0(x) + \sum\limits_{t=1}^{T}\sum\limits_{j=1}^{J}c_{tj}I(x \in R_{tj})$$

分類

  分類的原理與迴歸是相似的,只是損失函數不一樣,致使負梯度擬合不一樣,其餘步驟相同。損失函數使用似然函數。

二元損失函數$$L(y, f(x)) = log(1+ exp(-yf(x)))$$$$r_{ti} = -\bigg[\frac{\partial L(y, f(x_i)))}{\partial f(x_i)}\bigg]_{f(x) = f_{t-1}\;\; (x)} = y_i/(1+exp(y_if(x_i)))$$多元損失函數$$L(y, f(x)) = - \sum\limits_{k=1}^{K}y_klog\;p_k(x)$$

正則化

  • 學習率:每一個損失擬合值的係數,在0-1之間。
  • cart樹剪枝等正則化。
  • 子採樣:不放回的採樣數據。

sklearn實現

  框架參數

  • n_estimators:學習器個數,默認100
  • learning_rate: 學習率,默認1,與學習器個數一同調參。
  • subsample:子採樣比例,用於正則化,0-1之間,默認是1.
  • loss:損失函數。

  對於分類模型,有對數似然損失函數"deviance"和指數損失函數"exponential"二者輸入選擇。默認是對數似然損失函數"deviance"。通常來講,推薦使用默認的"deviance"。它對二元分離和多元分類各自都有比較好的優化。而指數損失函數等於把咱們帶到了Adaboost算法。

  對於迴歸模型,有均方差"ls", 絕對損失"lad", Huber損失"huber"和分位數損失「quantile」。默認是均方差"ls"。通常來講,若是數據的噪音點很少,用默認的均方差"ls"比較好。若是是噪音點較多,則推薦用抗噪音的損失函數"huber"。而若是咱們須要對訓練集進行分段預測的時候,則採用「quantile」。

  • alpha:這個參數只有GradientBoostingRegressor有,當咱們使用Huber損失"huber"和分位數損失「quantile」時,須要指定分位數的值。默認是0.9,若是噪音點較多,能夠適當下降這個分位數的值。

  弱學習器是Cart樹,參數與cart樹相同。

  下面是調參實踐,首先訓練一個默認模型:

#梯度提高樹
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.metrics import roc_auc_score

gbdt=GradientBoostingClassifier(random_state=10).fit(X_train,y_train)
print('訓練精度:{}'.format(gbdt.score(X_train,y_train)))
print('測試精度:{}'.format(gbdt.score(X_test,y_test)))
print('測試AUC:{}'.format(roc_auc_score(y_test,gbdt.predict_proba(X_test)[:,1])))
訓練精度:1.0
測試精度:0.958041958041958
測試AUC:0.978511530398323

  而後令學習率爲0.1,尋找最優的學習器個數,爲80個。

from sklearn.model_selection import GridSearchCV

param_test1 = {'n_estimators':range(20,101,10)}
gsearch1 = GridSearchCV(estimator = GradientBoostingClassifier(learning_rate=0.1,
                                  max_depth=8, random_state=10), 
                       param_grid = param_test1, scoring='roc_auc',iid=False,cv=5).fit(X_train,y_train)
gsearch1.best_params_,gsearch1.best_score_
({'n_estimators': 80}, 0.9836974622979643)

  使用以上兩參數,來網格搜索最大深度和最小葉片分割數以及最小葉片數據量。

param_test2 = {'max_depth':range(2,14,2),
               'min_samples_split':range(10,41,5),
              'min_samples_leaf':[5,41,5]}
gsearch2 = GridSearchCV(GradientBoostingClassifier(n_estimators=80,learning_rate=0.1,random_state=10),
                        param_test2,scoring='roc_auc',cv=5).fit(X_train,y_train)
gsearch2.best_params_,gsearch2.best_score_
({'max_depth': 10, 'min_samples_leaf': 5, 'min_samples_split': 15},
 0.9939034991321204)

  使用新模型參數預測:

gbdt_grided = GradientBoostingClassifier(max_depth=10,min_samples_leaf=5,min_samples_split=10,
                                         n_estimators=160,learning_rate=0.05,random_state=10).fit(X_train,y_train)
print('訓練集AUC{}'.format(roc_auc_score(y_train,gbdt_grided.predict_proba(X_train)[:,1])))
print('測試集AUC{}'.format(roc_auc_score(y_test,gbdt_grided.predict_proba(X_test)[:,1])))
訓練集AUC1.0
測試集AUC0.9865828092243186

小結

優勢

  • 能夠靈活處理各類類型的數據,包括連續值和離散值。
  • 在相對少的調參時間狀況下,預測的準確率也能夠比較高。這個是相對SVM來講的。
  • 使用一些健壯的損失函數,對異常值的魯棒性很是強。好比 Huber損失函數和Quantile損失函數。

缺點

  • 因爲弱學習器之間存在依賴關係,難以並行訓練數據。不過能夠經過自採樣的SGBT來達到部分並行。

XGBoost

XGB原理

  XGBoost是GBDT的一個高效實現,主要從下面三個方面作了優化:

  • 算法自己的優化:在算法的弱學習器模型選擇上,對比GBDT只支持決策樹,還能夠直接不少其餘的弱學習器。在算法的損失函數上,除了自己的損失,還加上了正則化部分。在算法的優化方式上,GBDT的損失函數只對偏差部分作負梯度(一階泰勒)展開,而XGBoost損失函數對偏差部分作二階泰勒展開。
  • 算法運行效率的優化:對每一個弱學習器,好比決策樹創建的過程作並行選擇,找到合適的子樹分裂特徵和特徵值。在並行選擇以前,先對全部的特徵的值進行排序分組,方便前面說的並行選擇。對分組的特徵,選擇合適的分組大小,使用CPU緩存進行讀取加速。將各個分組保存到多個硬盤以提升IO速度。
  • 對於缺失值的特徵,經過枚舉全部缺失值在當前節點是進入左子樹仍是右子樹來決定缺失值的處理方式。算法自己加入了L1和L2正則化項,能夠防止過擬合,泛化能力更強。

  Boosting加法模型能夠表示爲$$\hat y_i=\sum _{k=1}^Kf_k(x_i)$$其中K爲弱學習器個數,整個模型的損失函數爲$$L=\sum_{i=1}^n l(y_i,\hat y_i)$$n爲樣本容量,上一節所說的GBDT使用的是MSE做爲損失函數,固然,也能夠用其餘損失函數,考慮正則化項,損失函數變爲$$L=\sum _{i=1}^nl(y_i,\hat y_i)+\sum_{k=1}^K\Omega (f_k)$$因爲$$\hat y_i^t=\hat y_i^{t-1}(x_i)+f_t(x_i)$$其中$f_t(x_i)$就是第t個新加入的模型,所以$$L=\sum _{i=1}^nl(y_i,\hat y_i^{t-1}+f_t)+\sum_{k=1}^K\Omega (f_k)$$

由泰勒定理,$$f(x)=\sum_{i=0}^n\frac {f^{(i)}(a)}{i!}(x-a)^i+R_{n+1}(x)$$其中$R_{n+1}(x)$爲$x^n$的高階無窮小,當n = 2時$$f(x+\delta x)=f(x)+f'(x)\delta x+\frac 12f''(x)\delta x^2$$

作以下替換$$\hat y_i^{t-1}=x,f_t=\delta x$$得$$L=\sum _{i=1}^n[l(y_i,\hat y_i^{t-1})+g_i\delta f_t+\frac 12h_i\delta f_t^2]+\sum_{k=1}^K\Omega (f_k)$$

其中$$g_i=\frac{\partial l(y_i,\hat y_i^{t-1})}{\partial\hat y_i^{t-1}} ,h_i=\frac{\partial^2 l(y_i,\hat y_i^{t-1})}{\partial[\hat y_i^{t-1}]^2}$$

因爲已經訓練完成第t-1個模型,所以,上一個模型的損失函數爲常數,最終第t個模型的損失函數轉化爲$$\begin{split} L&\approx\sum_{i=1}^n(g_if_t+\frac12h_if_t^2)+\sum_{k=1}^K\Omega(f_k)\\&= \sum_{i=1}^n \left [ g_iw_{q(x_i)}+\frac12h_iw_{q(x_i)}^2 \right] + \gamma T + \frac12 \lambda \sum_{j=1}^T w_j^2 \\&= \sum_{j=1}^T \left[(\sum_{i \in I_j}g_i)w_j + \frac12(\sum_{i \in I_j}h_i + \lambda)w_j^2 \right]+ \gamma T\end{split}$$其中因爲決策樹同節點中的預測值相等,有$$f_t(x)=w_{q(x)}$$

令$$G_j=\sum_{i \in I_j}g_i,H_j=\sum_{i \in I_j}h_i$$則$$L = \sum_{j=1}^T \left[G_iw_j + \frac12(H_i + \lambda)w_j^2 \right] + \gamma T$$

令一階偏導爲0得$$w_j^*=-\frac{G_j}{H_j+\lambda}$$此時$$L = -\frac12 \sum_{j=1}^T \frac{G_j^2}{H_j+\lambda} + \gamma T$$

  以上就是模型的損失函數,在構建決策樹模型時,使用L代替MSE進行分叉。

import xgboost as xgb
from sklearn.datasets.samples_generator import make_classification
from sklearn.model_selection import GridSearchCV
# X爲樣本特徵,y爲樣本類別輸出, 共10000個樣本,每一個樣本20個特徵,輸出有2個類別,沒有冗餘特徵,每一個類別一個簇
X, y = make_classification(n_samples=10000, n_features=20, n_redundant=0,
                             n_clusters_per_class=1, n_classes=2, flip_y=0.1)

X_train, X_test, y_train, y_test = train_test_split(X,y,stratify = y,random_state=1)

sklearn_xgb = xgb.XGBClassifier(learning_rate= 0.5, verbosity=1, objective='binary:logistic',random_state=1)
sklearn_xgb.fit(X_train, y_train, early_stopping_rounds=10, eval_metric="error",
        eval_set=[(X_test, y_test)])
gsCv = GridSearchCV(sklearn_xgb,
                   {'max_depth': [4,5,6],
                    'n_estimators': [5,10,20]})
gsCv.fit(X_train,y_train)
print(gsCv.best_score_)
print(gsCv.best_params_)
[0]    validation_0-error:0.1248
Will train until validation_0-error hasn't improved in 10 rounds.
[1]    validation_0-error:0.116
[2]    validation_0-error:0.116
[3]    validation_0-error:0.116
[4]    validation_0-error:0.1164
[5]    validation_0-error:0.1164
[6]    validation_0-error:0.1164
[7]    validation_0-error:0.116
[8]    validation_0-error:0.1164
[9]    validation_0-error:0.1184
[10]    validation_0-error:0.118
[11]    validation_0-error:0.1172
Stopping. Best iteration:
[1]    validation_0-error:0.116

0.8838666666666667
{'max_depth': 5, 'n_estimators': 5}

XGB參數

XGBoost框架參數 

  對於XGBoost的框架參數,最重要的是3個參數: booster,n_estimators和objectve。

  • booster:XGBoost使用的弱學習器類型,能夠是默認的gbtree, 也就是CART決策樹,還能夠是線性弱學習器gblinear以及DART。通常來講,使用gbtree就能夠了,不須要調參。
  • n_estimators:決策樹弱學習器的個數。n_estimators過小,容易欠擬合,n_estimators太大,模型會過於複雜,通常須要調參選擇一個適中的數值。
  • objective:要解決的問題是分類仍是迴歸,或其餘問題,以及對應的損失函數。具體能夠取的值不少,通常只關心在分類和迴歸的時候使用的參數。在迴歸問題objective通常使用reg:squarederror ,即MSE均方偏差。二分類問題通常使用binary:logistic, 多分類問題通常使用multi:softmax。

XGBoost 弱學習器參數

  這裏只討論使用gbtree默認弱學習器的參數。要調參的參數主要是決策樹的相關參數以下:

  • max_depth: 控制樹結構的深度。
  • min_child_weight: 最小的子節點權重閾值,若是某個樹節點的權重小於這個閾值,則不會再分裂子樹,即這個樹節點就是葉子節點。這裏樹節點的權重使用的是該節點全部樣本的二階導數的和,即XGBoost原理裏面的Htj:$$H_{tj} = \sum\limits_{x_i \in R_{tj}}h_{ti}$$這個值須要網格搜索尋找最優值,在sklearn GBDT裏面,沒有徹底對應的參數,不過min_samples_split從另外一個角度起到了閾值限制。
  • gamma: XGBoost的決策樹分裂所帶來的損失減少閾值。也就是咱們在嘗試樹結構分裂時,會嘗試最大化下式:$$\max \frac{1}{2}\frac{G_L^2}{H_L + \lambda} + \frac{1}{2}\frac{G_R^2}{H_R+\lambda}-\frac{1}{2}\frac{(G_L+G_R)^2}{H_L+H_R+ \lambda} - \gamma$$這個最大化後的值須要大於gamma,才能繼續分裂子樹。
  • subsample: 子採樣參數,這個也是不放回抽樣,和sklearn GBDT的subsample做用同樣。選擇小於1的比例能夠減小方差,即防止過擬合,可是會增長樣本擬合的誤差,所以取值不能過低。初期能夠取值1,若是發現過擬合後能夠網格搜索調參找一個相對小一些的值。
  • colsample_bytree/colsample_bylevel/colsample_bynode: 這三個參數都是用於特徵採樣的,默認都是不作採樣,即便用全部的特徵創建決策樹。colsample_bytree控制整棵樹的特徵採樣比例,colsample_bylevel控制某一層的特徵採樣比例,而colsample_bynode控制某一個樹節點的特徵採樣比例。好比咱們一共64個特徵,則假設colsample_bytree,colsample_bylevel和colsample_bynode都是0.5,則某一個樹節點分裂時會隨機採樣8個特徵來嘗試分裂子樹。
  • reg_alpha/reg_lambda: 這2個是XGBoost的正則化參數。reg_alpha是L1正則化係數,reg_lambda是L2正則化係數,在原理篇裏咱們討論了XGBoost的正則化損失項部分:

XGBoost 其餘參數

  XGBoost還有一些其餘的參數須要注意,主要是learning_rate。
  learning_rate控制每一個弱學習器的權重縮減係數,和sklearn GBDT的learning_rate相似,較小的learning_rate意味着咱們須要更多的弱學習器的迭代次數。一般咱們用步長和迭代最大次數一塊兒來決定算法的擬合效果。因此這兩個參數n_estimators和learning_rate要一塊兒調參纔有效果。固然也能夠先固定一個learning_rate,而後調完n_estimators,再調完其餘全部參數後,最後再來調learning_rate和n_estimators。

  此外,n_jobs控制算法的併發線程數, scale_pos_weight用於類別不平衡的時候,負例和正例的比例。相似於sklearn中的class_weight。importance_type則能夠查詢各個特徵的重要性程度。能夠選擇「gain」, 「weight」, 「cover」, 「total_gain」 或者 「total_cover」。最後能夠經過調用booster的get_score方法獲取對應的特徵權重。「weight」經過特徵被選中做爲分裂特徵的計數來計算重要性,「gain」和「total_gain」則經過分別計算特徵被選中作分裂特徵時帶來的平均增益和總增益來計算重要性。「cover」和 「total_cover」經過計算特徵被選中作分裂時的平均樣本覆蓋度和整體樣本覆蓋度來來計算重要性。

LightGBM

from lightgbm import LGBMRegressor
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import GridSearchCV
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.externals import joblib

# 加載數據
iris = load_iris()
data = iris.data
target = iris.target

# 劃分訓練數據和測試數據
X_train, X_test, y_train, y_test = train_test_split(data, target, test_size=0.2)

# 模型訓練
gbm = LGBMRegressor(objective='regression', num_leaves=31, learning_rate=0.05, n_estimators=20)
gbm.fit(X_train, y_train, eval_set=[(X_test, y_test)], eval_metric='l1', early_stopping_rounds=5)

# 模型存儲
joblib.dump(gbm, 'loan_model.pkl')
# 模型加載
gbm = joblib.load('loan_model.pkl')

# 模型預測
y_pred = gbm.predict(X_test, num_iteration=gbm.best_iteration_)

# 模型評估
print('The rmse of prediction is:', mean_squared_error(y_test, y_pred) ** 0.5)

# 特徵重要度
print('Feature importances:', list(gbm.feature_importances_))

# 網格搜索,參數優化
estimator = LGBMRegressor(num_leaves=31)
param_grid = {
    'learning_rate': [0.01, 0.1, 1],
    'n_estimators': [20, 40]
}
gbm = GridSearchCV(estimator, param_grid)
gbm.fit(X_train, y_train)
print('Best parameters found by grid search are:', gbm.best_params_)
[1]    valid_0's l1: 0.770574    valid_0's l2: 0.729519
Training until validation scores don't improve for 5 rounds
[2]    valid_0's l1: 0.736515    valid_0's l2: 0.662428
[3]    valid_0's l1: 0.70474    valid_0's l2: 0.602743
[4]    valid_0's l1: 0.673927    valid_0's l2: 0.548122
[5]    valid_0's l1: 0.647149    valid_0's l2: 0.498853
[6]    valid_0's l1: 0.619693    valid_0's l2: 0.454836
[7]    valid_0's l1: 0.59361    valid_0's l2: 0.41521
[8]    valid_0's l1: 0.568332    valid_0's l2: 0.378919
[9]    valid_0's l1: 0.546353    valid_0's l2: 0.346133
[10]    valid_0's l1: 0.523806    valid_0's l2: 0.316952
[11]    valid_0's l1: 0.502036    valid_0's l2: 0.290314
[12]    valid_0's l1: 0.481625    valid_0's l2: 0.266628
[13]    valid_0's l1: 0.461931    valid_0's l2: 0.245002
[14]    valid_0's l1: 0.445287    valid_0's l2: 0.225741
[15]    valid_0's l1: 0.427082    valid_0's l2: 0.20802
[16]    valid_0's l1: 0.409383    valid_0's l2: 0.190996
[17]    valid_0's l1: 0.392466    valid_0's l2: 0.175393
[18]    valid_0's l1: 0.377264    valid_0's l2: 0.162742
[19]    valid_0's l1: 0.36181    valid_0's l2: 0.150029
[20]    valid_0's l1: 0.348036    valid_0's l2: 0.139806
Did not meet early stopping. Best iteration is:
[20]    valid_0's l1: 0.348036    valid_0's l2: 0.139806
The rmse of prediction is: 0.37390595890720224
Feature importances: [1, 9, 40, 18]
Best parameters found by grid search are: {'learning_rate': 0.1, 'n_estimators': 40}
相關文章
相關標籤/搜索