adaboost-笔记(1)

来源:互联网 发布:域名不以封疆之界 编辑:程序博客网 时间:2024/06/06 09:08

1 - 加法模型

加法模型,就是通过训练集不断的得到不同的分类器(回归),然后将这些分类器组合成一个新的分类器的过程。

假设有N个样本,且我们的加法模型如下:

f(x)=m=1Mβmb(x;Ym)

其中x为自变量,即样本;Ym为第m个分类器的参数;b(x;Ym)为分类器,也就是基函数;βm为该分类器的系数。

可以看出,在给定这样一个加法模型的思路以及固定的训练集后,我们要做的就是最小化该模型的损失,即:

minβm,Ymi=1N(yi,m=1Mβmb(xi;Ym))

对于这样一个模型,训练的思路是:因为是个加法模型,所以可以从前向后,每一步只学习一个分类器(即基函数)和系数,让它逐步的逼近目标函数,直到达到我们能够接受的误差为止。该方法也叫做前向分步算法。

前向分布算法过程如下
假设目前训练集T=(x1,y1),(x2,y2),...(xN,yN);损失函数L(y,f(x));分类器b(x;Y)。目标是得到最后的加法模型f(x)

1)得到第一个分类器f0(x)=0
2)对于m=1,2,...M

i)如数学归纳法一样,假设目前已经得到了前m1个分类器:

f(x)=fm1(x)=im1βib(x;Yi)

那么,对于第m个分类器的参数及系数求法:
(βm,Ym)=argminβ,Yi=1NL(yi,fm1(xi)+βb(xi;Y))

这样就得到了第m个分类器的参数和系数;
ii)然后更新旧加法模型,得到新的加法模型:
f(x)=fM(x)=m=1Mβmb(x;Ym)

这样,就是将整个模型转换成了一步求得一个模型的参数和系数的优化问题上。

2 - adaboost

adaboost是加法模型的一个特例。假设目前有训练集T={(x1,y1),(x2,y2),...,(xN,yN)}, 其中样本都为n维向量xiRn, 标签yi{1,+1}

1)先设定初始时的训练样本的权值:

D1=(w11,...,w1i,...,w1N),w1i=1N,i=1,2,...N

2)对m=1,2,...,M,即有M个分类器,则:

i)使用具有权值分布Dm的训练集学习,得到第m个基本分类器:

Gm(x):{1,+1}

ii)然后计算基于当前分类器Gm(x)在训练集上的分类误差率:

em=P(Gm(xi)yi)=i=1NwmiI(Gm(xi)yi)

ps:当然是选择当前权值基础上分类误差率最低的那个分类器作为当前分类器。所以其实是通过ii)来确定i)的分类器

iii)计算该分类器Gm(x)的系数:

αm=12log1emem

这里对数是自然对数。

ps:可以发现,当em12时,αm0,并且αm随着em的减小而增大,也就是分类误差率越小的基本分类器在最终分类器中作用越大。

iv)更新训练集的权值为下一个分类器做准备:

Dm+1=(wm+1,1,...,wm+1,i,...,wm+1,N)

wm+1,i=wmiZmexp(αmyiGm(xi)),i=1,2,...N

这里Zm是归一化因子:
Zm=i=1Nwmiexp(αmyiGm(xi))

ps:权值更新的式子可以写成如下形式:

wm+1,i={wmiZmeαm,wmiZmeαm,Gm(xi)=yiGm(xi)yi

可以看出,当样本分类正确时,其权值在变小,而当样本分类错误时,其权值被放大,由此,误分类样本在下一轮学习中会起更大作用,也就是下一个分类器会更关注那些误分类的样本。

3)构建基本分类器的线性组合:

f(x)=m=1MαmGm(x)

得到最终分类器:
G(x)=sign(f(x))=sign(m=1MαmGm(x))

2.1 这里举个例子

假设分类器是一个阈值分类器,即x>v,y=1x<v,y=1,训练集为简单的一维数据:

这里写图片描述

图2.1 李航书上表8.1

