1024 祝大家快乐
xgboost这篇论文写得比较易懂,陈天奇大牛有科普的意思,推荐读原文,这里只是详细记录一下。
文章目录
- 1. Introduction
- 2. 提升树
- 2.1 带正则项的目标函数
- 2.2 梯度提升树
- 2.3 Shrinkage and Column Subsampling
- 3. Split Finding algorithms
- 3.1 基础的精确贪心算法
- 3.2 近似算法
- 3.3 加权分位数算法
- 3.4 Sparsity-aware Split Finding
- 4. System Design
- 4.1 Column Block for Parallel Learning
1. Introduction
比赛大杀器
本篇论文的贡献:
- 高度弹性的端到端的提升树系统
- 提出了一个有理论支撑的加权分位数算法
- 介绍了一个新颖的并行树学习的稀疏感知算法
- 提出了一种有效的缓存感知块结构,用于out-of-core树学习
2. 提升树
2.1 带正则项的目标函数
给定一个m个特征的n个样本集
将每棵树看做一个函数,K颗树集成来计算输出结果
将样本从样本空间映射到叶子的节点空间,w为每个叶子节点的权重,T为树的叶子数
可以看出,包含两部分,树的结构q和权重w,q将一个样本映射到叶子节点,w为叶子节点赋一个权重。那么可以从下图看出,一个样本的得分,是在每颗树下的叶子权重加和。为了学习每棵树,树的目标函数:
定义了一个凸的损失函数,模型的预测精度由偏差和方差共同决定,损失函数代表了模型的偏差,想要方差小则需要更简单的模型, 所以目标函数最终由损失函数L与抑制模型复杂度的正则项Ω组成。后面的为含义为树的复杂度的正则项,描述了树的复杂度,可以看到包含了树的叶子数和叶子score的模的平方和,该正则项可以最终帮助避免过拟合。
2.2 梯度提升树
第t颗树生成计算的损失函数
这里可以把到t-1的所有树的加和看做变量,把看做自变量的修正,即,二阶泰勒展开
其中为一阶导,为二阶导
t之前的树已经确定了,把常数项移除后得到
定义叶子节点j的集合,把样本空间(n个)映射到叶子空间(T个),上面的等式(3)重写下
可以看出损失是w的二次函数,则最优w的值为
带入损失函数
公式(6)用来评估树的结构q的质量,表示树的杂质(impurity)
(7)用作评估分割为和带来的收益,通过公式(6)中计算获得
2.3 Shrinkage and Column Subsampling
除了损失函数中的正则项,文中还提出了两种降低过拟合的方式–学习率和列采样。
- 学习率(xgboost中的eta)减少了每棵树的影响,为未来的树木留出空间来改进模型。
- 列采样之前被用于随机森林,通过随机性降低过拟合,根据反馈,使用列子采样比传统的行子采样更有效的防止过拟合。
3. Split Finding algorithms
3.1 基础的精确贪心算法
如何找到最好的分割点?贪心算法是列举所有特征的所有可能值,找到最佳分割点。为了有效的完成寻找,算法必须先对数据根据特征排序。
是当前可分的节点,是所有样本的二阶导的和,为所有样本的一阶导的和,对于每棵树,遍历所有的节点,根据分割后的、和、找到增益最大的分割点。
3.2 近似算法
精确的贪心算法显然不适合大规模的数据,因为它贪婪的列举了所有可能的分割点。
近似算法根据特征分布的百分位数提出候选分割点。首先将连续特征映射为候选点分割的桶,然后再遍历这些较少的分裂点来找到最佳分裂点。
分割点的候选集的构建有两种方式global和local,区别在于构建分割候选集的时间。global构建在构建树的开始构建候选集,后续不同的节点采用相同的分割候选集。local则是在每次分割后重新构建分割候选集。
可以看出,在某种程度下,近似算法的AUC都可以接近精确算法,local的方式比global需要更少的桶,因为它每次分割后重新定义候选分割集。
分割候选集的效果对比,eps是间隔参数
3.3 加权分位数算法
这里加权是加的h,也就是损失的二阶导。
定义第k个特征值和每一个训练样本的二阶导组成的集合
定义一个rank函数
表达的含义就是小于z的所有特征值的h相加,h表征分位数分的是loss,也就是根据loss大小做的分割,而不是样本特征的分布。
每一段间隔,产生一个候选分割点,大约有个候选分割点
为什么采用h作为权重呢?这个开始我也很疑惑
前面的公式(3)可以写作下式。这下就可以理解h表征loss这句话的含义了。
上述的样本有相同的权重,当样本有着不同权重时,作者在附录里也给出了解决方案和理论证明。
3.4 Sparsity-aware Split Finding
稀疏特征是比较普遍的现象,例如存在缺失值、比较多的零项、特征工程的产物(one-hot),让算法意识到数据中的稀疏模式是比较重要的。为了解决这种情况,当某个值是缺失的,会被分到一个默认方向
Xgboost 在处理带缺失值的特征时,先对非缺失的样本进行排序,对该特征缺失的样本先不处理,然后在遍历每个分裂点时,将这些缺失样本分别划入左子树和右子树来计算损失然后求最优。
如果训练样本中没有缺失值,而预测过程中出现了缺失值,那么样本会被默认分到右子树。
要理解下面的算法图,可以假设有按排序的
ascent descent
1 3
2 2
3 1
null null
null null
这样就可以理解每个特征遍历时的两次线性搜索
- enumerate missing value goto right
- enumerate missing value goto left
4. System Design
4.1 Column Block for Parallel Learning
xgboost的并行是在特征粒度上的。决策树的学习最耗时的一个步骤就是对特征的值进行排序(因为要确定最佳分割点),为了减小排序成本,xgboost在训练之前,预先对数据进行了排序,然后保存为block结构(CSC),后面的迭代中重复地使用这个结构,大大减小计算量。这个block结构也使得并行成为了可能,在进行节点的分裂时,需要计算每个特征的增益,最终选增益最大的那个特征去做分裂,那么各个特征的增益计算就可以开多线程进行。
为每个列收集统计数据可以并行化,给我们一个并行算法的分裂查找。 重要的是,列块结构还支持列子采样,因为在块中很容易选择列的子集。
时间复杂度分析
更新于 2020-12-16