机器学习实战—集成学习

2023-11-11

一.简介

1.1 集成学习

一群人的智慧总是比一个人强,这就是集成学习的核心思想。如果你聚合一组预测器(比如分类器或回归器)的预测,得到的预测结果也比最好的单个预测器要好。这样的一组预测器称为集成,这种技术也叫集成学习。

1.2 随机森林

我们训练一组决策树分类器,每一棵树都基于训练集不同的随机子集进行训练。做出预测时,只需要获得所有树各自的预测,然后得票最多的类别作为预测结果。这样一组决策树的集成被称为随机森林,随机森林是迄今可用的最强大的机器学习算法之一。

二.集成学习—投票分类器

2.1 概念

如果我们已经训练好了一些分类器,并且每个分类器的准确率都比较客观,为了创建一个更好的分类器,最简单的方法就是聚合每个分类器的预测,然后将的票最多的结果作为预测类别。这种大多数投票分类器称为硬投票分类器。事实上,即使每个分类器都是弱学习器(意味着它的的预测效果只比随机预测好一点),通过集成依然可以实现一个强学习器

当预测器尽可能相互独立时,集成方法的效果最优。获得多种分类器的方法之一就是使用不同的算法进行训练(例如逻辑回归、SVM、Knn等)。这会增加它们犯不同类型错误的机会,从而提高集成的准确率。

2.2 代码实现

使用到了随机森林、SVM和逻辑回归来集成一个投票分类器

from sklearn.ensemble  import RandomForestClassifier  #随机森林分类器
from sklearn.ensemble  import VotingClassifier  #投票分类器
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
iris=load_iris()  #加载数据集
X_train, X_test, Y_train, Y_test = train_test_split(iris.data, iris.target, test_size=0.3,  random_state=42)
log_clf=LogisticRegression()  #逻辑回归评估
rnd_clf=RandomForestClassifier()
svm_clf=SVC()
voting_clf=VotingClassifier(
 estimators=[('lr',log_clf),('rf',rnd_clf),('svc',svm_clf)],
 voting='hard'  #硬投票#
)
voting_clf.fit(X_train,Y_train)
print(clf.__class__.__name__,accuracy_score(Y_test,voting_clf.predict(X_test)))

结果输出为预测准确率(预测全对为1)
在这里插入图片描述

如果voting='hard’表示为voting='soft’这时候我们的硬投票分类器就变成了软投票分类器,从前面我们知道硬投票分类器是选择具有最高票数类的集合(如果有三个投票器中有两个认为当前水果是苹果,一个认为是橘子,则苹果的票最多所以硬投票法会认为当前水果是苹果),而软投票分类器下每个分类器会计算出类别的概率,然后将概率在所有单分类器上平均,最后选出平均概率最高的类作为预测(同样我们有两个个分类器,分类器 1 以 40% 的概率预测对象是一块苹果,而分类器2 以 60% 的概率预测它是一个苹果,那么软投票分类器会认为有(40%+60%)/2=50%的概率认为这个水果上苹果,最后软投票器会选择平均概率最高的类别)

三.集成学习—bagging和pasting

3.1 简介

前面介绍投票分类器时我们获得不同分类器来集成学习的第一种方法,即直接使用不同的算法。现在介绍的另一种思想就是对于每个预测器都使用相同的机器学习算法,但是在不同的训练集的子集上训练(注意子集的选择上随机的)。在对于子集的不同的选取方式(下面我们会称为抽样方式)的不同,我们可以将抽样方式分为两种类型:

  1. bagging方法(bootstrap aggregating),也叫做自举汇聚法,采样时样本放回(即原训练集不会发生变化),下一个预测器继续抽样
  2. pasting方法,采样时样本不放回(即原训练集变小了),下一个预测器继续抽样

在这里插入图片描述

采用bagging和pasting方法,没可以通过不同的CPU内核甚至不同的服务器并行地训练预测器,类似的预测同样也是可以并行的,这就是bagging和pasting方法如此流行的原因,它是非常易于扩展的。

3.2 Scikit-Learn中使用bagging和pasting

