RF谒兄,GBDT和Xgboost構(gòu)造新特征+LR融合的原理及實踐

轉(zhuǎn)載:https://blog.csdn.net/anshuai_aw1/article/details/82983997
關(guān)于Xgboost的知識點很多,本篇博客介紹如何利用Xgboost構(gòu)造新特征社付,且在此基礎(chǔ)上承疲,介紹與LR模型融合的相關(guān)知識點邻耕。

一 目錄
二 實踐
2.1 如何獲得樣本落在哪個葉子節(jié)點
2.2 舉例
2.2.1 訓練集準備
2.2.2 RF+LR
2.2.3 GBDT+LR
2.2.4 Xgboost+LR
2.2.5 單獨使用RF,GBDT和Xgboost
2.2.6 結(jié)果對比
三 為什么Xgboost+LR 的融合效果沒有想象的那么好
四 參考文獻

一 原理

為什么要使用LR模型進行融合呢? 這是因為LR(邏輯回歸)算法簡單有效燕鸽,成為工業(yè)界最常用的算法之一兄世。但LR算法是線性模型,不能捕捉到非線性西悉尼啊研,需要大量的特征工程找到特征組合御滩。為了發(fā)現(xiàn)有效的特征組合,F(xiàn)acebook在2014年論文ractical Lessons from Predicting Clicks on Ads at Facebook 介紹通過GBDT (Gradient Boost Decision Tree)+ LR 的方案 (XGBoost 是 GBDT 的后續(xù)發(fā)展)党远。在這篇論文中他們提出一中將Xgboost作為feature transform 的方法削解。隨后在多個Kaggle比賽中,均證明此思路的有效性沟娱。

大概的思想可以描述為如下:先用已有特征訓練Xgboost模型氛驮,然后利用Xgboost模型學習到的樹來構(gòu)造新特征,最后把這些新特征加入原有特征一起訓練模型济似。構(gòu)造的新特征向量是取值0/1的矫废,向量的每個元素對應(yīng)于Xgboost模型中樹的葉子結(jié)點。當一個樣本點通過某棵樹最終落在這棵樹的一個葉子結(jié)點上砰蠢,那么在新特征向量中這個葉子結(jié)點對應(yīng)的元素值為1磷脯,而這棵樹的其他葉子結(jié)點對應(yīng)的元素值為0。新特征向量的長度等于XGBoost模型里所有樹包含的葉子結(jié)點數(shù)之和娩脾。最后將新的特征扔到LR模型進行訓練。

舉例說明打毛。下面的圖中的兩棵樹是GBDT(Xgboost一樣)學習到的柿赊,第一棵樹有3個葉子結(jié)點,而第二棵樹有2個葉子節(jié)點幻枉。對于一個輸入樣本點x碰声,如果它在第一棵樹最后落在其中的第二個葉子結(jié)點,而在第二棵樹里最后落在其中的第一個葉子結(jié)點熬甫。那么通過GBDT獲得的新特征向量為[0, 1, 0, 1, 0]胰挑,其中向量中的前三位對應(yīng)第一棵樹的3個葉子結(jié)點,后兩位對應(yīng)第二棵樹的2個葉子結(jié)點椿肩。

image.png

二實踐

2.1 如何獲得樣本落在哪個葉子節(jié)點

在實踐中的關(guān)鍵點是如何獲得每個樣本落在訓練后的每棵樹的哪個葉子結(jié)點上瞻颂。

A、對于Xgboost來說郑象,因為其有sklearn接口和自帶接口贡这,因此有兩種方法可以獲得:

①、sklearn接口厂榛「墙茫可以設(shè)置pre_leaf=True獲得每個樣本在每顆樹上的leaf_Index丽惭。XGBoost官方文檔

image.png

②、自帶接口辈双。利用apply()方法可以獲得leaf indices责掏。SKlearn GBDT API
!E韧换衬!此過程需注意: 無論是設(shè)置pre_leaf=True還是利用apply()方法,獲得的都是葉子節(jié)點的 index喜爷,也就是說落在了具體哪顆樹的哪個葉子節(jié)點上冗疮,并非是0/1變量,因此需要自己動手去做 onehot 編碼檩帐。onehot 可以在 sklearn 的預(yù)處理包中調(diào)用即可术幔。
B、對于其它的樹模型湃密,如隨機森林和GBDT诅挑,我們只能使用apply()方法獲得leaf indices。

2.2 舉例

接下來泛源,我們舉例來說明如何利用樹模型拔妥,尤其是Xgboost來構(gòu)建新特征,并且是如何與LR模型進行融合达箍。

本例子對Feature transformations with ensembles of trees進行了改進没龙,使得更加健壯易讀。

