Machine Learning---6--Adaboost

1、基于数据集多重抽样的分类器

1.1 bagging

自举汇聚法(bootstrap aggregating),也称为bagging方法,是在从原始数据集选择S次后得到S个新数据集的一种技术。新数据集和原数据集的大小相等,每个数据集都是在原始数据集中有放回随机选择样本得到,这意味着新数据集中可以有重复的样本,也可能没有包括原数据集的所有样本。

在S个数据集建好之后,将某个学习算法分别作用于每个数据集就得到了S个分类器。当我们要对新数据进行分类时,就可以应用这S个分类器进行分类。与此同时,选择分类器投票结果中最多的类别作为最后的分类结果。

1.2 boosting

boosting和bagging很类似,他们使用相同类型的分类器,但是在boosting中,不同的分类器是通过串行训练而获得的。Boosting集中关注被已有分类器错分的那些数据来获得新的分类器。

由于boosting分类的结果是基于所有分类器的加权求和的结果,所以在boosting中分类器的权重并不相等,每个权重代表的是其对于分类器在上一轮迭代中的成功度。

Boosting方法有多个版本,本节只关注其中一个最流行的版本AdaBoost。

1.3 AdaBoost

AdaBoost是adaptive boosting(自适应boosting)的缩写,它的理论根植于使用弱分离器和多个实例来构建一个强分类器。这里的“弱”意味着分类器的性能比随机猜测要略好,但是也不会好太多;而“强”分类器的错误率将会低很多。

其运行过程如下:训练数据中的每个样本,并赋予其一个权重,这些权重构成了向量D。一开始,这些权重都初始化成相等值。首先在训练数据上训练出一个弱分类器并计算该分类器的错误率,然后在同一数据集上再次训练弱分类器。在分类器的第二次训练当中,将会重新调整每个样本的权重,其中第一次分对的样本的权重将会降低,而第一次分错的样本的权重将会提高。为了从所有弱分类器中得到最终的分类结果,AdaBoost为每个分类器都分配了一个权重值alpha,这些alpha值是基于每个弱分类器的错误率进行计算的。其中,错误率ε的定义为:

而alpha的计算公式为:


计算出alpha值之后,可以对权重向量D进行更新,以使得那些正确分类的样本的权重降低而错分样本的权重升高。 

如果某个样本被正确分类,权重更改为:

而如果被错分,权重则更改为:

在计算出D之后,AdaBoost又开始进入下一轮迭代,知道训练错误率为0或者弱分类器的数目达到用户指定值为止。

2、AdaBoost算法的实现---python代码

## 1、 构建弱分类器---单层决策树是AdaBoost中最流行的弱分类器。
import numpy as np

def loadSimpData():
    '''
    导入简单训练数据    
    '''
    datMat = np.matrix([[ 1. ,  2.1],
        [ 2. ,  1.1],
        [ 1.3,  1. ],
        [ 1. ,  1. ],
        [ 2. ,  1. ]])
    classLabels = [1.0, 1.0, -1.0, -1.0, 1.0]
    return datMat,classLabels


def buildStump(dataArr,classLabels,D):
    '''
    建立一个单层决策树
    输人为权重向量D,
    返回具有最小错误率的单层决策树、最小的错误率以及估计的类别向量
    '''    
    dataMatrix =np. mat(dataArr); labelMat =np. mat(classLabels).T
    m,n = np.shape(dataMatrix)
    numSteps = 10.0; bestStump = {}; bestClasEst = np.mat(np.zeros((m,1)))
    minError = np.inf #
    for i in range(n):#对数据集中的每一个特征
        rangeMin = dataMatrix[:,i].min(); rangeMax = dataMatrix[:,i].max();
        stepSize = (rangeMax-rangeMin)/numSteps
        for j in range(-1,int(numSteps)+1):#对每个步长
            for inequal in ['lt', 'gt']: #对每个不等号
                threshVal = (rangeMin + float(j) * stepSize)
                predictedVals = stumpClassify(dataMatrix,i,threshVal,inequal)
                errArr = np.mat(np.ones((m,1)))
                errArr[predictedVals == labelMat] = 0
                weightedError = D.T*errArr  #计算加权错误率
                #print("split: dim %d, thresh %.2f, thresh ineqal: %s, the weighted error is %.3f" % (i, threshVal, inequal, weightedError))
                #如果错误率低于minError,则将当前单层决策树设为最佳单层决策树                
                if weightedError < minError:
                    minError = weightedError
                    bestClasEst = predictedVals.copy()
                    bestStump['dim'] = i
                    bestStump['thresh'] = threshVal
                    bestStump['ineq'] = inequal
    return bestStump,minError,bestClasEst

