机器学习-第八章 集成学习

8.1 个体与集成

集成学习是通过构建并结合多个学习器来完成任务。

集成学习的一般结构:一组"个体学习器"通过某种策略将它们结合起来。

集成学习的种类:
1)同质集成
个体学习器通过某种算法训练而成,此时集成中只包含同种类型的个体学习器,这就是同质集成。如,每个个体学习器通过C4.5决策树算法训练而成,最终组成"决策树集成";再如"神经网络集成"中都是神经网络。
同质集成中的个体学习器称为"基学习器",相应算法称为"基学习算法"。
2)异质集成
集成中包含不同算法训练而成的个体学习器,如集成中同时包含决策树和神经网络,这样的集成就是异质集成。异质集成中的个体学习器称为"组件学习器"

集成学习示意图

要获得好的集成,个体学习器应当"好而不同"
"好"即个体学习器要有一定的"准确性",不能太差;
"不同"即要有"多样性",学习器之间要有差异。

举一个例子:在二分类任务中,假定三个分类器(h)在三个测试样本的表现如下,其中√表示分类正确,×表示分类错误,集成学习的结果通过"少数服从多数"的原则产生。
集成中的学习器应好而不同

图a中,每个分类器h的精度是66.6%,但是集成中的精度提升到100%;图b中,每个分类器的结果都是一样的,因此集成中没有变化;图c中,每个分类器的精度只有33.3%,集成中的精度降低为0。从上面可以看出,图a的三个分类器满足了"好而不同","好"即有66.6%的精度,"不同"即每个分类器的结果不同;而图b虽然"好",但是分类器结果相同;图c虽然结果不同,但是精度太低。

假设基学习器的误差相互独立,则集成的错误率为

从集成错误率中可以看出,个体学习器的数目T越大,集成错误率越低,直至为0。

然而,现实中,基学习器不是相互独立的,所以个体学习器的"准确性"和"多样性"本身就存在冲突。一般的,准确性很高之后,要增加多样性就需牺牲准确性。

如何产生结合"好而不同"的个体学习器,是集成学习研究的核心。

  • 对于产生好而不同的学习器的方式
    根据个体学习器的生成方式,目前的集成学习方法大致可分为两大类:
    第一类:个体学习器问存在强依赖关系、必须串行生成的序列化方法。代表是Boosting
    第二类:个体学习器间不存在强依赖关系、可同时生成的并行化方法。代表是Bagging"随机森林" (Random Forest)

  • 结合学习器的方式。
    1)平均法
    2)投票法
    3)学习法

上面的产生和结合方式将在下面讲到。

8.2 Boosting

弱学习器常指泛化性略优于随机猜测的学习器。
例如在二分类问题上精度略高于50%的分类器目。

Boosting是可以将弱学习器提升为强学习器的算法。
Boosting主要关住降低偏差,因此Boosting能基于泛化性能相当弱的学习器构建出很强的集成。

工作机制:
先从初始训练集训练出一个基学习器;
再根据基学习器的表现对训练样本分布进行调整,使得先前基学习器做错的训练样本的权重变高,在后续受到更多关注;
然后基于调整权重后的样本分布来训练下一个基学习器;
如此重复进行,直至基学习器数目达到事先指定的值T;
最终将这T个基学习器进行加权结合。

Boosting工作机制示意图

关于Boosting的两个核心问题:
1)每一轮如何改变训练数据的权值或概率分布?
通过提高那些在前一轮被弱分类器分类错误样例的权值,减小前一轮分类正确样例的权值,来使得分类器对误分的数据有较好的效果。

2)通过什么方式来组合弱分类器?
通过加法模型将弱分类器进行线性组合

Boosting族中最著名的是AdaBoost算法。
刚开始训练时对每一个训练例赋相等的权重,然后用该算法对训练集训练t轮,每次训练后,对训练失败的训练例赋以较大的权重,也就是让学习算法在每次学习以后更注意学错的样本,从而得到多个预测函数。通过拟合残差的方式逐步减小残差,将每一步生成的模型叠加得到最终模型。

y∈{-1,1},f(x)是真实(值)函数。
AdaBoost算法流程

以下是AdaBoost的推导

基于基学习器的线性组合,来最小化指数损失函数

