集成算法的参数空间与网格优化

目录

1. 探索参数空间

1.1 学习曲线

1.2. 决策树对象Tree

2. 使用网格搜索在随机森林上进行调参


1. 探索参数空间

        随机森林集成算法的超参数种类繁多、取值丰富,且参数之间会相互影响、共同作用于算法的最终结果,因此集成算法的调参是一个难度很高的过程。在超参数优化还未盛行的时候,随机森林的调参是基于方差-偏差理论(variance-bias trade-off)和学习曲线完成的,而现在可以依赖于网格搜索来完成自动优化。在对任意算法进行网格搜索时,需要明确两个基本事实:一是参数对算法结果的影响力大小,二是用于进行搜索的参数空间。

        对随机森林来说,各个参数对算法的影响排列大致如下:

影响力参数
⭐⭐⭐⭐⭐
几乎总是具有巨大影响力
n_estimators(整体学习能力)
max_depth(粗剪枝)
max_features(随机性)
⭐⭐⭐⭐
大部分时候具有影响力
max_samples(随机性)
class_weight(样本均衡)
⭐⭐
可能有大影响力
大部分时候影响力不明显
min_samples_split(精剪枝)
min_impurity_decrease(精剪枝)
max_leaf_nodes(精剪枝)
criterion(分枝敏感度)

当数据量足够大时,几乎无影响
random_state
ccp_alpha(结构风险)

        随机森林在剪枝方面的空间总是很大的,因为默认参数下树的结构基本没有被影响(也就是几乎没有剪枝),因此当随机森林过拟合的时候,我们可以尝试粗、精、随机等各种方式来影响随机森林。通常在网格搜索当中,我们会考虑所有有巨大影响力的参数、以及1~2个影响力不明显的参数。

        虽然随机森林调参的空间较大,但大部分时候在调参过程中依然难以突破,因为树的集成模型的参数空间非常难以确定。当没有数据支撑时,人们很难通过感觉或经验来找到正确的参数范围。举例来说,我们也很难直接判断究竟多少棵树对于当前的模型最有效,同时,我们也很难判断不剪枝时一棵决策树究竟有多深、有多少叶子、或者一片叶子上究竟有多少个样本,更不要谈凭经验判断树模型整体的不纯度情况了。可以说,当森林建好之后,我们简直是对森林一无所知。对于网格搜索来说,新增一个潜在的参数可选值,计算量就会指数级增长,因此找到有效的参数空间非常重要。此时我们就要引入两个工具来帮助我们:学习曲线 and 决策树对象Tree的属性

1.1 学习曲线

        学习曲线是以参数的不同取值为横坐标,模型的结果为纵坐标的曲线。当模型的参数较少、且参数之间的相互作用较小时,我们可以直接使用学习曲线进行调参。但对于集成算法来说,学习曲线更多是探索参数与模型关系的关键手段。许多参数对模型的影响是确定且单调的,例如n_estimators,树越多模型的学习能力越强,再比如ccp_alpha,该参数值越大模型抗过拟合能力越强,因此我们可能通过学习曲线找到这些参数对模型影响的极限,并围绕这些极限点来构筑参数空间。

Option = [1,*range(5,101,5)]
#生成保存模型结果的arrays
trainRMSE = np.array([])
testRMSE = np.array([])
trainSTD = np.array([])
testSTD = np.array([])
for n_estimators in Option:#按照当下的参数,实例化模型reg_f = RFR(n_estimators=n_estimators,random_state=1412)#实例化交叉验证方式,输出交叉验证结果cv = KFold(n_splits=5,shuffle=True,random_state=1412)result_f = cross_validate(reg_f,x,y,cv=cv,scoring="neg_mean_squared_error",return_train_score=True)#根据输出的MSE进行RMSE计算train = abs(result_f["train_score"])**0.5test = abs(result_f["test_score"])**0.5#将本次交叉验证中RMSE的均值、标准差添加到arrays中进行保存trainRMSE = np.append(trainRMSE,train.mean())testRMSE = np.append(testRMSE,test.mean())trainSTD = np.append(trainSTD,train.std())testSTD = np.append(testSTD,test.std())
def plotCVresult(Option,trainRMSE,testRMSE,trainSTD,testSTD):#一次交叉验证下,RMSE的均值与std的绘图xaxis = Optionplt.figure(figsize=(8,6),dpi=80)#RMSEplt.plot(xaxis,trainRMSE,color="k",label = "RandomForestTrain")plt.plot(xaxis,testRMSE,color="red",label = "RandomForestTest")#标准差 - 围绕在RMSE旁形成一个区间plt.plot(xaxis,trainRMSE+trainSTD,color="k",linestyle="dotted")plt.plot(xaxis,trainRMSE-trainSTD,color="k",linestyle="dotted")plt.plot(xaxis,testRMSE+testSTD,color="red",linestyle="dotted")plt.plot(xaxis,testRMSE-testSTD,color="red",linestyle="dotted")plt.xticks([*xaxis])plt.legend(loc=1)plt.show()
plotCVresult(Option,trainRMSE,testRMSE,trainSTD,testSTD)

