【机器学习】集成学习(以随机森林为例)

news2024/11/15 21:43:56

文章目录

  • 集成学习
  • 随机森林
  • 随机森林回归填补缺失值
  • 实例:随机森林在乳腺癌数据上的调参
  • 附录参数


集成学习

集成学习(ensemble learning)是时下非常流行的机器学习算法,它本身不是一个单独的机器学习算法,而是通过在数据上构建多个模型集成所有模型的建模结果

集成算法会考虑多个评估器的建模结果,汇总之后得到一个综合的结果,以此来获取比单个模型更好的回归或分类表现

多个模型集成成为的模型叫做集成评估器(ensemble estimator),组成集成评估器的每个模型都叫做基评估器(base estimator)。通常来说,有三类集成算法:装袋法(Bagging),提升法(Boosting)和stacking

  • Bagging的核心思想是构建多个相互独立的评估器,然后对其预测进行平均或多数表决原则来决定集成评估器的结果。装袋法的代表模型就是随机森林
  • Boosting,基评估器是相关的,是按顺序一一构建的。其核心思想是结合弱评估器的力量一次次对难以评估的样本进行预测,从而构成一个强评估器。提升法的代表模型有Adaboost梯度提升树
    在这里插入图片描述

如何得到若干个个体学习器:

  • 所有的个体学习器都是一个种类的,或者说是同质的。比如都是决策树个体学习器,或者都是神经网络个体学习器。
  • 所有的个体学习器不全是一个种类的,或者说是异质的。比如我们有一个分类问题,对训练集采用支持向量机个体学习器,逻辑回归个体学习器和朴素贝叶斯个体学习器来学习,再通过某种结合策略来确定最终的分类强学习器。

如何选择一种结合策略:

比较常用的集成策略有直接平均、加权平均等。最直接的集成学习策略就是直接平均,即“投票”。我们先从讨论最常见的基于多数票机制的集成方法。简单来说,多数票机制就是选择多数分类器所预测的分类标签,也就是那些获得50%以上支持的预测结果。

可以看一下scikit-learn库中有关集成学习的类:

类的功能
ensemble.AdaBoostClassifierAdaBoost分类
ensemble.AdaBoostRegressorAdaboost回归
ensemble.BaggingClassifier装袋分类器
ensemble.BaggingRegressor装袋回归器
ensemble.ExtraTreesClassifierExtra-trees分类(超树,极端随机树)
ensemble.ExtraTreesRegressorExtra-trees回归
ensemble.GradientBoostingClassifier梯度提升分类
ensemble.GradientBoostingRegressor梯度提升回归
ensemble.IsolationForest隔离森林
ensemble.RandomForestClassifier随机森林分类
ensemble.RandomForestRegressor随机森林回归
ensemble.RandomTreesEmbedding完全随机树的集成
ensemble.VotingClassifier用于不合适估算器的软投票/多数规则分类器

随机森林

随机森林算法可以简单概况为以下四个步骤:

  1. 随机提取一个规模为n的bootstrap样本(从训练集中有放回的随机选择n个样本)
  2. 基于提取的bootstrap样本生成决策树。在每个结点上完成以下任务:
  • 不放回的选取d个特征;
  • 根据目标函数的要求,例如信息增益最大化,使用选定的最佳特征来分裂结点。
  1. 把步骤1和2重复k次
  2. 聚合每棵树的预测结果,并且以多数票机制确定标签的分类。

关于bootstrap样本不放回说明:
在一个含有n个样本的原始训练集中,我们进行随机采样,每次采样一个样本,并在抽取下一个样本之前将该样本放回原始训练集,也就是说下次采样时这个样本依然可能被采集到,这样采集n次,最终得到一个和原始训练集一样大的,n个样本组成的自助集。
在这里插入图片描述在这里插入图片描述我们用交叉验证再次比较单颗决策树和随机森林:

# 交叉验证:
from sklearn.model_selection import cross_val_score
import matplotlib.pyplot as plt

rfc = RandomForestClassifier(n_estimators=30)
rfc_s = cross_val_score(rfc, wine.data, wine.target, cv=10)

clf = DecisionTreeClassifier()
clf_s = cross_val_score(clf, wine.data, wine.target, cv=10)


