集成学习:AdaBoost、GBDT、XGBoost、Bagging、RF

概论

集成学习(Ensemble Learning)一般结构:产生一组个体学习器(Individual Learner)再用某种策略把他们结合起来。

根据所有个体学习器相同与否分为“同质”(homogeneous)和“异质”(heterogenous)。

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

  • 个体学习器之间存在强依赖关系,必须串行生成个体生成器,如 Boosting
  • 不存在强依赖关系,可以并行生成个体生成器,如 Bagging 和 Random Forest

Boosting

Boosting 是指一类将弱学习器提升为强学习器的集成算法:

  1. 先从初始训练集训练出一个基学习器;
  2. 根据基学习器的表现对训练样本的分布做出调整,使得预测错误的样本得到更多关注;
  3. 基于调整后的训练样本训练下一个学习器;

重复训练 T 个学习器,然后再进行加权结合。

从偏差-方差角度来讲,Boosting方法主要关注于降低偏差

Note

偏差-方差分析

假设目标函数:

y=f(x)+ε

其中:

  • f(x) 是数据的真实生成过程;
  • ε 是观测噪声,满足 E[ε]=0Var(ε)=σ2
  • 我们学习的模型是 h(x),依赖于从数据集中学到的模型参数。

对于一个数据点 (x,y),泛化误差的期望是:

ED,ε[(yh(x))2]=ED,ε[(f(x)+εh(x))2]

展开后得到:

=(ED[h(x)]f(x))2偏差(Bias)2+ED[(h(x)E[h(x)])2]方差(Variance)+σ2噪声(Noise)

直观地理解:对于一个数据点,我们希望用相同数量的样本集训练这个模型时,能够得到相近的结果,且尽可能地贴合其标签。

数学形式 含义
偏差 (Bias²) (E[h(x)]f(x))2 模型预测的平均值与**真实值(注意不是标签)**之间的误差
方差 (Variance) E[(h(x)E[h(x)])2] 模型预测随不同训练集波动性大小
噪声 (Noise) σ2 数据本身的不可预测性

偏差-方差权衡(Bias-Variance Tradeoff):提高模型复杂度可以减少偏差,但可能增加方差。

AdaBoost

宏观分析

H(x)=t=1Tαtht(x)
  • ht(x) 表示一个弱分类器,个体学习器;
  • αt 衡量每个弱分类器的重要性;

宏观上看,AdaBoost 所做的是训练 T 个基学习器组成一个集成学习器 H(x),在组合过程中不断最小化 H(x) 的指数损失函数:

Lexp(H|D)=E(x,y)D[eyH(x)]=eH(x)P(y=1x)+eH(x)P(y=1x)

使用指数函数是因为将其求关于 H(x) 的偏导并使偏导为 0 时,此时位于最低值位置的 H(x) 有:

sign(H(x))=sign(12logP(Y=1|x)P(Y=1|x))

上面的式子中,当正类概率大于负类时,sign(H(x))为 1,反之为 -1,这符合我们想要的预测效果。故最小化指数损失函数,其实也是在寻找一个能够最大化贝叶斯准确率(使用了log-likelihood来近似)的 H(x)

实际实现

步骤:

  1. 初始化权重
  2. 训练分类器
  3. 根据分类器的错误率 αt=12ln(1εtεt) 调整该分类器的权重
  4. 根据分类器在某个样本上的偏差调整该样本的权重 wt+1(i)=wt(i)eαtyiht(xi)
  5. 归一化权重
  6. 进行下一个学习器的训练

具体步骤实现:

  1. 初始化样本权重 w,记在训练第 t 个学习器时,第 i 个样本的权重是 wti
w1(i)=1m,i=1,2,,m
  1. 训练一个弱分类器 ht(x),使得加权错误率最小,记 εt 为第 t 个基分类器的错误率:
εt=P(yht(x))=i=1mwt(i)I(ht(xi)yi)
  1. 计算弱分类器的系数(权重):
