xgboost笔记

云梦
2021-04-02 / 0 评论 / 400 阅读 / 正在检测是否收录...
温馨提示:
本文最后更新于2021年11月25日,已超过737天没有更新,若内容或图片失效,请留言反馈。

1.xgboost对特征缺失敏感吗,对缺失值做了什么操作,存在什么问题?

不敏感,可以自动处理,处理方式是将missing值分别加入左节点 右节点取分裂增益最大的节点将missing样本分裂进这个节点 。这种处理方式的问题在xgboost仅仅在特征的非缺失的值上进行分裂然后missing值直接放入其中一个节点,显然当缺失值很多的情况下,比如缺失80%,那么xgb分裂的时候仅仅在20%的特征值上分裂,这是非常容易过拟合的。

2.Lightgbm相对于xgboost的优缺点?

优点:直方图算法—更高(效率)更快(速度)更低(内存占用)更泛化(分箱与之后的不精确分割也起到了一定防止过拟合的作用); 缺点:直方图较为粗糙,会损失一定精度,但是在gbm的框架下,基学习器的精度损失可以通过引入更多的tree来弥补。

3.XGB和lightGBM在节点分裂时候的区别是什么?

xgb是level-wise,lgb是leaf-wise,level-wise指在树分裂的过程中,同一层的非叶子节点,只要继续分裂能够产生正的增益就继续分裂下去,而leaf-wise更苛刻一点,同一层的非叶子节点,仅仅选择分裂增益最大的叶子节点进行分裂。

4.XGBoost和GBDT的区别有哪些?

4.1、算法层面: (1)损失函数的二阶泰勒展开; (2)树的正则化概念的引入,对叶节点数量和叶子节点输出进行了约束,方式是将二者形成的约束项加入损失函数中; (3)二阶泰勒展开与树正则化推出了新的叶子节点输出的计算公式而不是原始gbdt那样的简单平均; (4) a、对于基础学习器的改进,XGBoost和GBDT的区别有哪些【面试题详解】插图分裂的时候自动根据是否产生正增益指导是否进行分裂,因为引入了正则项的概念,分裂的时候这个预剪枝更加严苛; b、对于缺失值的处理,xgboost根据左右子节点的增益大小将缺失值分到增益大的节点中,而sklearn中的gbdt是无法处理缺失值的,因为sklearn中的gbdt是以sklearn中的cart为基学习器的,而sklearn中的cart也并没有实现对缺失值的处理功能。 (5)学习率,Shrinkage,对每一颗树都乘以小于1的学习率,来削弱每一颗树的影响,这样的结果就是会引入更多的树来处理使得基学习器得数量变多,从而降低过拟合,不过其实sklearn中的gbdt也实现了。。。不知道为什么这么多人把这一点也列为不同; (6)引入了随机森林使用的列采样功能,便于降低过拟合; (7)引入了许多近似直方图之类的优化算法来进一步提高树的训练速度与抗过拟合的能力,这个比较复杂,因为实现了很多种算法,后面单独写一篇来总结;

4.2、工程层面 (1)对每个特征进行分块(block)并排序(pre_sort),将排序后的结构保存在内存中,这样后续分裂的时候就不需要重复对特征进行排序然后计算最佳分裂点了,并且能够进行并行化计算.这个结构加速了split finding的过程,只需要在建树前排序一次,后面节点分裂时直接根据索引得到梯度信息。

5.XGB特征重要性程度是怎么判断的?

官网上给出的方案,total_gain就是特征带来的总的分裂增益,也就是我们常规意义上的分裂总增益,weight,被用来作为分裂节点的次数,也就是我们常规意义上的分裂总次数,gain=total_gain/weight,计算的是每一次分裂带来的平均增益,total_cover表示特征分裂的样本数,举个例子,假设初始样本有10000个,第一次分裂的时候使用了特征A,也就是特征A在这10000个样本上分裂,则此时的cover值为10000,假设根据特征A分裂出左枝的样本有1000个,右边有9000个,而在左枝特征B是最优特征根据这1000个样本进行分裂,则B当前的cover是1000,依次类推最后求和。而cover显然就是total_cover/weight,也就是平均每次分裂所“负责”的样本数。

