当前位置: 首页 > news >正文

机器学习算法——集成学习

目录

  • 1. Bagging
    • 1.1 工作流程
    • 1.2 代码实践
  • 2. 随机森林
    • 2.1 工作流程
    • 2.2 代码实践
  • 3. Adaboost
    • 3.1 工作流程
    • 3.2 样本权值的更新策略
    • 3.3 代码实践
  • 4. Stacking
    • 4.1 代码实践
  • 5. Voting
    • 5.1 代码实践
  • 6. 集成学习分类

1. Bagging

Bagging(bootstrap aggregating:自举汇聚法)也叫装袋法,其思想是通过将许多相互独立的学习器的结果进行结合,从而提高整体学习器的泛化能力,是一种并行集成学习方法

1.1 工作流程

  1. 从原始样本集中使用Bootstraping(有放回抽样,这种抽样方法产生的样本子集能很好的反映总体的分布特性)方法抽取n个训练样本,共进行K轮抽取,得到K个训练集(训练集之间相互独立)。
  2. 对于每个训练集,使用相同的数据学习算法(比如决策树、KNN等)独立训练一个基本模型。
  3. 将测试样例输入到所有基本模型中,每个模型都给出一个预测值。对于分类问题:通过投票的方式确定分类结果(每个模型只有一票);对于回归问题:计算预测值的均值作为预测结果。

1.2 代码实践

from sklearn import neighbors
from sklearn import datasets
from sklearn.ensemble import BaggingClassifier
from sklearn import tree
from sklearn.model_selection import train_test_split
import numpy as np
import matplotlib.pyplot as plt#------------------------------------------------------------------#
# 使用datasets模块导入鸢尾花数据集,并切分特征值和标签值
# train_test_split(x_data, y_data):将数据集划分为测试集和训练集,
# 默认情况下,训练集占3/4,测试集占1/4
#-----------------------------------------------------------------#
iris = datasets.load_iris()
x_data = iris.data[:,:2]
y_data = iris.target
x_train, x_test, y_train, y_test = train_test_split(x_data, y_data)
# 利用等高线绘制分类边界图
def plot(model):# 获取数据值所在的范围x_min, x_max = x_data[:, 0].min() - 1, x_data[:, 0].max() + 1y_min, y_max = x_data[:, 1].min() - 1, x_data[:, 1].max() + 1# 生成网格矩阵元素xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02),np.arange(y_min, y_max, 0.02))#-----------------------------------------------------## 预测分类结果# ravel():将多为数据展平为一维数据# np.c_:按列连接两个数组,即拼接成点的坐标的形式# contourf(xx, yy, z):创建填充等高线图,参数需为二维数组#-----------------------------------------------------#z = model.predict(np.c_[xx.ravel(), yy.ravel()])z = z.reshape(xx.shape)cs = plt.contourf(xx, yy, z)
# 创建KNN模型,使用训练集训练模型
knn = neighbors.KNeighborsClassifier()
knn.fit(x_train, y_train)
# 绘制分类边界图
plot(knn)
# 样本散点图
plt.scatter(x_data[:, 0], x_data[:, 1], c=y_data)
# 打印准确率
knn.score(x_test, y_test)

在这里插入图片描述

# 创建CART决策树模型,使用训练集训练模型
dtree = tree.DecisionTreeClassifier()
dtree.fit(x_train, y_train)
# 绘制分类边界图
plot(dtree)
# 样本散点图
plt.scatter(x_data[:, 0], x_data[:, 1], c=y_data)
# 打印准确率
dtree.score(x_test, y_test)

在这里插入图片描述

# 创建 Bagging 分类器对象,以KNN分类器作为基分类器,创建100个KNN基分类器
bagging_knn = BaggingClassifier(knn, n_estimators=100)
# 模型拟合
bagging_knn.fit(x_train, y_train)
# 绘制分类边界图
plot(bagging_knn)
# 样本散点图
plt.scatter(x_data[:, 0], x_data[:, 1], c=y_data)
# 打印准确率
bagging_knn.score(x_test, y_test)

