机器学习实战第7章——利用adaboost元算法提高分类性能(代码片段)

weiququ weiququ     2022-12-23     376

关键词:

将不同的分类器组合起来,这种组合结果被称为集成方法或元算法(meta-algorithm)。

使用集成方法时会有多种形式:(1)可以是不同算法的集成(2)可以是同一种算法在不同设置下的集成(3)数据集不同部分分配给不同分类器之后的集成,等等

接下来介绍基于同一种分类器多个不同实例的两种不同计算方法bagging和boosting

1. bagging

  原理:从原始数据集选择S次后得到S个新数据集的一种技术。新数据集和原数据集的大小相等。每个数据集都是通过在原始数据集中随机选择一个样本来进行替换而得到的。这里的替换就意味着可以多次地选择同一样本,允许重复。(取出,放回)。将某个学习算法分别作用于每个数据集就得到S个分类器。每个分类器的权值相同

2. boosting

  原理:集中关注被已有分类器错分的那些数据来获得新的分类器。是所有分类器加权求和结果,每个分类器的权值不同。

  从弱学习算法出发,反复学习,得到一系列弱分类器(又称为基本分类器),然后组合这些弱分类器,构成一个强分类器。大多的boosting方法都是改变训练数据的概率分布(训练数据的权值分布),针对不同的训练数据分布调用弱学习算法学习一系列弱分类器。

  那么对于boosting方法,有两个问题需要回答:(1) 在每一轮如何改变训练数据的权值或者概率分布?

                       (2)如何将弱分类器组合成一个强分类器?

  接下来介绍boosting中一个最流行的算法AdaBoost,在AdaBoost是如何解决上面两个问题的呢?对于第一个问题,AdaBoost的做法是,提高那些被前一轮弱分类器错误分类样本的权值,而降低被正确分类样本的权值。对于第二个问题,AdaBoost采取加权多数表决的方法,加大分类误差率小的弱分类器的权值,减小分类误差率大的弱分类器的权值

3. AdaBoost算法

    技术分享图片

下面是具体的算法:

    技术分享图片

  技术分享图片

  对于(2)中的(d)根据下式得到

      技术分享图片

具体代码如下:

import numpy as np
from math import log


def loadSimpData():
    datMat = np.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):      #general function to parse tab -delimited floats
    numFeat = len(open(fileName).readline().split(	)) #get number of fields
    dataMat = []; labelMat = []
    fr = open(fileName)
    for line in fr.readlines():
        lineArr =[]
        curLine = line.strip().split(	)
        for i in range(numFeat-1):
            lineArr.append(float(curLine[i]))
        dataMat.append(lineArr)
        labelMat.append(float(curLine[-1]))
    return dataMat,labelMat


"""
    函数说明:通过阈值比较对数据进行分类
    Parameters:
        dataMatrix -输入数据
        dimen -第几列
        threshVal -阈值
        threshIneq -不等号
    return:
        分类结果
"""
def stumpClassify(dataMatrix, dimen, threshVal, threshIneq):
    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


"""
    函数说明:建立单层决策树
    Parameters:
        dataArr     -输入数据集
        classLabels -分类
        D           -权重向量
    return:
        bestStump   -最佳单层决策树字典
        minError    -最小错误率
        bestClassEst    -最佳类别估计值
"""
def buildStump(dataArr, classLabels, D):
    dataMatrix = np.mat(dataArr)
    labelMat = np.mat(classLabels).T
    m, n = np.shape(dataMatrix)
    #numSteps:步数; bestStump:保存最佳单层决策树的相关信息; bestClassEst:最佳预测结果
    numSteps = 10.0; bestStump = ; bestClassEst = np.mat(np.zeros((m, 1)))
    minError = np.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 = np.mat(np.ones((m, 1)))
                errArr[predictedVals == labelMat] = 0
                weightError = D.T * errArr    #计算加权错误率
                print("split:dim %d,thresh %.2f,thresh inequal: %s,the weighted error is %.3f"%(i,threshVal,inequal,weightError))
                # 找到最小错误率的最佳单层决策树,并保存相关信息
                if weightError < minError:
                    minError = weightError
                    bestClassEst = predictedVals.copy()
                    bestStump[dim] = i
                    bestStump[thresh] = threshVal
                    bestStump[ineq] = inequal
    return bestStump, minError, bestClassEst


