当做重要决定时,我们可能会考虑吸取多个专家而不只是一个人的意见。机器学习处理问题也是这样,这就是元算法(meta-algorithm)背后的思路。

  元算法对其他算法进行组合的一种方式,其中最流行的一种算法就是AdaBoost算法某些人认为AdaBoost是最好的监督学习的方法,所以该方法是机器学习工具箱中最强有力的工具之一。

  集成学习或者元算法的一般结构是:先产生一组“个体学习器”,再用某种策略将他们结合起来。个体学习器通常是由一个现有的学习算法从训练数据产生。

  根据个体学习器的生成方式,目前的集成学习方法大致可分为两大类,即

  1.个体学习器间存在强依赖关系、必须串行生成的序列化方法,典型的代表是Boosting,其中AdaBoost就是Boosting的最流行的一个版本

  2.个体学习器间不存在强依赖关系、可同时生成的并行化方法,典型的代表是Bagging和“随机森林”(Random Forest)

AdaBoost

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

缺点:对离群点敏感

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

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

自举汇聚法(bootstrap aggregating),也称为bagging方法,它直接基于自助采样法(bootstrap samping)。

给定包含m个样本的数据集,我们先随机取出一个样本放入采样集中,再把该样本放回初始数据集,使得下次采样时该样本仍有可能被选中,这样,经过m次随机采样操作,我们得到了含m个样本的采样集。这样从原始数据集选择T次后得到T个新数据集,且每个新数据集的大小和原数据集的大小相等。在T个新数据集建好之后,将某个学习算法分别作用于每个数据集就得到了T个分类器。当我们要对新数据集进行分类时,就可以应用这T个分类器进行分类。与此同时,选择分类器投票结果中最多的类别作为最后的分类结果(权重相等)。

Boosting

boosting是一种和bagging很类似的技术。其使用的多个分类器的类型都是一致的。

在boosting中,不同的分类器是通过串行训练而获得的,每个新分类器都根据已训练出的分类器的性能来进行训练。boosting是通过集中关注被已有分类器错分的那些数据来获得新的分类器。

boosting分类的结果是基于所有分类器的加权求和结果的,在bagging中的分类器权重是相等的,而boosting中的分类器权重并不相等,每个权重代表的是其对应分类器在上一轮迭代中的成功度。

现在介绍其中的AdaBoost

弱分类器的“弱”意味着分类器的性能比随机猜测要略好,但是也不会好太多。这就是说,在二分类情况下,弱分类器的错误率会高于50%,而强分类器的错误率会低很多。

AdaBoostadaptive boosting(自适应boosting)的缩写,其运行过程如下:

假设一个二类分类的训练数据集

<1>训练数据中的每个样本,并赋予其一个权重,这些权重构成了初始向量D。一开始,这些权重都初始化成相等值。

AdaBoost算法多种推导方式,比较容易理解的是基于“加性模型”,即基学习器的线性组合

  ,其中 为基学习器, 为系数

来最小化指数损失函数(exponential loss function),损失函数见 机器学习-损失函数 (转)

   ,其中f(x)是正确的分类,等于-1或者1,H(x)是分类器的分类结果,等于-1或者1

  

            

,所以对该式子求的偏导,得 ,并令其等于0,得

   

<2>首先在训练分类器上训练出一个弱分类器并计算该分类的错误率,然后在同一数据集上再次训练弱分类器。

在分类器的第二次训练中,将会重新调整每个样本的权重,其中第一次分对的样本的权重将会降低,而第一次分错的样本的权重将会提高。为了从所有弱分类器中得到最终的分类结果,AdaBoost为每个分类器都分配了一个权重值alpha,这些alpha值是基于每个弱分类器的错误率进行计算的。

其中,错误率 的定义为

  = 为正确分类的样本数目/所有样本数目

alpha的计算公式如下:

  

计算出alpha值之后,可以对权重向量D进行更新,以使得那些正确分类的样本的权重降低而错分样本的权重升高。D的计算方法如下:

   

其中,规范化因子

  

它使得成为一个概率分布

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

  

如果某个样本被错误分类,那么该样本的权重更改为

  

在计算出D之后,AdaBoost算法又开始进入下一轮迭代

AdaBoost算法会不断地重复训练和调整权重的过程,直到训练错误率为0或者弱分类器的数目达到用户的指定值为止。

from numpy import *

def loadSimpData():
datMat = matrix([[ 1. , 2.1],
[ 1.5, 1.6],
[ 1.3, 1. ],
[ 1. , 1. ],
[ 2. , 1. ]])
classLabels = [1.0, 1.0, -1.0, -1.0, 1.0]
return datMat,classLabels