当绘制学习曲线时,可以很容易找到泛化误差开始上升或转变为平稳趋势的转折点。因此我们可以选择转折点或转折点附近的n_estimators取值,例如20。然而,n_estimators会受到其他参数的影响,例如:单棵决策树的结构更简单时(依赖剪枝时),或单棵决策树训练的数据更简单时(依赖随机性时),可能需要更多树。因此n_estimators的参数空间可以被确定为range(20,100,5),如果比较保守,甚至可以确认为是range(15,25,5)。

1.2. 决策树对象Tree

        在sklearn中,树模型是单独的一类对象,每个树模型背后都有一套完整的属性供我们调用,包括树的结构、树的规模等众多细节。随机森林是树组成的算法,因此也可以调用这些属性。

#训练一个随机森林
reg_f = RFR(n_estimators=10,random_state=1412)
reg_f = reg_f.fit(x,y)

\bullet 属性.estimators_

reg_f.estimators_  #返回一片随机森林中所有的树
[DecisionTreeRegressor(max_features=1.0, random_state=1608637542),DecisionTreeRegressor(max_features=1.0, random_state=1273642419),DecisionTreeRegressor(max_features=1.0, random_state=1935803228),DecisionTreeRegressor(max_features=1.0, random_state=787846414),DecisionTreeRegressor(max_features=1.0, random_state=996406378),DecisionTreeRegressor(max_features=1.0, random_state=1201263687),DecisionTreeRegressor(max_features=1.0, random_state=423734972),DecisionTreeRegressor(max_features=1.0, random_state=415968276),DecisionTreeRegressor(max_features=1.0, random_state=670094950),DecisionTreeRegressor(max_features=1.0, random_state=1914837113)]
reg_f.estimators_[0]  #使用索引单独提取一棵树
DecisionTreeRegressor(max_features=1.0, random_state=1608637542)

\bullet 属性.max_depth

reg_f.estimators_[0].tree_.max_depth #查看第一棵树的实际深度
21
#对随机森林中所有树查看实际深度
for t in reg_f.estimators_:print(t.tree_.max_depth)
21
23
24
19
22
25
21
21
22
22

如果树的数量较多,也可以查看平均或分布

reg_f = RFR(n_estimators=100,random_state=1412)
reg_f = reg_f.fit(x,y)
d = pd.Series([],dtype="int64")
for idx,t in enumerate(reg_f.estimators_):d[idx] = t.tree_.max_depthd.describe()
count    100.000000
mean      22.250000
std        1.955954
min       19.000000
25%       21.000000
50%       22.000000
75%       23.000000
max       30.000000
dtype: float64

假设现在随机森林过拟合,max_depth的最大深度范围设置在[15,25]之间就会比较有效,如果希望激烈地剪枝,则可以设置在[10,15]之间。

相似的,也可以调用其他属性来辅助我们调参:

参数参数含义对应属性属性含义
n_estimators树的数量reg.estimators_森林中所有树对象
max_depth允许的最大深度.tree_.max_depth树实际的深度
max_leaf_nodes允许的最大
叶子节点量
.tree_.node_count树实际的总节点量
min_sample_split分枝所需最小样本量.tree_.n_node_samples每片叶子上实际的样本量
min_weight_fraction_leaf分枝所需最小
样本权重
tree_.weighted_n_node_samples每片叶子上实际的样本权重
min_impurity_decrease分枝所需最小
不纯度下降量
.tree_.impurity
.tree_.threshold
每片叶子上的实际不纯度
每个节点分枝后不纯度下降量

