使用eli5 explain_weights无法获取sklearn随机森林各类别特征重要性
问题原因与解决方案
我来帮你捋清楚这个问题:
首先,你遇到的核心问题是模型本身的特性和PermutationImportance的默认设置导致无法返回分类别的特征重要性:
- scikit-learn的
RandomForestClassifier自带的feature_importances_是全局指标,它是基于所有类别的节点不纯度计算的平均值,从设计上就没有分类别的拆分,所以直接用explain_weights(rf)只会返回整体的特征重要性。 - 你使用的
PermutationImportance默认采用的是单一全局性能指标(比如准确率accuracy),计算出的特征重要性是一维数组,自然也只能输出整体结果,而不是每个类别的细分数据。
eli5文档里提到的「返回每个待预测类别的特征重要性」,更多是针对线性模型(比如LogisticRegression、SGDClassifier)这类本身每个类别都有对应系数的模型;对于树模型,必须手动调整PermutationImportance的参数才能实现分类别的重要性计算。
解决方法:自定义分类别的评估指标
要让PermutationImportance计算每个类别的特征重要性,你需要指定一个能返回每个类别单独得分的评估指标,具体步骤如下:
- 导入sklearn的评分工具和你想用的评估指标(比如精确率、召回率都可以)
- 创建一个自定义的scorer,设置
average=None让指标返回每个类别的单独得分 - 将这个scorer传给
PermutationImportance的scoring参数
修改后的完整代码如下:
import pandas as pd import eli5 from eli5.sklearn import PermutationImportance from sklearn import datasets from sklearn.model_selection import train_test_split from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import precision_score, make_scorer # 新增导入 x, y = datasets.make_classification(n_samples=200, n_features=5, n_informative=3, n_redundant=2, n_classes=4) df = pd.concat([pd.DataFrame(x, columns=['feat_1', 'feat_2', 'feat_3', 'feat_4', 'feat_5']), pd.DataFrame(y, columns=['classe'])], axis=1) df = df.replace({'classe': {0: '1st', 1: '2nd', 2: '3rd', 3: '4th'}}) labels = pd.unique(df['classe']) train, test = train_test_split(df, stratify=df['classe'], test_size=0.40) rf = RandomForestClassifier() rf.fit(train[['feat_1', 'feat_2', 'feat_3', 'feat_4', 'feat_5']], train['classe']) # 关键修改:创建返回每个类别精确率的scorer scorer = make_scorer(precision_score, average=None) perm = PermutationImportance(rf, scoring=scorer).fit(test[['feat_1', 'feat_2', 'feat_3', 'feat_4', 'feat_5']], test['classe']) var_imp_classes = eli5.explain_weights(perm, top=5, targets=labels, target_names=labels, feature_names=['feat_1', 'feat_2', 'feat_3', 'feat_4', 'feat_5']) print(eli5.format_as_text(var_imp_classes))
运行这段代码后,你就能看到每个类别对应的特征重要性(均值+标准差)了。你也可以根据需求替换评估指标,比如用recall_score或者f1_score,只要保持average=None即可。
内容的提问来源于stack exchange,提问作者G.L
相关产品推荐
相关产品推荐