plt.plot(range(1,11), rfc_s, label='RandomForest')
plt.plot(range(1,11), clf_s, label='DecisionTree')
plt.legend()
plt.show()

在这里插入图片描述随机森林始终大于等于单科决策树。
关于随机森林scikit-learn里面的RandomForestClassifier类参数详解:

  1. n_estimators这是森林中树木的数量,即基评估器的数量。
    这个参数对随机森林模型的精确性影响是单调的,n_estimators
    大,模型的效果往往越好
    。但是相应的,任何模型都有决策边界,n_estimators达到一定的程度之后,随机森林的精确性往往不在上升或开始波动,并且,n_estimators越大,需要的计算量和内存也越大,训练的时间也会越来越长。对于这个参数,我们是渴望在训练难度和模型效果之间取得平衡。
superpa = []
for i in range(200):
    rfc = RandomForestClassifier(n_estimators=i+1,n_jobs=-1)
    rfc_s = cross_val_score(rfc,wine.data,wine.target,cv=10).mean()
    superpa.append(rfc_s)
print(max(superpa),superpa.index(max(superpa)))
plt.figure(figsize=[20,5])
plt.plot(range(1,201),superpa)
plt.show()

可以通过这个来找到最佳的n_estimators
在这里插入图片描述
2. random_state
随机森林中其实也有random_state,用法和分类树中相似,只不过在分类树中,一个random_state只控制生成一棵树,而随机森林中的random_state控制的是生成森林的模式,而非让一个森林中只有一棵树。

在这里插入图片描述random_state固定时,随机森林中生成是一组固定的树,但每棵树依然是不一致的,这是
用”随机挑选特征进行分枝“的方法得到的随机性。并且我们可以证明,当这种随机性越大的时候,袋装法的效果一
般会越来越好。用袋装法集成时,基分类器应当是相互独立的,是不相同的。

  1. 其他:

在这里插入图片描述


随机森林回归填补缺失值

基本思想:
数据集=特征数据+标签,因为是有监督的学习,我们的标签数据肯定是完整的,假设特征数据特征A有缺失值需要填充,可以这样做:

  1. 特征数据 = 特征数据(除去特征A) + 标签
  2. 标签=特征A
  3. 现在数据集的特点是:特征数据完整,标签数据有缺失值
  4. 拿标签数据不缺失的数据进行训练,训练完成后,拿模型对缺失的数据进行预测填充,这就完成了我们数据集的填充。

上面的情况只是一列缺失,也就是一个特征缺失,对于多个特征都有缺失的情况该怎么处理:

  1. 遍历所有的特征,从缺失最少的开始进行填补(因为填补缺失最少的特征所需要的准确信息最少)。
  2. 填补一个特征时,先将其他特征的缺失值用0代替,每完成一次回归预测,就将预测值放到原本的特征矩阵中,再继续填补下一个特征。每一次填补完毕,有缺失值的特征会减少一个,所以每次循环后,需要用0来填补的特征就越来越少。当进行到最后一个特征时(这个特征应该是所有特征中缺失值最多的),已经没有任何的其他特征需要用0来进行填补了,而我们已经使用回归为其他特征填补了大量有效信息,可以用来填补缺失最多的特征。
  3. 遍历所有的特征后,数据就完整,不再有缺失值了。
X_missing_reg = X_missing.copy() # 对原始数据进行copy
sortindex = np.argsort(X_missing_reg.isnull().sum(axis=0)).values # 对缺失特征的数目进行排序并返回索引下标顺序
for i in sortindex:
    
    #构建我们的新特征矩阵和新标签
    df = X_missing_reg
    fillc = df.iloc[:,i]  # 要填充的特征=》标签
    df = pd.concat([df.iloc[:,df.columns != i],pd.DataFrame(y_full)],axis=1) # 除去要需要填充的特征的特征数据+标签=》特征数据
    
    #在新特征矩阵中,对含有缺失值的列,进行0的填补
    df_0 =SimpleImputer(missing_values=np.nan,
                        strategy='constant',fill_value=0).fit_transform(df)
    
    #找出我们的训练集和测试集
    Ytrain = fillc[fillc.notnull()] # 新标签里面没有缺失的值
    Ytest = fillc[fillc.isnull()] # 新标签里面缺失的值,后面进行预测填充
    Xtrain = df_0[Ytrain.index,:] # 训练集
    Xtest = df_0[Ytest.index,:] # 测试集
    
    #用随机森林回归来填补缺失值
    rfc = RandomForestRegressor(n_estimators=100) 
    rfc = rfc.fit(Xtrain, Ytrain)
    Ypredict = rfc.predict(Xtest) 
    
    #将填补好的特征返回到我们的原始的特征矩阵中
    X_missing_reg.loc[X_missing_reg.iloc[:,i].isnull(),i] = Ypredict 

