机器学习之集成学习——《机器学习》周志华著


智能控制与优化决策课题组制作。
对应周志华《机器学习》第七章内容。

1.谈谈集成学习的概念和思想。

集成学习是将若干个弱分类器通过一定的策略组合之后产生一个强分类器。弱分类器指的是分类准确率只比随机猜测略好一点的分类器。强分类器的分类准确率会高很多,这里的“强”和“弱”是相对的。
其思想可以表达如下:
在这里插入图片描述
集成学习的主要思路是先通过一定的规则生成多个学习器,再采用某种集成策略进行组合,最后综合判断输出最终结果。要获得好的集成,个体学习器应该“好而不同”,要有一定的“准确性”,即学习器不能太坏,并且要有多样性,之间具有差异。互为补充,才可提升效果。集成学习可以显著的提高学习系统的泛化能力。
几种常见的结合策略:
1、平均法——数值型输出常用结合策略

  • 简单平均法
  • 加权平均法,要求权重非负且和为1

2、投票法——分类

  • 绝对多数投票法—若某标记得票过半,则预测为该标记;否则拒绝预测。(在可靠性要求较高的学习任务中很有效)
  • 相对多数投票法—预测为得票最多的标记,若同时有多个标记获得最高票,则从中随机选取一个。
  • 加权投票法—要求权重非负且和为1

2.集成学习方法可以分为哪几类,并且分别阐述它们的特点。

集成学习方法可以分为Bagging和Boosting,它们的特点如下:

1)样本选择上:

Bagging:训练集是在原始集中有放回选取的,从原始集中选出的各轮训练集之间是独立的。

Boosting:每一轮的训练集不变,只是训练集中每个样例在分类器中的权重发生变化。而权值是根据上一轮的分类结果进行调整。

2)样例权重:

Bagging:使用均匀取样,每个样例的权重相等

Boosting:根据错误率不断调整样例的权值,错误率越大则权重越大。

3)预测函数:

Bagging:所有预测函数的权重相等。

Boosting:每个弱分类器都有相应的权重,对于分类误差小的分类器会有更大的权重。

4)并行计算:

Bagging:各个预测函数可以并行生成

Boosting:各个预测函数只能顺序生成,因为后一个模型参数需要前一轮模型的结果。

3.在集成学习中,阐述针对二分类问题的AdaBoost算法实现过程。思考AdaBoost算法在每一轮如何改变训练数据的权值或概率分布?

相关符号定义:

  • D m D_{m} Dm:训练样本集的权值分布;
  • w 1 i w_{1i} w1i:每个训练样本的权值大小;
  • G m ( x ) G_{m}(x) Gm(x):基本分类器;
  • G ( x ) G(x) G(x):最终的分类器;
  • e m e_{m} em:误差率
  • a m a_{m} am:弱分类器的权重

给定一个训练数据集 T = ( x 1 , y 1 ) , ( x 2 , y 2 ) … ( x N , y N ) T={(x_{1},y_{1}), (x_{2},y_{2})…(x_{N},y_{N})} T=(x1,y1),(x2,y2)(xN,yN),其中实例 x ∈ X x\in X xX,而实例空间 X ∈ R n X\in \mathbb{R}^{n} XRn y i y_{i} yi属于标记集合{-1,+1},Adaboost的目的就是从训练数据中学习一系列弱分类器或基本分类器,然后将这些弱分类器组合成一个强分类器。

Adaboost的算法流程如下:

  • 步骤1. 首先,初始化训练数据的权值分布。每一个训练样本最开始时都被赋予相同的权值:1/N。
    在这里插入图片描述
  • 步骤2. 进行多轮迭代,用m = 1,2, …, M表示迭代的第多少轮
    a. 使用具有权值分布 D m D_{m} Dm的训练数据集学习,得到基本分类器(选取让误差率最低的阈值来设计基本分类器):
    在这里插入图片描述
    b. 计算 G m ( x ) G_{m}(x) Gm(x)在训练数据集上的分类误差率
    在这里插入图片描述
    由上述式子可知, G m ( x ) G_{m}(x) Gm(x)在训练数据集上的误差率 e m e_{m} em就是被 G m ( x ) G_{m}(x) Gm(x)误分类样本的权值之和。
    c. 计算基本分类器在最终分类器中所占的权重
    a m = 1 2 l n 1 − e m e m a_{m}=\frac{1}{2}ln\frac{1-e_{m}}{e_{m}} am=21lnem1em
    由上述式子可知, e m ⩽ e_{m} \leqslant em时, a m ⩾ 0 a_{m} \geqslant0 am0,且 a m a_{m} am随着 e m e_{m} em的减小而增大,意味着分类误差率越小的基本分类器在最终分类器中的作用越大。
    d. 更新训练数据集的权值分布(目的:得到样本的新的权值分布),用于下一轮迭代
    在这里插入图片描述
    使得被基本分类器 G m ( x ) G_{m}(x) Gm(x)误分类样本的权值增大,而被正确分类样本的权值减小。就这样,通过这样的方式,AdaBoost方法能“重点关注”或“聚焦于”那些较难分的样本上.其中, Z m Z_{m} Zm是规范化因子,使得 D m + 1 D_{m+1} Dm+1成为一个概率分布:
    在这里插入图片描述
  • 步骤3. 组合各个弱分类器
    在这里插入图片描述
    从而得到最终分类器,如下:
    在这里插入图片描述

