1. 程式人生 > >帶你走進高效機器學習演算法——GBDT

帶你走進高效機器學習演算法——GBDT

GBDT(Gradient Boosting Decision Tree 梯度提升決策樹)演算法近年十分流行,被廣泛應用於各類資料探勘以及機器學習的比賽之中並有著良好的表現。下面讓我們來走進這個演算法。

起源

提起GBDT的起源,我們不得不引出以下幾個概念。

整合學習

引用百科中的一段話:

整合學習是使用一系列學習器進行學習,並使用某種規則把各個學習結果進行整合從而獲得比單個學習器更好的學習效果的一種機器學習方法。一般情況下,整合學習中的多個學習器都是同質的"弱學習器"。

所謂“同質”,是指整合中只包含同種型別的個體學習器。所謂“弱學習器”,是指泛化效能略優於隨機猜測的學習器,例如在二分類問題上精度略高於50%的分類器。換句話說,弱學習器的結果接近於靠猜。 整合學習通過將多個學習器進行結合,通常可以獲得比單一學習器顯著優越的泛化效能,這對弱學習器尤明顯。如何結合個體學習器,就是整合學習研究的核心。目前的整合學習方法大致可分為兩大類:1)個體學習器間存在強依賴關係、必須序列生成的序列化方法,代表是Boosting;2)個體學習器間不存在強依賴關係、可同時生成的並行化方法,代表是Bagging和隨機森林(Random Forest)。 ###Boosting Boosting是一族可將弱學習器提升為強學習器的演算法。 Boosting演算法原理:

  • 先對N個訓練樣本S1的學習得到一個基分類器M1;
  • 將S1中分錯的樣本和其他新的資料一起構成新的N個訓練樣本S2,再得到一個基分類器M2;
  • 將S1和S2中都分錯的樣本和其他新的資料一起構成新的N個訓練樣本S3,再得到一個基分類器M3;
  • 以此類推,直至基學習器數達到事先指定的值T,最終將所有基學習器進行加權結合。

簡單來說,就是基於同一訓練集和同一個演算法訓練出T個基學習器,每一輪訓練都針對上一輪的訓練結果調整樣本分佈。 Boosting族演算法最著名的代表是AdaBoost。

Bagging

Bagging是Bootstrap AGGregatING的縮寫,基於自助取樣法(bootstrap sampling)(一種有放回的抽樣方法,即可能抽到重複的樣本)。 Bagging演算法原理:

  • 使用自助取樣法取樣出T個含有m個訓練樣本的取樣集,然後基於每個取樣集訓練出一個基學習器,再將這些基本學習器進行結合。
  • 在對預測輸出進行結合時,Bagging通常對分了任務使用簡單投票法,對迴歸任務使用簡單平均法。

Gradient Boosting

Gradient Boosting是一種Boosting的方法,它主要的思想是,每一次建立模型是在之前建立模型損失函式的梯度下降方向。損失函式是評價模型效能(一般為擬合程度+正則項),認為損失函式越小,效能越好。而讓損失函式持續下降,就能使得模型不斷改性提升效能,其最好的方法就是使損失函式沿著梯度方向下降。Gradient Boost是一個框架,裡面可以套入很多不同的演算法。

GBDT應用

分類

from sklearn import ensemble
clf = ensemble.GradientBoostingClassifier()
gbdt_model = clf.fit(X_train, y_train)  # Training model
predicty_x = gbdt_model.predict_proba(test_x)[:, 1]  # predict: probablity of 1
# 包含的引數
# loss = loss, learning_rate = learning_rate, n_estimators = n_estimators,
# min_samples_split = min_samples_split,
# min_samples_leaf = min_samples_leaf,
# min_weight_fraction_leaf = min_weight_fraction_leaf,
# max_depth = max_depth, init = init, subsample = subsample,
# max_features = max_features,
# random_state = random_state, verbose = verbose,
# max_leaf_nodes = max_leaf_nodes, warm_start = warm_start,
# presort = presort  

迴歸

from sklearn import ensemble
clf = ensemble.GradientBoostingRegressor()
gbdt_model = clf.fit(X_train, y_train)  # Training model
y_upper = gbdt_model.predict(x_test)  # predict  

構建新特徵

思想:GBDT每棵樹的路徑直接作為LR輸入特徵使用。 用已有特徵訓練GBDT模型,然後利用GBDT模型學習到的樹來構造新特徵,最後把這些新特徵加入原有特徵一起訓練模型。構造的新特徵向量是取值0/1的,向量的每個元素對應於GBDT模型中樹的葉子結點。當一個樣本點通過某棵樹最終落在這棵樹的一個葉子結點上,那麼在新特徵向量中這個葉子結點對應的元素值為1,而這棵樹的其他葉子結點對應的元素值為0。新特徵向量的長度等於GBDT模型裡所有樹包含的葉子結點數之和。

# 弱分類器的數目
n_estimator = 10
# 隨機生成分類資料。
X, y = make_classification(n_samples=80000)  
# 切分為測試集和訓練集,比例0.5
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5)
# 將訓練集切分為兩部分,一部分用於訓練GBDT模型,另一部分輸入到訓練好的GBDT模型生成GBDT特徵,然後作為LR的特徵。這樣分成兩部分是為了防止過擬合。
X_train, X_train_lr, y_train, y_train_lr = train_test_split(X_train, y_train, test_size=0.5)
# 呼叫GBDT分類模型。
grd = GradientBoostingClassifier(n_estimators=n_estimator)
# 呼叫one-hot編碼。
grd_enc = OneHotEncoder()
# 呼叫LR分類模型。
grd_lm = LogisticRegression()


# 使用X_train訓練GBDT模型,後面用此模型構造特徵
grd.fit(X_train, y_train)

# fit one-hot編碼器
grd_enc.fit(grd.apply(X_train)[:, :, 0])

# 使用訓練好的GBDT模型構建特徵,然後將特徵經過one-hot編碼作為新的特徵輸入到LR模型訓練。

grd_lm.fit(grd_enc.transform(grd.apply(X_train_lr)[:, :, 0]), y_train_lr)
# 用訓練好的LR模型多X_test做預測
y_pred_grd_lm = grd_lm.predict_proba(grd_enc.transform(grd.apply(X_test)[:, :, 0]))[:, 1]
# 根據預測結果輸出
fpr_grd_lm, tpr_grd_lm, _ = roc_curve(y_test, y_pred_grd_lm)