如何让SHAP汇总图展示原始分类列而非独热编码后的拆分列?
如何让SHAP汇总图展示原始分类列而非独热编码后的拆分列?
这个问题我之前也遇到过!独热编码确实会把分类特征拆成多个独立的二进制列,导致SHAP汇总图显示的是拆分后的零散列,想要合并回原始的分类列其实有两种实用的方法,我给你一步步讲:
方法一:对已独热编码的特征进行分组展示
如果已经完成了独热编码的流程,不想改动建模环节,可以通过SHAP的summary_plot参数,把同一原始分类特征下的独热列分组:
首先,我们需要先明确每个原始分类特征对应哪些独热编码后的列索引:
category1对应独热后的A、B、C,也就是索引0、1、2category2对应独热后的X、Y,也就是索引3、4
然后修改SHAP可视化的代码部分:
# 定义分组:键是原始分类列名,值是对应的独热列索引 group_indices = { "category1": [0, 1, 2], "category2": [3, 4] } group_names = list(group_indices.keys()) # 绘制分组后的SHAP汇总图 shap.summary_plot( shap_values, X_test, feature_names=feature_names, group_indices=group_indices, group_names=group_names )
这样SHAP就会把同一原始分类下的所有独热列的SHAP值合并,展示成原始的两个分类列。
方法二:用XGBoost原生支持分类特征(更高效)
其实XGBoost从1.3版本开始就支持直接处理分类特征,不需要提前做独热编码!这样不仅能避免特征膨胀,还能让SHAP直接识别原始分类列,同时降低特征排列的计算成本,是更推荐的做法。
完整的修改后代码如下:
import pandas as pd from xgboost import XGBClassifier from sklearn.model_selection import train_test_split import shap # 示例数据(2个输入列,1个输出列) data = { 'category1': ['A', 'B', 'C', 'A', 'B'], 'category2': ['X', 'Y', 'X', 'Y', 'X'], 'target': [0, 1, 0, 1, 0] } df = pd.DataFrame(data) # 将分类列转为pandas的category类型(XGBoost需要这个标记) df['category1'] = df['category1'].astype('category') df['category2'] = df['category2'].astype('category') # 数据拆分 X = df.drop('target', axis=1) y = df['target'] X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=42 ) # 训练模型时开启分类特征支持 model = XGBClassifier( enable_categorical=True, # 关键参数:开启原生分类特征支持 use_label_encoder=False, eval_metric='logloss' ) model.fit(X_train, y_train, eval_set=[(X_test, y_test)], verbose=False) # SHAP解释部分 explainer = shap.TreeExplainer(model) shap_values = explainer.shap_values(X_test) # 直接绘制SHAP汇总图,会自动显示原始分类列 shap.summary_plot(shap_values, X_test)
这种方法不需要任何额外的分组操作,SHAP图直接展示category1和category2两个原始列,同时模型训练的效率也更高。
备注:内容来源于stack exchange,提问作者Hyunjik Bae
相关产品推荐
相关产品推荐