基学习器的线性组合
指数损失函数
使用指数损失函数是因为其具有可微的、较好的数学性质。

第一个基学习器h1是通过基学习算法用于初始数据发布获得。
之后迭代产生αt和ht,当学习器ht基于发布Dt产生后,ht的权重αt,要使得αtht最小化指数损失函数。对于每个αtht有,

每个基学习器的指数损失函数
因为权重αt,要使得指数损失函数最小,因此对权重令偏导为0,得
得到Ht-1集成之后,样本分布需要调整,使得学习器ht能纠正Ht-1的错误。理想的ht能纠正Ht-1的全部错误,即最小化指数损失函数。如下

推导之后,可以再次巩固AdaBoost算法的流程。
算法流程:https://blog.csdn.net/qq_37960402/article/details/88426900

AdaBoost的例题

AdaBoost算法的实现代码

import pdb
import numpy as np
import operator
import math
def dataset():
    data=[0,1,2,3,4,5,6,7,8,9]
    labels=[1,1,1,-1,-1,-1,1,1,1,-1]
    return data,labels


def mytree(data,label,D1):    #生成最优决策树
    point=(np.array(data[:-1])+np.array(data[1:]))/2   #取data中相邻两者之间的平均值
    dic={}
    sign={}
    for i in point:      #遍历平均值
        predict1=np.array(data<i)       #判断左边为1
        predict1=(predict1+0)+(predict1-1)    #将结果转换为[1,-1]
        result1=sum(abs(predict1-label)/2*D1)  #误差

        predict2 = np.array(data > i)    #判断右边为1
        predict2 = (predict2 + 0) + (predict2 - 1)
        result2 = sum(abs(predict2 - label) / 2 * D1)
        if  result1<=result2:   #保存符号和左右边哪个结果更好
            dic[i]=result1
            sign[i]='<'
        else:
            dic[i]=result2
            sign[i]='>'
    bestpoint = sorted(dic.items(),key=operator.itemgetter(1))
    return bestpoint[0],sign[bestpoint[0][0]]



def Zm1(label,Gm,a,D1):   #返回当前样本的权重
    sum=0
    for i in range(len(label)):
        sum+=D1[i]*math.e**(-a*label[i]*Gm[i])
    newD1=[]
    for i in range(len(label)):
        w=D1[i]/sum*math.e**(-a*label[i]*Gm[i])
        newD1.append(w)
    return newD1


def adaboot1():
    data,label=dataset()           #获取数据集和标签文件
    D1=[1/len(data)]*len(data)     #求每一个样本的初始权重,0.1
    bestpoint=[]                   #保存目前最佳的分割点
    besta=[]                       #保存每一棵基决策树对应的权重
    signall=[]                       #保存每一个最佳分割点对应的符号(大于或小于)
    result=[]                         #保存每个基决策树对样本分类的结果
    for i in range(20):
        ht,sign=mytree(data,label,D1)   #当前最好的树
        signall.append(sign)            #保存记号
        bestpoint.append(ht[0])         #保存当前最佳分割点
        if sign==str('>'):
            Gm= np.array(data > ht[0])
            Gm = (Gm+0) + (Gm-1)
        else:
            Gm= np.array(data < ht[0])
            Gm = (Gm+ 0) + (Gm- 1)       #样本带入树中得到当前样本结果

        a=0.5*(math.log((1-ht[1])/ht[1]))    #通过误差计算得到基决策树权值
        besta.append(a)
        result.append(Gm)
        D1=Zm1(label,Gm,a,D1)                #计算得到每个样本点的权值

        sum1=[0]*len(data)              #以下循环计算当前结果是否达到最优
        for i in range(len(result)):
            sum1+=result[i]*besta[i]     #result=w1f(x1)+w2f(x2)+..
        sum1 = np.array(sum1>=0)
        sum1 = (sum1 + 0) + (sum1- 1)

        if sum(sum1==label)==len(data):    #如果结果相等,则输出以下语句
            print("一种生成{}棵基函数".format(len(result)))
            for i in range(len(result)):
                dic = {}
                print ("第{}棵决策树是".format(i+1))
                if signall[i]==str('>'):
                    dic['num'+'>' + str(bestpoint[i])]=1
                    dic['num'+'<' + str(bestpoint[i])] = -1
                if signall[i] == str('<'):
                    dic['num'+'<' + str(bestpoint[i])] = 1
                    dic['num'+'>' + str(bestpoint[i])] = -1
                print(dic)
                print ("权值是{}".format(besta[i]))
                print()
            break