1)最开始每个样本的权重为相等,即:
D1=(w11,w12,...w110)

w1i=0.1,i=1,2,...,10

2)然后计算基于v={1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5}一共9个可选划分点基础上误差分类率最小的分类器:
e0.5=0.5,{2,3,7,8,9}
e1.5=0.4,{3,7,8,9}
e2.5=0.3,{7,8,9}
e3.5=0.4,{4,7,8,9}
e4.5=0.5,{4,5,7,8,9}
e5.5=0.6,{4,5,6,7,8,9}
e6.5=0.5,{4,5,6,8,9}
e7.5=0.4,{4,5,6,9}
e8.5=0.3,{4,5,6}
i)因为当2.5时,错误率最低,则第一个分类器:
G1(x)={1,1,x<2.5x>2.5

ii)当前误差率为0.3
iii)计算第一个分类器系数:
α1=12log1e1e1=0.4236

iv)更新训练集的权值分布:
D2=(w21,...,w2i,...w210)
w2i=w1iZ1exp(αiyiG1(xi)),i=1,2,...10
D2=(0.0715,0.0715,0.0715,0.0715,0.0715,0.0715,0.1666,0.1666,0.1666,0.0715)

d1 = [0.1]*10y = [1,1,1,-1,-1,-1,1,1,1,-1]z = []def g1(x):    return 1 if x < 2.5 else -1for ind,(d1Item,yItem) in enumerate(zip(d1,y)):    z.append(d1Item*np.exp(-0.4236*yItem*g1(ind)))d2 = [ zItem/sum(z) for zItem in z ]

f1(x)=0.4236G1(x)
此时分类器sign[f1(x)]当前误分类3个{7,8,9}

3)接着处理m=2时。
同上述方法计算每个阈值v={1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5}下分类误差率
e0.5=0.6428,{2,3,7,8,9}
e1.5=0.5713,{3,7,8,9}
e2.5=0.4998,{7,8,9}
e3.5=0.5713,{4,7,8,9}
e4.5=0.6428,{4,5,7,8,9}
e5.5=0.7143,{4,5,6,7,8,9}
e6.5=0.5477,{4,5,6,8,9}
e7.5=0.3811,{4,5,6,9}
e8.5=0.2145,{4,5,6}

#python 计算误分类率代码weight=np.asarray([0.0715,0.0715,0.0715,0.0715,0.0715,0.0715,0.1666,0.1666,0.1666,0.0715])eInd = np.asarray([4,5,6])-1weight[eInd].sum()  #0.2145

最低的分类器:

G2(x)={1,1,x<8.5x>8.5

i)此时误差率为0.2143
ii)系数为0.6496
iii)训练集权值分布:
D3={0.0455,0.0455,0.0455,0.1667,0.1667,0.1667,0.1060,0.1060,0.1060,0.0455}
f2(x)=0.4236G1(x)+0.6496G2(x)
iv)此时分类器sign[f2(x)]训练集上错分类样本还是3个{4,5,6}

//scala计算误分类代码 def g1(x:Int):Int = if (x<2.5) 1 else -1 def g2(x:Int):Int = if (x<8.5) 1 else -1 def f2(x:Int):Double = 0.4236*g1(x) + 0.6496*g2(x) val X = List(0,1,2,3,4,5,6,7,8,9) X.foreach(x=>println(f"${f2(x)}%.0f"))

4)如上述计算过程,第三轮得到的分类器:

f3(x)=0.4236G1(x)+0.6496G2(x)+0.7514G3(x)

此时误分类样本为0个,所以无需训练所谓第四个基分类器。
最终分类器为:
G(x)=sign[f3(x)]=sign[0.4236G1(x)+0.6496G2(x)+0.7514G3(x)]

3 - boosting tree

提升树是以回归树或者分类树作为基本分类器的模型,被认为统计学习中性能最好的方法之一(当然还有svm了)。
该类方法是采用了加法模型(基函数的线性组合)和前向分布算法,用决策树为基函数的提升方法叫提升树,分类问题 时,可采用二叉分类树,回归问题时,可采用二叉回归树。提升树模型可以表示为决策树的加法模型:

