如何获取包含预处理与分类步骤的决策树Pipeline的特征重要性?
解决方案
核心思路有两种,第一种是将OneHot编码生成的同一原始特征下所有哑变量的特征重要性求和,得到原始特征总重要性;第二种是使用排列重要性直接计算原始特征的贡献,无需处理编码逻辑。
方法1:哑变量重要性求和
该方法直接对齐Pipeline的特征输出顺序,按原始特征的编码拆分规则求和,实现简单:
import pandas as pd import numpy as np # 1. 提取数值特征的重要性(数值特征未拆分,直接取对应位置的数值即可) numeric_imp = clf.named_steps['classifier'].feature_importances_[:len(numeric_features)] numeric_imp_df = pd.DataFrame({ '原始特征': numeric_features, '重要性': numeric_imp }) # 2. 提取离散特征的重要性(同一原始特征的所有哑变量重要性求和) # 拿到OneHotEncoder实例,获取每个离散特征生成的哑变量数量 ohe = clf.named_steps['preprocessor'].named_transformers_['nominal'].named_steps['ohe'] cat_counts = [len(cats) for cats in ohe.categories_] # 离散特征对应的重要性片段从数值特征之后开始 nominal_imp_array = clf.named_steps['classifier'].feature_importances_[len(numeric_features):] # 按哑变量数量切割重要性数组,分段求和 nominal_imp_list = [] start_idx = 0 for feat, count in zip(nominal_features, cat_counts): end_idx = start_idx + count total_imp = nominal_imp_array[start_idx:end_idx].sum() nominal_imp_list.append({'原始特征': feat, '重要性': total_imp}) start_idx = end_idx nominal_imp_df = pd.DataFrame(nominal_imp_list) # 3. 合并结果并按重要性降序排序 total_imp_df = pd.concat([numeric_imp_df, nominal_imp_df], ignore_index=True).sort_values('重要性', ascending=False) print(total_imp_df)
方法2:排列重要性(更推荐)
该方法直接基于模型性能变化计算特征贡献,不受编码方式影响,结果更鲁棒:
from sklearn.inspection import permutation_importance # 基于测试集计算排列重要性,n_repeats为重复打乱次数,值越高结果越稳定 perm_result = permutation_importance( estimator=clf, X=X_test, y=y_test, n_repeats=10, random_state=42, n_jobs=-1 ) # 整理结果 perm_imp_df = pd.DataFrame({ '原始特征': X_train.columns, '重要性均值': perm_result.importances_mean, '重要性标准差': perm_result.importances_std }).sort_values('重要性均值', ascending=False) print(perm_imp_df)
注意:排列重要性需要使用独立的测试集计算,避免过拟合带来的结果偏差。
内容的提问来源于stack exchange,提问作者chesslad
相关产品推荐
相关产品推荐

