[经典面试题]:随机森林RF,梯度提升决策树GBDT,极限提升树Xgboost,轻量级梯度提升机lightgbm理论比较

11 篇文章 1 订阅
3 篇文章 0 订阅

1. 简介

RF(Random Forest)、GBDT和XGBoost都属于集成学习(Ensemble Learning)模型,集成学习的目的是通过结合多个基学习器的预测结果来改善单个学习器的泛化能力和鲁棒性。

根据个体学习器的生成方式,目前的集成学习方法大致分为两大类:

即个体学习器之间存在强依赖关系、必须串行生成的序列化方法,以及个体学习器间不存在强依赖关系、可同时生成的并行化方法;前者的代表就是Boosting,后者的代表是Bagging和“随机森林”(Random Forest)。

bagging和boosting的区别:

bagging通过减少方差提高模型的性能,如果各个模型预测结果都相互独立:

Var ⁡ ( ∑ X i n ) = Var ⁡ ( X i ) n \operatorname{Var}\left(\frac{\sum X_{i}}{n}\right)=\frac{\operatorname{Var}\left(X_{i}\right)}{n} Var(nXi)=nVar(Xi)

因此,多样化的模型才能减少方差。

boosting通过减少偏差来提高模型性能, 当前模型预测误差:

在这里插入图片描述

序列化的方法是通过拟合残差,从而偏差更小。

为什么boosting的树深度比bagging浅?

这是因为boosting的树串行学习,拟合残差,很容易获得较低的偏差,树太深会过拟合,方差过大;bagging的树是相互独立,为了让一棵树具有较高的精度,即较小的偏差,需要树的深度较深。

2. 随机森林Random Forest(RF)

2.1 随机森林原理

Bagging 算法:

