机器学习实战第七章 - 利用AdaBoost元算法提高分类性能

AdaBoost是一种集成学习方法,属于Boosting家族。它通过串行训练获得强依赖的学习器,每个新分类器根据之前的分类器表现调整样本权重。本文介绍了AdaBoost的工作原理、训练流程、Python实现及应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一,AdaBoost概述

AdaBoost是adaptive boosting(自适应boosting)的缩写。
AdaBoost是一种Boosting族的集成学习方法。弱学习器之间是强依赖序列化的,即不同的学习器是通过串行训练而获得的,每个新分类器都根据已训练出来的分类器的性能来进行训练。Boosting是通过集中关注被已有分类器错分的那些数据来获得新的分类器。

AdaBoost特点如下:

  1. 优点:泛化错误率低,易编码,可以应用在大部分分类器上,无参数调整。
  2. 缺点:对离群点敏感。
  3. 适用数据类型:数值型和标称型。
  4. AdaBoost的训练误差随着基学习器的数目的增大将以指数速率下降,但基于的假设是基学习器的误差相互独立,所以要尽量让基学习器好而不同(既要有高的准确率又要多样性),这也是集成学习研究的一个核心。

二,AdaBoost具体流程:基于错误提升分类器的性能

1,具体流程

  1. 训练数据中的每个样本并赋予其一个权重, 这些权重构成了样本权重向量D。一开始这些样本权重都是初始化为相等值。
  2. 首先在训练数据上训练出一个弱分类器,并计算弱分类器的错误率,然后在同一数据集再次训练弱分类器。
  3. 在分类器的第二次训练当中,将会重新调整每个样本的权重, 其中第一次分对的样本的权重将会降低,而第一次分错的样本的权重将会提高。
  4. 最终的分类结果是所有弱分类器的线性加权求和的结果,其中每个弱分类器的权重αα是基于每个弱分类器的错误率来进行计算的。具体如下:
    错误率εε定义如下:
    ε=ε=错误分类样本数所有样本数

    在AdaBoost中:
    ε=ε=错分样本的权重之和

    αα的计算公式如下(由最小化指数损失函数得到):
    α=12ln1εεα=12ln⁡1−εε

    函数图像如下:
    图像
    即错误率越大权重越小。
  5. 计算出αα之后,就可以对样本权重向量进行更新,上一次正确分类的样本权重降低,错误分类的样本权重升高。
    正确分类的样本权重更改为:
    D(t+1)i=D(t)ieαSum(D)Di(t+1)=Di(t)e−αSum(D)

    错误分类的样本权重更改为:
    D(t+1)i=D(t)ieαSum(D)Di(t+1)=Di(t)eαSum(D)

    这些计算公式也是由最小化分类误差确定的,具体推导过程李航《统计学习方法》的第145页:可以认为AdaBoost算法是模型为加法模型、损失函数为指数函数、学习算法为前向分步算法时的二分类学习算法。基分类器的权重αα的计算公式和样本权重更新公式都是用前向分步算法最小化加法模型的指数损失函数时得到的!
  6. 在计算出D之后,AdaBoost又开始进入下一轮迭代。AdaBoost会不断重复训练和调整权重,直至训练错误率为0或弱分类器的数目达到用户的指定值为止。

    如下图所示:
    图解AdaBoost

2,伪代码

AdaBoost伪代码

三,AdaBoost的实现

1,基于单层决策树构建弱分类器

单层决策树也成决策树桩,是最简单的一种决策树。
构建伪代码如下:
DS伪代码

Python代码如下:

def buildStump(dataArray,classLabels,D):
    dataMat = mat(dataArray)
    labelsMat = mat(classLabels).T
    m,n = shape(dataMat)
    numSteps = 10.0
    bestStump = {}
    minError = inf
    bestclasEst = mat(zeros((m,1)))
    for i in range(n):
        rangeMin = dataMat[:,i].min()
        rangeMax = dataMat[:,i].max()
        stepSize = (rangeMax-rangeMin)/numSteps
        for j in range(-1,int(numSteps)+1):
            for inequal in ['lt','gt']:
                threshVal = rangeMin+float(j)*stepSize
                predictedVal = ones((m,1))
                if inequal == 'lt':
                    predictedVal[dataMat[:,i]<=threshVal] = -1.0
                else:
                    predictedVal[dataMat[:,i]>threshVal] = -1.0
                errorArr = ones((m,1))
                errorArr[predictedVal==labelsMat] = 0
                weightedError = float(D.T*errorArr)
                print("dimen:%d,thresh:%.2f,thresh inequal:,%s,weighted error: %.3f"%(i,threshVal,inequal,weightedError))
                if weightedError < minError:
                    minError = weightedError
                    bestclasEst = predictedVal.copy()
                    bestStump['dim'] = i
                    bestStump['thresh'] = threshVal
                    bestStump['ineq'] = inequal
    return bestStump,minError,bestclasEst