下面使用了BaggingClassifier类解决分类问题,预测器使用的机器学习算法是决策树算法

from sklearn.ensemble import BaggingClassifier
from sklearn.tree import DecisionTreeClassifier
bag_clf=BaggingClassifier(DecisionTreeClassifier(),n_estimators=500,max_samples=100,bootstrap=True,n_jobs=-1)
bag_clf.fit(X_train,Y_train)
y_pred=bag_clf.predict(X_test) 

n_estimators=500:表示有500个决策树分类器
max_samples=100:表示每次从训练实例中选取100个实例进行训练
如果基本的预测器都可以估计类别预测(即有predict_proba()方法),则BaggingClassifier会自动使用软投票机制(如果要使用pasting,则将bootstrap=false就行)

3.3 包外评估

  1. 简介

对于bagging采样方法,我们每次采样都会将样本放回原来的训练集,所以对于每个预测器抽样基于训练集的大小都是一样的,如果我们每次采样的比例假如我们都只采用60%,那么对于每个预测器都会剩下40%的实例没有使用到,这样的实例我们称为包外实例(oob),因此我们可以直接将每个预测器模型在这没使用到的40%的数据上进行评估,而无需再单独的区设置验证集来进行评估,这种思想我们就叫做包外评估。

  1. API使用

在Scikit-Learn中,我们创建BaggingClassfier时,设置oob_score=TRUE我们就可以使用包外评估了

from sklearn.metrics import accuracy_score
bag_clf=BaggingClassifier(DecisionTreeClassifier(),n_estimators=500,bootstrap=True,n_jobs=1,oob_score=True)
bag_clf.fit(X_train,Y_train)
y_pred=bag_clf.predict(X_test)
accuracy_score(Y_test,y_pred)

3.4 随机补丁和随机子空间

BaggingClassifier类也支持对特征进行采样(针对实例的特定的某个或某些特征进行采样),采用由两个超参数控制:max_features和bootstrap_features,由于是特征采样,因此每个预测器将用输入特征的子集(随机的)进行训练。

  1. 随机补丁方法:对训练实例和特征都进行采样(只选取一部分实例的部分特征)
  2. 随机子空间法:保留所哟的训练实例但对特征进行抽样(选取所有实例的部分特征)
from sklearn.ensemble import BaggingClassifier
from sklearn.tree import DecisionTreeClassifier
X_train, X_test, Y_train, Y_test = train_test_split(iris.data[:,2:], iris.target, test_size=0.3,  random_state=42)
bag_clf=BaggingClassifier(DecisionTreeClassifier(),n_estimators=500,max_features=2,
                          bootstrap_features=iris.feature_names[2:],bootstrap=True,n_jobs=-1)
bag_clf.fit(X_train,Y_train)
y_pred=bag_clf.predict(X_test)  

四.集成学习—随机森林

4.1 简介

前面已经介绍过随机森林就是一群决策树的集成,因此我们可以将随机森林理解为一种特殊的集成学习,(决策树看我这篇博客)。由于是一种集成学习,所以随机森林应该也也有着很多的随机性,在决策树中我们通过不纯度来选择决策边界来分裂节点,但在随机森林中我们分裂节点的方法发生了些许变化,随机森林中的决策树是在随机生成的特征子集里搜索最好的特征,这样随机森林在决策树的生长上有了更多的随机性和多样性,这里用更高的偏差换取了更低的方差(偏差是算法在训练集上的错误率,方差上算法在测试集上的错误率,由于随机森林使得决策树的生长更加随机,所以它对训练数据可能拟合的效果没那么好的,导致偏差上升,但由于其随机性增强这就导致它对测试数据拟合的更好,这就是所谓的方差下降)

4.2 API使用

这里使用的是Scikit-Learn提供的RandomForestClassifier接口

from sklearn.ensemble import RandomForestClassifier
rnd_clf=RandomForestClassifier(n_estimators=500,max_leaf_nodes=16,n_jobs=-1)#n_jobs表示并行的意思,多余决策树之间并行运行
rnd_clf.fit(X_train,Y_train)

