深度学习模型在与医学有关的各种任务中表现出了令人印象深刻的性能,但其黑箱性质往往会引起人们对可解释性的担忧,从而阻碍其临床应用。在本文中,我们将探讨如何利用 SHapley Additive exPlanations(SHAP)来解释训练好的深度学习模型,以便对乳腺肿瘤进行分类。SHAP 可以让人们深入了解每个特征是如何影响模型预测的,从而提高模型的透明度和信任度。SHAP 采用博弈论方法,利用经典的 Shapley 值将最佳信用分配与局部解释联系起来。
威斯康星州乳腺癌数据
本文将使用 Kaggle 提供的威斯康星州乳腺癌数据集。该数据集包含从乳房肿块图像中提取的各种特征,以及表示肿块是良性还是恶性的目标列,因此是一个二元分类问题。让我们首先加载数据集并进行基本预处理,使其符合学习模型所期望的形状和格式。
# Load dataset
df = pd.read_csv('data.csv')
df = df.drop('Unnamed: 32', axis=1)
# Encode categorical column using integers
lab_enc = preprocessing.LabelEncoder()
df['diagnosis_enc'] = lab_enc.fit_transform(df['diagnosis'])
# Get features and labels
X = df.drop(['id', 'diagnosis', 'diagnosis_enc'], axis=1)
Y = df['diagnosis_enc']
# Perform train test split
x_train, x_test, y_train, y_test = train_test_split(X, Y, test_size=0.2)
# Perform standardization
scaler = StandardScaler()
scaler.fit(x_train)
X_train_norm = scaler.transform(x_train)
X_test_norm = scaler.transform(x_test)
模型设计
任务中使用的深度学习模型是用 TensorFlow 构建的。它由一个输入层、两个使用 ReLU 激活的密集隐藏层(每个层有 32 个神经元)和一个使用 sigmoid 激活函数的输出层组成。该模型采用二元交叉熵损失和 Adam 优化器进行编译。这种相对简单的结构能有效区分良性肿瘤和恶性肿瘤,可用于演示 SHAP 分析。不过,同样的方法也可应用于更复杂的架构。
#Create model class using sequential
model = tf.keras.Sequential()
#Add two hidden layers with 32 neurons
model.add(tf.keras.layers.Dense(32, input_shape=(X_train_norm.shape[1],), activation = 'relu'))
model.add(tf.keras.layers.Dense(32, activation = 'relu'))
#Output layer
model.add(tf.keras.layers.Dense(1, activation='sigmoid'))
#Compile with loss and optimizer
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['acc'])
模型评估
模型训练了 100 个历元,训练和验证损失如下。
该模型的性能使用测试集进行评估。测试集的分类报告如下。模型的总体准确率为 92%。该模型表现出足够好的性能,具有较高的精确度和召回率,在大多数情况下都能做出准确的预测。
precision recall f1-score support
Benign 0.99 0.89 0.94 75
Malignant 0.83 0.97 0.89 39
accuracy 0.92 114
macro avg 0.91 0.93 0.92 114
weighted avg 0.93 0.92 0.92 114
SHAP 分析
我们将使用 SHAP python 软件包计算模型的 SHAP 值,通过为每个特征赋值来衡量特征的重要性。该值通过将平均模型预测值推向两侧来显示特征对结果的影响。DeepExplainer 工具适用于深度学习模型,可为每个特征提供 SHAP 值。
import shap
# Initialize JS visualization
shap.initjs()
# Calculate SHAP values
explainer = shap.DeepExplainer(model, X_train_norm)
shap_values = explainer.shap_values(X_test_norm)
由于 SHAP 值是针对每个数据实例计算的,因此汇总图可以很好地估算全局特征的重要性。x 轴代表 SHAP 绝对值的平均值,表示对模型预测所有样本的平均影响。特征按其重要性排序,平均 SHAP 值最高的特征排在最前面。从图中可以看出,concave points_worst 对模型输出的影响最大,紧随其后的是 concavity_worst。这些特征对确定乳腺癌的良性或恶性分类至关重要。其他特征也发挥了重要作用,但与最重要的特征相比,它们的影响略小。这幅图强调了乳房肿块的特定特征,尤其是与凹度和紧密度相关的特征,对模型区分良性和恶性病例至关重要。
#Visualizing global feature importance using summary plot
shap.summary_plot(shap_values, feature_names = X.columns)
SHAP 瀑布图详细分解了每个特征对单个预测的贡献。在这里,我们看到的是一个特定实例的预测过程。该图从基线值开始,基线值代表模型预测的平均值,也称为期望值。从基线值开始,我们可以看到各个特征对最终预测结果的贡献。该图有效地显示了所有这些特征贡献的组合如何导致最终的模型输出,在本例中为 0.753。这种详细的细分有助于我们了解驱动模型对这一特定实例做出决定的具体因素,为我们提供了对模型行为的宝贵见解,并提高了对其预测的信任度。
#Visualizing each feature's impact on decision using waterfall plot
shap.plots._waterfall.waterfall_legacy(explainer.expected_value[0].numpy(), shap_values[0][0], feature_names = X.columns)
最后,SHAP 力图全面展示了不同特征对模型在多个实例中预测结果的影响。每条线代表一个实例的预测结果,颜色表示特征的影响方向。红色表示对预测的正贡献,蓝色表示负贡献。y 轴表示模型的预测值,从负影响到正影响不等。x 轴表示按相似度排序的各个实例。力图有效地说明了所有特征对模型预测的累积影响,提供了一个透明的视图,显示单个特征值如何影响整个决策过程。
# visualize all the training set predictions
shap.plots.force(explainer.expected_value.numpy(), shap_values[0], feature_names = X.columns)
本文展示了如何利用 SHAP 来解释深度学习模型。通过了解每个特征对模型预测的影响,我们可以获得有价值的见解,并建立对模型的信任。SHAP 为模型的可解释性提供了一个强大的工具集,使复杂的模型更加透明和易懂。