机器学习算法——利用AdaBoost元算法提高分类性能(基于单层决策树构建的弱分类器)

本文深入探讨了AdaBoost元算法,一种集成学习方法,详细解释了其工作原理、流程及如何构建弱分类器。通过使用单层决策树,AdaBoost能有效提升分类器性能,实现从弱学习到强学习的转变。

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

当做出重要决定时,我们往往会听取多个专家而不只是一个人的意见。元算法正是采用这种思路,元算法是对其他算法进行组合的一种方式,本篇博文主要介绍AdaBoost元算法,该算法是机器学习工具箱中最强有力的工具之一。
博文用到的数据集和代码:
链接:https://pan.baidu.com/s/1cJ6B1Z8tFUDopnXsEQBnrw
提取码:01gm

集成学习

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

之前的博文已经介绍了几种常用的分类器,包括决策树,朴素贝叶斯,支持向量机等。它们有着不同的特性,我们可以将不同的分类器组合起来,这种组合结果就被称为集成方法或者元算法。
使用集成方法时有多种形式:可以是不同算法的集成,也可以是同一种算法在不同设置下的集成,还可以是数据集不同部分分配给不同分类器之后的集成。

AdaBoost
优点:泛化错误率低,易编码,可以应用在大部分分类器上,无参数调整。
缺点:对离群点敏感
适用数据类型:数值型和标称型数据

1.1 bagging:基于数据随机重抽样的分类器构建方法

自举汇聚法(boostrap aggregating) ,也称为bagging方法,是在从原始数据集选择S次后得到S个新数据集的一种技术。新数据集和原数据集的大小相等。每个数据集都是通过在原始数据集中随机选择一个样本来进行替换而得到的。
也就是说,从原始集合中随机选择一个样本,然后随机选择一个样本来代替这个样本。bagging中的数据集通常被认为是放回取样得到的,比如要得到一个大小为n的新数据集,该数据集中的每个样本都是在原始数据集中随机抽样(即抽样之后又放回)得到的。
因此,替换就意味着可以多次地选择同一个样本,这一性质也使得新数据集中可以出现重复的值,而原始数据集的某些值在新集合中则不再出现。
在S个数据集构建好之后,将某个学习算法分别作用于每个数据集就得到了S个数据集。当我们要面对新数据进行分类时,就可以应用这S个分类器进行分类,与此同时,选择分类器投票结果中最多的类别作为最后的分类结果。
当然,除了上述的bagging方法,还有更先进的方法,例如随机森林,限于篇幅,按下不表,后续会增加一篇博文继续学习。

1.2 boosting:

boosting是一种与bagging很类似的技术。在boosting和bagging中,所使用的多个分类器的类型都是一致的。但是在前者中,不同的分类器是通过串行训练获得的,每个新分类器都根据已训练出的分类器的性能来进行训练。boosting是通过集中关注被已有分类器错分的那些数据来获取新的分类器。
由于boosting分类的结果是基于所有分类器的加权求和结果的,因此boosting与bagging不太一样。bagging中的分类器全中国是相等的,而boosting中的分类器权重并不相等,每个权重代表的是其对应分类器在上一轮迭代中的成功度。
本文重点介绍AdaBoost

Adaboost的一般流程
(1)收集数据:可以使用任何方法,诸如爬虫等
(2)准备数据:依赖于所使用的弱分类器类型,后续将使用单层决策树,该分类其可以处理处理任何数据类型,也可以使用其他任意类型的弱分类器,作为弱分类器,简单分类器的效果最好
(3)分析数据:可以绘制出相关的散点图等
(4)训练算法:AdaBoost的大部分时间都在训练上,分类器将多次在同一数据集上训练弱分类器
(5)测试算法:计算分类的正确率
(6)使用算法:和SVM一样,原始的AdaBoost用于二分类,如果需要应用多分类,就需要像多类SVM中一样对算法做出修改。

boost 算法系列的起源来自于PAC Learnability(直译过来称为:PAC 可学习性)。这套理论主要研究的是什么时候一个问题是可被学习的。PAC 模型的作用相当于提供了一套严格的形式化语言来陈述以及刻画这里所提及的可学习性 Learnability 以及(样本)复杂度 (Sample) Complexity 问题。

PAC 定义了学习算法的强弱:

  • 弱学习算法:识别错误率小于1/2(即准确率仅比随机猜测略高的学习算法)
  • 强学习算法:识别准确率很高并能在多项式时间内完成的学习算法。

更为严格的定义:

  • 弱学习算法:一个概念如果存在一个多项式的学习算法能够学习它,并且学习的正确率仅比随机猜测略好(高于50%),那么,这个概念是弱可学习的
  • 强学习算法:一个概念如果存在一个多项式的学习算法能够学习它,并且正确率很高,那么,这个概念是强可学习的。

2、 基于错误提升分类器的性能

任意给定仅比随机猜测略好的弱学习算法 ,是否可以将其提升为强学习算法?
或者说能否使用弱分类器和多个实例来构建一个强分类器?

AdaBoost算法正是脱胎于此。AdaBoost是adaptive boosting的缩写。
Adaboost是一种迭代算法,其核心思想是针对同一个训练集训练不同的分类器,即弱分类器,然后把这些弱分类器集合起来,构造一个更强的最终分类器,比起弱分类器,这个“强”分类器的错误率会低很多。

