python小白之路:第十九章 Boosting模型(一)

Boosting(提升)

集成学习的一种方法。相比于bagging的并行式,boosting是序列式或者串行的方式,各个基分类器间有依赖关系。

类似于我们人类的学习方式。在学习一些知识的过程中,通过某种方式比如月考期中期末考试,有些知识点我们确认已经较为掌握,可有的知识点我们通过测验发现做错了,自己掌握的并不好,因此,会着重去练习犯错的知识点,以期降低错误率。

对于原始训练集,第一次我们训练了一个弱学习器1,统计了错误的情况,即这次训练的效果。根据这次的效果,给予犯错误的样本更高的权重,得到第二次训练的数据集的权值分布,用来训练弱学习器2。通过不断的迭代,我们得到了多个弱学习器,将它们的预测结果加权融合,就得到了最终的强学习器。

那么,按照以上思路,有几个关键问题:1.每一轮遍历如何改变数据的权值或概率分布?2.如何加权弱分类器的预测结果得到强分类器?

1 AdaBoost算法

1.1 开始

原始训练集 T = T= T={ ( x 1 , y 1 ) , ( x 2 , y 2 ) , ( x 3 , y 3 ) . . . ( x n , y n ) {(x_1,y_1),(x_2,y_2),(x_3,y_3)...(x_n,y_n)} (x1,y1),(x2,y2),(x3,y3)...(xn,yn)}, y i ∈ Y = y_i\in Y= yiY={-1,+1}

选定基分类器G

进行循环M次(也可以设置阈值),即 m = 1 , 2 , 3... M m=1,2,3...M m=1,2,3...M
D m = ( w m , 1 , w m , 2 , w m , 3 . . . , w m , n ) D_m=(w_{m,1},w_{m,2},w_{m,3}...,w_{m,n}) Dm=(wm,1,wm,2,wm,3...,wm,n)
初始化:第一次训练时权值一样,即 w 1 i = 1 n , i = 1 , 2 , 3... n w_{1i}=\frac{1}{n},i=1,2,3...n w1i=n1,i=1,2,3...n
D 1 = ( w 11 , w 12 , w 13 . . . w 1 n ) D_1=(w_{11},w_{12},w_{13}...w_{1n}) D1=(w11,w12,w13...w1n)

1.2 中间

以进行到第m次为例:

使用m-1次训练完更新后的权值分布进行训练,得到基分类器 G m G_m Gm:

选取让误差率最低的阈值来设计基分类器

G m ( x ) : χ → { − 1 , + 1 } G_m(x):\chi \to \{-1,+1\} Gm(x):χ{1,+1}

G m ( x ) G_m(x) Gm(x)在训练集上的分类误差率 e m e_m em:

即本轮预测错误的样本数据的权重和;

I ( G m ( x i ) ≠ y i ) I(G_m(x_i)\not=y_i) I(Gm(xi)=yi)为判别函数,表示 G m ( x i ) ≠ y i G_m(x_i)\not=y_i Gm(xi)=yi成立则 I I I为1,反之为0;

e m < 0.5 e_m<0.5 em<0.5;

e m = P ( G m ( x i ) ≠ y i ) = ∑ i = 1 n w m i I ( G m ( x i ) ≠ y i ) = ∑ G m ( x i ) ≠ y i w m i e_m=P(G_m(x_i)\not=y_i)\\ =\sum^n_{i=1}w_{mi}I(G_m(x_i)\not=y_i)\\ = \sum_{G_m(x_i)\not=y_i}w_{mi} em=P(Gm(xi)=yi)=i=1nwmiI(Gm(xi)=yi)=Gm(xi)=yiwmi

损失函数:

为了求解后面两个参数 α m \alpha_m αm w m + 1 , i w_{m+1,i} wm+1,i,需要定义adaboost的损失函数同时最小化损失函数。对于不同的损失函数,两个参数的求法可能不同。

这里选择指数损失函数