αt=12ln(1εtεt)

这个更新权重的方式是由指数函数损失对 αt 的偏导为 0 得到的,使用 εt 计算的 αtht 的指数损失函数如下:

Lexp(αtht|D)=E(x,y)D[eyαth(t)]=eαtP(ht(x)=y)+eαtP(ht(x)y)//ht(x)y 大于 0 =eαt(1εt)+eαtεt
  1. 更新样本权重,根据第 αtht 个学习器在该样本上的指数函数损失更新其权重:
wt+1(i)=wt(i)e(αtyiht(xi))
  1. 然后归一化使得 i=1mwt+1(i)=1

梯度提升决策树 GBDT

Gradient Boosting Decision Tree

每个学习器的都是一个CART回归树,前 t 个学习器的集成预测 Ht(x) 的一般形式是前 t1 个学习器的预测加上第 t 个学习器的预测(γ 是学习率) :

Ht(x)=Ht1(x)+γht(x)

在第 t 轮,我们要构造一棵树来拟合上一轮损失函数对输出的误差:

L(t)=i=1n(yi,Ht1(xi)+ht(xi))

在这里,Ht(xi)ht(xi) 都属于自变量空间,而 是因变量。这个朴素目标对于决策树来说太难优化了。因为我们要优化的是一个树,无法像神经网络那样计算损失然后求导反向传播来改变树的结构。在构建树的过程中,我们需要知道其目标值是什么,用于监督树的构建。由于在训练 t 个树的时候,前 t1 的都已经构建完成,于是,把损失函数 前面的模型 Ht1(xi) 处泰勒展开为:

(yi,Ht1(xi)+ht(xi))(yi,Ht1(xi))+Ht1(xi)ht(xi)

一阶泰勒展开告诉我们,Ht1 处沿着 Ht1(xi) 的方向增大,所以我们需要让自变量往这个梯度的相反方向移动,也就是自变量的增值 ht(xi) 以负梯度作为其目标值,于是 ht(xi) 的目标值为:

ri(t)=[(yi,Ht1(xi))Ht1(xi)]

ht(xi) 的目标值是这个的时候,因变量就会在 Ht1(xi) 沿着负梯度的方向变化,从而降低 Ht(xi) 时的损失。注意,我们还有学习率的存在,其控制我们具体走多长的步伐。

Note

从优化角度看:GBDT 是在函数空间中做梯度下降。区别于神经网络模型的梯度下降,神经网络模型是在参数空间的梯度下降,即通过修改参数来降低损失函数的值,也就是对参数求偏导。GBDT 在函数空间做梯度下降,是通过构造函数来实现集成模型的损失降低,每一步都在尝试构建一个新的函数去逼近当前损失函数对模型输出的负梯度,进而让整体集成的模型的损失往梯度下降方向走一步;

设损失函数为平方损失 (yi,Ht1(xi))=12(yiHt1(xi))2 ,对 Ht1(x) 求偏导得到 (yiHt1(xi)),再对梯度求负得到 ri(t)=yiHt1(xi),所以很多情况下,第 t 个学习器拟合的是真实值与前面 t1 个学习器的残差。

XGBoost

XGBoost 是 GBDT 的变种,加入了:

  1. 二阶梯度优化:将 ht 的损失在模型 ht1​ 附近做二阶泰勒近似,则其损失函数为:

    L(t)=(yi,Ht1(xi)+ht(xi))i=1n[(yi,Ht1(xi))+Ht1(xi)ht(xi)+122Ht12(xi)ht2(xi)]+Ω(ht)

    去除常数项后,我们可以得到其优化目标为

    L~(t)=i=1n[ Ht1(xi)ht(xi)+122Ht12(xi)ht2(xi)]+Ω(ht)
  2. 正则化 Ω 控制模型复杂度,防止过拟合

    step functions to fit data points, illustrating bias-variance tradeoff