上面的代码使用所有的可用的CPU内核(n_jobs=-1),训练了一个拥有500棵树的随机森林分类器(每棵树限制为最多16个椰子树节点)

4.3 极端随机树

在上面我们说到随机树里单棵决策树的生长过程中每个节点的分裂时是选取的随机特征子集中最好的一个特征,如果我们在随机的特征子集中选择的不再是最好的特征而是随机选择一个,这样决策树的增长会更加的随机,这种极端随机的决策树组成的森林称为极端随机树集成。子啊scikit-Learn中使用ExtraTreesClassifier类可以创建一个极端随机树分类器,它的使用方法和RandomForestClassifier的使用方法是一样的。

4.4 特征重要性

在决策树中我们使用CART剪枝训练算法来选择特征设定阈值,而被选择的节点相比于那些没有被选择的节点上更加重要的。而在随机森林中使得测量每个特征的相对重要性变得更加容易,Scikit-Learn通过查看使用该特征的树节点平均减少不纯度(为了要将表格转化为一棵树,决策树需要找出最佳结点和最佳的分枝方法,对分类树来说,衡量这个“最佳”的指标叫做“不纯度”。通常来说,不纯度越低,决策树对训练集的拟合越好)的程度来衡量该特征的重要性,也就是减少的不纯度越多就越重要。

from sklearn.datasets import load_iris
iris=load_iris()
rnd_clf=RandomForestClassifier(n_estimators=500,n_jobs=-1)
rnd_clf.fit(iris["data"],iris["target"])
for name ,score in zip(iris["feature_names"],rnd_clf.feature_importances_):
    print(name,score)

在这里插入图片描述

代码中我们通过rnd_clf.feature_importances_来获取每个特征的重要性,可以看出petal width(cm)是最重要的,并且所有特征重要性分数加起来是1(因为Scikit-learn会在训练后为每个特征自动计算该分数,然后对结果进行缩放以使得所有重要性分数之和为1)

五.集成学习—提升法Boosting

5.1 简介

boosting是指可以将几个弱学习器结合成一个强学习器的任意集成方法。大多数提升法的总体思路是循环训练预测器,每一次都对其前序预测器做出一些改正。

5.2 AdaBoost

AdaBoost是目前最流行的提升法方法,它的思路也是遵循循环训练预测器,新的预测器对其前面的预测器进行纠正的方法之一就是更加关注前序欠拟合的训练实例,这样新的预测器会不断地越来越关注于难缠的问题,这就是AdaBoost技术

在这里插入图片描述

当这种依序学习技术有一个重要的缺陷就是无法并行,因为每个预测器只能在前一个预测器训练完成并评估之后才能开始训练,所以在扩展方面,它的表现不如bagging和pasting方法

5.2 AdaBoost原理解析

  1. AdaBoost算法的初始时会将每个实例权重 w ( i ) w^{(i)} w(i)最初设置为 1 m \frac 1 m m1,然后对第一个预测器进行训练,并根据训练集计算其加权错误率 r 1 r_1 r1,第j个预测器的加权错误率的求法
    r j = ∑ i = 1 m w ( i ) ( y ^ j ( i ) ≠ y ( i ) ) ∑ i = 1 m w ( i ) r_j=\frac {\sum_{i=1}^m w^{(i)}(\hat y_j^{(i)}\neq y^{(i)})} {\sum_{i=1}^m w^{(i)}} rj=i=1mw(i)i=1mw(i)(y^j(i)=y(i))

y ^ j ( i ) \hat y_j^{(i)} y^j(i)是第i个实例的第j个预测器的预测

  1. 预测器的权重这里我们记为 a j a_j aj,它的计算方法如下列公式所示。其中 β \beta β是我们的学习率超参数(默认为1),可以看出我们的预测器越准确( r j r_j rj越小)其权重就越高。

a j = β l o g 1 − r j r j a_j=\beta log \frac {1-r_j} {r_j} aj=βlogrj1rj

  1. 然后AdaBoost算法使用下面公式来更新实例的权重,从而提高了错误分类的实例的权重