\bullet 属性.tree_.node_count

#所有树上的总节点数
for t in reg_f.estimators_:print(t.tree_.node_count)
1807
1777
1763
1821
1777
1781
1811
1771
1753
1779

\bullet 属性.tree_.threshold

#每个节点上的不纯度下降量,为负数则表示该节点是叶子节点
reg_f.estimators_[0].tree_.threshold.tolist()[:20]
[6.5,5.5,327.0,214.0,0.5,1.0,104.0,0.5,-2.0,-2.0,-2.0,105.5,28.5,0.5,1.5,-2.0,-2.0,11.0,1212.5,2.5]
#min_impurity_decrease的范围设置多少会剪掉多少叶子?
pd.Series(reg_f.estimators_[0].tree_.threshold).value_counts().sort_index()
-2.0       9040.5        431.0        321.5        562.0        32... 1118.5      11162.5      11212.5      21254.5      11335.5      1
Length: 413, dtype: int64

根据结果显示:对于第一棵树,有904个叶子节点;有43个节点不纯度下降为0.5;依此类推……

pd.set_option("display.max_rows",None)
np.cumsum(pd.Series(reg_f.estimators_[0].tree_.threshold).value_counts().sort_index()[1:])

从这棵树反馈的结果来看,min_impurity_decrease在现有数据集上至少要设置到[2,10]的范围才可能对模型有较大的影响。

更多属性可以参考:

from sklearn.tree._tree import Tree
help(Tree)

        现在模型正处于过拟合的状态,需要抗过拟合,且整体数据量不是非常多,随机抽样的比例不宜减小,因此我们挑选以下五个参数进行搜索:n_estimatorsmax_depthmax_featuresmin_impurity_decreasecriterion

2. 使用网格搜索在随机森林上进行调参

import numpy as np
import pandas as pd
import sklearn
import matplotlib as mlp
import matplotlib.pyplot as plt
import time #计时模块time
from sklearn.ensemble import RandomForestRegressor as RFR
from sklearn.model_selection import cross_validate, KFold, GridSearchCVdata=pd.read_csv('F:\\Jupyter Files\\机器学习进阶\\集成学习\\datasets\\House Price\\train_encode.csv',encoding='utf-8')
data.drop('Unnamed: 0', axis=1, inplace=True)
x=data.iloc[:,:-1]
y=data.iloc[:,-1]

step1 :建立benchmark

reg = RFR(random_state=1412)
cv = KFold(n_splits=5,shuffle=True,random_state=1412)
result_pre_adjusted = cross_validate(reg,x,y,cv=cv,scoring="neg_mean_squared_error",return_train_score=True,verbose=True)
def RMSE(cvresult,key):return (abs(cvresult[key])**0.5).mean()
RMSE(result_pre_adjusted,"train_score")
11177.272008319653
RMSE(result_pre_adjusted,"test_score")
30571.26665524217

step2:创建参数空间

param_grid_simple = {"criterion": ["squared_error","poisson"], 'n_estimators': [*range(20,100,5)], 'max_depth': [*range(10,25,2)], "max_features": ["log2","sqrt",16,32,64,"auto"], "min_impurity_decrease": [*np.arange(0,5,10)]}

step3:实例化用于搜索的评估器、交叉验证评估器与网格搜索评估器

reg = RFR(random_state=1412,verbose=True)
cv = KFold(n_splits=5,shuffle=True,random_state=1412)
search = GridSearchCV(estimator=reg,param_grid=param_grid_simple,scoring = "neg_mean_squared_error",verbose = True,cv = cv)

step4:训练网格搜索评估器

start = time.time()
search.fit(x,y)
print(time.time() - start)

ps:这部分代码跑了将近一个小时,但菜菜老师在实例化随机森林和网格搜索评估器的时候都加了参数n_jobs=-1,即调用全部线程,花了7分钟左右的时间。而我实例化的时候加n_jobs这个参数会报错(试了很多种方法都没法解决😅),最终只能不写,默认n_jobs=1,即只调用一个线程,跑了将近一个小时。(有没有小伙伴知道如何解决这个问题的欢迎来dd😊)

step5:查看结果

search.best_estimator_

