多个树模型特征贡献度与可视化

news2024/9/28 10:04:19

背景

在机器学习中,特征的重要性是了解模型如何做出预测的关键指标之一,在树模型中,特征重要性通常通过特征的分裂节点来衡量,通过观察特征在模型中的贡献,可以对数据集中的重要特征有更深入的理解,之前的文章中,分别介绍了如何通过RF、 XGBoost 和 LightGBM 来提取特征贡献度,在本篇文章中,将加入 CatBoost 模型,并进行可视化综合比较这些树模型中的特征重要性

加载数据

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
plt.rcParams['font.family'] = 'Times New Roman'
plt.rcParams['axes.unicode_minus'] = False
df = pd.read_excel('气象、环境、火灾烧毁.xlsx')

# 划分特征和目标变量
X = df.drop(['month', 'day', 'area'], axis=1)
y = df['area']
# 划分训练集和测试集
# 注意:random_state=42 是为了确保结果的可复现性,并且针对该数据集进行了特定处理。读者在使用自己的数据时,可以自由修改此参数。
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, 
                                                    random_state=42)
df.head()

"这个数据集包含了气象、环境和火灾信息,其中X、Y表示地理位置,month和day是日期信息,FFMC、DMC、DC、ISI是火灾相关的气象指数,temp表示温度,RH是湿度,wind是风速,rain是降雨量,area是火灾烧毁的面积,在建模时,我们未使用日期信息(month 和 day)

多个模型训练

对四种常用的树模型(随机森林、XGBoost、LightGBM 和 CatBoost)的回归任务进行建模,首先,为每个模型设置初始参数,并定义用于网格搜索的超参数范围(如,树的数量、深度、学习率等),然后,通过 GridSearchCV 对每个模型进行 5 折交叉验证,在不同的超参数组合下寻找最佳模型配置,优化评价指标为负均方误差(MSE),模型训练完成后,还原计算最优模型的均方根误差(RMSE),作为模型性能的评估标准。最后,使用这些最优参数重新训练模型以得到最终模型

from sklearn.ensemble import RandomForestRegressor

# 创建随机森林回归器实例,并设置参数
rf_regressor = RandomForestRegressor(
    n_estimators=100,         # 'n_estimators'是森林中树的数量。默认是100,可以根据需要调整。
    criterion='squared_error', # 'criterion'参数指定用于拆分的质量指标。'squared_error'(默认)表示使用均方误差,另一选项是'absolute_error'。
    max_depth=None,           # 'max_depth'限制每棵树的最大深度。'None'表示不限制深度。
    min_samples_split=2,      # 'min_samples_split'指定一个节点分裂所需的最小样本数。默认是2。
    min_samples_leaf=1,       # 'min_samples_leaf'指定叶子节点所需的最小样本数。默认是1。
    min_weight_fraction_leaf=0.0, # 'min_weight_fraction_leaf'与'min_samples_leaf'类似,但基于总样本权重。默认是0.0。
    random_state=42,          # 'random_state'控制随机数生成,以便结果可复现。42是一个常用的随机种子。
    max_leaf_nodes=None,      # 'max_leaf_nodes'限制每棵树的最大叶子节点数。'None'表示不限制。
    min_impurity_decrease=0.0 # 'min_impurity_decrease'在分裂节点时要求的最小不纯度减少量。默认是0.0。
)

# 训练模型
rf_regressor.fit(X_train, y_train)

import xgboost as xgb
from sklearn.model_selection import GridSearchCV

# XGBoost回归模型参数
params_xgb = {
    'learning_rate': 0.02,            # 学习率,控制每一步的步长,用于防止过拟合。典型值范围:0.01 - 0.1
    'booster': 'gbtree',              # 提升方法,这里使用梯度提升树(Gradient Boosting Tree)
    'objective': 'reg:squarederror',  # 损失函数,这里使用平方误差,适用于回归任务
    'max_leaves': 127,                # 每棵树的叶子节点数量,控制模型复杂度
    'verbosity': 1,                   # 控制 XGBoost 输出信息的详细程度,0表示无输出,1表示输出进度信息
    'seed': 42,                       # 随机种子,用于重现模型的结果
    'nthread': -1,                    # 并行运算的线程数量,-1表示使用所有可用的CPU核心
    'colsample_bytree': 0.6,          # 每棵树随机选择的特征比例,用于增加模型的泛化能力
    'subsample': 0.7,                 # 每次迭代时随机选择的样本比例,用于增加模型的泛化能力
    'eval_metric': 'rmse'             # 评价指标,这里使用均方根误差(rmse)
}