6.xgb的预排序算法是怎么做的呢?

将原始特征进行排序之后以块的形式保存到内存中,在块里面保存排序后的特征值及对应样本的引用,以便于获取样本的一阶、二阶导数值,但意味着除了保存原始特征之外还要保存原始特征的排序结果,耗内存。

7.RF和xgboost哪个对异常点更敏感?

xgb明显敏感的多,当然对rf也是有一定影响的,rf的每棵数的生成是独立的,异常点数量不多的情况下异常点常常和正常样本中的某些样本合并在一个分支里。但是xgb不一样,异常样本的t-1轮的预测值和真实标签计算出来的负梯度会一直很大。 假设当到达某一轮的时候,所有正常样本的计算得到的负梯度都很小而异常样本的负梯度很大例如【0.0000001,0.0000001,0.0000001,0.0000001,0.0000001,10】,这个时候新树会可能会继续进行不正常的分裂为0.0000001,0.0000001,0.0000001,0.0000001,0.00000010.0000001,0.0000001,0.0000001,0.0000001,0.00000010.0000001,0.0000001,0.0000001,0.0000001,0.0000001,101010,而这样的分裂是不合理的,因为异常值本身可能是因为某些人为失误导致的数据记录错误,或者异常样本完全是属于另外一种分布,此时强制要进行模型训练会导致模型的结果有偏从而发生过拟合。当然异常样本数量很少比如10个以内的时候而正常样本有100000000个其实基本没什么影响,但是如果占比较高的话是会产生影响的。

8.xgb何时停止分裂?

人工设定的参数,max_depth,min_data_in_leaf等等,这类通过超参数形式限制树的复杂度的方法都会引发xgb的分裂的停止,也就是常说的预剪枝;人工不限制,自由生长的情况下,当分裂增益小于0则基学习器停止分裂.

9.XGB和lightGBM在节点分裂时候的区别是什么?

xgb是level-wise,lgb是leaf-wise,level-wise指在树分裂的过程中,同一层的非叶子节点,只要继续分裂能够产生正的增益就继续分裂下去,而leaf-wise更苛刻一点,同一层的非叶子节点,仅仅选择分裂增益最大的叶子节点进行分裂。

10.xgb和lgb在特征、数据并行上存在什么差异?

1)特征并行 lgbm特征并行的前提是每个worker留有一份完整的数据集,但是每个worker仅在特征子集上进行最佳切分点的寻找;worker之间需要相互通信,通过比对损失来确定最佳切分点;然后将这个最佳切分点的位置进行全局广播,每个worker进行切分即可。xgb的特征并行与lgbm的最大不同在于xgb每个worker节点中仅有部分的列数据,也就是垂直切分,每个worker寻找局部最佳切分点,worker之间相互通信,然后在具有最佳切分点的worker上进行节点分裂,再由这个节点广播一下被切分到左右节点的样本索引号,其他worker才能开始分裂。二者的区别就导致了lgbm中worker间通信成本明显降低,只需通信一个特征分裂点即可,而xgb中要广播样本索引。

2)数据并行 当数据量很大,特征相对较少时,可采用数据并行策略。lgbm中先对数据水平切分,每个worker上的数据先建立起局部的直方图,然后合并成全局的直方图,采用直方图相减的方式,先计算样本量少的节点的样本索引,然后直接相减得到另一子节点的样本索引,这个直方图算法使得worker间的通信成本降低一倍,因为只用通信以此样本量少的节点。xgb中的数据并行也是水平切分,然后单个worker建立局部直方图,再合并为全局,不同在于根据全局直方图进行各个worker上的节点分裂时会单独计算子节点的样本索引,因此效率贼慢,每个worker间的通信量也就变得很大。

