机器学习网格搜索超参数优化实战(随机森林) ##4

文章目录

  • 基于Kaggle电信用户流失案例数据(可在官网进行下载)
    • 数据预处理模块
    • 时序特征衍生
    • 第一轮网格搜索
    • 第二轮搜索
    • 第三轮搜索
    • 第四轮搜索
    • 第五轮搜索

基于Kaggle电信用户流失案例数据(可在官网进行下载)

导入库

# 基础数据科学运算库
import numpy as np
import pandas as pd# 可视化库
import seaborn as sns
import matplotlib.pyplot as plt# 时间模块
import timeimport warnings
warnings.filterwarnings('ignore')# sklearn库
# 数据预处理
from sklearn import preprocessing
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import OrdinalEncoder
from sklearn.preprocessing import OneHotEncoder# 实用函数
from sklearn.metrics import accuracy_score, recall_score, precision_score, f1_score, roc_auc_score
from sklearn.model_selection import train_test_split# 常用评估器
from sklearn.pipeline import make_pipeline
from sklearn.linear_model import LogisticRegression
from sklearn import tree
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier# 网格搜索
from sklearn.model_selection import GridSearchCV# 自定义评估器支持模块
from sklearn.base import BaseEstimator, TransformerMixin# re模块相关
import inspect, re# 其他模块
from tqdm import tqdm
import gc

数据预处理模块

然后进行数据清洗相关工作:

# 读取数据
tcc = pd.read_csv('WA_Fn-UseC_-Telco-Customer-Churn.csv')# 标注连续/离散字段
# 离散字段
category_cols = ['gender', 'SeniorCitizen', 'Partner', 'Dependents','PhoneService', 'MultipleLines', 'InternetService', 'OnlineSecurity', 'OnlineBackup', 'DeviceProtection', 'TechSupport', 'StreamingTV', 'StreamingMovies', 'Contract', 'PaperlessBilling','PaymentMethod']# 连续字段
numeric_cols = ['tenure', 'MonthlyCharges', 'TotalCharges']# 标签
target = 'Churn'# ID列
ID_col = 'customerID'# 验证是否划分能完全
assert len(category_cols) + len(numeric_cols) + 2 == tcc.shape[1]# 连续字段转化
tcc['TotalCharges']= tcc['TotalCharges'].apply(lambda x: x if x!= ' ' else np.nan).astype(float)
tcc['MonthlyCharges'] = tcc['MonthlyCharges'].astype(float)# 缺失值填补
tcc['TotalCharges'] = tcc['TotalCharges'].fillna(0)# 标签值手动转化 
tcc['Churn'].replace(to_replace='Yes', value=1, inplace=True)
tcc['Churn'].replace(to_replace='No',  value=0, inplace=True)features = tcc.drop(columns=[ID_col, target]).copy()
labels = tcc['Churn'].copy()

时序特征衍生

# 定义辅助函数
def colName(ColumnTransformer, numeric_cols, category_cols):col_name = []col_value = ColumnTransformer.named_transformers_['cat'].categories_for i, j in enumerate(category_cols):if len(col_value[i]) == 2:col_name.append(j)else:for f in col_value[i]:feature_name = j + '_' + fcol_name.append(feature_name)col_name.extend(numeric_cols)return(col_name)

进行简单的时序特征衍生:

# 划分训练集和测试集
train, test = train_test_split(tcc, random_state=22)X_train = train.drop(columns=[ID_col, target]).copy()
X_test = test.drop(columns=[ID_col, target]).copy()y_train = train['Churn'].copy()
y_test = test['Churn'].copy()X_train_seq = pd.DataFrame()
X_test_seq = pd.DataFrame()# 年份衍生
X_train_seq['tenure_year'] = ((72 - X_train['tenure']) // 12) + 2014
X_test_seq['tenure_year'] = ((72 - X_test['tenure']) // 12) + 2014# 月份衍生
X_train_seq['tenure_month'] = (72 - X_train['tenure']) % 12 + 1
X_test_seq['tenure_month'] = (72 - X_test['tenure']) % 12 + 1# 季度衍生
X_train_seq['tenure_quarter'] = ((X_train_seq['tenure_month']-1) // 3) + 1
X_test_seq['tenure_quarter'] = ((X_test_seq['tenure_month']-1) // 3) + 1# 独热编码
enc = preprocessing.OneHotEncoder()
enc.fit(X_train_seq)seq_new = list(X_train_seq.columns)# 创建带有列名称的独热编码之后的df
X_train_seq = pd.DataFrame(enc.transform(X_train_seq).toarray(), columns = cate_colName(enc, seq_new, drop=None))X_test_seq = pd.DataFrame(enc.transform(X_test_seq).toarray(), columns = cate_colName(enc, seq_new, drop=None))# 调整index
X_train_seq.index = X_train.index
X_test_seq.index = X_test.index
ord_enc = OrdinalEncoder()
ord_enc.fit(X_train[category_cols])X_train_OE = pd.DataFrame(ord_enc.transform(X_train[category_cols]), columns=category_cols)
X_train_OE.index = X_train.index
X_train_OE = pd.concat([X_train_OE, X_train[numeric_cols]], axis=1)X_test_OE = pd.DataFrame(ord_enc.transform(X_test[category_cols]), columns=category_cols)
X_test_OE.index = X_test.index
X_test_OE = pd.concat([X_test_OE, X_test[numeric_cols]], axis=1)

第一轮网格搜索

NameDescription
n_estimators决策树模型个数
criterion规则评估指标或损失函数,默认基尼系数,可选信息熵
splitter树模型生长方式,默认以损失函数取值减少最快方式生长,可选随机根据某条件进行划分
max_depth树的最大生长深度,类似max_iter,即总共迭代几次
min_samples_split内部节点再划分所需最小样本数
min_samples_leaf叶节点包含最少样本数
min_weight_fraction_leaf叶节点所需最小权重和
max_features在进行切分时候最多带入多少个特征进行划分规则挑选
random_state随机数种子
max_leaf_nodes叶节点最大个数
min_impurity_decrease数据集再划分至少需要降低的损失值
bootstrap是否进行自助抽样
oob_score是否输出袋外数据的测试结果
min_impurity_split数据集再划分所需最低不纯度,将在0.25版本中移除
class_weight各类样本权重
ccp_alpha决策树限制剪枝参数,相当于风险项系数
max_samples进行自助抽样时每棵树分到的样本量

  随机森林需要搜索的7个参数及其第一轮搜索时建议的参数空间如下:

params经验最优范围
min_samples_leaf[1, 4, 7]; range(1, 10, 3)
min_samples_split[1, 4, 7]; range(1, 10, 3)
max_depth[5, 10, 15]; range(5, 16, 5)
max_leaf_nodes[None, 20, 40, 60]; [None] + list(range(20, 70, 20))
n_estimators[10, 80, 150]; range(10, 160, 70)
max_features[‘sqrt’, ‘log2’] +[ l o g 2 ( m ) log_2{(m)} log2(m)*50%, m \sqrt{m} m *150%] 其中m为特征数量
max_samples[None, 0.4, 0.5, 0.6]
start = time.time()# 设置超参数空间
parameter_space = {"min_samples_leaf": range(1, 10, 3), "min_samples_split": range(1, 10, 3),"max_depth": range(5, 16, 5),"max_leaf_nodes": [None] + list(range(20, 70, 20)), "n_estimators": range(10, 160, 70), "max_features":['sqrt', 'log2'] + list(range(2, 7, 2)), "max_samples":[None, 0.4, 0.5, 0.6]}# 实例化模型与评估器
RF_0 = RandomForestClassifier(random_state=12)
grid_RF_0 = GridSearchCV(RF_0, parameter_space, n_jobs=15)# 模型训练
grid_RF_0.fit(X_train_OE, y_train)grid_RF_0.score(X_train_OE, y_train), grid_RF_0.score(X_test_OE, y_test)

对比之前逻辑回归结果显示:

ModelsCV.best_score_train_scoretest_score
Logistic+grid0.80450.80550.7932
RF+grid_R10.80840.85170.7848
# 查看超参数最优取值
grid_RF_0.best_params_

在这里插入图片描述

  • max_depth本轮最优取值为10,而原定搜索空间为[5, 10, 15],因此第二轮搜索时就可以以10为中心,缩小步长,进行更精准的搜索;
  • max_features本轮最优取值为sqrt,说明最优解极有可能在4附近,因此第二轮搜索时可以设置一组更加精准的在4附近的数值,搭配sqrt参数一起进行搜索;
  • max_leaf_nodes本轮最优取值为None,则有可能说明上一轮给出的其他备选数值不够激进,下一轮搜索时可以在一个更大的区间范围内设置备选数值;
  • max_samples本轮最优取值为0.4,下一轮可以以0.4为中心,设置一组跨度更小、精度更高的取值进行搜索;
  • min_samples_leaf本轮最优取值为1,下一轮可以设置range(1, 4)进行搜索(参数不能取得比1更小的值);
  • min_samples_split本轮最优取值为7,下一轮可以以7为中心,设置更小的范围进行搜索;
  • n_estimators本轮最优取值为80,下一轮可以以80为中心,设置更小的范围进行搜索,但需要注意的是,上一轮n_estimators取值搜索的跨度为70,下轮搜索时可以缩减到10。

第二轮搜索

start = time.time()# 设置超参数空间
parameter_space = {"min_samples_leaf": range(1, 4), "min_samples_split": range(6, 9),"max_depth": range(9, 12),"max_leaf_nodes": [None] + list(range(10, 100, 30)), "n_estimators": range(70, 100, 10), "max_features":['sqrt'] + list(range(2, 5)), "max_samples":[None, 0.35, 0.4, 0.45]}# 实例化模型与评估器
RF_0 = RandomForestClassifier(random_state=12)
grid_RF_0 = GridSearchCV(RF_0, parameter_space, n_jobs=15)# 模型训练
grid_RF_0.fit(X_train_OE, y_train)grid_RF_0.score(X_train_OE, y_train), grid_RF_0.score(X_test_OE, y_test)
ModelsCV.best_score_train_scoretest_score
Logistic+grid0.80450.80550.7932
RF+grid_R10.80840.85170.7848
RF+grid_R20.80880.84590.7922
grid_RF_0.best_params_

在这里插入图片描述

  • max_depth本轮最优取值为11,在原定搜索空间上界,下次搜索可以进一步向上拓展搜索空间;
  • max_features本轮最优取值为2,是原定搜索空间的下界,下次搜索可向下拓展搜索空间,也就是将1带入进行搜索。但需要注意的是,sqrt作为非数值型结果,仍然需要带入进行搜索,这轮被淘汰并不代表重新调整搜索空间后仍然被淘汰;
  • max_leaf_nodes本轮最优取值仍然为None,说明在一个更大的范围内进行更激进的搜索并没有达到预想的效果,下一轮可以反其道而行之,设置一个上一轮没有搜索到的数值较小的空间(1-20),来进行更加精准的搜索;
  • max_samples本轮最优取值仍然为0.4,基本可以确定最优取值就在0.4附近,下一轮可以进一步设置一个步长更小的区间进行搜索;
  • min_samples_leaf本轮最优取值为2,恰好落在本轮搜索空间的中间,下一轮搜索时不用调整取值;
  • min_samples_split本轮最优取值仍然为7,恰好落在本轮搜索空间的中间,下一轮搜索时不用调整取值;
  • n_estimators本轮最优取值为90,下一轮可以以90为中心,设置更小的范围进行搜索,但需要注意的是,上一轮n_estimators取值搜索的跨度为10,下轮搜索时可以缩减到4。

第三轮搜索

start = time.time()# 设置超参数空间
parameter_space = {"min_samples_leaf": range(1, 4), "min_samples_split": range(6, 9),"max_depth": range(10, 15),"max_leaf_nodes": [None] + list(range(1, 20, 2)), "n_estimators": range(85, 100, 4), "max_features":['sqrt'] + list(range(1, 4)), "max_samples":[None, 0.38, 0.4, 0.42]}# 实例化模型与评估器
RF_0 = RandomForestClassifier(random_state=12)
grid_RF_0 = GridSearchCV(RF_0, parameter_space, n_jobs=15)# 模型训练
grid_RF_0.fit(X_train_OE, y_train)grid_RF_0.score(X_train_OE, y_train), grid_RF_0.score(X_test_OE, y_test)
ModelsCV.best_score_train_scoretest_score
Logistic+grid0.80450.80550.7932
RF+grid_R10.80840.85170.7848
RF+grid_R20.8087850.84590.7922
RF+grid_R30.8087840.84150.7927
grid_RF_0.best_params_

在这里插入图片描述

  • max_depth本轮最优取值为10,在原定搜索空间下界,下次搜索可以进一步向下拓展搜索空间,当然,根据第二轮第三轮max_depth在9和10反复变动的现象,估计max_depth最终的最优取值也就是9、10左右;
  • max_features本轮最优取值又回到了sqrt,也就是4附近,结合第一轮sqrt的最优结果,预计max_features最终最优取值也就在4附近,接下来的搜索将是收尾阶段,我们可以设计一个sqrt+log2+4附近的搜索组合;
  • max_leaf_nodes本轮最优取值仍然为None,三轮搜索都没有改变max_leaf_nodes的最优取值,并且本轮还设置了非常多的备选取值,说明max_leaf_nodes的最优取值极有可能就是None,接下来我们只需保留None+大范围搜索的组合即可,以防其他参数变动时max_leaf_nodes的最优取值发生变化;
  • max_samples本轮最优取值变成了0.38,而训练集总样本数为5282,5282*0.38约为2007,下轮开始我们将把比例转化为具体的样本数,进行更加精准的搜索,及围绕2007附近的数值空间进行搜索;
  • min_samples_leaf本轮最优取值为3,恰好落在本轮搜索空间的上届,下一轮搜索时略微拓展搜索空间的上界;
  • min_samples_split本轮最优取值仍然为7,恰好落在本轮搜索空间的中间,下一轮搜索时不用调整取值;
  • n_estimators本轮最优取值为97,下一轮可以以97为中心,设置更小的范围进行搜索;

第四轮搜索

start = time.time()# 设置超参数空间
parameter_space = {"min_samples_leaf": range(2, 5), "min_samples_split": range(6, 9),"max_depth": range(8, 12),"max_leaf_nodes": [None] + list(range(10, 70, 20)), "n_estimators": range(95, 105, 2), "max_features":['sqrt', 'log2'] + list(range(1, 6, 2)), "max_samples":[None] + list(range(2002, 2011, 2))}# 实例化模型与评估器
RF_0 = RandomForestClassifier(random_state=12)
grid_RF_0 = GridSearchCV(RF_0, parameter_space, n_jobs=15)# 模型训练
grid_RF_0.fit(X_train_OE, y_train)grid_RF_0.score(X_train_OE, y_train), grid_RF_0.score(X_test_OE, y_test)
ModelsCV.best_score_train_scoretest_score
Logistic+grid0.80450.80550.7932
RF+grid_R10.80840.85170.7848
RF+grid_R20.8087850.84590.7922
RF+grid_R30.8087840.84150.7927
RF+grid_R40.8095420.84060.7882
grid_RF_0.best_params_

在这里插入图片描述- max_depth本轮最优取值为9,能够进一步肯定max_depth最终的最优取值也就是9、10左右;

  • max_features本轮最优取值变成了5,仍然在4附近变化,后续继续保留sqrt+log2+4附近的搜索组合;
  • max_leaf_nodes本轮最优取值仍然为None,并没有发生任何变化,后续仍然保留原定搜索范围;
  • max_samples本轮最优取值为2002,这是第一次围绕max_samples进行整数搜索,接下来可以以2002为中心,设置一个更小搜索空间;
  • min_samples_leaf本轮最优取值为3,恰好落在本轮搜索空间的上届,下一轮搜索时略微拓展搜索空间的上界;
  • min_samples_split本轮最优取值变成了8,根据之前的搜索结果,该参数最优取值基本都在7和8之间变动,因此可以设置一个6-9的搜索空间,确保下次如果再出现参数在7、8之间变动时,仍然在搜索范围内;
  • n_estimators本轮最优取值为99,结合之前搜索出来的97的结果,预计该参数最终的最优取值应该就是97-99之间,可以据此设置下一轮搜索空间;

第五轮搜索

# "min_samples_leaf":以3为中心
# "min_samples_split":重点搜索7、8两个值
# "max_depth":重点搜索9、10两个值
# "max_leaf_nodes":大概率为None
# "n_estimators": 重点搜索97、98、99三个值
# "max_features":5附近的值+['sqrt', 'log2']
# "max_samples":2002向下搜索,重点搜索2002、2001和2000三个值# 设置超参数空间
parameter_space = {"min_samples_leaf": range(2, 5), "min_samples_split": range(6, 10),"max_depth": range(8, 12),"max_leaf_nodes": [None], "n_estimators": range(96, 101), "max_features":['sqrt', 'log2'] + list(range(3, 7)), "max_samples":[None] + list(range(2000, 2005))}# 实例化模型与评估器
RF_0 = RandomForestClassifier(random_state=12)
grid_RF_0 = GridSearchCV(RF_0, parameter_space, n_jobs=15)# 模型训练
grid_RF_0.fit(X_train_OE, y_train)grid_RF_0.score(X_train_OE, y_train), grid_RF_0.score(X_test_OE, y_test)
ModelsCV.best_score_train_scoretest_score
Logistic+grid0.80450.80550.7932
RF+grid_R10.80840.85170.7848
RF+grid_R20.8087850.84590.7922
RF+grid_R30.8087840.84150.7927
RF+grid_R40.8095420.84060.7882
RF+grid_R50.8104880.84830.7955
grid_RF_0.best_params_

在这里插入图片描述
至此,大致得到最优结果,往后调优思路可大致照此.

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

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

相关文章

单片机学习笔记---LCD1602功能函数代码

目录 LCD1602.c 模拟写指令的时序 模拟写数据的时序 初始化 显示字符 显示字符串 显示数字 显示有符号的数字 显示16进制数字 显示二进制数 LCD1602.h main.c 上一篇讲了LCD1602的工作原理,这一节开始代码演示! 新创建工程:LCD1…

Java学习第十四节之多维数组和Arrays类讲解

多维数组 package array;public class ArrayDemo05 {public static void main(String[] args) {//[4][2] 面向对象/*1,2 array[0]2,3 array[1]3,4 array[2]4,5 array[3]*/int[][] array {{1,2},{2,3},{3,4},{4,5}};for (int i 0; i <array.length; i) {for (int…

MyBatis篇----第六篇

系列文章目录 文章目录 系列文章目录前言一、什么是 MyBatis 的接口绑定?有哪些实现方式?二、使用 MyBatis 的 mapper 接口调用时有哪些要求?三、Mapper 编写有哪几种方式?前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳…

Java实现课程案例资源库系统 JAVA+Vue+SpringBoot+MySQL

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 管理员需求分析2.2 用户需求分析 三、系统设计3.1 业务流程设计3.1.1 管理员业务流程设计3.1.2 用户业务流程设计3.1.3 首页功能模块及业务流程分析3.1.4 案例资源中心功能模块及业务流程分析3.1.5 用户信息中心功能模块…

[GXYCTF2019]禁止套娃

进来发现只有这句话&#xff0c;习惯性访问一下flag.php&#xff0c;发现不是404&#xff0c;那就证明flag就在这了&#xff0c;接下来要想办法拿到flag.php的源码。 这道题是.git文件泄露网页源码&#xff0c;githack拿到index.php源码 这里观察到多次判断&#xff0c;首先要…

Python实现MACD指标计算:股票技术分析的利器系列(1)

Python实现MACD指标计算&#xff1a;股票技术分析的利器系列&#xff08;1&#xff09; 介绍核心代码&#xff1a;EMA核心代码&#xff1a;MACD200 次交易日的收盘价格完整代码最终运行代码的效果展示DIFDEAMACD 介绍 先看看官方介绍&#xff1a; MACD (平滑异同平均线&#x…

AlmaLinux更换鼠标样式为Windows样式

文章目录 前言先看看条件与依赖第一步&#xff1a;测试最终效果第二步&#xff1a;使用CursorXP修改鼠标样式CurosrXP安装CursorXP使用 第三步&#xff1a;Linux端环境搭建与命令执行UbuntuFedora其他系统均失败 第四步&#xff1a;应用主题 前言 只不过是突发奇想&#xff0c…

扶贫|精准扶贫管理系统|基于Springboot的精准扶贫管理系统设计与实现(源码+数据库+文档)

精准扶贫管理系统目录 目录 基于Springboot的精准扶贫管理系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、管理员模块的实现 &#xff08;1&#xff09;用户信息管理 &#xff08;2&#xff09;贫困户信息管理 &#xff08;3&#xff09;新闻类型管理 &a…

Virt a Mate(VAM)游戏折腾记录

如有更新见原文&#xff1a;https://blog.iyatt.com/?p13283 1 前言 如果在网上看到有些视频名字带有 VAM 的&#xff0c;可能就是玩这个游戏录屏的。这个游戏可以建模、操作模型动作、构建场景等等。之前大致知道有这么个东西&#xff0c;只是电脑配置太差了&#xff0c;新…

AGV|RGV基本概念及导航分类与差异

AGV是自动导引运输车&#xff0c;装备采用电磁或光学等自动导引装置&#xff0c;能够沿规定的导引路径行驶&#xff0c;具有安全保护以及各种移载功能的运输车。其导航方式主要分磁条|磁钉导航、激光导航、激光反光板、激光自然导航、二维码导航、惯性导航等方式&#xff0c;广…

洛谷C++简单题小练习day12—寻找最小值小程序

day12--寻找最小值--2.16 习题概述 题目描述 给出 n 和 n 个整数 ai​&#xff0c;求这 n 个整数中最小值是什么。 输入格式 第一行输入一个正整数 n&#xff0c;表示数字个数。 第二行输入 n 个非负整数&#xff0c;表示 1,2…a1​,a2​…an​&#xff0c;以空格隔开。 …

【数位dp】【动态规划】【状态压缩】【推荐】1012. 至少有 1 位重复的数字

作者推荐 视频算法专题 本文涉及知识点 动态规划汇总 LeetCode:1012. 至少有 1 位重复的数字 给定正整数 n&#xff0c;返回在 [1, n] 范围内具有 至少 1 位 重复数字的正整数的个数。 示例 1&#xff1a; 输入&#xff1a;n 20 输出&#xff1a;1 解释&#xff1a;具有至…