一、介绍
(一)数据介绍
训练数据
- 2018-02-01到2018-04-15用户对商品的行为、评价、用户数据。
预测数据
- 2018-04-16 到 2018-04-22 预测用户对哪些品类和店铺有购买。
原始数据
表名 数量 内容 user 160w 用户信息 action 3721w 用户-商品行为 comment 177w 商品的评论 shop 1w 店铺信息 product 35w 商品信息 数据概况
- 2月份的数据异常,由于春节,全部舍弃
行为 数量 内容 type=2 219w 大概1/20 sku_id(type=2) 12w 购买的商品 测试集训练集
train test new user 153w 16w 6w user_cate 464w 17w 12w user_cate_shop 1390w 17w 14w user_sku 2214w 18w 16w
(二)评价指标
- 用户-品类
- 用户-品类-店铺
- score=0.4F11+0.6F12
精确率和召回率:
其中:Precise为准确率,Recall为召回率; F11 是label=1或0的F1值,F12 是pred=1或0的F1值。
二、探索阶段
思考一:
是不是有的用户只浏览不买东西,那这些用户就几乎不可能买东西,可删。
- 不是,160w中所有用户都有过下单行为。
思考二:
最后一周加购物车的是不是很可能买?
- 线上结果不太好。
三、问题分析
二分类:
问题难点
- 时序分类问题和很多传统的问题最大的不同之处在于,没有标准的训练集也没有标准的测试集,这些都需要自己构建。最简单的构建方案是枚举用户,品类和店铺,但是不可行。
- 启发式构建候选集,假设用户未来7天购买的都是之前有过交互行为的品类和店铺。
把问题看作二分类问题
- 对于<user, cate, shop>,预测购买与否
数据集划分:
把2018-04-09到2018-04-15的数据用来做标签。
特征工程:
- 用户:基本,action,actionRatio,lastTime,循环周期,重复购买率,下了几单,浏览了几次。
- 品类:action,actionRatio,周期,复购率,下了几单,浏览了几次。
- 店铺:基本,评论数,好评率,差评率,action,actionRatio,循环周期,重复购买率,下了几单,浏览了几次。
- 用户-品类:action,actionRatio,lastTime,周期,排序,排序2,去掉已经买过的浏览次数。
- 用户-店铺:action,actionRatio,lastTime,周期,排序,排序2,去掉已经买过的浏览次数。
- 店铺-品类:
- 用户-品类-店铺:action,actionRatio,lastTime,周期,排序,排序2,去掉已经买过的浏览次数。
- 刚开始是只用了基本的特征,还有action,actionRatio,线上0.02
- 加入循环周期,复购率,sessionID,排序,去掉购买排序,去掉购买的浏览次数,线上0.035
- 加入时间窗口,1,3,5,7,0.041
- 把排序,去掉购买排序,去掉购买的浏览次数,sessionID,这些比较好的特征放到时间窗,线上0.05。
- 模型融合,0.051
- 尝试过滚动时间轴构建训练集和测试集,通过将几个滚动构建的训练集进行拼接,第一周训练集,第二周打label,第二周训练集,第三周打label。但是结果不好,可能是因为一周太久了,用了太久之前的数据,可能滚动时间轴的时候一天一天比较好。
四、专业问题
(一)XGB参数
通用参数
booster
:gbtree和gblinearsilent
:1(不输出)nthread
:-1(使用所有线程)Booster参数
n_estimator
:num_boosting_rounds最大的树个数,最大迭代次数。learning_rate
:eta,默认0.3。gamma
:默认0,节点分裂所需的最小损失函数下降值。subsample
:默认1。对于每棵树,行采样比例。过小导致欠拟合。colsample_bytree
:默认1,一般0.8左右。每棵树列采样比例。colsample_bylevel
:默认1,每棵树每次节点分裂列采样比例。max_depth
: 系统默认值为6,树的最大深度。max_delta_step
:默认0,限制每棵树权重改变的最大步长,类不平衡,对逻辑回归很有帮助。lambda
:默认0,权重的L2正则化项。alpha
:默认0,权重的L1正则化项。scale_pos_weight
:默认1,类不平衡时,可使算法更快收敛,设置为正负样本比。学习目标参数
objective
:
reg:linear– 线性回归
reg:logistic – 逻辑回归
binary:logistic – 二分类逻辑回归,输出为概率
binary:logitraw – 二分类逻辑回归,输出的结果为wTx
count:poisson – 计数问题的poisson回归,输出结果为poisson分布
multi:softmax – 使用softmax目标函数做多分类,需设置num_class
multi:softprob – 如同softmax,输出每个数据分为每个类的概率。eval_metric
:通过目标函数选择
rmse: 均方根误差
mae: 平均绝对值误差
logloss: negative log-likelihood
error: 二分类错误率,阈值0.5
error@t: 不同的划分阈值可以通过 ‘t’进行设置
merror: 多分类错误率
mlogloss: 多分类log损失
auc: 曲线下的面积
ndcg: Normalized Discounted Cumulative Gain
map: 平均正确率
(二)调参过程
- 选择较大
learning_rate
0.1,网格搜索找到最佳迭代次数n_estimator
,先大范围大粒度,然后小范围,小粒度。- 调
min_child_weight
和max_depth
,因为影响较大- 调
gamma
,最小损失函数下降值- 调
subsample
和colsample_bytree
- 调正则项
reg_alpha
和reg_lambda
- 调低
learning_rate
import xgboost as xgb
from xgboost.sklearn import XGBClassifier
from sklearn import cross_validation, metrics
from sklearn.grid_search import GridSearchCV
parameters = {
'max_depth': [5, 10, 15, 20, 25],
'learning_rate': [0.01, 0.02, 0.05, 0.1, 0.15],
'n_estimators': [500, 1000, 2000, 3000, 5000],
'min_child_weight': [0, 2, 5, 10, 20],
'max_delta_step': [0, 0.2, 0.6, 1, 2],
'subsample': [0.6, 0.7, 0.8, 0.85, 0.95],
'colsample_bytree': [0.5, 0.6, 0.7, 0.8, 0.9],
'reg_alpha': [0, 0.25, 0.5, 0.75, 1],
'reg_lambda': [0.2, 0.4, 0.6, 0.8, 1],
'scale_pos_weight': [0.2, 0.4, 0.6, 0.8, 1]
}
xlf = xgb.XGBClassifier(max_depth=10,
learning_rate=0.01,
n_estimators=2000,
silent=True,
objective='binary:logistic',
nthread=-1,
gamma=0,
min_child_weight=1,
max_delta_step=0,
subsample=0.85,
colsample_bytree=0.7,
colsample_bylevel=1,
reg_alpha=0,
reg_lambda=1,
scale_pos_weight=1,
seed=1440,
missing=None)
gsearch = GridSearchCV(xlf, param_grid=parameters, scoring='accuracy', cv=3)
gsearch.fit(train_x, train_y)
print("Best score: %0.3f" % gsearch.best_score_)
print("Best parameters set:")
best_parameters = gsearch.best_estimator_.get_params()
for param_name in sorted(parameters.keys()):
print("\t%s: %r" % (param_name, best_parameters[param_name]))
(三)处理不平衡
大概70:1,XGB中有
scale_pos_weight
,可以快速收敛,没有其他特殊处理,因为不知道正负例比例,也不知道最终提交多少合适,都是根据输出的概率调,只要概率能保证正例的概率比负例大即可。
(四)特征选择
有filter,wrapper,embedded三种方法,用了embedded中基于树模型的特征选择方法。
from sklearn.feature_select import SelectFromModel
各种树模型也可以直接输出feature_importance_
(五)模型融合
stacking最终线性融合最好
- 线性融合
- 前2.3w取交集,得到约2w
- 1.7w取并集,得到约2w
- stacking
- 对于Model1,假设training set包含10000行,testing set包含2500行,每一次的交叉验证中training data是8000行,testing data是2000行
- 每一次的交叉验证包含三个过程:
1)基于8000行训练模型
2)预测2000行,记为a1
3)预测2500行,记为b1- 5折交叉验证,生成5列2000行的a1-a5,和5列2500行的b1-b5。
- a1-a5拼凑起来,形成10000行1列,记为A1。b1-b5每行求平均,得到2500行1列,记为B1
- Model1-Model5:得到A1-A5,B1-B5
- training data:A1-A5,10000行5列
testing data:B1-B5,2500行5列
(六)GBDT、XGB、LGB区别
RF与GBDT之间的区别与联系?
- 相同点:都是由多棵树组成,最终的结果都是由多棵树一起决定。
- 不同点:
随机森林:分类树&回归树,GBDT:回归树
随机森林:并行,GBDT:串行
随机森林:多数表决,GBDT:累加求和
随机森林:异常值不敏感,GBDT:异常值比较敏感
随机森林:减少方差,GBDT:减少偏差
随机森林:不需要归一化,GBDT需要归一化???
【GBDT优缺点】
- 优点
预测阶段,可并行计算。
在分布稠密的数据集上,泛化能力和表达能力都很好。
采用决策树作为弱分类器,较好的解释性和鲁棒性,
能自动发现特征间的高阶关系。- 局限性
在高维稀疏的数据集上,表现不如SVM或神经网络。
在处理文本分类问题上,表现不够好。
训练过程需要串行训练。
【GBDT和XGBoost比较】
- GBDT是机器学习算法,XGBoost是该算法的工程实现。
- 在使用CART作为基分类器时,XGBoost显式地加入了正则项,和树叶子结点个数和叶节点预测值有关。
- GBDT只使用了一阶导,XGBoost对损失函数二阶泰勒展开,同时使用一阶导和二阶导。
- GBDT采用CART作为基分类器,XGBoost支持多种类型的基分类器,比如线性分类器。
- GBDT在每轮迭代时使用全部的数据,XGBoost支持对数据进行采样。
- GBDT没有对缺失值进行处理,XGBoost能自动学习出缺失值的处理策略。当样本的第i个特征值缺失时,XGBoost将该样本分别划分到左结点和右结点,然后计算其增益,哪个大就划分到哪边。
【为什么用泰勒展开】
- 使用一阶和二阶偏导,二阶导有利于梯度下降的更快更准。
- 可以在不选定损失函数具体形式的情况下,仅仅依靠输入数据的值就可以进行叶子分裂优化计算,本质上也就把损失函数的选取和模型算法优化/参数选择分开了。
- 这种去耦合增加了xgboost的适用性,使得它按需选取损失函数,可以用于分类,也可以用于回归。
【XGBoost和LightBGM比较】
- 切分算法(切分点的选取)
XGBoost:pre-sorted算法。
对所有特征都按照特征的数值进行预排序;然后遍历分割点找到最佳分割点;将数据分裂成左右子节点。优点:能够更精确的找到数据分隔点。缺点:空间时间复杂度高。
LightGBM:histogram算法。
先把连续的浮点特征值离散化成k个整数,同时构造一个宽度为k的直方图。在直方图中遍历,寻找最优分割点。优点:占用的内存更低,只保存特征离散化后的值,1/8,降低了计算的代价。缺点:牺牲了精度。- 决策树生长策略上
XGBoost:带深度限制的level-wise生长策略,分裂的不一定是最优的。
LightGBM:leaf-wise生长策略,每次从所有叶子中找到最优分裂,容易生长出比较深的决策树,产生过拟合。- histogram 做差加速
一个叶子的直方图可以由它的父亲节点的直方图与它兄弟的直方图做差得到。
网友评论