adaboot1()

代码来源:https://blog.csdn.net/qq_37960402/article/details/88539253

8.3 Bagging与随机森林

为了提高泛化能力,要尽可能使基学习器相对独立,对训练样本进行采样以产生若干个不同的子集,对每一个子集训练一个基学习器;又为了进行有效的学习获得较好的集成,子集不能完全不同,因此使用子集之间相互有交叠的采样方法。

1. Bagging

bagging 是一种个体学习器之间不存在强依赖关系、可同时生成的并行式集成学习方法。

bagging基于自助采样法(bootstrap sampling),即给定包含m个样本的数据集,先随机从样本中取出一个样本放入采样集中,再把该样本返回初始数据集,使得下次采样时该样本仍可以被选中。这样,经过m次随机采样,就可以得到包含m个样本的采样集,初始数据集中有的样本多次出现,有的未出现。训练集中约有63.2%的样本出现在采样集中。

上面的操作进行T次得到T个每个含m个样本的采样集,基于每个采样集训练一个基学习器,一共训练出T个,再将基学习器进行组合。这就是Bagging的基本流程。在对输出进行预测时,Bagging通常对分类进行简单投票法,对回归使用简单平均法。在分类中,若出现票数相同的情况,则随机取一个。

Bagging的基本流程

Bagging的优点:

  • Bagging 是一个很高效的集成学习算务。
  • 与标准 AdaBoost 只适用于二分类任务不间,Bagging能不经修改地用于多分类、回归等任务。
  • 每个基学习器使用63.2%的数据,所以剩下36.8%的数据可以用来做验证集来对泛化性能进行“包外估计”(out-of-bag estimate)。
    进行包外估计,需要记录每个基学习器所使用的样本。
    令Dt表示ht实际使用的训练样本集,令Hoob(x)表示对样本x的包外预测,即仅考虑剩余未使用的x训练的基学习器在x上的预测
    包外样本(剩余的样本)有其他用途
    当基学习器是决策树时,可以使用包外样本来辅助剪枝;
    当基学习器是神经网络,可用包外样本来辅助早停以减少过拟合。

从偏差-方差的角度来说,boosting主要关注减小偏差,而Bagging主要关注降低方差,也就说明boosting在弱学习器上表现更好,而降低方差可以减小过拟合的风险,所以Bagging通常在强分类和复杂模型上表现得很好。举个例子:bagging在不减枝决策树、神经网络等易受样本扰动的学习器上效果更为明显。

2. 随机森林

随机森林是Bagging算法的进化版,对bagging进行了改进。
随机森林RF以决策树为基学习器构建Bagging集成的基础上,进一步在决策数训练过程中引入了随机属性选择。

具体来说,传统决策树在选择划分属性时是在当前结点的属性集合(假定有d个属性)中选择一个最优属性;
而在RF中,对基决策树的每个结点,先从该结点的属性集合中随机选择一个包含k个属性的子集,然后再从子集中选择一个最优属性用于划分。

k描述了随机性的引入程度。若k=d,则决策树的构建与传统决策树相同;若k=1,则随机选择一个属性用于划分;一般情况,k=long2d。

RF的优点
随机森林中基学习器的多样性不仅来自样本扰动,还来自属性扰动,这就使得最终集成的泛化性能可通过个体学习器之间差异度的增加而进一步提升。

RF与Bagging的比较

两者的收敛性相似,但RF的起始性能相对较差,特别只有一个基学习器时。随着基学习器数量的增加,随机森林通常会收敛到更低的泛化误差。随机森林的训练效率常优于Bagging,因为Bagging是“确定型”决策树,而随机森林使用“随机型”决策树。

8.4 结合策略

通过上面对个体学习器产生的方式了解之后,我们来看一下个体学习器的结合。
结合有以下三个好处:
1)结合多个学习器可以提升泛化性能。
2)多个学习器结合可以降低陷入槽糕局部极小点的风险。
3)结合多个学习器,可以扩大假设空间,学得更好的近似。

