(李航统计学习方法)提升方法

本文主要包括adaboost和提升树,后期会扩展到XGboost和LightGBM。
boosting通过改变样本训练权重,学习多个弱分类器,最后进行线性组合,提高分类性能。
两个着重点:如何改变数据的样本权重或概率分布 如何将弱分类器整合成强分类器

Adaboost(Adaptiveboost)

adaboost通过提高错误分类样本权重,使的下一轮错误数据由于上一轮调高权重,而受到弱分类的关注。同时,使用加权多数表决的方式,组成一个强分类器。
算法流程:

  1. 初始化样本数据权重,假设样本权重均匀分布,得到初始权重分布D1
  2. 使用初始权重的训练数据集学习,得到基本分类器G1
  3. 计算G1在权重分布D1上的误差率
  4. 依据公式计算G1的权重
  5. 在D1基础上,依据误分率更改样本的权重分布,错误分类数据的权重提升,得到权重分布D2
  6. 迭代m轮,构建线性组合的强分类器Gm

adaboost的训练误差分析

在这里插入图片描述
这说明,可以在每一轮选取适当的Gm使得Zm最小,从而使训练误差下降最快,对二分类问题,有如下结果:
在这里插入图片描述
adaBoost的另外一个解释:
模型:加法模型
策略:最小化指数函数
算法:前向分步
公式的推导:
1、证明使用指数函数作为损失函数的合理性
2、计算弱分类器的权重
3、更新权重分布
adaboost python实现:

from numpy import *
def loaddata():
    datMat=matrix([
        [1.0,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,threshInsq):
    """
    
    :param dataMatrix:数据 
    :param dimen: 特征
    :param threshVal: 阈值
    :param threshInsq: 大于还是小于
    :return: 
    """
    retArray= ones((shape(dataMatrix)[0],1))
    if threshInsq=='lt':
        retArray[dataMatrix[:,dimen]<=threshVal]=-1.0
    else:
        retArray[dataMatrix[:,dimen]>threshVal]=-1.0
    return retArray

def buildStump(dataArr,classLabels,D):
    """
    
    :param dataArr:数据 
    :param classLabels: 样本类别
    :param D: 权重的分布
    :return: 
    """
    dataMatrix=mat(dataArr)
    labelMat=mat(classLabels).T
    m,n=shape(dataMatrix)
    numSteps=10.0
    bestStump={}
    bestClassEnt=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)
                threshVal=(rangeMin+float(j)*stepSize)
                errArr=mat(ones((m,1)))
                #计算错误的权重
                errArr[predictedVals==labelMat]=0
                weightedError=D.T*errArr
                if weightedError<minError:
                    minError=weightedError
                    bestClassEnt=predictedVals.copy()
                    bestStump['dim']=i
                    bestStump['thresh']=threshVal
                    bestStump['ineq']=inequal
    return  bestStump,minError,bestClassEnt


def adaBoostTrainDS(dataArr,classLabels,numIt=40):
    """
    
    :param dataArr: 数据
    :param classLabels: 样本类别
    :param numIt: 迭代次数
    :return: 
    """
    weakClassArr=[]
    m=shape(dataArr)[0]
    ##初始的权重分布
    D=mat(ones((m,1))/m)
    aggClassEst=mat(zeros((m,1)))
    ##迭代numlt次
    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)
        print("classEst",classEst.T)

        expon=multiply(-1*alpha*mat(classLabels).T,classEst)
        #更新权重
        D=multiply(D,exp(expon))
        D=D/D.sum()
        aggClassEst+=alpha*classEst
        aggErrors=multiply(sign(aggClassEst)!=mat(classLabels).T,ones((m,1)))
        errorRate=aggErrors.sum()/m
        print('total error:',errorRate)
        if errorRate==0.0:
            break
    return weakClassArr

def adaClassify(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'])
        ##利用前面训练好的adaboost模型进行预测
        aggClassEst+=classifierArr[i]['alpha']*classEst
        print(aggClassEst)
    return sign(aggClassEst)

if __name__ == '__main__':
    datMat,classLabels=loaddata()
    classifierArray=adaBoostTrainDS(datMat,classLabels,30)
    print("[0,0]:\n", adaClassify([0, 0], classifierArray))
    print("\n\n[[5,5],[0,0]]:\n", adaClassify([[5, 5], [0, 0]], classifierArray))

提升树算法

提升树算法采用的是前向分步算法通过经验风险极小化确定下一颗决策树的参数
针对不同问题提升树学习算法,主要区别在于使用损失函数的不同,包括回归问题使用均方误差,分类问题的指数损失函数,以及一般决策问题的一般损失函数。
梯度提升树与adaboost的关系
梯度提升树分为分类树,回归树;adaboost将基本弱分类器限制为二类分类树就是提升树

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值