【2023.8.8 学习日志】XGBoost方法、预测共享单车租用量的流程

参考文献:Dataworkshop

XGBoost

全称
extreme gradient boost
regularized gradient boost
它用于监督学习问题,比如:分类、回归和排序。

XGBoost方法详解-知乎
在经典的决策树算法中,ID3的目标函数是基于“信息熵”,CART的目标函数是基于“GINI系数”,
XGBoost的目标函数引入了“偏差”这个变量。
在这里插入图片描述
GBDT与XGBoost之间的区别是:前者使用梯度下降法(所以只有一次导数)求参数,后者使用牛顿法(使用到了损失函数的二次导数);

如何高效地生成一棵决策树?
在XGBoost中,利用贪心算法生成一棵树,从而提高了效率。
贪心算法:每一步都选择当前最优,从而达到全局最优解。
在决策树生成的背景下,其表述为“保证每一次节点的分裂产生的新树,都是目标函数最小的”。

如何判断是否应该分裂一个节点?
分裂后的树的目标函数值小于分裂前的树的目标函数值。如果增益太小,那么做这次分裂,会带来更大的负面影响——增加模型复杂度,所以下面模型中会有个惩罚项,从而避免这种情况发生。
在这里插入图片描述
上面选择了最佳特特征进行划分,下面要考虑对于这个最佳特征,用于划分特征输入空间的最佳特征值是什么。
XGBoost采用加权分位法来做。

对选定最佳分裂特征的特征值进行“重要性”排序,根据排序的结果,选出值得尝试分裂的特征值。
特征值的重要性排名,
在我们得到了使用加权分位法的分裂点之后,在贪心算法的分裂过程中,我们就只需要对这几个分裂点进行尝试,而不需要与原先一样,对所有的特征值进行尝试。这大大减少了算法的开销。

基于加权分位法,我们有两种策略进行分裂点的计算:1、全局策略;2、局部策略
全局策略:生成树之前,就计算好了所有特征的分裂点,如此一来,开销比较低;缺点是如果分裂点比较少,准确率是不够的;
局部策略:因地制宜,在节点处,根据该节点所包含的样本计算所有特征的分裂点。每个节点所包含的样本不同,这些样本的特征值也是不同的。对每个结点重新计算分裂结点,以保证准确性。优点是,分裂点数目不用太多,也能达到一定的准确率;缺点是,开销比较大。

  • 全局策略和局部策略的对比
    分裂点数目相同时,局部策略在AUC指标上优于全局策略;
    分裂点数目越多,两个策略的效果越好;
    全局策略可以通过增加分裂点的数目,达到逼近局部策略的效果。

  • 步骤

  1. 基于贪心算法进行划分,计算目标函数增益,选择该节点使用哪个特征
  2. 为了提高算法效率,使用“加权分位法”,计算分裂点,只考虑分裂点的目标函数值,而不是该特征的所有特征值。
  3. 可以选择“全局策略”或“局部策略”,计算分裂点。

XGBoost对缺失值的处理方法,
以对第k个特征为例,把第k个特征为缺失值的样本选出来;然后,对剩余样本进行划分;最后,看把缺失值全部放在“左节点”,放在“右节点”哪个增益大,就代表这个特征最好的划分。
如果训练集有缺失值,那么在训练过程中会指定这些缺失值去哪边(左边还是右边),在预测阶段测试集的缺失值也会去到那一边;
如果训练集没有缺失值,那么在预测阶段测试集中的缺失值会被默认分到左子树上(这是默认方向)。
XGBoost关于缺失值处理的小细节
XGBoost方法及其实战 - 知乎
XGBoost方法的参数调整及其含义
min_child_weight这个参数可以用来控制过拟合,当节点上的所有样本的权重和小于min_child_weight时,停止该节点的分裂,这个节点变成了叶节点。

收缩率,弱学习器的权重值,目的是防止过拟合。值越小,越减少过拟合。

在这里插入图片描述

超参数的训练,

XGBoost的缺点:
基于预排序方法的决策树算法
步骤:先对所有特征排序,找用于分裂的特征,再找一个特征上最好的分割点,然后将数据分裂成左右子节点。
优点是,能精确找到分割点;
缺点是,空间消耗很大(不仅保存数据的特征值,还保存特征排序的结果,以便于后续计算分割点);

