热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Adaboost算法实例解析

Adaboost算法实例解析1Adaboost的原理1.1Adaboost基本介绍AdaBoost,是英文AdaptiveBoosting(自适应增
Adaboost 算法实例解析

1 Adaboost的原理

1.1 Adaboost基本介绍   

    AdaBoost,是英文"Adaptive Boosting"(自适应增强)的缩写,由Yoav Freund和Robert Schapire在1995年提出。Adaboost是一种迭代算法,其核心思想是针对同一个训练集训练不同的分类器(弱分类器),然后把这 Adaboost 些弱分类器集合起来,构成一个更强的最终分类器(强分类器)。其算法本身是通过改变数据分布来实现的,它根据每次训练集之中每个样本的分类是否正确,以及上次的总体分类的准确率,来确定每个样本的权值。将修改过权值的新数据集送给下层分类器进行训练,最后将每次训练得到的分类器最后融合起来,作为最后的决策分类器。使用adaboost分类器可以排除一些不必要的训练数据特徵,并将关键放在关键的训练数据上面。


主要解决的问题
  目前,对adaBoost算法的研究以及应用大多集中于分类问题,同时近年也出现了一些在回归问题上的应用。就其应用adaBoost系列主要解决了: 两类问题、多类单标签问题、多类多标签问题、大类单标签问题,回归问题。它用全部的训练样本进行学习。

 

1.2 Adaboost算法介绍

 

算法分析 

 该算法其实是一个简单的弱分类算法提升过程,这个过程通过不断的训练,可以提高对数据的分类能   Adaboost
力。整个过程如下所示:   
      1. 先通过对N个训练样本的学习得到第一个弱分类器;   
      2. 将分错的样本和其他的新数据一起构成一个新的N个的训练样本,通过对这个样本的学习得到第二个弱分类器 ;   
      3. 将1和2都分错了的样本加上其他的新样本构成另一个新的N个的训练样本,通过对这个样本的学习得到第三个弱分类器;
  4. 最终经过提升的强分类器 。即某个数据被分为哪一类要通过 , ……的多数表决。

     Adaboost的自适应在于:前一个基本分类器分错的样本会得到加强,加权后的全体样本再次被用来训练下一个基本分类器。同时,在每一轮中加入一个新的弱分类器,直到达到某个预定的足够小的错误率或达到预先指定的最大迭代次数。

     具体说来,整个Adaboost 迭代算法就3步:

  1. 初始化训练数据的权值分布。如果有N个样本,则每一个训练样本最开始时都被赋予相同的权重:1/N。
  2. 训练弱分类器。具体训练过程中,如果某个样本点已经被准确地分类,那么在构造下一个训练集中,它的权重就被降低;相反,如果某个样本点没有被准确地分类,那么它的权重就得到提高。然后,权重更新过的样本集被用于训练下一个分类器,整个训练过程如此迭代地进行下去。
  3. 将各个训练得到的弱分类器组合成强分类器。各个弱分类器的训练过程结束后,加大分类误差率小的弱分类器的权重,使其在最终的分类函数中起着较大的决定作用,而降低分类误差率大的弱分类器的权重,使其在最终的分类函数中起着较小的决定作用。换言之,误差率低的弱分类器在最终分类器中占的权重较大,否则较小。

 

Adaboost算法流程

对于这个算法需要介绍的是:

  1. 算法开始前,需要将每个样本的权重初始化为1/m,这样一开始每个样本都是等概率的分布,每个分类器都会公正对待。

  2. 开始迭代后,需要计算每个弱分类器的分类错误的误差,误差等于各个分错样本的权重和,这里就体现了样本权重的作用。如果一个分类器正确分类了一个权重大的样本,那么这个分类器的误差就会小,否则就会大。这样就对分类错误的样本更大的关注。

  3. 获取最优分类器后,需要计算这个分类器的权重,然后再更新各个样本的权重,然后再归一化

  4. 算法迭代的次数一般不超过弱分类器的个数,如果弱分类器的个数非常之多,那么可以权衡自己性价比来折中选择。

  5. 迭代完成后,最后的分类器是由迭代过程中选择的弱分类器线性加权得到的。

 

1.3 Adaboost实例解析

   例1. 下面,给定下列训练样本,请用AdaBoost算法学习一个强分类器。

求解过程:初始化训练数据的权值分布,令每个权值W1i = 1/N = 0.1,其中,N = 10,i = 1,2, ..., 10,然后分别对于m = 1,2,3, ...等值进行迭代。

    拿到这10个数据的训练样本后,根据 X 和 Y 的对应关系,要把这10个数据分为两类,一类是“1”,一类是“-1”,根据数据的特点发现:“0 1 2”这3个数据对应的类是“1”,“3 4 5”这3个数据对应的类是“-1”,“6 7 8”这3个数据对应的类是“1”,9是比较孤独的,对应类“-1”。抛开孤独的9不讲,“0 1 2”、“3 4 5”、“6 7 8”这是3类不同的数据,分别对应的类是1、-1、1,直观上推测可知,可以找到对应的数据分界点,比如2.5、5.5、8.5 将那几类数据分成两类。当然,这只是主观臆测,下面实际计算下这个过程。

迭代过程1

对于m=1,在权值分布为D1(10个数据,每个数据的权值皆初始化为0.1)的训练数据上,经过计算可得:

  1. 阈值v取2.5时误差率为0.3&#xff08;x <2.5时取1&#xff0c;x > 2.5时取-1&#xff0c;则6 7 8分错&#xff0c;误差率为0.3&#xff09;&#xff0c;
  2. 阈值v取5.5时误差率最低为0.4&#xff08;x <5.5时取1&#xff0c;x > 5.5时取-1&#xff0c;则3 4 5 6 7 8皆分错&#xff0c;误差率0.6大于0.5&#xff0c;不可取。故令x > 5.5时取1&#xff0c;x <5.5时取-1&#xff0c;则0 1 2 9分错&#xff0c;误差率为0.4&#xff09;&#xff0c;
  3. 阈值v取8.5时误差率为0.3&#xff08;x <8.5时取1&#xff0c;x > 8.5时取-1&#xff0c;则3 4 5分错&#xff0c;误差率为0.3&#xff09;。

所以无论阈值v取2.5&#xff0c;还是8.5&#xff0c;总得分错3个样本&#xff0c;故可任取其中任意一个如2.5&#xff0c;弄成第一个基本分类器为&#xff1a;

上面说阈值v取2.5时则6 7 8分错&#xff0c;所以误差率为0.3&#xff0c;更加详细的解释是&#xff1a;因为样本集中

  1. 0 1 2对应的类&#xff08;Y&#xff09;是1&#xff0c;因它们本身都小于2.5&#xff0c;所以被G1(x)分在了相应的类“1”中&#xff0c;分对了。
  2. 3 4 5本身对应的类&#xff08;Y&#xff09;是-1&#xff0c;因它们本身都大于2.5&#xff0c;所以被G1(x)分在了相应的类“-1”中&#xff0c;分对了。
  3. 但6 7 8本身对应类&#xff08;Y&#xff09;是1&#xff0c;却因它们本身大于2.5而被G1(x)分在了类"-1"中&#xff0c;所以这3个样本被分错了。
  4. 9本身对应的类&#xff08;Y&#xff09;是-1&#xff0c;因它本身大于2.5&#xff0c;所以被G1(x)分在了相应的类“-1”中&#xff0c;分对了。

从而得到G1(x)在训练数据集上的误差率&#xff08;被G1(x)误分类样本“6 7 8”的权值之和&#xff09;e1&#61;P(G1(xi)≠yi) &#61; 3*0.1 &#61; 0.3

然后根据误差率e1计算G1的系数&#xff1a;

这个a1代表G1(x)在最终的分类函数中所占的权重&#xff0c;为0.4236。
接着更新训练数据的权值分布&#xff0c;用于下一轮迭代&#xff1a;

值得一提的是&#xff0c;由权值更新的公式可知&#xff0c;每个样本的新权值是变大还是变小&#xff0c;取决于它是被分错还是被分正确。

即如果某个样本被分错了&#xff0c;则yi * Gm(xi)为负&#xff0c;负负等正&#xff0c;结果使得整个式子变大&#xff08;样本权值变大&#xff09;&#xff0c;否则变小。

第一轮迭代后&#xff0c;最后得到各个数据的权值分布D2 &#61; (0.0715, 0.0715, 0.0715, 0.0715, 0.0715,  0.0715, 0.1666, 0.1666, 0.1666, 0.0715)。由此可以看出&#xff0c;因为样本中是数据“6 7 8”被G1(x)分错了&#xff0c;所以它们的权值由之前的0.1增大到0.1666&#xff0c;反之&#xff0c;其它数据皆被分正确&#xff0c;所以它们的权值皆由之前的0.1减小到0.0715。

分类函数f1(x)&#61; a1*G1(x) &#61; 0.4236G1(x)。

此时&#xff0c;得到的第一个基本分类器sign(f1(x))在训练数据集上有3个误分类点&#xff08;即6 7 8&#xff09;。

    从上述第一轮的整个迭代过程可以看出&#xff1a;被误分类样本的权值之和影响误差率&#xff0c;误差率影响基本分类器在最终分类器中所占的权重。

 迭代过程2

对于m&#61;2&#xff0c;在权值分布为D2 &#61; (0.0715, 0.0715, 0.0715, 0.0715, 0.0715,  0.0715, 0.1666, 0.1666, 0.1666, 0.0715)的训练数据上&#xff0c;经过计算可得&#xff1a;

  1. 阈值v取2.5时误差率为0.1666*3&#xff08;x <2.5时取1&#xff0c;x > 2.5时取-1&#xff0c;则6 7 8分错&#xff0c;误差率为0.1666*3&#xff09;&#xff0c;
  2. 阈值v取5.5时误差率最低为0.0715*4&#xff08;x > 5.5时取1&#xff0c;x <5.5时取-1&#xff0c;则0 1 2 9分错&#xff0c;误差率为0.0715*3 &#43; 0.0715&#xff09;&#xff0c;
  3. 阈值v取8.5时误差率为0.0715*3&#xff08;x <8.5时取1&#xff0c;x > 8.5时取-1&#xff0c;则3 4 5分错&#xff0c;误差率为0.0715*3&#xff09;。

所以&#xff0c;阈值v取8.5时误差率最低&#xff0c;故第二个基本分类器为&#xff1a;

面对的还是下述样本&#xff1a;

很明显&#xff0c;G2(x)把样本“3 4 5”分错了&#xff0c;根据D2可知它们的权值为0.0715, 0.0715,  0.0715&#xff0c;所以G2(x)在训练数据集上的误差率e2&#61;P(G2(xi)≠yi) &#61; 0.0715 * 3 &#61; 0.2143。

计算G2的系数&#xff1a;

更新训练数据的权值分布&#xff1a;

D3 &#61; (0.0455, 0.0455, 0.0455, 0.1667, 0.1667,  0.01667, 0.1060, 0.1060, 0.1060, 0.0455)。被分错的样本“3 4 5”的权值变大&#xff0c;其它被分对的样本的权值变小。
f2(x)&#61;0.4236G1(x) &#43; 0.6496G2(x)

此时&#xff0c;得到的第二个基本分类器sign(f2(x))在训练数据集上有3个误分类点&#xff08;即3 4 5&#xff09;。

 迭代过程3

对于m&#61;3&#xff0c;在权值分布为D3 &#61; (0.0455, 0.0455, 0.0455, 0.1667, 0.1667,  0.01667, 0.1060, 0.1060, 0.1060, 0.0455)的训练数据上&#xff0c;经过计算可得&#xff1a;

  1. 阈值v取2.5时误差率为0.1060*3&#xff08;x <2.5时取1&#xff0c;x > 2.5时取-1&#xff0c;则6 7 8分错&#xff0c;误差率为0.1060*3&#xff09;&#xff0c;
  2. 阈值v取5.5时误差率最低为0.0455*4&#xff08;x > 5.5时取1&#xff0c;x <5.5时取-1&#xff0c;则0 1 2 9分错&#xff0c;误差率为0.0455*3 &#43; 0.0715&#xff09;&#xff0c;
  3. 阈值v取8.5时误差率为0.1667*3&#xff08;x <8.5时取1&#xff0c;x > 8.5时取-1&#xff0c;则3 4 5分错&#xff0c;误差率为0.1667*3&#xff09;。

所以阈值v取5.5时误差率最低&#xff0c;故第三个基本分类器为&#xff08;下图画反了&#xff0c;待后续修正&#xff09;&#xff1a;

依然还是原样本&#xff1a;

此时&#xff0c;被误分类的样本是&#xff1a;0 1 2 9&#xff0c;这4个样本所对应的权值皆为0.0455&#xff0c;

所以G3(x)在训练数据集上的误差率e3&#61; P(G3(xi)≠yi) &#61; 0.0455*4 &#61; 0.1820。

计算G3的系数&#xff1a;

更新训练数据的权值分布&#xff1a;

D4 &#61; (0.125, 0.125, 0.125, 0.102, 0.102,  0.102, 0.065, 0.065, 0.065, 0.125)。被分错的样本“0 1 2 9”的权值变大&#xff0c;其它被分对的样本的权值变小。

f3(x)&#61;0.4236G1(x) &#43; 0.6496G2(x)&#43;0.7514G3(x)

此时&#xff0c;得到的第三个基本分类器sign(f3(x))在训练数据集上有0个误分类点。至此&#xff0c;整个训练过程结束。

    G(x) &#61; sign[f3(x)] &#61; sign[ a1 * G1(x) &#43; a2 * G2(x) &#43; a3 * G3(x) ]&#xff0c;将上面计算得到的a1、a2、a3各值代入G(x)中&#xff0c;得到最终的分类器为&#xff1a;G(x) &#61; sign[f3(x)] &#61; sign[ 0.4236G1(x) &#43; 0.6496G2(x)&#43;0.7514G3(x) ]。

 

------- ----  用图解深入浅出的解释adaboost ---—————

也许你看了上面的介绍或许还是对adaboost算法云里雾里的&#xff0c;没关系&#xff0c;百度大牛举了一个很简单的例子&#xff0c;你看了就会对这个算法整体上很清晰了。

  下面我们举一个简单的例子来看看adaboost的实现过程&#xff1a;

图中&#xff0c;“&#43;”和“-”分别表示两种类别&#xff0c;在这个过程中&#xff0c;我们使用水平或者垂直的直线作为分类器&#xff0c;来进行分类。

  第一步&#xff1a;

根据分类的正确率&#xff0c;得到一个新的样本分布D2­&#xff0c;一个子分类器h1

  其中划圈的样本表示被分错的。在右边的途中&#xff0c;比较大的“&#43;”表示对该样本做了加权。

 

也许你对上面的ɛ1&#xff0c;ɑ1怎么算的也不是很理解。下面我们算一下&#xff0c;不要嫌我啰嗦&#xff0c;我最开始就是这样思考的&#xff0c;只有自己把算法演算一遍&#xff0c;你才会真正的懂这个算法的核心&#xff0c;后面我会再次提到这个。

算法最开始给了一个均匀分布 D 。所以h1 里的每个点的值是0.1。ok&#xff0c;当划分后&#xff0c;有三个点划分错了&#xff0c;根据算法误差表达式得到 误差为分错了的三个点的值之和&#xff0c;所以ɛ1&#61;(0.1&#43;0.1&#43;0.1)&#61;0.3&#xff0c;而ɑ1 根据表达式 的可以算出来为0.42. 然后就根据算法 把分错的点权值变大。如此迭代&#xff0c;最终完成adaboost算法。

  第二步&#xff1a;

根据分类的正确率&#xff0c;得到一个新的样本分布D3&#xff0c;一个子分类器h2

  第三步&#xff1a;

得到一个子分类器h3

  整合所有子分类器&#xff1a;

因此可以得到整合的结果&#xff0c;从结果中看&#xff0c;及时简单的分类器&#xff0c;组合起来也能获得很好的分类效果&#xff0c;在例子中所有的。

五 Adaboost 疑惑和思考

  到这里&#xff0c;也许你已经对adaboost算法有了大致的理解。但是也许你会有个问题&#xff0c;为什么每次迭代都要把分错的点的权值变大呢&#xff1f;这样有什么好处呢&#xff1f;不这样不行吗? 这就是我当时的想法&#xff0c;为什么呢&#xff1f;我看了好几篇介绍adaboost 的博客&#xff0c;都没有解答我的疑惑&#xff0c;也许大牛认为太简单了&#xff0c;不值一提&#xff0c;或者他们并没有意识到这个问题而一笔带过了。然后我仔细一想&#xff0c;也许提高错误点可以让后面的分类器权值更高。然后看了adaboost算法&#xff0c;和我最初的想法很接近&#xff0c;但不全是。 注意到算法最后的表到式为&#xff0c;这里面的a 表示的权值&#xff0c;是由得到的。而a是关于误差的表达式&#xff0c;到这里就可以得到比较清晰的答案了&#xff0c;所有的一切都指向了误差。提高错误点的权值&#xff0c;当下一次分类器再次分错了这些点之后&#xff0c;会提高整体的错误率&#xff0c;这样就导致 a 变的很小&#xff0c;最终导致这个分类器在整个混合分类器的权值变低。也就是说&#xff0c;这个算法让优秀的分类器占整体的权值更高&#xff0c;而挫的分类器权值更低。这个就很符合常理了。到此&#xff0c;我认为对adaboost已经有了一个透彻的理解了。

 

六 总结

  最后&#xff0c;我们可以总结下adaboost算法的一些实际可以使用的场景&#xff1a;

  1&#xff09;用于二分类或多分类的应用场景

  2&#xff09;用于做分类任务的baseline

  无脑化&#xff0c;简单&#xff0c;不会overfitting&#xff0c;不用调分类器

  3&#xff09;用于特征选择&#xff08;feature selection)

  4&#xff09;Boosting框架用于对badcase的修正

  只需要增加新的分类器&#xff0c;不需要变动原有分类器

  由于adaboost算法是一种实现简单&#xff0c;应用也很简单的算法。Adaboost算法通过组合弱分类器而得到强分类器&#xff0c;同时具有分类错误率上界随着训练增加而稳定下降&#xff0c;不会过拟合等的性质&#xff0c;应该说是一种很适合于在各种分类场景下应用的算法。

     

      这个是我看过对adaboost写的比较容易懂的文章了&#xff0c;等有空的时候我自己运行下adaboost的python代码&#xff0c;到时候再把这篇文章修改下。

      对了&#xff0c;如果看到我的博客后&#xff0c;有意愿和我技术沟通的&#xff0c;可以加我QQ 340217138 讨论。

 参考&#xff1a;

  http://blog.csdn.net/tiandijun/article/details/48036025

     http://blog.csdn.net/haidao2009/article/details/7514787

 

转:https://www.cnblogs.com/www-caiyin-com/p/6759381.html



推荐阅读
  • IOS Run loop详解
    为什么80%的码农都做不了架构师?转自http:blog.csdn.netztp800201articledetails9240913感谢作者分享Objecti ... [详细]
  • 开机自启动的几种方式
    0x01快速自启动目录快速启动目录自启动方式源于Windows中的一个目录,这个目录一般叫启动或者Startup。位于该目录下的PE文件会在开机后进行自启动 ... [详细]
  • JUC(三):深入解析AQS
    本文详细介绍了Java并发工具包中的核心类AQS(AbstractQueuedSynchronizer),包括其基本概念、数据结构、源码分析及核心方法的实现。 ... [详细]
  • 使用ArcGIS for Java和Flex浏览自定义ArcGIS Server 9.3地图
    本文介绍了如何在Flex应用程序中实现浏览自定义ArcGIS Server 9.3发布的地图。这是一个基本的入门示例,适用于初学者。 ... [详细]
  • 本文介绍了几种常用的图像相似度对比方法,包括直方图方法、图像模板匹配、PSNR峰值信噪比、SSIM结构相似性和感知哈希算法。每种方法都有其优缺点,适用于不同的应用场景。 ... [详细]
  • 字符串学习时间:1.5W(“W”周,下同)知识点checkliststrlen()函数的返回值是什么类型的?字 ... [详细]
  • 最详尽的4K技术科普
    什么是4K?4K是一个分辨率的范畴,即40962160的像素分辨率,一般用于专业设备居多,目前家庭用的设备,如 ... [详细]
  • 网站访问全流程解析
    本文详细介绍了从用户在浏览器中输入一个域名(如www.yy.com)到页面完全展示的整个过程,包括DNS解析、TCP连接、请求响应等多个步骤。 ... [详细]
  • 在多线程并发环境中,普通变量的操作往往是线程不安全的。本文通过一个简单的例子,展示了如何使用 AtomicInteger 类及其核心的 CAS 无锁算法来保证线程安全。 ... [详细]
  • 秒建一个后台管理系统?用这5个开源免费的Java项目就够了
    秒建一个后台管理系统?用这5个开源免费的Java项目就够了 ... [详细]
  • 近期在研究逆向工程,因此尝试了一些CTF题目。通过合天网络安全实验室的CTF实战演练平台(http://www.hetianlab.com/CTFrace.html),我对Linux逆向工程的掌握还不够深入,因此暂时跳过了RE300题目。首先从逆向100开始,将文件后缀名修改为.apk进行初步分析。这一过程不仅帮助我熟悉了基本的逆向技巧,还加深了对Android应用结构的理解。 ... [详细]
  • MySQL的查询执行流程涉及多个关键组件,包括连接器、查询缓存、分析器和优化器。在服务层,连接器负责建立与客户端的连接,查询缓存用于存储和检索常用查询结果,以提高性能。分析器则解析SQL语句,生成语法树,而优化器负责选择最优的查询执行计划。这一流程确保了MySQL能够高效地处理各种复杂的查询请求。 ... [详细]
  • 精选在线API编辑工具推荐
    本文将介绍几款优秀的在线API编辑工具,包括它们的功能特点和使用方法,帮助开发者提高工作效率。 ... [详细]
  • 文章目录Golang定时器Timer和Tickertime.Timertime.NewTimer()实例time.AfterFunctime.Tickertime.NewTicke ... [详细]
  • 通过使用Sqoop导入工具,可以精确控制并高效地将表数据的特定子集导入到HDFS中。具体而言,可以通过在导入命令中添加WHERE子句来指定所需的数据范围,从而在数据库服务器上执行相应的SQL查询,并将查询结果高效地存储到HDFS中。这种方法不仅提高了数据导入的灵活性,还确保了数据的准确性和完整性。 ... [详细]
author-avatar
sen0226714
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有