目录:

1. Boosting方法的简介

2. AdaBoost算法

3.基于单层决策树构建弱分类器

4.完整的AdaBoost的算法实现

5.总结

1. Boosting方法的简介 返回目录

Boosting方法的基本思想:对于一个复杂的任务来说,将多个专家的判断进行适当的综合所得出的判断,要比其中任何一个专家单独的判断好. 实际上就是“三个臭皮匠顶个诸葛亮的道理。”(参考:李航 《统计学习方法》)

对于分类问题而言, 给定一个训练集,求比较粗糙的分类规则(弱分类器)要比求精确的分类规则(强分类器)容易得多。Boosting方法就是从弱学习算法出发,反复学习,得到一系列弱分类器(又称基本分类器),然后组合这些弱分类器,构成一个强分类器。

对于Boosting方法来说,需要回答两个问题:

  • 每一轮如何改变训练数据的权值或者概率分布
  • 如何将若分类器组合成一个强分类器

2. AdaBoost算法 返回目录

boosting 方法拥有多个版本,其中最流行的一个版本就是AdaBoost,即adaptive boosting.

对与上面提到的两个问题,AdaBoost的做法分别是:

  • 对于第一个问题:提高那些被前一轮弱分类器错误分类的样本的权值,而降低那些被正确分类样本的权值.
  • 对于第二个问题:采取加权多数表决的方法,具体就是,加大分类误差率较小的弱分类器的权值,使其在表决中起较大的作用,减小分类误差率大的弱分类器的权值,使其在表决中起较小的作用.

具体算法流程描述如下:

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

$T=\{(x_{1},y_{1}),(x_{2,}y_{2}),\cdots,(x_{N},y_{N})\}$

其中,每个样本点由实例与标记组成. 实例 $x_{i}\in X\subseteq R^{n}$ ,标记 $y_{i}\in Y$$\subseteq R^{n}$, $X$ 是实例空间,$Y$ 是标记集合.

输入:训练数据集 $T=\{(x_{1},y_{1}),(x_{2,}y_{2}),\cdots,(x_{N},y_{N})\}$,其中 $x_{i}\in X\subseteq R^{n}$, $y_{i}\in Y=\{-1,+1\}$;弱分类器;

输出:最终分类器 $G(x)$.

(1) 初始化训练数据的权值分布

$D_{1}=\{w_{11},\cdots,w_{1i},\cdots,w_{1N}\},w_{1N}=\frac{1}{N},i=1,2,\cdots,N$

初始化的时候让每个训练样本在基本分类器的学习中作用相同

(2) 对 $m=1,2,\cdots,M$

(a) 使用具有权值分布 $D_{m}$ 的训练数据学习,得到基本分类器

$G_{m}(x):X\longrightarrow\{-1,+1\}$

(b) 计算 $G_{m}(x)$ 在训练数据集上的分类误差

$e_{m}=P(G_{m}(x_{i})\neq y_{i})=\sum_{i=1}^{N}w_{mi}I(G_{m}(x_{i})\neq y_{i})$ (1)

(c) 计算 $G_{m}(x)$ 的系数

$\alpha_{m}=\frac{1}{2}\log\frac{1-e_{m}}{e_{m}}$ (2)

这里对数是自然对数. $\alpha_{m}$ 表示 $G_{m}(x)$ 在最终分类器中的重要性,由该式可知,当 $e_{m}\leq\frac{1}{2}$ 时,$\alpha_{m}\geq0$,并且 $\alpha_{m}$ 随着 $e_{m}$ 的减小而增大,所以误差率越小的基本分类器在最终分类器中的作用越大.

(d) 更新训练数据集的权值分布

$D_{m+1}=\{w_{m+1,1},\cdots,w_{m+1,i},\cdots,w_{m+1,N}\}$ (3)

$w_{m+1,i}=\frac{w_{mi}}{Z_{m}}\exp(-\alpha_{m}y_{i}G_{m}(x_{i})),i=1,2,\cdots,N$ (4)

这里 $Z_{m}$ 是归一化因子.

$Z_{m}=\sum_{i=1}^{N}w_{mi}\exp(-\alpha_{m}y_{i}G_{m}(x_{i}))$

它使 $D_{m+1}$ 成为一个概率分布. 式 (4) 还可以写成:

\[w_{m+1,i}=\left\{ \begin{array}{c}\frac{w_{mi}}{Z_{m}}e^{-\alpha_{m}},G_{m}(x_{i})=y_{i}\\\frac{w_{mi}}{Z_{m}}e^{\alpha_{m}},G_{m}(x_{i})\neq y_{i}\end{array}\right.\]

由此可知,被基本分类器 $G_{m}(x)$ 误分类样本的权值得以扩大,而被正确分类样本的权值却得以缩小,因此误分类样本在下一轮学习中起更大作用.

(3) 构建基本分类器的线性组合

$f(x)=\sum_{i=1}^{N}\alpha_{m}G_{m}(x)$

得到最终分类器

$G(x)=$sign$(f(x))=$sign$(\sum_{m=1}^{M}\alpha_{m}G_{m}(x))$

线性组合 $f(x)$ 实现 $M$ 个基本分类器的加权表决. $f(x)$ 的符号决定了实例 $x$ 的类别,$f(x)$ 的绝对值表示分类的确信度.

3.基于单层决策树构建弱分类器 返回目录

所谓单层决策树(decision stump, 也称决策树桩)就是基于简单的单个特征来做决策,由于这棵树只有一次分裂过程,因此实际上就是一个树桩。

首先通过一个简单的数据集来确保在算法实现上一切就绪.

  1. def loadSimpData():
  2. dataMat = np.matrix( [ [ 1., 2.1],
  3. [ 2., 1.1],
  4. [ 1.3, 1.],
  5. [ 1., 1. ],
  6. [ 2., 1. ] ] )
  7. classLabels = [ 1.0, 1.0, -1.0, -1.0, 1.0 ]
  8. return dataMat, classLabels

下图给出了上面数据集的示意图

如果使用上面所述的单层决策树来对上面的样本点进行分类,即试着从某个坐标轴选择一个值(选择一条与坐标轴平行的直线)来将所有蓝色样本和褐色样本分开,这显然不可能。但是使用多棵单层决策树,就可以构建出一个能对该数据集完全正确的分类器.

首先给出单层决策树生成函数

  1. def stumpClassify( dataMatrix, dimen, threshVal, threshIneq ):
  2. '''
  3. 通过阈值比较对数据进行分类,所有在阈值一边的数据会分到类别-1,而在
  4. 另外一边的数据分到类别+1.
  5. '''
  6. retArray = np.ones( ( np.shape( dataMatrix )[ 0 ], 1 ) )
  7. if threshIneq == 'lt':
  8. retArray[ dataMatrix[ :, dimen ] <= threshVal ] = -1.0
  9. else:
  10. retArray[ dataMatrix[ :, dimen ] > threshVal ] = -1.0
  11. return retArray
  12. def buildStump( dataArr, classLabels, D ):
  13. '''
  14. '''
  15. dataMatrix = np.mat(dataArr)
  16. labelMat = np.mat(classLabels).T
  17. m,n = np.shape(dataMatrix)
  18. numSteps = 10.0 #用于在特征的所有可能值上进行遍历
  19. bestStump = {} #存储给定权重向量 D 时所得到的最佳单层决策树的信息
  20. bestClassEst = np.mat( np.zeros( (m, 1) ) )
  21. minError = np.inf
  22. for i in range( n ):
  23. # 对于每一维的特征
  24. rangeMin = dataMatrix[:, i].min()
  25. rangeMax = dataMatrix[:, i].max()
  26. stepSize = ( rangeMax - rangeMin ) / numSteps
  27. for j in range( -1, int( numSteps ) + 1 ):
  28. # 对于每一个阈值
  29. for inequal in [ 'lt', 'gt' ]:
  30. threshVal = rangeMin + float( j ) * stepSize
  31. predictedVals = stumpClassify( dataMatrix, i,
  32. threshVal, inequal )
  33. errArr = np.mat( np.ones( ( m, 1 ) ) )
  34. errArr[ predictedVals == labelMat ] = 0
  35. weightedError = D.T * errArr
  36. # print "split: dim %d, thresh %.2f, thresh inequal: \
  37. # %s, the weighted error is %.3f" % \
  38. # ( i, threshVal, inequal, weightedError )
  39. if weightedError < minError:
  40. minError = weightedError
  41. bestClassEst = predictedVals.copy()
  42. bestStump[ 'dim' ] = i
  43. bestStump[ 'thresh' ] = threshVal
  44. bestStump[ 'ineq' ] = inequal
  45. return bestStump, minError, bestClassEst

上面两个函数作用是对于给定的数据集选出最佳的单层决策树.

4.完整的AdaBoost的算法实现 返回目录

下面给出完整的AdaBoost的算法实现

  1. def adaBoostTrainDS( dataArr, classLabels, numIt = 40 ):
  2. '''
  3. 基于单层决策树的AdaBoost训练过程
  4. '''
  5. weakClfArr = []
  6. m = np.shape( dataArr )[ 0 ]
  7. D = np.mat( np.ones( ( m, 1 ) ) / m )
  8. aggClassEst = np.mat( np.zeros( ( m, 1 ) ) )
  9. for i in range( numIt ):
  10. # 每一次循环 只有样本的权值分布 D 发生变化
  11. bestStump, error, classEst = buildStump( dataArr, classLabels, D )
  12. print " D: ", D.T
  13.  
  14. # 计算弱分类器的权重
  15. alpha = float( 0.5 * np.log( ( 1 - error ) / max( error, 1e-16 ) ) )
  16. bestStump[ 'alpha' ] = alpha
  17. weakClfArr.append( bestStump )
  18. print "classEst: ", classEst.T
  19.  
  20. # 更新训练数据集的权值分布
  21. expon = np.multiply( -1 * alpha * np.mat( classLabels ).T, classEst )
  22. D = np.multiply( D, np.exp( expon ) )
  23. D = D / D.sum()
  24.  
  25. # 记录对每个样本点的类别估计的累积值
  26. aggClassEst += alpha * classEst
  27. print "aggClassEst: ", aggClassEst.T
  28.  
  29. # 计算分类错误率
  30. aggErrors = np.multiply( np.sign(aggClassEst) !=
  31. np.mat( classLabels ).T, np.ones( ( m, 1 ) ) )
  32. errorRate = aggErrors.sum() / m
  33. print "total error: ", errorRate, "\n"
  34.  
  35. # 如果完全正确,终止迭代
  36. if errorRate == 0.0:
  37. break
  38. return weakClfArr
  39.  
  40. if __name__ == '__main__':
  41. print __doc__
  42. datMat, classLabels = loadSimpData()
  43. # plt.scatter(datMat[:, 0], datMat[:, 1], c=classLabels, markers=classLabels, s=200, cmap=plt.cm.Paired)
  44. print adaBoostTrainDS( datMat, classLabels, 9 )

AdaBoost

运行结果

  1. D: [[ 0.2 0.2 0.2 0.2 0.2]]
  2. classEst: [[-1. 1. -1. -1. 1.]]
  3. aggClassEst: [[-0.69314718 0.69314718 -0.69314718 -0.69314718 0.69314718]]
  4. total error: 0.2
  5.  
  6. D: [[ 0.5 0.125 0.125 0.125 0.125]]
  7. classEst: [[ 1. 1. -1. -1. -1.]]
  8. aggClassEst: [[ 0.27980789 1.66610226 -1.66610226 -1.66610226 -0.27980789]]
  9. total error: 0.2
  10.  
  11. D: [[ 0.28571429 0.07142857 0.07142857 0.07142857 0.5 ]]
  12. classEst: [[ 1. 1. 1. 1. 1.]]
  13. aggClassEst: [[ 1.17568763 2.56198199 -0.77022252 -0.77022252 0.61607184]]
  14. total error: 0.0
  15.  
  16. [{'dim': 0, 'ineq': 'lt', 'thresh': 1.3, 'alpha': 0.6931471805599453}, {'dim': 1, 'ineq': 'lt', 'thresh': 1.0, 'alpha': 0.9729550745276565}, {'dim': 0, 'ineq': 'lt', 'thresh': 0.90000000000000002, 'alpha': 0.8958797346140273}]

可以看到错误率逐步被降到 $0.0$, 最终的分类器包含 $3$ 个基本分类器.

下面基于AdaBoost进行分类,需要做的就只是将弱分类器的训练过程从程序中抽取出来,然后应用到某个具体实例上去。每个弱分类器的结果以其对应的 alpha 值作为权值. 所有这些弱分类器的结果加权求和就得到了最后的结果.

AdaBoost分类函数

adaClassify

测试

  1. if __name__ == '__main__':
  2. print __doc__
  3. datMat, classLabels = loadSimpData()
  4. # plt.scatter(datMat[:, 0], datMat[:, 1], c=classLabels, markers=classLabels, s=200, cmap=plt.cm.Paired)
  5. classifierArr = adaBoostTrainDS( datMat, classLabels, 9 )
  6. print adaClassify( [ 0, 0 ], classifierArr )

测试结果

  1. [[-0.69314718]]
  2. [[-1.66610226]]
  3. [[-2.56198199]]
  4. [[-1.]]

可以发现,随着迭代进行,数据点 $[0, 0]$ 的分类确信度越来越强.

5.总结 返回目录

AdaBoost的优点:泛化错误率低,可以用在大部分分类器上,无参数调整(自适应).

缺点:对离群点敏感.

基于Python的机器学习实战:AadBoost的更多相关文章

  1. 基于Python的机器学习实战:KNN

    1.KNN原理: 存在一个样本数据集合,也称作训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一个数据与所属分类的对应关系.输入没有标签的新数据后,将新数据的每个特征与样本集中数据对应 ...

  2. 基于Python的机器学习实战:Apriori

    目录: 1.关联分析 2. Apriori 原理 3. 使用 Apriori 算法来发现频繁集 4.从频繁集中挖掘关联规则 5. 总结 1.关联分析  返回目录 关联分析是一种在大规模数据集中寻找有趣 ...

  3. 【python与机器学习实战】感知机和支持向量机学习笔记(一)

    对<Python与机器学习实战>一书阅读的记录,对于一些难以理解的地方查阅了资料辅以理解并补充和记录,重新梳理一下感知机和SVM的算法原理,加深记忆. 1.感知机 感知机的基本概念 感知机 ...

  4. K近邻 Python实现 机器学习实战(Machine Learning in Action)

    算法原理 K近邻是机器学习中常见的分类方法之间,也是相对最简单的一种分类方法,属于监督学习范畴.其实K近邻并没有显式的学习过程,它的学习过程就是测试过程.K近邻思想很简单:先给你一个训练数据集D,包括 ...

  5. 朴素贝叶斯算法的python实现 -- 机器学习实战

    import numpy as np import re #词表到向量的转换函数 def loadDataSet(): postingList = [['my', 'dog', 'has', 'fle ...

  6. 基于python的机器学习开发环境安装(最简单的初步开发环境)

    一.安装Python 1.下载安装python3.6 https://www.python.org/getit/ 2.配置环境变量(2个) 略...... 二.安装Python算法库 安装顺序:Num ...

  7. 基于python的机器学习实现日元币对人民币汇率预测

    ## 导入所需的包 import pandas as pd import numpy as np import matplotlib.pyplot as plt import tensorflow a ...

  8. 《机器学习实战》基于朴素贝叶斯分类算法构建文本分类器的Python实现

    ============================================================================================ <机器学 ...

  9. 机器学习实战笔记(Python实现)-08-线性回归

    --------------------------------------------------------------------------------------- 本系列文章为<机器 ...

随机推荐

  1. virtualenv 模块

    作用 安装虚拟环境 下载组件 pip3 install virtualenv 使用 命令行创建使用 """ 创建虚拟环境 """ virtu ...

  2. 小强学Python+OpenCV之-1.3绘图

    目标 今天的课程比较轻松,我们来学习一下OpenCV中几个绘图函数: cv2.line cv2.rectangle cv2.circle 画直线 直接经过前面两节的内容.我想直接上代码应该是可以接受的 ...

  3. 自学Linux Shell1.1-Linux初识

    点击返回 自学Linux命令行与Shell脚本之路 1.1-Linux初识(架构.内核.shell) 1. Linux架构 Linux系统一般有4个主要部分:内核.shell.文件系统和应用程序.(有 ...

  4. Android 屏幕操作

    1 全屏显示Activity 代码 : 方法一:编程实现 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, Window ...

  5. 【BZOJ2228】[ZJOI2011]礼物(单调栈)

    [BZOJ2228][ZJOI2011]礼物(单调栈) 题面 BZOJ 洛谷 题解 如果这个玩意不是一个三维立方体,而是一个二维的矩形,让你在里面找一个最大正方形,那么全世界都会做. 丢到三维上?似乎 ...

  6. KMP 模式串匹配 失去匹配的瞬间你还有什么

    KMP: KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt同时发现,因此人们称它为克努特——莫里斯——普拉特操作(简称KMP算法).KMP算法的关键 ...

  7. Chrome 下,重复使用 XMLHttpRequest进行Post数据时,遇到一个奇怪的问题

    var http_request; //在外面申明对象,主要为了在updatePage中使用     //无刷新更新内容 function post(url,parameter) {        i ...

  8. 内存分布图,errno

    输出错误,errno是默认的全局变量 错误处理函数: 错误号:errno perror函数:        void perror(const char *s); strerror函数:        ...

  9. 在 CentOS 6.x 上安装最新版本的 git

    在 CentOS 的默认仓库中有git,所以最简单的方法是: $ sudo yum install git 这种方法虽然简单,但是一般仓库里的版本更新不及时,比如 CentOS 仓库中的 git 最新 ...

  10. struts下载

    struts下载地址:http://struts.apache.org/download.cgi