Ω(ht)=γLeaves+12λj=1Leaveswj2
  • Leaves:树的叶子数
  • wj:第 j 个叶子节点的分数(回归树的预测值)
  • γλ 是两个超参数
  1. 推导最优叶子分数:GBDT 直接让叶子来拟合负梯度,因此叶子的分数通常是其内所有样本负梯度的平均值。而 XGBoost 在构建树的结构后,会根据损失函数推导一个最优的叶子分数 wj,使得损失函数最小。

    前面的优化目标中,我们是根据训练样本的损失来构建的,现在,我们可以用所有叶子的损失之和来等价训练样本的损失。舍弃二阶近似中的常数项、展开正则化项、合并同类项后,我们可以得到(Ij 表示叶子 j 中的样本集合,wj 表示该叶子输出的分数):

    L~(t)=j=1Leaves[(iIjHt1(xi))wj+12(iIj2Ht12(xi)+λ)wj2]+γLeaves

    求该函数的最值点,即求 wj 的偏导并让导数为 0,我们可以求得:

    wj=iIjHt1(xi)iIj2Ht12(xi)+λ

    此即为叶子结点 j 的预测值。

  2. 推导树的损失和构建树:将叶子节点的分数代入 L~(t) 可得到整个决策树结构的损失:

    L~(t)=12j=1T(iIjHt1(xi))2iIj2Ht12(xi)+λ

    这个损失函数可以用来衡量第 t 个决策树结构的质量,帮助我们构建 ht。通常来说,我们无法枚举所有决策树结构来获取最优的 ht,一般都是在构造 ht 的每一步贪心地选择分支的属性及其值。有了上面的整棵树的损失函数,对于每次分支,当前节点及其样本集 I 在分支前的损失为:

    Lbefore=12(iIHt1(xi))2iI2Ht12(xi)+λ

    在分支后,其分裂成两个节点,包含的样本集分别为 IRIL,两个节点的损失之和为:

    Lafter=12[(iILHt1(xi))2iIL2Ht12(xi)+λ+(iIRHt1(xi))2iIR2Ht12(xi)+λ]

    然而,需要注意的是,相比分裂前,整棵树会多一个叶子节点,所以分裂的损失应该加上一个 γ1

    Lsplite=LafterLbefore+γ

    于是乎,我们在每次选择分裂的属性及根据哪个值进行分裂时,选择的依据为能带来最大的 Lsplit 的属性和划分点。

  3. 缩减(Shrinkage)与列采样(Column Subsampling):对于每一步 ht(xi) 的结果,会乘以一个学习率 η 再加上 Ht1(xi)。在构建决策树的时候,使用了 Random Forest 的列采样技术,在构建每一棵树或每个节点时,随机选择部分特征用于寻找最佳切分点,从而引入随机性,降低过拟合风险。

  4. 近似贪婪:在划分属性时,除了严格地枚举所有可能的枚举点之外,还可以采用近似算法。其先找到候选的分位数,并要求小于分位数的样本的二阶导数之和全部样本的二阶导数之和比例差异不能超过某个阈值 ϵ,以此保证分位数之间的样本数量均衡,没有过大或过小的桶。

    Dk={(xik,bi)} 表示所有样本的第 k 个属性的值及损失对该样本的二阶导数 birk(z) 表示属性值 k 小于 z 的所有样本的二阶导数之和占全部样本的比例:

    rk(z)=1(x,b)Dkb(x,b)Dk,x<zb

    我们的目标是找到一群切分点 {sk1,sk2,...skl} (总共 l 个)使得

    |rk(sk,j)rk(sk,j+1)|<ϵ,sk1=minixikskl=maxixik

    也就是下一个被选中的分位数与上一个被选中的分位数之间的差值必须小于 ϵ,划分点之间形成的桶总是有着近似相等的Hessian总和。此时 1/ϵ 表示可能作为候选的划分点的大致数量。

  5. 稀疏处理/缺失值处理:在分裂节点时,仅考虑每个特征的非缺失样本中枚举所有可能的切分点。在划分后,考虑分裂特征为缺失值的样本全部默认走左子树或右子树两种情况,分别计算增益,选择增益较大的方向作为该值缺失的样本在当前节点的默认走向。在枚举每个属性的切分点的时候,0 值也会被全部跳过,不会枚举切分点。而且 0 值样本也会被看做是缺失值样本分配一个默认走向。

  6. 系统层优化:

    1. CSC(compressed column):在开始训练之前,把每一列排序后存储在一个连续的内存块中,而不是以行为单位存储。这样之后,每个节点分裂后节点内的样本每一列特征仍然会保持有序状态,而且可以并行化地处理多个特征,同时得到多个特征的增益,因为他们的内存完全独立。并且由于每个特征内的每个值是连续内存的,所以CPU读取很快,相比行存储减少了大量的随机读取。
    2. 缓存预取 Prefectching:由于 CSC 是连续的,所以我们天然地可以在 CPU 计算某个样本的梯度的时候,提前将下一步样本准备好并放入 CPU 缓存。