"""
    函数说明:基于单层决策树的AdaBoost训练过程
    Patameters:
        dataArr     -数据集
        classLabels -数据标签
        numIt       -迭代次数
    return:
        weakClassArr    -所有的最佳分类器决策树
        aggClassEst     -累计分类估计
"""
def adaBoostTrainDS(dataArr,classLabels,numIt=40):
    weakClassArr = []
    m = np.shape(dataArr)[0]
    D = np.mat(np.ones((m,1))/m)   #init D to all equal
    aggClassEst = np.mat(np.zeros((m,1)))
    for i in range(numIt):
        bestStump,error,classEst = buildStump(dataArr,classLabels,D)#build Stump
        print("D:",D.T)
        # alpha公式:alpha=1/2*ln((1-error)/error)
        # max(error, 1e-16)是为了防止error=0的情况
        alpha = float(0.5 * log((1.0 - error) / max(error, 1e-16)))
        bestStump[alpha] = alpha
        weakClassArr.append(bestStump)                  #保存最优单层决策树
        print("classEst: ",classEst.T)
        #更新D,D是一个概率分布向量,总和为1
        # D=(D*exp(-alpha*classLabels*classEst))/D.sum()
        # classEst是分类器预测的分类结果,classEst是
        # np.multiply是矩阵对应元素相乘,返回和矩阵大小一样,classLabels是m*1,classEst是1*m
        expon = np.multiply(-1 * alpha * np.mat(classLabels).T,classEst) #exponent for D calc, getting messy
        D = np.multiply(D, np.exp(expon))                              #Calc New D for next iteration
        D = D / D.sum()
        #更新累计估计类别
        #aggClassEst记录每个类别的累计估计值,最终分类函数为f(x) = sign(aggClassEst)
        aggClassEst += alpha*classEst
        print("aggClassEst: ",aggClassEst.T)
        #计算错误率
        aggErrors = np.multiply(np.sign(aggClassEst) != np.mat(classLabels).T,np.ones((m,1)))
        errorRate = aggErrors.sum() / m
        print("total error: ",errorRate)
        #误差为0时退出循环
        if errorRate == 0.0: break
    return weakClassArr,aggClassEst

""" 函数说明:测试算法,AdaBoost分类函数 Parameters: datToClass -待分类样例 classifierArr -多个弱分类器组成的数组 return: 类别 """ def adaClassify(datToClass,classifierArr): dataMatrix = np.mat(datToClass) m = np.shape(dataMatrix)[0] aggClassEst = np.mat(np.zeros((m,1))) for i in range(len(classifierArr)): #基于每个分类器得到一个类别值 print(classifierArr[i]) classEst = stumpClassify(dataMatrix,classifierArr[i][dim], classifierArr[i][thresh], classifierArr[i][ineq])#call stump classify aggClassEst += classifierArr[i][alpha]*classEst print(aggClassEst) return np.sign(aggClassEst)
if __name__ == __main__: datMat, classLabels = loadSimpData() D = np.mat(np.ones((5,1)) / 5) buildStump(datMat, classLabels, D) classifierArr, aggClassEst = adaBoostTrainDS(datMat, classLabels) print(adaClassify([0,0],classifierArr)) print(adaClassify([[0,0],[1,0],[2,2]],classifierArr)) #将第5章的马疝病数据应用到AdaBoost算法中 datArr, labelArr = loadDataSet(horseColicTraining2.txt) classifierArr,aggClassEst = adaBoostTrainDS(datArr, labelArr, 10) testArr, testLableArr = loadDataSet(horseColicTest2.txt) prediction = adaClassify(testArr, classifierArr) errArr = np.mat(np.ones((67,1))) errRate = errArr[prediction!= np.mat(testLableArr).T].sum() / 67 print(errRate)

技术分享图片

4. 非均衡分类问题

  非均衡分类问题是指,在很多情况下不同类别的分类代价并不相等。例如对于垃圾邮件过滤的例子,如果我们把所有的邮件都预测为垃圾邮件,则用户可能会错过重要的合法邮件,如果我们把所有的邮件都预测为合法邮件,则会影响到用户体验,但是这两种代价是不一样的。

性能度量

  性能度量是指衡量模型泛化能力的评价标准。在回归问题中常用的性能度量是“均方误差”(mean squared error)。而在分类问题中错误率是一种常用的性能度量,错误率是指分类错误的样本占样本总数的比例,实际上这样的度量错误掩盖了样例如何被错分的事实。在机器学习中,有一个普遍使用的称为混淆矩阵的工具,它可以帮助人们更好的了解分类中的错误。