3)投票并行(lgbm) 当数据量和维度都很大时,选用投票并行,该方法是数据并行的一个改进。数据并行中的合并直方图的代价相对较大,尤其是当特征维度很大时。大致思想是:每个worker首先会找到本地的一些优秀的特征,然后进行全局投票,根据投票结果,选择top的特征进行直方图的合并,再寻求全局的最优分割点。这个方法我没有找到很好的解释,因此,面试过程中答出前面两种我觉得就ok了吧。

11.为什么xgboost不用后剪枝?

后剪枝计算代价太高了,合并一次叶节点就要计算一次测试集的表现,数据量大的情况下非常消耗时间,而且也并不是特别必要,因为这样很容易过拟合测试集。

12.xgboost如何处理缺失值?

通常情况下,我们人为在处理缺失值的时候大多会选用中位数、均值或是二者的融合来对数值型特征进行填补,使用出现次数最多的类别来填补缺失的类别特征。

很多的机器学习算法都无法提供缺失值的自动处理,都需要人为地去处理,但是xgboost模型却能够处理缺失值,也就是说模型允许缺失值存在。 原是论文中关于缺失值的处理将其看与稀疏矩阵的处理看作一样。在寻找split point的时候,不会对该特征为missing的样本进行遍历统计,只对该列特征值为non-missing的样本上对应的特征值进行遍历,通过这个技巧来减少了为稀疏离散特征寻找split point的时间开销。在逻辑实现上,为了保证完备性,会分别处理将missing该特征值的样本分配到左叶子结点和右叶子结点的两种情形,计算增益后选择增益大的方向进行分裂即可。可以为缺失值或者指定的值指定分支的默认方向,这能大大提升算法的效率。如果在训练中没有缺失值而在预测中出现缺失,那么会自动将缺失值的划分方向放到右子树。

13.XGBoost与GBDT有什么不同?

基分类器:XGBoost的基分类器不仅支持CART决策树,还支持线性分类器,此时XGBoost相当于带L1和L2正则化项的Logistic回归(分类问题)或者线性回归(回归问题)。

导数信息:XGBoost对损失函数做了二阶泰勒展开,GBDT只用了一阶导数信息,并且XGBoost还支持自定义损失函数,只要损失函数一阶、二阶可导。

正则项:XGBoost的目标函数加了正则项, 相当于预剪枝,使得学习出来的模型更加不容易过拟合。

列抽样:XGBoost支持列采样,与随机森林类似,用于防止过拟合。 缺失值处理:对树中的每个非叶子结点,XGBoost可以自动学习出它的默认分裂方向。如果某个样本该特征值缺失,会将其划入默认分支。

并行化:注意不是tree维度的并行,而是特征维度的并行。XGBoost预先将每个特征按特征值排好序,存储为块结构,分裂结点时可以采用多线程并行查找每个特征的最佳分割点,极大提升训练速度。

14.XGBoost为什么使用泰勒二阶展开?

精准性:相对于GBDT的一阶泰勒展开,XGBoost采用二阶泰勒展开,可以更为精准的逼近真实的损失函数。 可扩展性:损失函数支持自定义,只需要新的损失函数二阶可导。

15.XGBoost为什么可以并行训练?

XGBoost的并行,并不是说每棵树可以并行训练,XGB本质上仍然采用boosting思想,每棵树训练前需要等前面的树训练完成才能开始训练。 XGBoost的并行,指的是特征维度的并行:在训练之前,每个特征按特征值对样本进行预排序,并存储为Block结构,在后面查找特征分割点时可以重复使用,而且特征已经被存储为一个个block结构,那么在寻找每个特征的最佳分割点时,可以利用多线程对每个block并行计算。

16.XGBoost为什么快?

分块并行:训练前每个特征按特征值进行排序并存储为Block结构,后面查找特征分割点时重复使用,并且支持并行查找每个特征的分割点

候选分位点:每个特征采用常数个分位点作为候选分割点 CPU cache