fM(x)=m=1MT(x;Θm)

其中,T(x;Θm)表示一棵决策树;Θm表示第m棵决策树的参数;M为树的个数。
对于整个过程,如上面的加法模型一样,先确定初始提升树f0(x)=0,然后第m轮之后,整个的模型:
fm(x)=fm1(x)+T(x;Θm)

其中fm1(x)是当前求得的模型,然后通过经验风险最小化确定下一棵决策树的参数Θm
Θ^m=argminΘmi=1NL(yi,fm1(xI)+T(xi;θm))

ps:因为树的线性组合可以很好的拟合训练数据,即使数据中的输入与输出的关系很复杂也如此。所以提升树是一个高功能的学习算法

通常来说,不同的提升树学习算法,主要区别在于使用的损失函数:1)平方误差损失函数的回归问题;2)指数损失函数的分类问题;3)一般损失函数的一般决策问题。
对于二类分类问题,即将adaboost中的基本分类器限制为二类分类树(即树桩:一个根节点,两个叶子节点)。这里主要介绍回归问题的提升树。

假设训练集T={(x1,y1),(x2,y2),...,(xN,yN)},且xiXRn,yiYR.对于一棵回归树,如果将输入空间划分成J个互不相交的区域R1,R2,...RJ并且在每个区域上确定输出常量cj,那么树可表示为:

T(x:Θ)=j=1JcjI(xRj)

其中参数Θ={(R1,c1),(R2,c2),...,(RJ,cJ)}表示树的区域划分和各个区域上的常量输出J表示回归树的复杂度,即最终叶节点个数。

前向分步步骤
假设训练集T={(x1,y1),(x2,y2),...,(xN,yN)},且xiXRn,yiYR

1)初始化f0(x)=0

2)对于轮数m=1,2,...,M

i)当第m步时,已知前m1轮结果,需要求解:

Θ^m=argminΘmi=1NL(yi,fm1(xi)+T(xi;Θm))

得到的Θ^m即为第m棵树的参数。当采用平方误差损失函数时,:
L(y,f(x))=(yf(x))2

代入得:
L(y,fm1(x)+T(x:Θm))==[yfm1(x)T(x;Θm)]2[rT(x;Θm)]2

其中r=yfm1(x)是前m1轮后得到的模型拟合数据的残差,所以对于回归问题的提升树来说,就是拟合当前模型的残差。
ii)对于每个样本i=1,...N
求得他们的残差:
rmi=yifm1(xi),i=1,2,...N

iii)拟合这轮得到的残差rmi,基于整个训练集学习一棵新的回归树,得到T(x;Θm)

iv)更新fm(x)=fm1(x)+T(x;Θm)

3)得到最后结果模型:

fM(x)=m=1MT(x;Θm)

3.1 回归提升树例子

如下表数据:

这里写图片描述

图3.1.1 李航书上表8.2

x取值范围[0.5,10.5],y取值范围为[5.0,10.0]。为了简单起见,这里只采用树桩来生成每轮的回归树,且输入空间只划分成2个区域{R1,R2}
这里略过了f0(x).直接生成f1(x):
通过优化下面的问题:
minsminc1xiR1(yic1)2+minxiR2(yic2)2(3.1.1)

来求解切分点s,使得:
R1={x|xs},R2={x|x>s}
从而计算在当前切分点基础上,在R1,R2使平方损失误差达到最小值的c1,c2:
c1=1N1xiR1yi,c2=1N2xiR2yi(3.1.2)

1)上述训练集样本的切分点有{1.5,2.5,3.5,4.5,5.5,6.5,7.5,8.5,9.5}
对应的最小误差值如下:
这里写图片描述

