特征选择:基于随机森林的Boruta算法应用

机器学习关系型数据库数据安全

picture.image

前言

Boruta算法是一种用于特征选择的包裹式算法,专门设计用于确定数据集中哪些特征对预测模型是重要的

Boruta算法原理

  • 构 建随机森林模型: 首先,Boruta算法使用随机森林模型来计算每个特征的重要性, 随机森林是一种集成学习方法,它通过构建多个决策树并取平均值来提高模型的准确性和稳定性
  • 创 建影子特征: 为了评估原始特征的重要性,Boruta算法会对数据进行打乱,生成一组与原始特征对应的影子特征, 这些影子特征是通过随机排列原始特征的数据生成的,它们不应该对目标变量有预测能力
  • 比较特征重要性: 算法将原始特征的重要性与影子特征的重要性进行比较, 如果一个原始特征的重要性显著高于所有影子特征的最大重要性,那么它被认为是“重要的”; 如果它的重要性低于影子特征的最大重要性,则被认为是“无关的”, 对于那些无法明显判断的重要性,算法会将其标记为“待定”
  • 逐步消除无关特征: 算法通过迭代的方式,逐步剔除那些被标记为“无关”的特征,然后重新构建模型,直到所有特征都被分类为“重要”或“无关”,或者达到设定的迭代次数
  • 输出结果: 最终,Boruta算法输出三类特征——重要的、无关的和待定的, 重要特征可以保留用于模型构建,而无关特征则可以被舍弃, 对于待定的特征,可能需要进一步的分析或选择性保留

代码实现

数据读取处理


          
import pandas as pd
          
import numpy as np
          
import matplotlib.pyplot as plt
          
from sklearn.model_selection import train_test_split
          
df = pd.read_csv('Chabuhou.csv')
          

          
# 划分特征和目标变量
          
X = df.drop(['Electrical_cardioversion'], axis=1)
          
y = df['Electrical_cardioversion']
          
# 划分训练集和测试集
          
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, 
          
                                                    random_state=42, stratify=df['Electrical_cardioversion'])
          
df.head()
      

picture.image

读取数据,将其分为特征(X)和目标变量(y),然后将数据集按80%训练集和20%测试集进行划分,使用的是一个心脏电复律的数据集包含46个特征变量一个目标变量为二分类任务

Boruta算法特征选择


          
from sklearn.ensemble import RandomForestClassifier
          
from boruta import BorutaPy
          

          
# 初始化随机森林模型
          
rf = RandomForestClassifier(n_jobs=-1, class_weight='balanced', max_depth=5)
          

          
# 初始化Boruta特征选择器
          
boruta_selector = BorutaPy(rf, n_estimators='auto', verbose=2, random_state=42)
          

          
# 对训练数据进行特征选择
          
boruta_selector.fit(X_train.values, y_train.values)
          

          
# 检查选中的特征
          
selected_features = X_train.columns[boruta_selector.support_].to_list()
          

          
# 打印被选择的特征
          
print("Selected Features: ", selected_features)
          

          
# 打印被剔除的特征
          
rejected_features = X_train.columns[~boruta_selector.support_].to_list()
          
print("Rejected Features: ", rejected_features)
          

          
# 打印有待定性的特征
          
tentative_features = X_train.columns[boruta_selector.support_weak_].to_list()
          
print("Tentative Features: ", tentative_features)
      

picture.image

初始化随机森林分类器模型用于评估特征重要性,并通过Boruta特征选择器与影子特征进行对比,确定哪些特征是重要的,随后对训练数据应用Boruta算法,以筛选出对模型预测最有用的特征,Boruta算法默认在内部迭代100次,如需更改迭代次数,可通过添加参数max_iter进行调整


          
# 获取特征排名
          
feature_ranks = boruta_selector.ranking_
          
# 将特征名称和排名结合成一个DataFrame
          
feature_importance_df = pd.DataFrame({
          
    'Feature': X_train.columns,
          
    'Rank': feature_ranks
          
})
          
feature_importance_df
      

picture.image