实例:随机森林在乳腺癌数据上的调参

  1. 导入所需要的库
from sklearn.datasets import load_breast_cancer # 乳腺癌的数据集
from sklearn.ensemble import RandomForestClassifier # 随机森林分类树
from sklearn.model_selection import GridSearchCV # 网格搜索 调参
from sklearn.model_selection import cross_val_score # 交叉验证
import matplotlib.pyplot as plt # 画图
import pandas as pd
import numpy as np
  1. 数据处理
data = load_breast_cancer()
# jupyter 查看数据信息
data
data.data.shape
data.target
  1. 简单建模
rfc = RandomForestClassifier(n_estimators=100,random_state=90)
score_pre = cross_val_score(rfc,data.data,data.target,cv=10).mean()
score_pre

在这里插入图片描述

  1. 调参优化

在机器学习中,我们用来衡量模型在未知数据上的准确率的指标,叫做泛化误差(Genelization error)
在这里插入图片描述最佳模型是泛化误差最低的点,左边是欠拟合,模型不够复杂,右边是过拟合,模型太过复杂。
对树模型来说,树越茂盛,深度越深,枝叶越多,模型就越复杂。
对于随机森林最终的几个参数:

参数对模型在未知数据上的评估性能的影响影响程度
n_estimators提升至平稳,n_estimators↑,不影响单个模型的复杂度⭐⭐⭐⭐
max_depth有增有减,默认最大深度,即最高复杂度,向复杂度降低的方向调参max_depth↓,模型更简单,且向图像的左边移动⭐⭐⭐
min_samples _leaf有增有减,默认最小限制1,即最高复杂度,向复杂度降低的方向调参min_samples_leaf↑,模型更简单,且向图像的左边移动⭐⭐
min_samples _split有增有减,默认最小限制2,即最高复杂度,向复杂度降低的方向调参min_samples_split↑,模型更简单,且向图像的左边移动⭐⭐
max_features有增有减,默认auto,是特征总数的开平方,位于中间复杂度,既可以向复杂度升高的方向,也可以向复杂度降低的方向调参max_features↓,模型更简单,图像左移max_features↑,模型更复杂,图像右移max_features是唯一的,既能够让模型更简单,也能够让模型更复杂的参数,所以在调整这个参数的时候,需要考虑我们调参的方向
criterion有增有减,一般使用gini看具体情况

1)n_estimators
初步大范围的调:

scorel = []
for i in range(0,200,10):
    rfc = RandomForestClassifier(n_estimators=i+1,
    n_jobs=-1,
    random_state=90)
    score = cross_val_score(rfc,data.data,data.target,cv=10).mean()
    scorel.append(score)
print(max(scorel),(scorel.index(max(scorel))*10)+1)
plt.figure(figsize=[20,5])
plt.plot(range(1,201,10),scorel)
plt.show()

在这里插入图片描述大范围确定n_estimators71附近,缩小范围再次调整:

scorel = []
for i in range(65,75):
    rfc = RandomForestClassifier(n_estimators=i,
    n_jobs=-1,
    random_state=90)
    score = cross_val_score(rfc,data.data,data.target,cv=10).mean()
    scorel.append(score)
print(max(scorel),([*range(65,75)][scorel.index(max(scorel))]))
plt.figure(figsize=[20,5])
plt.plot(range(65,75),scorel)

在这里插入图片描述可以确定n_estimators=73,相比之前的准确率是有提升的。

2)max_depth
采用网格搜索:

# 调整max_depth
param_grid = {'max_depth':np.arange(1, 20, 1)}
# 一般根据数据的大小来进行一个试探,乳腺癌数据很小,所以可以采用1~10,或者1~20这样的试探
# 但对于像digit recognition那样的大型数据来说,我们应该尝试30~50层深度(或许还不足够
#   更应该画出学习曲线,来观察深度对模型的影响
rfc = RandomForestClassifier(n_estimators=73
                             ,random_state=90
                             )