对于任意样本点 ( x i , y i ) (x_i,y_i) (xi,yi),预测值为 f ( x i ) f(x_i) f(xi):
L ( y i , f ( x i ) ) = e − y i f ( x i ) L(y_i,f(x_i))=e^{-y_if(x_i)} L(yi,f(xi))=eyif(xi)
对于样本集合:
L ( y i , f ( x i ) ) = ∑ i = 1 N e − y i f ( x i ) L(y_i,f(x_i))=\sum_{i=1}^Ne^{-y_if(x_i)} L(yi,f(xi))=i=1Neyif(xi)
期望表示:

y是样本的实际类别, f ( x ) f(x) f(x)是预测的类别,x的权重服从D分布,E代表期望

L ( y i , f ( x i ) ) = E x   D [ e − y f ( x ) ] L(y_i,f(x_i))=E_{x\text~D}[e^{-yf(x)}] L(yi,f(xi))=Ex D[eyf(x)]

证明合理性:

证明 f ( x ) f(x) f(x)可以使损失函数最小化,则可以让上式对 f ( x ) f(x) f(x)求偏导等于0

L ( y , f ( x ) ) = e − y f ( x ) P ( y = 1 ∣ x ) + e − y f ( x ) P ( y = − 1 ∣ x ) L(y,f(x))=e^{-yf(x)}P(y=1|x) +e^{-yf(x)}P(y=-1|x) L(y,f(x))=eyf(x)P(y=1x)+eyf(x)P(y=1x)

∂ L ( y , f ( x ) ) ∂ f ( x ) = − e − f ( x ) P ( y = 1 ∣ x ) + e f ( x ) P ( y = 1 ∣ x ) = 0 \frac{\partial L(y,f(x))}{\partial f(x)}=-e^{-f(x)}P(y=1|x) +e^{f(x)}P(y=1|x)=0 f(x)L(y,f(x))=ef(x)P(y=1x)+ef(x)P(y=1x)=0

P ( y = 1 ∣ x ) = e 2 f ( x ) P ( y = − 1 ∣ x ) P(y=1|x)=e^{2f(x)}P(y=-1|x) P(y=1x)=e2f(x)P(y=1x)

f ( x ) = 1 2 ln ⁡ P ( y = − 1 ∣ x ) P ( y = 1 ∣ x ) f(x)=\frac{1}{2}\ln\frac{P(y=-1|x)}{P(y=1|x)}\\ f(x)=21lnP(y=1x)P(y=1x)

s i g n ( f ( x ) ) = s i g n ( 1 2 ln ⁡ P ( y = − 1 ∣ x ) P ( y = 1 ∣ x ) ) sign(f(x))=sign(\frac{1}{2}\ln\frac{P(y=-1|x)}{P(y=1|x)}) sign(f(x))=sign(21lnP(y=1x)P(y=1x))

P ( y = 1 ∣ x ) P(y=1|x) P(y=1x)> P ( y = − 1 ∣ x ) P(y=-1|x) P(y=1x)时, s i g n ( f ( x ) ) sign(f(x)) sign(f(x))=1;反之为-1。这种结果正好符合我们想要的分类规则,同时也符合最小化时分类错误率也最小。

加法模型(additive model):

b ( x ; γ m ) b(x;\gamma_m) b(x;γm)为基函数, γ m \gamma_m γm是基函数的参数, β m \beta_m βm是基函数的系数

按照前面说的思路不难看出,我们最终要得到的强学习器就是一个加法模型

f ( x ) = ∑ m = 1 M β m b ( x ; γ m ) f(x)=\sum^M_{m=1}\beta_mb(x;\gamma_m) f(x)=m=1Mβmb(x;γm)

最小化损失函数:
min ⁡ β m , γ m ∑ i = 1 N L ( y i , ∑ m = 1 M β m b ( x i ; γ m ) ) \min_{\beta_m,\gamma_m}\sum_{i=1}^NL\left(y_i,\sum_{m=1}^M\beta_mb(x_i;\gamma_m) \right) βm,γmmini=1NL(yi,m=1Mβmb(xi;γm))
前向分步算法(Forward stagewise algorithm):

由于最小化损失函数很复杂,同时adaboost学习的模型是基分类器组成的加法模型,所以可以使用该算法。

思路是从前向后,一步一步学习,每次只学一个基函数和他的系数,通过加法模型,逐渐逼近优化目标函数式即我们要的最终学习器。

