如何在多分类任务中绘制全类别SHAP汇总图
多分类任务中一次性绘制所有类别的SHAP汇总图解决方案
问题背景
使用XGBoost结合SHAP分析多分类任务的特征重要性时,仅能逐个生成单类别柱状汇总图,需要实现在一张图中展示每个特征对所有类别的贡献。环境版本:SHAP 0.45.0,Python 3.10.12。
解决方案
SHAP自带的summary_plot对多分类任务的柱状图不支持直接批量展示,需要手动处理SHAP值后,用可视化库绘制分组柱状图或子图布局的单类别汇总图。
方案1:分组柱状图(单图对比跨类别特征贡献)
通过计算每个特征在不同类别下的平均绝对SHAP值,生成分组柱状图,直观对比同一特征对不同类别的重要性:
import matplotlib.pyplot as plt import seaborn as sns # 计算每个类别下,每个特征的平均绝对SHAP值(绝对值代表特征对模型输出的影响程度) mean_abs_shap = [] for class_shap in shap_values: mean_abs = np.mean(np.abs(class_shap), axis=0) mean_abs_shap.append(mean_abs) # 转换为DataFrame,便于可视化处理 feature_names = [f"Feature {i}" for i in range(X_test.shape[1])] shap_df = pd.DataFrame( np.array(mean_abs_shap).T, columns=[f"Class {c}" for c in range(len(shap_values))], index=feature_names ) # 按所有类别的平均SHAP值排序,取前10个最具代表性的特征(可按需调整数量) top_n_features = 10 shap_df['Overall Mean'] = shap_df.mean(axis=1) shap_df_sorted = shap_df.sort_values(by='Overall Mean', ascending=False)\ .drop('Overall Mean', axis=1)\ .head(top_n_features) # 绘制分组柱状图 plt.figure(figsize=(12, 8)) sns.barplot(data=shap_df_sorted.T, palette='viridis') plt.title('SHAP Feature Importance by Class (Top 10 Features)') plt.xlabel('Class') plt.ylabel('Mean Absolute SHAP Value') plt.xticks(rotation=45) plt.tight_layout() plt.show()
方案2:子图布局(单图展示所有类别的独立汇总图)
如果希望保留SHAP原生柱状图的样式,可将每个类别的汇总图以子图形式排列在一张画布中:
import matplotlib.pyplot as plt n_classes = len(shap_values) # 设定子图行列数(按3列排列,可按需调整) n_cols = 3 n_rows = (n_classes + n_cols - 1) // n_cols plt.figure(figsize=(15, n_rows * 5)) for class_idx in range(n_classes): plt.subplot(n_rows, n_cols, class_idx + 1) # 绘制单类别SHAP柱状图,关闭自动展示 shap.summary_plot(shap_values[class_idx], X_test, plot_type="bar", show=False) plt.title(f"Class {class_idx}") plt.tight_layout() plt.show()
说明
- 平均绝对SHAP值是衡量特征重要性的常用方式,它消除了SHAP值正负方向的影响,只体现特征对模型输出的影响程度。
- 方案1适合对比同一特征在不同类别下的重要性差异;方案2适合快速查看每个类别的Top特征,保留SHAP原生可视化风格。
内容的提问来源于stack exchange,提问作者cconsta1
相关产品推荐
相关产品推荐