ad_reg = RFR(n_estimators=85, max_depth=23, max_features=16, random_state=1412)
cv = KFold(n_splits=5,shuffle=True,random_state=1412)
result_post_adjusted = cross_validate(ad_reg,x,y,cv=cv,scoring="neg_mean_squared_error",return_train_score=True,verbose=True)
RMSE(result_post_adjusted,"train_score")
11000.81099038192
RMSE(result_post_adjusted,"test_score")
28572.070208366855
axis = range(1,6)
plt.figure(figsize=(8,6),dpi=80)plt.plot(xaxis,abs(result_pre_adjusted["train_score"])**0.5,color="green",label = "RF_pre_ad_Train")
plt.plot(xaxis,abs(result_pre_adjusted["test_score"])**0.5,color="green",linestyle="--",label = "RF_pre_ad_Test")
plt.plot(xaxis,abs(result_post_adjusted["train_score"])**0.5,color="orange",label = "RF_post_ad_Train")
plt.plot(xaxis,abs(result_post_adjusted["test_score"])**0.5,color="orange",linestyle="--",label = "RF_post_ad_Test")
plt.xticks([1,2,3,4,5])
plt.xlabel("CVcounts",fontsize=16)
plt.ylabel("RMSE",fontsize=16)
plt.legend()
plt.show()

不难发现,网格搜索之后的模型过拟合程度减轻,且在训练集与测试集上的结果都有提高,可以说从根本上提升了模型的基础能力。

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

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

相关文章

【Matlab】智能优化算法_麻雀搜索算法SSA

【Matlab】智能优化算法_麻雀搜索算法SSA 1.背景介绍2.数学模型3.文件结构4.伪代码5.详细代码及注释5.1 Get_Functions_details.m5.2 main.m5.3 SSA.m 6.运行结果7.参考文献 1.背景介绍 麻雀通常是群居的鸟类,有很多种类。它们分布在世界的大部分地区,喜…

【【51单片机的蜂鸣器-11】】

51单片机的蜂鸣器 DS1302我一直有问题搁置了几百天了 先来看看蜂鸣器 搞了一个礼拜verilog然后出去吃饭 估计自己得有10多天没看c语言和51单片机了 现在先处理一下蜂鸣器的问题 蜂鸣器 蜂鸣器分为有源蜂鸣器和无源蜂鸣器 有源内部自带震荡源,将正负极接上直流电压…

Spring的创建和使用

文章目录 一、通过Maven创建一个Spring项目准备工作(第一次需要配置)1.创建一个Maven项目2.引入依赖(spring-context、spring-beans)3.添加启动类 二、存储Bean对象1.创建一个Bean对象2.把Bean对象存储到Spring中 三、获取Bean对象…

招聘小程序制作:连接人才与企业

随着人才市场的竞争日益激烈,招聘小程序成为了企业寻找优秀人才和求职者找到理想工作的重要工具。通过招聘小程序,企业可以发布招聘信息、筛选简历,而求职者可以浏览职位、提交简历等。 招聘小程序的好处 精准匹配人才:招聘小程序…

二叉树的右视图

给定一个二叉树的 根节点 root,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。 示例 1: 输入: [1,2,3,null,5,null,4] 输出: [1,3,4] 示例 2: 输入: [1,null,3] 输出: [1,3] 示例 3: 输入: [] 输出: [] 代…

k8s Label 2

在 k8s 中,我们会轻轻松松的部署几十上百个微服务,这些微服务的版本,副本数的不同进而会带出更多的 pod 这么多的 pod ,如何才能高效的将他们组织起来的,如果组织不好便会让管理微服务变得混乱不堪,杂乱无…

VScode 右键菜单加入使用用VSCode打开文件和文件夹【Windows】

VScode 右键菜单加入使用用VSCode打开文件和文件夹【Windows】 介绍修改注册表添加右键打开文件属性修改注册表添加右键打开文件夹属性修改注册表添加右键空白区域属性 介绍 鼠标右击文件或者文件夹,可直接用VSCode打开,非常方便。但如果我们在安装VSCo…

工厂方法模式详解

文章目录 前言一、工厂方法模式的定义二、举个例子三、工厂方法模式的缺点总结 前言 工厂方法模式是应用比较广泛的一种设计模式,它相对于简单工厂模式进行了一些优化,如果再增加一个具体产品不用修改代码,也不会违反开闭原则。 一、工厂方法…

