目录

引言

一、 基于数据集多重抽样的分类器

1.1 bagging:基于数据随机重抽样的分类器构建方法

1.2 boosting

二、 训练算法

三、基于单层决策树构建弱分类器

四、完整AdaBoost算法的实现

五、测试算法:基于AdaBoost的分类

六、在一个难数据集上应用AdaBoost

七、非均衡分类问题

7.1 其他分类性能度量指标:正确率、召回率及ROC曲线

引言

元算法是对其他算法进行组合的一种方式。AdaBoost是最流行的元算法。这一章学习讨论boosting方法及其代表分类器AdaBoost,建立单层决策树分类器。AdaBoost算法将应用在上述单层决策树分类器之上。

一、 基于数据集多重抽样的分类器

先前学习了KNN、决策树、朴素贝叶斯、logistic回归、支持向量机五种不同的分类算法,它们都拥有各自的优缺点。将不同的分类器组合起来的结果就称为是集成方法亦或者称为元算法。集成方法会有很多不同的形式,可以是不同算法的集成,也可以是同一个算法在不同设置下的集成,还可以是数据集不同部分分配给不同分类器之后的集成。

AdaBoost算法的优缺点:

优点:泛化错误率降低,易编码,可以应用在大部分分类器上,无参数调整

缺点:对离群点敏感

适用数据类型: 数值型和标称型数据

1.1 bagging:基于数据随机重抽样的分类器构建方法

自举汇聚法即bagging法是在原始数据集选择S次后得到S个新数据集的一种技术新数据集和原数据集大小相等,每个数据集都是通过在原始数据集中随机选择一个样本来进行可替换而得到的。这里的替换就意味着可以多次选择同一个样本。这一个性质允许新数据集中可以有重复的值存在,而原本的数据集的某些值就不存在了。

建立好S个数据集后,将学习算法分别作用于每个数据集就得到了S个分类器。当对新数据进行分类是,可以应用S个分类器进行分类,选择分类器投票结果中得票数最多的类别作为分类结果。

1.2 boosting

boosting是一种与bagging很类似的技术。不论是在boosting还是在bagging中,所使用的多个分类器类型是一致的,前者的不同分类器是通过串行训练得到的,每个新分类器都根据已训练出的分类器的性能来进行训练。而boosting通过集中关注被已有分类器错分的那些数据来获得新的分类器。

bagging中分类器的权重是相等的,boosting中的分类器权重并不相等,每个权重代表的是其对应分类器在上一轮迭代中的成功度。

AdaBoosting的一般流程

1、收集数据:可以使用任意方法

2、准备数据:依赖于所使用的弱分类器类型,这里使用的是单层决策树,该分类器可以处理任何类型数据。也可以使用任意分类器作为弱分类器。

3、分析数据:可以使用任意方法

4、训练算法:AdaBoost的大部分时间都用在训练上,分类器将多次在同一个数据集上训练弱分类器

5、测试算法:计算分类的错误率

6、使用算法:同SVM一样,AdaBoost预测两个类别中的一个,将它应用到多个类别的场合,就要像多类SVM中的做法一样对AdaBoost进行修改。

二、 训练算法

AdaBoost的运行过程如下:训练数据中的每个样本,并赋予其一个权重,权重构成向量D。将这些权重都初始化成相等值。先在训练数据上训练一个弱分类器并计算该分类器的错误率,然后再同一数据集上再次训练弱分类器。再分类器的第二次训练中,将会重新调整每个样本的权重,其中第一次分对的样本的权重将会降低,第一次错误分的权重将会提高。

将错误率定义为:

alpha的计算公式为:

AdaBoost算法流程如下图:

图1  AdaBoost算法的示意图

计算除alpha值后,对权重向量D进行更新,使得正确分类权重降低错误分类权重升高。D的计算方法如下:

某个样本的被正确分类,那么该样本的权重更改为:

如果是某个样本被错分,该样本的权重更改为:

在计算出D之后,AdaBoost就开始进入下一轮迭代。AdaBoost算法会不断的重复训练和调整权重的过程,直到训练错误率达到0或弱分类器的数目达到用户的指定值为止。

三、基于单层决策树构建弱分类器

单层决策树是一种简单的决策树。构建AdaBoost代码时首先需要通过一个简单数据集来确保在算法实现上一切就绪。创建adaboost.py的新文件加入代码:

def loadSimpData():datMat = matrix([[1.0, 2.1],  # 构建矩阵[2.0, 1.1],[1.3, 1.0],[1.0, 1.0],[2.0, 1.0]])classLabels = [1.0, 1.0, -1.0, -1.0, 1.0]return datMat, classLabels

这里是创建数据集,将矩阵中的数据呈现在坐标系中:

import adaboost
from numpy import *
import matplotlib.pyplot as pltdataMat, classLabels = adaboost.loadSimpData()fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(array(dataMat[:, 0]), array(dataMat[:, 1]).tolist())
plt.show()

图1  简单数据

建立单层决策数,令第一个函数用于测试是否有某个值小于或者大于我们正在测试的阈值。第二函数在一个加权数据集中集中循环,并找到具有最低错误率的单层决策树。

# 单层决策树分类函数
def stumpClassify(dataMatrix, dimen, threshVal, threshIneq):retArray = ones((shape(dataMatrix)[0], 1))         # 创建以dataMatrix的行数为行,1为列的1矩阵if threshIneq == 'lt':retArray[dataMatrix[:, dimen] <= threshVal] = -1.0   # 如果小于阈值,则赋值为-1else:retArray[dataMatrix[:, dimen] > threshVal] = -1.0    # 如果大于阈值,则赋值为-1return retArray# 找到数据集上最佳的单层决策树
def buildStump(dataArr, classLabels, D):dataMatrix = mat(dataArr); labelMat = mat(classLabels).Tm, n = shape(dataMatrix)numSteps = 10.0; bestStump = {}; bestClasEst = mat(zeros((m, 1)))  minError = float('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']:                # 大于和小于的情况,均遍历。lt:less than,gt:greater thanthreshVal = (rangeMin + float(j) * stepSize)                    # 计算阈值predictedVals = stumpClassify(dataMatrix, i, threshVal, inequal)  # 计算分类结果errArr = np.mat(np.ones((m,1)))                                 # 初始化误差矩阵errArr[predictedVals == labelMat] = 0                           # 分类正确的,赋值为0weightedError = D.T * errArr                                    # 计算误差print("split: dim %d, thresh %.2f, thresh ineqal: %s, the weighted error is %.3f" % (i, threshVal, inequal, weightedError))if weightedError < minError:               # 找到误差最小的分类方式minError = weightedErrorbestClasEst = predictedVals.copy()bestStump['dim'] = ibestStump['thresh'] = threshValbestStump['ineq'] = inequalreturn bestStump, minError, bestClasEst

三层嵌套的for循环是程序中最主要的部分,第一层for循环在数据集的所有特征上遍历。通过计算最小值和最大值来了解应该需要多大的步长。第二层的for循环再这些值上遍历。甚至将阈值设置为整个取值范围之外也是可以的。最后一个for循环则是再大于和小于之间切换不等式。嵌套的三层for循环之内,在数据集及三个循环变量上调用stumpClassify()函数,基于这些循环变量,函数会返回分类预测结果。errArr的作用为:当predictedVals中的值不等于labelMat中的真正类别标签值,errArr的相应位置为1。

了解实际运行过程:

dataMat, classLabels = adaboost.loadSimpData()
D = mat(ones((5, 1)) / 5)
bestStump,minError,bestClasEst = adaboost.buildStump(dataMat,classLabels,D)
print('bestStump:\n', bestStump)
print('minError:', minError)
print('bestClasEst:\n', bestClasEst)

四、完整AdaBoost算法的实现

刚才创建了一个基于加权输入值进行决策的分类器。现在实现一个完整的AdaBoost算法就拥有了所有需要的所有信息。

实现的伪代码为:

对每次迭代:

利用buildStump()函数找到最佳的单层决策树

将最佳单层决策树加入到单层决策树数组

计算alpha

计算新的权重向量D

更新累计类别估计值

如果错误率等于0.0,退出循环

代码如下:

# 迭代次数为numIt次或者知道训练错误率为0为止
def adaBoostTrainDS(dataArr, classLabels, numIt = 40):  # 设置迭代次数为40次weakClassArr = []m = shape(dataArr)[0]  # m为dataArr的行数值D = mat(np.ones((m, 1)) / m)  # 包含每个数据点的权重 一开始所有权重为1/maggClassEst = mat(zeros((m, 1)))  # 记录每个数据点的类别估计累计值for i in range(numIt):bestStump, error, classEst = buildStump(dataArr, classLabels, D)  # 获得字典、错误率、类别估计值print("D:", D.T)  # 输出Dalpha = float(0.5 * log((1.0-error) / max(error, 1e-16)))  # 确保没有错误时不会发生除零溢出bestStump['alpha'] = alpha   # alpha值加入到bestStump字典中weakClassArr.append(bestStump)  # 字典又添加到列表中,字典包括了分类所需要的所有信息print("classEst:", classEst.T)expon = multiply(-1*alpha*np.mat(classLabels).T, classEst)D = multiply(D, exp(expon))D = D / D.sum()  # 计算新权重aggClassEst += alpha*classEstprint("aggClassEst:", aggClassEst.T)aggErrors = multiply(sign(aggClassEst) != mat(classLabels).T, ones((m,1)))# sign()得到二值分类结果errorRate = aggErrors.sum()/m  # 误差值print("total error:", errorRate, "\n")if errorRate == 0.0: breakreturn weakClassArr

结果为:

dataMat, classLabels = adaboost.loadSimpData()
weakClassArr, aggClassEst = adaboost.adaBoostTrainDS(dataMat, classLabels)
print(weakClassArr)
print(aggClassEst)

五、测试算法:基于AdaBoost的分类

拥有多个弱分类器以及其对应的alpha值,进行测试就很容易了,将弱训练器的训练过程从程序中抽离出来,应用到具体实例上,每个弱分类器的结果以其对应的alpha值作为权重。所有这些弱分类器的结果加权求和就得到了最后的结果。

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'])aggClassEst += classifierArr[i]['alpha'] * classEstprint(aggClassEst)return sign(aggClassEst)

adaClassify()函数是利用训练出的弱分类器进行分类的函数,函数的输入是由一个或多个待分类样例datToClass以及多个弱分类器组成的数组classifierArr.函数adaClassify()首先将dtToClass转换成了一个Numpy矩阵,并得到datToClass中待分类样例的个数m。构建一个0列向量aggClassEst,这个列向量与adaBoostTrainDS()含义一致。

遍历classifierArr中所有弱分类器,并基于stumpClassify()对每个分类器得到一个类别的估计值,输出的类别估计值乘上该单层决策树的alpha权重然后累加到aggClassEstshang。

当没有弱分类器数组是,可以输入:

dataArr, labelArr = adaboost.loadSimpData()
classifierArr = adaboost.adaBoostTrainDS(dataArr, labelArr, 30)
adaboost.adaClassify([0, 0], classifierArr)

输出结果为:

六、在一个难数据集上应用AdaBoost

添加自适应数据加载函数:

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
dataArr, labelArr = adaboost.loadDataSet('D:\\learning\\horseColicTraining2.txt')
classifierArray = adaboost.adaBoostTrainDS(dataArr, labelArr, 10)print(classifierArray)

结果为:

表1  不同弱分类器数目情况下的AdaBoost测试和分类错误率

七、非均衡分类问题

7.1 其他分类性能度量指标:正确率、召回率及ROC曲线

错误率指的是在所有测试样例中错分的样例比例,实际上这样的错误掩盖了样例是如何被错分的事实,机器学习中存在一个普遍适用的混淆矩阵,可以帮助了解分类中的错误。

表2  一个三类问题的混淆矩阵

当矩阵中的非对角元素均为0,就会得到一个完美的分类器。当面的二类问题时混淆矩阵可以表示为:

表3  二类问题的混淆矩阵,输出采用不同的类别标签

当某个类别的重要性高于其他类别时,可以利用上述定义来定义出多个比错误率更好的新指标。第一个指标是正确率,给出的预测为正例样本中真正正例的比例,第二个指标是召回率给出的是预测为正例的真实正例的比例。在召回率很大的分类器中,真正判错的正例数目并不多。

ROC曲线是另一个用于度量分类中的非均衡性的工具,代表接收者操作特征。

图2  利用10个单层决策树的AdaBoost马疝病检测系统的ROC曲线

ROC曲线不但可以用于比较分类器,还可以基于成本效益分析来做出决策。在不同的阈值下不同的分类器的表现情况可能各不相同。

ROC曲线的绘制以及AUC计算函数:

def plotROC(predStrengths, classLabels):cur = (1.0, 1.0)  # 绘制光标的位置ySum = 0.0  # 用于计算AUCnumPosClas = np.sum(np.array(classLabels) == 1.0)  # 统计正类的数量yStep = 1 / float(numPosClas)  # y轴步长xStep = 1 / float(len(classLabels) - numPosClas)  # x轴步长sortedIndicies = predStrengths.argsort()  # 预测强度排序fig = plt.figure()fig.clf()  # 清除所有轴ax = plt.subplot(111)# 每得到一个标签为1.0的类,则要沿着y轴的方向下降一个步长,即不断降低真阳率# 类似的对其他类别的标签,则是在x轴方向上到退了一个步长for index in sortedIndicies.tolist()[0]:  # 转换成列表if classLabels[index] == 1.0:delX = 0;delY = yStepelse:delX = xStep;delY = 0ySum += cur[1]  # 高度累加ax.plot([cur[0], cur[0] - delX], [cur[1], cur[1] - delY], c='b')  # 绘制ROCcur = (cur[0] - delX, cur[1] - delY)  # 更新绘制光标的位置ax.plot([0, 1], [0, 1], 'b--')plt.title('ROC curve for adaboost horse colic detection system')plt.xlabel('false positive rate',)plt.ylabel('true positive rate')ax.axis([0, 1, 0, 1])print('AUC面积为:', ySum * xStep)  # y轴的矩形高度乘xStep得到AUC面积plt.show()

这里需要将adaboostTrainDS()的返回值改为:

    return weakClassArr, aggClassEst

结果图为:

图3  输出结果

机器学习第七章笔记——利用AdaBoost元算法提高分类性能相关推荐

  1. 《机器学习实战》学习笔记(七):利用AdaBoost 元算法提高分类性能

    欢迎关注WX公众号:[程序员管小亮] [机器学习]<机器学习实战>读书笔记及代码 总目录 https://blog.csdn.net/TeFuirnever/article/details ...

  2. 机器学习算法——利用AdaBoost元算法提高分类性能(基于单层决策树构建的弱分类器)

    当做出重要决定时,我们往往会听取多个专家而不只是一个人的意见.元算法正是采用这种思路,元算法是对其他算法进行组合的一种方式,本篇博文主要介绍AdaBoost元算法,该算法是机器学习工具箱中最强有力的工 ...

  3. 机器学习实战 -- 利用AdaBoost 元算法提高分类性能

    组合相似的分类器来提高分类性能 应用AdaBoost算法 处理非均衡分类问题 元算法是对其他算法进行组合的一种方式. 基于数据集多重抽样的分类器 我们可以将不同的分类器组合起来,而这种组合结果被称为集 ...

  4. python机器学习实战6:利用adaBoost元算法提高分类性能

    1.adaBoost元算法简介 在之前我们LZ介绍了不同的分类器,如果我们根据实际的要求对这些分类器进行组合,这种组合的结果则被称为集成算法(ensemble method)或者元算法(meta-me ...

  5. 利用AdaBoost元算法提高分类性能

    本篇博文涵盖如下内容: 组合相似的分类器来提高分类性能 应用AdaBoost算法 处理非均衡分类问题 元算法(meta-algorithm): 对其他算法进行组合的一种方式. 最为流行的元算法: Ad ...

  6. 《机器学习实战》chapter 07利用AdaBoosting元算法提高分类性能

    第一部分:集成方法介绍 集成方法通过组合多个分类器的分类结果,获得了比简单分类器更好的分类结果 1.bagging,通过随机抽样的替换方式,得到了与原始数据集规模一样的数据集. 在S个数据集建好以后, ...

  7. 机器学习实践之集成方法(随机森林和AdaBoost元算法提高分类性能)

       本文根据最近学习机器学习书籍网络文章的情况,特将一些学习思路做了归纳整理,详情如下.如有不当之处,请各位大拿多多指点,在此谢过. (未添加文章标签,特此补上,2018.1.14记.) 一.概述 ...

  8. 使用 AdaBoost 元算法提高分类器性能

    转自穆晨 阅读目录 前言 一种原始的元算法 - bagging (自举汇聚法) boost (提高任意给定学习算法精确度算法) vs bagging (自举汇聚法) AdaBoost 元算法的基本原理 ...

  9. 第七章:集成学习(利用AdaBoost元算法...)

    ---恢复内容开始--- 集成学习其实不能算一个算法,应该算是一种框架,集百家之长.集成算法具体有Bagging与Boosting两种大类.两者区别: 1)Bagging是并行的,它就好比找男朋友,美 ...

最新文章

  1. 换了路由器电脑都连不上网了_技术丨电脑连不上网,我要如何冲浪?
  2. java 中文问号问题_解决java中的中文乱码问题(ZT)
  3. cookie的相关知识
  4. python爬虫提取a标签_Python爬虫 Pyppeteer获取a标签的文本和链接
  5. 百练OJ:1017:装箱问题
  6. kettle 空字符串 null问题解决
  7. java 高级编程进阶_JAVA高级编程之hibernate进阶学习
  8. jl计算机二级c语言考什么,计算机等级考试二级C语言考前密卷(9)2
  9. GraphChi: Large-Scale Graph Computation on Just a PC
  10. 巩固——Vue中如何使用less和scss?
  11. CentOS7 (精简操作指令)
  12. 供应链拼图:拼合未来的全球经济
  13. c盘满了怎么清理垃圾而不误删?教你瞬间多出20个G
  14. 五险一金 ,即将毕业的每个人都看看吧
  15. this的三种用法 详解
  16. 【APICloud系列|34】上架华为应用市场缺少免责函?
  17. IE浏览器无法添加进信任站点和受限站点,添加后被还原
  18. Springboot拦截器实现IP黑名单
  19. python写入指定的excel_python 写入Excel
  20. 操作系统存储管理实验课程设计报告

热门文章

  1. 解决微信公众号文章的防盗链
  2. 区块链技术让传统旅游业焕发新机
  3. 使用python 批量将 HEIC格式图片转换成JPG或者PNG格式的图片
  4. 粤教版高中信息技术必修一《数据与计算》第一章:python编程作ASCII编码excel表
  5. IT行业8大发展趋势
  6. 虚拟化服务器虚拟出的gpu的驱动,微软虚拟机显卡及驱动的设置
  7. sql server导入mdf与ldf文件
  8. 无线网络用友服务器,用友T3网络与服务器要如何连接?用友T3网络与服务器要...
  9. win10控制面板快捷键_常用的几个win10使用小窍门
  10. Android P WiFi自动连接评分机制