# 初始化XGBoost回归模型
model_xgb = xgb.XGBRegressor(**params_xgb)

# 定义参数网格,用于网格搜索
param_grid = {
    'n_estimators': [100, 200, 300, 400, 500],  # 树的数量
    'max_depth': [3, 4, 5, 6, 7],               # 树的深度
    'learning_rate': [0.01, 0.02, 0.05, 0.1],   # 学习率
}

# 使用GridSearchCV进行网格搜索和k折交叉验证
grid_search = GridSearchCV(
    estimator=model_xgb,
    param_grid=param_grid,
    scoring='neg_mean_squared_error',  # 评价指标为负均方误差
    cv=5,                              # 5折交叉验证
    n_jobs=-1,                         # 并行计算
    verbose=1                          # 输出详细进度信息
)

# 训练模型
grid_search.fit(X_train, y_train)

# 输出最优参数
print("Best parameters found: ", grid_search.best_params_)
print("Best RMSE score: ", (-grid_search.best_score_) ** 0.5)  # 还原RMSE

# 使用最优参数训练模型
best_model_xgboost = grid_search.best_estimator_

import lightgbm as lgb

# LightGBM回归模型参数
params_lgb = {
    'learning_rate': 0.02,             # 学习率,控制每一步的步长,用于防止过拟合
    'boosting_type': 'gbdt',           # 提升方法,这里使用梯度提升决策树
    'objective': 'regression',         # 损失函数,这里使用回归任务
    'num_leaves': 127,                 # 每棵树的叶子节点数量,控制模型复杂度
    'verbosity': 1,                    # 控制 LightGBM 输出信息的详细程度
    'seed': 42,                        # 随机种子,用于重现模型的结果
    'n_jobs': -1,                      # 并行运算的线程数量,-1表示使用所有可用的CPU核心
    'colsample_bytree': 0.6,           # 每棵树随机选择的特征比例,用于增加模型的泛化能力
    'subsample': 0.7,                  # 每次迭代时随机选择的样本比例,用于增加模型的泛化能力
    'metric': 'rmse'                   # 评价指标,这里使用均方根误差(rmse)
}

# 初始化LightGBM回归模型
model_lgb = lgb.LGBMRegressor(**params_lgb)

# 定义参数网格,用于网格搜索
param_grid = {
    'n_estimators': [100, 200, 300, 400, 500],  # 树的数量
    'max_depth': [3, 4, 5, 6, 7],               # 树的深度
    'learning_rate': [0.01, 0.02, 0.05, 0.1],   # 学习率
}

# 使用GridSearchCV进行网格搜索和k折交叉验证
grid_search = GridSearchCV(
    estimator=model_lgb,
    param_grid=param_grid,
    scoring='neg_mean_squared_error',  # 评价指标为负均方误差
    cv=5,                              # 5折交叉验证
    n_jobs=-1,                         # 并行计算
    verbose=1                          # 输出详细进度信息
)

# 训练模型
grid_search.fit(X_train, y_train)

# 输出最优参数
print("Best parameters found: ", grid_search.best_params_)
print("Best RMSE score: ", (-grid_search.best_score_) ** 0.5)  # 还原RMSE

# 使用最优参数训练模型
best_model_lgb = grid_search.best_estimator_

import catboost as cb

# CatBoost回归模型参数
params_catboost = {
    'learning_rate': 0.02,            # 学习率,控制每一步的步长
    'loss_function': 'RMSE',          # 损失函数,这里使用均方根误差(RMSE)
    'eval_metric': 'RMSE',            # 评价指标,这里同样使用RMSE
    'random_seed': 42,                # 随机种子
    'verbose': 100,                   # 控制 CatBoost 输出信息的详细程度,输出每100次迭代的进度
    'thread_count': -1,               # 使用所有可用的CPU核心
    'bootstrap_type': 'Bernoulli',    # 自举类型,用于控制模型的泛化能力
    'subsample': 0.7,                 # 每次迭代时随机选择的样本比例
    'colsample_bylevel': 0.6          # 每层随机选择的特征比例,用于增加模型的泛化能力
}

