DeepSHAP蜂群图仅显蓝色点无颜色梯度的问题求助
问题描述
我参考SHAP Deep Explainer示例,使用泰坦尼克数据集开展实验,自行用shap.summary_plot(shap_values[0], feature_names = test_data.columns)生成蜂群图时,图中仅显示蓝色点,无侧边梯度标尺,和官方示例的蓝红梯度着色效果不符。实验代码如下:
# import package import shap import numpy as np import pandas as pd import matplotlib.pyplot as plt from sklearn.preprocessing import StandardScaler from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Dense, Dropout from tensorflow.keras import optimizers import warnings warnings.filterwarnings('ignore') %matplotlib inline import os # load data os.chdir('/titanic/') train_data = pd.read_csv('./train.csv', index_col=0) test_data = pd.read_csv('./test.csv', index_col=0) train_data.head() def data_preprocessing(df): df = df.drop(columns=['Name', 'Ticket', 'Cabin']) # fill na df[['Age']] = df[['Age']].fillna(value=df[['Age']].mean()) df[['Embarked']] = df[['Embarked']].fillna(value=df['Embarked'].value_counts().idxmax()) df[['Fare']] = df[['Fare']].fillna(value=df[['Fare']].mean()) # categorical features into numeric df['Sex'] = df['Sex'].map( {'female': 1, 'male': 0} ).astype(int) # one-hot encoding embarked_one_hot = pd.get_dummies(df['Embarked'], prefix='Embarked') df = df.drop('Embarked', axis=1) df = df.join(embarked_one_hot) return df # train data processing train_data = data_preprocessing(train_data) train_data.isnull().sum() # create data for training x_train = train_data.drop(['Survived'], axis=1).values # Check test data test_data.isnull().sum() # scale scale = StandardScaler() x_train = scale.fit_transform(x_train) # prepare y_train y_train = train_data['Survived'].values test_data = data_preprocessing(test_data) x_test = test_data.values.astype(float) # scaling x_test = scale.transform(x_test) # Check test data test_data.isnull().sum() # build mlp model = Sequential() model.add(Dense(32, input_dim=x_train.shape[1], activation='relu')) model.add(Dropout(0.25)) model.add(Dense(128, activation='relu')) model.add(Dropout(0.25)) model.add(Dense(32, activation='relu')) model.add(Dropout(0.25)) model.add(Dense(8, activation='relu')) model.add(Dropout(0.25)) model.add(Dense(2, activation='softmax')) # compile model model.compile(loss='sparse_categorical_crossentropy', optimizer = 'adam', metrics = ['accuracy']) # fit model model.fit(x_train, y_train, epochs=10, batch_size=64) # compute SHAP values explainer = shap.DeepExplainer(model, x_train) shap_values = explainer.shap_values(x_test) shap.summary_plot(shap_values[0], plot_type = 'bar', feature_names = test_data.columns) shap.initjs() shap.force_plot(explainer.expected_value[0].numpy(), shap_values[0][0], features = test_data.columns) shap.decision_plot(explainer.expected_value[0].numpy(), shap_values[0][0], features = test_data.iloc[0,:], feature_names = test_data.columns.tolist()) shap.plots._waterfall.waterfall_legacy(explainer.expected_value[0].numpy(), shap_values[0][0], feature_names = test_data.columns)
原因分析
出现该问题的核心原因是未向shap.summary_plot()传入用于着色的原始特征值:
- 官方示例中,
summary_plot默认用原始特征值给点着色,以此展示特征值高低对SHAP值的影响; - 仅传入SHAP值和特征名时,SHAP无法获取原始特征的数值分布,只能默认用SHAP值本身作为着色依据。而二分类任务的SHAP值分布可能集中在某一区间,导致视觉上呈现单一蓝色,且缺失对应特征值的梯度标尺;
- 另外,你使用标准化后的
x_test计算SHAP值,但着色需要的是预处理后未标准化的原始特征数值,标准化后的数据分布被压缩,也会影响着色效果。
解决办法
修改shap.summary_plot()的调用代码,传入未标准化的原始特征数据作为features参数:
# 使用预处理后未标准化的test_data作为features传入 shap.summary_plot(shap_values[0], features=test_data, feature_names=test_data.columns)
补充说明:
test_data是经过data_preprocessing()处理后的数据集(包含编码后的分类特征、填充后的数值特征,但未做StandardScaler标准化),保留了特征的原始数值分布,能让SHAP根据特征值高低生成蓝红梯度的着色;- 需确保传入的
features和计算SHAP值时的x_test样本一一对应,避免样本顺序错乱; - 若想指定特定特征用于着色,可以额外添加
feature_index参数,默认使用所有特征的数值分布即可。
内容的提问来源于stack exchange,提问作者natnicha teja
相关产品推荐
相关产品推荐