命中优化: 使用缓存预取的方法,对每个线程分配一个连续的buffer,读取每个block中样本的梯度信息并存入连续的Buffer中。

Block 处理优化:Block预先放入内存;Block按列进行解压缩;将Block划分到不同硬盘来提高吞吐

17.XGBoost防止过拟合的方法 XGBoost在设计时,为了防止过拟合做了很多优化,具体如下:

 目标函数添加正则项:叶子节点个数+叶子节点权重的L2正则化.
 列抽样:训练的时候只用一部分特征(不考虑剩余的block块即可).
 子采样:每轮计算可以不使用全部样本,使算法更加保守.
 shrinkage: 可以叫学习率或步长,为了给后面的训练留出更多的学习空间.

18.为什么XGBoost相比某些模型对缺失值不敏感?

对存在缺失值的特征,一般的解决方法是:

离散型变量:用出现次数最多的特征值填充;
 连续型变量:用中位数或均值填充;

一些模型如SVM和KNN,其模型原理中涉及到了对样本距离的度量,如果缺失值处理不当,最终会导致模型预测效果差。 而树模型对缺失值的敏感度低,大部分时候可以在数据缺失时时使用。原因就是,一棵树中每个结点在分裂时,寻找的是某个特征的最佳分裂点(特征值),完全可以不考虑存在特征值缺失的样本,也就是说,如果某些样本缺失的特征值缺失,对寻找最佳分割点的影响不是很大。 XGBoost对缺失数据有特定的处理方法,详情参考上篇文章第7题。 因此,对于有缺失值的数据在经过缺失处理后:

 当数据量很小时,优先用朴素贝叶斯
 数据量适中或者较大,用树模型,优先XGBoost
 数据量较大,也可以用神经网络
 避免使用距离度量相关的模型,如KNN和SVM

19.XGBooost参数调优的一般步骤 首先需要初始化一些基本变量,例如:

 max_depth = 5
 min_child_weight = 1
 gamma = 0
 subsample, colsample_bytree = 0.8
 scale_pos_weight = 1

确定learning rate和estimator的数量 learning rate可以先用0.1,用cv来寻找最优的estimators

max_depth和 min_child_weight 我们调整这两个参数是因为,这两个参数对输出结果的影响很大。我们首先将这两个参数设置为较大的数,然后通过迭代的方式不断修正,缩小范围。 max_depth,每棵子树的最大深度,check from range3,10,23,10,23,10,2。 min_child_weight,子节点的权重阈值,check from range1,6,21,6,21,6,2。 如果一个结点分裂后,它的所有子节点的权重之和都大于该阈值,该叶子节点才可以划分。

gamma 也称作最小划分损失min_split_loss,check from 0.1 to 0.5,指的是,对于一个叶子节点,当对它采取划分之后,损失函数的降低值的阈值。

 如果大于该阈值,则该叶子节点值得继续划分
 如果小于该阈值,则该叶子节点不值得继续划分

subsample, colsample_bytree subsample是对训练的采样比例 colsample_bytree是对特征的采样比例 both check from 0.6 to 0.9

正则化参数 alpha 是L1正则化系数,try 1e-5, 1e-2, 0.1, 1, 100 lambda 是L2正则化系数

降低学习率 降低学习率的同时增加树的数量,通常最后设置学习率为0.01~0.1

20.XGBoost如何选择最佳分裂点?

XGBoost在训练前预先将特征按照特征值进行了排序,并存储为block结构,以后在结点分裂时可以重复使用该结构。 因此,可以采用特征并行的方法利用多个线程分别计算每个特征的最佳分割点,根据每次分裂后产生的增益,最终选择增益最大的那个特征的特征值作为最佳分裂点。 如果在计算每个特征的最佳分割点时,对每个样本都进行遍历,计算复杂度会很大,这种全局扫描的方法并不适用大数据的场景。XGBoost还提供了一种直方图近似算法,对特征排序后仅选择常数个候选分裂位置作为候选分裂点,极大提升了结点分裂时的计算效率。