def plotBestFit(weakClassArr):		#画出数据集和所有的基学习器
#import matplotlib.pyplot as plt
dataMat,labelMat=loadSimpData() #数据矩阵和标签向量
dataArr = array(dataMat) #转换成数组
n = shape(dataArr)[0]
xcord1 = []; ycord1 = [] #声明两个不同颜色的点的坐标
xcord2 = []; ycord2 = []
for i in range(n):
if int(labelMat[i])== 1:
xcord1.append(dataArr[i,0]); ycord1.append(dataArr[i,1])
else:
xcord2.append(dataArr[i,0]); ycord2.append(dataArr[i,1])
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(xcord1, ycord1, s=30, c='red', marker='s')
ax.scatter(xcord2, ycord2, s=30, c='green')
print "weakClassArr[0]['thresh']",weakClassArr[0]['dim']
for j in range(len(weakClassArr)):
if(weakClassArr[j]['dim'] == 1):
x = arange(-0.0, 2.5, 0.1)
y = x*0+weakClassArr[j]['thresh']
ax.plot(x, y)
else:
y = array(arange(-0.0, 2.5, 0.1))
x = y*0+weakClassArr[j]['thresh']
ax.plot(x, y)
plt.xlabel('X1'); plt.ylabel('X2');
plt.show() def stumpClassify(dataMatrix,dimen,threshVal,threshIneq): #通过阈值比较对数据进行分类
retArray = ones((shape(dataMatrix)[0],1)) #首先将返回的数组的全部元素设置为1
if threshIneq == 'lt':
retArray[dataMatrix[:,dimen] <= threshVal] = -1.0 #将满足<=不等式的元素设为-1
else:
retArray[dataMatrix[:,dimen] > threshVal] = -1.0 #将满足>不等式的元素设为-1
return retArray def buildStump(dataArr,classLabels,D): #遍历stumpClassify()函数所有的可能输入值,并找到数据集上最佳的单层决策树
dataMatrix = mat(dataArr); labelMat = mat(classLabels).T
m,n = shape(dataMatrix) #m=5,n=2
numSteps = 10.0; bestStump = {}; bestClasEst = mat(zeros((m,1)))
minError = inf #初始误差总和,为无穷大
for i in range(n): #循环X和Y两个维度
rangeMin = dataMatrix[:,i].min(); rangeMax = dataMatrix[:,i].max(); #取得X和Y两个维度的最大值和最小值特征
stepSize = (rangeMax-rangeMin)/numSteps #步进长度
for j in range(-1,int(numSteps)+1): #从-1到10步进
for inequal in ['lt', 'gt']: #"lt"为满足<=不等式,"gt"为满足>不等式
threshVal = (rangeMin + float(j) * stepSize) #当前阈值
predictedVals = stumpClassify(dataMatrix,i,threshVal,inequal) #根据阈值和不等式,计算预测的分类
errArr = mat(ones((m,1)))
errArr[predictedVals == labelMat] = 0 #样本估计错误的标记为1
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 def adaBoostTrainDS(dataArr,classLabels,numIt=40): #基于单层决策树的AdaBoost训练
weakClassArr = []
m = shape(dataArr)[0] #需要分类的数据量,m=5
D = mat(ones((m,1))/m) #D为权重向量,初始D1...D5的和等于1
aggClassEst = mat(zeros((m,1))) #基分类器的线性组合
for i in range(numIt):
#建立单层决策树,bestStump包括维度,不等式,阈值,error泛化误差,classEst是每个基分类器
bestStump,error,classEst = buildStump(dataArr,classLabels,D)
print "最佳决策树=",bestStump,"泛化误差=",error,"更新前的分类器预测结果=",classEst.T
#print "D:",D.T
alpha = float(0.5*log((1.0-error)/max(error,1e-16))) #根据泛化误差,计算基分类器的权重α值
bestStump['alpha'] = alpha #把权重α值添加到最佳决策树的列表中
print "最佳决策树=",bestStump
weakClassArr.append(bestStump) #保存单层最佳决策树参数到数组中
print "预测分类: ",classEst.T
expon = multiply(-1*alpha*mat(classLabels).T,classEst) #权重α×真实分类×预测分类,multiply为对应元素相乘,不是矩阵相乘
D = multiply(D,exp(expon)) #Calc New D for next iteration
D = D/D.sum() #更新D,D.sum()为规范化因子
#calc training error of all classifiers, if this is 0 quit for loop early (use break)
aggClassEst += alpha*classEst
print "更新后的分类器预测结果: ",aggClassEst.T
aggErrors = multiply(sign(aggClassEst) != mat(classLabels).T,ones((m,1))) #boolean值和1相乘
errorRate = aggErrors.sum()/m #计算错误率
print "total error: ",errorRate
if errorRate == 0.0: break
return weakClassArr,aggClassEst def adaClassify(datToClass,classifierArr): #AdaBoost分类函数
dataMatrix = mat(datToClass) #输入[0,0]转换成[[0,0]]矩阵
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']*classEst #计算在每一个基分类器上的预测值的累加和
print "aggClassEst=",aggClassEst
return sign(aggClassEst)

main.py

# coding:utf-8
# !/usr/bin/env python import adaboost if __name__ == '__main__':
datMat,classLabels = adaboost.loadSimpData()
weakClassArr,aggClassEst = adaboost.adaBoostTrainDS(datMat,classLabels)
print "弱分类器组合:",weakClassArr
print adaboost.adaClassify([[0,0],[5,5]],weakClassArr)
adaboost.plotBestFit(weakClassArr)

