【机器学习】【提升方法-BoostingTree-3】提升树学习算法详解+示例讲解数学求解过程

1.提升树的简介

提升树是以分类树或回归树为基本分类器的提升方法。提升树被认为是统计学习中性能最好的方法之一

1.1提升方法思路

采用加法模型(即基函数的线性组合)与前向分布算法。

1.2提升树

以决策树为基函数的提升方法称为提升树(boosting tree)

1.3二叉分类树

对分类问题决策树是二叉分类树

1.4二叉回归树

对回归问题决策树是二叉回归树

1.5决策树桩

在AdaBoosting算法中用到的基本分类器base_generator:

base_generator = lambda x,v,f1,f2:(x<y and [f1] or [f2])[0]

可以看做有一个根节点v直接连接两个叶子f1和f2,如果x小于根节点v,则x的分类标签取f1,如果x大于根节点v,则x的分类标签取f2。则base_generator就可以看做一个简单的决策树,即所谓的决策树桩(decision stump)

1.6提升树模型公式

提升树模型表示为决策树的加法模型:



2.提升树(BoostingTree)学习算法详解

注:针对不同问题的提升树学习算法,其主要区别在于使用的损失函数不同。比如用平方误差损失函数的回归问题,用指数损失函数的分类问题,还有用一般损失函数的一般决策问题。

如果提升树学习算法使用AdaBoosting算法中的基本分类器作为二类分类树,这是的提升树学习算法就演化为AdaBoosting算法。这里我们讲解回归问题的提升树学习算法~

2.1提升树学习算法中的基本操作简介

已知一个训练数据集train_samples =[[x1,y1],[x2,y2],[,x3,y3],[x4,y4],[x5,y5]]

则X=[x1,x2,x3,x4,x5]是输入空间,Y=[y1,y2,y3,y4,y5]是输出空间,Y[i]是X[i]的回归结果

下面以一个具体训练数据集来讲解

    #训练数据集 Train Samples
    #train_samples[:,0]为数据集,train_samples[:,1]为回归结果集
    train_samples = np.array([[1, 5.56],
                  [2, 5.70],
                  [3, 5.91],
                  [4, 6.40],
                  [5, 6.80],
                  [6, 7.05],
                  [7, 8.90],
                  [8, 8.70],
                  [9, 9.00],
                  [10,9.05]])

2.1.1数据X

则X=[1,2,3,4,5,6,7,8,9,10]是输入空间,Y=[5.56, 5,70, 5.91, 6.40, 6.80, 7.05, 8.90, 8.70, 9.00, 9.05]是输出空间(即回归结果)

python代码:

X,Y =train_samples[:,0],train_samples[:,1]

2.1.2回归值

比如X[0]=1的回归值是Y[0]=5.56,X[5]=6的回归值是Y[5]=6.80

即在训练数据集中,数据值回归值的回归函数为:f(X[i]) = Y[i]

2.1.3切分点s和切分点集合S

数据集合的切分点s:将X切分成两个子数据集的数据,比如1.5可以将X切分为如下两个子数据集RX1和RX2

s=1.5,RX1 = [1],RX2 = [2, 3, 4, 5, 6, 7, 8, 9, 10]

