实战微博互动预测之三 _xgboost 答疑解惑

1. 说明

  前两篇完成了特征工程的相关工作:加入用户的统计特征,分析文本信息内容,并作为新特征加入了数据集。

本篇我们来看看算法,实战微博互动预测(后简称本例)的评估算法如下:

  公式中 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 的使用。

2. xgboost 注意事项

 xgboost 提供两种调用方式,一种是自身接口,一种是类似 sklearn 的接口,建议使用自身接口,因为很多重要功能,如存取模型,评估功能都无法通过 sklearn 接口调用。

  在资料,示例和文档都不多的情况下,建议下载源码,学习其中的 example,demo,test 中的使用方法,以及直接分析源码的调用流程。

3. xgboost 源码

  一般使用 xgboost 直接用 pip install 安装即可,下载源码主要以学习为主。

  下载使用命令:

1
git clone https://github.com/dmlc/xgboost

 xgboost 主要是 c 语言实现的,本例中主要通过 python 接口调用,在 demo 目录中可以看到示例。

4. xgboost 学习率与迭代次数

 xgboost 是一种迭代改进的算法,它每次给错误分类的实例增加权重,并进入下一次迭代。因此需要指定迭代次数和每次权重改进的程度(学习率)。

  迭代次数通过 num_boost_round 设置,次数越多,花费时间越长,xgboost 除了可以设置固定迭代次数以外,还可以根据评估,判断如果 n 次不再改进,则停止迭代(具体见 eval 部分)。

  学习率通过 eta 设置,它是每次迭代之后对原模型的改进程度,学习率越高收敛越快,但也可能因为粒度太大,错过极值点。

调参方法是先粗调再细调:一开始将学习率设大一点,比如 0.1-0.3;次数设少一点,比如 50 次,即能快速改善模型又不花太长时间。后面细调时再变小学习率,增加迭代次数。

5. xgboost 的 eval 系列参数

 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 次评估输出一次。

6. 样本不均衡问题

1) 设置 scale_pos_weight

  有时会遇到样本不均衡的问题,比如正例占 99%,反例占 1%,那么如果预测为全正例或者随机抽机,正确率也占 99%。此时可使用 scale_pos_weight 提高反例权重,默认为 1,不增加权重。

2) DMatrix 设置 weight

  使用 xgb 自带的调用接口 (非 sklearn 接口),需要把数据转成 DMatrix 格式,如果想给不同实例分配不同权重,可以转换时使用 weight 参数,它传入与实例个数等长的数组,数组中每个数对应一个实例的权重,在 xgb 每次迭代后调整权重时也会将它计算在内。

7. Xgboost 自带的调参方法

  之前文章中说过 Xgboost 与 sklearn 的 GridSearchCV 结合调参的方法。Xgboost 内部的 cv() 函数提供了交叉验证的功能,也可用于调参。网上例程不多,具体可参见源码中的:demo/guide-python/cross_validation.py

8. Xgboost 的误差函数

 Xgboost 可以处理二分类,多分类,回归问题。处理不同问题,主要的区别在于指定不同的误差函数,xgboost 会根据不同误差函数计算的结果调整权重进行下一次迭代。通过参数 objective 可设置 xgb 自带的误差函数:回归一般用 reg:xxx(如 reg:linear),二分类用 binary:xxx(如 binary:logistic),多分类用 multi:xxx(如 multi:softmax)。误差函数的功能是通过训练集的 label 和预测值计算一阶梯度,二阶梯度,在源码中可以看到它们是如何实现的(C 语言部分)。在调用 train() 训练时,也可以用参数 obj 自定义误差函数。

9. 本例中 xgb 的使用

1) 评估

  本例的评分算法和普通算法差别很大,因此使用 feval 自定义了评估函数,效果还不错,就是计算时间比较长。所以有时会把它暂时注释掉。

2) 误差函数

  本例是一个回归问题,因此使用了 reg:linear,线性计算误差函数,它的实现非常简单,一阶梯度是预测值与标签值相减,二阶梯度是 1.0。

3) 关于权重

  本题要求反馈多的实例在计算结果时拥有更大的权重,一开始的想法是给这些实例加权,于是使用了在 DMatrix 转换时设置 weight,后来又自定义了误差函数。但效果都不好,正确率不升反降。我觉得可能由于这是一个回归问题,回归的权重算法是:偏差越大,权重越大,以促进快速收敛。一般反馈多的实例偏差都大,如果再把权重计算再内,就重复加权了。