Bagging

使用自助采样法将训练集划分为 T 个含有相同数量 m 的采样集,用这 T 个数据集训练 T 个基学习器。

这种方法源自于集成学习的个体学习器互补逻辑:要得到性能更优的预测,集成中的个体学习器应该尽可能相互独立。如果分类器的错误率相互独立,则可以由 Hoeffding 不等式推导出其错误率会随着个体分类器的数量的增大而指数下降。

自助采样法:随机选取一个样本放到采样集,然后将其返回原数据集。

Note

Hoeffding 不等式是概率论中的不等式,用于回答问题:当我们用有限样本估计一个期望时,它和真实期望之间可能相差多少?独立变量的样本均值与真实期望的偏差超过某个阈值的概率,会随着样本数量增加而指数级下降。

Hoeffding 不等式(霍夫丁不等式):设 X1,X2,,Xn 是独立的随机变量,且每个 Xi 的取值区间为 [ai,bi]。定义 Sn=i=1nXi,则对任意 t>0,有:

P(SnE[Sn]t)exp(2t2i=1n(biai)2),P(E[Sn]Snt)exp(2t2i=1n(biai)2).

这条式子构建了样本之和偏离变量之期望和的偏差大于 t置信上界。这表示 Sn 偏离真实 Sn 的概率,随着偏差 t 的增大而指数级下降

如果我们做出两个假设:

  • 每个样本 Xi[0,1],即 ai=0,bi=1

  • 所有 Xi 的独立同分布

于是有:

biai=1i=1n(biai)2=n

代入不等式后,就有了突出 n 的形式:

P(SnE[Sn]t)exp(2t2/n)

这表示在相同的 t 下,随着 n 的增加,在样本上计算出的变量和与真实的期望的偏差呈指数级下降。

随机森林

随机森林可以看作是 Bagging 的一个变体,其在 Bagging 的基础上,根据决策树的特性,引入了随机属性选择

决策树中:选择划分属性时在当前节点的属性集合中选择一个最优属性进行划分

随机森林:先随机选择一个大小为 k属性子集,再从这个子集中选择要一个最优属性进行划分

可以看出,Bagging 试图让各个个体学习尽可能独立的方法是给他们不同的训练集,而随机森林是直接根据决策树的模型特点,从其构建过程中直接引入随机性来增加个体学习器之间的独立性。

模型融合

简单策略

对所有个体学习器的预测结合的方法通常有:

  • 回归
    • 简单平均
    • 加权平均,权重一般从训练数据中学习而来
  • 分类
    • 绝对多数投票:超过半数则作为预测,没有超过半数的则拒绝预测
    • 相对多数投票:随机选取一个得票最多的标记
    • 加权投票:与加权平均类似