每次需要最小化的损失函数:
( β m , γ m ) = a r g min ⁡ β , γ ∑ i = 1 N L ( y i , f m − 1 ( x i ) + β b ( x i ; γ ) ) (\beta_m,\gamma_m)=arg\min_{\beta,\gamma}\sum_{i=1}^NL\left(y_i,f_{m-1}(x_i)+\beta b(x_i;\gamma) \right) (βm,γm)=argβ,γmini=1NL(yi,fm1(xi)+βb(xi;γ))
在adaboost里运用该算法:

w m i = e − y i f m − 1 ( x i ) w_{mi}=e^{-y_if_{m-1}(x_i)} wmi=eyifm1(xi),与最小化无关,但依赖于 f m − 1 ( x ) f_{m-1}(x) fm1(x)

( α m , G m ( x ) ) = a r g min ⁡ α , G ∑ i = 1 N e − y i ( f m − 1 ( x i ) + α G ( x i ) ) = a r g min ⁡ α , G ∑ i = 1 N w m i e − y i α G ( x i ) (\alpha_m,G_m(x))=arg\min_{\alpha,G}\sum_{i=1}^Ne^{-y_i(f_{m-1}(x_i)+\alpha G(x_i) )}\\=arg\min_{\alpha,G}\sum_{i=1}^N w_{mi}e^{-y_i\alpha G(x_i)} (αm,Gm(x))=argα,Gmini=1Neyi(fm1(xi)+αG(xi))=argα,Gmini=1NwmieyiαG(xi)

G m ( x ) ​ G_m(x)​ Gm(x)的系数 α m ​ \alpha_m​ αm

G m ( x ) G_m(x) Gm(x)在最终分类器中的权重,分类误差越小的基分类器在最终分类器中的作用应该越大,即权重越大。

a r g min ⁡ α ∑ i = 1 N w m i e − y i α G ( x i ) = ∑ y i = G m ( x i ) w m i e − α + ∑ y i ≠ G m ( x i ) w m i e α = ( e α − e − α ) ∑ i = 1 N w m i I ( y i ≠ G ( x i ) ) + e − α ∑ i = 1 N w m i arg\min_{\alpha}\sum_{i=1}^N w_{mi}e^{-y_i\alpha G(x_i)}=\sum_{y_i=G_m(x_i)} w_{mi}e^{-\alpha}+\sum_{y_i\not=G_m(x_i)} w_{mi}e^{\alpha}\\ =(e^{\alpha}-e^{-\alpha})\sum_{i=1}^N w_{mi}I(y_i\not=G(x_i))+e^{-\alpha}\sum_{i=1}^N w_{mi}\\ argαmini=1NwmieyiαG(xi)=yi=Gm(xi)wmieα+yi=Gm(xi)wmieα=(eαeα)i=1NwmiI(yi=G(xi))+eαi=1Nwmi

α m ​ \alpha_m​ αm求偏导:
∂ L ∂ α m = ( e α m + e − α m ) ∑ i = 1 N w m i I ( y i ≠ G ( x i ) ) − e − α m ∑ i = 1 N w m i = 0 \frac{\partial L}{\partial \alpha_m}=(e^{\alpha_m}+e^{-\alpha_m})\sum_{i=1}^N w_{mi}I(y_i\not=G(x_i))-e^{-\alpha_m}\sum_{i=1}^N w_{mi}=0 αmL=(eαm+eαm)i=1NwmiI(yi=G(xi))eαmi=1Nwmi=0

e α m ∑ i = 1 N w m i I ( y i ≠ G ( x i ) ) = e − α m ∑ i = 1 N w m i − e − α m ∑ i = 1 N w m i I ( y i ≠ G ( x i ) ) e^{\alpha_m}\sum_{i=1}^Nw_{mi}I(y_i\not=G(x_i))=e^{-\alpha_m}\sum_{i=1}^N w_{mi}-e^{-\alpha_m}\sum_{i=1}^Nw_{mi}I(y_i\not=G(x_i)) eαmi=1NwmiI(yi=G(xi))=eαmi=1Nwmieαmi=1NwmiI(yi=G(xi))

e α m ∗ e m = e − α m ∗ ( 1 − e m ) e^{\alpha_m}*e_m=e^{-\alpha_m}*(1-e_m) eαmem=eαm(1em)