求训练数据集的切分点集合S的python代码:

        '''计算所有可能切分点的集合,S'''
        X,N,S= train_samples[:,0], np.shape(train_samples)[0],[]
        for i in (np.arange(N)[0:-1]:
            S.append((X[i] + X[i+1])/2.0)

2.1.4切分点集合S

所有可能的切分点的集合,称为切分点(segmentation point)集合S

则S=[1.5, 2.5, 3.5, 4.5, 5.6, 6.5 7.5, 8.5, 9.5]

2.1.5切分区域R

切分区域有数据切分区域(RX1,RX2),和回归值切分区域(RY1,RY2)

when 切分点s=1.5

数据切分区域   :RX1 = [1],RX2 = [2, 3, 4, 5, 6, 7, 8, 9, 10]

回归值切分区域:RY1 = [5.56],RY2 = [5,70, 5.91, 6.40, 6.80, 7.05, 8.90, 8.70, 9.00, 9.05]

python代码:

RX = [X[0:i+1], X[i+1:]]
RY = [Y[0:i+1], Y[i+1:]]

2.1.6平均回归值c1和c2

在RX1内部使得平方损失误差达到最小值的回归值,记为c1

在RX2内部使得平方损失误差达到最小值得回归值,记为c2

可以很容易知道,c1=mean(RY1),c2=mean(RY2)

用上面的RY1和RY2计算就是:c1 =mean(RY1) = 5.56,c2 = mean(RY2) = 7.50

cur_c1 = np.mean(RY[0])
cur_c2 = np.mean(RY[1])

2.1.7切分点的回归误差平方和m

when 切分点s=1.5

数据切分区域   :RX1 = [1],RX2 = [2, 3, 4, 5, 6, 7, 8, 9, 10]

回归值切分区域:RY1 = [5.56],RY2 = [5,70, 5.91, 6.40, 6.80, 7.05, 8.90, 8.70, 9.00, 9.05]

切分区域的平均回归值:c1 = 5.56,c2 = 7.50

切分点s=1.5的回归误差平方和m:

m=(5.56-c1)^2 + (5.70-7.50)^2 + (5.91-7.50)^2 + (6.40-7.50)^+……+(9.00-7.50)^2+(9.05-7.50)^2

   =15.72

m1_ufunc = lambda y : np.power(y-c1 ,2)
m2_ufunc = lambda y : np.power(y-c2, 2)
m1_func  = np.frompyfunc(m1_ufunc, 1, 1)
m2_func  = np.frompyfunc(m2_ufunc, 1, 1)
cur_m = m1_func(RY[0]).sum() + m2_func(RY[1]).sum()

2.1.8最佳切分点s

现在我们选取最佳切分点作为当前即将要生成的回归树的根节点

最佳切分点:求切分点集合S中每个切分点的回归误差平方和m,m值最小的切分点s就是最佳切分点

还是用使用面的数据,可以依次求得每个切分点的回归误差平方和m

S=[1.5, 2.5, 3.5, 4.5, 5.6, 6.5 7.5, 8.5, 9.5]

M=[m(s1), m(s2), m(s3), m(s4), m(s5), m(s6), m(s7), m(s8), m(s9)]

   =[m(1.5), m(2.5), m(3.5), m(4.5), m(5.5), m(6.5), m(7.5), m(8.5), m(9.5)]

   =[15.72, 12.07, 8.36, 5.78, 3.91, 1.93, 8.01, 11.73, 15.74]

mean(M) = 1.93 = mean(M(6.5)) => 最佳切分点s=6.5

i = np.argmin(M)
s,m,c1,c2 = S[i], M[i], C[i][0], C[i][1]

2.1.9回归树T(x)

回归树T(x) = T(x|{v,f1,f2})

根节点v为最佳切分点s,左叶子f1=c1=6.24,右叶子f2=c2=8.91

def Tx(x, s, c1, c2):
    if x < s:
        return f1
    else:
        return f2

建议使用lambda+(and-or)定义回归树T(x)

Tx = lambda x,s,c1,c2 :(x<s and [c1] or [c2])[0]

2.1.10残差(residual)

有训练数据输入空间X,输出空间Y,以及学习得到的提升树f(x)

Y[i] - f(X[i])称为f(x)拟合训练数据X[i]的残差,记作r(X[i])=Y[i] - f(X[i])

2.1.11残差表(Residual Table)

经过计算我们学习生成了训练数据集的第一个回归树T(x) = T(x | {s=6.5, f1=6.24, f2=8.91})

因为此T(x)是我们求得的第一个回归树,则学习到的提升树f(x)=T(x)

如果T(x)是我们求得的第K个回归树,则学习到的提升树更新为f(x) = f(x) + T(x)

X[i]残差r(X[i]) = Y[i] - f(X[i])

我们可以求得更新提升树后的残差表Rsd

R = [r(X[0]), r(x[1]), r(X[2]), r(X[3]), r(X[4]), r(X[5]), r(X[6]), r(X[7]), r(X[8]), r(X[9])]

=[Y[0]-f(X[0]),Y[1]-f(X[1]),Y[2]-f(X[2]),Y[3]-f(X[3]),Y[4]-f(X[4]), Y[5]-f(X[5]), Y[6]-f(X[6]), Y[7]-f(X[7]), Y[8]-f(X[8]), Y[9]-f(X[9])]

=[5.56-f(1), 5.70-f(2), 5.91-f(3), 6.40-f(4), 6.80-f(5), 7.05-f(6), 8.90-f(7), 8.70-f(8), 9.00-f(9), 9.05-f(10)]

=[5.56-f(1), 5.70-f(2), 5.91-f(3), 6.40-f(4), 6.80-f(5), 7.05-f(6), 8.90-f(7), 8.70-f(8), 9.00-f(9), 9.05-f(10)]
注:f(x|{v=6.5, f1=6.24, f2=8.91}) = 如果x<v回归值取f1=6.24,如果x>=6.5回归值取f2=8.91

=[5.56-6.24, 5.70-6.24, 5.91-6.24, 6.40-6.24, 6.80-6.24, 7.05-6.24, 8.90-8.91, 8.70-8.91, 9.00-8.91, 9.05-8.91]
=[-0.68, -0.54, -0.33, 0.16, 0.56, 0.81, -0.01, -0.21, 0.09, 0.14]

python代码:

        #更新残差表(用提升树拟合训练数据的残差表)
        rsd_ufunc = lambda x,y : (x<s and [y-c1] or [y-c2])[0]
        rsd_func = np.frompyfunc(rsd_ufunc, 2, 1)
        rsd = rsd_func(X, Y)

2.1.12f(x)训练数据的平方损失误差

如果有提升树f(x),并求出了用f(x)拟合训练数据的残差表Rsd

rsd =[-0.68, -0.54, -0.33, 0.16, 0.56, 0.81, -0.01, -0.21, 0.09, 0.14]

用f(x)拟合训练数据的平方损失误差e=残差表中每个残差平方的和

e = (0.68)^2 + (-0.54)^2 + (0.33)^2 + (0.16)^2 + (0.56)^2 + (0.81)^2 + (-0.01)^2 + (0.09)^2 + (0.14)^2

   = 1.93

python代码:

        #计算用提升树f(x)拟合训练数据的平方损失误差
        e_ufunc = lambda r : np.power(r,2)#r为残差
        e_func  = np.frompyfunc(e_ufunc, 1, 1)
        e = e_func(rsd).sum() #rsd为当前提升树f(x)的残差表

2.1.13提升树

我们学习得到一个新的回归树T(x),如果已有学习得到的提升树f(x),则新学习到的提升树更新为:

    f(x) = f(x) + T(x)

通过提升树学习,我们得到了提升树f(x)的存储体FX为:

 [[ 6.5   6.24  8.91]
 [ 3.5  -0.52  0.22]
 [ 6.5   0.15 -0.22]
 [ 4.5  -0.16  0.11]
 [ 6.5   0.07 -0.11]
 [ 1.5  -0.22  0.02]]

先解释说明,如何理解f(x)的这个存储体FX:

FX[0] = [6.5 6.24 8.91],表示这是第一个学习得到的回归树T(x),根节点v=6.5,左叶子f1=6.24,右叶子f2=8.91

FX[5] = [1.5 -0.22 0.02],表示这是最后一个学习得到的回归时T(x),根节点v=1.5,左叶子=-0.22,右叶子f2=0.02

可知我们一共学习到6个回归树,提升树f(x)等于这6个回归树的加:

f(x) = T1(x) + T2(x) + T3(x) + T4(x) + T5(x) + T6(x)

      =T(x|FX[0]) + T(x|FX[1]) + T(x|FX[2]) + T(x|FX[3]) + T(x|FX[4]) +T(x|FX[5])

提升树的回归函数python代码:

    def Regress(self, test_samples):
        '''提升树的回归函数
        使用学习得到的提升树,对给定的单个测试数据test_x进行回归
        :param test_samples:测试数据集
        :return 回归结果
        '''
        base_tree = lambda x,v,f1,f2 : (x<v and [f1] or [f2])[0]
        reg_efunc = lambda x : sum([base_tree(x,v,f1,f2) for v,f1,f2 in self.FX])
        reg_func = np.frompyfunc(reg_efunc, 1, 1)
        return reg_func(test_samples)

2.1.14提升树学习终止

如果用提升树f(x)拟合训练数据的平方损失误差e小于允许的最大平方损失误差max_e,则提升树学习终止,f(x)为最终的提升树

3.2回归问题的提升树学习算法步骤

输入:训练数据集T={(x1,y1), (x2,y2), ..., (xn, yn)},其中X是输入空间,Y是输出空间

输出:提升树f(x)

(1)初始化提升树f(x)

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值