上两篇说了决策树到集成学习的大概,这节我们通过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原理和实现的更多相关文章

  1. Adaboost原理及目标检测中的应用

    Adaboost原理及目标检测中的应用 whowhoha@outlook.com Adaboost原理 Adaboost(AdaptiveBoosting)是一种迭代算法,通过对训练集不断训练弱分类器 ...

  2. 集成学习之Boosting —— AdaBoost原理

    集成学习大致可分为两大类:Bagging和Boosting.Bagging一般使用强学习器,其个体学习器之间不存在强依赖关系,容易并行.Boosting则使用弱分类器,其个体学习器之间存在强依赖关系, ...

  3. 机器学习之AdaBoost原理与代码实现

    AdaBoost原理与代码实现 本文系作者原创,转载请注明出处: https://www.cnblogs.com/further-further-further/p/9642899.html 基本思路 ...

  4. AdaBoost原理详解

    写一点自己理解的AdaBoost,然后再贴上面试过程中被问到的相关问题.按照以下目录展开. 当然,也可以去我的博客上看 Boosting提升算法 AdaBoost 原理理解 实例 算法流程 公式推导 ...

  5. 机器学习-分类器-Adaboost原理

    Adaboost原理 Adaboost(AdaptiveBoosting)是一种迭代算法,通过对训练集不断训练弱分类器,然后把这些弱分类器集合起来,构成强分类器.adaboost算法训练的过程中,初始 ...

  6. AdaBoost原理,算法实现

    前言: 当做重要决定时,大家可能综合考虑多个专家而不是一个人的意见.机器学习处理问题也是如此,这就是元算法背后的思路.元算法是对其他算法进行组合的一种方式,前几天看了一个称作adaboost方法的介绍 ...

  7. adaboost原理与实践

    Adaboost是一种迭代算法,其核心思想是针对同一个训练集训练不同的分类器(弱分类器),然后把这些弱分类器集合起来,构成一个更强的最终分类器(强分类器).其算法本身是通过改变数据分布来实现的,它根据 ...

  8. Adaboost原理推导

    Adaptive Boosting是一种迭代算法.每轮迭代中会在训练集上产生一个新的学习器,然后使用该学习器对所有样本进行预测,以评估每个样本的重要性(Informative).换句话来讲就是,算法会 ...

  9. Adaboost原理及相关推导

    提升思想 一个概念如果存在一个多项式的学习算法能够学习它,并且正确率很高,那么,这个概率是强可学习的.一个概念如果存在一个多项式的学习算法能够学习它,并且学习的正确率仅比随机猜测略好,那么,这个概念是 ...

随机推荐

  1. Ceph monitor故障恢复探讨

    1 问题 一般来说,在实际运行中,ceph monitor的个数是2n+1(n>=0)个,在线上至少3个,只要正常的节点数>=n+1,ceph的paxos算法能保证系统的正常运行.所以,对 ...

  2. SSD性能对比

    SSD性能测试顺序写 16k iops 85061.08顺序写 8k iops 146250.93顺序写 4k iops 239816.69顺序写 2k iops 294540.87顺序写 1k io ...

  3. Java关键字--static

    在Java中,将关键字static分为三部分进行讨论,分别为Java静态变量.Java静态方法.Java静态类 Java Static Variables Java instance variable ...

  4. delphi使用outputdebugstring调试程序和写系统日志

    delphi使用outputdebugstring调试程序和写系统日志 procedure TForm1.btn1Click(Sender: TObject); begin OutputDebugSt ...

  5. WPF 模板

    一.DataTemplate(数据模板)1.引用命名空间xmlns:别名="clr-namespace:命名空间" 2.调用命名空间下的类别和属性<Window.Resour ...

  6. C# HttpWebRequest 绝技 根据URL地址获取网页信息

    如果要使用中间的方法的话,可以访问我的帮助类完全免费开源:C# HttpHelper,帮助类,真正的Httprequest请求时无视编码,无视证书,无视Cookie,网页抓取 1.第一招,根据URL地 ...

  7. 【android原生态RPG游戏框架源码】

    转载请注明原创地址:http://www.cnblogs.com/zisou/p/android-RPG.html 这份源码是在今年6月份写的,当时公司有一个技术部们的学习讨论的讲座,然后我自己就写了 ...

  8. Cocos2d-JS项目之一:环境(IDE 运行js-tests、IDE 和 studio 统一工程)

    环境:cocos 引擎(包括 studio)2.2.1 for Mac.cocos2d-js-v3.5.Cocos Code IDE 1.2 for Mac,cocos 引擎指的是下面这个东西: 各种 ...

  9. 使用before、after伪类制作三角形

    使用before.after伪类实现三角形的制作,不需要再为三角形增加不必要的DOM元素,影响阅读. <!DOCTYPE html><html><head>    ...

  10. getRequestURI,getRequestURL的区别

    转自:http://www.cnblogs.com/JemBai/archive/2010/11/10/1873764.html test1.jsp======================= &l ...