AdaBoost推导及实现

AdaBoost 属于集成学习算法的一种。集成学习通过构建多个学习任务。结构框架如图所示

这里写图片描述

集成学习通过多个分类器进行结合,因而大多数情况下拥有较好的泛化性能,以AdaBoost为例,其集成方法各有千秋:可以是同一算法在不同设置下集成;也可以是在不同数据集上集成,一般数据进行抽样训练。
不同的学习器要有一定的准确性,又要有差异性。
如图是Ada的模型:

这里写图片描述
右边矩形代表不同权重下的数据集(同一数据集)

AdaBoost既可以用于分类问题,也可以用于回归问题。
关于如何推导出算法的简洁公式:(二分类为例)
二分类问题 y{1,1} 和真实的取值函数 f(x) , 假设基础分类器的错误率为 ϵ ,对于每个分类器 hi(x)

P[hi(x)f(x)]=ϵ

原则上若超过半数以上的分类器分类正确,则认为集成分类就是正确的
集成分类器是其线性组合:
H(x)=sign(t=1Thi(x))

而在AdaBoost中,有一种加权线性模型:
H(x)=t=1Tαihi(x)

其中 αi 为各自分类器的权重。
在分布 D 上,(D为分类器权重向量),定义的最小化损失函数Lexp的表达式为(exp为 exponential loss function 即最小化损失函数):
Lexp(H|D)=ef(x)H(x)

一个多元复合函数,要求其最小化,则求偏导;这里需要对目标函数也就是 H(x) 求偏导:
H(x)1H11H2 ,因而链式求偏导过程为:
ef(x)H(x):f(x):{1,1H(x):{H1(x)H2(x)

那么:

Lexp(H|D)H(x)=ef(x)H(x)H(x)=ef1(x)H1(x)H1(x)+ef1(x)H1(x)H(x)=ef1(x)H1(x)[f1(x)]H(x)H1(x)+ef1(x)H1(x)[f1(x)]H(x)H1(x)

因为 f1(x)=1 f1(x)=1 ,代入上式得:

Lexp(H|D)H(x)=eH1(x)P(f(x)=1|x)+eH1(x)P(f(x)=1|x)

令其为0求解:
eH1(x)P(f(x)=1|x)=eH1(x)P(f(x)=1|x)eH1(x)eH1(x)=P(f(x)=1|x)P(f(x)=1|x)=eH1(x)+H1(x)=e2H(x):H(x)=12lnP(f(x)=1|x)P(f(x)=1|x)

值得注意的是 H(x) 一开始由基于算法初始数据分布而来。

因为: Ht(x)=αtf(x) ,那么:

Lexp(αtf(x)|Dt)αt=12ln1ϵϵ

算法获得 Ht1 后,下一轮学习的 ht 将修正 Ht1 的错误:

Lexp((Ht1+ht)|D)=ef(x)[Ht1(x)+ht]=ef(x)Ht1(x)ef(x)ht(x)

对后一项进行二阶泰勒展开:
因为:二阶泰勒展开: ex=1x+x22

故上式得: ef(x)Ht1(x)[1f(x)ht(x)+f(x)2ht(x)22]

又因为 f(x)2=ht(x)2=1ef(x)Ht1(x)[1f(x)ht(x)+12]

argmax=ef(x)Ht1(x)f(x)ht(x)

argmax=ef(x)Ht1(x)ExD[ef(x)Ht1(x)]f(x)ht(x)

那么每次权重 D 的迭代:

Dt+1=Dt(x)ef(x)Ht(x)Sum(D(x))=Dt(x)eαtf(x)ht(x)Sum(D(x))

下面是代码,公式所有代码实现均在train方法里面:注意一点就是:第一个分类器是基于算法初始数据分布而来(和猜差不多?),此后迭代的生成 ht αt ,而后生成 Dt

class AdaBoost(object):
    def __init__(self,data_matrix,labels,iter_nums):
        self.X = np.matrix(data_matrix)
        self.y = np.matrix(labels)
        samples = np.shape(data_matrix)[0]    
        self.D = np.mat(np.ones((samples,1))/samples)
        self.iter = range(iter_nums)

    def stumpClassfily(self,data_matrix,dimen,thresh_val,thresh_ineq):
        rest_arr = np.ones((np.shape(data_matrix)[0],1))
        if thresh_ineq is 'lt':
            rest_arr[data_matrix[:,dimen]<=thresh_val] = -1.0
        else:
            rest_arr[data_matrix[:,dimen]>thresh_val] = -1.0
        return rest_arr

    def buildStump(self):
        samples,features = np.shape(self.X)
        num_steps = 10
        best_stump = {}
        best_class_estimate = np.mat(np.zeros((samples,1)))
        min_error = np.inf

        for i in range(features):
            range_min = self.X[:,i].min()
            range_max = self.X[:,i].max()
            step_size = (range_max-range_min)/num_steps
            for j in range(-1,num_steps+1):
                for inequal in ['lt','gt']:
                    thresh_val = (range_min+float(j)*step_size)
                    predict_val = self.stumpClassfily(self.X,i,thresh_val,inequal)
                    error_matrix = np.matrix(np.ones((samples,1)))
                    error_matrix[predict_val==self.y.T] = 0
                    weight_error = self.D.T * error_matrix

                    if weight_error < min_error:
                        min_error = weight_error
                        best_class_estimate = predict_val.copy()
                        best_stump['dim'] = i
                        best_stump['thresh'] = thresh_val
                        best_stump['ineq'] = inequal
        return best_stump,min_error,best_class_estimate


    def train(self):
        weak_class_arr = []
        samples = np.shape(self.X)[0]
        aggravete_class_est = np.mat(np.zeros((samples,1)))
        for rounds in self.iter:
            best_stump,error,class_est = self.buildStump()
            alpha = float(0.5*np.log((1.0-error)/max(error,1e-16)))
            best_stump['alpha'] = alpha
            weak_class_arr.append(best_stump)
            expon_loss_func = np.multiply(-1*alpha*self.y.T,class_est)
            self.D = np.multiply(self.D,np.exp(expon_loss_func))
            self.D = self.D/self.D.sum()
            aggravete_class_est += alpha*class_est
            agg_errors_matrix = np.multiply(np.sign(aggravete_class_est)!=self.y.T,
                                            np.ones((samples,1)))
            error_rate = agg_errors_matrix.sum()/samples
            if error_rate is 0.0:break

        return weak_class_arr


class Predcitor(AdaBoost):
    def __init__(self,data_matrix,classifyer_set):
        self.X = data_matrix
        self.classifyers = classifyer_set


    def predict(self):
        samples = np.shape(self.X)[0]
        agg_class_est = np.mat(np.zeros((samples,1)))
        for classifyer in self.classifyers:
            class_est = self.stumpClassfily(self.X,classifyer['dim'],
                                            classifyer['thresh'],
                                            classifyer['ineq'])
            agg_class_est += classifyer['alpha']*class_est
        return np.sign(agg_class_est)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值