所谓集成学习,是指构建多个分类器(弱分类器)对数据集进行预测,然后用某种策略将多个分类器预测的结果集成起来,作为最终预测结果。通俗比喻就是“三个臭皮匠赛过诸葛亮”,或一个公司董事会上的各董事投票决策,它要求每个弱分类器具备一定的“准确性”,分类器之间具备“差异性”。
集成学习根据各个弱分类器之间有无依赖关系,分为Boosting和Bagging两大流派:
Boosting流派,各分类器之间有依赖关系,必须串行,比如Adaboost、GBDT(Gradient Boosting Decision Tree)、Xgboost。是一个迭代学习的过程,用于自适应地改变训练样本的分布,使得基分类器聚焦在那些很难分的样本上。对错误的样本重点学习,准确率会更高。
Bagging流派,各分类器之间没有依赖关系,可各自并行,比如随机森林(Random Forest)。是一个自助聚集过程,是一种根据均匀概率分布从数据中重复抽样的技术。选择训练集之后,单独训练每个分类器。最后的结果由投票决定。对每个样本的学习是均等的,所以有更低的方差,也就是更好的稳定性。
而著名的Adaboost作为boosting流派中最具代表性的一种方法。
AdaBoost,是英文"Adaptive Boosting"(自适应增强)的缩写,由Yoav Freund和Robert Schapire在1995年提出。它的自适应在于:前一个基本分类器分错的样本会得到加强,加权后的全体样本再次被用来训练下一个基本分类器。同时,在每一轮中加入一个新的弱分类器,直到达到某个预定的足够小的错误率或达到预先指定的最大迭代次数。
Adaboost的两个问题:
1 每一轮如何改变训练数据的权值:提高那些被前一轮弱分类器错误分类样本的权值,降低那些被正确分类样本的权值。
2 如何将弱分类器组合成一个强分类器:加权多数表决,加大分类误差率小的弱分类器的权值,使其在表决中起较大的作用,减小分类误差率大的弱分类器的权值,使其在表决中起较小的作用。
输入:二分类的数据训练集 T = { ( x 1 , y 1 ) , ( x 2 , y 2 ) . . . ( x N , y N ) } T=\{(x_1,y_1),(x_2,y_2)...(x_N,y_N)\} T={(x1,y1),(x2,y2)...(xN,yN)}
y i ∈ y = { − 1 , + 1 } y_i \in y=\{-1,+1\} yi∈y={−1,+1}
输出:最终分类器G(X)
D 1 = ( w 11 , w 12 , . . . w 1 N ) D_1=(w_{11},w_{12},...w_{1N}) D1=(w11,w12,...w1N), w 1 i = 1 N w_{1i}=\dfrac{1}{N} w1i=N1
这个代表第一轮的权值分布。
对于分类错误的数据,按照权重计算其损失。也可以称为分类错误率。是当前分类器分类性能的一个指标。
当 e m < = 1 2 e_m<=\dfrac{1}{2} em<=21的时候, α m > = 0 \alpha_m>=0 αm>=0。也就是说如果当前分类器,比随机猜测的概率要好。
当 e m > 1 2 e_m>\dfrac{1}{2} em>21的时候, α m < 0 \alpha_m<0 αm<0。当前分类器被丢弃。
如果分对了,那么 y i G m ( x i ) y_iG_m(x_i) yiGm(xi)是一个正数,那么 − α m y i G m ( x i ) -\alpha_my_iG_m(x_i) −αmyiGm(xi)就是一个负数。如果分错了,那么 − α m y i G m ( x i ) -\alpha_my_iG_m(x_i) −αmyiGm(xi)就是一个正数。
因为 e x p ( 正 数 ) > e x p ( 负 数 ) exp(正数)>exp(负数) exp(正数)>exp(负数),最后除以一个归一化因子,所以相对而言,在分错的情况下, w m i w_{mi} wmi就会占一个比较大的权重。
Z m Z_m Zm是归一化因子, Z m = ∑ i = 1 N w m i e x p ( − α m y i G m ( x i ) ) Z_m=\sum_{i=1}^Nw_{mi}exp(-\alpha_my_iG_m(x_i)) Zm=∑i=1Nwmiexp(−αmyiGm(xi))
f ( x ) = ∑ m = 1 M α m G m ( x ) f(x)=\sum_{m=1}^M\alpha_mG_m(x) f(x)=∑m=1MαmGm(x)
分类器强,权重就高。
G ( x ) = s i g n ( f ( x ) ) = s i g n ( ∑ m = 1 M α m G m ( x ) ) G(x)=sign(f(x))=sign(\sum_{m=1}^M\alpha_mG_m(x)) G(x)=sign(f(x))=sign(∑m=1MαmGm(x))
看这里 α m \alpha_m αm的作用。
α m \alpha_m αm会随着 e m e_m em的增加而减少。这是因为如果一个分类器误差率高,那它起得作用就小。
在训练数据权重分配方面,当分类不正确的时候 w m + 1 , i = w m , i Z m e α m w_{m+1,i}=\dfrac{w_{m,i}}{Z_m}e^{\alpha_m} wm+1,i=Zmwm,ieαm,当分类正确的时候 w m + 1 , i = w m , i Z m e − α m w_{m+1,i}=\dfrac{w_{m,i}}{Z_m}e^{-\alpha_m} wm+1,i=Zmwm,ie−αm,数值比分配不正确的时候要小。通过正负号,增加错误样本的学习权重。
f ( x ) = ∑ m = 1 M β m b ( x ; r m ) f(x)=\sum_{m=1}^M\beta_mb(x;r_m) f(x)=∑m=1Mβmb(x;rm)
β \beta β是基函数的系数
b b b是基函数
这个形式和Adaboost一样: f ( x ) = ∑ m = 1 M α m G m ( x ) f(x)=\sum_{m=1}^M\alpha_mG_m(x) f(x)=∑m=1MαmGm(x),不同的是学习过程不同。Adaboost是不断调整训练数据集数据的权重学习的。
给定训练数据和损失函数L(y,f(x)),学习加法模型f(x),使用损失函数极小化: m i n β m , γ m ∑ i = 1 N L ( y i , ∑ m = 1 M β m b ( x ; r m ) ) min_{\beta_m,\gamma_m} \sum_{i=1}^NL(y_i, \sum_{m=1}^M\beta_mb(x;r_m)) minβm,γm∑i=1NL(yi,∑m=1Mβmb(x;rm))
寻找使得损失函数最小的 β m , γ m \beta_m,\gamma_m βm,γm。但是这是一个复杂的优化问题。使用前向分布算法解决。
解决思路:根据学习的是加法模型,如果能够从前向后,每一步只学习一个基函数及其系数,逐步逼近优化目标函数。最后累加起来就是学习目标。
每一步的优化的损失函数是: m i n β , γ ∑ i = 1 N L ( y i , β b ( x i ; γ ) ) min_{\beta,\gamma} \sum_{i=1}^NL(y_i,\beta b(x_i;\gamma)) minβ,γ∑i=1NL(yi,βb(xi;γ))
学习M步之后,得到 m i n β m , γ m ∑ i = 1 N L ( y i , ∑ m = 1 M β m b ( x ; r m ) ) min_{\beta_m,\gamma_m} \sum_{i=1}^NL(y_i, \sum_{m=1}^M\beta_mb(x;r_m)) minβm,γm∑i=1NL(yi,∑m=1Mβmb(x;rm))
前向分布算法
输入:训练数据集 T = { ( x 1 , y 1 ) , ( x 2 , y 2 ) . . . . ( x N , y N ) } T=\{(x_1,y_1),(x_2,y_2)....(x_N,y_N)\} T={(x1,y1),(x2,y2)....(xN,yN)},损失函数 L ( y , f ( x ) ) L(y,f(x)) L(y,f(x)),基函数集 { b ( x ; γ ) } \{b(x;\gamma)\} {b(x;γ)}
输出:加法模型f(x)
1 初始化 f 0 ( x ) = 0 f_0(x)=0 f0(x)=0
f 0 ( f ) = 0 f_0(f)=0 f0(f)=0是一个函数,是一个效果很差的函数,一个函数就是一个映射。
2 对m=1,2…M
极小化损失函数: ( β m , γ m ) = a r g m i n β , γ ∑ i = 1 N L ( y i , f m − 1 ( x i ) + β b ( x i ; γ ) ) (\beta_m,\gamma_m)=argmin_{\beta,\gamma}\sum_{i=1}^NL(y_i,f_{m-1}(x_i)+\beta b(x_i;\gamma)) (βm,γm)=argminβ,γ∑i=1NL(yi,fm−1(xi)+βb(xi;γ))得到参数 β m , γ m \beta_m,\gamma_m βm,γm。
这里是一个加法模型,加法模型可以累加。 f m − 1 f_{m-1} fm−1是上一轮学习得到的函数。本轮学习的函数是在上一轮函数的基础上加上当前要学习的基函数 β b ( x i ; γ ) \beta b(x_i;\gamma) βb(xi;γ)。
更新 f m ( x ) = f m − 1 ( x ) + β m b ( x i ; γ m ) f_m(x)=f_{m-1}(x)+\beta_m b(x_i;\gamma_m) fm(x)=fm−1(x)+βmb(xi;γm)
3 得到加法模型
f ( x ) = ∑ m = 1 M β m b ( x i ; γ m ) f(x)=\sum_{m=1}^M\beta_m b(x_i;\gamma_m) f(x)=∑m=1Mβmb(xi;γm)
可以通过证明:Adaboost是boosting方法的一种特例,是基函数为分类器,损失函数是指数函数的boosting。
那也就是基函数如果为回归函数的话,应该也有一种称呼?
如果boosting的基函数是决策树,并且所有基函数的系数都为1,那么成为提升决策树BDT。
BDT被认为是统计学习中性能最好的方法之一。
树可以相加?
什么是一棵树:是对特征空间的划分以及每个划分的输出。树相加就是对重叠区域的进一步划分。
对分类问题,决策树是二叉分类树。
对回归问题,决策树是二叉回归树。
定义: f M ( x ) = ∑ m = 1 M T ( x ; θ m ) f_M(x)=\sum_{m=1}^MT(x;\theta_m) fM(x)=∑m=1MT(x;θm)
1 确定初始提升树 f 0 ( x ) = 0 f_0(x)=0 f0(x)=0
2 第m步的模型: f m ( x ) = f m − 1 ( x ) + T ( x ; θ m ) f_m(x)=f_{m-1}(x)+T(x;\theta_m) fm(x)=fm−1(x)+T(x;θm)
f m − 1 ( x ) f_{m-1(x)} fm−1(x)是当前模型,通过经验风险极小化确定下一颗决策树的参数 θ m \theta_m θm: θ m ^ = a r g m i n θ m ∑ i = 1 N L ( y i , f m − 1 ( x i ) + T ( x i ; θ m ) ) \hat{\theta_m}=arg min_{\theta_m}\sum_{i=1}^NL(y_i,f_{m-1}(x_i)+T(x_i;\theta_m)) θm^=argminθm∑i=1NL(yi,fm−1(xi)+T(xi;θm))
决策树模型。将X划分为J个互不相交的区域R1,R2…RJ。并且在每个空间上确定输出常量 c j c_j cj。那么树可以表示为 T ( x ; θ ) = ∑ j = 1 J c j I ( x ∈ R j ) T(x;\theta)=\sum_{j=1}^Jc_jI(x\in R_j) T(x;θ)=∑j=1JcjI(x∈Rj)
针对不同问题的提升树,使用的函数不同。回归问题使用平方误差损失;分类问题使用指数损失函数。
当使用平方误差损失函数的时候,
L ( y , f ( x ) ) = ( y − f ( x ) ) 2 = [ y − f m − 1 ( x ) − T ( x ; θ ) ] 2 = [ r − T ( x ; θ ) ] 2 L(y,f(x))=(y-f(x))^2\\ =[y-f_{m-1}(x)-T(x;\theta)]^2\\ =[r-T(x;\theta)]^2 L(y,f(x))=(y−f(x))2=[y−fm−1(x)−T(x;θ)]2=[r−T(x;θ)]2
其中 r = y − f m − 1 ( x ) r=y-f_{m-1}(x) r=y−fm−1(x),这可以理解为是在之前模型的残差上学习当前树模型。可以认为当前模型学习的不是y,而是y减去上一次模型已经学好部分,也就是说学习的是上一次模型的残差。每一次学习,学得是之前的模型没有学习好的部分。
输入:训练数据集 T = { ( x 1 , y 1 ) , ( x 2 , y 2 ) . . . ( x N , y N ) } T=\{(x_1,y_1),(x_2,y_2)...(x_N,y_N)\} T={(x1,y1),(x2,y2)...(xN,yN)}, y i ∈ y y_i \in y yi∈y是一个R
输出:提升树 f M ( x ) f_M(x) fM(x)
1 初始化 f 0 ( x ) = 0 f_0(x)=0 f0(x)=0
2 对m=1,2…M
f m ( x ) = f m − 1 ( x ) + T ( x ; θ m ) f_m(x)=f_{m-1}(x)+T(x;\theta_m) fm(x)=fm−1(x)+T(x;θm),m=1,2,3…M
计算残差: L ( y , f ( x ) ) = ( y − f ( x ) ) 2 = [ y − f m − 1 ( x ) − T ( x ; θ ) ] 2 = [ r − T ( x ; θ ) ] 2 L(y,f(x))=(y-f(x))^2=[y-f_{m-1}(x)-T(x;\theta)]^2=[r-T(x;\theta)]^2 L(y,f(x))=(y−f(x))2=[y−fm−1(x)−T(x;θ)]2=[r−T(x;θ)]2
其中 r = y − f m − 1 ( x ) r=y-f_{m-1}(x) r=y−fm−1(x)。这是因为对于第m轮, f m − 1 ( x ) f_{m-1}(x) fm−1(x)是一个已知的值。
拟合残差学习一个回归树,得到 T ( x ; θ ) T(x;\theta) T(x;θ)。拟合残差的过程就是求得:
θ m ^ = a r g m i n θ m ∑ i = 1 N L ( y i , f m − 1 ( x i ) + T ( x i ; θ m ) ) = a r g m i n θ m [ r − T ( x ; θ ) ] 2 \hat{\theta_m}=arg min_{\theta_m}\sum_{i=1}^NL(y_i,f_{m-1}(x_i)+T(x_i;\theta_m))=arg min_{\theta_m}[r-T(x;\theta)]^2 θm^=argminθm∑i=1NL(yi,fm−1(xi)+T(xi;θm))=argminθm[r−T(x;θ)]2
使得损失函数最小的参数 θ \theta θ。
更新 f m ( x ) = f m − 1 ( x ) + T ( x ; θ ) f_m(x)=f_{m-1}(x)+T(x;\theta) fm(x)=fm−1(x)+T(x;θ)
3 得到回归问题提升树: f M ( x ) = ∑ m − 1 M T ( x ; θ ) f_M(x)=\sum_{m-1}^MT(x;\theta) fM(x)=∑m−1MT(x;θ)
BDT使用一阶梯度学习得到最优参数,称为GBDT。
BDT每次学习的是残差。GBDT是使用f(x)的一阶梯度来学习参数。
利用损失函数的负梯度更新模型:直接对f(x)求偏导,而不是对f(x)的参数 θ \theta θ求偏导。
为什么使用梯度学习参数?
1 函数f(x),是一个从X空间到Y空间的一个映射。这个f(x)可能有很多个。所有的f(x)构成一个假设空间,我们需要从假设空间中查找一个最优的f(x)作为最终的映射。寻找方法可以是平方误差损失最小,或者指数损失函数最小。
2 一般我们在查找最优的f(x)的时候,是通过f(x)的参数空间去寻找,找到最优的参数,就找到了最优的f(x)。例如假设f(x)=wx+b,那么就是寻找使得损失函数最小的w和b。
这是一般情况。
w ∗ = a r g m i n w L ( w ) w^*=argmin_wL(w) w∗=argminwL(w)
∂ L ( w ) ∂ x = 0 = > w ∗ = w − α ∂ L ( w ) ∂ x \dfrac{{\partial L(w)}}{{\partial x}}=0=>w*=w-\alpha\dfrac{{\partial L(w)}}{{\partial x}} ∂x∂L(w)=0=>w∗=w−α∂x∂L(w)
找到 w ∗ w^* w∗,找到最优的f(x)。
那是不是可以直接在假设空间学习f(x)?也是就是 ∂ L ( y , f ( x ) ) ∂ f ( x ) \dfrac{\partial L(y,f(x))}{\partial f(x)} ∂f(x)∂L(y,f(x))
计算过程就是假设, ∂ L ( y , f ( x ) ) ∂ f ( x ) = 0 \dfrac{\partial L(y,f(x))}{\partial f(x)}=0 ∂f(x)∂L(y,f(x))=0
f ∗ = f − α ∂ L ( y , f ( x ) ) ∂ f ( x ) f^*=f-\alpha \dfrac{\partial L(y,f(x))}{\partial f(x)} f∗=f−α∂f(x)∂L(y,f(x))
假设学习率 α = 1 \alpha=1 α=1,那么就是 f ∗ = f − ∂ L ( y , f ( x ) ) ∂ f ( x ) f^*=f-\dfrac{\partial L(y,f(x))}{\partial f(x)} f∗=f−∂f(x)∂L(y,f(x)),也就是函数f(x)-函数的梯度。
最终就变成了使用f(x)梯度的负值,来拟合学习f(x)。
下一个问题:不是所有函数都有参数。看我们的决策树: T ( x ; θ ) = ∑ j = 1 J c j I ( x ∈ R j ) T(x;\theta)=\sum_{j=1}^Jc_jI(x\in R_j) T(x;θ)=∑j=1JcjI(x∈Rj)
X G B o o s t = e X t r e m e + G B D T = e X t r e m e + ( G r a d i e n t + B D T ) = e X t r e m e + G r a d i e n t + ( B o o s t i n g + D e c i s i o n T r e e ) XGBoost = eXtreme + GBDT\\ =eXtreme+(Gradient + BDT)\\ =eXtreme+ Gradient + (Boosting + DecisionTree) XGBoost=eXtreme+GBDT=eXtreme+(Gradient+BDT)=eXtreme+Gradient+(Boosting+DecisionTree)
GBDT的问题是:1 使用一阶梯度,我们知道如果可以使用二阶梯度那结果会更加准确。2 训练方式是使得经验风险最小化,这就可能会出现过拟合。需要加入正则化项。
训练数据集 D = { ( X i , y i ) } D=\{(X_i,y_i)\} D={(Xi,yi)},其中 X i ∈ R m X_i \in R^m Xi∈Rm, y i ∈ R y_i \in R yi∈R,|D|=n
决策树模型: f ( X ) = w q ( X ) f(X)=w_{q(X)} f(X)=wq(X)。
其中q: R m R^m Rm->{1,2,3…T},也就是X到决策树叶子节点编号的映射。 w ∈ R T w \in R^T w∈RT,是叶子节点向量。T为决策树叶子节点数量。 w ⃗ = ( w ( 1 ) , w ( 2 ) . . . w ( T ) ) T \vec{w}=(w^{(1)},w^{(2)}...w^{(T)})^T w=(w(1),w(2)...w(T))T,每一个元素是叶子节点的预测输出。
这个模型的含义就是:首先有输入 X i X_i Xi,通过q(X)能够得到叶子节点的编号t。其次,通过访问w[t]能够得到这个叶子节点的预测输出。从而完成从 X i X_i Xi到输出。
而之前的决策树模型定义为 T ( X ) = ∑ j = 1 J c j I ( X ∈ R j ) T(X)=\sum_{j=1}^Jc_jI(X \in R^j) T(X)=∑j=1JcjI(X∈Rj)
为什么要重新定义决策树?是为了后面做二阶梯度降低难度。这是xgboost第一个精彩的地方。
提升决策树模型: y i ^ = ϕ ( X i ) = ∑ k = 1 K f k ( X i ) \hat{y_i}=\phi(X_i)=\sum_{k=1}^Kf_k(X_i) yi^=ϕ(Xi)=∑k=1Kfk(Xi),其中 f k ( x ) f_k(x) fk(x)为第k颗决策树。
正则化目标函数: L ( ϕ ) = ∑ i l ( y i , y i ^ ) + ∑ k Ω ( f k ) L(\phi)=\sum_{i}l(y_i,\hat{y_i})+\sum_k\Omega(f_k) L(ϕ)=∑il(yi,yi^)+∑kΩ(fk),
其中 Ω ( f k ) = γ T + 1 2 λ ∣ ∣ w ∣ ∣ 2 = γ T + 1 2 ∑ j = 1 T w j 2 \Omega(f_k)=\gamma T+\dfrac{1}{2}\lambda ||w||^2=\gamma T+\dfrac{1}{2}\sum_{j=1}^Tw_j^2 Ω(fk)=γT+21λ∣∣w∣∣2=γT+21∑j=1Twj2
也就是加入正则化项。对树的规模T,以及树的输出 w j w_j wj都做了限制。无论模型多么复杂,我们都可以通过约束其系数,降低模型复杂度。
第t轮目标函数,也就是 f t f_t ft这颗树的正则化目标函数:
L ( t ) = ∑ i = 1 n l ( y i , y i ^ ( t − 1 ) + f t ( X i ) ) + Ω ( f t ) L^{(t)}=\sum_{i=1}^nl(y_i,\hat{y_i}^{(t-1)}+f_t(X_i))+\Omega(f_t) L(t)=∑i=1nl(yi,yi^(t−1)+ft(Xi))+Ω(ft)
根据泰勒公式展示二阶:
移除常数项之后:
这个式子中的第一部分是对数据集的遍历,第s三分是对叶子节点的遍历。这种方式不利于计算。
我们考虑对于数据集的遍历,对于每一条数据最终肯定分到某个叶子节点了。所以可以把对数据集的遍历转为对叶子节点的遍历:
定义叶子节点j上的样本的下标集合 I j = { i ∣ q ( X j ) = j } I_j=\{i|q(X_j)=j\} Ij={i∣q(Xj)=j},那么
举个例子。例如我们班有50名同学。班级有5个小组,每个同学属于一个小组。那如果想点名,叫到每个同学一次。我们可以按照花名册,从1到50点名。我们也可以按照小组,从第1组点到第5组,这样也可以完成对所有同学的点名。
这相当于xgboos第二个精彩的地方。
由于 w j ∗ = a r g m i n w j L ~ ( t ) w^*_j=arg min_{w_j} \widetilde{L}^{(t)} wj∗=argminwjL (t)
令 ∂ L ~ ( t ) ∂ w j = 0 \dfrac{\partial \widetilde{L}^{(t)}}{\partial w_j}=0 ∂wj∂L (t)=0,
得到每个叶子节点最优的输出值: w j ∗ = − ∑ i ∈ I j g i ∑ i ∈ I j h i + λ w_j^*=-\dfrac{\sum_{i\in I_j}g_i}{\sum_{i\in I_j}h_i+\lambda} wj∗=−∑i∈Ijhi+λ∑i∈Ijgi
g i g_i gi, h i h_i hi是关于t-1轮的函数,所以是可以计算得到的。
带回到上面的式子得到损失函数:
那怎么确定T呢?在这里以损失函数作为树分裂的依据。假设依据某个特征以及值分裂后得到 I L I_L IL和 I R I_R IR左右两个实例集。令 I = I L + I R I=I_L+I_R I=IL+IR,则分裂之后的损失减少量:
这个可以作为依据评估待分裂节点。
具体分裂查找的精确贪婪算法:
特征维度有d个。
第一层先遍历特征维度k从1到d。
根据第k个特征的值,把所有数据集排序。
按照排序后到的数据集遍历,遍历到第j个数据,按照 x j k x_jk xjk将数据集分为两部分。
分别计算两部分的损失值。
score保存最大的损失值差。
最终以score最大时候的特征k以及数值 x j k x_jk xjk作为树分裂的依据。
因为这里是贪婪算法,所以得到的是局部最优解。