在这里插入图片描述
提高那些被前一轮弱分类器错误分类样本的权值,而降低那些被正确分类样本的权值。采取这种操作可以使那些没有得到准确分类的数据由于其权值的加大而受到后一轮的弱分类器的更多关注,从而改变在每一轮训练数据的权值或概率分布。
原文:https://blog.csdn.net/v_JULY_v/article/details/40718799

4.随机森林与集成学习之间有什么样的关系?

随机森林的基本思想是用随机的方式建立一个森林,通过自助法(bootstrap)重采样技术,从原始训练样本集 N N N中有放回地重复随机抽取 k k k个样本生成新的训练样本集合,然后根据自助样本集生成 k k k个分类树组成随机森林。森林里面有很多的决策树组成,随机森林的每一棵决策树之间是没有关联的。在得到森林之后,当有一个新的输入样本进入的时候,就让森林中的每一棵决策树分别进行一下判断,看看这个样本应该属于哪一类(对于分类算法),然后看看哪一类被选择最多,就预测这个样本为那一类。这也是集成学习中的一个基本思路。
随机森林在以决策树为基学习器,构建Bagging的基础上,进一步在决策树的训练过程中引入了随机属性选择。Bagging是集成学习框架下的一个很大的门类,所以随机森林从结构上来讲是属于集成学习的。随机森林就是通过集成学习的思想将多棵树集成的一种算法,它的基本单元是决策树,而它的本质属于集成学习方法。

5. 用python实现基于单层决策树的AdaBoost算法

5.1算法实现伪代码

for i from(1,2,…,M)
1)找出最佳单层决策树:
将最小分类误差率min error=inf
对数据集中的每一个特征:
对该特征的每个步长(找出决策阈值):
对每个不等号 ( &gt; = , &lt; ) (&gt;=,&lt;) >=,<:
建立一颗单层决策树(只包含树桩)并利用加权数据集并计算该决策树的分类误差率
如果分类误差率小于minerror,则将当前单层决策树设置成最佳单层决策树。
2)利用单层决策树的分类误差率计算该决策树的比例系数 α \alpha α
3)计算更新权重向量 D D D
4)更新累计类别估计值,计算AdaBoost模型的错误率
5)如果错误率为0或者分类器数目 i &gt; M i&gt;M i>M,则退出循环

5.2 python 实现代码

// An highlighted block
import numpy as np

def loadSimData():
    '''
    输入:无
    功能:提供一个两个特征的数据集
    输出:带有标签的数据集
    '''
    datMat = np.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

def stumpClassify(dataMatrix,dimen,thresholdValue,thresholdIneq):
    '''
    输入:数据矩阵,特征维数(第几个特征),某一特征的分类阈值,分类不等号(标志)
    功能:输出决策树桩标签---单层决策树分类函数
    输出:标签
    '''
    returnArray =  np.ones((np.shape(dataMatrix)[0],1))
    if thresholdIneq == 'lt':
        returnArray[dataMatrix[:,dimen] <= thresholdValue] = -1#小于阈值,赋值为-1
    else:
        returnArray[dataMatrix[:,dimen] > thresholdValue] = -1#大于阈值,赋值为-1
    return returnArray#分类结果

def buildStump(dataArray,classLabels,D):
    '''
    输入:数据矩阵,标签矩阵,特征的权值分布
    功能:在数据集上,找到加权错误率(分类错误率)最小的单层决策树,在数据集上找到最佳的单层决策树
    输出:最佳树桩(特征,分类特征阈值,不等号方向),最小加权错误率,该权值向量D下的分类标签估计值
    '''
    dataMatrix = np.mat(dataArray); 
    labelMat = np.mat(classLabels).T
    m,n = np.shape(dataMatrix)#m样本个数 n为特征个数
    stepNum = 10.0;#初始化一个步数
    bestStump = {}; #用字典储存树桩信息
    bestClassEst = np.mat(np.zeros((m,1)))#初始化分类结果为1
    minError = np.inf#最小误差初始化为无穷大
    for i in range(n):#遍历所有特征
        rangeMin = dataMatrix[:,i].min(); #找到特征中最小值
        rangeMax = dataMatrix[:,i].max() #找到特征中最大值
        stepSize = (rangeMax - rangeMin)/stepNum#计算步长
        for j in range(-1, int(stepNum)+1):
            for thresholdIneq in ['lt', 'gt']:#大于和小于的情况均遍历
                thresholdValue =  rangeMin + float(j) * stepSize#计算阈值
                predictClass = stumpClassify(dataMatrix,i,thresholdValue,thresholdIneq)#计算分类结果
                errArray =  np.mat(np.ones((m,1)))#初始化误差矩阵
                errArray[predictClass == labelMat] = 0#分类正确 赋值为0
                weightError = D.T * errArray#计算误差
                #print "split: dim %d, thresh: %.2f,threIneq:%s,weghtError %.3F" %(i,thresholdValue,thresholdIneq,weightError)
                if weightError < minError:#找到误差最小的分类方式
                    minError = weightError
                    bestClassEst = predictClass.copy()
                    bestStump['dimen'] = i#特征列
                    bestStump['thresholdValue'] = thresholdValue#阈值
                    bestStump['thresholdIneq'] = thresholdIneq#标志
    return bestClassEst, minError, bestStump