# 初始化CatBoost回归模型
model_catboost = cb.CatBoostRegressor(**params_catboost)

# 定义参数网格,用于网格搜索
param_grid = {
    'iterations': [100, 200],  # 迭代次数(等价于树的数量)
    'depth': [3, 4],                 # 树的深度
    'learning_rate': [0.05, 0.1], # 学习率
}

# 使用GridSearchCV进行网格搜索和k折交叉验证
grid_search = GridSearchCV(
    estimator=model_catboost,
    param_grid=param_grid,
    scoring='neg_mean_squared_error',  # 评价指标为负均方误差
    cv=5,                              # 5折交叉验证
    n_jobs=-1,                         # 并行计算
)

# 训练模型
grid_search.fit(X_train, y_train)

# 输出最优参数
print("Best parameters found: ", grid_search.best_params_)
print("Best RMSE score: ", (-grid_search.best_score_) ** 0.5)  # 还原RMSE

# 使用最优参数训练模型
best_model_catboost = grid_search.best_estimator_

多模型特征重要性提取

提取和排序随机森林、XGBoost、LightGBM 和 CatBoost 模型的特征重要性,生成一个包含各模型特征贡献度的 DataFrame,以便比较不同模型对特征重要性的评估差异,代码在获取特征贡献度时,随机森林、XGBoost 和 LightGBM 都通过各自的 feature_importances_ 属性提取特征重要性,而 CatBoost 则使用 get_feature_importance() 方法获取

# 获取RandomForest特征重要性并排序
rf_feature_importances = rf_regressor.feature_importances_
rf_sorted_indices = np.argsort(rf_feature_importances)[::-1]
rf_sorted_features = X_train.columns[rf_sorted_indices]
rf_sorted_importances = rf_feature_importances[rf_sorted_indices]

# 获取XGBoost特征重要性并排序
xgb_feature_importances = best_model_xgboost.feature_importances_
xgb_sorted_indices = np.argsort(xgb_feature_importances)[::-1]
xgb_sorted_features = X_train.columns[xgb_sorted_indices]
xgb_sorted_importances = xgb_feature_importances[xgb_sorted_indices]

# 获取LightGBM特征重要性并排序
lgb_feature_importances = best_model_lgb.feature_importances_
lgb_sorted_indices = np.argsort(lgb_feature_importances)[::-1]
lgb_sorted_features = X_train.columns[lgb_sorted_indices]
lgb_sorted_importances = lgb_feature_importances[lgb_sorted_indices]

# 获取CatBoost特征重要性并排序
catboost_feature_importances = best_model_catboost.get_feature_importance()
catboost_sorted_indices = np.argsort(catboost_feature_importances)[::-1]
catboost_sorted_features = X_train.columns[catboost_sorted_indices]
catboost_sorted_importances = catboost_feature_importances[catboost_sorted_indices]

# 创建一个DataFrame来保存所有模型的特征重要性
feature_importance_df = pd.DataFrame({
    "RandomForest_Feature": rf_sorted_features,
    "RandomForest_Importance": rf_sorted_importances,
    "XGBoost_Feature": xgb_sorted_features,
    "XGBoost_Importance": xgb_sorted_importances,
    "LightGBM_Feature": lgb_sorted_features,
    "LightGBM_Importance": lgb_sorted_importances,
    "CatBoost_Feature": catboost_sorted_features,
    "CatBoost_Importance": catboost_sorted_importances
})
feature_importance_df

特征重要性可视化比较

使用 NetworkX 库构建了一个有向图,用于可视化多个模型中提取的特征重要性排名的比较

展示了四种不同机器学习模型(随机森林、XGBoost、LightGBM 和 CatBoost)中的特征重要性排名对比。每个圆圈代表一个特征,其在垂直方向上的位置表示该特征在相应模型中的重要性排名。颜色从深蓝色(重要性高)到浅蓝色(重要性低)逐渐变化【针对第一个模型后面为相同特征相同颜色】,以突出每个特征的排名顺序。箭头用于连接相同的特征,帮助比较这些特征在不同模型中的重要性变化。例如,“DMC”和“temp”在大多数模型中都被认为是较为重要的特征,而像“rain”这样的特征在各个模型中的排名较低。通过节点之间的连接,可以直观地看到每个特征在不同模型中的重要性是如何变化的