在这里插入图片描述

# 创建 Bagging 分类器对象,以CART决策树分类器作为基分类器,创建100个基分类器
bagging_tree = BaggingClassifier(dtree, n_estimators=100)
# 模型拟合
bagging_tree.fit(x_train, y_train)
# 绘制分类边界图
plot(bagging_tree)
# 样本散点图
plt.scatter(x_data[:, 0], x_data[:, 1], c=y_data)
# 打印准确率
bagging_tree.score(x_test, y_test)

在这里插入图片描述
准确率汇总

算法准确率
KNN73.6 8%
Bagging(KNN)76.32%
DecisionTree57.89%
Bagging(DecisionTree)60.53%

注:由于数据集切分的随机性和Bagging中每个基分类器所使用的训练集不同,因此每次运行的结果可能不同,且Bagging的准确率可能会比单分类器的准确率低

2. 随机森林

随机森林(Random Forest)是通过集成学习的思想将多棵树(基分类器)进行集成的一种算法,它的基本单元是决策树。随机森林=决策树+Bagging+随机属性选择

2.1 工作流程

  1. 样本随机选择:从原始样本集中使用Bootstraping(有放回抽样,这种抽样方法产生的样本子集能很好的反映总体的分布特性)方法抽取n个训练样本,共进行K轮抽取,得到K个训练集(训练集之间相互独立)。
  2. 特征随机选择:当决策树的每个节点需要分裂时,从所有属性 M 中随机选择 K 个属性 (K<<M,这样可以增加随机性,避免过拟合,并提高模型的多样性),然后从这 K 个属性中选择最佳分割属性作为节点的分裂属性,直到满足某个停止条件(例如达到最大深度、节点样本数小于阈值等)。
  3. 重复以上步骤 n 次,建立 n 棵 CART 决策树(决策树形成过程中没有进行剪枝),这 m 棵 CART 决策树形成随机森林。
  4. 通过投票的方式决定数据属于哪一类。

样本和特征的随机选择能很大程度上减少过拟合的风险(决策树容易过拟合),同时也能增强模型的准确性和泛化能力。

随机森林图示
在这里插入图片描述
图中每棵树的样本集合和分支节点的特征均不相同。

2.2 代码实践

from sklearn import tree
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
import numpy as np
import matplotlib.pyplot as plt# 载入数据集,划分特征数据与标签数据,并绘制散点图
data = np.genfromtxt("LR-testSet2.txt", delimiter=",")
x_data = data[:,:-1]
y_data = data[:, -1]
plt.scatter(x_data[:,0],x_data[:,1],c=y_data)

在这里插入图片描述

# 将数据集切分为训练集和测试集,比例为1:1
x_train, x_test, y_train, y_test = train_test_split(x_data, y_data, test_size = 0.5)# 利用等高线绘制分类边界图
def plot(model):# 获取数据值所在的范围x_min, x_max = x_data[:, 0].min() - 1, x_data[:, 0].max() + 1y_min, y_max = x_data[:, 1].min() - 1, x_data[:, 1].max() + 1# 生成网格矩阵元素xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02),np.arange(y_min, y_max, 0.02))#-----------------------------------------------------## 预测分类结果# ravel():将多为数据展平为一维数据# np.c_:按列连接两个数组,即拼接成点的坐标的形式# contourf(xx, yy, z):创建填充等高线图,参数需为二维数组#-----------------------------------------------------#z = model.predict(np.c_[xx.ravel(), yy.ravel()])z = z.reshape(xx.shape)cs = plt.contourf(xx, yy, z)
# 创建决策树模型,使用训练数据进行拟合
dtree = tree.DecisionTreeClassifier()
dtree.fit(x_train, y_train)# 绘制分类边界图和样本散点图
plot(dtree)
plt.scatter(x_test[:, 0], x_test[:, 1], c=y_test)
dtree.score(x_test, y_test)