1个分类器————            2个分类器————            3个分类器————

机器学习——AdaBoost元算法的更多相关文章

  1. 机器学习实战 - 读书笔记(07) - 利用AdaBoost元算法提高分类性能

    前言 最近在看Peter Harrington写的"机器学习实战",这是我的学习笔记,这次是第7章 - 利用AdaBoost元算法提高分类性能. 核心思想 在使用某个特定的算法是, ...

  2. 【转载】 机器学习实战 - 读书笔记(07) - 利用AdaBoost元算法提高分类性能

    原文地址: https://www.cnblogs.com/steven-yang/p/5686473.html ------------------------------------------- ...

  3. 机器学习技法-AdaBoost元算法

    课程地址:https://class.coursera.org/ntumltwo-002/lecture 重要!重要!重要~ 一.Adaptive Boosting 的动机 通过组合多个弱分类器(hy ...

  4. 在Titanic数据集上应用AdaBoost元算法

    一.AdaBoost 元算法的基本原理 AdaBoost是adaptive boosting的缩写,就是自适应boosting.元算法是对于其他算法进行组合的一种方式. 而boosting是在从原始数 ...

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

    前言 有人认为 AdaBoost 是最好的监督学习的方式. 某种程度上因为它是元算法,也就是说它会是几种分类器的组合.这就好比对于一个问题能够咨询多个 "专家" 的意见了. 组合的 ...

  6. 第九篇:使用 AdaBoost 元算法提高分类器性能

    前言 有人认为 AdaBoost 是最好的监督学习的方式. 某种程度上因为它是元算法,也就是说它会是几种分类器的组合.这就好比对于一个问题能够咨询多个 "专家" 的意见了. 组合的 ...

  7. 机器学习算法( 七、AdaBoost元算法)

    一.概述 当做重要决定时,大家可能都会考虑吸取多个专家而不只是一个人的意见.机器学习处理问题时又何尝不是如此?这就是元算法(meta-algorithm)背后的思路.元算法是对其他算法进行组合的一种方 ...

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

    当做重要决定时,大家可能都会吸取多个专家而不只是一个人的意见.机器学习处理问题时又何尝不是如此?这就是元算法背后的思路.元算法是对其他算法进行组合的一种方式. 自举汇聚法(bootstrap aggr ...

  9. 监督学习——AdaBoost元算法提高分类性能

    基于数据的多重抽样的分类器 可以将不通的分类器组合起来,这种组合结果被称为集成方法(ensemble method)或者元算法(meta-algorithom) bagging : 基于数据随机抽样的 ...

随机推荐

  1. 纯js实现10分钟倒计时

    一个简单实现倒计时的小栗子~ 效果图:简陋的不能再简陋了,捂脸 代码: <!DOCTYPE HTML> <html> <head> <title> 倒计 ...

  2. 开启基本数据结构和算法之路--初识Graphviz

    在我的Linux刀耕开荒阶段,就想开始重拾C,利用C实现常用的基本数据结构和算法,而数据结构和算法的掌握的熟练程度正是程序的初学者与职业程序员的分水岭. 那么怎么开启这一段历程呢? 按照软件工程的思想 ...

  3. Android学习--自己在使用HttpConnection时遇到的EOFException

    在学习第一行代码第14章酷欧天气的时候,HttpUtil类中的sendHttpRequest方法发出请求,然后返回响应信息,但是出现了EOFException异常,代码如下: HttpURLConne ...

  4. 使用parted给大于2T的磁盘分区

    1.使用命令parted /dev/sdb [root@server ~]# parted /dev/sdb GNU Parted 2.1 使用 /dev/sdb Welcome to GNU Par ...

  5. 通过cmd完成FTP上传文件操作

    一直使用 FileZilla 这个工具进行相关的 FTP 操作,而在某一次版本升级之后,发现不太好用了,连接老是掉,再后来完全连接不上去. 改用了一段时间的 Web 版的 FTP 工具,后来那个页面也 ...

  6. Morris post order traversal algorithm

    Sept. 5, 2015 花时间把代码读明白, 比光看书强. 动手写代码, 改代码,  兴趣是最好的老师. 多记几个例子, 增加情趣. 举个例子关于中序遍历,            4       ...

  7. Hbase学习连接

    http://blog.csdn.net/baolibin528/article/details/43672131 http://m.blog.csdn.net/article/details?id= ...

  8. Linux 进程与线程五

    pthread_self函数 pthread_t pthread_self(void); 一般会成功,返回当前线程的ID 注意:在子线程中执行exit()函数会退出整个进程,一般使用pthread_e ...

  9. [LeetCode] Two Sum III - Data structure design 两数之和之三 - 数据结构设计

    Design and implement a TwoSum class. It should support the following operations:add and find. add - ...

  10. Android 提醒公共方法 Notification

    SimpAndroidFarme是近期脑子突然发热想做的android快速开发的框架,目标是模块化 常用的控件,方便新手学习和使用.也欢迎老鸟来一起充实项目:项目地址 今天的目标是做一个公共的提醒方法 ...