import networkx as nx

feature = feature_importance_df[['RandomForest_Feature', 'XGBoost_Feature', 'LightGBM_Feature', 'CatBoost_Feature']]

plt.figure(figsize=(12, 8), dpi=1200)

# 创建一个有向图
G = nx.DiGraph()
unique_features = pd.unique(feature.values.ravel('K'))

# 使用一个色系的渐变色
colors = plt.cm.Blues_r(np.linspace(0.3, 0.9, len(unique_features)))
feature_color_map = {feature_name: colors[i % len(colors)] for i, feature_name in enumerate(unique_features)}
pos = {}
for i, model in enumerate(feature.columns):
    for j, feature_name in enumerate(feature[model]):
        # 添加节点
        G.add_node(f'{model}_{feature_name}', label=feature_name)
        pos[f'{model}_{feature_name}'] = (i, -j) 
        if i > 0:
            previous_model = feature.columns[i - 1]
            for prev_j, prev_feature_name in enumerate(feature[previous_model]):
                if feature_name == prev_feature_name:
                    G.add_edge(f'{previous_model}_{prev_feature_name}', f'{model}_{feature_name}', color='black')  # 固定边的颜色为黑色
node_labels = nx.get_node_attributes(G, 'label')
node_colors = [feature_color_map[node_labels[node]] for node in G.nodes()]
nx.draw(G, pos, labels=node_labels, with_labels=True, node_color=node_colors, node_size=3000, font_size=10)
edges = G.edges()
nx.draw_networkx_edges(G, pos, edge_color='black', arrowstyle='-|>', arrowsize=20, width=2)
for i, model in enumerate(feature.columns):
    plt.text(i, -len(feature), model, horizontalalignment='center', fontsize=12, fontweight='bold')
plt.gca().set_axis_off()

plt.title('Feature Ranking Comparison Across Models with Gradual Color Scheme and Styled Arrows')
plt.savefig("Feature Ranking Comparison Across Models with Gradual Color Scheme and Styled Arrows.pdf",bbox_inches='tight')
plt.show()

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

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

相关文章

F28335 的 EPWM 外设

