前两篇完成了特征工程的相关工作:加入用户的统计特征,分析文本信息内容,并作为新特征加入了数据集。
本篇我们来看看算法,实战微博互动预测(后简称本例)的评估算法如下:
公式中f代表转发,c代表评论,l代表赞,p代表预测,r代表真实值;deviation是真实值与预测值的偏差,具体公式如下:
precision是准确率,根据偏差算出:
sig为符号函数,当x>0时sig(x)=1,当x<=0时,sig(x)为0。Counti为每篇的反馈总数,当Counti>100时,以按100计算。
与大多数评估算法不同,本例中每个实例有不同权重,反馈越多实例权重越大。而我们常用的算法比如GBDT是根据误差迭代改进的,默认情况下各实例权重是一样的,这块儿需要单独处理一下。
具体算法还是使用xgboost库,之前看到的大多数关于xgboost的文章,要么是讲数学原理,要么是参数的中文说明,xgboost似乎还是一个黑盒,下面就结合具体问题看看xgboost的使用。
xgboost提供两种调用方式,一种是自身接口,一种是类似sklearn的接口,建议使用自身接口,因为很多重要功能,如存取模型,评估功能都无法通过sklearn接口调用。
在资料,示例和文档都不多的情况下,建议下载源码,学习其中的example,demo,test中的使用方法,以及直接分析源码的调用流程。
一般使用xgboost直接用pip install安装即可,下载源码主要以学习为主。
下载使用命令:
git clone https://github.com/dmlc/xgboost
xgboost主要是c语言实现的,本例中主要通过python接口调用,在demo目录中可以看到示例。
xgboost是一种迭代改进的算法,它每次给错误分类的实例增加权重,并进入下一次迭代。因此需要指定迭代次数和每次权重改进的程度(学习率)。
迭代次数通过num_boost_round设置,次数越多,花费时间越长,xgboost除了可以设置固定迭代次数以外,还可以根据评估,判断如果n次不再改进,则停止迭代(具体见eval部分)。
学习率通过eta设置,它是每次迭代之后对原模型的改进程度,学习率越高收敛越快,但也可能因为粒度太大,错过极值点。
调参方法是先粗调再细调:一开始将学习率设大一点,比如0.1-0.3;次数设少一点,比如50次,即能快速改善模型又不花太长时间。后面细调时再变小学习率,增加迭代次数。
eval系列参数用于评估模型的状态,可以在每次迭代之后给模型打分,它本身与模型如何计算无关(无论它设成什么,最终模型都不变),只是评估当前模型好坏。这个功能非常重要,比如:有时候会看到在迭代过程中训练集评分提高,而测试集评分下降,一般就是过拟合了。使用它还可以控制当模型不再改进时,停止迭代(具体通过early_stopping_rounds设置)。
1) evals设置估计数据
evals可设置训练集和测试集,在每次迭代后用训练集和测试集代入模型,并给预测结果评分。
2) eval_metric现成的评估函数
可以设置rmse,logloss,error,merror,mlogloss,auc,ndcg,map等xgb自带的评估函数。
3) feval自定义评估函数
本例就需要自定义估伻函数,使用feval方法实现。它和梯度下降算法无法,主要用于显示,并判断何时终止迭代。最好别写太复杂,否则会延长计算时间。
4) early_stopping_rounds自动停止迭代
通过early_stopping_rounds设置,如果在n轮内正确率没有提升,则退出迭代,具体根据evals给出的数据判断,若其中包含多组数据,则取最后一个。
如果设置了early_stopping_rounds,模型会生成三个属性,best_score, best_iteration, bst.best_ntree_limit,以便下次选择最合适的迭代次数。
5) verbose_eval输出评估信息
如果设置为True输出评估信息,设置为数字,如5则每5次评估输出一次。
1) 设置scale_pos_weight
有时会遇到样本不均衡的问题,比如正例占99%,反例占1%,那么如果预测为全正例或者随机抽机,正确率也占99%。此时可使用scale_pos_weight提高反例权重,默认为1,不增加权重。
2) DMatrix设置weight
使用xgb自带的调用接口 (非sklearn接口),需要把数据转成DMatrix格式,如果想给不同实例分配不同权重,可以转换时使用weight参数,它传入与实例个数等长的数组,数组中每个数对应一个实例的权重,在xgb每次迭代后调整权重时也会将它计算在内。
之前文章中说过Xgboost与sklearn的GridSearchCV结合调参的方法。Xgboost内部的cv()函数提供了交叉验证的功能,也可用于调参。网上例程不多,具体可参见源码中的:demo/guide-python/cross_validation.py
Xgboost可以处理二分类,多分类,回归问题。处理不同问题,主要的区别在于指定不同的误差函数,xgboost会根据不同误差函数计算的结果调整权重进行下一次迭代。通过参数objective可设置xgb自带的误差函数:回归一般用reg:xxx(如reg:linear),二分类用binary:xxx(如binary:logistic),多分类用multi:xxx(如multi:softmax)。误差函数的功能是通过训练集的label和预测值计算一阶梯度,二阶梯度,在源码中可以看到它们是如何实现的(C语言部分)。在调用train()训练时,也可以用参数obj自定义误差函数。
1) 评估
本例的评分算法和普通算法差别很大,因此使用feval自定义了评估函数,效果还不错,就是计算时间比较长。所以有时会把它暂时注释掉。
2) 误差函数
本例是一个回归问题,因此使用了reg:linear,线性计算误差函数,它的实现非常简单,一阶梯度是预测值与标签值相减,二阶梯度是1.0。
3) 关于权重
本题要求反馈多的实例在计算结果时拥有更大的权重,一开始的想法是给这些实例加权,于是使用了在DMatrix转换时设置weight,后来又自定义了误差函数。但效果都不好,正确率不升反降。我觉得可能由于这是一个回归问题,回归的权重算法是:偏差越大,权重越大,以促进快速收敛。一般反馈多的实例偏差都大,如果再把权重计算再内,就重复加权了。