技术分享图片

   正确率/查准率(precision):预测为正例的样本中真正正例的比例

            技术分享图片

   召回率/查全率(recall):预测为正例的真正例占所有正例的比例

            技术分享图片

  通常查准率和查全率是一对矛盾的度量。一般来说查准率高的时候,查全率会偏低;而查全率高的时候,查准率会偏低。通常只有在一些简单任务中查准率和查全率都很高。

  P-R图能直观的显示出学习器在样本总体上的查全率、查准率。

        技术分享图片

  图中的平衡点(BEP)是查准率=查全率时的取值,BEP高则更优,对于图中的三个学习器,A优于B优于C。

  但BEP还是过于简化了,通常使用的是F1度量

      技术分享图片

  对于有偏好的情况:

      技术分享图片

  其中ß>O 度量了查全率对查准率的相对重要性. ß = 1时退化为标准的F1; ß> 1 时查全率有更大影响; ß < 1 时查准率有更大影响

  

   接下来介绍ROC曲线

      技术分享图片

   纵坐标为真阳率(真正例率):

        技术分享图片

  横坐标为假阳率(假正例率):

        技术分享图片

  AUC(area under the curve):ROC曲线下的面积,对不同的ROC曲线进行比较的一个指标,给出的是分类器的平均性能值。一个完美的分类器的AUC是1,而随机猜测的AUC则为0.5。若一个学习器的ROC曲线能把另一个学习器的ROC曲线完全包住,则这个学习器的性能比较好。

  实现代码如下,书中是以(1.0,1.0)点为起点来画曲线的,我改成了以(0.0,0.0)为起点,这样更好理解一些。

  绘制过程:给定m+个正例,m-个反例,将分类器的预测强度进行排序,然后把分类阈值设为最大,即把所有的样例都预测为反例,此时真阳率和假阳率均为0,在坐标(0,0)处标记一个点。然后将分类阈值依次设置为每个样例的预测值,即依次将每个样例划分为正例。设前一个坐标点为(x,y),若当前点为真正例,则它的坐标为(x,y+1/m+),真阳率变大;若当前点为假正例,则坐(x+1/m-,y),假阳率变大。

"""
    函数说明:ROC曲线绘制及AUC计算函数
    Parameters:
        predStrengths   -分类器的预测强度,马疝病数据集中为1*299
        classLabels     -分类标签
"""
def plotROC(predStrengths, classLabels):
    import matplotlib.pyplot as plt
    # cur = (1.0,1.0) #绘制光标的位置
    cur = (0.0,0.0) #绘制光标的位置
    ySum = 0.0 #用于计算AUC的值
    numPosClas = sum(np.array(classLabels)==1.0)    #保存正例的数目
    yStep = 1/float(numPosClas); xStep = 1/float(len(classLabels)-numPosClas)   #y轴的步长、x轴的步长
    sortedIndicies = predStrengths.argsort()#获取排好序的索引,从小到大
    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][::-1]:  #改为从大到小
        if classLabels[index] == 1.0:   #标签为1修改真阳率
            delX = 0; delY = yStep;
        else:                           #标签不为1,修改假阳率
            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)
        ax.plot([cur[0],cur[0]+delX],[cur[1],cur[1]+delY], c=b)
        # cur = (cur[0]-delX,cur[1]-delY)
        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)   #AUC,小矩形面积之和


if __name__ == __main__:
    datArr, labelArr = loadDataSet(horseColicTraining2.txt)
    classifierArr,aggClassEst = adaBoostTrainDS(datArr, labelArr, 50)
    #testArr, testLableArr = loadDataSet(horseColicTest2.txt)
    #prediction = adaClassify(testArr, classifierArr)
    #errArr = np.mat(np.ones((67,1)))
    #errRate = errArr[prediction!= np.mat(testLableArr).T].sum() / 67
    #print(errRate)
    plotROC(aggClassEst.T, labelArr)

结果如下:

    技术分享图片

参考:

《机器学习实战》

《机器学习》周志华

《统计学习方法》

 

机器学习实战笔记-利用adaboost元算法提高分类性能

做重要决定时,大家可能都会考虑吸取多个专家而不只是一个人的意见。机器学习处理问题时又何尝不是如此?这就是元算法(meta-algorithm)背后的思路。元算法是对其他算法进行组合的一种方式7.1基于数据集多重抽样的分类器??... 查看详情

机器学习实战之第七章集成方法(随机森林和adaboost)

第7章集成方法ensemblemethod集成方法:ensemblemethod(元算法:metaalgorithm)概述概念:是对其他算法进行组合的一种形式。通俗来说:当做重要决定时,大家可能都会考虑吸取多个专家而不只是一个人的意见。机器学习处理问题时又何... 查看详情

机器学习(利用adaboost元算法提高分类性能)(代码片段)