GS = GridSearchCV(rfc,param_grid,cv=10)
GS.fit(data.data,data.target)

在这里插入图片描述可以发现准确率没有变化,可以不设置这个参数。

3)其他参数也可以采用网格搜索来找出:

"""
有一些参数是没有参照的,很难说清一个范围,这种情况下我们使用学习曲线,看趋势
从曲线跑出的结果中选取一个更小的区间,再跑曲线
param_grid = {'n_estimators':np.arange(0, 200, 10)}
param_grid = {'max_depth':np.arange(1, 20, 1)}
    
param_grid = {'max_leaf_nodes':np.arange(25,50,1)}
 对于大型数据集,可以尝试从1000来构建,先输入1000,每100个叶子一个区间,再逐渐缩小范围
有一些参数是可以找到一个范围的,或者说我们知道他们的取值和随着他们的取值,模型的整体准确率会如何变化,这
样的参数我们就可以直接跑网格搜索
param_grid = {'criterion':['gini', 'entropy']}
param_grid = {'min_samples_split':np.arange(2, 2+20, 1)}
param_grid = {'min_samples_leaf':np.arange(1, 1+10, 1)}
 
param_grid = {'max_features':np.arange(5,30,1)} 
"""

附录参数

在这里插入图片描述在这里插入图片描述
在这里插入图片描述


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1080001.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Rust入门基础

文章目录 Rust相关介绍为什么要用Rust?Rust的用户和案例 开发环境准备安装Rust更新与卸载Rust开发工具 Hello World程序编写Rust程序编译与运行Rust程序 Cargo工具Cargo创建项目Cargo构建项目Cargo构建并运行项目Cargo检查项目Cargo为发布构建项目 Rust相关介绍 为…

关于串口服务器及转接线的一些基础知识笔记

1.普通个人计算机9针串口为232接口,部分特殊工业计算机为485接口。接线方式差异较大,容易区分。 2.串口服务器的作用:带串口的设备(支持常见232、485/422接口方式),将其串口数据信号通过串口服务器转为网络…

角谷猜想:键盘输入一个整数,输出角谷猜想验证过程

键盘输入一个整数,输出角谷猜想验证过程。 (本笔记适合python循环、if条件语句、字符串格式化输出的 coder 翻阅) 【学习的细节是欢悦的历程】 Python 官网:https://www.python.org/ Free:大咖免费“圣经”教程《 python 完全自学教程》&…

cdsn目录处理:空行替换2个```,在2个```中间添加“# 空行文本后遇到的第1行文字”?

原标题: python查找替换:查找空行,空行前后添加,中间添加 # 空格 空行后遇到的第1行文字?初始代码 查找空行空行前后添加 中间添加 # 空行后遇到的第1行文字txt 36 96 159 8 72可以使用Python的字符串处理函数来查找…

【数据库系统概论】第一章数据库绪论

第一章目录: 1.1数据库系统概述 1.1.1四个基本概念 数据: 数据库:Database -DB 数据库管理系统(DBMS) 数据库系统(DBS)(有四个组成要素) 1.1.2数据管理技术的产生…

【电商API封装接口】电商百万商品资源一键导入,助力企业流量变现

电商API接口是淘宝开放平台提供的一组数据接口,供开发者使用来获取淘宝平台上商品、店铺、订单等相关信息。根据功能和分类,淘宝API主要包括以下几个方面: 1. 商品API:提供了搜索、详情、评价等与商品相关的接口,可以…

vue2 打印数据 以及使用 (2)

安装 To install using npm:npm install print-js --saveTo install using yarn:yarn add print-js页面效果 <template><div><table width"100%" height"100%" border"1"><tr><td colspan"1">1</td&…

python图片处理:添加背景文生图(2)

文生图3.0&#xff1a;添加背景图片 3个回车文生图꧂写在前面&#xff1a;肉麻的话꧁ 哈哈&#xff0c;我明白了&#xff01;请允许我再试一次以幽默的方式来重新描述文本&#xff1a; 亲爱的主人大大&#xff0c;你是超级棒的&#xff01;如果你不想处理枯燥的代码&#xff0…

前端TypeScript学习day03-TS高级类型

