【算法】集成学习:AdaBoost

集成学习

集成学习通过构建并合并多个学习器来完成学习任务,有时也被称为多分类器系统。
如果在集成学习中我们使用的学习器只包括同种类型的个体学习器,如“决策树集成”中全是决策树,这种集成叫同质集成,这里面的个体学习器称之为“基学习器”,相应的学习算法称之为“基学习算法”,反之称为“异质集成”,个体学习器称为“组件学习器”。


集成学习

集成学习的结果通过投票法产生,即“少数服从多数”。
对个体学习器的要求:

  • 准确性:个体学习器应该有一定的准确性。
  • 多样性:个体学习器间应该具有差异性。

集成学习大致可以分为两类:

  • 个体学习器间存在强依赖关系,必须串行生成序列化的方法,如Boosting
  • 个体学习器间不存在强依赖关系,可同时生成的并行化方法,如Bagging,和随机森林

AdaBoost

Boosting是一族可以将弱学习器提升为强学习器的算法,AdaBoost(adaptive boosting自适应增强)Boost一族的典型代表。

AdaBoost算法流程

训练集T=\{(x_1,y_1), (x_2,y_2)…(x_N,y_N)\},其中x_i \in R^n,y_i \in \{-1,1\},使用M个弱学习器。

  • 步骤一:
    初始化训练数据的权值分布,一开始每一个样本赋予相同的权值\frac{1}{N}
    D_1=(w_{11},w_{1,2},...,w_{1N}),w_{1i}=\frac{1}{N},i=1,2,...,N

  • 步骤二:
    进行多轮的迭代学习,使用具有权值分布的D_m的训练数据集来学习,得到基本分类器。分对的样本的权值会降低,分错的样本的权值会增加,目的是使分错的训练样本得到更多的关注。每个学习器都会有一个权值a_m,a_m的值是基于每个弱分类器的错误率\epsilon_m进行计算的。
    \epsilon=\frac{未正确分类的样本数目}{所有样本数目}
    \epsilon_m=P(G_m(x_i) \ne y_i) =\Sigma_{i=1}^Nw_{mi}I(G_m(x_i) \ne y_i)
    学习器的权值为
    \alpha_m = \frac{1}{2}ln(\frac{1-\epsilon}{\epsilon})
    从这个公式可以看出当\epsilon小于0.5时\alpha>=0,意味着学习器的误差率越小的基学习器在最终的分类器中作用越大。
    然后我们还需要做的就是更新样本的权值
    D_{m+1}=(w_{m+1,1},w_{m+1,2},...,w_{m+1,N})
    w_{m+1,i}=\frac{w_{mi}}{Z_m}exp(-\alpha_m y_iG_m(x_i)),i=1,2,...,N
    这样可以使得被基本分类器Gm(x)误分类样本的权值增大,而被正确分类样本的权值减小。
    其中Z_m是规范化因子,可以使得D_{m+1}成为一个概率分布
    Z_m= \Sigma_{i=1}^Nw_{mi}exp(-\alpha_m y_i G_m(x_i))
    具体的证明过程参见周志华《机器学习》P172~P176

  • 步骤三:
    组合各弱学习器:
    f(x)=\Sigma_{m=1}^{M}\alpha_mG_m(x)
    得到最终的分类器为
    G(x)=sign(f(x))=sign(\Sigma_{m=1}^{M}\alpha_mG_m(x))
    sign(x)x<0,x=0,x>0时取值为-1,0,1

AdaBoost流程

参考这个图片可以更加形象的理解AdaBoost的流程。
伪代码表示:
伪代码表示

Python 实现

AdaBoost.py

#-*- coding=utf8 -*-
from numpy import *
def loadData():
    dataMat = matrix([[1.,2.1],
                      [2.,1.1],
                      [1.3,1.1],
                      [1.,1.],
                      [2.,1.]])
    classLabel = [1.0,1.0,-1.0,-1.0,1.0]
    return dataMat,classLabel

#根据数据与阀值的比较进行分类
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)
    #initial
    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
                weightedError = D.T*errArr
                if weightedError < minerror:
                    minerror = weightedError
                    bestClasEst = predictedVals.copy()
                    bestStump['dim'] = i
                    bestStump['thresh']=threshVal
                    bestStump['ineq'] = inequal
    #返回单层决策树的节点,误差,以及预测值
    return bestStump,minerror,bestClasEst

#基于单层决策树的AdaBoost训练过程
def AdaBoostTrainDS(dataArr,classLabels,numIt=40):
    #弱分类器的列表
    weakClassArr=[]
    m = shape(dataArr)[0]
    #step1:初始化训练数据的权值
    D = ones((m,1))/m
    aggClassEst = mat(zeros((m,1)))
    #串行训练各个弱分类器
    for i in range(numIt):
        bestStump,error,classEst = buildStump(dataArr,classLabels,D)
        print "D: ",D.T
        #计算学习器的权值
        alpha = float(0.5 * log((1.0 - error)/max(error, 1e-16)))
        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: ",alpha*classEst
        aggErrors = multiply(sign(aggClassEst)!=mat(classLabels).T,ones((m,1)))
        errorRate = aggErrors.sum()/m
        print "total error: ",errorRate,"\n"
        if errorRate == 0.0:
            break;
    return weakClassArr

#AdaBoost分类器
def adaClassify(datToClass,classfierArr):
    dataMatrix = mat(datToClass)
    m = shape(dataMatrix)[0]
    aggClassEst = mat(zeros((m,1)))
    for i in range(len(classfierArr)):
        classEst = stumpClassify(dataMatrix,classfierArr[i]['dim'],classfierArr[i]['thresh'],classfierArr[i]['ineq'])
        aggClassEst +=classfierArr[i]['alpha']*classEst
        print aggClassEst
    return sign(aggClassEst)

test.py

import AdaBoost
from numpy import *
#import api
#test loadData
dataMat,classLabel = AdaBoost.loadData()
print dataMat
#test buildStump
D = mat(ones((5,1))/5)
print AdaBoost.buildStump(dataMat,classLabel,D)
#test AdaBoost
classifierArr=AdaBoost.AdaBoostTrainDS(dataMat,classLabel,9)
#test classifier
print AdaBoost.adaClassify([[0,0],[5,5]],classifierArr)
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,204评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,091评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,548评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,657评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,689评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,554评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,302评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,216评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,661评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,851评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,977评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,697评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,306评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,898评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,019评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,138评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,927评论 2 355

推荐阅读更多精彩内容