结合策略如下
假定集成包含T个基学习器{h1,h2,……,hT},其中hi在样例x上的输出为hi(x)。

1. 平均法

数值型输出hi(x)∈R,常用的是平均法。

  • 简单平均法
  • 加权平均法


    加权平均法不一定优于简单平均法。一般在个体学习器性能相差较大时宜使用加权平均法,而在个体学习器性能相近时宜使用简单平均法。

2. 投票法

对分类来说,学习器hi将从类别集合C={c1,c2,……,cN}中预测出一个类别标记,最常用的是投票法。为便于讨论,我们将hi在样本x上的预测输出表示为一个N维向量(hi1(x),hi2(x),……,hiN(x)),其中hij(x)是hi在类别标记cj上的输出。

  • 绝对多数投票法
  • 相对多数投票法
  • 加权投票法

3. 学习法

当数据很多时,可以通过另一个学习器来结合,即学习法。其中典型代表为Stacking,在stacking中我们把个体学习器称为初级学习器,用于结合的学习器称为次学习器或者元学习器。

Stacking的主要思想为:先从初始数据集训练出初级学习器,然后“生成”一个新的数据集用于训练次级学习器。生成的新数据中,初级学习器的输出被当做样例输入特征而初始样本的标记仍被当做样例标记。

在训练阶段,次级学习器的训练数据集是利用初级学习器来产生的,若直接用初级学习器的训练集来产生训练数据集,则很有可能会出现过拟合;所以一般在使用Stacking时,采用交叉验证或留一法的方式,用训练初级学习器未使用的样本来产生次级学习器的训练样本。
如以k折交叉验证法为例。初始训练集D被随机分为k个大小相同的子集D1,D2,……,Dk。令Dj和D^j=D/Dj(Dj的补集)分别表示第j折的测试集训练集
给定T个初级学习算法,初级学习器htj 在训练集D^j 上使用第t个学习算法而得。对测试集Dj中每个样本xi,令zit=htj(xi),即xi在初始学习器ht上的输出记为zit,则由xi产生的次级训练集的样例部分为zi=(zi1,zi2,……,ziT),而标记部分为yi。那么在整个过程结束之后,从T个初级学习器产生的次级训练集就是D'={(zi,yi)}mi=1,最后将次级训练集用于训练次级学习器。

8.5 多样性

1. 误差-分歧分解

上面的推导只适用于回归学习,难以推广到分类学习。

2. 多样性度量

多样性度量(diversity measure)是用于度量集成中个体分类器的多样性,即估算个体学习器的多样化程度。

  • 不合度量


  • 相关系数


  • Q-统计量


  • k-统计量


3. 多样性增强

增强多样性的方法有:

  • 数据样本扰动
    给定初始数据集,可从中产生出不同的数据子集,再利用不同的数据子集训练出不同的个体学习器。如boosting 和bagging,这种方法对“不稳定学习器”(例如,决策树,神经网络)很有效。对于稳定基学习器,如 线性学习器,支持向量机,朴素贝叶斯往往使用输入属性扰动。
  • 输入属性扰动
    训练样本通常由一组属性描述,不同的“子空间”提供了观察数据的不同视角。从不同子空间训练出的个体学习器必然有所不同。子空间一般指从初始的高维属性空间投影产生的低维属性空间。若数据只包含少量属性,或者冗余属性很少,则不宜使用输入属性扰动法.
  • 输出表示扰动
    基本思路是对输出表示进行操纵以增强多样性。可对训练样本
    的类标记稍作变动,如翻转法(Flipping Output),随机改变一些训练样本的标记;也可对输出表示进行转化,如“输出调制法”(Output Smearing)。
  • 算法参数扰动
    通过随机设置不同的参数可以产生不同的基学习器。对参数较少的算法,可通过将其学习过程中某些环节用其他类似方式代替?从而达到扰动的目的,例如可将决策树使用的属性选择机制替换成其他的属性选择机制。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,539评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,911评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,337评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,723评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,795评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,762评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,742评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,508评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,954评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,247评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,404评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,104评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,736评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,352评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,557评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,371评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,292评论 2 352

推荐阅读更多精彩内容