(创作不易&#xff0c;感谢有你&#xff0c;你的支持&#xff0c;就是我前行的最大动力&#xff0c;如果看完对你有帮助&#xff0c;请留下您的足迹&#xff09; 目录 TypeScript 高级类型 class 类 class继承 extends implements 类成员可见性 public protected …

c语言终点站--文件操作

前言&#xff1a; 为什么要学习文件操作呢&#xff1f;想要知道这个问题&#xff0c;我们就需要先了解什么是数据的可持久化。 那么什么是数据的可持久化呢&#xff1f;数据的可持久化就是把内存中的数据对象永久的保存在电脑的磁盘文件中&#xff0c;将程序数据在持久状态和…

mysql面试题40:列值为null或者空字符串时,查询是否会用到索引?

该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:列值为null或者空字符串时,查询是否会用到索引? 当列的值为NULL时,查询可能会使用索引,但具体是否使用索引取决于数据库的优化器和查询条件。…

点向行列连边的网络流图优化成行列连边的二分图:CF1592F2

https://www.luogu.com.cn/problem/CF1592F2 做完F1&#xff0c;然后用1的结论来思考。 场上推了几个性质。首先op4的操作行列必然两两不同&#xff0c;所以op4最多 max ⁡ ( n , m ) \max(n,m) max(n,m) 次。然后手玩发现只有除 ( n , m ) (n,m) (n,m) 的三个格子都为1&am…

ChatGPT 是如何产生心智的? | 京东云技术团队

一、前言 - ChatGPT真的产生心智了吗&#xff1f; 来自斯坦福大学的最新研究结论&#xff0c;一经发出就造成了学术圈的轰动&#xff0c;“原本认为是人类独有的心智理论&#xff08;Theory of Mind&#xff0c;ToM&#xff09;&#xff0c;已经出现在ChatGPT背后的AI模型上”…

芯科蓝牙BG27开发笔记10-BG27样板调试

样板使用了1.5V电源&#xff0c;boost升压到1.8V供MCU使用&#xff0c;因此IO通信的电平需要注意&#xff1a; 不能使用常用的5V、3.3V的jlink进行调试&#xff0c;类似的uart通信也一样。 BRD4001A底板的jlink如何使用&#xff1f; 参考开发板套件的说明文档《ug551-brd4194…

purr map walk 学习教程 完整版教程学习

Function reference • purrrhttps://purrr.tidyverse.org/reference/index.htmlMap over multiple input simultaneously (in "parallel") — pmap • purrr 11 Other purrr functions | Functional Programming (stanford.edu) 关注微信&#xff1a;生信小博士 1…

【解决问题思路分析】记录hutool默认使用服务端上次返回cookie的问题解决思路

背景&#xff1a; 本服务需要调用第三方接口获取数据&#xff0c;首先调用public-key接口获取公钥&#xff0c;然后用公钥加密密码&#xff0c;将用户名和密码传入/ticket接口&#xff0c;获取Cookie和response body中的token。 排查思路 由于是调用第三方接口出现问题&…

OnlyOffice文档服务器安装及集成使用

OnlyOffice文档服务器安装及集成使用 一、安装1.使用docker安装2.开启防火墙3.配置4.访问测试 二、应用集成1.前端集成(React)(1).安装onlyoffice/document-editor-react(2).使用 ONLYOFFICE 文档 React 组件 2.后台集成(Java)(1) getFile接口(2) callback接口(3) getFile接口和…

SpringBoot拦截器实现

1.定义一个拦截器类&#xff0c;实现HandlerInterceptor接口 创建一个Interceptor类实现HandlerInterceptor接口&#xff0c;重写preHandle()&#xff0c;postHandle()&#xff0c;afterCompletion() 三个方法 如下代码&#xff0c;我们就创建了一个Spring的拦截器 /*** auth…

战神引擎传奇假设教程

战神引擎传奇假设教程 --------------------------------------------------------------------------------------------------- 传奇这款游戏可以说是一代人的回忆&#xff0c;特别是8090后&#xff0c;传奇对他们有着许许多多的难忘的回忆&#xff0c; 随着时代的发展&…

typora常用偏好设置

启用自动保存 关闭拼写检查 插入图片的设置 将图片保存在当前文件夹内 换行设置 关闭换行符的显示功能