在这里插入图片描述

# 创建随机森林模型,其包含50个决策树基分类器
RF = RandomForestClassifier(n_estimators=50)
RF.fit(x_train, y_train)plot(RF)
RF.score(x_test, y_test)

在这里插入图片描述

3. Adaboost

AdaBoost(Adaptive Boosting:自适应增强)的自适应在于:前一个基分类器中被错误分类的样本的权值会增大(将学习器的重点放在容易出错的样本上可以提升学习器的性能),而正确分类的样本的权值会减小,并将样本用来训练下一个基分类器。同时,在每一轮迭代中,加入一个新的基分类器,直到达到某个预定的足够小的错误率或达到预先指定的最大迭代次数才确定最终的强分类器 ,Adaboost是一种串行集成学习方法,基学习器之间存在强依赖关系。
在这里插入图片描述

3.1 工作流程

  1. 初始化训练数据的权值分布,假设有 N 个训练样本,则每一个训练样本最开始时都被赋予相同的权值: w i = 1 N w_i =\frac{1}{N} wi=N1
  2. 训练弱分类器 h i h_i hi,具体训练过程:如果某个训练样本被基分类器 h i h_i hi准确地分类,那么在构造下一个样本集时,它对应的权值要减小;相反,如果某个训练样本被错误分类,那么它的权值要增大。权值更新过的样本集被用于训练下一个基分类器,整个训练过程不断迭代。
  3. 将各个训练得到的弱分类器(基分类器)组合成一个强分类器。各个弱分类器的训练过程结束后,分类误差小的弱分类器的权重较大,使其在最终的分类函数中起着较大的决定作用,分类误差大的弱分类器的权重较小,使其在最终的分类函数中起着较小的决定作用。

3.2 样本权值的更新策略

对于第 t t t轮迭代,基分类器 h h h在训练集 D t D_t Dt上的错误率为 α t \alpha _t αt α t < 0.5 \alpha _t<0.5 αt<0.5)。
则基分类器 h h h的权重更新公式
α t = 1 2 l n 1 − α t α t \alpha _t=\frac{1}{2}ln\frac{1-\alpha _t}{\alpha_t} αt=21lnαt1αt
样本 i i i的权重更新公式
W i t + 1 = W i t e − α t Z t , y = y ^ W_i^{t+1}=\frac{W_i^{t}e^{-\alpha _t}}{Z_t},y=\hat{y} Wit+1=ZtWiteαt,y=y^
W i t + 1 = W i t e α t Z t , y ≠ y ^ W_i^{t+1}=\frac{W_i^{t}e^{\alpha _t}}{Z_t},y\ne\hat{y} Wit+1=ZtWiteαt,y=y^
其中, y y y为真实值, y ^ \hat{y} y^为预测值。样本被正确分类时,权重需减小;样本被错误分类时,权重需增大。 Z t Z_t Zt为归一化因子(更新后的样本权重之和),以保证样本权重之和为1。


样本 x x x最终的预测结果
H ( x ) = s i g m o i d ( ∑ t = 1 T α t h t ( x ) ) H(x)=sigmoid(\sum_{t=1}^T\alpha _th_t(x)) H(x)=sigmoid(t=1Tαtht(x))

3.3 代码实践

import numpy as np
import matplotlib.pyplot as plt
from sklearn import tree
from sklearn.ensemble import AdaBoostClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import make_gaussian_quantiles
from sklearn.metrics import classification_report#-------------------------------------------------------------------------#
# make_gaussian_quantiles:生成具有高斯分布的量化数据
# n_samples:样本数量500个样本,2个样本特征,两个样本特征的均值默认为0
# n_features:每个样本的特征数
# n_classes:数据集的类别数
# mean:指定每个类别的均值
#-------------------------------------------------------------------------#
x1, y1 = make_gaussian_quantiles(n_samples=500, n_features=2, n_classes=2)
x2, y2 = make_gaussian_quantiles(mean=(3, 3), n_samples=500, n_features=2, n_classes=2)# 将两组数据合成一组数据
x_data = np.concatenate((x1, x2))
y_data = np.concatenate((y1, - y2 + 1))# 数据集散点图
plt.scatter(x_data[:, 0], x_data[:, 1], c=y_data)