2.2.1 訓練集準備

從代碼中缎玫,可以看到硬纤,我們對訓練集X_train又進行了一次切分,生成了訓練集X_train, X_train_lr和測試集y_train, y_train_lr赃磨。特別要注意數(shù)據(jù)集的大小筝家,后續(xù)我們會進行分析。

注意:我們設(shè)定了n_estimator = 10邻辉,這意味著樹模型中只有10顆樹.


import numpy as np
np.random.seed(10)
 
import matplotlib.pyplot as plt
import xgboost as xgb
 
from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import ( RandomForestClassifier,
                              GradientBoostingClassifier)
from sklearn.preprocessing import OneHotEncoder
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_curve,  roc_auc_score
from scipy.sparse import hstack
 
 
 
X, y = make_classification(n_samples=80000)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5)
 
# It is important to train the ensemble of trees on a different subset
# of the training data than the linear regression model to avoid
# overfitting, in particular if the total number of leaves is
# similar to the number of training samples
X_train, X_train_lr, y_train, y_train_lr = train_test_split(
    X_train, y_train, test_size=0.5)
 
n_estimator = 10
 
'''
X_train為20000*20
X_train_lr為20000*20
y_train為20000*1
y_train_lr為20000*1
y_test 為40000*1
'''

2.2.2 RF+LR

我們首先使用隨機森林進行實驗溪王。這里我們需要對代碼進行一個解讀。


# Supervised transformation based on gradient boosted trees
grd = GradientBoostingClassifier(n_estimators=n_estimator)
grd_enc = OneHotEncoder()
grd_lm = LogisticRegression(solver='lbfgs', max_iter=1000)
 
grd.fit(X_train, y_train)
grd_enc.fit(grd.apply(X_train)[:, :, 0])
grd_lm.fit(grd_enc.transform(grd.apply(X_train_lr)[:, :, 0]), y_train_lr)
 
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)
print("GBT+LR的AUC為:", roc_auc_score(y_test, y_pred_grd_lm))

2.2.3 GBDT+LR

我們其次使用隨機森林進行實驗值骇。其代碼與隨機森林幾乎一樣莹菱。不再進行代碼解讀。

# Supervised transformation based on gradient boosted trees
grd = GradientBoostingClassifier(n_estimators=n_estimator)
grd_enc = OneHotEncoder()
grd_lm = LogisticRegression(solver='lbfgs', max_iter=1000)
 
grd.fit(X_train, y_train)
grd_enc.fit(grd.apply(X_train)[:, :, 0])
grd_lm.fit(grd_enc.transform(grd.apply(X_train_lr)[:, :, 0]), y_train_lr)
 
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)
print("GBT+LR的AUC為:", roc_auc_score(y_test, y_pred_grd_lm))

2.2.4 Xgboost+LR

最后吱瘩,我們使用Xgboost進行實驗芒珠。

# Supervised transformation based on xgboost
xgb = xgb.XGBClassifier(nthread=4,     #含義:nthread=-1時,使用全部CPU進行并行運算(默認), nthread=1時搅裙,使用1個CPU進行運算皱卓。
                          learning_rate=0.08,    #含義:學習率裹芝,控制每次迭代更新權(quán)重時的步長,默認0.3娜汁。調(diào)參:值越小嫂易,訓練越慢。典型值為0.01-0.2掐禁。
                          n_estimators=50,       #含義:總共迭代的次數(shù)怜械,即決策樹的個數(shù)
                          max_depth=5,           #含義:樹的深度,默認值為6傅事,典型值3-10缕允。調(diào)參:值越大,越容易過擬合蹭越;值越小障本,越容易欠擬合
                          gamma=0,               #含義:懲罰項系數(shù),指定節(jié)點分裂所需的最小損失函數(shù)下降值响鹃。
                          subsample=0.9,       #含義:訓練每棵樹時驾霜,使用的數(shù)據(jù)占全部訓練集的比例。默認值為1买置,典型值為0.5-1粪糙。調(diào)參:防止overfitting。
                          colsample_bytree=0.5) #訓練每棵樹時忿项,使用的特征占全部特征的比例蓉冈。默認值為1,典型值為0.5-1轩触。調(diào)參:防止overfitting洒擦。
 
xgb_enc = OneHotEncoder()
xgb_lm = LogisticRegression(solver='lbfgs', max_iter=1000)
 
xgb.fit(X_train, y_train)
xgb_enc.fit(xgb.apply(X_train))
xgb_lm.fit(xgb_enc.transform(xgb.apply(X_train_lr)), y_train_lr)
 