投票可分为:

  • 硬投票:用最终标记投票
  • 软投票:用概率投票

学习法:Stacking 堆叠集成

用交叉验证法分割数据集,对每一折数据的训练集上都训练一个基学习器 ht(j)(在第 j 折训练集上训练的第 t 个模型),并用相应的测试集来输入该学习器得到其输出 zi(t) (第 t 个学习器对第 i 个样本的预测),组合所有的 zi(t) 形成数据集 (zi,yi) 用来训练一个次级学习器 gg 将会根据所有的

  1. 训练个体学习器

    • 对每个基学习器 hj,用 K 折交叉验证生成对每个训练样本的 out-of-fold 预测值:

      zi(t)=ht(j)(xi)

      其中 ht(j) 表示在第 j 折训练集上训练的第 t 个模型;

    • 这样可以避免学习器直接输出训练集的标签,导致过拟合,提高泛化能力。

  2. 构造新的训练集

    • 组合所有个体学习器的输出,得到新特征:

      zi=[zi(1),zi(2),...,zi(T)]
    • 对应的标签仍是 yi

  3. 训练次级学习器(Meta-Learner)

    • (zi,yi) 训练 meta-learner g(z)
  4. 预测时流程

    • 先用 base learners 对测试集进行预测,得到 ztest
    • 然后用 meta-learner 对 ztest 输出最终预测。

多样性

误差-分歧分解

构建好的集成学习器应该让所有个体学习器好而不同,下面形式化这一性质。集成分歧是个体学习器与最终集成学习器之间的差异,比如每个学习器的预测和最终集成学习器的预测的加权 MSE。

A¯(h|x)=wiiT(hi(x)H(x))2

其中的累加的每一项称为个体学习器 hi 的分歧 (hi(x)H(x))2

E(hi|x)hi 的误差,即 E(hi|x)=(hi(x)y)2,则个体学习器的误差的加权平均值为:

E(h|x)=i=1Twi(hi(x)y)2

从上面两条式子中,我们可以推导出分歧与集成学习器的误差之间的关系,即

A(h|x)=wiiT(hi(x)H(x))2=iTwi(hi(x)22hiH(x)+H(x)2)=iTwihi(x)22H(x)iTwihi(x)+H(x)2=iTwihi(x)22H(x)2+H(x)2//iTwihi(x)=H(x)=i=1Twihi(x)2H(x)2=i=1Twi(yhi(x))2(f(x)H(x))2//iT2wihi(x)y=2H(x)y=iTwiE(hi|x)E(H|x)

可以推导出 集成学习的泛化误差=个体学习器的误差加权平均值-集成分歧,此即为误差分歧分解:

E(H|x)=E(h|x)A(h|x)

上式即为误差-分歧分解,可以看到个体误差越低、分歧越高,则集成的误差越低:

  • 个体学习器偏差足够小的情况下,缺少多样性也无所谓;
  • 个体学习器偏差过大但是分歧也比较大,多样性比较好的话也可以弥补。

度量多样性

to be continue…

参考资料

  1. 周志华《机器学习》
  2. Introduction to Boosted Trees — xgboost 3.1.0-dev documentation
  3. XGBoost论文原文
  4. GBDT的原理、公式推导、Python实现、可视化和应用 - 知乎
  5. XGBoost的原理、公式推导、Python实现和应用 - 知乎
  6. 一篇入门之-GBDT集成算法原理与实现详述-老饼讲解
  7. 决策树(ID3、C4.5、CART)的原理、Python实现、Sklearn可视化和应用 - 知乎
  8. 集成学习—GBDT(论文研读)_gbdt论文-CSDN博客
  9. 矩阵微分与向量函数Taylor展开_向量泰勒展开-CSDN博客
  10. 图解机器学习算法(9) | GBDT模型详解(机器学习通关指南·完结)-CSDN博客
  11. ChatGPT