对于 i = 1 , 2 , . . . . . , m 对于i=1,2,.....,m 对于i=1,2,.....,m
w ( i ) ← { w ( i ) , 如果 y ^ j ( i ) = y ( i ) w ( i ) e x p ( a j ) w^{(i)}\leftarrow \begin{cases} w^{(i)},如果 \hat y_j^{(i)}=y^{(i)}\\ w^{(i)}exp(a_j)\\ \end{cases} w(i){w(i),如果y^j(i)=y(i)w(i)exp(aj)
4. 然后对所有实例权重进行归一化(除以 ∑ i = 1 m w ( i ) \sum_{i=1}^m w^{(i)} i=1mw(i)
5. 最后使用更新后的权重训练一个新的预测器,然后重复整个过程(计算新预测器的权重,更新实例权重)直到达到所需的预测器或得到完美的预测器时算法结束
a 1 f 1 + a 2 f 2 + . . . + a n f n = F a_1f_1+a_2f_2+...+a_nf_n=F a1f1+a2f2+...+anfn=F

a i a_i ai是我们第i个预测器的权值(计算方法如上), f i f_i fi是我们第i个预测器的预测结果

  1. 最后进行预测,AdaBoost就是简单地计算所有预测器的预测结果,并使用预测器权重 a j a_j aj对他们进行加权,最后得到大多数加权投票的类就是预测器给出的预测类

总结:再看一下AdaBoost算法的思想,其实就是一种“前人栽树,后人乘凉”的思想,通过一次次迭代训练使得预测器越来越强大,在一次次迭代过程中,当前训练的模型只关心前一个训练的模型的错误所在,然后专注于解决这个错误,具体的Adaboost运作流程如下:

  1. 初始化所有的样本的权重为 w ( i ) = 1 m w^{(i)}=\frac 1 m w(i)=m1
  2. 然后利用当前预测器的训练结果更新所有的样本的权重(上面的第3步),对于预测正确的样本我们权重保持不变,对于预测错误的样本我们会增加其权重
  3. 然后基于这个实例权重已经更新的训练集,我们再训练下一个弱预测器(这时会更加关注权重大的样本的,即上一次预测错误的样本的)
  4. 然后迭代上面过程
  5. 最后进行预测

5.3 AdaBoost的API使用

Scikitlearn使用的是AdaBoost的多分类版本,叫做SAMME(基于多类指数损失函数的逐步添加模型),如果使用的预测器可以估算出每类的概率,可以使用SAMME的变体,SAMME.R,它和SAMME不同的是,它依赖的是类概率而不是类预测。

from sklearn.ensemble import AdaBoostClassifier
ada_clf=AdaBoostClassifier(DecisionTreeClassifier(max_depth=1),n_estimators=200,algorithm="SAMME.R",learning_rate=0.5)
ada_clf.fit(X_train,Y_train)

上面代码的决策树的深度为1(max_depth=1,即每棵树只有两个叶子节点),创建了200棵这样的决策树(n_estimators=200),使用的算法是SAMME.R(algorithm=“SAMME.R”),学习率 β \beta β为0.5(learning_rate=0.5)。如果出现过拟合问题我们可以从两个方面下手:

  1. 减少决策树的数量
  2. 对每个决策树进行正则化

5.4 梯度提升

上面上面介绍的AdaBoost算法,提升法中梯度提升算法也是使用非常广泛的,于AdaBoost的原理一样它也是逐步在集成中添加预测器,并对每一个前序预测器的错误进行改正。不同之处在于,他不像AdaBoost那样在每个迭代中调整实例的权重 w w w,而是让新的预测器针对前预测器的残差进行拟合。(残差在数理统计中是指实际观察值与估计值(拟合值)之间的差)

5.5 梯度提升原理

下面的案例是一个简单的回归问题,来解释梯度提升算法的运作原理,使用决策树作为基础预测器,这被称为梯度树提升或者梯度提升回归树(GBRT)

  1. 初始:训练集上训练第一个决策树
from sklearn.tree import DecisionTreeClassifier
tree_reg1=DecisionTreeClassifier(max_depth=2)
tree_reg1.fit(X_train,Y_train)

决策树的深度为2

  1. 第二步:针对第一个预测器的残差训练第二个决策树
y2=Y_train-tree_reg1.predict(X_train)  #计算残差
tree_reg2=DecisionTreeRegressor(max_depth=2)
tree_reg2.fit(X_train,y2)
  1. 第三步:将前面得到的两棵树的预测相加,对性实例进行预测
y_pred=sum(tree.predict(iris.data[2:3,2:]) for tree in(tree_reg1,tree_reg2))
y_pred

以上便是梯度提升的运作原理

5.6 梯度提升API使用

scikit-learn使用的GradientBoostingRegressore类

from sklearn.ensemble import GradientBoostingRegressor
gbrt=GradientBoostingRegressor(max_depth=2,n_estimators=3,learning_rate=1.0)
gbrt.fit(X_train,Y_train)

在这里超参数learning_rate(学习率)对每棵树的贡献进行缩放,其值越小则每棵树的贡献越小,则需要更多的树来拟合训练集,这样同样最后模型的泛化效果会比较好。

总结:介绍完梯度提升我们会发现一个新的问题,就是在使用梯度提升算法时我们如何选择合适的树的数量,这里有两种思路:

  1. 使用提前停止法(提前停止(英语:early stopping)是一种在使用诸如梯度下降之类的迭代优化方法时,可对抗过拟合的正则化方法)
  2. 使用XGBoost(其提供了梯度提升的优化实现)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

机器学习实战—集成学习 的相关文章

随机推荐

  • 计算机学报——主题“区块链”,检索到25篇

    CCF期刊导航https mp weixin qq com s Hu ozQG uoYDLN0jQzUhDQhttps mp weixin qq com s Hu ozQG uoYDLN0jQzUhDQ 按时间排序 序号 篇名 时间 关键词
  • main函数的前序执行过程简单介绍

    main函数的前序执行过程简单介绍 main函数其实是我们能控制的程序入口 但是程序编译之后进行执行却不是从main函数开始的 这里主要讲解下VC6 0 下编译的程序在执行main函数之前的流程 其实主要为在执行main函数之前做了环境变量
  • 光通量发光强度照度亮度关系_买灯只选瓦数?那就大错特错了,灯具亮度选择大有学问...

    一 在装修中 灯光的选择对最终的效果有着非常大的影响 太亮会曝光刺眼 太暗效果也不好 所以选择灯具也变得非常重要了 首先 说一下影响空间亮度的因素有哪些 1 灯具数量 这个起到直接影响因素 在灯具参数一样的情况下 数量多肯定会越亮 反之同理
  • 前端需要懂的nginx

    前言 作为一名前端 我们除了node作为服务以外 我们还有什么选择 那么简单容易上手的Nginx可以满足你的一切幻想 学习nginx可以让我们更加清晰前端项目上线的整个流程 作为一个前端 或多或少都会对Nginx有一些经验 那为什么还要学习
  • ASTreeView Demo:Add, Edit & Delete nodes

  • 主从数据库一致性问题

    原因 数据库集群的主从数据同步存在延时 延迟期间从库上的读请求会读取到不一致的数据 如下图所示 不管同步还是异步 只要存在数据冗余就存在数据一致性问题 解决方案 整体思路 数据库的主从同步可以实现数据的最终一致性 延迟时间一般在几毫秒以内
  • 电路原理 的 一些基础知识

    电容 与 电感 的 伏安特性 电感的伏安特性公式 电容的伏安特性公式 电感 和 电容 元件的串并联 电感串联 电感并联 电容串联 电容并联 RC电路 的 零输入响应 和 零状态响应 零输入响应 零状态响应 RLC串联谐振电路 变压器等效电路
  • 解决问题:Do not know how to handle these types to promote: {‘DoubleTensor‘, ‘FloatTensor‘}

    今天在使用pytorch1 7训练模型 调用apex时出现了该问题 Doubletensor是64位float类型 Floattensor是32位float类型 调试程序发现第二次迭代时 变量v和msd k 的数据类型不同 如图所示 因此在
  • 微信小程序做一个文档预览

    文档预览 首先展示效果 js页面 wxml页面 首先展示效果 图片预览 视频预览 js页面 首先在data中定义变量 itemId null saveTopList 存储顶层文件列表 folderList 存储当前显示的文件列表 showL
  • MachineLearningWu_16/P72-P77_Diagnostic

    x 1 导数 计算图 大型网络 计算图就是根据链式法则求取偏导 大型网络就是多层网络堆叠而成 x 2 Diagnostic 在我们对深度学习有了一些认知后 最重要的就是模型的诊断 以带有L1正则化的线性回归为例 我们需要预测房屋的价格 此时
  • 阿里云服务器配置选择指南(2023新版教程)

    阿里云服务器配置选择 CPU内存 带宽 存储配置 小白指南 阿里云服务器配置选择方法包括云服务器类型 CPU内存 操作系统 公网带宽 系统盘存储 网络带宽选择 安全配置 监控等 阿小云分享阿里云服务器配置选择方法 选择适合自己的云服务器配置
  • 十五个Python经典案例,学会这些,Python基础已过关!

    今天给大家搜集了十五道Python的经典案例 希望各位都能学会 不懂得大家可以在加群在群里发消息问问题 想要资料的也自取 一 猜数字 1到4能组成多少个互不相同且不重复数字的三位数 分别是 分析 可填在百位 十位 个位的数字都是1 2 3
  • annie : cannot unmarshal string into go struct field multipage.aid

    用annie下载B站视频的时候 报错cannot unmarshal string into go struct field multipage aid 去项目的issue里查了一下没找到相应解决方案 然后换了个方式进入视频以后获得了一个新
  • JAVA-Word转PDF各种版本实现方式--亲测有效。。。持续更新中

    当下做一个项目 就是各种操作office 客户的需求总是各种不按常理 来需求就得搞啊 对JAVA操作office这方面真是头大 弟弟是真滴不懂不会啊 无奈只好试啊试的 网上一大堆好使的 一大堆不好使的 整了一大堆word转PDF的方法 但是
  • 【Python】retrying模块使用场景

    大家在做数据抓取或者用selenium自动化进行元素定位的时候 经常遇到由于网络问题导致的抓取数据失败 或者定位元素失败 针对这种情况 我们可以通过设置等待时间去控制 其实还有一种方法 就是使用retrying 它提供一个装饰器函数retr
  • 完美解决python3.6环境下,使用pyinstaller打包.exe时报错的情况。

    初次使用python就被python强大的第三方库所吸引 也正因很多都是第三方库 存在更新不及时的情况也很多 下载pyinstaller 为了偷懒我是直接使用 pip install pyinstaller 然后开始打包 pyinstall
  • MYSQL查询大于某个时间的数据

    今天 SELECT FROM 表名 WHERE TO DAYS 时间字段名 TO DAYS NOW 昨天 SELECT FROM 表名 WHERE TO DAYS NOW TO DAYS 时间字段名 gt 1 7天前 SELECT FROM
  • Spark性能调优案例

    在实际工作中 性能调优是必不可少的 虽然业务千种百样 实际落地的解决方案可能也不尽相同 但归根结底 调优的最终目的是使得内存 CPU IO均衡而没有瓶颈 基本上 思路都是结合实际业务 数据量从硬件出发 考虑如何充分利用CPU 内存 IO 除
  • Windows下基于IIS服务的SSL服务器的配置

    实验环境 Windows Server 2008 R1 CA Windows Server 2008 R2 web服务器 Windows 7 x64 客户端 3台虚拟机打开桥接模式 保证能够相互ping通 实验原理 CA 根CA 负责为服务
  • 机器学习实战—集成学习

    文章目录 一 简介 1 1 集成学习 1 2 随机森林 二 集成学习 投票分类器 2 1 概念 2 2 代码实现 三 集成学习 bagging和pasting 3 1 简介 3 2 Scikit Learn中使用bagging和pastin