y_pred_xgb_lm = xgb_lm.predict_proba(
    xgb_enc.transform(xgb.apply(X_test)))[:, 1]
fpr_xgb_lm, tpr_xgb_lm, _ = roc_curve(y_test, y_pred_xgb_lm)
print("xgboost+LR的AUC為:", roc_auc_score(y_test, y_pred_xgb_lm))

在之前的代碼中,我們只是用樹模型構(gòu)造的新特征來訓練LR怕膛。

接下來,我們更近一步秦踪,將新特征與原始的20個特征進行拼接形成新的數(shù)據(jù)集來訓練LR褐捻。


X_train_ext = hstack([xgb_enc.transform(xgb.apply(X_train_lr)), X_train_lr])
X_test_ext = hstack([xgb_enc.transform(xgb.apply(X_test)), X_test])
xgb_lm.fit(X_train_ext, y_train_lr)
 
y_pred_xgb_originalfeature_lm = xgb_lm.predict_proba(X_test_ext)[:, 1]
fpr_xgb_originalfeature_lm, tpr_xgb_originalfeature_lm, _ = roc_curve(y_test, y_pred_xgb_originalfeature_lm)
print("xgboost新特征與原始特征+LR的AUC為:", roc_auc_score(y_test, y_pred_xgb_originalfeature_lm))

2.2.5 單獨使用RF, GBDT和Xgboost

為了進行對比,我們也輸出單獨使用RF,GBDT和Xgboost的結(jié)果椅邓。

# The gradient boosted model by itself
y_pred_grd = grd.predict_proba(X_test)[:, 1]
fpr_grd, tpr_grd, _ = roc_curve(y_test, y_pred_grd)
print("GBT的AUC為:", roc_auc_score(y_test, y_pred_grd))
 
# The random forest model by itself
y_pred_rf = rf.predict_proba(X_test)[:, 1]
fpr_rf, tpr_rf, _ = roc_curve(y_test, y_pred_rf)
print("RF的AUC為:", roc_auc_score(y_test, y_pred_rf))
 
 
# The xgboost model by itself
xgb.fit(X_train, y_train)
y_pred_xgb = xgb.predict_proba(X_test)[:, 1]
fpr_xgb, tpr_xgb, _ = roc_curve(y_test, y_pred_xgb)
print('xgboost的AUC為:' , roc_auc_score(y_test, y_pred_xgb))

2.2.6 結(jié)果對比
我們運行整個代碼柠逞,結(jié)果為:

RF+LR的AUC為: 0.972532755993
GBT+LR的AUC為: 0.984711442675
xgboost+LR的AUC為: 0.992587688381
xgboost新特征與原始特征+LR的AUC為: 0.992632312284
GBT的AUC為: 0.98220013158
RF的AUC為: 0.965762807823
xgboost的AUC為: 0.99284427301

我們可以看到:對于RF和GBT,與LR進行融合后的結(jié)果要比單獨使用RF和GBT要好景馁。而對于Xgboost板壮,單獨使用Xgboost效果最好,其次是xgboost新特征與原始特征+LR合住,最后才是xgboost+LR绰精。這與我們預(yù)期不符撒璧。為什么會出現(xiàn)這樣的結(jié)果,值得我們討論笨使。

畫圖來進一步看下ROC曲線:

plt.figure(1)
plt.plot([0, 1], [0, 1], 'k--')
plt.plot(fpr_rf, tpr_rf, label='RF')
plt.plot(fpr_rf_lm, tpr_rf_lm, label='RF + LR')
plt.plot(fpr_grd, tpr_grd, label='GBT')
plt.plot(fpr_grd_lm, tpr_grd_lm, label='GBT + LR')
plt.plot(fpr_xgb, tpr_xgb, label='XGB')
plt.plot(fpr_xgb_lm, tpr_xgb_lm, label='XGB + LR')
plt.plot(fpr_xgb_originalfeature_lm, tpr_xgb_originalfeature_lm, label='XGB + ori_fea+ LR')
plt.xlabel('False positive rate')
plt.ylabel('True positive rate')
plt.title('ROC curve')
plt.legend(loc='best')
plt.show()

plt.figure(2)
plt.xlim(0, 0.2)
plt.ylim(0.8, 1)
plt.plot([0, 1], [0, 1], 'k--')
plt.plot(fpr_rf, tpr_rf, label='RF')
plt.plot(fpr_rf_lm, tpr_rf_lm, label='RF + LR')
plt.plot(fpr_grd, tpr_grd, label='GBT')
plt.plot(fpr_grd_lm, tpr_grd_lm, label='GBT + LR')
plt.plot(fpr_xgb, tpr_xgb, label='XGB')
plt.plot(fpr_xgb_lm, tpr_xgb_lm, label='XGB + LR')
plt.plot(fpr_xgb_originalfeature_lm, tpr_xgb_originalfeature_lm, label='XGB + ori_fea + LR')
plt.xlabel('False positive rate')
plt.ylabel('True positive rate')
plt.title('ROC curve (zoomed in at top left)')
plt.legend(loc='best')
plt.show()
image
image