元算法背后的思路是对其他算法进行组合的一种方式,Afromnumpyimport*defloadSimpData():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]returndatMat,classLabelsdefloadDataSet(fileName 查看详情

机器学习——adaboost元算法

...他算法进行组合的一种方式,其中最流行的一种算法就是AdaBoost算法。某些人认为AdaBoost是最好的监督学习的方法,所以该方法是机器学习工具箱中最强有力的工具之一。  集成学习或者元算法的一般结构是:先产生一组“个... 查看详情

机器学习算法-adaboost

本章内容组合类似的分类器来提高分类性能应用AdaBoost算法处理非均衡分类问题主题:利用AdaBoost元算法提高分类性能1.基于数据集多重抽样的分类器-AdaBoost长处泛化错误率低,易编码,能够应用在大部分分类器上,无需參数调整... 查看详情

机器学习实战第1章机器学习基础

第1章机器学习基础机器学习概述机器学习就是把无序的数据转换成有用的信息。获取海量的数据从海量数据中获取有用的信息我们会利用计算机来彰显数据背后的真实含义,这才是机器学习的意义。机器学习场景例如:识别动... 查看详情

机器学习实战第13章利用pca来简化数据

第13章利用PCA来简化数据降维技术场景我们正通过电视观看体育比赛,在电视的显示器上有一个球。显示器大概包含了100万像素点,而球则可能是由较少的像素点组成,例如说一千个像素点。人们实时的将显示器上的百万像素转... 查看详情

机器学习实战第2章k-近邻算法(k-nearestneighbor,knn)

第2章k-近邻算法<scripttype="text/javascript"src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=default"></script>KNN概述k-近邻(kNN,k-NearestNeighbor)算法主要是用来进行分类的.KNN场景电影可以按照题材分类,那么如何区分&nbs 查看详情

机器学习实战第11章——使用apriori算法进行关联分析(代码片段)

从大规模数据集中寻找物品间的隐含关系被称作关联分析(associationanalysis)或者关联规则学习(associationrulelearning)。 优点:简单缺点:对大数据集比较慢使用数据类型:数值型或者标称型 一、相关定义:频繁项集:经常出... 查看详情

《机器学习实战》第7章的一处代码错误(代码片段)

---------------------------------------------------------------------------IndexErrorTraceback(mostrecentcalllast)<ipython-input-69-fab03f1fce4e>in<module>()---->1adaboost.buildStump(da 查看详情

java机器学习库smile实战adaboost

1.AdaBoost算法简介      Boost算法系列的起源来自于PACLearnability(PAC可学习性)。这套理论主要研究的是什么时候一个问题是可被学习的,当然也会探讨针对可学习的问题的具体的学习算法。这套理论是由Valiant提出来的,... 查看详情

机器学习实战[machinelearninginaction]

...算法、朴素贝叶斯算法、Logistic回归算法、支持向量机、AdaBoost集成方法、基于树的回归算法和分类回归树(CART)算法等。第三部分则重点介绍无监督学习及其一些主要算法:k均值聚类算法、Apriori算法、FP-Growth算法。第四部分... 查看详情

机器学习实战之第一章机器学习基础

第1章机器学习基础机器学习概述机器学习就是把无序的数据转换成有用的信息。获取海量的数据从海量数据中获取有用的信息我们会利用计算机来彰显数据背后的真实含义,这才是机器学习的意义。机器学习场景例如:识别动... 查看详情

《机器学习实战》学习笔记——k近邻算法

1.numpy中一些函数的用法学习shape()用法:shape :tupleofintsTheelementsoftheshapetuplegivethelengthsofthecorrespondingarraydimensions.。  shape返回一个元组,依次为各维度的长度。shape[0]:第一维长度,shape[1]:第二维长度。  tile()用法:numpy.tile 查看详情

361机器学习常见算法

K-近邻算法(KNearestNeighbors)参考:机器学习实战教程(一):K-近邻算法(史诗级干货长文)决策树算法(DecisionTree)参考:机器学习实战教程(二):决策树基础篇之让我们从相亲说起参考:机器学习实战教程(三):决策树... 查看详情

人脸检测——基于机器学习3adaboost算法

简介主要工作AdaBoost算法的人脸检测算法包含的主要工作:(1)通过积分图快速求得Haar特征;(2)利用AdaBoost算法从大量的特征中选择出判别能力较强的少数特征用于人脸检测分类;(3)提出一个级联结构模型,将若干个弱分... 查看详情

机器学习——提升方法adaboost算法,推导过程

0提升的基本方法  对于分类的问题,给定一个训练样本集,求比较粗糙的分类规则(弱分类器)要比求精确的分类的分类规则(强分类器)容易的多。提升的方法就是从弱分类器算法出发,反复学习,得到一系列弱分类器(... 查看详情

机器学习之adaboost算法原理

...代表算法就是是boosting系列算法。在boosting系列算法中,Adaboost是最著名的算法之一。Adaboost 查看详情