def adaBoostTrainDS(dataArray,classLabels,numIt=40):
    '''
    输入:数据集,标签向量,最大迭代次数
    功能:创建adaboost加法模型
    输出:多个弱分类器的数组
    '''
    weakClass = []#定义弱分类数组,保存每个基本分类器bestStump
    m,n = np.shape(dataArray)
    D = np.mat(np.ones((m,1))/m)#初始化权重
    aggClassEst = np.mat(np.zeros((m,1)))
    for i in range(numIt):
        print("i:",i)
        bestClassEst, minError, bestStump = buildStump(dataArray,classLabels,D)#step1:找到最佳的单层决策树
        print("D.T:", D.T)
        alpha = float(0.5*np.log((1-minError)/max(minError,1e-16)))#step2: 计算分类器权重alpha
        print("alpha:",alpha)
        bestStump['alpha'] = alpha
        weakClass.append(bestStump)#step3:将基本分类器添加到弱分类的数组中
        print("classEst:",bestClassEst)
        expon = np.multiply(-1*alpha*np.mat(classLabels).T,bestClassEst)#计算e的指数项
        D = np.multiply(D, np.exp(expon))
        D = D/D.sum()#step4:更新权重,该式是让D服从概率分布
        aggClassEst += alpha*bestClassEst#step5:更新累计类别估计值
        print("aggClassEst:",aggClassEst.T)
        print(np.sign(aggClassEst) != np.mat(classLabels).T)
        aggError = np.multiply(np.sign(aggClassEst) != np.mat(classLabels).T,np.ones((m,1)))#计算误差
        print("aggError",aggError)
        aggErrorRate = aggError.sum()/m
        print("total error:",aggErrorRate)
        if aggErrorRate == 0.0: break#误差为0退出循环
    return weakClass

def adaTestClassify(dataToClassify,weakClass):
    dataMatrix = np.mat(dataToClassify)        
    m =np.shape(dataMatrix)[0]
    aggClassEst = np.mat(np.zeros((m,1)))
    for i in range(len(weakClass)):
        classEst = stumpClassify(dataToClassify,weakClass[i]['dimen'],weakClass[i]['thresholdValue']\
                                 ,weakClass[i]['thresholdIneq'])
        aggClassEst += weakClass[i]['alpha'] * classEst
        print(aggClassEst)
    return np.sign(aggClassEst)
if __name__  ==  '__main__':
    D =np.mat(np.ones((5,1))/5)
    dataMatrix ,classLabels= loadSimData()
    bestClassEst, minError, bestStump = buildStump(dataMatrix,classLabels,D)
    weakClass = adaBoostTrainDS(dataMatrix,classLabels,9)            
    testClass = adaTestClassify(np.mat([0,0]),weakClass)

结果:

// An highlighted block
i: 0
D.T: [[0.2 0.2 0.2 0.2 0.2]]
alpha: 0.6931471805599453
classEst: [[-1.]
 [ 1.]
 [-1.]
 [-1.]
 [ 1.]]
aggClassEst: [[-0.69314718  0.69314718 -0.69314718 -0.69314718  0.69314718]]
[[ True]
 [False]
 [False]
 [False]
 [False]]
aggError [[1.]
 [0.]
 [0.]
 [0.]
 [0.]]
total error: 0.2
i: 1
D.T: [[0.5   0.125 0.125 0.125 0.125]]
alpha: 0.9729550745276565
classEst: [[ 1.]
 [ 1.]
 [-1.]
 [-1.]
 [-1.]]
aggClassEst: [[ 0.27980789  1.66610226 -1.66610226 -1.66610226 -0.27980789]]
[[False]
 [False]
 [False]
 [False]
 [ True]]
aggError [[0.]
 [0.]
 [0.]
 [0.]
 [1.]]
total error: 0.2
i: 2
D.T: [[0.28571429 0.07142857 0.07142857 0.07142857 0.5       ]]
alpha: 0.8958797346140273
classEst: [[1.]
 [1.]
 [1.]
 [1.]
 [1.]]
aggClassEst: [[ 1.17568763  2.56198199 -0.77022252 -0.77022252  0.61607184]]
[[False]
 [False]
 [False]
 [False]
 [False]]
aggError [[0.]
 [0.]
 [0.]
 [0.]
 [0.]]
total error: 0.0
[[-0.69314718]]
[[-1.66610226]]
[[-2.56198199]]

结果分析:通过三次迭代之后,错误率为0,停止迭代,随着迭代的进行,数据点[0,0]的分类结果也越来越强。
原文:https://blog.csdn.net/LY_ysys629/article/details/72842067

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值