两边取对数,进一步整理:
α m = 1 2 ln ⁡ 1 − e m e m \alpha_m =\frac{1}{2}\ln\frac{1-e_m}{e_m} αm=21lnem1em

更新样本权重 D m + 1 = ( w m + 1 , 1 , w m + 1 , 2 , w m + 1 , 3 . . . , w m + 1 , n ) D_{m+1}=(w_{m+1,1},w_{m+1,2},w_{m+1,3}...,w_{m+1,n}) Dm+1=(wm+1,1,wm+1,2,wm+1,3...,wm+1,n)

本轮分配错误的话即 y i ≠ G m ( x i ) y_i\not=G_m(x_i) yi=Gm(xi) y i G m ( x i ) = − 1 y_iG_m(x_i)=-1 yiGm(xi)=1;反之为1。

对于 e x e^{x} ex有,当x>0时, e x > 1 e^{x}>1 ex>1;x<0时, e x < 1 e^{x}<1 ex<1

w ˉ m + 1 , i = e − y i f m ( x i ) = e − y i ( f m − 1 ( x i ) + α m G m ( x i ) ) = w ˉ m , i e − y i α m G m ( x i ) \bar w_{m+1,i}=e^{-y_if_m(x_i)} \\ =e^{-y_i(f_{m-1}(x_i)+\alpha_m G_m(x_i) )}\\ =\bar w_{m,i}e^{-y_i\alpha_mG_m(x_i)} wˉm+1,i=eyifm(xi)=eyi(fm1(xi)+αmGm(xi))=wˉm,ieyiαmGm(xi)

权重归一化:
规 范 化 因 子 : Z m = ∑ i = 1 n w m i e − y i α m G m ( x i ) w m + 1 , i = w m , i e − y i α m G m ( x i ) Z m , i = 1 , 2 , 3 , . . . , n 规范化因子:Z_m=\sum^n_{i=1}w_{mi}e^{-y_i\alpha_mG_m(x_i)}\\ w_{m+1,i}=\frac{w_{m,i}e^{-y_i\alpha_mG_m(x_i)}}{Z_m} ,i=1,2,3,...,n Zm=i=1nwmieyiαmGm(xi)wm+1,i=Zmwm,ieyiαmGm(xi)i=1,2,3,...,n

1.3 结束

迭代完成后,组合分类器:

前进分步算法每次更新的加法模型 f m ( x ) = f m − 1 ( x ) + β m b ( x ; γ m ) f_m(x)=f_{m-1}(x)+\beta_mb(x;\gamma_m) fm(x)=fm1(x)+βmb(x;γm)

f ( x ) = f M ( x ) = ∑ m = 1 M β m b ( x ; γ m ) = ∑ m = 1 M α m G m ( x ) f(x)=f_M(x)=\sum^M_{m=1}\beta_mb(x;\gamma_m)\\=\sum^M_{m=1}\alpha_mG_m(x) f(x)=fM(x)=m=1Mβmb(x;γm)=m=1MαmGm(x)
最终分类器:

为了分类只有-1和+1

G ( x ) = s i g n ( f ( x ) ) G(x)=sign(f(x)) G(x)=sign(f(x))

2 代码

# 以李航老师的《统计学习方法》(第二版)的p158例子为例

import numpy as np

x = [0,1,2,3,4,5,6,7,8,9]
y = [1,1,1,-1,-1,-1,1,1,1,-1]

