AdaBoost 算法

参考Blog:

adaBoost算法

参考书籍:

《机器学习实战》

  • 参考书籍:

Adaboost是一种迭代算法,其核心思想是针对同一个训练集训练不同的分类器(弱分类器),然后把这些弱分类器集合起来,构成一个更强的最终分类器(强分类器)。Adaboost算法本身是通过改变数据分布来实现的,它根据每次训练集之中每个样本的分类是否正确,以及上次的总体分类的准确率,来确定每个样本的权值。将修改过权值的新数据集送给下层分类器进行训练,最后将每次得到的分类器最后融合起来,作为最后的决策分类器。

算法概述

AdaBoost为每个分类器分配了一个权重值alpha,这些alpha值是基于每个弱分类器的错误率进行计算的

    1. 先通过对N个训练样本的学习得到第一个弱分类器(权重相等)
  • 2.在第二次训练中,第一次分对的样本的权重降低,分错的样本权重提高(突出错误样本)

  • 3.最终经过提升的强分类器,即某个数据被分为哪一类主要由各匪类器权值决定

对比Bagging(基于数据随机重抽样的分类器构建方法)
  • 使用加权后选取的训练数据代替随机选取的训练样本,训练的重点被放在被已有分类器错分的那些数据,从而获得新的分类器
  • 联合所有弱分类器,使用加权的投票机制代替平均投票机制。分类效果好的弱分类器具有较大的权重,分类效果差的分类器具有较小的权重。
算法训练过程

adaBoost 算法流程


屏幕快照 2018-01-12 下午9.39.21.png

1.被错误分类的样本权重(alpha)会升高(见下面👇alpha定义)

  1. 分类效果差的分类器的权重会降低
  • 错误率的定义为:


    错误率定义
  • alpha计算公式:


    屏幕快照 2018-01-12 下午9.33.28.png
  • 样本权重公式:

屏幕快照 2018-01-12 下午9.38.34.png

由公式可以看到,权值是关于误差的表达式。每次迭代都会提高错分点的权值,当下一次分类器再次错分这些点之后,会提高整体的错误率,这样就导致分类器权值变小,进而导致这个分类器在最终的混合分类器中的权值变小,也就是说,Adaboost算法让正确率高的分类器占整体的权值更高,让正确率低的分类器权值更低,从而提高最终分类器的正确率。

实例讲解

[站外图片上传中...(image-17246c-1515809860998)]
图中“+”和“-”表示两种类别。我们用水平或者垂直的直线作为分类器进行分类。
算法开始前默认均匀分布D,共10个样本,故每个样本权值为0.1.
第一次分类:
[站外图片上传中...(image-72228f-1515809860998)]
第一次划分有3个点划分错误,根据误差表达式计算可得
e1 = (0.1+0.1+0.1)/1.0 = 0.3

分类器权重为:


屏幕快照 2018-01-12 下午10.03.12.png

第二次分类:



分类误差为e2 = 0.2144
分类器权重:a2 = 0.6493

错分的3个点权值为:d2 = 0.1*(1-0.2144)/0.2144 = 0.3664

第三次分类:



e3= 0.1365 a3 = 0.9223 d3 = 0.6326

最终的强分类器即为三个弱分类器的叠加:


屏幕快照 2018-01-12 下午10.07.37.png
adaboost Python代码
# -*- coding: utf-8 -*-
'''
将所有的弱分类器的结果加权求和就可以得到最后的结果 :P

'''

from numpy import *

# demo数据集
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 stumpClassify(dataMatrix,dimen,threshVal,threshIneg):
    retArray = ones((shape(dataMatrix)[0],1))
    if threshIneg == 'lt':
        #数据过滤
        retArray[dataMatrix[:,dimen] <= threshVal] = -1.0
    else:
        retArray[dataMatrix[:,dimen] > threshVal] = -1.0
    return retArray

def buildStump(dataArr,classLabels,D):
    dataMatrix = mat(dataArr)
    labelMat = mat(classLabels).T
    m,n = shape(dataMatrix)
    numSteps = 10.0 ; bestStump = {};bestClasEst = 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)
                predictedVals = stumpClassify(dataMatrix,i,threshVal,inequal)
                errArr = mat(ones((m,1)))
                errArr[predictedVals == labelMat] = 0
                weightdError = D.T * errArr
                # print "split : dim %d ,thresh %.2f , thresh inequal: %s, the weighted error is %.3f" % \
                #     (i,threshVal,inequal,weightdError)

                if weightdError < minError:
                    minError = weightdError
                    bestClasEst = predictedVals.copy()
                    bestStump['dim'] = i
                    bestStump['thresh'] = threshVal
                    bestStump['ineq'] = inequal

    return bestStump,minError,bestClasEst


def adaBoostTrainDS(dataArr,classLabels,numIt=40): # 单层决策树(decision stump)
    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)
        print "current D:",D.T
        # 算法为分配器分配的权重值
        alpha = float(0.5*log((1.0-error)/max(error,1e-16)))  # 确保不会发生除0
        bestStump['alpha'] = alpha
        weakClassArr.append(bestStump)
        print "classEst: ",classEst.T

        expon = multiply(-1*alpha*mat(classLabels).T,classEst)
        D= multiply(D,exp(expon))
        D = D/D.sum()
        aggClassEst += alpha*classEst #将错误率累加计算,可以更好的估计出这个值是对的还是错误的
        print "aggClassEst: ",aggClassEst.T

        aggErrors = multiply(sign(aggClassEst) != mat(classLabels).T,ones((m,1))) # numpy.sign() 大于0的返回1,小于0的返回-1 ,等于0的返回0
        errorRate = aggErrors.sum()/m
        print "total error: ",errorRate,"\n"
        if errorRate == 0.0:break
    return weakClassArr


def addClassify(datToClass,classifierArr):
    dataMatrix = mat(datToClass)
    m = shape(dataMatrix)[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 += classifierArr[i]['alpha']*classEst #将多个弱分类器的错误率累加计算,可以更好的估计出这个值是否是错误的
        print aggClassEst
    return sign(aggClassEst)

if __name__ == '__main__':
    dataMat,classLabels = loadSimpData()
    adaBoostTrainDS(dataMat,classLabels,9)
算法优点:
  • 1)Adaboost是一种有很高精度的分类器
  • 2)可以使用各种方法构建子分类器,Adaboost算法提供的是框架
  • 3)不用做特征筛选
  • 4)不用担心overfitting的问题
算法缺点:
  • 1)容易受到噪声干扰(大部分算法存在这样的缺点)
  • 2)训练时间较长
  • 3)依赖弱分类器的选择
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容