AdaBoost(自适应增强算法)

AdaBoost(自适应增强算法)

AdaBoost的目标是通过一个弱分类器构建一个强分类器,AdaBoost的大致运行过程:训练数据中的每一个样本,并赋予其一个权重,形成对应的权重向量 D ,一开始所有训练样本具有相同权值,然后使用弱分类器分类并计算出该分类器的错误率,然后再统一数据集上面再次训练弱分类器,在第二次训练中,将会调整每个样本的权值,其中第一次分队的样本的权重将会降低,第一次分错的样本权重将会提高。最终我们能得到一组分类器,通过,并且根据最终每个分类器的错误率为每个分类器赋予一个权重值alpha, alpha 公式如下:

α=12ln(1ϵϵ)1
,当 alpha 得到后我们对权重向量 D 进行更新,使得正确分类的样本权值降低,错分样本权重升高,计算方法如下:如果某个样本被正确分类则权重值更改为:
D(t+1)i=D(t)ieαSum(D)2
,如果某个样本被错分,那么样本的权重更改为:
D(t+1)i=D(t)ieαSum(D)3
,通过不断的训练和调整权重产生新的分类器,知道训练错误率为0或者达到指定值为止。

通过单层决策树构建弱分类器

单层决策树是一种简单的决策树,不像之前的介绍的决策树,它只会做一层分裂,例如判断数值大于指定值时归类到class1,否则归类到class2。
构建一个简单的数据集:

dataMat = 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]


AdaBoost需要构建多个单层决策树,多个决策树组合起来实现正确的对数据集进行分类。
单层决策树实现:

#dimen 表示特征下标
#threshVal 表示分隔值
#threshIneq 表示分隔方式
def stumpClassify(dataMat, dimen, threshVal, threshIneq):
    retArray = ones((shape(dataMat)[0],1))
    if threshIneq == 'lt':
        for i in shape(dataMat)[0]:
            if dataMat[i][dimen] <= threshVal: retArray[i] = -1.0
    else:
        for i in shape(dataMat)[0]:
            if dataMat[i][dimen] > threshVal: retArray[i] = -1.0
    return retArray

AdaBoost算法实现:
通过下面的方法可选择出在当前权重 D <script type="math/tex" id="MathJax-Element-9">D</script>下最佳的决策分类信息,返回值分别为当前最优分类器,当前分类器的误差值,最终的分类结果。

#这里的D为每个样本的初始权重,计算方式为 D = ones((shape(dataMat)[0],1))/shape(dataMat)[0]
def buildStump(dataMat, classLabels, D):
    dataMatrix = mat(dataMat);labelMatrix=mat(classLabels).T
    m,n = shape(dataMatrix)
    numSteps = 10.0; bestStump ={};bestClassEst=mat(zeros((m,1)))
    minError = 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)
                predictValue = stumpClassify(dataMatrix, i, threshVal, inequal)
                errArr = mat(ones((m,1)))
                for classIndex in range(0,m):
                    if errArr[classIndex] == labelMatrix[classIndex]:
                        errArr[classIndex]=0
                weightError = D.T * errArr
                if weightError < minError:
                    minError = weightError
                    bestClassEst = predictVals.copy()
                    bestStump['dim'] = i
                    bestStump['thresh'] = threshVal
                    bestStump['ineq'] = inequal
    return bestStump, minError, bestClassEst

    Example Result:
    >>> bestStump
    {'dim': 0, 'ineq': 'lt', 'thresh': 1.3}
    >>> minError
    matrix([[ 0.2]])
    >>> bestClassEst
    array([[-1.],
           [ 1.],
           [-1.],
           [-1.],
           [ 1.]])

完整AdaBost Training 算法实现:
算法输出结果为一组弱分类器,每个分类器都有对应的权重值

def adaBoostTrainDS(dataArr, classLables, numIt=40):
    #用于存储弱分类器组
    weakClassArr = []
    m = shape(dataArr)[0]
    #初始化训练数据权重值
    D = mat(ones((m,1))/m)
    aggClassEst = mat(zeros((m,1)))

    for i in range(numIt):
        bestStump, error, classEst = buildStump(dataArr, classLabels, D)
        #计算alpha值
        alpha = float(0.5*log((1.0 - error)/max(error, 1e-16)))
        bestStump['alpha'] = alpha
        weakClassArr.append(bestStump)
        #更新权重向量D,数学公式参见上面的
        #得到的 expon为一个 (m,1)的向量
        expon = multiply(-1*alpha*mat(classLabel).T, classEst)
        ##利用上面的 公式(2) 公式(3)更新 D
        D = multiply(D, exp(expon))
        D = D/D.sum()
        aggClassEst += alpha*classEst
        ##当前所有分类器组合得到的分类结果
        prediction = sign(aggClassEst)
        ##计算误差值
        aggError = ones((m,1))
        for i in range(prediction.shape()[0]):
            if prediction[i] == classLabels.T[i] :
                aggError[i] = 0
        # 上面的for 循环可以简单用下面的语句
        #aggErrors = multiply(sign(aggClassEst)!=mat(classLabels).T, ones((m,1)))

        #计算错误率
        errorRate = aggError.sum()/m
        if errorRate == 0.0: break;

    return weakClassArr

使用AdaBoost分类器进行分类目标数据

def adaClassify(dataToClass, classifierArr):
    dataMatrix = mat(dataToClass)
    m = shape(dataMatix)[0]
    ##现将测试数据的分类结果初始为0
    aggClassEst = mat(zeros((m,1)))
    for i in range(len(classifierArr)):
        classEst = stumpClassify(dataMatrix, classifierArr[i]['dim'], classifierArr[i]['thresh'], classifierArr[i]['ineq'])
        aggClassEst+= classifier[i]['alpha']*classEst


    return sign(aggClassEst)

AdaBoost 分类性能调优

不同弱分类数目会存在不同的分类错误率,但并不是说弱分类器的数量越多分类错误率越低,通常情况下,AdaBoost会达到一个稳定的测试错误率,而并不会随分类数目的增多而提高,另外一些情况下弱分类器数量当超过每一个最佳数值后,随着弱分类器数量的增加,错误率也会随之增高,这种现象称之为过拟合,因此在构造我们分类器时我们需要通过不断分类错误率和分类器数目找到一个最佳的分类器数。
这是一个分类器数目和错误率映射case:

分类器数目训练错误率(%)测试错误率(%)
10.280.27
100.230.24
500.190.21
1000.190.22
5000.160.25
10000.140.31
100000.110.33
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值