使用boruta_selector.ranking_获取每个特征的排名,这个排名表示了特征的重要性,数值越小代表特征越重要,这里只展示部分特征,最后确定重要的特征为 ['Type_of_atrial_fibrillation', 'BMI', 'Left_atrial_diameter', 'Systolic_blood_pressure', 'NtproBNP']

多次运行Boruta算法以评估特征排名稳定性


          
# 初始化随机森林模型
          
rf = RandomForestClassifier(n_jobs=-1, class_weight='balanced', max_depth=5)
          

          
# 初始化存储特征排名的 DataFrame
          
ranking_df = pd.DataFrame(index=range(1, 21), columns=X_train.columns)
          

          
# 运行 Boruta 20 次
          
for i in range(20):
          
    print(f"Iteration {i+1}")
          
    
          
    # 初始化Boruta特征选择器
          
    boruta_selector = BorutaPy(rf, n_estimators='auto', verbose=2, random_state=i, max_iter=50)
          
    
          
    # 对训练数据进行特征选择
          
    boruta_selector.fit(X_train.values, y_train.values)
          
    
          
    # 获取特征排名
          
    feature_ranks = boruta_selector.ranking_
          
    
          
    # 将特征排名保存到 DataFrame 中
          
    ranking_df.loc[i+1] = feature_ranks
          
ranking_df
      

picture.image

多次运行Boruta算法,以不同的随机种子生成特征排名,并将每次的排名结果保存到一个DataFrame中,用于分析特征排名的一致性,并且指定max_iter=50不在是默认的100,提高运行速度

可视化

排名稳定性


          
# 确保数据集中只有数值列
          
numeric_ranking_df = ranking_df.apply(pd.to_numeric, errors='coerce')
          

          
# 计算每个特征的中位数
          
median_values = numeric_ranking_df.median()
          

          
# 根据中位数对列进行排序
          
sorted_columns = median_values.sort_values().index
          

          
# 设置绘图风格
          
plt.figure(figsize=(15, 8))
          
sns.set(style="whitegrid")
          

          
# 绘制箱线图
          
sns.boxplot(data=numeric_ranking_df[sorted_columns], palette="Greens")
          

          
plt.xticks(rotation=90)
          
plt.title("Sorted Feature Ranking Distribution by Boruta", fontsize=16)
          
plt.xlabel("Attributes", fontsize=14)
          
plt.ylabel("Importance", fontsize=14)
          
plt.tight_layout()
          
plt.show()
      

picture.image

从图表中可以看出,最左侧的特征(Type_of_atrial_fibrillation、BMI等)在多次迭代中排名较高,表明它们是模型中较为重要的特征,而最右侧的特征(如COPD、Amiodarone等)则在多次迭代中排名较低,说明它们在模型中被认为不太重要,与前面单次运行Boruta算法的结果一致,但是相比于单次运行,通过这个可视化可以发现某些特征在个别迭代中的重要性排名与大多数迭代结果不同,从而判断这些特征的重要性是否稳定,图中位于须线外的点正是代表了这些异常的排名结果,如果过多这种情况出现作者认为需要着重去考虑这种特征

往期推荐

利用SHAP解释二分类模型的四种机器学习GUI工具

模型过拟合与欠拟合的核心原理及其与数据集分割的关系

复现顶刊Streamlit部署预测模型APP

数据预处理全攻略:从缺失值到特征工程,一站式解决方案

精确度与参数的完美融合:用可视化解读模型优化过程

优化XGBoost回归模型:网格搜索与K折交叉验证实现

提升机器学习精度:利用SHAP值与蒙特卡洛模拟优化特征选择

picture.image

picture.image

picture.image

微信号|deep_ML

欢迎添加作者微信进入Python、ChatGPT群

进群请备注Python或AI进入相关群
无需科学上网、同步官网所有功能、使用无限制

如果你对类似于这样的文章感兴趣。

欢迎关注、点赞、转发~

个人观点,仅供参考

0
0
0
0
关于作者

文章

0

获赞

0

收藏

0

相关资源
CV 技术在视频创作中的应用
本次演讲将介绍在拍摄、编辑等场景,我们如何利用 AI 技术赋能创作者;以及基于这些场景,字节跳动积累的领先技术能力。
相关产品
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论