Bagging:各分类器之间没有依赖关系,可各自并行,
Bagging + 决策树 = 随机森林
Boosting:各分类器之间有依赖关系,必须串行,
比如Adaboost、GBDT(Gradient Boosting Decision Tree)、Xgboost
AdaBoost + 决策树 = 提升树
Gradient Boosting + 决策树 = GBDT
AdaBoost(Adaptive Boosting自适应增强):
前一个基本分类器被错误分类的样本的权值会增大,而正确分类的样本的权值会减小,并再次用来训练下一个基本分类器。同时,在每一轮迭代中,加入一个新的弱分类器,直到达到某个预定的足够小的错误率或达到预先指定的最大迭代次数才确定最终的强分类器。
Boosting根据错误率调整样本权重,错误率越大的样本权重越大。
使用boosted tree作为学习算法的优势:
- 使用不同类型的数据时,不需要做特征标准化/归一化
- 可以很容易平衡运行时效率和精度;比如,使用boosted tree作为在线预测的模型可以在机器资源紧张的时候截断参与预测的树的数量从而提高预测效率
- 学习模型可以输出特征的相对重要程度,可以作为一种特征选择的方法 模型可解释性好 对数据字段缺失不敏感
- 能够自动做多组特征间的interaction,具有很好的非性线性
特征重要度的计算 Friedman在GBM的论文中提出的方法:
特征j的全局重要度通过特征j在单颗树中的重要度的平均值来衡量
其中,M是树的数量。特征 j在单颗树中的重要度的如下
L为树的叶子节点数量,
L−1即为树的非叶子节点数量(构建的树都是具有左右孩子的二叉树),
vt是和节点 t相关联的特征,
it2是节点t分裂之后平方损失的减少值
一 .随机森林
单颗决策树:易过拟合
传统机器学习处理过拟合通常采用集成学习 (多颗树投票)
1.1 随机森林的生成方法
【在bagging的基础上+CART树】
1.从总数为N样本集中通过重采样的方式产生n个样本 (Bootstrap)
2.假设样本特征数目为a,对n个样本选择其中k个特征, 用建立决策树的方式获得最佳分割点
3.重复m次,产生m棵决策树
4.对于分类问题,按多棵树分类器投票决定最终分类结果;
对于回归问题,由多棵树预测值的均值决定最终预测结果
1.2 随机森林的随机性
1、每棵树的训练样本是随机的。
2、每棵树的训练特征集合也是随机从所有特征中抽取的。
两个随机性的引入对随机森林的分类性能至关重要。由于它们的引入,使得随机森林不容易陷入过拟合,并且具有很好得抗噪能力(比如:对缺省值不敏感)
1.3 使用随机森林去弥补特征向量中的缺失值
对于训练集中的缺失值,可以使用均值,0等方式进行预填充,然后使用随机森林分类,同一个分类下的数据,更新缺失值。
如果是分类变量缺失,用众数补上,
如果是连续型变量缺失,用中位数补上,
然后再次使用随机森林分类更新缺失值,4-6轮后可以达到一个比较好的效果。
1.4 使用随机森林对特征重要性进行评估
每个特征在随机森林中的每颗树上的贡献,然后取平均值对比
通常可以用基尼指数(Gini index)或者袋外数据(OOB)错误率作为评价指标来衡量。
特征Xj在节点m的重要性,即节点m分枝前后的Gini指数变化量
1.5 随机森林为什么不能用全样本去训练m颗决策树
全样本训练忽视了局部样本的规律(各个决策树趋于相同),对于模型的泛化能力是有害的,使随机森林算法在样本层面失去了随机性。
1.6 随机森林分类效果(错误率)与两个因素有关
森林中任意两棵树的相关性:相关性越大,错误率越大;
森林中每棵树的分类能力:每棵树的分类能力越强,整个森林的错误率越低。
减小特征选择个数m,树的相关性和分类能力也会相应的降低;
增大m,两者也会随之增大。
所以关键问题是如何选择最优的m(或者是范围),这也是随机森林唯一的一个参数。
1.6 OOB(Out Of Bag)袋外错误率
在bootstrapping的过程中,有些数据可能没有被选择,这些数据称为out-of-bag(OOB) examples。
1/N:每次抽样的概率
OOB:不管如何,总是接近于1/e
袋外错误率的应用
在随机森林中,有了out-of-bag(OOB) examples,我们就不需要拿出一部分数据了,out-of-bag(OOB) examples就是那部分没有用到的数据,我们可以直接当成验证集来使用。
obb error = 被分类错误数 / 总数
随机森林算法中不需要再进行交叉验证或者单独的测试集来获取测试集误差的无偏估计。
Breiman [1996b]在对 bagged 分类器的错误率估计研究中, 给出实证证据显示,out-of-bag 估计 和使用与训练集大小一致的测试集所得到的错误率一样精确. 所以, 使用out-of-bag error 估计可以不在另外建立一个测试集.
1.7 随机森林的优缺点
随机森林的优点
- 具有极高的准确率
- 引入两阶段随机 防止过拟合很好的抗噪声能力
- 既能处理离散型数据,也能处理连续型数据,数据集无需规范化
- 能处理很高维度的数据,并且不用做特征选择
- 可以得到变量重要性排序
- 训练可以高度并行化且性能普遍较好,对于大数据时代的大样本训练速度有优势
训练速度快- 能有效处理缺失值,就算存在大量的数据缺失,随机森林也能较好地保持精确性,一方面因为随机森林随机选取样本和特征,另一方面因为它可以继承决策树对缺失数据的处理方式。如果缺失数据的样本只是少量,随机森林甚至可以帮助去估计缺失值。
- 由于采用了随机采样,训练出的模型的方差小,对generlization error(泛化误差)使用的是无偏估计模型,泛化能力强
- 对于不平衡数据集来说,随机森林可以平衡误差。当存在分类不平衡的情况时,随机森林能提供平衡数据集误差的有效方法。(对正类和反类分别进行重采样或欠采样,
随机森林的缺点:
- 当随机森林中的决策树个数很多时,训练时需要的空间和时间会较大
- 对于许多统计建模者来说,随机森林给人的感觉就像一个黑盒子,你无法控制模型内部的运行。只能在不同的参数和随机种子之间进行尝试。
- 可能有很多相似的决策树,掩盖了真实的结果
- 对于小数据或者低维数据(特征较少的数据),可能不能产生很好的分类(随机性大大降低了)。
(处理高维数据,处理特征遗失数据,处理不平衡数据是随机森林的长处)- 执行数据虽然比boosting等快(随机森林属于bagging),但比单只决策树慢多了,且精度一般不如boosting方法
- 随机森林在解决回归问题时,并没有像它在分类中表现的那么好,这是因为它并不能给出一个连续的输出。当进行回归时,随机森林不能够做出超越训练集数据范围的预测,这可能导致在某些特定噪声的数据进行建模时出现过度拟合。(PS:随机森林已经被证明在某些噪音较大的分类或者回归问题上会过拟合)。
1.8 随机森林为什么不容易过拟合
随机森林由很多树组合在一起,单看每一棵树都可以是过拟合的,但是,既然是过拟合,就会拟合到非常小的细节上,因此随机森林通过引入随机性,让每一棵树拟合的细节不同,这时再把这些树组合在一起,过拟合的部分就会自动被消除掉。
所以随机森林不容易过拟合,但这不是绝对的,随机森林也是有可能出现过拟合的现象,只是出现的概率相对低。
就好比人类社会,有计算机的专家,也有神经生物学的专家,还有一个天文学的专家,这就像三颗过拟合的树,对于各自领域性能都很优秀,但对于宗教这类知识,三个人都不是很懂。由于三个人都处在同一个社会中,在社会中长久下来也有或多或少的接触过这方面的知识,于是三个人可以通过综合判断,得出宗教方面的一些正确答案。
当在随机森林中,如果我们用了远大于需求个数的树,就会发生过拟合的现象。所以一般在构建随机森林时我们会使用oob袋外错误率来修正模型的结构。
1.9 随机森林算法训练时主要需要调整哪些参数
1.如何选取K,可以考虑有N个属性,取K=根号N
2.最大深度(不超过8层)
3.棵数
4.最小分裂样本树
5.类别比例
1、n_estimators:随机森林建立子树的数量。较多的子树一般可以让模型有更好的性能,但同时会让代码变慢,严重的时候甚至还会导致过拟合!故需要通过交叉验证或者袋外错误率oob估计来选择最佳的随机森林子树数量。
2、max_features:随机森林允许单个决策树使用特征的最大数量。增加max_features一般能提高模型的性能,因为在每个树节点上,我们有更多的选择可以考虑。然而,这未必完全是对的,因为它降低了单个树的多样性(泛化能力),但这正是随机森林的一大特点。可以肯定的是,增加max_features会降低算法的速度,同时还会使得模型更加容易过拟合,因此,我们需要适当的平衡和选择最佳的max_features。
3、max_depth:决策树的最大深度。随机森林默认在决策树的建立过程中不会限制其深度,这也是随机森林的一大特点,其不必担心单棵树的过拟合。
4、min_samples_split:内部节点再划分所需要的最小样本数。如果某节点的样本数少于min_samples_split,则不会继续再尝试选择最优特征来进行划分。
5、min_samples_leaf:叶子节点最少样本数。这个值限制了叶子节点最少的样本数,如果某叶子节点数目小于样本数,则会和兄弟节点一起被剪枝。
6、max_leaf_nodes:最大叶子节点数。通过限制最大叶子节点数,可以防止过拟合,默认是“None”,即不限制最大的叶子节点数。如果加了限制,算法会建立在最大叶子节点数内最优的决策树。
7、min_impurity_split:节点划分最小不纯度。这个值限制了决策树的增长,如果某节点的不纯度(基于基尼系数,均方差,信息增益等)小于这个阈值,则该节点不再生成子节点。即为叶子节点。一般不推荐改动,默认值为1e-7。
概括一下,别看有整整7点,其实后5点全都是预剪枝的策略,在随机森林中,如果实在是为了防止过拟合等,可以采取预剪枝策略也就是上述的3-7方法。但对于随机森林这个模型而言,真正要调整的参数就n_estimators和max_features两个,而且在一般情况下,不需要怎么调就可以得到不错的结果。
二. GBDT
gbdt全称梯度下降树,
GBDT 求梯度推导
2.1 训练过程
gbdt通过多轮迭代,每轮迭代产生一个弱分类器,
每个分类器在上一轮分类器的残差基础上进行训练。
弱分类器一般会选择为CART TREE(也就是分类回归树)。
由于高偏差和低方差的要求 每个分类回归树的深度不会很深。
最终的总分类器 是将每轮训练得到的弱分类器加权求和得到的(也就是加法模型)。
通过经验风险极小化来确定下一个弱分类器的参数。具体到损失函数本身的选择也就是L的选择,有平方损失函数,0-1损失函数,对数损失函数等等。如果我们选择平方损失函数,那么这个差值其实就是我们平常所说的残差。
1.是希望损失函数能够不断的减小,
2.是希望损失函数能够尽可能快的减小。
所以如何尽可能快的减小呢?让损失函数沿着梯度方向的下降。这个就是gbdt 的 gb的核心了。
GBDT使用了前向分布算法,但是弱学习器限定了只能使用CART回归树模型,同时迭代思路和Adaboost也有所不同。
GBDT每一次的计算是都为了减少上一次的残差,进而在残差减少(负梯度)的方向上建立一个新的模型。
所以,当损失函数选用均方损失函数是时,每一次拟合的值就是(真实值 - 当前模型预测的值),即残差。此时的变量是,即“当前预测模型的值”,也就是对它求负梯度。
2.2 gbdt如何选择特征?
gbdt选择特征的细节其实是想问你CART Tree生成的过程。
gbdt的弱分类器默认选择的是CART TREE。其实也可以选择其他弱分类器的,选择的前提是低方差和高偏差。框架服从boosting 框架即可。
CART TREE 生成的过程其实就是一个选择特征的过程。
假设我们目前总共有 M 个特征。
第一步我们需要从中选择出一个特征 j,做为二叉树的第一个节点。
然后对特征 j 的值选择一个切分点 m.
一个样本的特征j的值如果小于m,则分为一类,
如果大于m,则分为另外一类。如此便构建了CART 树的一个节点。
其他节点的生成过程和这个是一样的。
现在的问题是在每轮迭代的时候,如何选择这个特征 j,以及如何选择特征 j 的切分点 m:
原始的gbdt的做法非常的暴力,首先遍历每个特征,然后对每个特征遍历它所有可能的切分点,找到最优特征 m 的最优切分点 j。
如何衡量我们找到的特征 m和切分点 j 是最优的呢? 我们用定义一个函数:
2.3 gbdt 如何构建特征 ?
gbdt 本身是不能产生特征的,但是我们可以利用gbdt去产生特征的组合。
在CTR预估中,工业界一般会采用逻辑回归去进行处理,逻辑回归本身是适合处理线性可分的数据,如果我们想让逻辑回归处理非线性的数据,其中一种方式便是组合不同特征,增强逻辑回归对非线性分布的拟合能力。
Facebook 在2014年 发表的一篇论文便是这种尝试下的产物,利用gbdt去产生有效的特征组合,以便用于逻辑回归的训练,提升模型最终的效果。
2.4 GBDT 如何用于分类 ?
首先明确一点,gbdt 无论用于分类还是回归一直都是使用的CART 回归树。不会因为我们所选择的任务是分类任务就选用分类树,这里面的核心是因为gbdt每轮的训练是在上一轮的训练的残差基础之上进行训练的。这里的残差就是当前模型的负梯度值 。这个要求每轮迭代的时候,弱分类器的输出的结果相减是有意义的。残差相减是有意义的。
如果选用的弱分类器是分类树,类别相减是没有意义的。
我们具体到分类这个任务上面来,我们假设样本 X 总共有 K类。来了一个样本 x,我们需要使用gbdt来判断 x 属于样本的哪一类。
其实我们可以用一个k维向量 [0,1,0] 来表示。0表示样本不属于该类,1表示样本属于该类。针对样本有k类的情况,我们实质上是在每轮的训练的时候是同时训练k颗树。
2.5 GBDT 的优缺点
GBDT相对SVM和LR的优点
- 缺失数据处理:Decision Tree 可以很好的处理 missing feature,这是他的天然特性,因为决策树的每个节点只依赖一个 feature,如果某个 feature 不存在,这颗树依然可以拿来做决策,只是少一些路径。像逻辑回归,SVM 就没这个好处。
- Decision Tree 可以很好的处理各种类型的 feature,也是天然特性,很好理解,同样逻辑回归和 SVM 没这样的天然特性。
- 对特征空间的 outlier 有鲁棒性,因为每个节点都是 x < 𝑇 的形式,至于大多少,小多少没有区别,outlier 不会有什么大的影响,同样逻辑回归和 SVM 没有这样的天然特性。
- 如果有不相关的 feature,没什么干扰,如果数据中有不相关的 feature,顶多这个 feature 不出现在树的节点里。逻辑回归和 SVM 没有这样的天然特性(但是有相应的补救措施,比如逻辑回归里的 L1 正则化)。
- 数据规模影响不大,因为我们对弱分类器的要求不高,作为弱分类器的决策树的深 度一般设的比较小,即使是大数据量,也可以方便处理。像 SVM 这种数据规模大的时候训练会比较麻烦。
GBDT的优点
- 适合低维数据
- 能处理非线性数据
- 可以灵活处理各种类型的数据,包括连续值和离散值。
- 在相对少的调参时间情况下,预测的准确率也可以比较高。这个是相对SVM来说的。
- 使用一些健壮的损失函数,对异常值的鲁棒性非常强。比如 Huber损失函数和Quantile损失函数。
- 缺失数据处理(CART对缺失值处理),
缺点-相对SVM/LR
通常在给定的不带噪音的问题上,其最佳分类效果还是不如 SVM,逻辑回归之类的。
但是,实际中往往有很大的噪音,使得 Decision Tree 这个弱势就不那么明显了。
而且,GBDT 通过不断的叠加组合多个小的 Decision Tree,他在不带噪音的问题上也能达到很好的分类效果。换句话说,通过GBDT训练组合多个小的 Decision Tree 往往要比一次性训练一个很大的 Decision Tree 的效果好很多。因此不能把 GBDT 理解为一颗大的决策树,几颗小树经过叠加后就不再是颗大树了,它比一颗大树更强。
缺点:
由于弱学习器之间存在依赖关系,难以并行训练数据。不过可以通过自采样的SGBT来达到部分并行。
如果数据维度较高时会加大算法的计算复杂度
2.6 GBDT和LR的对比
lr和gbdt的区别:
lr是线性模型,可解释性强,很容易并行化,但学习能力有限,需要大量的人工特征
gbdt是非线性模型,具有天然的特征组合的优势,特征表达能力强,但树与树之间无法并行,而且容易过拟合
结论:LR适合处理高维稀疏特征,而GBDT不适合。
主要原因有:
- 高维特征会导致gbdt运行过于耗时
- 从高维稀疏特征中难以进行有效的特征空间划分,且对噪音会很敏感。
- 高维稀疏特征大部分特征为0,假设训练集各个样本70%的特征为0,30%的特征非0。则某个维度特征在所有样本上也期望具有近似的取0的比例。当作分裂时,特征选择非常低效,特征只会在少部分特征取值非0的样本上得到有效信息。而稠密向量可以得到样本集的整体特征信息。
LR为什么在高维稀疏特征上表现较好。我的理解是:
- LR的目标就是找到一个超平面对样本是的正负样本位于两侧,由于这个模型够简单,不会出现gbdt上过拟合的问题。
- 高维稀疏特征是不是可以理解为低维的稠密特征映射到了高维空间。这里联想到了SVM的核技巧,不也是为了将特征由低维空间映射到高维空间中实现特征的线性可分吗?在SVM中已经证实了其有效性。这里面应该存在某种规律,LR在高维空间比低维空间中具有更高的期望实现更好分类效果的。
- lr等线性模型的正则化是对权重的惩罚
但是,树模型的正则化不一样,树模型的正则化为叶子结点数和深度,树只要一个结点就能完美的分割9900和10个样本,糟糕的是,这一个结点,最终产生的惩罚极其之小,人家结点数不多,也不深。
带正则化的线性模型比较不容易对稀疏特征过拟合
2.7 其他常见问题
gbdt的效果相比于传统的LR,SVM效果为什么好一些 ?
1.结合了多个弱分类器,是集成学习,所以泛化能力和准确率更高
2.SVM对于训练集不同的维度,数据量的大小,核函数的选择直接决定了模型的训练效果.gbdt相较于SVM和LR更不容易过拟合,因为它的超参学习能力较好,gbdt的泛化能力更多取决于数据集.
gbdt 如何加速训练?
XGBOOST
gbdt的参数有哪些,如何调参 ?
gbdt 实战当中遇到的一些问题 ?
由于GBDT很容易出现过拟合的问题,
所以推荐的GBDT深度不要超过6,而随机森林可以在15以上
三. XGBoost
XGBoost是陈天奇等人开发的一个开源机器学习项目,高效地实现了GBDT算法并进行了算法和工程上的许多改进,被广泛应用在Kaggle竞赛及其他许多机器学习竞赛中并取得了不错的成绩。
说到XGBoost,不得不提GBDT(Gradient Boosting Decision
Tree)。因为XGBoost本质上还是一个GBDT,但是力争把速度和效率发挥到极致,所以叫X (Extreme)GBoosted。包括前面说过,两者都是boosting方法。
xgboost是对gbdt进行来一系列的优化,比如损失函数进行了二阶展开,目标函数加入正则项,支持并行和默认缺失值处理等,在可扩展性和训练速度上有了巨大提升,但是核心思想没有大的变化。
3.1 XGBOOST 优化目标
事实上,如果不考虑工程实现、解决问题上的一些差异,XGBoost与GBDT比较大的不同就是目标函数的定义。XGBoost的目标函数如下图所示
其中:
红色箭头所指向的L 即为损失函数(比如平方损失函数:𝑙(𝑦𝑖,𝑦𝑖)=(𝑦𝑖−𝑦𝑖)2)
红色方框所框起来的是正则项(包括L1正则、L2正则)
红色圆圈所圈起来的为常数项
对于f(x),XGBoost利用泰勒展开三项,做一个近似。f(x)表示的是其中一颗回归树。
最终的目标函数只依赖于每个数据点在误差函数上的一阶导数和二阶导数。
XGBoost的核心算法思想与GBDT相同:
目标是要使得树群的预测值𝑦′𝑖尽量接近真实值𝑦𝑖,而且有尽量大的泛化能力。
3.2 正则项:树的复杂度
XGBoost对树的复杂度包含了两个部分:
一个是树里面叶子节点的个数T
一个是树上叶子节点的得分w的L2模平方(对w进行L2正则化,相当于针对每个叶结点的得分增加L2平滑,目的是为了避免过拟合)XGBoost的目标函数(损失函数揭示训练误差 + 正则化定义复杂度):
正则化公式也就是目标函数的后半部分,对于上式而言,𝑦′𝑖是整个累加模型的输出,正则化项∑kΩ(ft)是则表示树的复杂度的函数,值越小复杂度越低,泛化能力越强。
3.3 树该怎么长
节点如何进行分裂
- 枚举所有不同树结构的贪心法
选择一个特征分裂并计算loss function最小值,枚举完,找到最好的那个
总而言之,XGBoost使用了和CART回归树一样的想法,利用贪婪算法,遍历所有特征的所有特征划分点,不同的是使用的目标函数不一样。- 分裂后的目标函数值 比 单子叶子节点的目标函数 的增益
同时为了限制树生长过深,限制增益阈值,大于该阈值才分裂。
每次在上一次的预测基础上取最优进一步分裂/建树。
如何停止树的循环生成
- 当引入的分裂带来的增益小于设定阀值的时候,忽略这个分裂
- 设置树的最大深度
- 当样本权重和小于设定阈值时停止生长以防止过拟合。
超参数-最小的样本权重和min_child_weight。一个叶子节点样本太少了,也终止同样是防止过拟合;
3.3 XGBoost与GBDT有什么不同
- GBDT是机器学习算法,XGBoost是该算法的工程实现。
- 在使用CART作为基分类器时,XGBoost显式地加入了正则项来控制模 型的复杂度,有利于防止过拟合,从而提高模型的泛化能力。
- GBDT在模型训练时只使用了代价函数的一阶导数信息,XGBoost对代价函数进行二阶泰勒展开,可以同时使用一阶和二阶导数。
- 传统的GBDT采用CART作为基分类器,XGBoost支持多种类型的基分类器,比如线性分类器。 此时的xgboost相当于带L1和L2正则项的逻辑回归(分类问题)或者线性回归(回归问题)
- 传统的GBDT在每轮迭代时使用全部的数据,XGBoost则采用了与随机 森林相似的策略,支持对数据进行采样。列抽样 xgboost支持列抽样,即特征抽样,与随机森林类似,用于防止过拟合
- 传统的GBDT没有设计对缺失值进行处理,XGBoost能够自动学习出缺失值的处理策略。如果测试样本的该特征的特征值缺失,将会划入默认分支中去。
- 并行化 注意不是tree维度的并行(boosting策略类的加法模型都做不到tree级别的并行),而是特征维度的并行,xgboost预先将每个特征按特征值排好序,存储为block结构,分裂结点时,可以采用多线程并行查找每个特征的最佳分裂点,从而提升训练速度
- 处理不平衡 在计算损失函数时,考虑不平衡因素,加权损失。
3.4 为什么XGBoost要用泰勒展开,优势在哪里
XGBoost使用了一阶和二阶偏导, 二阶导数有利于梯度下降的更快更准. 使用泰勒展开取得函数做自变量的二阶导数形式,
可以在不选定损失函数具体形式的情况下, 仅仅依靠输入数据的值就可以进行叶子分裂优化计算,
本质上也就把损失函数的选取和模型算法优化/参数选择分开了. 这种去耦合增加了XGBoost的适用性, 使得它按需选取损失函数,
可以用于分类, 也可以用于回归。
可扩展性 损失函数支持自定义,只需要新的损失函数二阶可导
3.5 xgboost速度优化
并行训练是怎么并行
不是tree维度的并行(boosting策略类的加法模型都做不到tree级别的并行,每棵树训练前需要等待前面每棵树训练完成才能开始新一轮的训练)
而是特征维度的并行,xgboost预先将每个特征按特征值排好序,存储为block结构,分裂结点时,可以采用多线程并行查找每个特征(一个特征一个block块)的最佳分裂点,从而提升训练速度
如果在计算每个特征的最佳分割点时,对每个样本都进行遍历,计算复杂度会很大,这种全局扫描的方法并不适用大数据的场景。
XGBoost还提供了一种直方图近似算法,对特征排序后仅选择常数个候选分裂位置作为候选分裂点,极大提升了结点分裂时的计算效率。
做了哪些优化
分块并行,一个特征一个block块,训练前每个特征按照特征值的排序,存储为block块结构,后面查找特征分割点时可以重复使用,并且支持并且查找每个特征的分割点
候选分位点,每个特征采用常数个分位点作为候选分割点,这里注意有加权,不是直接按从小到大的分位点,而是按照权值的分位点,权值大小为二阶导。(因为可能不同的特征取值都对应同一个预测值,同一个预测值对应同一个损失,同一个二阶导,参考另一篇lightgbm8问
cpu cache命中,使用存储预取的方法,对每个线程分配一个连续的buffer,读取每个block中样本的梯度,并存入连续的buffer 中
block 处理优化,block预先放入内存中,block按列进行解压缩,将block划分导不同的硬盘提高吞吐(这条不太懂)
3.7 xgboost防止过拟合的方法
xgboost在设计之初,为了防止过拟合就采取了很多的优化,具体如下:
**目标函数加入正则项,**叶子结点个数+叶子结点权值的l2正则化
列抽样,训练时只用一部分特征,(不考虑剩余的block块即可)
子采样,下采样 每轮计算可以不采用所有的样本,使得算法更保守
shrinkage,可以叫做学习率或者布长,为了给后面的训练留出更多的学习空间
结点分裂时阈值限制,如果分裂后目标函数的增益小于该阈值,则不分裂。
当样本权重和小于设定阈值时停止生长。
XGBoost 先从顶到底建立树直到最大深度,再从底到顶反向检查是否有不满足分裂条件的结点,进行剪枝。
3.8 xgboost与缺失值
对缺失值在训练和测试时候的处理
xgboost模型的一个优点就是允许存在缺失值,对缺失值的处理如下:
在特征k上选择最佳的 分裂点时,不会对该列特征 missing的样本进行遍历,而只是对该列特征值为 non-missing的样本进行对应的特征值遍历,通过这个技巧减少了为稀疏离散特征寻找 分裂点的时间开销
逻辑实现上,为了保证完备性,会将该特征值missing的样本分别分配到左结点和右结点上去,两种情况都计算一遍后,选择分裂后增加最大的那个方向(左方向或者右方向),作为预测时特征值缺失样本的默认分支方向。
如果在训练时没有缺失值而在预测时有出现缺失值,那么会自动将缺失值的划分方向放到右结点上去。
为什么XGBoost相比某些模型对缺失值不敏感
对存在缺失值的特征,一般的解决方法是:
离散型变量:用出现次数最多的特征值填充;
连续型变量:用中位数或均值填充;
一些模型如SVM和KNN,其模型原理中涉及到了对样本距离的度量,如果缺失值处理不当,最终会导致模型预测效果很差。
而树模型对缺失值的敏感度低,大部分时候可以在数据缺失时时使用。原因就是,一棵树中每个结点在分裂时,寻找的是某个特征的最佳分裂点(特征值),完全可以不考虑存在特征值缺失的样本,也就是说,如果某些样本缺失的特征值缺失,对寻找最佳分割点的影响不是很大。
XGBoost对缺失数据有特定的处理方法, 因此,对于有缺失值的数据在经过缺失处理后:
当数据量很小时,优先用朴素贝叶斯
数据量适中或者较大,用树模型,优先XGBoost
数据量较大,也可以用神经网络
避免使用距离度量相关的模型,如KNN和SVM
3.9 xgboost的叶子结点的权值如何计算出来
xgboost经过一系列简化后最终的目标函数是:
利用一元二次函数求最值的知识,当目标函数达到最小值o b j ∗ 时,每个叶子结点的权重为w j ∗
3.10 xgboost和RF的区别
相同点: 都是多棵树,最终结果由多棵树一起决定
不同点:
集成学习 :RF属于bagging思想,gbdt属于boosting思想
偏差-方差权衡:RF在新树的生成过程中相当于不断降低模型的方差, 而GBDT在新树的生成过程中相当于不断降低模型的偏差
训练样本:RF在新树的生成过程是从全部样本集中又放回的抽样形成的, 而GBDT在新树的生成过程中采用全部数据
并行性:RF在新树的生成过程是完全可以并行的, 而GBDT在新树的生成过程中只能顺序生成
最终结果:RF对分类问题是多棵树多数表决(回归问题是取平均), 而GBDT是加权融合
数据敏感性:RF对异常数据不敏感, 而GBDT则对异常数据敏感,
联系第二点:偏差-方差权衡 泛化能力:RF不容易过拟合,而GBDT则容易过拟合,
同样联系第二点:偏差-方差权衡
3.11 xgboost如何处理不平衡数据
对于不平衡数据集,利用用户的购买行为,肯定极不平衡,这对xgboost的训练会有较大的影响,xgboost有两种自带的方法来解决:
第一种,如果你在意auc,可以通过设置scale_pos_weight来平衡正样本和负样本的权重,例如,正负样本比例是1:10时,scale_pos_weight可以取为10第二种,如何在意概率(预测得分的合理性),则不能重新平衡数据(会破坏数据真实分布),应该设置max_detla_step为一个有限数字来帮助收敛(基模型为lr时有效)。
那么,源码到底是怎么利用scale_pos_weight来平衡样本的呢,是调节权重还是过采样呢?请看源码: if
(info.labels[i] == 1.0f) w *= param_.scale_pos_weight
也就是说,应该是增大了少数样本的权重 除此之外,还可以通过上采样,下采样,或者自定义代价函数的方法来解决正负样本不平衡问题
3.12 xgboost的scalable性如何体现(可伸缩性,通用型)
基分类器的scalablity:弱分类器可以支持cart决策树,也可以支持lr和线性分类器
目标函数的scalablity: 支持自定义loss function,只需要其一阶、二阶可导。有这个特性是因为泰勒二阶展开,得到通用的目标函数形式。 学习方法的scalablity:
Block结构支持并行化,支持 Out-of-core计算。(这点也算scalablity?)
3.13 xgboost 如何评价特征重要性
我们采用三种方法来评判XGBoost模型中特征的重要程度:
weight:该特征在所有树中被用作分割样本的特征的总次数
gain :该特征在其出现过的所有树中产生的平均增益。
cover:该特征在其出现过的所有树中的平均覆盖范围。
注意:覆盖范围这里指的是一个特征用作分割点后,其影响的样本数量,即有多少样本经过该特征分割到两个子节点。
3.14 XGBooost参数调优的一般步骤
首先需要初始化一些基本变量,例如:
max_depth = 5
min_child_weight = 1
gamma = 0 subsample,
colsample_bytree = 0.8
scale_pos_weight = 1
(1)确定learning rate和estimator的数量
learning rate可以先用0.1,用cv来寻找最优的estimators
(2) max_depth和 min_child_weight
我们调整这两个参数是因为,这两个参数对输出结果的影响很大。我们首先将这两个参数设置为较大的数,然后通过迭代的方式不断修正,缩小范围。
max_depth,每棵子树的最大深度,check from range(3,10,2)。
min_child_weight,子节点的权重阈值,check from range(1,6,2)。
如果一个结点分裂后,它的所有子节点的权重之和都大于该阈值,该叶子节点才可以划分。
(3) gamma 也称作最小划分损失min_split_loss,check from 0.1 to
0.5,指的是,对于一个叶子节点,当对它采取划分之后,损失函数的降低值的阈值。 如果大于该阈值,则该叶子节点值得继续划分 如果小于该阈值,则该叶子节点不值得继续划分
(4) subsample, colsample_bytree
subsample是对训练的采样比例
colsample_bytree是对特征的采样比例 both check from 0.6 to 0.9
(5) 正则化参数 alpha 是L1正则化系数,try 1e-5, 1e-2, 0.1, 1, 100 lambda 是L2正则化系数
(6) 降低学习率 降低学习率的同时增加树的数量,通常最后设置学习率为0.01~0.1
XGBoost模型如果过拟合了怎么解决
当出现过拟合时,有两类参数可以缓解:
第一类参数:用于直接控制模型的复杂度。包括max_depth,min_child_weight,gamma 等参数
第二类参数:用于增加随机性,从而使得模型在训练时对于噪音不敏感。包括subsample,colsample_bytree
还有就是直接减小learning rate,但需要同时增加estimator 参数。
3.15 xgboost和LightGBM的区别
1.树生长策略:XGB采用level-wise的分裂策略,LGB采用leaf-wise的分裂策略。XGB对每一层所有节点做无差别分裂,但是可能有些节点增益非常小,对结果影响不大,带来不必要的开销。Leaf-wise是在所有叶子节点中选取分裂收益最大的节点进行的,但是很容易出现过拟合问题,所以需要对最大深度做限制。
2.分割点查找算法:XGB使用特征预排序算法,LGB使用基于直方图的切分点算法,其优势如下:1.减少内存占用,比如离散为256个bin时,1个Byte,8位即可,只需要用8位整形就可以保存一个样本被映射为哪个bin(这个bin可以说就是转换后的特征),对比预排序的exact greedy算法来说( 用float_32 4个Byte 保存特征值+用int_32 4个Byte来存储排序后对应的索引),可以节省7/8的空间。
2.计算效率提高,预排序的Exact greedy对每个特征都需要遍历一遍数据,并计算增益,复杂度为(#feature×#data)。而直方图算法在建立完直方图后,只需要对每个特征遍历该特征对应的直方图即可,复杂度为(#feature×#bins)。
3.LGB还可以使用直方图做差加速,一个节点的直方图可以通过父节点的直方图减去兄弟节点的直方图得到,从而加速计算 但实际上xgboost的近似直方图算法也类似于lightgbm这里的直方图算法,为什么xgboost的近似算法比lightgbm还是慢很多呢?
因为xgboost在每一层都动态构建直方图,
因为xgboost的直方图算法不是针对某个特定的feature,回忆带权分位点分割那里的知识(每个样本的权重是二阶导),每次分割后,样本重新划分,带权就需要重新调整,所有feature共享一个直方图(共享一个样本二阶导作为权的直方图),所以每一层都要重新构建直方图,而lightgbm中对每个特征都有一个直方图,并不是带权的,所以在开始时候构建一次直方图就够了。3.支持离散变量:无法直接输入类别型变量,因此需要事先对类别型变量进行编码(例如独热编码),而LightGBM可以直接处理类别型变量。
4.缓存命中率:XGB使用Block结构的一个缺点是取梯度的时候,是通过索引来获取的,而这些梯度的获取顺序是按照特征的大小顺序的,这将导致非连续的内存访问,举例来说,对ABCD四个样本,他们在某个特征上的梯度是【g_a,g_b,g_c,g_d】,而该维特征按照特征值大小排序是DBCA,则访问梯度的顺序是【g_d,g_b,g_c,g_a】,不连续的,可能使得CPU
cache缓存命中率低,从而影响算法效率。而LGB是基于直方图分裂特征的,梯度信息都存储在一个个bin中,用到某bin的时候,会把这个bin的信息放入到内存中,相当于把这个bin所包含样本的梯度信息都放入到内存中,从而访问梯度是连续的,缓存命中率高。
LightGBM 与 XGboost 的并行策略不同(这部分很工程,看的不是那么懂,只是略懂)
特征并行:LGB特征并行的前提是每个worker留有一份完整的数据集,但是每个worker仅在特征子集上进行最佳切分点的寻找;worker之间需要相互通信,通过比对损失来确定最佳切分点;然后将这个最佳切分点的位置进行全局广播,每个worker进行切分即可。XGB的特征并行与LGB的最大不同在于XGB每个worker节点中仅有部分的列数据,也就是垂直切分,每个worker寻找局部最佳切分点,worker之间相互通信,然后在具有最佳切分点的worker上进行节点分裂,再由这个节点广播一下被切分到左右节点的样本索引号,其他worker才能开始分裂。二者的区别就导致了LGB中worker间通信成本明显降低,只需通信一个特征分裂点即可,而XGB中要广播样本索引。
数据并行:当数据量很大,特征相对较少时,可采用数据并行策略。LGB中先对数据水平切分,每个worker上的数据先建立起局部的直方图,然后合并成全局的直方图,采用直方图相减的方式,先计算样本量少的节点的样本索引,然后直接相减得到另一子节点的样本索引,这个直方图算法使得worker间的通信成本降低一倍,因为只用通信以此样本量少的节点。XGB中的数据并行也是水平切分,然后单个worker建立局部直方图,再合并为全局,不同在于根据全局直方图进行各个worker上的节点分裂时会单独计算子节点的样本索引,因此效率贼慢,每个worker间的通信量也就变得很大。
投票并行(LGB):当数据量和维度都很大时,选用投票并行,该方法是数据并行的一个改进。数据并行中的合并直方图的代价相对较大,尤其是当特征维度很大时。大致思想是:每个worker首先会找到本地的一些优秀的特征,然后进行全局投票,根据投票结果,选择top的特征进行直方图的合并,再寻求全局的最优分割点。