21.XGBoost的Scalable性如何体现?

基分类器的scalability:弱分类器可以支持CART决策树,也可以支持LR和Linear。

目标函数的scalability:支持自定义loss function,只需要其一阶、二阶可导。有这个特性是因为泰勒二阶展开,得到通用的目标函数形式。

 学习方法的scalability:Block结构支持并行化,支持 Out-of-core计算。

22.比较LR和GBDT,说说什么情景下GBDT不如LR?

先说说LR和GBDT的区别: LR是线性模型,可解释性强,很容易并行化,但学习能力有限,需要大量的人工特征工程 GBDT是非线性模型,具有天然的特征组合优势,特征表达能力强,但是树与树之间无法并行训练,而且树模型很容易过拟合;当在高维稀疏特征的场景下,LR的效果一般会比GBDT好。原因如下: 先看一个例子: 假设一个二分类问题,label为0和1,特征有100维,如果有1w个样本,但其中只要10个正样本1,而这些样本的特征 f1的值为全为1,而其余9990条样本的f1特征都为0在高维稀疏的情况下这种情况很常见在高维稀疏的情况下这种情况很常见在高维稀疏的情况下这种情况很常见。 我们都知道在这种情况下,树模型很容易优化出一个使用f1特征作为重要分裂节点的树,因为这个结点直接能够将训练数据划分的很好,但是当测试的时候,却会发现效果很差,因为这个特征f1只是刚好偶然间跟y拟合到了这个规律,这也是我们常说的过拟合。 那么这种情况下,如果采用LR的话,应该也会出现类似过拟合的情况呀:y = W1f1 + Wifi+….,其中 W1特别大以拟合这10个样本。为什么此时树模型就过拟合的更严重呢? 仔细想想发现,因为现在的模型普遍都会带着正则项,而 LR 等线性模型的正则项是对权重的惩罚,也就是 W1一旦过大,惩罚就会很大,进一步压缩 W1的值,使他不至于过大。但是,树模型则不一样,树模型的惩罚项通常为叶子节点数和深度等,而我们都知道,对于上面这种 case,树只需要一个节点就可以完美分割9990和10个样本,一个结点,最终产生的惩罚项极其之小。 这也就是为什么在高维稀疏特征的时候,线性模型会比非线性模型好的原因了:带正则化的线性模型比较不容易对稀疏特征过拟合。

23.GBDT的原理?

GBDT是一种基于boosting集成思想的加法模型,训练时采用前向分布算法进行贪婪的学习,每次迭代都学习一棵CART树来拟合之前 t-1 棵树的预测结果与训练样本真实值的残差。 xgboost是基于GBDT的思想上做了一些优化,如下: GBDT以传统CART作为基分类器,而xgboosting支持线性分类器,相当于引入L1和L2正则化项的逻辑回归(分类问题)和线性回归(回归问题); GBDT在优化时只用到一阶导数,xgboost对代价函数做了二阶Talor展开,引入了一阶导数和二阶导数; 当样本存在缺失值是,xgboost能自动学习分裂方向; xgboost借鉴RF的做法,支持列抽样,这样不仅能防止过拟合,还能降低计算; xgboost的代价函数引入正则化项,控制了模型的复杂度,正则化项包含全部叶子节点的个数,每个叶子节点输出的score的L2模的平方和。从贝叶斯方差角度考虑,正则项降低了模型的方差,防止模型过拟合; xgboost在每次迭代之后,为叶子结点分配学习速率,降低每棵树的权重,减少每棵树的影响,为后面提供更好的学习空间; xgboost工具支持并行,但并不是tree粒度上的,而是特征粒度,决策树最耗时的步骤是对特征的值排序,xgBoosting在迭代之前,先进行预排序,存为block结构,每次迭代,重复使用该结构,降低了模型的计算;block结构也为模型提供了并行可能,在进行结点的分裂时,计算每个特征的增益,选增益最大的特征进行下一步分裂,那么各个特征的增益可以开多线程进行; 可并行的近似直方图算法,树结点在进行分裂时,需要计算每个节点的增益,若数据量较大,对所有节点的特征进行排序,遍历的得到最优分割点,这种贪心法异常耗时,这时引进近似直方图算法,用于生成高效的分割点,即用分裂后的某种值减去分裂前的某种值,获得增益,为了限制树的增长,引入阈值,当增益大于阈值时,进行分裂;

