adaboost原理和实现
上两篇说了决策树到集成学习的大概,这节我们通过adaboost来具体了解一下集成学习的简单做法。
集成学习有bagging和boosting两种不同的思路,bagging的代表是随机森林,boosting比较基础的adaboost,高级一点有GBDT,在这里我也说下我理解的这两个做法的核心区别:
随机森林的bagging是采用有放回抽样得到n个训练集,每个训练集都会有重复的样本,每个训练集数据都一样,然后对每个训练集生成一个决策树,这样生成的每个决策树都是利用了整个样本集的一部分,也就说每棵决策树只是学习了大部分,然后决策的时候综合每棵决策树的评分,最终得出一个总的评分
boosting的adaboost每次训练的时候用的是同一个数据集,但是前一棵决策树分错的样本在后面的权重会升高,相当于说,后面的决策树利用了前面决策树学习的结果,不断的优化这个结果,也就是说,后面的决策树恰恰擅长的是前面决策树不擅长(分错)的样本,相当于说,boosting的每棵决策树擅长的“领域”不一样,并且在擅长的领域都很厉害
而对比bagging,bagging中的每一棵树都是同样普通的决策树,相当于每棵决策树擅长的“领域”区分不大,也没有很擅长。
下面我们看下adaboost是如何工作的吧,这次我们使用更简单的例子。
这是二维平面的上的两个点,红色是正样本,绿色是负样本,如果使用强分类器,例如深度大于1的决策树,很简单就可以区分开了,或者使用逻辑回归,计算一下,就可以轻松得到一条直线把这两个类别的点区分开了,我们这里主要是先学习adaboost是如何把弱分类器组装成强大的强分类器以及boosting的学习效果
类别和之前不一样,这里的正负样本的类似是1,-1,原因是预测结果的分界线不一样,决策树是没有对类别做任何的操作,adaboost设计到多棵树的权重相加,使用0作为正负样本的分界线会更好
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
选择弱分类器:深度为1的决策树无疑是很弱的分类器,深度为1的决策树我们一般称为决策树墩,决策树墩在二维平面上是一条平行坐标轴的直线
对于我们的数据集,决策树墩是没有办法正确划分的,除非能学习出直线之间的组合关系
决策树墩做什么事情:决策树墩做的事情是根据特征的特征值给出判断错误的列表(个数)
def stumpClassify(dataMatrix,dimen,threshVal,threshIneq):#just classify the data
retArray = ones((shape(dataMatrix)[0],1))
if threshIneq == 'lt':
retArray[dataMatrix[:,dimen] <= threshVal] = -1.0
else:
retArray[dataMatrix[:,dimen] > threshVal] = -1.0
return retArray
构建决策树墩:设定步伐,遍历所有的特征和步伐(阀值)和方向(大于阀值还是小于阀值),找到最好的特征以及步伐和方向
得到错误率最小的特征,步伐和方向
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
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:
minError = weightedError
bestClasEst = predictedVals.copy()
bestStump['dim'] = i
bestStump['thresh'] = threshVal
bestStump['ineq'] = inequal
return bestStump,minError,bestClasEst
下面是adaboost的核心内容:如何提高划分错的样本的权重
首先用当前划分的错误计算得到一个α值(每个决策树墩的权重),然后对每个样本根据区分对错改变其权重值,最后最改变权重后的样本的权重做归一化
def adaBoostTrainDS(dataArr,classLabels,numIt=40):
weakClassArr = []
m = shape(dataArr)[0]
D = mat(ones((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 = float(0.5*log((1.0-error)/max(error,1e-16)))#计算α值
bestStump['alpha'] = alpha
#print "classEst: ",classEst.T
expon = multiply(-1*alpha*mat(classLabels).T,classEst) #计算新的权重
D = multiply(D,exp(expon)) #权重归一化
D = D/D.sum()
#每个样本到当前的评分
aggClassEst += alpha*classEst
#得到分类错误的列表(分对为零,分错为1,计算内积,得到分错的个数)
aggErrors = multiply(sign(aggClassEst) != mat(classLabels).T,ones((m,1)))
errorRate = aggErrors.sum()/m
print "total error: ",errorRate
bestStump['error_rate']=errorRate
weakClassArr.append(bestStump) #记录每一棵最优的决策树墩
if errorRate == 0.0: break
return weakClassArr,aggClassEst
下面我们看每一棵决策树墩的分类的效果吧:样本类别如下:
[1.0, 1.0, -1.0, -1.0, 1.0]
每个样本的权重如下
[ 0.2 0.2 0.2 0.2 0.2]
第一棵决策树,X1小于等于1.3为负样本,这棵树的权重为0.69,错误率0.2(分错了一个),每个样本被预测的结果如下:
[-0.69314718 0.69314718 -0.69314718 -0.69314718 0.69314718]
第一次权重调整:可以发现第一个样本(被分错的)权重升高了
[ 0.5 0.125 0.125 0.125 0.125]
两棵决策树:第二棵决策树X2小于等于1.0为负样本,权重0.97,错误率还是0.2,样本预测总评分如下
[ 0.27980789 1.66610226 -1.66610226 -1.66610226 -0.27980789]
第二次调整权重,可以看到最后一次被分错的权重最高,前一次被分错的稍小,一直被分对的概率最小
[ 0.28571429 0.07142857 0.07142857 0.07142857 0.5 ]
看下三棵决策树墩的效果:X1小于等于0.9的为负样本,权重0.9,错误率0,所有样本评分如下:可以发现虽然每个正样本的评分都大于0,但是有些评分已经高达2.5了,不过我们也发现,最后的评分跟一直分对或者分错没什么关系
[ 1.17568763 2.56198199 -0.77022252 -0.77022252 0.61607184]
在这个简单的数据中,错误率可以降到0,但是不是所有的数据集都可以达到错误率为0的,比如我们前面的100个点的实验
真正的原因在于数据集在特征维度是否是超平面可分的,如果可以,adaboost理论上可以把错误率降到0
希望到这里大家可以理解adaboost,理解集成学习。
adaboost原理和实现的更多相关文章
- Adaboost原理及目标检测中的应用
Adaboost原理及目标检测中的应用 whowhoha@outlook.com Adaboost原理 Adaboost(AdaptiveBoosting)是一种迭代算法,通过对训练集不断训练弱分类器 ...
- 集成学习之Boosting —— AdaBoost原理
集成学习大致可分为两大类:Bagging和Boosting.Bagging一般使用强学习器,其个体学习器之间不存在强依赖关系,容易并行.Boosting则使用弱分类器,其个体学习器之间存在强依赖关系, ...
- 机器学习之AdaBoost原理与代码实现
AdaBoost原理与代码实现 本文系作者原创,转载请注明出处: https://www.cnblogs.com/further-further-further/p/9642899.html 基本思路 ...
- AdaBoost原理详解
写一点自己理解的AdaBoost,然后再贴上面试过程中被问到的相关问题.按照以下目录展开. 当然,也可以去我的博客上看 Boosting提升算法 AdaBoost 原理理解 实例 算法流程 公式推导 ...
- 机器学习-分类器-Adaboost原理
Adaboost原理 Adaboost(AdaptiveBoosting)是一种迭代算法,通过对训练集不断训练弱分类器,然后把这些弱分类器集合起来,构成强分类器.adaboost算法训练的过程中,初始 ...
- AdaBoost原理,算法实现
前言: 当做重要决定时,大家可能综合考虑多个专家而不是一个人的意见.机器学习处理问题也是如此,这就是元算法背后的思路.元算法是对其他算法进行组合的一种方式,前几天看了一个称作adaboost方法的介绍 ...
- adaboost原理与实践
Adaboost是一种迭代算法,其核心思想是针对同一个训练集训练不同的分类器(弱分类器),然后把这些弱分类器集合起来,构成一个更强的最终分类器(强分类器).其算法本身是通过改变数据分布来实现的,它根据 ...
- Adaboost原理推导
Adaptive Boosting是一种迭代算法.每轮迭代中会在训练集上产生一个新的学习器,然后使用该学习器对所有样本进行预测,以评估每个样本的重要性(Informative).换句话来讲就是,算法会 ...
- Adaboost原理及相关推导
提升思想 一个概念如果存在一个多项式的学习算法能够学习它,并且正确率很高,那么,这个概率是强可学习的.一个概念如果存在一个多项式的学习算法能够学习它,并且学习的正确率仅比随机猜测略好,那么,这个概念是 ...
随机推荐
- Android中解决图像解码导致的OOM问题
Android中解决图像解码导致的OOM问题 原文链接:http://blog.csdn.net/zjl5211314/article/details/7042017
- javascript - 二叉树
都是些简单的东西,所以直接上代码了. /** * Created by huangjacky on 14-10-3. */ function Node(element, left, right) { ...
- Mac OS X Terminal 101:终端使用初级教程
Mac OS X Terminal 101:终端使用初级教程 发表于 2012 年 7 月 29 日 由 Renfei Song | 文章目录 1 为什么要使用命令行/如何开启命令行? 2 初识Com ...
- IIS兼容模式设置
X-UA-Compatible IE=EmulateIE7 来自为知笔记(Wiz)
- 从Tmux 转到GNU Screen
网上很多地方都说Tmux比GNU Screen要好用,不过无意间看到这篇Switching from tmux to GNU Screen之后,我发现GNU Screen的窗口/区域概念更好,至少是更 ...
- Java对象创建阶段的代码调用顺序
在创建阶段系统通过下面的几个步骤来完成对象的创建过程 为对象分配存储空间 开始构造对象 从超类到子类对static成员进行初始化 超类成员变量按顺序初始化,递归调用超类的构造方法 子类成员变量按顺序初 ...
- iOS 自定义滑动切换TabBar
貌似经常会用到,自己整理收藏起来,方便日后查找备用. 效果如图: 由于制作gif,调整了属性,所以看起来的效果不好.如果用默认配置,生成的gif会很大. 制作gif: 1.使用QuickTimePla ...
- 利用VBA查找excel中一行某列第一次不为空与最后一列不为空的列数
昨日同事有需求,想知道每个商品第一次销售的月份,以及最后一次销售的月份. 本想通过什么excel函数来解决,但是找了半天也没找到合适的,最后还是通过VBA来解决吧. 使用方法: Excel工具-宏-V ...
- 说说lambda表达式与表达式树(未完)
Lambda表达式可以转换成为代码(委托)或者数据(表达式树).若将其赋值给委托,则Lambda表达式将转换为IL代码:如果赋值给 Expression<TDelegate>,则构造出一颗 ...
- c++ 状态模式(state)
/************************************************************************/ /* 状态模式 */ /************* ...