注意,下文的原始的gbdt是以sklearn中的gbdt的实现为例子来阐述的,因为gbdt的改进版本有很多,为了叙述方便,使用这个最为人所知的实现来描述。
- 你有自己用过别的模型然后调参之类的吗?能说一下基本的调参流程吗?XGB知道吗,以XGB为例子说一下调参流程吧
(个人的思路):一般来说采用贝叶斯优化或者遗传算法等启发式的优化算法确定相对最佳参数(如果不熟悉的话用随机搜索也是可以的,或者网格搜索但是参数得到步长设置的很大,一步一步确定相对最优参数的区间),然后再根据实际的模型在验证集上的表现做一些微调,对于过拟合优先调整max_depth和树的数量,在实际使用过程中这两个参数对于模型的整体效果影响很大很明显。对于欠拟合,反着来就行了。
- XGB和GBDT的区别有哪些?
1、算法层面:
(1)损失函数的二阶泰勒展开;(具体的二阶泰勒展开的阐述下面那点会详细描述)
(2)树的正则化概念的引入,对叶节点数量和叶子节点输出进行了约束,方式是将二者形成的约束项加入损失函数中;
(3)二阶泰勒展开与树正则化推出了新的叶子节点输出的计算公式而不是原始gbdt那样的简单平均;
(4)a、对于基础学习器的改进,
分裂的时候自动根据是否产生正增益指导是否进行分裂,因为引入了正则项的概念,分裂的时候这个预剪枝更加严苛;
b、对于缺失值的处理,xgboost根据左右子节点的增益大小将缺失值分到增益大的节点中,而sklearn中的gbdt是无法处理缺失值的,因为sklearn中的gbdt是以sklearn中的cart为基学习器的,而sklearn中的cart也并没有实现对缺失值的处理功能。
(5)学习率,Shrinkage,对每一颗树都乘以小于1的学习率,来削弱每一颗树的影响,这样的结果就是会引入更多的树来处理使得基学习器得数量变多,从而降低过拟合,不过其实sklearn中的gbdt也实现了。。。不知道为什么这么多人把这一点也列为不同;
(6)、引入了随机森林使用的列采样功能,便于降低过拟合;
(7)、引入了许多近似直方图之类的优化算法来进一步提高树的训练速度与抗过拟合的能力,这个比较复杂,因为实现了很多种算法,后面单独写一篇来总结;
2、工程层面
(1)、对每个特征进行分块(block)并排序(pre_sort),将排序后的结构保存在内存中,这样后续分裂的时候就不需要重复对特征进行排序然后计算最佳分裂点了,并且能够进行并行化计算.这个结构加速了split finding的过程,只需要在建树前排序一次,后面节点分裂时直接根据索引得到梯度信息。
(2)
金贵涛:对xgboost的理解zhuanlan.zhihu.com其它更复杂的工程优化处理见这里。。。。
为什么xgb用二阶导:
1、形式上的统一:
下面来自xgb的官网叙述:
可以看到,损失函数为mse的时候,注意,此时我们没有进行二阶泰勒展开
对比可以看到,其它损失函数泰勒展开之后去掉常数最终的形式和mse的不泰勒展开的形式是完全一致的(mse的二阶梯为常数1,一阶梯度是y_pred-y_True),这么做的好处是,这样的话,1、 xgboost在对mse的损失函数设计完求解器之后,这一套代码可以直接复用给别的损失函数来使用,因为我们如果不做二阶泰勒展开的话,比如新的损失函数是二元交叉熵,在工程设计上,我们还要将损失函数的求导,然后把求导之后的式子写出来:
设计一个新的求解器去求解,很麻烦。
而进行了这样的设计之后,后续如果还有一些什么别的损失函数,底层的求解mse的代码可以直接使用,使用者只需要自行去求解新的损失函数的一阶梯度和二阶梯度的表达式,然后通过xgboost的自定义损失函数的功能就可以实现使用完备的xgboost的框架来求解自己的损失函数的最优值了。
2、关于速度的问题,gbdt的前向分布的求解思路可以说就和我们常见的逻辑回归求解的梯度下降是类似的,线性回归的梯度下降每一轮通过更新参数的方式接近损失函数的最优值,而gbdt则是用基学习器去拟合,相对而言,xgboost类似于使用牛顿法来求解线性回归,所以下面从牛顿和梯度下降的角度来阐述,的实际上我们常说的牛顿法比梯度下降法快是不准确的,应该是牛顿法的收敛速度要比梯度下降法快,也就是说牛顿法使用的迭代次数相对于梯度下降法要更少,但是由于涉及到计算二阶导的信息,牛顿法不一定在算法训练的时间上总比梯度下降法快,只是相对于梯度下降法而言,更少的迭代达到最优,这一点来看,并不算是优势。