机器学习实战-Adaboost(自适应boosting)

本文深入探讨了机器学习领域的集成算法,包括元算法、自举汇聚法(bagging法)、boosting算法,以及单层决策树等核心概念。详细介绍了如何通过集成不同分类器的方法提升模型性能,特别强调了单分类器设置集成的效果,并推荐使用xgboost。文章还涉及了数据加载、单层决策树生成、AdaBoost训练、分类器加权求和、ROC曲线绘制等多个实践环节。

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

元算法(集成算法):不同分类器的组合。类型可包括:不同算法集成、同一算法在不同设置下的集成、数据集不同部分分配给不同分类器后的集成

自举汇聚法(bagging法):从原数据集选择S次后得到S个新的数据集(大小相等,允许有重复)。(分类器权重相等)

boosting:与bagging类似,但是boosting是通过集中关注被已有的分类器错分的那些数据来获得新的分类器。(分类结果基于所有分类器的加权求和的结果)

单层决策树:基于单个特征来作出决策

说明:以下代码是单分类器的不同设置的集成,多个分类器组合效果会较好。推荐xgboost。

#encoding:utf-8
from numpy import *

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 loadDataSet(fileName):
    numFeat = len(open(fileName).readline().split('\t')) #获取文件内容
    dataMat = []; labelMat = []
    fr = open(fileName)
    for line in fr.readlines():
        lineArr =[]
        curLine = line.strip().split('\t')
        for i in range(numFeat-1):
            lineArr.append(float(curLine[i]))
        dataMat.append(lineArr)
        labelMat.append(float(curLine[-1]))
    return dataMat,labelMat
#单层决策树~生成
#通过阈值比较~阈值一侧为-1~另一侧为+1
def stumpClassify(dataMatrix,dimen,threshVal,threshIneq):#直接分类这些数据
    retArray = ones((shape(dataMatrix)[0],1))#均初始化为1
    if threshIneq == 'lt':
        retArray[dataMatrix[:,dimen] <= threshVal] = -1.0
    else:
        retArray[dataMatrix[:,dimen] > threshVal] = -1.0
    return retArray
#找到最佳单层决策树
#遍历stumpClassify()所有可能输入值,并找到数据集最佳单层决策树
#dataArr数据 classLabels类别标签 D:权重向量
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#当预测值与标签值相同时,errArr置0
                weightedError = D.T*errArr  #错误分类的权重
                print "split: dim %d, thresh %.2f, thresh ineqal: %s, the weighted error is %.3f" % (i, threshVal, inequal, weightedError)
                if weightedError < minError:#将当前错误率与历史最小错误率比较,如果当前值较小,就在词典bestStump中保存该单层决策树
                    minError = weightedError
                    bestClasEst = predictedVals.copy()
                    bestStump['dim'] = i
                    bestStump['thresh'] = threshVal
                    bestStump['ineq'] = inequal
    return bestStump,minError,bestClasEst#返回字典、错误率、类别估计值

#基于单层决策树的AdaBoost~~~numIt:弱分类器数目
def adaBoostTrainDS(dataArr,classLabels,numIt=40):
    weakClassArr = []
    m = shape(dataArr)[0]
    D = mat(ones((m,1))/m)   #初始化向量D~概率分布向量,总和为1
    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)))#alpha告诉总分类器本次单层决策树结果输出的权重, max(error,eps) 确保在error=0时不会除0溢出~
        bestStump['alpha'] = alpha#加入到bestStump字典中  
        weakClassArr.append(bestStump)                  #store Stump Params in Array
        #print "classEst: ",classEst.T
        #权重向量更新D=((D’t)*(e’-x))/sum(D)~~  ’号我在这里表示次幂
        expon = multiply(-1*alpha*mat(classLabels).T,classEst) 
        D = multiply(D,exp(expon))
        D = D/D.sum()
        #所有分类器的训练误差计算,如果为0,则跳出循环
        aggClassEst += alpha*classEst#得到类别估计值
        #print "aggClassEst: ",aggClassEst.T
        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,aggClassEst
#所有分类器的结果加权求和,得到最终结果
#利用训练出的多个弱分类器进行分类
#输入:一个或者多个待分类样例datToClass,多个弱分类器组成的数组classifierArr
def adaClassify(datToClass,classifierArr):
    dataMatrix = mat(datToClass)#do stuff similar to last aggClassEst in adaBoostTrainDS~转numpy矩阵
    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'])#call stump classify
        aggClassEst += classifierArr[i]['alpha']*classEst#得到类别估计值
        print aggClassEst
    return sign(aggClassEst)#返回aggClassEst的符号,即大于0为+1~小于0为-1
#输入:predStrengths-分类器的预测强度   classLabels类别标签
def plotROC(predStrengths, classLabels):
    import matplotlib.pyplot as plt
    cur = (1.0,1.0) #光标位置
    ySum = 0.0 #用于计算AUC值
    numPosClas = sum(array(classLabels)==1.0)#计算正例数目
    yStep = 1/float(numPosClas); xStep = 1/float(len(classLabels)-numPosClas)#x,y轴步长
    sortedIndicies = predStrengths.argsort()#get sorted index, it's reverse
    fig = plt.figure()
    fig.clf()
    ax = plt.subplot(111)
    #loop through all the values, drawing a line segment at each point
    for index in sortedIndicies.tolist()[0]:
        if classLabels[index] == 1.0:
            delX = 0; delY = yStep;
        else:
            delX = xStep; delY = 0;
            ySum += cur[1]
        #draw line from cur to (cur[0]-delX,cur[1]-delY)
        #分类代价计算
        ax.plot([cur[0],cur[0]-delX],[cur[1],cur[1]-delY], c='b')
        cur = (cur[0]-delX,cur[1]-delY)
    ax.plot([0,1],[0,1],'b--')
    plt.xlabel('False positive rate'); plt.ylabel('True positive rate')
    plt.title('ROC curve for AdaBoost horse colic detection system')
    ax.axis([0,1,0,1])
    plt.show()
    print "the Area Under the Curve is: ",ySum*xStep



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值