LightGBM,
为了解决GBDT每次训练都需要所有训练数据而造成效率比较低的问题,LightGBM在传统GBDT算法上做了优化。
GBDT对同一层的叶子不加区分,带来了一些没必要的开销。实际上,很多叶子的分裂增益较低,没必要搜索和分裂。LightGBM使用了带深度限制的leaf-wise的叶子生长算法。
listGBM支持类别特征

详细代码,见jupyter文件xgboost_study2(已经附上了)

  • 数据项描述
    datetime - hourly date + timestamp
    season - 1 = spring, 2 = summer, 3 = fall, 4 = winter
    holiday - whether the day is considered a holiday
    workingday - whether the day is neither a weekend nor holiday
    weather -
    1: Clear, Few clouds, Partly cloudy, Partly cloudy
    2: Mist + Cloudy, Mist + Broken clouds, Mist + Few clouds, Mist
    3: Light Snow, Light Rain + Thunderstorm + Scattered clouds, Light Rain + Scattered clouds
    4: Heavy Rain + Ice Pallets + Thunderstorm + Mist, Snow + Fog
    temp - temperature in Celsius
    atemp - “feels like” temperature in Celsius
    humidity - relative humidity
    windspeed - wind speed
    casual - number of non-registered user rentals initiated
    registered - number of registered user rentals initiated
    count - number of total rentals

下面简要记录文件的思路

内容:使用xgboost方法,根据特征数据预测count,registered,casual等响应变量,其中count=registed+casual
首先,从 datetime数据中提取出day,hour,dayofweek,weekend等信息,作为特征;
然后,

  • 尝试了以下几种方法去预测
  1. 使用 原数据的特征 直接预测 count;
  2. 使用 原数据的特征 间接预测count:具体地,首先使用XGBoost预测registedcasual,然后,二者加和得到count的预测值;
  3. 使用 原数据的特征 间接预测count:具体地,首先使用XGBoost预测log(count),然后,取对数得到count的预测值;
  4. 使用 原数据的特征 间接预测count:具体地,首先使用XGBoost预测log(registed+1)log(casual+1)(考虑到registered,casual可能取值为0),然后,二者取对数-1,再加和,得到count的预测值;
  5. 使用 原数据的特征的衍生特征(得到的数据集train_magic) 直接预测 count;
    比较上述所有方法的relative mean square log error.
  • 与其他方法作对比
    取“relative mean square log error”为性能指标(越小越好),比较XGBoost与随机森林、Adaboost,Bagging等其他机器学习集成方法的性能。

  • 调参
    除了网格搜索调参,这个项目还展示了贝叶斯优化方法搜索超参数的使用:具体地,调用python第三方库的使用hyperopt

remark:

小心过拟合

对比:
决策树虽然可解释性比较好,但是表现比较差;
集成学习方法:将弱分类器组成成强分类器,具体地,如随机森林、提升法.

日后再补……

数据分析的流程

详细代码见文件share_bicycle_demand(已经附上了)
数据还是上面的数据,学习的材料还是源自DataWorkShop这个github主。
下面简要罗列一下原作者的分析流程和一些细节。

数据预处理

首先,用.info检查数据的类型;
然后,使用.isnull().values.sum()检查数据中有无缺失值;
数据可视化部分包括:
对比不同年份,各个小时租用量的趋势;
对比是否为工作日,各个小时租用量的趋势;
对比不同年,月租用量的趋势;(绘制了箱线图和柱形图)
对比不同年,各个小时租用量的趋势。(绘制了箱线图和柱形图)

特征工程

删除掉方差比较小的特征、使用SelectKBest,chi2,RFE等方法选择比较重要的特征。具体地,对于不同的模型,重要特征也不同。所以,要为每个模型选择它专属的重要特征。

模型的选择

这里尝试了随机森林、adaboost,梯度提升等集成学习方法,为每一个模型方法选择他们的最优特征集合,然后训练模型,并预测count指标,打印出score。
比较这几种方法的score值,得出 梯度提升方法表现比较好。

进一步的特征工程

从时间项中分离出来”是否周末“、”对应季节的平均租用量“等信息加入到模型中

间接预测目标值

对预测值count,registered,casual等,先取对数,得到count_log,reg_log,casual_log。
然后,分别以count_log,reg_log,casual_log为训练目标值,以X_train为训练特征,训练模型,
接着,将测试集的特征信息X_test作为输入,带入到模型中,分别得到预测值 c o u n t l o g ^ \hat{count_{log}} countlog^, r e g l o g ^ \hat{reg_{log}} reglog^, c a s u a l l o g ^ \hat{casual_{log}} casuallog^
然后,对这三个预测值分别取指数,得到预测值 c o u n t ^ \hat{count} count^, r e g ^ \hat{reg} reg^, c a s u a l ^ \hat{casual} casual^

