集成学习小结(RF、adaboost、xgboost)
回顾监督学习的一些要素
训练样本:\(x_i\)
模型:给定 \(x_i\) 预测 \(\hat{y}_i\)
参数:需要从数据中学到的 \(\theta = \{w_j|j=1,2,\cdots,d\}\)
目标函数
\[obj(\theta) = L(\theta)+ \Omega(\theta)
\]即损失函数和正则化项。优化损失函数以拟合模型不断的逼近原始数据分布,优化正则项防止模型过拟合
- Loss
- square loss: \(l(y_i,\hat{y}_i) = (y_i,\hat{y}_i)^2\)
- logistic loss: \(l(y_i,\hat{y}_i) = y_iln(1+e^{-\hat{y}_i})+(1-y_i)ln(1+e^{y_i})\)
- Regularization
- L2: \(\Omega(w) = \lambda||w||^2\)
- L1: \(\Omega(w) = \lambda||w||_1\)
- Loss
集成学习(学什么)
bagging | boosting | |
---|---|---|
算法 | random forest | adaboost, GBDT, Xgboost,LightGBM... |
采样 | 有放回的抽取和原始数据大小相同的样本集合 | 不同模型的采样方式不同(行采样、列采样) |
优缺点 | 高偏差,底方差 | 高方差,低偏差 |
bagging
高偏差,底方差
bagging的代表模型随机森林
- 为什么叫随机森林?随机性体现在两个方面:
- 数据随机:每次从数据集中,有放回的随机采样和原数据集大小相同的数据
- 特征随机:树生成时,随机选择部分特征计算增益进行划分
- 随机森林如何计算特征重要性?
- 袋外数据法
- 对每一颗决策树,选择相应的袋外数据(out of bag,OOB)计算袋外数据误差,记为errOOB1.
- 随机对袋外数据OOB所有样本的特征X加入噪声干扰(可以随机改变样本在特征X处的值),再次计算袋外数据误差,记为errOOB2。
- 假设森林中有N棵树,则特征X的重要性=∑(errOOB2-errOOB1)/N。如果加入随机噪声后,袋外数据准确率大幅度下降(即errOOB2上升),说明这个特征对于样本的预测结果有很大影响,进而说明重要程度比较高。
- 基尼指数(Gini index)法
- 袋外数据法
boosting
高方差,低偏差
模型:假设有 \(K\) 棵树
\[\hat{y}_{i}=\sum_{k=1}^{K} f_{k}\left(x_{i}\right), \quad f_{k} \in(\mathcal{F})
\]参数
- 每棵树的结构,叶子结点分数
- 不再是学习权重,而是学习函数(树)\(\theta={f_1,f_2,\cdots,f_K}\)
怎么学习树呢?
Define objective (loss, regularization), and optimize it!!
定义目标函数
\[O b j=\sum_{i=1}^{n} l\left(y_{i}, \hat{y}_{i}\right)+\sum_{k=1}^{K} \Omega\left(f_{k}\right)
\]- 如何定义树的复杂度?
- 树的深度、结点数量
- 叶子结点权重
- ……
- 如何定义树的复杂度?
对决策树模型,很容易想到下面的信息
- 使用信息增益选择特征:信息增益对应Loss
- 剪枝处理:正则化
- 树的最大深度:对树进行约束
- 叶子结点值平滑处理:叶子结点权重L2正则化
adaboost
基于误差改变样本权重
- 分类误差率是误分类样本的权值之和
原始的adaboost只能直接用于二分类
梯度提升(怎么学)
GBDT
用残差的负梯度拟合
Xgboost
我们已经定义了模型和目标函数,知道要去学什么,下面我们看看怎么学?
目标函数:
\[\sum_{i=1}^{n} l\left(y_{i}, \hat{y}_{i}\right)+\sum_{k} \Omega\left(f_{k}\right), f_{k} \in \mathcal{F}
\]在一般的监督学习算法,我们可以使用梯度下降求解找到最优参数。但是现在参数变成树,如何找到最优的一组树
Boosting(叠加式训练)
\[\begin{aligned}
\hat{y}_{i}^{(0)} &=0 \\
\hat{y}_{i}^{(1)} &=f_{1}\left(x_{i}\right)=\hat{y}_{i}^{(0)}+f_{1}\left(x_{i}\right) \\
\hat{y}_{i}^{(2)} &=f_{1}\left(x_{i}\right)+f_{2}\left(x_{i}\right)=\hat{y}_{i}^{(1)}+f_{2}\left(x_{i}\right) \\
& \cdots \\
\hat{y}_{i}^{(t)} &=\sum_{k=1}^{t} f_{k}\left(x_{i}\right)=\hat{y}_{i}^{(t-1)}+f_{t}\left(x_{i}\right)
\end{aligned}
\]\(\hat{y}^{(t)}_i\) 表示训练第 \(t\) 棵树后对应的模型,\(\hat{y}_{i}^{(t-1)}\) 表示已经训练好的 \(t-1\) 棵树组成的模型,\(f_{t}(x_{i})\) 代表第 \(t\) 棵树。
如何确定第 \(t\) 棵树?
- 优化目标函数
第 \(t\) 轮的预测结果为 \(\hat{y}_{i}^{(t)}=\hat{y}_{i}^{(t-1)}+f_{t}\left(x_{i}\right)\)
训练的目标函数为
\[\begin{aligned}
O b j^{(t)} &=\sum_{i=1}^{n} l\left(y_{i}, \hat{y}_{i}^{(t)}\right)+\sum_{i=1}^{t} \Omega\left(f_{i}\right) \\
&= \sum_{i=1}^{n} l\left(y_{i}, \hat{y}_{i}^{(t-1)}+f_{t}\left(x_{i}\right)\right)+ \sum_{i=1}^{t-1} \Omega\left(f_{i}\right) +\Omega\left(f_{t}\right)
\\
&= \sum_{i=1}^{n} l\left(y_{i}, \hat{y}_{i}^{(t-1)}+f_{t}\left(x_{i}\right)\right)+\Omega\left(f_{t}\right)+\text {constant }
\end{aligned}
\]因为前 \(t-1\) 棵树已经训练了,树已经确定了,所以复杂度是常数
使用 square loss
\[\begin{aligned}
O b j^{(t)} &=\sum_{i=1}^{n}\left(y_{i}-\left(\hat{y}_{i}^{(t-1)}+f_{t}\left(x_{i}\right)\right)\right)^{2}+\Omega\left(f_{t}\right)+\text {const } \\
&=\sum_{i=1}^{n}\left[2\left(\hat{y}_{i}^{(t-1)}-y_{i}\right) f_{t}\left(x_{i}\right)+f_{t}\left(x_{i}\right)^{2}\right]+\Omega\left(f_{t}\right)+\text {const }
\end{aligned}
\]
使用泰勒级数近似
使用二阶展开 \(f(x+\Delta x) \simeq f(x)+f^{\prime}(x) \Delta x+\frac{1}{2} f^{\prime \prime}(x) \Delta x^{2}\)
考虑函数 \(L(y_i,\hat{y}_{i}^{(t-1)}+f_{t}(x_i)) = f(x+\Delta x)\) ,在 \(\hat{y_i}^{(t-1)}\) 二阶展开
\[O b j^{(t)} \simeq \sum_{i=1}^{n}\left[l\left(y_{i}, \hat{y}_{i}^{(t-1)}\right)+g_{i} f_{t}\left(x_{i}\right)+\frac{1}{2} h_{i} f_{t}^{2}\left(x_{i}\right)\right]+\Omega\left(f_{t}\right)+\text {constant }
\]其中 \(g_{i}=\partial_{\hat{y}^{(t-1)}} l\left(y_{i}, \hat{y}^{(t-1)}\right), \quad h_{i}=\partial_{\hat{y}^{(t-1)}}^{2} l\left(y_{i}, \hat{y}^{(t-1)}\right)\)
注意到 \(l(y_{i}, \hat{y}_{i}^{(t-1)}),g_i,h_i\) 都是已知的(因为是前 \(t-1\) 棵树)
- 如果使用平方损失,就会是这个样子
\[g_{i}=\partial_{\hat{y}^{(t-1)}}\left(\hat{y}^{(t-1)}-y_{i}\right)^{2}=2\left(\hat{y}^{(t-1)}-y_{i}\right) \\h_{i}=\partial_{\hat{y}^{(t-1)}}^{2}\left(y_{i}-\hat{y}^{(t-1)}\right)^{2}=2
\]
我们找到可以求解的目标函数了吗?还没有!!\(f_t(x_i)和\Omega(f_t)\) 还没有定义,如何定义?
- 如果使用平方损失,就会是这个样子
定义一棵树
我们用树的目的是什么?根据样本找到合理的预测值 $f_t(x_i) $,如果我们将叶子结点的值作为预测值 \(w\),样本所在的位置记为 \(q(x_i)\):
\[f_{t}(x_i)=w_{q(x_i)}
\]对下面的树,\(w=\{2,0.1,-1\}\)
所以 \(x_i\) 分别为小男孩、老奶奶、小女孩。对应的 \(f_t(x_i )\) 为 \(w[q_{(x_1)}]=w[1]=2,\quad w[q_{(x_5)}]=w[3]=-1,\quad w[q_{(x_4)}]=w[2]=0.1\)
- 可以这样定义树的复杂度
\[\Omega\left(f_{t}\right)=\gamma T+\frac{1}{2} \lambda \sum_{j=1}^{T} w_{j}^{2}
\]其中 \(T\) 表示叶子结点数量,后一项是对叶子结点值进行 \(L2\) 正则。上面那棵树的复杂度就可以表示为 \(\Omega\left(f_{t}\right)=\gamma 3+\frac{1}{2} \lambda (4+0.01+1)\)
同时定义叶子结点的样本集合为 (落在结点 \(j\) 的样本有哪些):
\[I_{j}=\left\{i | q\left(x_{i}\right)=j\right\}
\]对应的 \(I_1 = \{小男孩(x_1)\},I_2=\{小女孩(x_4)\},I_3 = \{妈妈,爷爷,奶奶(x_2,x_3,x_5)\}\)。这棵树的目标函数中 \(g_iw_{q(x_i)}\) 可以表示为:
\[\sum_{i=1}^5 g_iw_{q(x_i)} = g_1w_{q(x_1)}+g_2w_{q(x_2)}+g_3w_{q(x_3)}+g_4w_{q(x_4)}+g_5w_{q(x_5)}\\
= g_1w_{q(x_1)}+g_2w_{q(x_2)}+[g_3+g_4+g_5]w_{q(x_5)}\\
=\sum_{i\in I_1}g_1w_{q(x_1)}+\sum_{i\in I_2}g_2w_{q(x_2)}+\sum_{i\in I_3}g_iw_{q(x_3)}\\
= \sum_{j=1}^3 \left[(\sum_{i\in I_1}g_i)w_{q(x_j)}+(\sum_{i\in I_2}g_i)w_{q(x_j)}+(\sum_{i\in I_3}g_i)w_{q(x_j)} \right]
\]- 可以这样定义树的复杂度
新的目标函数
将按照样本优化 转化 为按叶子结点优化
\[\begin{aligned}
O b j^{(t)} & \simeq \sum_{i=1}^{n}\left[g_{i} f_{t}\left(x_{i}\right)+\frac{1}{2} h_{i} f_{t}^{2}\left(x_{i}\right)\right]+\Omega\left(f_{t}\right) \\
&=\sum_{i=1}^{n}\left[g_{i} w_{q\left(x_{i}\right)}+\frac{1}{2} h_{i} w_{q\left(x_{i}\right)}^{2}\right]+\gamma T+\lambda \frac{1}{2} \sum_{j=1}^{T} w_{j}^{2} \\
&=\sum_{j=1}^{T}\left[\left(\sum_{i \in I_{j}} g_{i}\right) w_{j}+\frac{1}{2}\left(\sum_{i \in I_{j}} h_{i}+\lambda\right) w_{j}^{2}\right]+\gamma T \\
&= \sum_{j=1}^{T}\left[G_jw_{j}+\frac{1}{2}\left(H_j+\lambda\right) w_{j}^{2}\right]+\gamma T
\end{aligned}
\]将\(w\) 看做参数,上面的式子是一元二次方程,\(G_j、H_j\)分别表示对应叶子节点的样本集。\(ax^2+by+c=0\) 大家都很熟悉,在\(x=-\frac{b}{2a}\) 处取最小值,类似的:
\[w_{j}^{*}=-\frac{G_{j}}{H_{j}+\lambda} \quad O b j=-\frac{1}{2} \sum_{j=1}^{T} \frac{G_{j}^{2}}{H_{j}+\lambda}+\gamma T
\]现在可以计算这棵树的目标函数了:
目标函数的值更小,对应的树的结构更好。
这就结束了吗?不,才刚刚开始
在上面求解目标函数时,我们假设已知第 \(t\) 棵树的结构了,然后得到了这棵树对应的score。但是,现在我们不知道树的结构,怎么办?我可以根据已有样本,穷举所有可能的树,找到最小的目标函数值,就对应最优的那棵树。但是穷举这件事,还是不太靠谱,计算复杂度太高了...
贪心算法生成树
回顾决策树方法,我们通过计算信息增益,寻找信息增益最大的特征进行划分,\(g(D,A) = H(D)-H(D|A)\), 信息增益越大就是让熵变化最大,即 \(max(原不确定性-划分后不确定性)\) 。对应的,我们选择新的 \(obj\) 和 旧的 \(obj\) 差异最大的进行划分。
从深度为0开始构建树
对每个结点尝试划分,目标函数将会改变:
怎么快速找到划分点?
- 将样本特征排序,从左至右线性扫描
具体来说,对每个结点,枚举所有的特征
- 对每个特征,根据特征值将样本排序
- 排序后,进行线性扫描,确定最佳划分特征
复杂度是多少?
- \(O(ndKlogn)\),\(d\) 个特征,每个特征排序需要\(O(nlogn)\),树深度为\(K\),需要\(K\)次。
回顾整个过程
每次迭代生成一颗新的树
每次迭代开始,计算:
\[g_{i}=\partial_{\hat{y}^{(t-1)}} l\left(y_{i}, \hat{y}^{(t-1)}\right), \quad h_{i}=\partial_{\hat{y}^{(t-1)}}^{2} l\left(y_{i}, \hat{y}^{(t-1)}\right)
\]贪心策略生成第 \(t\) 棵树
\[O b j=-\frac{1}{2} \sum_{j=1}^{T} \frac{G_{j}^{2}}{H_{j}+\lambda}+\gamma T
\]
将第\(k\)棵树加入到模型中:
\(y^{(t)}=y^{(t-1)}+\epsilon f_{t}\left(x_{i}\right)\),\(\epsilon\) 表示学习率
几种模型比较
Xgboost 与 GBDT
目标函数方面:
- 传统GBDT在优化时只用到一阶导数信息,xgboost则对代价函数进行了二阶泰勒展开,同时用到了一阶和二阶导数。二阶偏导相当于找到了一阶导数的下降方向, 会使梯度下降的更快, 收敛的更快
- xgboost在代价函数里加入了正则项,用于控制模型的复杂度。正则项里包含了树的叶子节点个数、每个叶子节点上输出的score的L2模的平方和。从Bias-variance tradeoff角度来讲,正则项降低了模型的variance,使学习出来的模型更加简单,防止过拟合,这也是xgboost优于传统GBDT的一个特性。
- Shrinkage(缩减),相当于学习速率(xgboost中的eta)。xgboost在进行完一次迭代后,会将叶子节点的权重乘上该系数,主要是为了削弱每棵树的影响,让后面有更大的学习空间。实际应用中,一般把eta设置得小一点,然后迭代次数设置得大一点。(补充:传统GBDT的实现也有学习速率)
模型构建方面
传统GBDT以CART作为基分类器,xgboost还支持线性分类器,这个时候xgboost相当于带L1和L2正则化项的逻辑斯蒂回归(分类问题)或者线性回归(回归问题)。(只要函数可一阶和二阶求导。)
列抽样(column subsampling)。xgboost借鉴了随机森林的做法,支持列抽样,不仅能降低过拟合,还能减少计算,这也是xgboost异于传统gbdt的一个特性。
对缺失值的处理。对于特征的值有缺失的样本,xgboost可以自动学习出它的分裂方向。
(多线程并行)xgboost工具支持并行。boosting不是一种串行的结构吗?怎么并行的?
注意xgboost的并行不是tree粒度的并行,xgboost也是一次迭代完才能进行下一次迭代的(第t次迭代的代价函数里包含了前面t-1次迭代的预测值)。xgboost的并行是在特征粒度上的。我们知道,决策树的学习最耗时的一个步骤就是对特征的值进行排序(因为要确定最佳分割点),xgboost在训练之前,预先对数据进行了排序,然后保存为block结构,后面的迭代中重复地使用这个结构,大大减小计算量。这个block结构也使得并行成为了可能,在进行节点的分裂时,需要计算每个特征的增益,最终选增益最大的那个特征去做分裂,那么各个特征的增益计算就可以开多线程进行。
可并行的近似直方图算法。树节点在进行分裂时,我们需要计算每个特征的每个分割点对应的增益,即用贪心法枚举所有可能的分割点。当数据无法一次载入内存或者在分布式情况下,贪心算法效率就会变得很低,所以xgboost还提出了一种可并行的近似直方图算法,用于高效地生成候选的分割点。
xgboost 和 LR
xgboost擅长连续值处理,LR擅长离散值处理
LR将特征离散化原因?
- 增强泛化能力
- 稀疏向量,计算简单
- 离散后方便特征交叉
缺失值处理
one-hot
GBDT+LR
为什么建树采用GBDT而非RF?
且GBDT前面的树,特征分裂主要体现对多数样本有区分度的特征;后面的树,主要体现的是经过前N颗树,残差仍然较大的少数样本。优先选用在整体上有区分度的特征,再选用针对少数样本有区分度的特征,思路更加合理,这应该也是用GBDT的原因
adaboost只能用于二分类
LightGBM
直方图差加速
一个叶子的直方图可以由它的父亲节点的直方图与它兄弟的直方图做差得到, 在分裂节点的时候, 计算玩所有左孩子的直方图之后, 直接用父节点的直方图-左孩子的直方图就可以得到右孩子的直方图.特征并行减少了传输切分结果的步骤
每个worker上保留完整的数据集,而不是列采样子集(空间换时间)
数据并行
- 不合并所有局部直方图得到全局直方图。合并无交叉的不同特征的直方图
- 使用直方图差,减少叶节点传输
references
https://zhuanlan.zhihu.com/p/34534004
https://homes.cs.washington.edu/~tqchen/pdf/BoostedTree.pdf
http://wepon.me/files/gbdt.pdf
李航. 统计学习方法
周志华. 机器学习
http://www.mamicode.com/info-detail-2548410.html
集成学习小结(RF、adaboost、xgboost)的更多相关文章
- 决策树(中)-集成学习、RF、AdaBoost、Boost Tree、GBDT
参考资料(要是对于本文的理解不够透彻,必须将以下博客认知阅读): 1. https://zhuanlan.zhihu.com/p/86263786 2.https://blog.csdn.net/li ...
- 集成学习之Boosting —— AdaBoost实现
集成学习之Boosting -- AdaBoost原理 集成学习之Boosting -- AdaBoost实现 AdaBoost的一般算法流程 输入: 训练数据集 \(T = \left \{(x_1 ...
- 集成学习之Boosting —— AdaBoost原理
集成学习大致可分为两大类:Bagging和Boosting.Bagging一般使用强学习器,其个体学习器之间不存在强依赖关系,容易并行.Boosting则使用弱分类器,其个体学习器之间存在强依赖关系, ...
- 集成学习原理:Adaboost
集成学习通过从大量的特征中挑出最优的特征,并将其转化为对应的弱分类器进行分类使用,从而达到对目标进行分类的目的. 核心思想 它是一种迭代算法,其核心思想是针对同一个训练集训练不同的分类器(弱分类器), ...
- 【Python机器学习实战】决策树与集成学习(七)——集成学习(5)XGBoost实例及调参
上一节对XGBoost算法的原理和过程进行了描述,XGBoost在算法优化方面主要在原损失函数中加入了正则项,同时将损失函数的二阶泰勒展开近似展开代替残差(事实上在GBDT中叶子结点的最优值求解也是使 ...
- 【集成学习】sklearn中xgboost模块的XGBClassifier函数
# 常规参数 booster gbtree 树模型做为基分类器(默认) gbliner 线性模型做为基分类器 silent silent=0时,不输出中间过程(默认) silent=1时,输出中间过程 ...
- 【集成学习】sklearn中xgboost模块中plot_importance函数(绘图--特征重要性)
直接上代码,简单 # -*- coding: utf-8 -*- """ ################################################ ...
- 【Python机器学习实战】决策树与集成学习(六)——集成学习(4)XGBoost原理篇
XGBoost是陈天奇等人开发的一个开源项目,前文提到XGBoost是GBDT的一种提升和变异形式,其本质上还是一个GBDT,但力争将GBDT的性能发挥到极致,因此这里的X指代的"Extre ...
- 集成学习之Boosting —— XGBoost
集成学习之Boosting -- AdaBoost 集成学习之Boosting -- Gradient Boosting 集成学习之Boosting -- XGBoost Gradient Boost ...
随机推荐
- PHP password_get_info() 函数
password_get_info() 函数用于返回指定散列(hash)的相关信息. PHP 版本要求: PHP 5 >= 5.5.0, PHP 7高佣联盟 www.cgewang.com 语法 ...
- intel:spectre&Meltdown侧信道攻击(五)—— DRAM address mapping
前面介绍了row hammer,理论上很完美,实际操作的时候会面临很尴尬的问题:内存存储数据最小的单位是cell(就是个电容,充电是1,放电是0),无数个横着的cell组成row,无数个竖着的cell ...
- python5.1文件的读取
fh1=open(r"C:\222.txt","r")#用open函数读取文件,“r”进行转义,fh1文件句柄data=fh1.read()#把读取的句柄赋值给 ...
- 微信小程序--家庭记账小账本(五)
(源码已上传至github,https://github.com/xhj1074376195/CostBook_weixin) 今天,尝试弄了账单的表,发现还是弄不了,于是就把账单上的删除功能给去了, ...
- VMWare虚拟机问题总结
windows7提示:在该系统上全局禁用了虚拟打印功能,不会为该虚拟机启用此功能,虚拟设备:'seria10'将断开连接. 解决:打开虚拟机前选择 编辑-->首选项-->设备--&g ...
- C#LeetCode刷题之#532-数组中的K-diff数对(K-diff Pairs in an Array)
问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3716 访问. 给定一个整数数组和一个整数 k, 你需要在数组里找 ...
- 【工具-代码】OSS阿里云存储服务-代码实现
上一章节[工具]OSS阿里云存储服务--超级简单--个人还是觉得Fastdfs好玩 https://www.cnblogs.com/Yangbuyi/p/13488323.html 接上一个文章讲解还 ...
- hdfs学习(二)
一.HDFS文件限额配置 在多人共用HDFS的环境下,配置设置非常重要.特别是在Hadoop处理大量资料的环境,如果没有配额管理,很容易把所有的空间用完造成别人无法存取.Hdfs的配额设定是针对目录而 ...
- JavaScript 基础四
遍历对象的属性 for...in 语句用于对数组或者对象的属性进行循环操作. for (变量 in 对象名字) { 在此执行代码 } 这个变量是自定义 符合命名规范 但是一般我们 都写为 k 或则 k ...
- 在GitHub上删除仓库 or 项目,基操!!
创建错误或者想要抛弃某个仓库or项目,点击选择项目,选择Setting页面,左侧方框Option页拉到底: 你就可以看到一个红色的危险域,called Danger Zone,这不禁让我想到了黑子篮球 ...