24.为什么xgboost不用后剪枝?

后剪枝计算代价太高了,合并一次叶节点就要计算一次测试集的表现,数据量大的情况下非常消耗时间,而且也并不是特别必要,因为这样很容易过拟合测试集。

25.xgboost.XGBClassifier 分类算法&参数详解?

class xgboost.XGBClassifiermaxdepth=3,learningrate=0.1,nestimators=100,silent=True,objective=′binary:logistic′,booster=′gbtree′,njobs=1,nthread=None,gamma=0,minchildweight=1,maxdeltastep=0,subsample=1,colsamplebytree=1,colsamplebylevel=1,regalpha=0,reglambda=1,scaleposweight=1,basescore=0.5,randomstate=0,seed=None,missing=None,∗∗kwargsmax_depth=3, learning_rate=0.1, n_estimators=100, silent=True, objective='binary:logistic', booster='gbtree', n_jobs=1, nthread=None, gamma=0, min_child_weight=1, max_delta_step=0, subsample=1, colsample_bytree=1, colsample_bylevel=1, reg_alpha=0, reg_lambda=1, scale_pos_weight=1, base_score=0.5, random_state=0, seed=None, missing=None, **kwargsmaxd​epth=3,learningr​ate=0.1,ne​stimators=100,silent=True,objective=′binary:logistic′,booster=′gbtree′,nj​obs=1,nthread=None,gamma=0,minc​hildw​eight=1,maxd​eltas​tep=0,subsample=1,colsampleb​ytree=1,colsampleb​ylevel=1,rega​lpha=0,regl​ambda=1,scalep​osw​eight=1,bases​core=0.5,randoms​tate=0,seed=None,missing=None,∗∗kwargs

 booster
    gbtree 树模型做为基分类器(默认)
    gbliner 线性模型做为基分类器
 n_jobs 并行线程数
 silent
    silent=0时,不输出中间过程(默认)
    silent=1时,输出中间过程
 nthread
    nthread=-1时,使用全部CPU进行并行运算(默认)
    nthread=1时,使用1个CPU进行运算。
 scale_pos_weight

正样本的权重,在二分类任务中,当正负样本比例失衡时,设置正样本的权重,模型效果更好。例如,当正负样本比例为1:10时,scale_pos_weight=10。

 n_estimatores
    含义:总共迭代的次数,即决策树的个数
    调参:
 max_depth
    含义:树的深度,默认值为6,典型值3-10。
    调参:值越大,越容易过拟合;值越小,越容易欠拟合。
 min_child_weight
  含义:默认值为1,。
 调参:值越大,越容易欠拟合;值越小,越容易过拟合(值较大时,避免模型学习到局部的特殊样本)。
 subsample
    含义:训练每棵树时,使用的数据占全部训练集的比例。默认值为1,典型值为0.5-1。
    调参:防止overfitting。
 colsample_bytree
    含义:训练每棵树时,使用的特征占全部特征的比例。默认值为1,典型值为0.5-1。
    调参:防止overfitting。
 ​
 learning_rate
    含义:学习率,控制每次迭代更新权重时的步长,默认0.3。
    调参:值越小,训练越慢。
    典型值为0.01-0.2。
 gamma
    惩罚项系数,指定节点分裂所需的最小损失函数下降值。
    调参:
 alpha
    L1正则化系数,默认为1
 lambda
    L2正则化系数,默认为1

 

4

评论 (0)

取消