XGBoost号称“比赛夺冠的必备大杀器”,横扫机器学习Kaggle、天池、DataCastle、Kesci等国内外数据竞赛罕逢敌手,堪称机器学习算法中的王者,业界使用者众多!
在涉及非结构化数据(图像、文本等)的预测问题中,人工神经网络显著优于所有其他算法或框架。但当涉及到中小型结构/表格数据时,基于决策树的算法现在被认为是最佳方法。而基于决策树算法中最惊艳的,非XGBoost莫属了。
XGBoost最初由陈天奇开发。陈天奇是华盛顿大学计算机系博士生,研究方向为大规模机器学习。他曾获得KDD CUP 2012 Track 1第一名,并开发了SVDFeature,XGBoost,cxxnet等著名机器学习工具,是Distributed (Deep) Machine Learning Common的发起人之一。
Xgboost有两大类接口:Xgboost原生接口 和sklearn接口,并且Xgboost能够实现分类与回归两种任务。下面将分享对其中回归任务工控实践,也就是XGBoost和Sklearn接口做以解析。
XGBoost算法可以给预测模型带来能力的提升。当我们对其表现有更多了解的时候,我们会发现他有如下优势:
正则化
XGBoost在代价函数里加入了正则项,用于控制模型的复杂度。正则项里包含了树的叶子节点个数,每个叶子节点上输出的score的L2模的平方和。从Bias-variance tradeoff角度来讲,正则项降低了模型的variance,使学习出来的模型更加简单,防止过拟合,这也是Xgboost优于传统GBDT的一个特征
并行处理
XGBoost的并行式在特征粒度上的,也就是说每一颗树的构造都依赖于前一颗树。一般来说,决策树的学习最耗时的一个步骤就是对特征的值进行排序(因为要确定最佳分割点),在训练之前,预先对数据进行了排序,然后保存为block结构,后面的迭代中重复使用这个结构,大大减小计算量。这个block结构也使得并行成为了可能,在进行节点的分裂的时候,需要计算每个特征的增益,最终选增益最大的那个特征去做分裂,那么各个特征的增益计算就可以开多线程进行。
灵活性
XGBoost支持用户自定义目标函数和评估函数,只要目标函数二阶可导就行。它对模型增加了一个全新的维度,所以我们的处理不会受到任何限制。
缺失值处理
对于特征的值有缺失的样本,XGBoost可以自动学习出他的分裂方向。XGBoost内置处理缺失值的规则。用户需要提供一个和其他样本不同的值,然后把它作为一个参数穿进去,以此来作为缺失值的取值。XGBoost在不同节点遇到缺失值时采用不同的处理方法,并且会学习未来遇到缺失值时的处理方法。
剪枝
XGBoost先从顶到底建立所有可以建立的子树,再从底到顶反向机芯剪枝,比起GBM,这样不容易陷入局部最优解
内置交叉验证
XGBoost允许在每一轮Boosting迭代中使用交叉验证。因此可以方便的获得最优Boosting迭代次数,而GBM使用网格搜索,只能检测有限个值。
监控某罐体设备液位变换,每10分钟测量罐内液体容量(液位),以此回归预测某时刻,就是可能不在正常工作测量的时刻,估算某时刻液位,从整体上来说,相当于解决数据缺失问题。
通过此预测,可以相互验证罐体是否漏夜等安全报警信息,从另一个角度报警。
import xgboost as xgb
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.model_selection import cross_val_score, KFold
from sklearn.metrics import mean_squared_error
import matplotlib.pyplot as plt
from xgboost import plot_importance
from sklearn.metrics import r2_score
def model_train_reg(x_train,x_test,y_train,y_test):
params ={'learning_rate': 0.1,
'max_depth': 10, # 构建树的深度,越大越容易过拟合
'num_boost_round':2000,
'objective':'reg:squarederror', # 线性回归问题
#'objective': 'reg:linear', # 线性回归问题,早期版本的参与,将被reg:squarederror替换
'random_state': 7,
'gamma':0,
'subsample':0.8,
'colsample_bytree':0.8,
'reg_alpha':0.005,
'n_estimators' : 1000,
'eval_metric':['logloss','rmse','mae'], #分类有“auc”
'eta':0.3 #为了防止过拟合,更新过程中用到的收缩步长。eta通过缩减特征 的权重使提升计算过程更加保守。缺省值为0.3,取值范围为:[0,1]
}
dtrain = xgb.DMatrix(x_train, label=y_train)
dtest = xgb.DMatrix(x_test,label=y_test)
res = xgb.cv(params,dtrain,num_boost_round=5000,metrics='rmse',early_stopping_rounds=25)
#找到最佳迭代轮数
best_nround = res.shape[0] - 1
watchlist = [(dtrain,'train'),(dtest,'eval')]
evals_result = {}
model = xgb.train(params,dtrain,num_boost_round=best_nround,evals = watchlist,evals_result=evals_result)
y_pred=model.predict(xgb.DMatrix(x_test))
y_pred = list(map(lambda x: x if x >= 0 else 0,y_pred))
MSE = np.sqrt(sum((np.array(y_test) - np.array(y_pred)) ** 2 ) / len(y_pred) ) #均方根误差作为结果
R2 = r2_score(y_test,y_pred)
print ('MSE: %f' % MSE)
print ('r2_score: %.2f' %R2)
print('绘制训练RMSE下降趋势图')
#验证数据评估指标,与param参数,'eval_metric':['logloss','rmse','mae']相关
#验证包括训练和验证两个部分(train、eval),如上所示3个参数,则是6组数据
names = []
values = []
for e_name,e_mtrs in evals_result.items():
#print('- {}'.format(e_name))
for e_mtr_name, e_mtr_vals in e_mtrs.items():
#print(' - {}'.format(e_mtr_name))
names.append(e_name + '_' + e_mtr_name)
#print(' - {}'.format(e_mtr_vals))
values.append(e_mtr_vals)
plt.figure(12)
plt.rcParams['font.sans-serif']=['SimHei'] #显示中文
plt.grid()
plt.subplot(121)
plt.scatter(y_test,y_pred,s=20)
plt.plot([min(y_test),max(y_test)],[min(y_pred),max(y_pred)])
plt.xlabel('实际液位')
plt.ylabel('预测液位')
plt.subplot(122)
#plt.plot(values[0],label = names[0],color='green')
plt.plot(values[1],label = names[1],color='blue')
#plt.plot(values[2],label = names[2],color='coral')
plt.plot(values[3],label = names[3],color='deeppink')
plt.show()
return model
#读取Excel数据
df0 = get_DataFromExcel()
df0 = pd.concat([df0,feature_datatime(df0)],axis=1)
print(df0.dtypes)
x_train,x_test,y_train,y_test = init_train_data(df0)
model= model_train_reg(x_train,x_test,y_train,y_test)
#model.save_model('OilCanXGbLinear.model') # 保存训练模型
# 显示重要特征
plot_importance(model)
plt.show()
(1)学习过程中监控
训练过程监控输出,重点代码如下所示,Watchlist不会影响模型训练。:
watchlist = [(dtrain,'train'),(dtest,'eval')]
evals_result = {}
其中,RMSE是下降的,比较快,为什么logloss几乎不变呢,需要进一步学习研究。
(2)预测与真实值对比分析,以及RMSE下降情况
(3)特征重要程度
XGBoost的特征重要性是如何得到的?某个特征的重要性(feature score),等于它被选中为树节点分裂特征的次数的和,比如特征A在第一次迭代中(即第一棵树)被选中了1次去分裂树节点,在第二次迭代被选中2次……那么最终特征A的feature score就是 1+2+….
对于XGBoost模型评估的方法,一般采用交叉验证(cross-validation 简称cv)将数据集分为k等份,对于每一份数据集,其中k-1份用作训练集,单独的那一份用作验证集。
利用xXGBoost.cv可以找出最优的树,详见文中代码。
res = xgb.cv(params,dtrain,num_boost_round=5000,metrics='rmse',early_stopping_rounds=25)
#找到最佳迭代轮数
best_nround = res.shape[0] - 1
其中,early_stop 是在多少轮 metrics 没有变好的情况下提前结束,等于是找到了最佳的迭代轮数。
XGBoost的参数可以分为三种类型:通用参数、booster参数以及学习目标参数
From xgboost-unity, the bst: prefix is no longer needed for booster parameters. Parameter with or without bst: prefix will be equivalent(i.e. both bst:eta and eta will be valid parameter setting) .
objective [ default=reg:linear ]
定义学习任务及相应的学习目标,可选的目标函数如下:
base_score [ default=0.5 ]
the initial prediction score of all instances, global bias
eval_metric [ default according to objective ]
校验数据所需要的评价指标,不同的目标函数将会有缺省的评价指标(rmse for regression, and error for classification, mean average precision for ranking)
用户可以添加多种评价指标,对于Python用户要以list传递参数对给程序,而不是map参数list参数不会覆盖’eval_metric’
The choices are listed below:
seed [ default=0 ]
随机数的种子。缺省值为0
可以用于产生可重复的结果(每次取一样的seed即可得到相同的随机划分)
dtrain:训练的数据
num_boost_round:这是指提升迭代的次数,也就是生成多少基模型
evals:这是一个列表,用于对训练过程中进行评估列表中的元素。
形式是evals = [(dtrain,‘train’),(dval,‘val’)]或者是evals = [(dtrain,‘train’)],对于第一种情况,它使得我们可以在训练过程中观察验证集的效果
obj:自定义目的函数
feval:自定义评估函数
maximize:是否对评估函数进行最大化
early_stopping_rounds:早期停止次数
假设为100,验证集的误差迭代到一定程度在100次内不能再继续降低,就停止迭代。这要求evals 里至少有 一个元素,如果有多个,按最后一个去执行。返回的是最后的迭代次数(不是最好的)。如果early_stopping_rounds存在,则模型会生成三个属性,bst.best_score,bst.best_iteration和bst.best_ntree_limit
evals_result:字典,存储在watchlist中的元素的评估结果。
verbose_eval :(可以输入布尔型或数值型),也要求evals里至少有 一个元素。如果为True,则对evals中元素的评估结果会输出在结果中;如果输入数字,假设为5,则每隔5个迭代输出一次。
learning_rates:每一次提升的学习率的列表,
xgb_model:在训练之前用于加载的xgb model。
欢迎读者反馈指导。
参考:
[1]《Indexing and selecting data》 Pandas User Guide
[2]《Python机器学习笔记:XgBoost算法》 博客园 ,战争热诚 2019年3月
[3]《XGBoost-Python完全调参指南-参数解释篇》 CSDN博客, Will-Lin, 2016年3月
[4]《应用XGboost实现多分类模型实践》 CSDN博客 ,肖永威 ,2019年4月
[5]《XGBoost算法应用入门学习实践》 CSDN博客 , 肖永威 ,2018年6月