k发现当s=6.5m(s)达到最小值。此时R1={1,2,...,6};R2={7,8,9,10}.c1=6.24;c2=8.91。所以回归树T1(x)为:
T1(x)={6.24,8.91,x<6.5x6.5

从而f1(x)=T1(x)

X = [1,2,3,4,5,6,7,8,9,10]Y0 = [5.56, 5.70, 5.91, 6.40, 6.80, 7.05, 8.90, 8.70, 9.00, 9.05]X_splits = [1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5]def cost_split_point(ind,xs,YT):       R1 = YT[:ind+1]    R2 = YT[ind+1:]    c1 = round(mean(R1),3)    c2 = round(mean(R2),3)    ans0 = [(x-c1)*(x-c1) for x in R1]    ans1 = [(x-c2)*(x-c2) for x in R2]    return [sum(ans0+ans1), c1, c2]cost = [[xs]+cost_split_point(ind,xs,Y0) for ind,xs in enumerate(X_splits)]#[[1.5, 15.723, 5.559, 7.501],# [2.5, 12.083, 5.629, 7.726],# [3.5, 8.365, 5.723, 7.985],# [4.5, 5.775, 5.892, 8.25],# [5.5, 3.911, 6.073, 8.540],# [6.5, 1.930, 6.236, 8.912],# [7.5, 8.009, 6.617, 8.916],# [8.5, 11.735, 6.877, 9.025],# [9.5, 15.738, 7.113, 9.050]]

2)计算f1(x)拟合训练集的残差计算公式r2i=yif1(xi),i=1,2,...,10

这里写图片描述

图3.1.3

f1(x)拟合训练集后的平方损失为:
L(y,f1(x))=i=110(yif1(xi))2=1.93

r_2i = [-0.68, -0.54, -0.33, -0.16, 0.56, 0.81, -0.01, -0.21, 0.09, 0.14]r_2i = np.array(r_2i)loss = (r_2i*r_2i).sum()#1.9301

3)在计算新的回归树时,选择的训练集是图3.1.3 而不是原来的3.1.1,即是基于上一轮模型结果之后的残差。从而得到这一轮的回归树:

T2(x)={0.52,0.22,x<3.5x3.5

Y1 = [-0.68, -0.54, -0.33, 0.16, 0.56, 0.81, -0.01, -0.21, 0.09, 0.14]cost = [[xs]+cost_split_point(ind,xs,Y1) for ind,xs in enumerate(X_splits)]#[[1.5, 1.417, -0.680, 0.073],# [2.5, 1.002, -0.609, 0.151],# [3.5, 0.790, -0.517, 0.22],# [4.5, 1.129, -0.347, 0.230],# [5.5, 1.657, -0.166, 0.164],# [6.5, 1.930, -0.003, 0.003],# [7.5, 1.929, -0.004, 0.007],# [8.5, 1.896, -0.029, 0.115],# [9.5, 1.908, -0.017, 0.140]]

在得到这一轮的回归树之后,将前面得到的模型与当前模型相加,且重合区域需要注意相加减,如当x<3.5时,f2(x)=0.52+6.24=5.72

f2(x)=f1(x)+T2(x)=5.72,6.46,9.13,x<3.53.5x<6.5x6.5

f2(x)拟合训练集损失为L(y,f2(x))=10i=1(yif2(xi))2=0.79

如此得到最后结果:

f6(x)=f5(x)+T6(x)=5.63,5.82,6.56,6.83,8.95,x<2.52.5x<3.53.5x<4.54.5x<6.5x6.5

当前模型拟合训练集平方损失为0.17.假设此时误差已经满足要求,那么就可以将f6(x)作为整个训练集的提升树

3.2 gradient boosting tree

当提升树中选取的损失函数是平方损失和指数损失函数时,训练过程如上述所属,可是当一般损失函数而言,优化相对就较为麻烦了,这时候可以用freidma提出的gradient boosting算法,这是与最速下降法相似的方法,使用了损失函数的负梯度:

rmi=[dL(y,f(xi))df(xi)]f(x)=fm1(x)

将其作为3.1中每一轮计算的平方损失残差值,即这一轮所谓的”训练集”
其他部分的计算不变。

参考资料:
[] 李航,统计学习方法

2017/04/07 第一次修改!

0 0