暴雪娱乐遭DDoS攻击,《暗黑破坏神》等多款游戏受影响

6月25日上午11点,有游戏玩家反应Blizzard Battle.net无法登入、连线缓慢及网站问题,暴雪也证实其电玩平台遭到DDoS攻击。 暴雪娱乐的 Battle.net在线服务遭到分布式拒绝服务(DDoS)攻击,导致玩家无法正常登录游戏或游戏…

VSCode下载安装(保姆级--一步到胃)

前言 Visual Studio Code(简称“VSCode” )是Microsoft在2015年4月30日Build开发者大会上正式宣布一个运行于 Mac OS X、Windows和 Linux 之上的,针对于编写现代Web和云应用的跨平台源代码编辑器,可在桌面上运行,并且…

SAP CAP篇十:理解Fiori UI的Annoation定义

本文目录 本系列此前的文章官方文档和基础概念SAP CAP对Fiori UI的支持package.json的新增内容Annotation定义List Page 生成的Edmx文件 对应代码及branch 本系列此前的文章 SAP CAP篇一: 快速创建一个Service,基于Java的实现 SAP CAP篇二:为Service加上…

TypeScript 学习笔记(七):条件类型

条件类型 TS中的条件类型就是在类型中添加条件分支,以支持更加灵活的泛型,满足更多的使用场景。内置条件类型是TS内部封装好的一些类型处理,使用起来更加便利。 一、基本用法 当T类型可以赋值给U类型时,则返回X类型&#xff0c…

小程序首页轮播图设计

效果图 微信小程序的数据详解 indicator-dots:是否显示面板指示点【默认false 】 indicator-color:指示点颜色【默认rgba(0, 0, 0, .3)】 indicator-active-color:当前选中的指示点颜色【默认#000000】 autoplay:是否自动切换…

Redis的过期策略以及内存淘汰机制

目录 一、过期策略1.1、定时删除1.1.1、过期1.1.2、过期的 key 集合1.1.3、定时扫描策略1.1.4、 Redis 中所有的 key 在同一时间过期了,会出现怎样的结果1.1.5、从库的过期策略 1.2、惰性删除1.3、定时删除和惰性删除的总结 二、缓存淘汰算法2.1、缓存淘汰算法概述2…

ngsoc使用指南

和威胁告警差不多。 ngsoc是以资产为核心,以安全事件为管理的关键流程,建立一套威胁检测,相应,预测,和持续监控分析,一体化的监控与相应平台。 和天眼的区别:会把天眼的告警,其他安…

MFC扩展库BCGControlBar Pro v33.5新版亮点 - 其他增强功能

BCGControlBar库拥有500多个经过全面设计、测试和充分记录的MFC扩展类。 我们的组件可以轻松地集成到您的应用程序中,并为您节省数百个开发和调试时间。 BCGControlBar专业版 v33.5已正式发布了,此版本包含了Ribbon(功能区)自定义…

Ansible自动化运维工具的认识

目录 一、Ansible概述 二、Ansible特点 三、Ansible应用 1、使用者 2、Ansible工具集合 3、作用对象 四、Ansible的搭建 1、实验环境 2、环境准备 Ansible: 3、创建ssh免密交互登录 client端环境准备 五、Ansible配置 六、Ansible命令 1、ansible 实…

【软件测试】web测试bug定位思路总结,“我“不再背锅...

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 需要掌握的知识 …

ASUS华硕ROG幻14 2021款GA401QM原厂Win10系统工厂模式带ASUS Recovery恢复功能

自带恢复分区、所有驱动、出厂主题壁纸LOGO、Office办公软件、奥创控制中心等预装程序 所需要工具:16G或以上的U盘(非必需) 文件格式:HDI,SWP,OFS,EDN,KIT,TLK多个底包 文件大小:11.34GB 注:恢复时会清空电脑上所有盘的数据&…

系列七、VMware中的CentOS服务不息屏

一、场景 VMware中安装好CentOS7等虚拟机后,过一段时间会自动息屏,这个时候如果想执行操作,需要重新输入 用户名/密码,体验感不好。 二、解决方法 应用程序》系统工具》设置》Privacy》锁屏》自动锁屏(关闭&#xff0…