生活随笔
收集整理的這篇文章主要介紹了
GBDT和LR结合使用分析
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
?文章來源:https://www.deeplearn.me/1797.html
?
GBDT+LR 的特征組合方案是工業界經常使用的組合,尤其是計算廣告 CTR 中應用比較廣泛,方案的提出者是 Facebook 2014 的一篇論文。
相關的開發工具包,sklearn 和 xgboost(ps:xgboost 是一個大殺器,并且支持 hadoop 分布式,你可以部署實現分布式操作,博主部署過,布置過程較為負責,尤其是環境變量的各種設置)
特征決定模型性能上界,例如深度學習方法也是將數據如何更好的表達為特征。如果能夠將數據表達成為線性可分的數據,那么使用簡單的線性模型就可以取得很好的效果。GBDT 構建新的特征也是使特征更好地表達數據。
主要參考 Facebook[1],原文提升效果:
在預測 Facebook 廣告點擊中,使用一種將決策樹與邏輯回歸結合在一起的模型,其優于其他方法,超過 3%。
主要思想:GBDT 每棵樹的路徑直接作為 LR 輸入特征使用。
用已有特征訓練 GBDT 模型,然后利用 GBDT 模型學習到的樹來構造新特征,最后把這些新特征加入原有特征一起訓練模型。構造的新特征向量是取值 0/1 的,向量的每個元素對應于 GBDT 模型中樹的葉子結點。當一個樣本點通過某棵樹最終落在這棵樹的一個葉子結點上,那么在新特征向量中這個葉子結點對應的元素值為 1,而這棵樹的其他葉子結點對應的元素值為 0。新特征向量的長度等于 GBDT 模型里所有樹包含的葉子結點數之和。
上圖為混合模型結構。輸入特征通過增強的決策樹進行轉換。 每個單獨樹的輸出被視為稀疏線性分類器的分類輸入特征。 增強的決策樹被證明是非常強大的特征轉換。
例子 1:上圖有兩棵樹,左樹有三個葉子節點,右樹有兩個葉子節點,最終的特征即為五維的向量。對于輸入 x,假設他落在左樹第一個節點,編碼[1,0,0],落在右樹第二個節點則編碼[0,1],所以整體的編碼為[1,0,0,0,1],這類編碼作為特征,輸入到線性分類模型(LR or FM)中進行分類。
需要注意的是在 sklearn 或者 xgboost 輸出的結果都是葉子節點的 index,所以需要自己動手去做 onehot 編碼,然后交給 lr 訓練,onehot 你可以在 sklearn 的預處理包中調用即可
論文中 GBDT 的參數,樹的數量最多 500 顆(500 以上就沒有提升了),每棵樹的節點不多于 12。
下面給出二者相結合的代碼演示
?
# -*- coding: utf-8 -*-# @Time : 2018/2/27 上午 10:39# @Author : Tomcj# @File : gbdt_lr.py# @Software: PyCharmimport xgboost as xgbfrom sklearn.datasets import load_svmlight_filefrom sklearn.model_selection import train_test_splitfrom sklearn.linear_model import LogisticRegressionfrom sklearn.metrics import roc_curve, auc, roc_auc_scorefrom sklearn.externals import joblibfrom sklearn.preprocessing import OneHotEncoderimport numpy as npfrom scipy.sparse import hstack???def xgb_feature_encode(libsvmFileNameInitial):?# load 樣本數據X_all, y_all = load_svmlight_file(libsvmFileNameInitial)?# 訓練/測試數據分割X_train, X_test, y_train, y_test = train_test_split(X_all, y_all, test_size = 0.3, random_state = 42)?# 定義模型xgboost = xgb.XGBClassifier(nthread=4, learning_rate=0.08,n_estimators=50, max_depth=5, gamma=0, subsample=0.9, colsample_bytree=0.5)# 訓練學習xgboost.fit(X_train, y_train)??# 預測及 AUC 評測y_pred_test = xgboost.predict_proba(X_test)[:, 1]xgb_test_auc = roc_auc_score(y_test, y_pred_test)print('xgboost test auc: %.5f' % xgb_test_auc)?# xgboost 編碼原有特征X_train_leaves = xgboost.apply(X_train)X_test_leaves = xgboost.apply(X_test)# 訓練樣本個數train_rows = X_train_leaves.shape[0]# 合并編碼后的訓練數據和測試數據X_leaves = np.concatenate((X_train_leaves, X_test_leaves), axis=0)X_leaves = X_leaves.astype(np.int32)?(rows, cols) = X_leaves.shape?# 記錄每棵樹的編碼區間cum_count = np.zeros((1, cols), dtype=np.int32)?for j in range(cols):if j == 0:cum_count[0][j] = len(np.unique(X_leaves[:, j]))else:cum_count[0][j] = len(np.unique(X_leaves[:, j])) + cum_count[0][j-1]?print('Transform features genenrated by xgboost...')# 對所有特征進行 ont-hot 編碼,注釋部分是直接使用 onehot 函數,結果輸出保證是 libsvm 格式也可以使用#sklearn 中的 dump_svmlight_file 操作,這個文件代碼是參考別人的代碼,這些點都是可以優化的。?# onehot=OneHotEncoder()# onehot.fit(X_leaves)# x_leaves_encode=onehot.transform(X_leaves)for j in range(cols):keyMapDict = {}if j == 0:initial_index = 1else:initial_index = cum_count[0][j-1]+1for i in range(rows):if X_leaves[i, j] not in keyMapDict:keyMapDict[X_leaves[i, j]] = initial_indexX_leaves[i, j] = initial_indexinitial_index = initial_index + 1else:X_leaves[i, j] = keyMapDict[X_leaves[i, j]]?# 基于編碼后的特征,將特征處理為 libsvm 格式且寫入文件print('Write xgboost learned features to file ...')xgbFeatureLibsvm = open('xgb_feature_libsvm', 'w')for i in range(rows):if i < train_rows:xgbFeatureLibsvm.write(str(y_train[i]))else:xgbFeatureLibsvm.write(str(y_test[i-train_rows]))for j in range(cols):xgbFeatureLibsvm.write(' '+str(X_leaves[i, j])+':1.0')xgbFeatureLibsvm.write('\n')xgbFeatureLibsvm.close()??def xgboost_lr_train(xgbfeaturefile, origin_libsvm_file):?# load xgboost 特征編碼后的樣本數據X_xg_all, y_xg_all = load_svmlight_file(xgbfeaturefile)X_train, X_test, y_train, y_test = train_test_split(X_xg_all, y_xg_all, test_size = 0.3, random_state = 42)?# load 原始樣本數據X_all, y_all = load_svmlight_file(origin_libsvm_file)X_train_origin, X_test_origin, y_train_origin, y_test_origin = train_test_split(X_all, y_all, test_size = 0.3, random_state = 42)??# lr 對原始特征樣本模型訓練lr = LogisticRegression(n_jobs=-1, C=0.1, penalty='l1')lr.fit(X_train_origin, y_train_origin)joblib.dump(lr, 'lr_orgin.m')# 預測及 AUC 評測y_pred_test = lr.predict_proba(X_test_origin)[:, 1]lr_test_auc = roc_auc_score(y_test_origin, y_pred_test)print('基于原有特征的 LR AUC: %.5f' % lr_test_auc)?# lr 對 load xgboost 特征編碼后的樣本模型訓練lr = LogisticRegression(n_jobs=-1, C=0.1, penalty='l1')lr.fit(X_train, y_train)joblib.dump(lr, 'lr_xgb.m')# 預測及 AUC 評測y_pred_test = lr.predict_proba(X_test)[:, 1]lr_test_auc = roc_auc_score(y_test, y_pred_test)print('基于 Xgboost 特征編碼后的 LR AUC: %.5f' % lr_test_auc)?# 基于原始特征組合 xgboost 編碼后的特征X_train_ext = hstack([X_train_origin, X_train])del(X_train)del(X_train_origin)X_test_ext = hstack([X_test_origin, X_test])del(X_test)del(X_test_origin)?# lr 對組合后的新特征的樣本進行模型訓練lr = LogisticRegression(n_jobs=-1, C=0.1, penalty='l1')lr.fit(X_train_ext, y_train)joblib.dump(lr, 'lr_ext.m')# 預測及 AUC 評測y_pred_test = lr.predict_proba(X_test_ext)[:, 1]lr_test_auc = roc_auc_score(y_test, y_pred_test)print('基于組合特征的 LR AUC: %.5f' % lr_test_auc)?if __name__ == '__main__':xgb_feature_encode("/Users/leiyang/xgboost/demo/data/agaricus.txt.train")xgboost_lr_train("xgb_feature_libsvm","/Users/leiyang/xgboost/demo/data/agaricus.txt.train")?
下面給出一個 ipynb 文件,也是從官方的文件改過來的,主要是對 GBDT 輸出到 lr 部分數據觀察
?
view rawgbdt_lr.ipynb?hosted with ? by?GitHub
總結
以上是生活随笔為你收集整理的GBDT和LR结合使用分析的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。