1 PWM 简介 2 F28335的ePWM介绍 2.1 时基模块TB (1)时基模块的功能 (2)时基模块的关键信号和寄存器 给出时基模块内部结构图来了解里面的关键信号和寄存器,时基模块内部结构图如下所示: (3…

十一假期地区人流量出行大数据分析:技术驱动下的深度洞察

随着国庆黄金周的临近,旅游市场再次迎来了一年一度的出行高峰。在这个数字化时代,如何利用大数据、第三方接口等先进技术进行数据采集与分析,以更精准地预测人流量、优化资源配置、提升旅游体验,成为了行业内外关注的焦点。 一、…

播放器 SDK

腾讯云视立方播放器 SDK 是音视频终端 SDK(腾讯云视立方)的子产品 SDK 之一,基于腾讯云强大的后台能力与 AI 技术,提供视频点播和直播播放能力的强大播放载体。结合腾讯云点播或云直播使用,可以快速体验流畅稳定的播放…

Debian安装mysql遇到的问题解决及yum源配置

文章目录 一、安装mysql遇到的问题解决二、Debain系统mysql8.0的安装以及远程连接三、彻底卸载软件四、Python 操作 mysql五、debian软件源source.list文件格式说明1. 第一部分2. 第二部分3. 第三部分4. 第四部分5. 关于源的混用问题6. 按需修改自己的sources.list7. 更新软件包…

部标主动安全(ADAS+DMS)对接说明

1.前言 上一篇介绍了部标(JT/T1078)流媒体对接说明,这里说一下如何对接主动安全附件服务器。 流媒体的对接主要牵扯到4个方面: (1)平台端:业务端系统,包含前端呈现界面。 &#x…

相机的内参 外参

相机的内参和外参是计算机视觉和摄影测量中的重要概念。以下是对它们的详细说明: 内参(Intrinsic Parameters) 内参定义了相机的内部特性,主要包括焦距、主点坐标以及畸变系数。内参矩阵 K 形式如下: 外参&#xf…

C++-list使用学习

###list(链表)是C里面的一种容器,底层是双向的; 这就决定了它的迭代器使用的场景和能够使用的算法;双向(例如list)不能像随机(例如vector)那样用迭代器任意加上几去使用&…

【L波段差分干涉SAR卫星(陆地探测一号01组)】

L波段差分干涉SAR卫星(陆地探测一号01组) L波段差分干涉SAR卫星(陆地探测一号01组)是我国自主研发的重要卫星系统,以下是对该卫星的详细介绍: 一、基本信息 卫星组成:陆地探测一号01组由A星…

SysML图例-无人机

DDD领域驱动设计批评文集>> 《软件方法》强化自测题集>> 《软件方法》各章合集>>

AndroidLogger插件使用技巧

它是一个Notepad插件,由于未上架Notepad的插件市场,因此需要独立下载并解压到 Notepad 安装目录下 plugin 里面即可。已更新到 SourceForge,您可以到那里获取最新的包,目前还在持续升级。 https://sourceforge.net/projects/andro…

简单顺序计算器

C语言题目:简单顺序计算器,用python代码解。 (笔记模板由python脚本于2024年09月27日 22:58:16创建,本篇笔记适合喜欢python的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网:https://www.python.org/ Free:大咖…

使用FFmpeg压缩MP3格式音频

FFmpeg简介 FFmpeg 是一个开源的多媒体框架,能够录制、转换数字音频和视频,并将其转码到流行的格式。它被广泛应用于音视频处理领域,支持几乎所有的音视频格式和编解码器。以下是 FFmpeg 的一些关键特点和功能: 主要特点 跨平台…

Stable Diffusion绘画 | SDXL模型使用注意事项

注意事项 SDXL模型的使用,对电脑配置要求更高,需要 8GB 以上显存的显卡SDXL模型兼容性不太好,容易出现错误,对 Mac 电脑不友好只能选择 SDXL模型 训练的 LoRA 使用不能使用旧的 VAE文件 SDXL 专用 VAE 文件:sdxl_vae.…

CEPH的写入流程

1、客户端程序发起对文件的读写请求,ceph前端接口(RADOS Gateway)将文件切分成多个固定大小的对象(默认大小为4MB) 2、计算文件到对象的映射 (1) 计算OID为每个对象分配一个唯一的OID(Object ID&#xff09…

构造+bfs,CF 761E - Dasha and Puzzle

目录 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 二、解题报告 1、思路分析 2、复杂度 3、代码详解 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 761E - Dasha and Puzzle 二、解题报告 1、思路分析 如果一个点的度 >…

[数据集][目标检测]辣椒缺陷检测数据集VOC+YOLO格式695张5类别

重要说明:数据集图片里面都是一个辣椒,请仔细查看图片预览,确认符合要求下载 数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文…

时间安全精细化管理平台/iapp/mobile/facereg/facereg.html接口存在未授权访问漏洞

漏洞描述 登录--时间&安全精细化管理平台/iapp/mobile/facereg/facereg.html接口存在未授权访问漏洞,黑客可以未授权等级员工信息对平台造成影响 FOFA: body"登录--时间&安全精细化管理平台" 漏洞复现 IP/iapp/mobile/facereg…

SIMETRIX 探头和测量

来源:公众号 xuyuntong 随着工作的调整仿真那是越用越多了,在做仿真的时候我们对结果往往都需要做一些测量,怎么样让我们的测量更加的高效呢? 我们也从做中学,从学中做,仿真主要还是培养对电路的直觉虽说讲的是工具还是从电路做起,在做电路过程中把工具学了。 现在我…

[Python学习日记-30] Python中数据类型与文件操作的补充(Bytes 类型、字符编码的转换、深浅 Copy)

[Python学习日记-30] Python中数据类型与文件操作的补充 Bytes 类型 字符编码的转换 深浅 Copy Bytes 类型 一、定义 Bytes 类型是指一堆字节的集合,在 Python 中以 b 开头的字符串都是 Bytes 类型。从前面学习的字符编码当中知道,数据存到硬盘当中都…

C++ day07

C笔试题合集: 1、什么是虚函数?什么是纯虚函数? 1>在类中定义函数时,在函数名前加上virtual关键字,该函数就是虚函数,虚函数可以保证在父子类中只有一个该函数。 2>当虚函数头 0;时该函…