def stumpClassify(dataMatrix,dimen,threshVal,threshIneq):
    '''
    通过阈值比较对数据进行分类    
    '''
    retArray = np.ones((np.shape(dataMatrix)[0],1))
    if threshIneq == 'lt':
        retArray[dataMatrix[:,dimen] <= threshVal] = -1.0
    else:
        retArray[dataMatrix[:,dimen] > threshVal] = -1.0
    return retArray

##2、基于单层决策树的AdaBoost训练过程


def adaBoostTrainDS(dataArr,classLabels,numIt=40):
    '''
    基于单层决策树的AdaBoost训练过程
    '''
    weakClassArr = []
    m = np.shape(dataArr)[0]
    D = np.mat(np.ones((m,1))/m)   #初始化权重向量为1/m
    aggClassEst = np.mat(np.zeros((m,1)))#记录每个数据点的类别估计累计值
    for i in range(numIt):
        #建立一个单层决策树
        bestStump,error,classEst = buildStump(dataArr,classLabels,D)
        print("D:",D.T)
        #计算alpha,此处分母用max(error,1e-16)以防止error=0
        alpha = float(0.5*np.log((1.0-error)/max(error,1e-16)))
        bestStump['alpha'] = alpha  
        weakClassArr.append(bestStump)
        print("classEst: ",classEst.T)
        #计算下一次迭代的D
        expon = np.multiply(-1*alpha*np.mat(classLabels).T,classEst)
        D = np.multiply(D,np.exp(expon))                              
        D = D/D.sum()
        #以下计算训练错误率,如果总错误率为0,则终止循环
        aggClassEst += alpha*classEst
        print("aggClassEst: ",aggClassEst.T)
        aggErrors = np.multiply(np.sign(aggClassEst) != np.mat(classLabels).T,np.ones((m,1)))
        errorRate = aggErrors.sum()/m
        print("total error: ",errorRate)
        if errorRate == 0.0: break
    return weakClassArr,aggClassEst
 
    
##3、简单测试分类效果
def adaClassify(datToClass,classifierArr):
    
    '''
    利用训练出的多个弱分类器进行分类    
    datToClass:待分类数据
    classifierArr:训练的结果
    '''
    
    dataMatrix =np. mat(datToClass)
    m =np. shape(dataMatrix)[0]
    aggClassEst = np.mat(np.zeros((m,1)))
    #遍历classifierArr中的所有弱分类器,并基于stumpClassify对每个分类器得到一个类别的估计值
    for i in range(len(classifierArr)):
        classEst = stumpClassify(dataMatrix,classifierArr[i]['dim'],\
                                 classifierArr[i]['thresh'],\
                                 classifierArr[i]['ineq'])
        aggClassEst += classifierArr[i]['alpha']*classEst            #此处问题未解决--二维索引
        print(aggClassEst)
    return np.sign(aggClassEst)
    

if __name__ == "__main__":
    dataArr,labelArr=loadSimpData()
    print(labelArr)
    print('-----------------------')
    classifierArr=adaBoostTrainDS(dataArr,labelArr,30)
    print(classifierArr)
    print('-----------------------')
    pred=adaClassify([0,0],classifierArr)
    print(pred)
    



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值