Adaboost算法本身是改变数据分布实现的,它根据每次训练集之中的每个样本的分类是否正确,以及上次的总体分类的准确率,来确定每个样本的权值。将修改权值的新数据送给下层分类器进行训练,然后将每次训练得到的分类器融合起来,作为最后的决策分类器。以下给出 Adaboost算法的运行过程:

  1. 训练数据中的每个样本,并赋予其一个权重,这些权重构成向量D,一开始时权重D初始化为相等的值;
  2. 先在训练样本上训练得到第一个弱分类器并计算分类器的错误率 ;
  3. 在同一数据集上再次训练弱分类器,在分类器的二次训练中,会重新调整每个样本的权重,其中第一次分类正确的样本的权重将会降低,而分类错误的样本权重将会提高
  4. 为了从所有弱分类器中得到最终的分类结果,Adaboost为每个分类器都分配了一个权重值alpha,这一组值是基于每个弱分类器的错误率进行计算的。

其中错误率ε的定义为:
在这里插入图片描述
而α的计算公式如下:
在这里插入图片描述
AdaBoost算法的流程如下:
在这里插入图片描述
图中的左边表示数据集,其中直方图的不同宽度表示每个样例上的不同权重。在经过一个分类器之后,加权的预测结果会通过三角形中的alpha值进行加权,每个三角形中输出的加权结果在圆形中求和,从而得到最终的输出结果。
计算出alpha值后,可以对权重向量D进行更新,使得那些正确分类的样本的权重降低而错分样本的权重升高。计算方法如下:

对于正确分类的样本,其权重更改为:
在这里插入图片描述
对于错误分类的样本,其权重更改为:
在这里插入图片描述
在计算出权重向量D后,Adaboost方法开始进入下一轮的迭代。Adaboost方法会不断地重复训练和调整权重的过程,知道训练错误率为0(或达到用户指定的条件)为止。

Adaboost的训练过程就像一个学生学习的过程:我们把每个训练样例看做一道练习题,所有的训练样本看做一本习题集。第一次做题的时候,由于每道题都没有做过,不知道哪些难哪些简单,所以一视同仁,做完了对照答案,可能会有很多题目做的不对,那么对于做错的题目,我们就重点标记,给予更高的重视程度,这个用权重w来标示,到第二轮做题的时候就重视这些没做对的“难题”,对于第一次就做对的题目,可以认为是比较简单的,那么第二次的时候稍微看下就可以了,可以降低他的权重。并且,对于第一轮做完以后的效果给一个整体的评分,评价这轮做题的能力,这个就是alpha。在第二轮做题的时候,就按照上一轮调整过的权重对不同的题目给予不同的重视程度和时间分配。如此不断练习,几轮下来,难题就逐渐被攻克了。每轮做题都是有收获的,只不过每次收获的知识权重不同(alpha),这样,我们最后就得到m个分类器,综合每个分类器的权重,我们就能得到一个“学习成绩很好”的分类器了。

当然,这种训练思路不是没有弊端的:如果有个别极端数据导致分类器的分类失败,那么算法会着重考虑这个极端数据的情况,这也就使得AdaBoost对离群点非常敏感。

3、 基于单层决策树构建弱分类器

单层决策树(decision stump, 也称决策树桩)是一种简单的决策树。前面我们已经介绍了决策树的工作原理,接下来将构建一个单层决策树,而它仅基于单个特征来做决策。由于这棵树只有一次分裂过程,因此它实际上就是一个树桩。
数据集加载代码如下:

def loadSimpData():
    datMat = 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 draw(dataSet, labelSet):
    x1 = []
    x2 = []
    y1 = []
    y2 = []
    for i in range(len(labelSet)):
        if labelSet[i] == 1.0:
            x1.append(dataSet[i][0])
            y1.append(dataSet[i][1])
        else:
            x2.append(dataSet[i][0])
            y2.append(dataSet[i][1])
    axes = plt.figure().add_subplot(111)
    # 正类数据集
    first = axes.scatter(x1, y1, c='red')
    # 负类数据集
    second = axes.scatter(x2, y2, c='green')
    # 防止出现中文乱码
    chinese_font = matplotlib.font_manager.FontProperties(fname='C:\Windows\Fonts\simsun.ttc')
    plt.title('单层决策树测试数据', fontproperties=chinese_font)
    plt.show()

datMat, classLabels = loadSimpData()
draw(datMat, classLabels)

在这里插入图片描述
r如果想要试着从某个坐标轴上选择一个值(即选择一条与坐标轴平行的直线)来将所有的红色点和绿色点分开是不可能的。这就是单层决策树难以处理的著名问题,通过使用多棵单层决策树,我们就可以构建一个能够对该数据集完全正确分类的分类器。

有了数据,接下来就岢以通过构建多个函数来建立单层决策树。
第一个函数将用于测试是否有某个值小于或者大于我们正在测试的阈值。第二个函数则更加复杂一些,它会在一个加权数据集中循环,并找到具有最低错误率的单层决策树。
这个程序的伪代码看起来大致如下:
将最小错误率minError设为+00
对数据集中的每一个特征(第一层循环):
  对每个步长(第二层循环):
    对每个不等号(第三层循环):
      建立一棵单层决策树并利用加权数据集对它进行测试
      如果错误率低于m in Err0r,则将当前单层决策树设为最佳单层决策树返回最佳单雇决策树

单层决策树生成函数,代码如下:

def stumpClassify(dataMatrix, dimen, threshVal, threshIneq):  # just classify the data
    # 构建(m,1)单位数组
    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


def buildStump(dataArr, classLabels, D):
    dataMatrix = np.mat(dataArr)
    # 求出数据集维度
    labelMat = np.mat
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值