统计学习boosting算法

Boosting的原理的简单理解

通过构建几个弱分类器,将几个弱分类器进行集成,从而得到一个分类性能较好的强分类器。分类器的优化也就是训练过程是一个串行的过程,后一个分类器的优化是建立在前一个分类器的基础上的。
Boosting算法一个常见的实例就是提升树,这个树是一个二叉树,后一个树的构建在前几个树的基础上。树的参数的确定过程实际上就相当于神经网络的训练过程。树的参数包括:所选择的用来分类的特征是什么,按照这个特征进行分类的话,分类的阈值是什么。策略就是:大于这个分类阈值的话,把样本分为-1类还是小于分类阈值将样本划分为-1类,对应着右子树和左子树的概念。

具体代码实现

## adaptive boost 自适应的提升算法
## 具体的算法步骤是:
## 创建一个基本的分类树
## 获得当前的分类树的预测结果
## 根据规则进行样本权重的更新
## 'NoneType' object has no attribute 'append'

"初始化模型的参数"
import numpy as np
class AdaBoost():
    def __init__(self,X):
        self.x_train = X[:,:-1]
        self.x_label = X[:,-1]
        self.w = np.array([1/self.x_train.shape[0]]*np.shape(self.x_train)[0])
        self.G = []
        self.max_iter =10
        self.high = 0.1

        ## M个分类器这个变量怎么进行初始化呢??

    def one_classifier(self):
        _, n = np.shape(self.x_train)
        value = None
        sign = None
        best_stump = {}
        err_min = np.inf # 先设置为无穷大
        
        for i in range(n):
            value = max(self.x_train[:,i]) - min(self.x_train[:,i])
            step_size = value/n
            for j in range(int(n)+1):
                threshold = min(self.x_train[:,i]) + j*step_size
                # 左子树和右子树的分类的错误率都要进行计算
                # 目的是比较哪两个子树的分类的误差率较小
                for strategy in ['left','right']:
                    predict_label = self.predict_one(self.x_train,i,threshold,strategy)
                    # 接下来统计分类错误的个数
                    # 接下来统计加权的分类错误的权重
                    # 目的是为了比较左边子树和右边子树到底是哪一个的分类率较好
                    err_ = np.array(np.ones(np.shape(self.x_train)[0]))
                    err_[predict_label == self.x_label] = 0
                    err_1 = np.dot(self.w, err_) # 计算分类错误的样本的加权的权重
                    #err_num = int(m) - sum(predict_label == self.x_label)
                    #err_rate = err_num/m
                    if err_1 < err_min:
                        err_min = err_1
                        sign = predict_label
                        # 获得而一颗分类的子树
                        best_stump['dim'] = n
                        best_stump['threshold'] = j
                        best_stump['strategy'] = strategy

        return best_stump, sign, err_min

    @staticmethod
    def predict_one(data,dimension,thre,strategy):
        arr_base = np.array(np.ones(np.shape(X)[0]))
        if strategy == 'left':
            arr_base[data[:,dimension] <= thre] = -1
        else:
            arr_base[data[:,dimension] > thre] = -1
        return arr_base


    # 接下来是fit函数以及evaluate函数了
    def fit(self):
        
        G = 0
        
        # 先要设置一个基本的分类器,这个分类器表示的是各个弱分类器的和
        # 遍历1,到最大的迭代次数
        # 创建一个当前最佳的分类器树桩,获得弱分类器的加权系数
        # 在表示一个若分类器的字典里面增加一个属性,这个属性表示这个分类器的加权系数
        # 把这个弱分类器保存到大的分类器中
        # G进行更新,表示的是最后的分类器,也就是继承好以后的分类器
        # G进行输出,得到每一个样本的预测标签值
        # 计算集成后的分类器的误差
        # 判断误差是否小于阈值,如果是的话,说明此时这个集成以后的分类器的效果是比较好的,直接跳出循环
        # 如果误差不满足要求,则将更新训练集中每一个样本的权重
        # 样本的权重关系到重新构造的数据集的可能性
        # 其实这个训练过程iterations迭代就是相当于epoch,在这里一个batch就是全部分样本,也就是full_batch
        # 进行loss计算,根据计算的loss对参数权重进行更新,在这里说的参数权重就是指的模型的参数权重
        for i in range(self.max_iter):# 每一次迭代都会返回一个分类树的树桩
            best_stump, sign, err_min = self.one_classifier()   
            alpha = 1/2*np.log((1-err_min)/err_min) 
            best_stump['alpha'] = alpha
            self.G.append(best_stump)
            G += sign * alpha
            predict_end = np.sign(G)
            err_rate_ = sum(predict_end==self.x_label)/len(self.x_label)
            if err_rate_ <= self.high:
                print('iterations:')
                print(i)
                break
            else:
                self.weight_update(alpha,predict_end)
        return self.w


    def weight_update(self,alpha,predict):
        self.w = self.w * np.exp(-self.x_label*alpha*predict)# 这是一个向量
        self.w = self.w/(sum(self.w)) #被除数部分是一个求和以后的数值
    

    # 测试训练好的提升树对新样本的分类能力
    # 输入一个新的样本
    # 创建一个空的分类器
    # 把已经训练好的存储在self.G的列表中的每一个基本的子树复制过来
    # 遍历每一个基本的子分类器
    # 把每一个基本的子分类器的属性与值拿到,输入到一个分类器函数中,获得预测结果


    def test(self,x_test):
        G_total = 0
        m = np.shape(x_test)[0]
        for i in range(len(self.G)):
            G_test = self.G[i] # 
            G_test_ = self.predict_one(x_test,G_test['dim'],G_test['threshold'],G_test['strategy'])
            alpha = G_test['alpha']
            G_total += alpha*G_test_
        test_predict_ = np.sign(G_total)
        return test_predict_      
if __name__ =='__main__':

    # 加载训练数据
    X = np.array([[0, 1, 3], [0, 3, 1], [1, 2, 2], [1, 1, 3], [1, 2, 3], [0, 1, 2],
                [1, 1, 2], [1, 1, 1], [1, 3, 1], [0, 2, 1]])
    y = np.array([-1, -1, -1, -1, -1, -1, 1, 1, -1, -1])
    X = np.c_[X,y.T] #在最后面插入一列,表示的是标签

    clf = AdaBoost(X)
    weight = clf.fit()
    test_ = clf.test(X)
    test_ = np.array(test_,dtype=int)
    print(weight)
    print('Test label:')
    print(test_)
    print('---------------------------------')
    print('The true labels:')
    print(y)

迭代十次以后,训练集的样本的权重如下
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值