机器学习笔记 十七:基于Gini Importance、Permutation Importance、Boruta的随机森林模型重要性评估的比较

该博客介绍了如何使用随机森林进行模型拟合和预测,包括样本拆分、模型参数解释、特征重要性评估(GiniImportance、PermutationImportance、Boruta)以及基于不同方法的特征选择。通过对比不同特征选择后的预测性能,展示了排序重要性特征选择对模型性能略有提升。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 随机森林模型拟合和预测性能

1.1 样本拆分
X = wine.drop('quality', axis = 1)
y = wine['quality']

集合y:

在这里插入图片描述

df_train, df_test = train_test_split(wine, test_size=0.20) # random_state随机状态:保证每次分割的样本一致
df_train = df_train[list(wine.columns)] # 获取wine的列名:Index(['fixed acidity', 'volatile acidity', 'citric acid', 'residual sugar',
                                                        #       'chlorides', 'free sulfur dioxide', 'total sulfur dioxide', 'density',
                                                        #       'pH', 'sulphates', 'alcohol', 'quality'],
df_test = df_test[list(wine.columns)]

X_train, y_train = df_train.drop('quality',axis=1), df_train['quality']
X_test, y_test = df_test.drop('quality',axis=1), df_test['quality']

X_train.shape,y_train.shape,X_test.shape,y_test.shape

((1279, 11), (1279,), (320, 11), (320,))

注意:
若random_state随机状态未设置,将出现下面的情况,即每次划分的结果不一致

在这里插入图片描述

1.2 模型拟合

参数解释:

  • n_estimators : integer, optional (default=10) 整数,可选择(默认值为10)。 森林里决策树的数目。
  • criterion : string, optional (default=”gini”) 字符串,可选择(默认值为“gini”)。衡量分裂质量的性能(函数)。
  • min_samples_leaf : int, float, optional (default=1) 整数,浮点数,可选的(默认值为1)。需要在叶子结点上的最小样本数量:如果为int,那么考虑min_samples_leaf作为最小的数字。
  • n_jobs : integer, optional (default=1) 整数,可选的(默认值为1)。用于拟合和预测的并行运行的工作(作业)数量。如果值为-1,那么工作数量被设置为核的数量。
  • oob_score : bool (default=False) bool,(默认值为False)。是否使用袋外样本来估计泛化精度。
rf = RandomForestClassifier(n_estimators=200,
                            min_samples_leaf=5,
                            n_jobs=-1,
                            oob_score=True,
                            random_state=42)
rf.fit(X_train, y_train)
# 性能预测
print(classification_report(y_test, rf.predict(X_test)))

结果显示:

            precision   recall   f1-score   support

       0       0.91      0.98      0.94       281
       1       0.67      0.31      0.42        39
accuracy                           0.90       320
macro avg      0.79      0.64      0.68       320
weighted avg   0.88      0.90      0.88       320

其中,列表最左边的一列为分类的标签名,右边support列为每个标签的出现次数。avg / total行为各列的均值(support列为总和),precision、recall、f1-score三列分别为各个类别的精确度、召回率及值。
precision: 预测的准确性,获取的所有样本中,正确样本的占比
recall: 实际样本中,有多少样本被正确的预测出来了。
F1 Score: 统计学中用来衡量二分类模型精确度的一种指标。它同时兼顾了分类模型的精确率和召回率。F1分数可以看作是模型精确率和召回率的一种加权平均,它的最大值是1,最小值是0。

举例解释:
某池塘有1400条鲤鱼,300只虾,300只鳖。现在以捕鲤鱼为目的,撒网逮着了700条鲤鱼,200只虾,100只鳖。那么,这些指标分别如下:
精确率 = 700 / (700 +200 + 100) = 70%
召回率 = 700 / 1400 = 50%

1.3 特征重要性

Gini Importance: feature_importances_
gini不纯度: 从一个数据集中随机选取子项,度量其被错误的划分到其他组里的概率,计算式:

在这里插入图片描述
在这里插入图片描述
因此,基尼系数可以做为熵模型的一个近似替代。

基尼不纯度:
(1)基尼不纯度可以作为衡量系统混乱程度的标准;
(2)基尼不纯度越小,纯度越高,集合的有序程度越高,分类的效果越好
(3)基尼不纯度为 0 时,表示集合类别一致;
(4)在决策树中,比较基尼不纯度的大小可以选择更好的决策条件(子节点)

features = np.array(X_train.columns)
# gini不纯度
imps_gini=rf.feature_importances_
std_gini = np.std([tree.feature_importances_ for tree in rf.estimators_], axis=0) # 计算标准差
indices_gini = np.argsort(imps_gini) # 将imps_gini中的元素从小到大排列,提取其在排列前对应的index(索引)输出