线性组合三种集成模型得到最终结果

见’def modeling’函数

def modeling(models,data,n_folds=3): # linear combination of several ensumble models,like rondomForest,GradientBoost,XGBoost
    scores=[]
    kf=KFold(n_splits=n_folds)
    for n_fold,(train_idx,test_idx) in enumerate(kf.split(data)):
        print("n_fold: ",n_fold)
        y_pred = np.array([0.]*len(test_idx))# !! you can't write it as [0]

        for weight_for_model,feats,model in models:
            X=data[feats].values
            X_train,X_test = X[train_idx],X[test_idx]
            y_reg_train = data['registered_log'][train_idx].astype('float')
            y_cas_train = data['casual_log'][train_idx].astype('float')
            y_test=data['count'][test_idx].astype('float')

            model.fit(X_train,y_reg_train)
            y_pred_reg_log = model.predict(X_test)
            y_pred_reg=np.exp2(y_pred_reg_log)-1

            model.fit(X_train,y_cas_train)
            y_pred_cas_log = model.predict(X_test)
            y_pred_cas=np.exp2(y_pred_cas_log)-1

            y_pred+=weight_for_model*(y_pred_reg+y_pred_cas)

        score=rmsle(y_test,y_pred)
        scores.append(score)
    print("score:{0}, std-score:{1}".format(round(np.mean(scores),5),round(np.std(scores),4)))

xgb_params={'n_estimators':150,'learning_rate':0.1,'max_depth':5,'subsample':0.6,'colsample_bytree':0.8}
xgb_model = xgb.XGBRegressor(**xgb_params)

gb_params={'n_estimators':150,'max_depth':5,'random_state':0,'min_samples_leaf':10,'learning_rate':0.1,'subsample':0.7,'loss':'squared_error'}
gb_model=GradientBoostingRegressor(**gb_params)

rf_params={'n_estimators':1000,'max_depth':15,'random_state':0,'random_state':0,'min_samples_split':5,'n_jobs':-1}
rf_model=RandomForestRegressor(**rf_params)

xgb_feats =  ['weather', 'temp', 'atemp', 'humidity', 'windspeed', 'holiday', 'workingday', 'season','hour', 'dayofweek', 'year']
gb_feats =  ['weather', 'temp', 'atemp', 'humidity', 'windspeed', 'holiday', 'workingday', 'season','hour', 'dayofweek', 'year']
rf_feats = ['weather', 'temp', 'atemp', 'windspeed','workingday', 'season', 'holiday', 'hour', 'dayofweek',  'rush_hour', 'peak']

models=[
    (0.8*0.7,xgb_feats,xgb_model),
    (0.8*0.3,gb_feats,gb_model),
    (0.2,rf_feats,rf_model)
]

modeling(models,df_all[~df_all['is_test']])#trainData from df_all       
            
            
                          
        

代码二:贝叶斯优化调参

预测目标,选 “count”列
Final result: {
‘target’: -150.1472393766906,
‘params’: {‘colsample_bytree’: 0.876888634776859, ‘max_depth’: 7.698877185131134, ‘min_child_weight’: 21.89595721880947, ‘subsample’: 0.9967855924737787}}

D:\PyCharm2020\myven2v\Scripts\python.exe D:/PyCharm2020/myven2v/xgboost-lightgbm-hyperparameter-tuning-master/bayesHyper_Study4.py
Mem. usage decreases to  0.19Mb, (71.9% reduction)
|   iter    |  target   | colsam... | max_depth | min_ch... | subsample |
-------------------------------------------------------------------------
[0]	train-rmse:261.13659	test-rmse:266.44075
[200]	train-rmse:170.31282	test-rmse:176.45617
.....
[600]	train-rmse:142.63274	test-rmse:144.69786
[800]	train-rmse:140.60119	test-rmse:144.21686
[999]	train-rmse:139.24480	test-rmse:144.12899
| 22        | -150.2    | 0.9441    | 8.174     | 25.37     | 0.793     |
=========================================================================
0.0 hours 4.0 minutes 12.809617000000003 seconds
Final result:  {'target': -150.03965155427224, 'params': {'colsample_bytree': 0.9653678768627341, 'max_depth': 6.021691581706388, 'min_child_weight': 24.016201688956542, 'subsample': 0.7312737130360377}}

Process finished with exit code 0




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值