给定一个大小为 n {\displaystyle n} n 的训练集 D {\displaystyle D} D ,Bagging算法从中均匀、有放回地(即使用自助抽样法)选出 m {\displaystyle m} m 个大小为 n ′ {\displaystyle n'} n 的子集 D i {\displaystyle D_{i}} Di ,作为新的训练集。在这 m {\displaystyle m} m 个训练集上使用分类、回归等算法,则可得到 m {\displaystyle m} m 个模型,再通过取平均值、取多数票等方法,即可得到Bagging的结果。

因此,Bagging的基学习器之间属于并列生成,不存在强依赖关系。

Random Forest(随机森林)是Bagging的扩展变体,它在以决策树 为基学习器构建Bagging集成的基础上,进一步在决策树的训练过程中引入了随机特征选择,因此可以概括RF包括四个部分:
  
  (1)随机选择样本(放回抽样);
   随机选择样本和Bagging相同;
  
  (2)随机选择特征;
  
  (3)构建决策树;
  
  (4)随机森林投票(平均)。

随机选择特征是指在树的构建中,会从样本集的特征集合中随机选择部分特征,然后再从这个子集中选择最优的属性用于划分,这种随机性导致随机森林的偏差会有稍微的增加(相比于单棵不随机树),但是由于随机森林的‘平均’特性,会使得它的方差减小,而且方差的减小补偿了偏差的增大,因此总体而言是更好的模型。
  (As a result of this randomness, the bias of the forest usually slightly increases (with respect to the bias of a single non-random tree) but, due to averaging, its variance also decreases, usually more than compensating for the increase in bias, hence yielding an overall better model.)
  
在构建决策树的时候,RF的每棵决策树都最大可能的进行生长而不进行剪枝;在对预测输出进行结合时,RF通常对分类问题使用简单投票法,回归任务使用简单平均法。
  
RF的重要特性是不用对其进行交叉验证或者使用一个独立的测试集获得无偏估计,由于每个基学习器只使用了训练集中约63.2%的样本,剩下约36.8%的样本可用做验证集来对其泛化性能进行“包外估计”(out of bag ,oob,不属于训练集就是包外集),而包外估计的误分率是无偏的。

In this way, a test set classification is obtained for each case in about one-third of the trees. At the end of the run, take j to be the class that got most of the votes every time case n was oob. The proportion of times that j is not equal to the true class of n averaged over all cases is the oob error estimate. This has proven to be unbiased in many tests.

稍微解释下自助法选样本:

N个样本有放回选N个,每个样本每次被选中的概率 1 / N 1/N 1/N,不被选中的概率 1 − 1 / N 1-1/N 11/N,样本N次都不被选中的概率 ( 1 − 1 / N ) N (1-1/N)^N (11/N)N,当N趋于无穷大,值为 e − 1 = 0.368 e^{-1}=0.368 e1=0.368.

RF和Bagging对比:

RF的起始性能较差,特别当只有一个基学习器时,随着学习器数目增多,随机森林通常会收敛到更低的泛化误差。随机森林的训练效率也会高于Bagging,因为在单个决策树的构建中,Bagging使用的是‘确定性’决策树,在选择特征划分结点时,要对所有的特征进行考虑,而随机森林使用的是‘随机性’特征数,只需考虑特征的子集。

1.2 优缺点

随机森林的优点较多,简单总结:
  1、在数据集上表现良好,相对于其他算法有较大的优势(训练速度、预测准确度);
  2、能够处理很高维的数据,并且不用特征选择,而且在训练完后,给出特征的重要性;
  3、容易做成并行化方法。
  
RF的缺点:在噪声较大的分类或者回归问题上会过拟合。

3. 梯度提升决策树GBDT

提GBDT之前,谈一下Boosting,Boosting是一种与Bagging很类似的技术。不论是Boosting还是Bagging,所使用的多个分类器类型都是一致的。但是在前者当中,不同的分类器是通过串行训练而获得的,每个新分类器都根据已训练的分类器的性能来进行训练。Boosting是通过关注被已有分类器错分的那些数据来获得新的分类器。
  
由于Boosting分类的结果是基于所有分类器的加权求和结果的,因此Boosting与Bagging不太一样,Bagging中的分类器权值是一样的,而Boosting中的分类器权重并不相等,每个权重代表对应的分类器在上一轮迭代中的成功度

3.1 GBDT原理

GBDT与传统的Boosting区别较大,它的每一次计算都是为了减少上一次的残差,而为了消除残差,我们可以在残差减小的梯度方向上建立模型,所以说,在GradientBoost中,每个新的模型的建立是为了使得之前的模型的残差往梯度下降的方法,与传统的Boosting中关注正确错误的样本加权有着很大的区别。
  
在GradientBoosting算法中,关键就是利用损失函数的负梯度方向在当前模型的值作为残差的近似值,进而拟合一棵CART回归树。(也就是拟合的是负梯度值
  
基本流程:每轮迭代中,首先计算出当前模型在所有样本的负梯度, 然后,以该值为目标训练一个新的弱分类器,进行拟合并计算该弱分类器的权重
在这里插入图片描述
其中, a m \mathbf a_m am是第m次迭代模型,如回归树,中分裂的最佳变量。 L ( , ) L(,) L(,)函数可以是均方差函数(对于回归任务),也可以是对数似然函数,比如 l o g ( 1 + e − 2 y F ) log( {1 + e^{−2yF}}) log(1+e2yF).

GBDT的会累加所有树的结果,而这种累加是无法通过分类完成的,因此GBDT的树都是CART回归树,而不是分类树(尽管GBDT调整后也可以用于分类但不代表GBDT的树为分类树)。

GBDT使用梯度提升(Gradient Boosting) 作为训练方法, 而在逻辑回归或者神经网络的训练过程中往往采用梯度下降(Gradient Descent) 作为训练方法。

3.2 GBDT优缺点

GBDT的性能在RF的基础上又有一步提升,因此其优点也很明显:
  
(1) 它能灵活的处理各种类型的数据;
(2) 在相对较少的调参时间下,预测的准确度较高。
  
缺点:

(1)当然由于它是Boosting,因此基学习器之前存在串行关系,难以并行训练数据。
(2)GBDT在高维稀疏的数据集上, 表现不如支持向量机或者神经网络。

GBDT需要归一化吗?

树模型都不需要。
GBDT确实用到了gradient decent,但不是对feature的值做梯度下降,而是对残差做梯度下降
既然不是直接对feature数值进行梯度下降,我们自然也没有必要对其进行归一化。

梯度提升和梯度下降的区别和联系?

两者都是在每一轮迭代中, 利用损失函数相对于模型的负梯度方向的信息来对当前模型进行更新, 只不过在梯度下降中, 模型是以参数化形式表示, 从而模型的更新等价于参数的更新。 而在梯度提升中, 模型并不需要进行参数化表示, 而是直接定义在函数空间中, 从而大大扩展了可以使用的模型种类。
在这里插入图片描述

4. 极限提升树XGBoost

eXtreme Gradient Boosting,梯度提升极限树。

4.1 Xgboost原理

XGBoost的性能在GBDT上又有一步提升。坊间对XGBoost最大的认知在于其能够自动地运用CPU的多线程进行并行计算,同时在算法精度上也进行了精度的提高。
  
由于GBDT在合理的参数设置下,往往要生成一定数量的树才能达到令人满意的准确率,在数据集较复杂时,模型可能需要几千次迭代运算。但是XGBoost利用并行的CPU更好的解决了这个问题。

4.2 GBDT和XGBoost区别

(1)基学习器不同

传统的GBDT以CART树作为基学习器,XGBoost还支持线性分类器,这个时候XGBoost相当于L1和L2正则化的逻辑斯蒂回归(分类)或者线性回归(回归);

(2)代价函数不同

传统的GBDT在优化的时候只用到一阶导数信息,XGBoost则对代价函数进行了二阶泰勒展开,得到一阶和二阶导数;
在这里插入图片描述
(3)引入正则项(防止过拟合)

XGBoost在代价函数中加入了正则项,用于控制模型的叶节点数量和叶子节点输出。从权衡方差偏差来看,它降低了模型的方差,使学习出来的模型更加简单,放置过拟合,这也是XGBoost优于传统GBDT的一个特性;

在这里插入图片描述

在这里插入图片描述

(4)shrinkage(缩减),相当于学习速率(XGBoost中的eta)。(防止过拟合)

XGBoost在进行完一次迭代时,会将叶子节点的权值乘上该系数,主要是为了削弱每棵树的影响,让后面有更大的学习空间。(GBDT也有学习速率);

(5)列抽样(防止过拟合)

XGBoost借鉴了随机森林的做法,支持列抽样,不仅防止过 拟合,还能减少计算;

(6)对缺失值的处理。

传统的GBDT没有设计对缺失值进行处理, XGBoost能够自动学习出缺失值的处理策略。

对于特征的值有缺失的样本,XGBoost还可以自动 学习出它的分裂方向(还是判断增益);缺失值数据会被分到左子树和右子树分别计算损失,选中增益较大的分支。如果训练中没有数据缺失,预测时出现数据缺失,那么默认被分类到右子树。

zhihu 怎么理解决策树、xgboost能处理缺失值?而有的模型(svm)对缺失值比较敏感呢?

(7)基础学习器的改进

分裂的时候自动根据是否产生正增益指导是否进行分裂。

根据:
在这里插入图片描述
有:

L ~ ( t ) ( q ) = − 1 2 ∑ j = 1 T ( ∑ i ∈ I j g i ) 2 ∑ i ∈ I j h i + λ + γ T \tilde{\mathcal{L}}^{(t)}(q)=-\frac{1}{2} \sum_{j=1}^{T} \frac{\left(\sum_{i \in I_{j}} g_{i}\right)^{2}}{\sum_{i \in I_{j}} h_{i}+\lambda}+\gamma T L~(t)(q)=21j=1TiIjhi+λ(iIjgi)2+γT

分裂前后损失函数的差值:

Gain = 1 2 [ G L 2 H L + λ + G R 2 H R + λ − ( G L + G R ) 2 H L + H R + λ ] − γ \text {Gain}=\frac{1}{2}\left[\frac{G_{L}^{2}}{H_{L}+\lambda}+\frac{G_{R}^{2}}{H_{R}+\lambda}-\frac{\left(G_{L}+G_{R}\right)^{2}}{H_{L}+H_{R}+\lambda}\right]-\gamma Gain=21[HL+λGL2+HR+λGR2HL+HR+λ(GL+GR)2]γ

XGBoost最大化这个差值作为准则进行决策树的构建,通过遍历所有特征的所有取值,找到增益最大的分类方式。γ起到了一定的预剪枝效果。

相应算法:

g g g 是一阶导; h h h 是二阶导的值。
在这里插入图片描述
在这里插入图片描述

(8)XGBoost工具支持并行。

XGBoost的并行是在特征粒度上的

决策树的学习最耗时的一个步骤就是对特征的值进行排序(因为要确定最佳分割点),XGBoost在训练之前,预先对数据进行了排序,然后保存为block结构,后面的迭代 中重复地使用这个结构,大大减小计算量。这个block结构也使得并行成为了可能,在进行节点的分裂时,需要计算每个特征的增益,最终选增益最大的那个特征去做分裂,那么各个特征的增益计算就可以开多线程进行。

在这里插入图片描述
简单地说,对年龄、身高等特征进行排序并保存为block,然后对每个特征并行计算增益gain.

引入了许多近似直方图之类的优化算法来进一步提高树的训练速度与抗过拟合的能力。

5. 轻量级梯度提升机 LightGBM

(1) Lightgbm 分裂方式

xgboost采用的是level-wise(层级)的分裂策略,而lightGBM采用了leaf-wise(叶节点级)的策略,区别是xgboost对每一层所有节点做无差别分裂,可能有些节点的增益非常小,对结果影响不大,但是xgboost也进行了分裂,带来了务必要的开销。

leaf-wise的做法是在当前所有叶子节点中选择分裂收益最大的节点进行分裂,如此递归进行,很明显leaf-wise这种做法容易过拟合,因为容易陷入比较高的深度中,因此需要对最大深度做限制,从而避免过拟合。

在这里插入图片描述

关于lightgbm的增益
在这里插入图片描述
和xgboost一样。

lightgbm使用了基于histogram的决策树算法,这一点不同与xgboost中的 exact 算法(就是对特征值排序,遍历找最优分割点),histogram算法在内存和计算代价上都有不小优势。

(2) 内存上优化,引入直方图

很明显,直方图算法的内存消耗为(#data* #features * 1Bytes)(因为对特征分桶后只需保存特征离散化之后的值),而xgboost的exact算法内存消耗为:(2 * #data * #features* 4Bytes),因为xgboost既要保存原始feature的值,也要保存这个值的顺序索引,这些值需要32位的浮点数来保存。

在这里插入图片描述

在这里插入图片描述
增益计算公式(使用梯度的平方):

Δ loss ⁡ = s L 2 n L + s R 2 n R − s P 2 n P \Delta \operatorname{loss}=\frac{s_{L}^{2}}{n_{L}}+\frac{s_{R}^{2}}{n_{R}}-\frac{s_{P}^{2}}{n_{P}} Δloss=nLsL2+nRsR2nPsP2

遍历所有叶子结点:
	遍历所有特征:
		创建一个直方图,包含每个桶梯度和,桶样本数;
		遍历所有样本:
			累积梯度和,样本数
		遍历所有桶:
			计算以该桶为分割点的左边梯度和,样本数;并根据父节点,计算右边的参数;
			计算增益;
			保存最大增益。

在这里插入图片描述

(3) 计算上优化,特征捆绑,GOSS等算法

预排序算法在选择好分裂特征计算分裂收益时需要遍历所有样本的特征值,时间为(#data),而直方图算法只需要遍历桶就行了,时间为(#bin)

a. 直方图做差加速

一个子节点的直方图可以通过父节点的直方图减去兄弟节点的直方图得到(也得算兄弟节点,但起码速度差不多减半),从而加速计算。

但实际上xgboost的近似直方图算法也类似于lightgbm这里的直方图算法,为什么xgboost的近似算法比lightgbm还是慢很多呢?
-. xgboost在每一层都动态构建直方图, 因为xgboost的直方图算法不是针对某个特定的feature,而是所有feature共享一个直方图(每个样本的权重是二阶导),所以每一层都要重新构建直方图,而lightgbm中对每个特征都有一个直方图,所以构建一次直方图就够了。

直方图优化算法 blog

b. Exclusive Feature Bundling特征捆绑

在这里插入图片描述
特征捆绑有两个问题:1是将哪两个特征捆绑? 2是如何捆绑?

针对问题1,解决方案是,先初始化一个图,度数代表两个特征之间的冲突程度,根据两个特征冲突程度排序,选择冲突程度可以接受的两个特征捆绑。
这里统计两两特征的冲突程度,复杂度O(特征个数的平方)
为了提高效率,可以采用特征非零个数作为指标,进行排序。

特征捆绑就是对高维互斥的特征放进一个 bundle,这里是用图来定义是否互斥,并且允许少量不互斥的存在。这样相当于减少了特征维度(降到bundle的个数),bundle里边再适用桶(bin)来计算。

针对第二个问题,如何把两个特征合并?

方案是加偏置。
虽然特征互斥,但他们的取值范围可以有重叠,处理方式是加偏置。

bundle中绑定了两个特征A和B,A特征的原始取值为区间[0,10),B特征的原始取值为区间[0,20),我们可以在B特征的取值上加一个偏置常量10,将其取值范围变为[10,30),这样就可以放心的融合特征A和B了,因为在树模型中对于每一个特征都会计算分裂节点的,也就是通过将他们的取值范围限定在不同的bins中,在分裂时可以将不同特征很好的分裂到树的不同分支中去。

c. GOSS(Gradient based one-side algorithm)算法:

这是lightgbm最重要的两个工作内容之二。

如何减少数据样本量?

像AdaBoost可以通过给样本赋予不同的权重,权重小的可以舍弃。但是树模型没有权重一说。

lightgbm使用梯度来表示样本的权重,梯度小的说明已经拟合地很好了,选择梯度大的样本(对计算信息增益有帮助),梯度小的样本舍弃,减少数据量。

GOSS在进行数据采样的时候只保留了梯度较大的数据,但是如果直接将所有梯度较小的数据都丢弃掉势必会影响数据的总体分布,因此, GOSS首先将样本的梯度值按照绝对值大小降序排序,选取绝对值最大的a*100%个数据,然后在剩下的较小梯度数据中随机选择b*100%个数据,并且将这b%个数据乘以一个常数(1-a)/b %,最后使用这(a+b)%个数据来计算信息增益。

GOSS keeps all the instances with large gradients and performs random sampling on the instances with small gradients.

对于梯度小的,是随机采样(而不是丢弃)。
在这里插入图片描述

这里,可能有人会疑问:
Q:既然都遍历了一遍所有样本来求取梯度,可以直接根据梯度构建直方图,怎么还可提高时间复杂度?
A: 其实,每次迭代(拟合一颗新的决策树时),树的每次分裂都用遍历一遍样本来重新计算样本的梯度,获得新的直方图的。因此,在树拟合前,进行筛选样本是有降低时间复杂度的意义。

(4) lightgbm支持直接输入categorical 的feature

-. 在对离散特征分裂时,每个取值都当作一个桶,分裂时的增益算的是”是否属于某个category“的gain。类似于one-hot编码。

(5) lightgbm 优化并行计算

a. feature parallel

一般的feature parallel就是对数据做垂直分割(partiion data vertically,就是对属性分割),然后将分割后的数据分散到各个workder上,各个workers计算其拥有的数据的best splits point, 之后再汇总得到全局最优分割点,然后还需要把分割的结果再次分给各个worker,重复。

lightgbm不同点:每个worker都存储全部数据量,只需要局部最优分割点通讯,获得最优分割点,然后把最优分割点分给各个worker,重复。(通讯量,有含最优分割点的数据变成最优分割点的信息)

在这里插入图片描述

b. data parallel

传统的data parallel是将对数据集进行划分,也叫 平行分割(partion data horizontally), 分散到各个workers上之后,workers对得到的数据做直方图,汇总各个workers的直方图得到全局的直方图。

lightgbm的做法是使用”Reduce Scatter“机制,不汇总所有直方图,不同worker针对不同feature进行直方图汇总,然后不同特征的global 直方图再次汇总,做split,最后同步。

lightgbm 并行理解 博文 (推荐)
官网解释 并行机构

c. voting pv-tree

It uses two-stage voting to reduce the communication cost of feature histograms

使用投票来代替直方图通讯。
在这里插入图片描述
简而言之,就是,先候选出比较好的分割特征信息(每个worker),然后再汇总,组成总的global histograms,这时候再使用遍历,找最佳(先大范围,再小范围找最优。)

lightgbm 常用参数:

params = {
    'max_depth': 8,
    'task': 'train',
    'boosting_type': 'gbdt',
    'objective': 'binary',
    'metric': 'binary_error',
    'num_leaves': 31,
    'learning_rate': 0.05,
    'feature_fraction': 0.9,
    'bagging_fraction': 0.8,
    'bagging_freq': 5
}

其他:
lightgbm 高级实践用法 github;

6. 总结

Q1:Xgboost如何确定特征重要性?
A:
特征重要性可以用来做模型可解释性,这在风控等领域是非常重要的方面。xgboost实现中Booster类get_score方法输出特征重要性,其中importance_type参数支持三种特征重要性的计算方法:
1.importance_type=weight(默认值),特征重要性使用特征在所有树中作为划分属性的次数。2.importance_type=gain,特征重要性使用特征在作为划分属性时loss平均的降低量。3.importance_type=cover,特征重要性使用特征在作为划分属性时对样本的覆盖度。

Q2:Xgboost 的核心参数?
A:
模型正则化参数:
在这里插入图片描述
对叶节点的个数,L1,L2正则化的权重;

树的重要参数:树的数目;深度;树分类的增益阈值等。

模型学习参数:学习率;

样本参数:列抽样;行抽样比例;

这些参数都防止过拟合,以及学习收敛更快。

Q3: Lightgbm的重要参数?

和xgboost大同小异,但参数名称或者实现方式不一样:
学习率,叶节点数目,叶节点hessian值和的最小值(判断是否分裂),分裂的最小增益,bagging的比例,特征抽取比例,L1正则,L2正则。
在这里插入图片描述

Q4: XGboost模型跟LR模型的区别:
(1)模型
LR线性分类器, VC维是 d+1; XGBoost 作为boosting模型,可以无限分裂, 具有无限逼近样本VC维的特点, 因此,VC维远远大于 d+1.

(2) 策略
LR输出是y = 1的概率, 在极大似然下, LR的loss是交叉熵。LR的准则是最大熵原理,也就是, “为了追求最小分类误差”。

XGBoost的回归树的残差的绝对值的二阶导数,最小残差,本质上是回归算法。

残差不能使用SGD等梯度优化算法。

(3)算法
XGBoost添加了正则,包括树节点个数,叶节点的分数的L2平方。

(4)特征
XGBoost具有特征组合的能力, 而LR对每一维的特征都假设独立。


最近开通了个公众号,主要分享推荐系统,风控等算法相关的内容,感兴趣的伙伴可以关注下。
在这里插入图片描述


  1. Vico_Men 来源:CSDN
  2. GBDT 原论文;
  3. Xgboost 论文
  4. Lightgbm 论文
  5. CSDN 详解lightgbm
  6. random forest 中文博客
  7. Random forest 论文
  8. CSDN: XGBoost、LightGBM的详细对比介绍;
  9. 陈天奇 xgboost slide
  10. (推荐)『我爱机器学习』集成学习(四)LightGBM 这是我看到过介绍lightgbm最好的博文!
  11. zhihu: 快的不要不要的lightGBM;
  12. 论文:A Communication-Efficient Parallel Algorithm for Decision Tree;
  13. lightgbm 官方介绍视频(v.qq.com);
  14. GPU-acceleration for Large-scale Tree Boosting;
  15. A Communication-Efficient Parallel Algorithm for Decision Tree;
  16. Lightgbm 官方文档
  17. CSDN: Lightgbm 直方图优化算法深入理解;
  18. Gbdt、xgb、lgb、cat面经整理——from牛客;
  19. zhihu XGBoost特征重要性的实现原理? 作者:yymWater;
  20. 掘金:LightGBM,XGBoost构建过程
  21. CSDN:XGBoost 和 LightGBM 参数对比与调参
  22. Lightgbm features官方文档
  23. 随机森林 官方文档;
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

rosefunR

你的赞赏是我创作的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值