在这里插入图片描述

# 创建决策树模型并进行拟合
model = tree.DecisionTreeClassifier(max_depth=3)
model.fit(x_data, y_data)# 获取数据值所在的范围
x_min, x_max = x_data[:, 0].min() - 1, x_data[:, 0].max() + 1
y_min, y_max = x_data[:, 1].min() - 1, x_data[:, 1].max() + 1# 生成网格矩阵元素
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02),np.arange(y_min, y_max, 0.02))#--------------------------------------------------------#
# 预测分类结果
# ravel():将多为数据展平为一维数据
# np.c_:按列连接两个数组,即拼接成点的坐标的形式
# contourf(xx, yy, z):创建填充等高线图,参数需为二维数组
#--------------------------------------------------------#
z = model.predict(np.c_[xx.ravel(), yy.ravel()])
z = z.reshape(xx.shape)
cs = plt.contourf(xx, yy, z)# 样本散点图
plt.scatter(x_data[:, 0], x_data[:, 1], c=y_data)# 打印准确率
model.score(x_data,y_data)

在这里插入图片描述

# 创建AdaBoost模型,其包含10个基分类器
model = AdaBoostClassifier(DecisionTreeClassifier(max_depth=3), n_estimators=10)
# 训练模型
model.fit(x_data, y_data)# 获取数据值所在的范围
x_min, x_max = x_data[:, 0].min() - 1, x_data[:, 0].max() + 1
y_min, y_max = x_data[:, 1].min() - 1, x_data[:, 1].max() + 1# 生成网格矩阵元素
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02),np.arange(y_min, y_max, 0.02))#--------------------------------------------------------#
# 预测分类结果
# ravel():将多为数据展平为一维数据
# np.c_:按列连接两个数组,即拼接成点的坐标的形式
# contourf(xx, yy, z):创建填充等高线图,参数需为二维数组
#--------------------------------------------------------#
z = model.predict(np.c_[xx.ravel(), yy.ravel()])
z = z.reshape(xx.shape)
cs = plt.contourf(xx, yy, z)# 样本散点图
plt.scatter(x_data[:, 0], x_data[:, 1], c=y_data)# 打印准确率
model.score(x_data,y_data)

在这里插入图片描述
准确率从77.1%增加到98.2%,提升非常大。

4. Stacking

使用多个不同的分类器对训练集进预测,把预测得到的结果作为一个次级分类器的输入。次级分类器的输出是整个模型的预测结果。在Stacking方法中,有两个阶段的模型。 第一个阶段的模型是以原始训练集(无需抽样构造训练集,所有模型均使用相同的训练集)为输入的模型,叫做基模型(也叫 level-0 模型),可以选取多种基模型进行训练。第二个阶段的模型是以基模型在原始训练集上的预测作为训练集,以基模型在原始测试集上的预测作为测试集,叫做元模型(也叫 level-1 模型)1

Stacking算法的结构图示如下
在这里插入图片描述

4.1 代码实践