上面的圖為ROC曲線卿樱,下面的圖是對ROC曲線左上角進行了放大。

三硫椰、為什么Xgboost+LR的融合效果沒有想象中那么好

在2.2.6中繁调,我們提到了僅使用Xgboost的結(jié)果反而最好。這是為什么呢靶草?因為XGBoost + LR 只是一種特征工程的方法蹄胰,并不是一種能自動替代特征工程的方法。

借助參考文獻【2】奕翔,我們來驗證 XGBoost + LR 是嘗試自動替代特征工程的方法裕寨,還只是一種特征工程的方法。

我們在自己業(yè)務(wù)的數(shù)據(jù)上做了一些實驗糠悯。下圖便是實驗結(jié)果懒闷,其中: “xgboost+lr1" 是 XGBoost 的葉子節(jié)點特征宾濒、原始屬性特征和二階交叉特征一起給 LR 進行訓練;"xgboost+lr2" 則只有葉子節(jié)點特征給 LR;"lr1" 是原始屬性特征和二階交叉特征; "lr2" 只有原始屬性特征泌辫。


image.png

從上面的實驗來看:

  1. "xgboost+lr2" 明顯弱于 "lr1" 方法,說明只用葉子節(jié)點特征的 XGBoost + LR 弱于有特征工程的 LR 算法峭弟。即 XGBoost 葉子節(jié)點不能取代特征工程朗伶,XGBoost + LR 無法取代傳統(tǒng)的特征工程。

  2. "xgboost+lr1" 取得了所有方法中的最好效果昨稼,說明了保留原來的特征工程 XGBoost + LR 方法擁有比較好的效果节视。即 XGBoost 葉子節(jié)點特征是一種有效的特征,XGBoost + LR 是一種有效的特征工程手段假栓。

因此寻行,可以得到以下的結(jié)論:

盡管XGBoost+LR 在工業(yè)和競賽實踐中,都取得了不錯的效果匾荆。但 XGBoost 的葉子節(jié)點不能完全替代人工特征拌蜘, XGBoost + LR 并沒有像深度學習那樣試圖帶來自動特征工程的故事和邏輯。最終牙丽,XGBoost + LR 的格局沒有超越特征工程简卧。

參考文獻
【1】XGBoost+LR融合的原理和簡單實現(xiàn)

【2】XGBoost + LR 就是加特征而已

【3】XGBoost Plotting API以及GBDT組合特征實踐

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市烤芦,隨后出現(xiàn)的幾起案子举娩,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件铜涉,死亡現(xiàn)場離奇詭異智玻,居然都是意外死亡,警方通過查閱死者的電腦和手機尚困,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進店門链蕊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人滔韵,你說我怎么就攤上這事逻谦。” “怎么了陪蜻?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長滋将。 經(jīng)常有香客問我,道長症昏,這世上最難降的妖魔是什么随闽? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮掘宪,結(jié)果婚禮上攘烛,老公的妹妹穿的比我還像新娘魏滚。我一直安慰自己坟漱,他們只是感情好,可當我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布腥寇。 她就那樣靜靜地躺著沟突,像睡著了一般捕传。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上职辅,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天,我揣著相機與錄音簇秒,去河邊找鬼秀鞭。 笑死,一個胖子當著我的面吹牛锋边,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播剩辟,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼往扔,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了萍膛?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤噪馏,失蹤者是張志新(化名)和其女友劉穎欠肾,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體拟赊,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年瑟慈,在試婚紗的時候發(fā)現(xiàn)自己被綠了屋匕。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片过吻。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡蔗衡,死狀恐怖乳绕,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情洋措,我是刑警寧澤,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布王滤,位于F島的核電站雷酪,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏蔗怠。R本人自食惡果不足惜吩跋,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望桥温。 院中可真熱鬧梁丘,春花似錦、人聲如沸氛谜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽杨何。三九已至,卻和暖如春羊娃,著一層夾襖步出監(jiān)牢的瞬間埃跷,已是汗流浹背芦瘾。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工集畅, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留缅糟,地道東北人。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓赦颇,卻偏偏與公主長得像赴涵,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子髓窜,可洞房花燭夜當晚...
    茶點故事閱讀 44,976評論 2 355

推薦閱讀更多精彩內(nèi)容