plt.title('Feature Importance')
# plt.barh():横向的柱状图,可以理解为正常柱状图旋转了90°
plt.barh(range(len(indices_gini)), imps_gini[indices_gini], yerr=std_gini[indices_gini],color='c', align='center')
plt.yticks(range(len(indices_gini)), features[indices_gini])
plt.xlabel('Gini Importance')
plt.show()

在这里插入图片描述

1.4 Permutation Importance(permutation_importances)
# 从相同的随机数种子出发,可以得到相同的随机数序列
np.random.seed(10)
imps_perm, std_perm = permutation_importances(rf, X_train, y_train,
                              oob_classifier_accuracy

features = np.array(X_train.columns)
indices_perm = np.argsort(imps_perm)

plt.title('Feature Importances')
plt.barh(range(len(indices_perm)), imps_perm[indices_perm], yerr=std_perm[indices_perm],color='c', align='center')
plt.yticks(range(len(indices_perm)), features[indices_perm])
plt.xlabel('Permutation Importance')
plt.show()

在这里插入图片描述

1.5 Boruta
forest = RandomForestClassifier(n_estimators=200,
                                min_samples_leaf=5,
                                n_jobs=-1,
                                oob_score=True,
                                random_state=42)
feat_selector = BorutaPy(forest, verbose=2,max_iter=50)

np.random.seed(10)
import time
start = time.time()
feat_selector.fit(X_train.values, y_train.values)
end = time.time()
print(end - start)# 获取运行时间

迭代发生变化的节点:

BorutaPy finished running.

Iteration: 50 / 50
Confirmed: 8
Tentative: 0
Rejected: 2
169.35201215744019

print('明确的参数: \n',list(np.array(X_train.columns)[feat_selector.ranking_==1]))
print('\n待定的参数: \n',list(np.array(X_train.columns)[feat_selector.ranking_==2]))
print('\n拒绝的参数: \n',list(np.array(X_train.columns)[feat_selector.ranking_>=3]))

明确的参数:
[‘fixed acidity’, ‘volatile acidity’, ‘citric acid’, ‘chlorides’, ‘total sulfur dioxide’, ‘density’, ‘sulphates’, ‘alcohol’]

待定的参数:
[‘free sulfur dioxide’]

拒绝的参数:
[‘residual sugar’, ‘pH’]


2. 特征选择和性能比较

2.1 基于基尼重要性的特征选择

删除基尼重要性小于0.05的参数(3个):‘pH’,‘residual sugar’,‘free sulfur dioxide’

X_train_gini=X_train.drop(['pH','residual sugar','free sulfur dioxide'],axis=1)
X_test_gini=X_test.drop(['pH','residual sugar','free sulfur dioxide'],axis=1)

rf_gini = RandomForestClassifier(n_estimators=300, # 森林里(决策)树的数目
                            min_samples_leaf=5,
                            n_jobs=-1,
                            oob_score=True,
                            random_state=42)
rf_gini.fit(X_train_gini, y_train)
2.2 基于排序重要性的特征选择

删除排序重要性小于0.003的参数(6个):‘chlorides’,‘pH’,‘residual sugar’,‘fixed acidity’,‘free sulfur dioxide’,‘citric acid’

X_train_perm=X_train.drop(['chlorides','pH','residual sugar','fixed acidity','free sulfur dioxide','citric acid'],axis=1)
X_test_perm=X_test.drop(['chlorides','pH','residual sugar','fixed acidity','free sulfur dioxide','citric acid'],axis=1)

rf_gini = RandomForestClassifier(n_estimators=300, # 森林里(决策)树的数目
                            min_samples_leaf=5,
                            n_jobs=-1,
                            oob_score=True,
                            random_state=42)
rf_gini.fit(X_train_gini, y_train)
2.3 基于Boruta的特征选择

删除Boruta的拒绝变量(2个):‘residual sugar’, ‘pH’

X_train_boruta=X_train.drop(['pH','residual sugar'],axis=1)
X_test_boruta=X_test.drop(['pH','residual sugar'],axis=1)

rf_gini = RandomForestClassifier(n_estimators=300, # 森林里(决策)树的数目
                            min_samples_leaf=5,
                            n_jobs=-1,
                            oob_score=True,
                            random_state=42)
rf_gini.fit(X_train_gini, y_train)
2.4 预测性能比较
print('**************************** 原模型 ****************************')
print('\n')
print(classification_report(y_test, rf.predict(X_test)))

print ('\n')

print('****************** 基于基尼重要性的特征选择 ******************')
print('\n')
print(classification_report(y_test, rf_gini.predict(X_test_gini)))

print ('\n')

print('****************** 基于排序重要性的特征选择 ******************')
print('\n')
print(classification_report(y_test, rf_perm.predict(X_test_perm)))

print ('\n')

print('******************** 基于Boruta的特征选择 ********************')
print('\n')
print(classification_report(y_test, rf_boruta.predict(X_test_boruta)))

**************************** 原模型 ****************************

          precision    recall  f1-score   support

       0       0.90      0.97      0.93       274
       1       0.67      0.39      0.49        46

accuracy                           0.88       320
macro avg       0.79      0.68     0.71       320
weighted avg    0.87      0.88     0.87       320

****************** 基于基尼重要性的特征选择 ******************

          precision    recall  f1-score   support

       0       0.90      0.97      0.93       274
       1       0.67      0.39      0.49        46

accuracy                           0.88       320
macro avg       0.79      0.68     0.71       320
weighted avg    0.87      0.88     0.87       320

****************** 基于排序重要性的特征选择 ******************

           precision    recall  f1-score   support 

       0       0.89      0.99      0.94       274
       1       0.76      0.28      0.41        46

accuracy                           0.88       320
macro avg       0.83      0.63     0.67       320
weighted avg    0.87      0.88     0.86       320

******************** 基于Boruta的特征选择 ********************

          precision    recall  f1-score   support

       0       0.90      0.97      0.93       274
       1       0.67      0.39      0.49        46

accuracy                           0.88       320
macro avg       0.79      0.68     0.71       320
weighted avg    0.87      0.88     0.87       320

相比之下,排序重要性的特征选择方法稍好一些。基于Boruta的特征选择只删除了pH和原始模型的结果是一致的,并未对模型产生很大的影响。

### 随机森林模型敏感性分析与特征重要性评估 #### 特征重要性的概念及其应用价值 在机器学习领域,尤其是对于随机森林这样的集成算法而言,特征重要性提供了一种有效量化输入特征对预测模型输出能力的方法。一个特征的重要性得分越高,则表明该特征在模型预测过程中扮演的角色越关键,这不仅有助于深入理解数据结构,还能指导后续的特征工程工作[^1]。 #### 常见的特征重要性度量方式 ##### Gini Importance (基尼指数) Gini Importance 是基于决策树构建过程中的不纯度减少量来衡量各个特征的重要程度。每当分裂节点时,如果某个特定属性能够显著降低子节点内的类别混杂情况(即提高分类准确性),那么这个属性就会被认为具有较高的贡献值。在整个森林中累加这些贡献即可得到最终的特征评分[^2]。 ```python from sklearn.datasets import load_iris from sklearn.ensemble import RandomForestClassifier # 加载鸢尾花数据集作为示例 data = load_iris() X, y = data.data, data.target # 构建并训练随机森林分类器 clf = RandomForestClassifier(n_estimators=100, random_state=42) clf.fit(X, y) # 获取各特征对应的Gini Importance分数 gini_importances = clf.feature_importances_ print(gini_importances) ``` ##### Permutation Importance (置换重要性) 不同于依赖于模型内部机制计算得出的结果,Permutation Importance 采用一种更为直观的方式——通过打乱单个或多个特征值顺序后再观察整体性能的变化幅度来进行评价。当某项指标被打乱后导致模型表现急剧恶化,则说明该项指标本身携带的信息对于做出正确判断至关重要。 ```python import numpy as np from sklearn.inspection import permutation_importance result = permutation_importance(clf, X, y, n_repeats=10, random_state=42, scoring='accuracy') perm_sorted_idx = result.importances_mean.argsort() plt.boxplot(result.importances[perm_sorted_idx].T, vert=False, labels=np.array(data.feature_names)[perm_sorted_idx]) plt.title("Permutation Importances (test set)") plt.show() ``` ##### Boruta Boruta 方法则是利用影子特征的概念,在原始数据基础上添加一组经过随机化处理后的副本,并以此为基础运行标准RF或其他合适的分类/回归算法。随后对比真实特征与其对应“影子”的平均最大重要性得分差异,从而筛选出真正有意义的部分。 ```python from boruta import BorutaPy boruta_selector = BorutaPy(estimator=RandomForestClassifier(), n_estimators='auto', verbose=2, max_iter=100) boruta_selector.fit(X, y) selected_features = [feature for feature, support in zip(data.feature_names, boruta_selector.support_) if support] print(selected_features) ``` #### 敏感性分析的意义及实践建议 除了上述提到的各种特征重要性测量手段外,执行全面而系统的敏感性分析同样不可或缺。这类研究旨在探讨不同参数设置下模型行为是否会随某些因素变动发生明显改变,进而帮助识别潜在的风险点或是优化空间。针对随机森林来说,可以考虑调整如下几个方面: - **样本规模**:增加或减少训练集中实例数量; - **超参配置**:修改诸如`n_estimators`, `max_depth`等核心选项; - **噪声水平**:向部分选定维度引入不同程度的人工干扰信号。 通过对以上要素逐一实验验证其影响范围大小,便能更清晰地掌握哪些外部条件会对最终效果造成实质性冲击,同时也为进一步改进提供了理论依据和支持[^3]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jackson的生态模型

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值