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 -*-
2.# @Time    : 2018/2/27 上午 10:39
3.# @Author  : Tomcj
4.# @File    : gbdt_lr.py
5.# @Software: PyCharm
6.import xgboost as xgb
7.from sklearn.datasets import load_svmlight_file
8.from sklearn.model_selection import train_test_split
9.from sklearn.linear_model import LogisticRegression
10.from sklearn.metrics import roc_curve, auc, roc_auc_score
11.from sklearn.externals import joblib
12.from sklearn.preprocessing import  OneHotEncoder
13.import numpy as np
14.from scipy.sparse import hstack
15. 
16. 
17. 
18.def xgb_feature_encode(libsvmFileNameInitial):
19. 
20.    # load 样本数据
21.    X_all, y_all = load_svmlight_file(libsvmFileNameInitial)
22. 
23.    # 训练/测试数据分割
24.    X_train, X_test, y_train, y_test = train_test_split(X_all, y_all, test_size = 0.3, random_state = 42)
25. 
26.    # 定义模型
27.    xgboost = xgb.XGBClassifier(nthread=4, learning_rate=0.08,
28.                            n_estimators=50, max_depth=5, gamma=0, subsample=0.9, colsample_bytree=0.5)
29.    # 训练学习
30.    xgboost.fit(X_train, y_train)
31. 
32. 
33.    # 预测及 AUC 评测
34.    y_pred_test = xgboost.predict_proba(X_test)[:, 1]
35.    xgb_test_auc = roc_auc_score(y_test, y_pred_test)
36.    print('xgboost test auc: %.5f' % xgb_test_auc)
37. 
38.    # xgboost 编码原有特征
39.    X_train_leaves = xgboost.apply(X_train)
40.    X_test_leaves = xgboost.apply(X_test)
41.    # 训练样本个数
42.    train_rows = X_train_leaves.shape[0]
43.    # 合并编码后的训练数据和测试数据
44.    X_leaves = np.concatenate((X_train_leaves, X_test_leaves), axis=0)
45.    X_leaves = X_leaves.astype(np.int32)
46. 
47.    (rows, cols) = X_leaves.shape
48. 
49.    # 记录每棵树的编码区间
50.    cum_count = np.zeros((1, cols), dtype=np.int32)
51. 
52.    for j in range(cols):
53.        if j == 0:
54.            cum_count[0][j] = len(np.unique(X_leaves[:, j]))
55.        else:
56.            cum_count[0][j] = len(np.unique(X_leaves[:, j])) + cum_count[0][j-1]
57. 
58.    print('Transform features genenrated by xgboost...')
59.    # 对所有特征进行 ont-hot 编码,注释部分是直接使用 onehot 函数,结果输出保证是 libsvm 格式也可以使用
60.    #sklearn 中的 dump_svmlight_file 操作,这个文件代码是参考别人的代码,这些点都是可以优化的。
61. 
62.    # onehot=OneHotEncoder()
63.    # onehot.fit(X_leaves)
64.    # x_leaves_encode=onehot.transform(X_leaves)
65.    for j in range(cols):
66.        keyMapDict = {}
67.        if j == 0:
68.            initial_index = 1
69.        else:
70.            initial_index = cum_count[0][j-1]+1
71.        for i in range(rows):
72.            if X_leaves[i, j] not in keyMapDict:
73.                keyMapDict[X_leaves[i, j]] = initial_index
74.                X_leaves[i, j] = initial_index
75.                initial_index = initial_index + 1
76.            else:
77.                X_leaves[i, j] = keyMapDict[X_leaves[i, j]]
78. 
79.    # 基于编码后的特征,将特征处理为 libsvm 格式且写入文件
80.    print('Write xgboost learned features to file ...')
81.    xgbFeatureLibsvm = open('xgb_feature_libsvm', 'w')
82.    for i in range(rows):
83.        if i < train_rows:
84.            xgbFeatureLibsvm.write(str(y_train[i]))
85.        else:
86.            xgbFeatureLibsvm.write(str(y_test[i-train_rows]))
87.        for j in range(cols):
88.            xgbFeatureLibsvm.write(' '+str(X_leaves[i, j])+':1.0')
89.        xgbFeatureLibsvm.write('\n')
90.    xgbFeatureLibsvm.close()
91. 
92. 
93.def xgboost_lr_train(xgbfeaturefile, origin_libsvm_file):
94. 
95.    # load xgboost 特征编码后的样本数据
96.    X_xg_all, y_xg_all = load_svmlight_file(xgbfeaturefile)
97.    X_train, X_test, y_train, y_test = train_test_split(X_xg_all, y_xg_all, test_size = 0.3, random_state = 42)
98. 
99.    # load 原始样本数据
100.    X_all, y_all = load_svmlight_file(origin_libsvm_file)
101.    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)
102. 
103. 
104.    # lr 对原始特征样本模型训练
105.    lr = LogisticRegression(n_jobs=-1, C=0.1, penalty='l1')
106.    lr.fit(X_train_origin, y_train_origin)
107.    joblib.dump(lr, 'lr_orgin.m')
108.    # 预测及 AUC 评测
109.    y_pred_test = lr.predict_proba(X_test_origin)[:, 1]
110.    lr_test_auc = roc_auc_score(y_test_origin, y_pred_test)
111.    print('基于原有特征的 LR AUC: %.5f' % lr_test_auc)
112. 
113.    # lr 对 load xgboost 特征编码后的样本模型训练
114.    lr = LogisticRegression(n_jobs=-1, C=0.1, penalty='l1')
115.    lr.fit(X_train, y_train)
116.    joblib.dump(lr, 'lr_xgb.m')
117.    # 预测及 AUC 评测
118.    y_pred_test = lr.predict_proba(X_test)[:, 1]
119.    lr_test_auc = roc_auc_score(y_test, y_pred_test)
120.    print('基于 Xgboost 特征编码后的 LR AUC: %.5f' % lr_test_auc)
121. 
122.    # 基于原始特征组合 xgboost 编码后的特征
123.    X_train_ext = hstack([X_train_origin, X_train])
124.    del(X_train)
125.    del(X_train_origin)
126.    X_test_ext = hstack([X_test_origin, X_test])
127.    del(X_test)
128.    del(X_test_origin)
129. 
130.    # lr 对组合后的新特征的样本进行模型训练
131.    lr = LogisticRegression(n_jobs=-1, C=0.1, penalty='l1')
132.    lr.fit(X_train_ext, y_train)
133.    joblib.dump(lr, 'lr_ext.m')
134.    # 预测及 AUC 评测
135.    y_pred_test = lr.predict_proba(X_test_ext)[:, 1]
136.    lr_test_auc = roc_auc_score(y_test, y_pred_test)
137.    print('基于组合特征的 LR AUC: %.5f' % lr_test_auc)
138. 
139.if __name__ == '__main__':
140.    xgb_feature_encode("/Users/leiyang/xgboost/demo/data/agaricus.txt.train")
141.    xgboost_lr_train("xgb_feature_libsvm","/Users/leiyang/xgboost/demo/data/agaricus.txt.train")
142. 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值