from sklearn import datasets  
from sklearn import model_selection  
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier  
from sklearn.tree import DecisionTreeClassifier
# 需安装mlxtend模块:pip install mlxtend
from mlxtend.classifier import StackingClassifier 
import numpy as np  # 载入数据集,只要第1,2列的特征
iris = datasets.load_iris()  
x_data, y_data = iris.data[:, 1:3], iris.target  # 定义三个不同的分类器
clf1 = KNeighborsClassifier(n_neighbors=1)  
clf2 = DecisionTreeClassifier() 
clf3 = LogisticRegression()  # 定义一个次级分类器
lr = LogisticRegression()  
sclf = StackingClassifier(classifiers=[clf1, clf2, clf3],   meta_classifier=lr)# zip:用于将多个可迭代对象(例如列表、元组等)的对应元素打包成一个元组,返回一个迭代器
for clf,label in zip([clf1, clf2, clf3, sclf],['KNN','Decision Tree','LogisticRegression','StackingClassifier']):  #------------------------------------------------------------------------------## 在实际使用Stacking方法时,为了避免过拟合的风险,常常伴随着交叉验证操作# 使用3折交叉验证,每次取其中的一份作为测试集,两份作为训练集# 3折交叉验证会输出3个准确率,这里取3个准确率的均值# cross_val_score:计算交叉验证的评分#------------------------------------------------------------------------------#scores = model_selection.cross_val_score(clf, x_data, y_data, cv=3, scoring='accuracy')  print("Accuracy: %0.2f [%s]" % (scores.mean(), label)) 

运行结果

Accuracy: 0.91 [KNN]
Accuracy: 0.93 [Decision Tree]
Accuracy: 0.95 [LogisticRegression]
Accuracy: 0.93 [StackingClassifier]

5. Voting

对基分类器的预测结果使用投票的方式确定最终预测结果。

5.1 代码实践

from sklearn import datasets  
from sklearn import model_selection  
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier  
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import VotingClassifier
from sklearn.model_selection import train_test_split
import numpy as np# 载入数据集,只要第1,2列的特征(使单个分类器与Voting分类器的准确率之间存在差距,便于观察Voting分类器在准确率上的提升)。
iris = datasets.load_iris()  
x_data, y_data = iris.data[:, 1:3], iris.target  # 定义三个不同的分类器
clf1 = KNeighborsClassifier(n_neighbors=1)  
clf2 = DecisionTreeClassifier() 
clf3 = LogisticRegression()  # 定义Voting分类器
sclf = VotingClassifier([('knn',clf1),('dtree',clf2), ('lr',clf3)])   # zip:用于将多个可迭代对象(例如列表、元组等)的对应元素打包成一个元组,返回一个迭代器
for clf, label in zip([clf1, clf2, clf3, sclf],['KNN','Decision Tree','LogisticRegression','VotingClassifier']):  #------------------------------------------------------------------------------## 为了避免过拟合的风险,使用交叉验证方法# 使用3折交叉验证,每次取其中的一份作为测试集,两份作为训练集# 3折交叉验证会输出3个准确率,这里取3个准确率的均值# cross_val_score:计算交叉验证的评分#------------------------------------------------------------------------------#scores = model_selection.cross_val_score(clf, x_data, y_data, cv=3, scoring='accuracy')  print("Accuracy: %0.2f [%s]" % (scores.mean(), label)) 

运行结果

Accuracy: 0.91 [KNN]
Accuracy: 0.91 [Decision Tree]
Accuracy: 0.95 [LogisticRegression]
Accuracy: 0.95 [VotingClassifier]
# 将数据集划分为训练集和测试集
xtrain, xtest, ytrain, ytest = train_test_split(x_data, y_data, test_size=0.2)# 定义并训练三个不同的分类器
clf1 = KNeighborsClassifier(n_neighbors=1)  
clf1.fit(xtrain, ytrain)
clf2 = DecisionTreeClassifier() 
clf2.fit(xtrain, ytrain)
clf3 = LogisticRegression() 
clf3.fit(xtrain, ytrain)# 定义并训练Voting分类器
sclf = VotingClassifier([('knn',clf1),('dtree',clf2), ('lr',clf3)])   
sclf.fit(xtrain, ytrain)# 实际预测
print("KNN:{}".format(clf1.score(xtest,ytest)))
print("DecisionTree:{}".format(clf2.score(xtest,ytest)))
print("Logistic:{}".format(clf3.score(xtest,ytest)))
print("Voting:{}".format(sclf.score(xtest,ytest)))

运行结果

KNN:0.9
DecisionTree:0.9666666666666667
Logistic:0.9333333333333333
Voting:0.9666666666666667