def adaboost(M,x):
    m = 1
    D = [1/len(x)]*len(x) # 初始化
    f = [0]*len(x)
    while m <= M: # 迭代次数
        n = 0 
        G = []
        Z = 0
        em_min = 1 # 初始最低误差率
        v_best = 0 # 初始最佳划分点
        mark = 0
        # 确定最佳划分点
        for v in np.linspace(0.5,9.5,10):
            em1 = 0 # 初始误差率
            em2 = 0
            for i in range(0,len(x)):
                if (x[i] < v and y[i] != 1) or (x[i] > v and y[i] != -1): # 误差率等于分类错误的对应权重和
                    em1 += D[i]
            for j in range(0,len(x)):
                if (x[j] > v and y[j] != 1) or (x[j] < v and y[j] != -1): # 误差率等于分类错误的对应权重和
                    em2 += D[i]

            em = min(em1, em2)
            if em_min > em:  # 记录最低误差率和划分点
                em_min = em
                v_best = v
                if em1>em2:
                    mark = 1
                else:
                    mark = 0

        
        # 求系数a
        a = 0.5*np.log((1-em_min)/em_min)
        
        # 求基本分类器
        for i in range(0,len(x)) :
            if mark == 0:
                if x[i] < v_best:
                    G.append(1)
                else:
                    G.append(-1) 
            else:
                if x[i] < v_best:
                    G.append(-1)
                else:
                    G.append(1) 
        # 求规范化系数Z
        for i in range(0,len(x)):
            Z += D[i]*np.e**(-y[i]*a*G[i])
        # 更新权重
        for i in range(0,len(x)):
            D[i] = D[i]*np.e**(-y[i]*a*G[i])/Z
        # 求分类器
        for i in range(0,len(G)):
            f[i] = f[i] + a*G[i]
            if f[i] < 0 and y[i] != -1 :
                n+=1
            elif f[i] > 0 and y[i] != 1 :
                n+=1
        # 记录
        with open('record.txt','a+',encoding='utf-8') as fp:
            fp.write(f'第{m}次:'+'em:'+f'{em_min}'+'\n'+'v_best:'+f'{v_best}'+'\n'+'a:'+f'{a}'+'\n'+'G:'+str(G)+'\n'+'Z:'+str(Z)+'\n'+'D:'+str(D)+'\n'+'f:'+str(f)+'\n'+'误分类点个数:'+str(n)+'\n')
            fp.close()
        m+=1
    
    # 最终分类器
    for i in range(0,len(f)):
        if f[i] < 0 :
                f[i]= -1
        else:
                f[i]= 1

    return f

adaboost(3,x)



# 结果
# [1, 1, 1, -1, -1, -1, 1, 1, 1, -1]1次:

em:0.30000000000000004

v_best:2.5

a:0.4236489301936017

G:[1, 1, 1, -1, -1, -1, -1, -1, -1, -1]

Z:0.9165151389911682

D:[0.07142857142857142, 0.07142857142857142, 0.07142857142857142, 0.07142857142857142, 0.07142857142857142, 0.07142857142857142, 0.16666666666666663, 0.16666666666666663, 0.16666666666666663, 0.07142857142857142]

f:[0.4236489301936017, 0.4236489301936017, 0.4236489301936017, -0.4236489301936017, -0.4236489301936017, -0.4236489301936017, -0.4236489301936017, -0.4236489301936017, -0.4236489301936017, -0.4236489301936017]

误分类点个数:32次:

em:0.21428571428571427

v_best:8.5

a:0.6496414920651304

G:[1, 1, 1, 1, 1, 1, 1, 1, 1, -1]

Z:0.8206518066482896

D:[0.04545454545454546, 0.04545454545454546, 0.04545454545454546, 0.16666666666666669, 0.16666666666666669, 0.16666666666666669, 0.10606060606060606, 0.10606060606060606, 0.10606060606060606, 0.04545454545454546]

f:[1.073290422258732, 1.073290422258732, 1.073290422258732, 0.22599256187152872, 0.22599256187152872, 0.22599256187152872, 0.22599256187152872, 0.22599256187152872, 0.22599256187152872, -1.073290422258732]

误分类点个数:33次:

em:0.18181818181818185

v_best:5.5

a:0.752038698388137

G:[-1, -1, -1, -1, -1, -1, 1, 1, 1, 1]

Z:0.7713892158398703

D:[0.12499999999999996, 0.12499999999999996, 0.12499999999999996, 0.10185185185185185, 0.10185185185185185, 0.10185185185185185, 0.0648148148148148, 0.0648148148148148, 0.0648148148148148, 0.12499999999999996]

f:[0.3212517238705951, 0.3212517238705951, 0.3212517238705951, -0.5260461365166083, -0.5260461365166083, -0.5260461365166083, 0.9780312602596657, 0.9780312602596657, 0.9780312602596657, -0.3212517238705951]

误分类点个数:0



# sklearn
from sklearn.ensemble import AdaBoostClassifier

# 参数请参考官方文档
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值