趋近智
实践例子展示了如何使用shap Python库来计算和可视化SHAP值,这有助于理解个体预测和整体模型行为。
我们假设您已经有一个训练好的机器学习模型,并希望更好地理解其预测。在此例子中,我们设想已经在像Iris数据集这样大家熟悉的数据集上训练了一个梯度提升分类器。
首先,请确保您已安装所需的库。您主要需要shap、scikit-learn和pandas。
# 如果您尚未安装shap,请安装
# pip install shap
import shap
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.datasets import load_iris
# 加载Iris数据集
iris = load_iris()
X = pd.DataFrame(iris.data, columns=iris.feature_names)
y = iris.target
# 为了演示,我们简化为一个二元分类问题
# 类别0 对比 类别1 & 2
y_binary = (y > 0).astype(int)
class_names = ['setosa', 'not setosa'] # 将0映射为'setosa',1映射为'not setosa'
# 划分数据
X_train, X_test, y_train, y_test = train_test_split(X, y_binary, test_size=0.2, random_state=42)
# 训练一个梯度提升分类器
model = GradientBoostingClassifier(n_estimators=100, random_state=42)
model.fit(X_train, y_train)
print(f"模型已在 {X_train.shape[0]} 个样本上训练。")
print(f"正在 {X_test.shape[0]} 个样本上进行测试。")
这就配置好了我们的环境,数据已加载到Pandas DataFrame X 中,目标变量为 y_binary。我们已经训练了一个 GradientBoostingClassifier。
由于梯度提升是一个基于树的集成模型,计算SHAP值的最有效方式是使用shap.TreeExplainer。这个解释器利用树的内部结构进行更快的计算,相比于像KernelExplainer这样的模型无关方法更为迅速。
# 1. 初始化解释器
# 我们将训练好的模型传递给解释器。
explainer = shap.TreeExplainer(model)
# 2. 计算SHAP值
# 我们为测试集(或任何我们想解释的数据)计算SHAP值。
# 输出的'shap_values'通常是一个列表(用于多分类)或数组(用于二分类)
# 包含每个特征、每个实例的SHAP值。
# 对于使用scikit-learn模型的二元分类,shap通常返回
# 对应正类别(本例中为类别1)的值。
shap_values = explainer.shap_values(X_test)
# 检查形状:(样本数量,特征数量)
print(f"SHAP值形状: {shap_values.shape}")
# 检查预期值(基准值)
# 这是训练数据(或背景数据)上的平均预测
print(f"解释器预期值(基准值): {explainer.expected_value}")
shap_values变量现在包含一个数组,其中每行对应X_test中的一个实例,每列对应一个特征。该值本身表示该特征对模型输出(对数几率或概率,取决于模型和解释器设置)在该特定实例上的贡献,与基准值(explainer.expected_value)进行对比。
为了理解单个预测,力图非常有效。它显示了哪些特征使预测结果更高(正SHAP值,通常为红色),哪些特征使预测结果更低(负SHAP值,通常为蓝色)。
让我们解释测试集中第一个实例(X_test.iloc[0])的预测。
# 在环境中初始化JavaScript可视化(绘图所需)
shap.initjs()
# 解释第一个预测
instance_index = 0
# 为第一个实例创建力图
# 我们传入基准值、该实例的SHAP值和特征值
shap.force_plot(explainer.expected_value,
shap_values[instance_index,:],
X_test.iloc[instance_index,:],
matplotlib=False) # 使用Javascript绘图
力图显示了每个特征对单个实例预测的贡献。使预测结果更高的特征显示为红色,使预测结果更低的特征显示为蓝色。条形的长度表示特征影响的大小。
理解这个图:“基准值”表示所有样本的平均预测分数。列出的特征是那些使该特定实例的预测偏离基准值的特征。如果最终输出值高于基准值,则红色特征(正SHAP值)的集体影响强于蓝色特征(负SHAP值)。您可以清楚地看到哪些特征(如petal width (cm)或sepal length (cm))对这个特定预测影响最大以及影响方向。
尽管力图对于个体预测很适用,汇总图则提供了整个数据集(或您计算SHAP值所用的子集)上特征重要性的全局情况。
汇总图有多种样式。默认样式(plot_type="dot")显示了每个特征的SHAP值分布。
# 创建汇总图(点图版)
shap.summary_plot(shap_values, X_test, plot_type="dot")
测试集中每个特征的SHAP值分布。每个点代表一个特征在单个预测中的SHAP值。颜色表示特征值(红色=高,蓝色=低)。
理解:
petal length (cm)和petal width (cm)最具影响。petal length (cm),高值(红色点)通常具有高的正SHAP值,推动预测结果倾向类别1(“非狗尾草”)。低值(蓝色点)具有负SHAP值,推动预测结果倾向类别0(“狗尾草”)。sepal width (cm)整体影响较小(点集中在零附近),且特征值与影响方向之间的关联性不那么明显。另一种方式是,条形图显示了每个特征的平均SHAP绝对值,更清楚地展示了整体重要性的大小。
# 创建汇总图(条形图版)
shap.summary_plot(shap_values, X_test, plot_type="bar")
测试集中每个特征的平均SHAP绝对值。较高的条形表示对预测的平均影响越大。
这个条形图证实了,在这个数据集中,花瓣长度和宽度对模型预测的平均影响最大。
依赖图显示了单个特征的SHAP值如何随该特征值的变化而变化。它们还可以通过根据另一个特征的值来着色点,从而展示关联作用。
让我们研究模型输出对petal width (cm)的依赖性,并看看它是否与petal length (cm)有关联。
# 为'petal width (cm)'创建依赖图
# 根据'petal length (cm)'着色点以检查关联
shap.dependence_plot("petal width (cm)", shap_values, X_test, interaction_index="petal length (cm)")
'petal width (cm)'的值与其对应SHAP值之间的关系。颜色表示'petal length (cm)'的值。
理解:
petal width (cm)的增加,其SHAP值趋于增加,这意味着较高的花瓣宽度强烈地将预测推向“非狗尾草”。在花瓣宽度约为0.7-0.8厘米处有一个显著的跳跃。petal length (cm)着色有助于观察关联作用。请注意,高petal width (cm)(右侧)的点始终具有高petal length (cm)(红色)。相反,低petal width (cm)(左侧)的点大多具有低petal length (cm)(蓝色)。这种强关联在Iris数据集中是预期的。如果存在显著关联,您可能会在给定花瓣宽度下看到颜色的垂直分离(例如,在花瓣宽度=1.5时,红色点的SHAP值系统性地高于或低于蓝色点)。在这种情况下,关联作用看起来很小。通过生成和分析这些图,您不再只是了解模型的预测结果,而是理解它为什么做出该预测,确定局部和全局最具影响的特征,并考察潜在的特征关联。SHAP的这种实践应用对调试、验证以及在您的机器学习模型中建立信任具有重要价值。
这部分内容有帮助吗?
© 2026 ApX Machine Learning用心打造