XGboost_增量学习
Xgboost 之增量学习
1. 说明
当我们的训练数据非常多,并且还在不断增加时,每次都用全量训练,数据过多,时间过长,此时就可以使用增量训练:用新增的数据微调校正模型。
2. 全量与增量的差异
在使用增量训练时,最关心的问题是:全量和增量的差别,从而确定增量训练的使用场景。
假设有 200 条数据,第一次训练 150 条,第二次训练 50 条,和直接用 200 条训练的差异在于:在第二次训练 50 条时,前 150 条数据已经不存在了,模型更拟合于后面的数据。如果我们定期增量训练,那么离当前时间越近的数据对模型影响越大,这也是我们想要的结果。但如果最后一批数据质量非常差,就可能覆盖之前的正确实例的训练结果,把模型带偏。
同理,如果我们按时间把数据分成几部分,然后按从早到晚的顺序多次训练模型,每个模型在上一个模型基础上训练,也间接地参加了后期实例的权重。
Xgboost 提供两种增量训练的方式,一种是在当前迭代树的基础上增加新树,原树不变;另一种是当前迭代树结构不变,重新计算叶节点权重,同时也可增加新树。
对于已存在的决策树,早期训练的实例决定了模型的结构(选择哪些特征及分裂点),后期的实例决定最终的结果(叶节点的权重和新加入的树)。
综上,两个重点:第一,模型训练了一半,突然换了一批完全不同的数据继续训练,早期数据不再能再校正模型;第二,树一旦形成,结构就不再变化,后续的训练只能增加新树和重新计算前树的节点权重。
我觉得,还是尽量用全量数据训练,如果数据太多,必须增量时,尽量保证增量数据的质量和数量(均匀分布),以免带偏模型。
3. 例程
xgboost 源码中有增量训练的例程:tests/python/test_training_continuation.py,其中核心部分稍做修改如下:
1 | # -*- coding: utf-8 -*- |
4. 分析
训练函数 train() 中有个参数 xgb_model,可填写旧模型路径,或者模型指针,指定该参数后,新模型在旧模型的基础上训练。
从代码上看,增量训练的逻辑主要在 python 层面,和普通的训练模型比,只是在 c++ 底层实现了用旧模型填充 learner,而非初始化 learner。
回想一下前篇讨论过的训练过程:代入实例预测 ->对比预测结果和实际结果差异(误差函数)及误差方向(误差函数导数)->添加新决策树改进模型。继续训练也是如此。
从上面代码的输出结果可以看到,第一次 dump 的决策树是三棵,第二次 dump 出十棵(第一次三棵加第二次七棵)其中的前三棵与之前完全一样。就是说增量训练后,原来模型中的所有树都没变,只是在后面追加了更多的树。
如果在 params 中设置’process_type’:’update’,’update’:’refresh,’refresh_leaf’:True,则前三棵树结构不变,叶节点权重改变,最终结果一共七棵树(更新前三棵,新建后四棵)。