✨ 欢迎关注 ✨
本节介绍:利用K-medoids算法为SHAP解释器提供数据背景加快SHAP计算速度。数据采用模拟数据,作者根据个人对机器学习的理解进行代码实现与图表输出,仅供参考。 完整数据和代码将在稍后上传至交流群,成员可在交流群中获取下载。需要的朋友可关注公众文末提供的获取方式 。 购买前请咨询,避免不必要的问题。
✨ 基础知识 ✨
在机器学习中,SHAP计算通常使用shap.TreeExplainer对树模型进行快速计算,但对于如线性模型等其他模型,可以通过KernelExplainer和其predict属性进行计算;然而,当背景数据过大时,计算可能会变得非常慢,这时可以通过聚类算法提取具有代表性的聚类中心数据,减少背景数据量的同时保留关键信息,从而加速SHAP计算
✨ 基础代码 ✨
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = 'Times New Roman'
plt.rcParams['axes.unicode_minus'] = False
import warnings
# 忽略所有警告
warnings.filterwarnings("ignore")
df = pd.read_excel('2025-7-17-公众号Python机器学习AI.xlsx')
from sklearn.model_selection import train_test_split
# 划分特征和目标变量
X = df.drop(['Outcome'], axis=1)
y = df['Outcome']
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(
X,
y,
test_size=0.3,
random_state=42,
stratify=df['Outcome']
)
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report
# 构建逻辑回归模型
model = LogisticRegression(max_iter=1000) # max_iter 设大一点以避免收敛警告
# 模型训练
model.fit(X_train, y_train)
使用逻辑回归(Logistic Regression)构建一个常见的线性二分类模型,通过训练集来拟合数据
import shap
explainer = shap.KernelExplainer(
model_predict_proba,
X_train, # 注意:背景数据应该是 Pandas DataFrame 或 Numpy Array
)
print("KernelExplainer 初始化完成。")
# 计算 SHAP 值
# 将为测试集计算 SHAP 值。
# 如果测试集非常大,计算可能会非常耗时。
# 在这种情况下,你可能只想为一个子集计算 SHAP 值。
X_to_explain = X_test # 这里解释整个测试集
print(f"开始为 {X_to_explain.shape[0]} 个样本计算 SHAP 值 (这可能需要一些时间)...")
# KernelExplainer.shap_values() 期望输入数据 (X_to_explain) 是 NumPy 数组。
# 如果 X_to_explain 是 Pandas DataFrame,使用 .values 或 .to_numpy()
if isinstance(X_to_explain, pd.DataFrame):
X_to_explain_np = X_to_explain.to_numpy()
else:
X_to_explain_np = X_to_explain # 假设它已经是numpy数组了
# `nsamples` 参数控制为每个解释的实例生成多少扰动样本。
# 'auto' 让 shap 库决定。较大的值更准确但更慢。
try:
shap_values = explainer.shap_values(X_to_explain_np, nsamples='auto')
print("SHAP 值计算完成。")
print(f"SHAP 值矩阵的形状: {shap_values.shape}")
# 形状应该是 (num_samples_in_X_to_explain, num_features)
except Exception as e:
print(f"计算 SHAP 值时发生错误: {e}")
print("请检查模型预测函数和背景数据的格式与内容。")
shap_values = None
使用shap.KernelExplainer进行 SHAP 值计算,背景数据采用了完整的训练集,通过model_predict_proba函数对测试集进行解释
KernelExplainer 初始化完成。
开始为 231 个样本计算 SHAP 值 (这可能需要一些时间)...
100%
231/231 [02:17<00:00, 1.74it/s]
SHAP 值计算完成。
SHAP 值矩阵的形状: (231, 8)
该代码运行了2分17秒,计算了231个样本(测试集)的SHAP值
plt.figure(figsize=(10, 5), dpi=1200)
shap.summary_plot(shap_values, X_test, plot_type="bar", show=False)
plt.tight_layout()
plt.figure()
shap.summary_plot(shap_values, X_test, feature_names=X_test.columns, plot_type="dot", show=False)
这是完整训练集作为背景的结果,两种基础的shap解释可视化
from sklearn_extra.cluster import KMedoids
# 创建 KMedoids 模型
kmedoids = KMedoids(n_clusters=100, random_state=42)
# 训练 KMedoids 模型
kmedoids.fit(X_train)
# 获取聚类中心(medoids)
cluster_centers = kmedoids.cluster_centers_
# 将聚类中心转换为 DataFrame
cluster_centers_kmedoids = pd.DataFrame(cluster_centers, columns=X_train.columns)
explainer = shap.KernelExplainer(
model_predict_proba,
cluster_centers_kmedoids, # 注意:背景数据应该是 Pandas DataFrame 或 Numpy Array
)
print("KernelExplainer 初始化完成。")
# 计算 SHAP 值
# 将为测试集计算 SHAP 值。
# 如果测试集非常大,计算可能会非常耗时。
# 在这种情况下,你可能只想为一个子集计算 SHAP 值。
X_to_explain = X_test # 这里解释整个测试集
print(f"开始为 {X_to_explain.shape[0]} 个样本计算 SHAP 值 (这可能需要一些时间)...")
# KernelExplainer.shap_values() 期望输入数据 (X_to_explain) 是 NumPy 数组。
# 如果 X_to_explain 是 Pandas DataFrame,使用 .values 或 .to_numpy()
if isinstance(X_to_explain, pd.DataFrame):
X_to_explain_np = X_to_explain.to_numpy()
else:
X_to_explain_np = X_to_explain # 假设它已经是numpy数组了
# `nsamples` 参数控制为每个解释的实例生成多少扰动样本。
# 'auto' 让 shap 库决定。较大的值更准确但更慢。
try:
shap_values = explainer.shap_values(X_to_explain_np, nsamples='auto')
print("SHAP 值计算完成。")
print(f"SHAP 值矩阵的形状: {shap_values.shape}")
# 形状应该是 (num_samples_in_X_to_explain, num_features)
except Exception as e:
print(f"计算 SHAP 值时发生错误: {e}")
print("请检查模型预测函数和背景数据的格式与内容。")
shap_values = None
使用KMedoids聚类算法来提取训练集的 100 个聚类中心作为代表性样本,这些中心样本用作SHAP KernelExplainer的背景数据,从而减少背景数据量以加速SHAP计算。具体来说,kmedoids.fit(X_train) 训练模型后,kmedoids.cluster_centers_ 提取了 100 个聚类中心,这些中心代表了原始数据集的100个关键样本。然后,SHAP计算通过这些代表性样本作为背景数据进行,加速SHAP值的计算过程
KernelExplainer 初始化完成。
开始为 231 个样本计算 SHAP 值 (这可能需要一些时间)...
100%
231/231 [00:27<00:00, 9.23it/s]
SHAP 值计算完成。
SHAP 值矩阵的形状: (231, 8)
在27秒内完成了231个样本的 SHAP 值计算,相比使用完整训练集时的2分17秒,计算速度显著加快,从每秒1.74个样本提升到每秒9.23个样本,表明通过使用KMedoids聚类中心作为背景数据显著提高了计算效率,当然在提高运行速度的同时也得保证解释结果,同样的绘制上面 两种基础的shap解释可视化
plt.figure(figsize=(10, 5), dpi=1200)
shap.summary_plot(shap_values, X_test, plot_type="bar", show=False)
plt.tight_layout()
plt.figure()
shap.summary_plot(shap_values, X_test, feature_names=X_test.columns, plot_type="dot", show=False)
可以发现二者的结果基本上是一致的对于各个特征的解读
from sklearn.cluster import KMeans
# 创建 KMeans 模型
kmeans = KMeans(n_clusters=100, random_state=42)
# 训练 KMeans 模型
kmeans.fit(X_train)
# 获取K-means聚类中心
cluster_centers = kmeans.cluster_centers_
# 创建一个 DataFrame 存储聚类中心
cluster_centers_kmeans = pd.DataFrame(cluster_centers, columns=X_train.columns)
explainer = shap.KernelExplainer(
model_predict_proba,
cluster_centers_kmeans, # 注意:背景数据应该是 Pandas DataFrame 或 Numpy Array
)
print("KernelExplainer 初始化完成。")
# 计算 SHAP 值
# 将为测试集计算 SHAP 值。
# 如果测试集非常大,计算可能会非常耗时。
# 在这种情况下,你可能只想为一个子集计算 SHAP 值。
X_to_explain = X_test # 这里解释整个测试集
print(f"开始为 {X_to_explain.shape[0]} 个样本计算 SHAP 值 (这可能需要一些时间)...")
# KernelExplainer.shap_values() 期望输入数据 (X_to_explain) 是 NumPy 数组。
# 如果 X_to_explain 是 Pandas DataFrame,使用 .values 或 .to_numpy()
if isinstance(X_to_explain, pd.DataFrame):
X_to_explain_np = X_to_explain.to_numpy()
else:
X_to_explain_np = X_to_explain # 假设它已经是numpy数组了
# `nsamples` 参数控制为每个解释的实例生成多少扰动样本。
# 'auto' 让 shap 库决定。较大的值更准确但更慢。
try:
shap_values = explainer.shap_values(X_to_explain_np, nsamples='auto')
print("SHAP 值计算完成。")
print(f"SHAP 值矩阵的形状: {shap_values.shape}")
# 形状应该是 (num_samples_in_X_to_explain, num_features)
except Exception as e:
print(f"计算 SHAP 值时发生错误: {e}")
print("请检查模型预测函数和背景数据的格式与内容。")
shap_values = None
这里使用另外一种聚类算法KMeans聚类算法提取训练集的100个聚类中心作为代表性样本,作为SHAP KernelExplainer的背景数据,并计算测试集的SHAP值,以加速模型的解释过程
KernelExplainer 初始化完成。
开始为 231 个样本计算 SHAP 值 (这可能需要一些时间)...
100%
231/231 [00:26<00:00, 9.04it/s]
SHAP 值计算完成。
SHAP 值矩阵的形状: (231, 8)
时间显示SHAP值计算的进度,整个过程用时26秒,其中231个样本的SHAP值被计算完成,计算速度为每秒9.04个样本,表明计算相对较快,效率较高。相比于使用完整训练集时计算所需的更长时间,这个优化大大提高了计算速度
plt.figure(figsize=(10, 5), dpi=1200)
shap.summary_plot(shap_values, X_test, plot_type="bar", show=False)
plt.tight_layout()
plt.figure()
shap.summary_plot(shap_values, X_test, feature_names=X_test.columns, plot_type="dot", show=False)
可以发现这种方法和使用完整训练集作为背景得到的结果,略微存在差异, Age和 Insulin的排名有变化,但是其shap散点分布变化不大,而且这两个特征本身贡献度就较接近,也可以忽略不计,这里两种聚类方法都存在参数k也就是你选择的背景样本数量,它其实也会影响你的结果但是影响不会太大,至于这里为什么要先说KMedoids是因为它的聚类中心就是你的原始数据,而kmeans的聚类中心并不是你的原始数据,具体的可以参考往期文章——更具有解释意义的聚类算法K-medoids与常见算法K-means的比较实现,所以作者认为更推荐 KMedoids聚类得到背景样本数据
当然,公众号中还有更多机器学习期刊实战技巧,您可以通过历史文章进行检索和阅读,关注公众号,点击“发信息”>“历史文章”即可搜索公众号所有文章信息
✨ 该文章案例 ✨
在上传至交流群的文件中,像往期文章一样,将对案例进行逐步分析,确保读者能够达到最佳的学习效果。内容都经过详细解读,帮助读者深入理解模型的实现过程和数据分析步骤,从而最大化学习成果。
同时,结合提供的免费AI聚合网站进行学习,能够让读者在理论与实践之间实现融会贯通,更加全面地掌握核心概念。
✨ 介绍 ✨
本节介绍到此结束,有需要学习数据分析和Python机器学习相关的朋友欢迎到淘宝店铺:Python机器学习AI,下方提供淘宝店铺二维码获取作者的公众号合集。截至目前为止,合集已包含近300多篇文章,购买合集的同时,还将提供免费稳定的AI大模型使用。
更新的内容包含数据、代码、注释和参考资料。 作者仅分享案例项目,不提供额外的答疑服务。项目中将提供详细的代码注释和丰富的解读,帮助您理解每个步骤 。 获取 前请咨询,避免不必要的问题。
✨ 群友反馈 ✨
✨ 淘宝店铺 ✨
请大家打开淘宝扫描上方的二维码,进入店铺,获取更多Python机器学习和AI相关的内容 ,希望能为您的学习之路提供帮助!
往期推荐
期刊复现:连续数据与分类数据共存的SHAP可视化散点图与箱形图组合形式
期刊复现:多分类任务如何拆分为二分类任务并进行堆叠预测提高模型预测性能
期刊配图:SHAP值分析模型可解释性在柱状图与蜂窝图中的进阶组合展示
期刊配图:通过堆叠Mean|SHAP|展示不同区间对模型贡献度的可视化分析
期刊复现:利用UMAP降维算法可视化深度学习随着训练次数的增加模型区分能力的变化
期刊配图:PCA、t-SNE与UMAP三种降维方法简化高维数据的展示应用对比
Science期刊复现:分类、回归与Shap分析多角度揭示同一数据集变量对目标的影响
多模型SHAP+PDP解读Stacking集成模型:从基学习器到元学习器的可解释性与模型调参实现
如果你对类似于这样的文章感兴趣。
欢迎关注、点赞、转发~
个人观点,仅供参考