单层决策树只需要保存Dim、ThreshVal、InEquality和alpha即可。
单层决策树的生成函数是决策树的一个简化版本,也就是所谓的弱分类器,下面就将使用多个弱分类器来构建AdaBoost算法。

2,AdaBoost算法的实现

伪代码如下:
AdaBoost伪代码

Python代码如下:

def adaBoostTrainsDS(dataArr,classLabels,numIt=40):
    weakClassArr = []
    dataMat = mat(dataArr)
    m = shape(dataMat)[0]
    D = mat(ones((m,1))/m)
    aggClassEst = mat(zeros((m,1)))
    for i in range(numIt):
        bestStump,error,classEst = buildStump(dataMat,classLabels,D)
        alpha = 0.5*log((1-error)/max(error,1e-16))
        bestStump['alpha'] = alpha
        weakClassArr.append(bestStump)
        expon = multiply(-alpha*mat(classEst),mat(classLabels).T)
        D = multiply(D,exp(expon))
        D = D/D.sum()
        aggClassEst += alpha*classEst
        aggError = multiply(sign(aggClassEst)!=mat(classLabels).T,ones((m,1)))
        errorRate = aggError.sum()/m
        print('the total error is:%.2f'%(errorRate))
        if errorRate==0:
            break
    return weakClassArr

用户需要指定训练的迭代次数。

3,测试算法:基于AdaBoost的分类

Python代码如下:

def stumpClassify(dataMatrix,dimen,threshVal,threshIneq):
    retArray = ones((shape(dataMatrix)[0],1))
    if threshIneq=='lt':
        retArray[dataMatrix[:,dimen]<=threshVal] = -1.0
    else:
        retArray[dataMatrix[:,dimen]>threshVal] = -1.0
    return retArray
def adaClassify(datToClass,classifierArr):
    dataMat = mat(datToClass)
    m = shape(dataMat)[0]
    aggClassEst = mat(zeros((m,1)))
    for i in range(len(classifierArr)):
        classEst = stumpClassify(dataMat,classifierArr[i]['dim'],classifierArr[i]['thresh'],classifierArr[i]['ineq'])
        aggClassEst += classEst*classifierArr[i]['alpha']
        print(aggClassEst)
    return sign(aggClassEst)

4,在一个难的数据集上应用AdaBoost

读文件数据的代码:

def loadDataSet(filename):
    numFeat = len(open(filename).readline().split('\t'))-1
    fr = open(filename)
    dataArr = []
    classLabels = []
    for line in fr.readlines():
        lineArr = line.strip().split('\t')
        featureArr = []
        for j in range(numFeat):
            featureArr.append(float(lineArr[j]))
        dataArr.append(featureArr)
        classLabels.append(float(lineArr[-1]))
    dataMat = mat(dataArr)
    return dataMat,classLabels

使用AdaBoost进行预测的过程如下:

>>> datArr,labelArr = adaboost.loadDataSet('horseColicTraining2.txt')
>>> classifierArray = adaboost.adaBoostTrainDS(datArr,labelArr,10)
total error: 0.284280936455
total error: 0.284280936455
.
.
total error: 0.230769230769
>>> testArr,testLabelArr = adaboost.loadDataSet('horseColicTest2.txt')
>>> prediction10 = adaboost.adaClassify(testArr,classifierArray)
To get the number of misclassified examples type in:
>>> errArr=mat(ones((67,1)))
>>> errArr[prediction10!=mat(testLabelArr).T].sum()
16.0
>>> 16/67
0.23880597014925373

四,AdaBoost总结

  • 通常情况下,AdaBoost会达到一个稳定的测试错误率,而并不会随着弱分类器数目的增多而增加。
  • 很多人认为,AdaBoost和SVM是监督机器学习中最强大的两种方法。
  • AdaBoost这种针对错误的调节能力正是它的强大之处。
  • 总之,AdaBoost算法十分强大,它能快速处理其他分类器很难处理的数据集。
  • 为防止AdaBoost训练的过早停止,可以使用重采样法来重启动训练过程:即在抛弃不满足条件的当前基学习器之后,可根据当前分布重新对训练样本进行采样,再基于新的采样结果重新训练出基学习器,从而使得学习过程可以持续到预设的T轮完成。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值