6. 集成学习分类

按照基分类器的生成方式可分为
在这里插入图片描述

按照是否使用同一种基学习器(使用同一种基学习器的方法称为同质集成方法)可分为
在这里插入图片描述


  1. 集成学习之Stacking(堆栈)方法 ↩︎

相关文章:

  • Vue项目Jenkins自动化部署
  • Golang中读写CSV文件的全面指南
  • 鸿蒙原生应用/元服务开发-AGC分发如何编译打包应用
  • qt和window抓包程序
  • RK3588产测软件介绍
  • kafka原理看这一篇就够了
  • 【经验分享】Ubuntu如何设置swap交换
  • HIS系统源码,云HIS源码,二级医院信息管理系统源码,预约挂号支持、病患问诊、电子病历、开药发药、会员管理、统计查询、医生工作站、护士工作站
  • 推荐一个windows上传linux服务器/linux服务器的docker镜像的工具,摆脱docker cp,以及解决常见问题。
  • Redis的简单使用
  • ​软考-高级-系统架构设计师教程(清华第2版)【第20章 系统架构设计师论文写作要点(P717~728)-思维导图】​
  • Python-对象与json互转-json读写-文件读写
  • 2023年中国老年人护理用品市场规模及前景,呈现快速发展趋势[图]
  • 新能源充电桩工业4G路由器应用,推动绿色出行,响应环保理念
  • 【C++心愿便利店】No.14---C++之探索list底层原理
  • [case10]使用RSQL实现端到端的动态查询
  • [NodeJS] 关于Buffer
  • __proto__ 和 prototype的关系
  • angular2开源库收集
  • Docker 笔记(2):Dockerfile
  • Docker: 容器互访的三种方式
  • HTTP 简介
  • Mybatis初体验
  • MySQL Access denied for user 'root'@'localhost' 解决方法
  • niucms就是以城市为分割单位,在上面 小区/乡村/同城论坛+58+团购
  • Ruby 2.x 源代码分析:扩展 概述
  • sessionStorage和localStorage
  • vue-cli3搭建项目
  • 记一次和乔布斯合作最难忘的经历
  • 区块链将重新定义世界
  • 职业生涯 一个六年开发经验的女程序员的心声。
  • MiKTeX could not find the script engine ‘perl.exe‘ which is required to execute ‘latexmk‘.
  • k8s使用glusterfs实现动态持久化存储
  • Mac 上flink的安装与启动
  • Play Store发现SimBad恶意软件,1.5亿Android用户成受害者 ...
  • Salesforce和SAP Netweaver里数据库表的元数据设计
  • ​猴子吃桃问题:每天都吃了前一天剩下的一半多一个。
  • ​软考-高级-系统架构设计师教程(清华第2版)【第15章 面向服务架构设计理论与实践(P527~554)-思维导图】​
  • ​软考-高级-系统架构设计师教程(清华第2版)【第9章 软件可靠性基础知识(P320~344)-思维导图】​
  • ​水经微图Web1.5.0版即将上线
  • #NOIP 2014# day.1 T2 联合权值
  • $.type 怎么精确判断对象类型的 --(源码学习2)
  • (10)STL算法之搜索(二) 二分查找
  • (pojstep1.1.2)2654(直叙式模拟)
  • (附源码)ssm高校升本考试管理系统 毕业设计 201631
  • (九)One-Wire总线-DS18B20
  • (四)TensorRT | 基于 GPU 端的 Python 推理
  • .NET CORE 第一节 创建基本的 asp.net core
  • .NET 使用配置文件
  • .Net程序帮助文档制作
  • @column注解_MyBatis注解开发 -MyBatis(15)
  • @selector(..)警告提示
  • @SuppressLint(NewApi)和@TargetApi()的区别
  • [ element-ui:table ] 设置table中某些行数据禁止被选中,通过selectable 定义方法解决
  • [2019/05/17]解决springboot测试List接口时JSON传参异常