机器学习实战笔记(Python实现)-06-AdaBoost
---------------------------------------------------------------------------------------
本系列文章为《机器学习实战》学习笔记,内容整理自书本,网络以及自己的理解,如有错误欢迎指正。
源码在Python3.5上测试均通过,代码及数据 --> https://github.com/Wellat/MLaction
---------------------------------------------------------------------------------------
1、基于数据集多重抽样的分类器
1.1 bagging
自举汇聚法(bootstrap aggregating),也称为bagging方法,是在从原始数据集选择S次后得到S个新数据集的一种技术。新数据集和原数据集的大小相等,每个数据集都是在原始数据集中有放回随机选择样本得到,这意味着新数据集中可以有重复的样本,也可能没有包括原数据集的所有样本。
在S个数据集建好之后,将某个学习算法分别作用于每个数据集就得到了S个分类器。当我们要对新数据进行分类时,就可以应用这S个分类器进行分类。与此同时,选择分类器投票结果中最多的类别作为最后的分类结果。
1.2 boosting
boosting和bagging很类似,他们使用相同类型的分类器,但是在boosting中,不同的分类器是通过串行训练而获得的。Boosting集中关注被已有分类器错分的那些数据来获得新的分类器。
由于boosting分类的结果是基于所有分类器的加权求和的结果,所以在boosting中分类器的权重并不相等,每个权重代表的是其对于分类器在上一轮迭代中的成功度。
Boosting方法有多个版本,本节只关注其中一个最流行的版本AdaBoost。
1.3 AdaBoost
AdaBoost是adaptive boosting(自适应boosting)的缩写,它的理论根植于使用弱分离器和多个实例来构建一个强分类器。这里的“弱”意味着分类器的性能比随机猜测要略好,但是也不会好太多;而“强”分类器的错误率将会低很多。
其运行过程如下:训练数据中的每个样本,并赋予其一个权重,这些权重构成了向量D。一开始,这些权重都初始化成相等值。首先在训练数据上训练出一个弱分类器并计算该分类器的错误率,然后在同一数据集上再次训练弱分类器。在分类器的第二次训练当中,将会重新调整每个样本的权重,其中第一次分对的样本的权重将会降低,而第一次分错的样本的权重将会提高。为了从所有弱分类器中得到最终的分类结果,AdaBoost为每个分类器都分配了一个权重值alpha,这些alpha值是基于每个弱分类器的错误率进行计算的。其中,错误率ε的定义为:
而alpha的计算公式为:
AdaBoost算法流程如下图:
计算出alpha值之后,可以对权重向量D进行更新,以使得那些正确分类的样本的权重降低而错分样本的权重升高。
如果某个样本被正确分类,权重更改为:
而如果被错分,权重则更改为:
在计算出D之后,AdaBoost又开始进入下一轮迭代,知道训练错误率为0或者弱分类器的数目达到用户指定值为止。
2、AdaBoost算法的实现
2.1 构建弱分类器
单层决策树是AdaBoost中最流行的弱分类器。
算法伪代码↓
def buildStump(dataArr,classLabels,D):
'''
建立一个单层决策树
输人为权重向量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
weightedError = D.T*errArr #计算加权错误率
#print("split: dim %d, thresh %.2f, thresh ineqal: %s, the weighted error is %.3f" % (i, threshVal, inequal, weightedError))
#如果错误率低于minError,则将当前单层决策树设为最佳单层决策树
if weightedError < minError:
minError = weightedError
bestClasEst = predictedVals.copy()
bestStump['dim'] = i
bestStump['thresh'] = threshVal
bestStump['ineq'] = inequal
return bestStump,minError,bestClasEst def stumpClassify(dataMatrix,dimen,threshVal,threshIneq):
'''
通过阈值比较对数据进行分类
'''
retArray = ones((shape(dataMatrix)[0],1))
if threshIneq == 'lt':
retArray[dataMatrix[:,dimen] <= threshVal] = -1.0
else:
retArray[dataMatrix[:,dimen] > threshVal] = -1.0
return retArray
2.2 基于单层决策树的AdaBoost训练过程
算法伪代码↓
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 adaBoostTrainDS(dataArr,classLabels,numIt=40):
'''
基于单层决策树的AdaBoost训练过程
'''
weakClassArr = []
m = shape(dataArr)[0]
D = mat(ones((m,1))/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,此处分母用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
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
2.3 简单测试分类效果
def adaClassify(datToClass,classifierArr):
'''
利用训练出的多个弱分类器进行分类
datToClass:待分类数据
classifierArr:训练的结果
'''
dataMatrix = mat(datToClass)
m = shape(dataMatrix)[0]
aggClassEst = mat(zeros((m,1)))
#遍历classifierArr中的所有弱分类器,并基于stumpClassify对每个分类器得到一个类别的估计值
for i in range(len(classifierArr)):
classEst = stumpClassify(dataMatrix,classifierArr[i]['dim'],\
classifierArr[i]['thresh'],\
classifierArr[i]['ineq'])
aggClassEst += classifierArr[i]['alpha']*classEst
print(aggClassEst)
return sign(aggClassEst)
按如下指令测试:
3、实例:在马疝病数据集上应用AdaBoost分类器
前面一个章节中曾利用Logistic回归来预测患有疝病的马是否能够存活,而在本节我们将利用多个单层决策树和AdaBoost来预测。
def loadDataSet(fileName):
'''读取数据函数'''
numFeat = len(open(fileName).readline().split('\t')) #获取列数,默认最后一列为类标签且类标签为+1和-1
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 if __name__ == "__main__": '''马疝病测试'''
#导入训练数据
datArr,labelArr = loadDataSet('horseColicTraining2.txt')
weakClassArr,aggClassEst = adaBoostTrainDS(datArr,labelArr,10)
#导入测试数据
testArr,testLabelArr = loadDataSet('horseColicTest2.txt')
prediction = adaClassify(testArr,weakClassArr)
#计算错误率
errArr = mat(ones((67,1)))
errArr[prediction != mat(testLabelArr).T].sum()/67
将弱分类器的数目设定为1到10000之间的几个不同数字,并运行上述过程。得到如下结果
在同一数据集上采用Logistic回归得到的平均错误率为0.35,而使用AdaBoost方法,从表中可以看出,仅仅使用50个弱分类器就达到了较高的性能。
THE END.
机器学习实战笔记(Python实现)-06-AdaBoost的更多相关文章
- 机器学习实战笔记(Python实现)-08-线性回归
--------------------------------------------------------------------------------------- 本系列文章为<机器 ...
- 机器学习实战笔记(Python实现)-05-支持向量机(SVM)
--------------------------------------------------------------------------------------- 本系列文章为<机器 ...
- 机器学习实战笔记(Python实现)-04-Logistic回归
--------------------------------------------------------------------------------------- 本系列文章为<机器 ...
- 机器学习实战笔记(Python实现)-03-朴素贝叶斯
--------------------------------------------------------------------------------------- 本系列文章为<机器 ...
- 机器学习实战笔记(Python实现)-01-K近邻算法(KNN)
--------------------------------------------------------------------------------------- 本系列文章为<机器 ...
- 机器学习实战笔记(Python实现)-02-决策树
--------------------------------------------------------------------------------------- 本系列文章为<机器 ...
- 机器学习实战笔记(Python实现)-00-readme
近期学习机器学习,找到一本不错的教材<机器学习实战>.特此做这份学习笔记,以供日后翻阅. 机器学习算法分为有监督学习和无监督学习.这本书前两部分介绍的是有监督学习,第三部分介绍的是无监督学 ...
- 机器学习实战笔记(Python实现)-09-树回归
---------------------------------------------------------------------------------------- 本系列文章为<机 ...
- 机器学习实战笔记(Python实现)-07-模型评估与分类性能度量
1.经验误差与过拟合 通常我们把分类错误的样本数占样本总数的比例称为“错误率”(error rate),即如果在m个样本中有a个样本分类错误,则错误率E=a/m:相应的,1-a/m称为“精度”(acc ...
随机推荐
- C++ std::array
std::array template < class T, size_t N > class array; Code Example #include <iostream> ...
- Android开发学习之路-使用annotationProcessor配置Butterknife
Apt工具的作者宣布了不再维护该工具了,而且Android Studio也有了自己的插件,并且可以通过gradle来简单的配置. 其实用Butterknife的都知道,没有apt,onClick绑定不 ...
- Android开发学习之路-Git的极简教程?
Git是一个代码版本管理工具,也就是允许我们的一个项目拥有多个版本,这样我们可以随心所欲的修改我们的代码,如果出现问题,可以回退到某一个提交点.如果你还在用一堆堆注释来更新你的代码,那么可以尝试一下G ...
- Android笔记——Application的作用
一.Application是什么 Application和Actovotu,Service一样是android框架的一个系统组件,当android程序启动时系统会创建一个 application对象, ...
- 大数据时代下的SQL Server第三方负载均衡方案----Moebius测试
一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 架构原理(Architecture) 测试环境(Environment) 安装Moebius( ...
- JavaScript权威设计--JavaScript对象(简要学习笔记七)
1.with语句 语法: width(object){ statement } with语句可用于临时扩展作用域链.作用域链可以按序检索的对象列表,通过它可以进行变量名解析. with将object添 ...
- 前端学HTTP之连接管理
前面的话 HTTP连接是HTTP报文传输的关键通道.要掌握HTTP就需要理解HTTP连接的来龙去脉以及如何使用这些连接 如果想查看一个网页,浏览器收到URL时,会执行下图所示的步骤.将服务器的IP地址 ...
- 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(15)-权限管理系统准备
系列目录 这节我们说下权限系统的特点,本系统采用的是MVC4+EF5+IOC 接口编程的架构,其中的权限树用的是DWTree,功能上做到灵活,授权操控细致,权限可以细到按钮级别 ,为了部署简单,导致设 ...
- Apworks框架实战(六):使用基于Entity Framework的仓储基础结构
在前面的章节中,我们已经设计了一个简单的领域模型,接下来我们希望能够实现领域模型的持久化及查询.在Apworks中,实现了面向Entity Framework.NHibernate以及MongoDB的 ...
- 本博客现已迁移到chuxiuhong.com
欢迎大家访问,我会暂时保留这个博客的更新,实现两个博客的同步. 新博客地址: http://chuxiuhong.com