python打卡 15 复习日( shap 库绘制图形总结)

目录

SHAP (SHapley Additive exPlanations) 可视化笔记

一、SHAP 基础概念

1.1 SHAP 值核心思想

1.2 SHAP 值的数学表达

二、SHAP 可视化类型

2.1 全局特征重要性

2.1.1 条形图

2.1.2 蜂群图 (Beeswarm Plot)

2.2 局部解释

2.2.1 单个预测解释

2.2.2 力图 (Force Plot)

2.3 交互作用可视化

2.3.1 依赖图

2.3.2 交互作用图

三、SHAP 高级应用

3.1 模型比较

3.2 聚类分析

3.3 文本和图像解释

四、SHAP 使用技巧

4.1 加速计算

4.2 处理分类特征

4.3 自定义可视化

五、SHAP 可视化解读指南

六、完整示例代码

七、注意事项

开源数据集平台大全

一、综合型数据集平台

1. Kaggle Datasets

2. UCI Machine Learning Repository

3. Google Dataset Search

二、计算机视觉数据集

1. ImageNet

2. COCO (Common Objects in Context)

3. Open Images Dataset

三、自然语言处理数据集

1. Hugging Face Datasets

2. SQuAD (Stanford Question Answering Dataset)

3. GLUE Benchmark

四、科学和学术数据集

1. Figshare

2. Dryad

3. Zenodo

五、政府和公共数据

1. World Bank Open Data

2. NASA Open Data

3. EU Open Data Portal

六、特定领域数据集

1. 医学和生物信息学

2. 地理空间数据

3. 金融和经济

完整示例(我的专业相关:WiFi 数据集)

步骤一:数据预处理

步骤二 超参数优化

步骤三:shap库绘制图形


SHAP (SHapley Additive exPlanations) 可视化笔记

  SHAP 是一种基于博弈论的解释机器学习模型预测的方法,可以提供直观的特征重要性分析和单个预测的解释。

一、SHAP 基础概念

1.1 SHAP 值核心思想

  • 基于博弈论的 Shapley 值

  • 量化每个特征对模型预测的贡献度

  • 满足可加性:所有特征的 SHAP 值之和等于预测值与平均预测的差值

1.2 SHAP 值的数学表达

对于单个样本的预测:

二、SHAP 可视化类型

2.1 全局特征重要性

2.1.1 条形图

import shap

# 创建解释器
explainer = shap.Explainer(model)
shap_values = explainer(X)

# 全局特征重要性
shap.plots.bar(shap_values)

解读

  • 按平均绝对 SHAP 值降序排列

  • 显示各特征对模型输出的总体影响

2.1.2 蜂群图 (Beeswarm Plot)
shap.plots.beeswarm(shap_values)

特点

  • 展示特征值与 SHAP 值的关系

  • 颜色表示特征值高低

  • 点密度反映样本分布

2.2 局部解释

2.2.1 单个预测解释

# 解释单个样本
shap.plots.waterfall(shap_values[0])  # 第一个样本

解读

  • 显示从基线值到预测值的"流动"

  • 每个特征推动预测增加或减少

2.2.2 力图 (Force Plot)
shap.plots.force(shap_values[0])

特点

  • 直观显示各特征对当前预测的贡献

  • 红色表示正向推动,蓝色表示负向推动

2.3 交互作用可视化

2.3.1 依赖图

shap.plots.scatter(shap_values[:, "feature_name"])
 

解读

  • 显示某个特征的 SHAP 值如何随特征值变化

  • 可发现非线性关系和阈值效应

2.3.2 交互作用图

shap.plots.scatter(shap_values[:, "feature1"], color=shap_values[:, "feature2"])

解读

  • 显示两个特征的交互作用

  • 颜色表示第二个特征的值

三、SHAP 高级应用

3.1 模型比较

# 比较两个模型的 SHAP 值
explainer1 = shap.Explainer(model1)
explainer2 = shap.Explainer(model2)
shap_values1 = explainer1(X)
shap_values2 = explainer2(X)

shap.plots.scatter(shap_values1[:, "feature"], color=shap_values2[:, "feature"])

3.2 聚类分析

# 基于 SHAP 值聚类
clustering = shap.utils.hclust(X, shap_values)
shap.plots.bar(shap_values, clustering=clustering)
 

3.3 文本和图像解释

# 文本模型解释
explainer = shap.Explainer(text_model)
shap_values = explainer([text_sample])
shap.plots.text(shap_values)

# 图像模型解释
explainer = shap.Explainer(image_model)
shap_values = explainer([image_array])
shap.image_plot(shap_values, [image_array])

四、SHAP 使用技巧

4.1 加速计算

# 使用近似方法
explainer = shap.Explainer(model, algorithm="permutation")

# 对样本子集计算
shap_values = explainer(X[:100])  # 只计算前100个样本

4.2 处理分类特征

# 使用独热编码
X_encoded = pd.get_dummies(X, columns=["categorical_feature"])

# 或者使用 Partition 解释器
explainer = shap.PartitionExplainer(model, X)

4.3 自定义可视化

# 修改颜色和样式
shap.plots.beeswarm(shap_values, color=plt.get_cmap("coolwarm"))
 

五、SHAP 可视化解读指南

可视化类型适用场景关键解读点
条形图全局特征重要性特征对模型输出的总体影响排序
蜂群图特征影响分布特征值与 SHAP 值的关系、数据分布
力图单个预测解释各特征对特定预测的具体贡献
依赖图特征效应分析特征与预测的非线性关系
交互图特征交互作用两个特征如何共同影响预测

六、完整示例代码

import shap
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
import matplotlib.pyplot as plt

# 1. 准备数据和模型
# 假设 X_train, y_train 已经准备好
model = RandomForestClassifier().fit(X_train, y_train)

# 2. 创建 SHAP 解释器
explainer = shap.Explainer(model)
shap_values = explainer(X_train)

# 3. 全局解释
plt.figure(figsize=(10, 6))
shap.plots.bar(shap_values, show=False)
plt.title("Global Feature Importance")
plt.tight_layout()
plt.show()

# 4. 蜂群图
plt.figure(figsize=(10, 6))
shap.plots.beeswarm(shap_values, show=False)
plt.title("Feature Effects")
plt.tight_layout()
plt.show()

# 5. 单个样本解释
sample_idx = 0  # 解释第一个样本
shap.plots.waterfall(shap_values[sample_idx])

# 6. 特征依赖分析
feature_name = "age"  # 分析age特征
shap.plots.scatter(shap_values[:, feature_name])

七、注意事项

  1. 计算资源

    • SHAP 计算可能很耗时,特别是对大型数据集

    • 树模型可以使用 TreeSHAP 加速,其他模型考虑使用 KernelSHAP 或抽样

  2. 模型支持

    • TreeSHAP 适用于树模型(随机森林、XGBoost 等)

    • KernelSHAP 适用于任何模型,但计算更慢

  3. 解释一致性

    • SHAP 值会因随机种子不同而略有变化

    • 对重要结论建议多次运行验证

  4. 特征相关性

    • 当特征高度相关时,SHAP 解释可能不稳定

    • 考虑使用 SHAP 交互值或聚类分析

SHAP 提供了强大的模型解释能力,帮助理解模型行为、验证特征重要性,并识别潜在的偏差问题。正确解读 SHAP 可视化结果对于模型调试和业务解释至关重要。

开源数据集平台大全

一、综合型数据集平台

1. Kaggle Datasets

2. UCI Machine Learning Repository

  • 网址UCI Machine Learning Repository

  • 特点:

    • 最古老的机器学习数据集库之一(1987年创建)

    • 包含400+个经典数据集

    • 每个数据集都有详细的元数据描述

3. Google Dataset Search

二、计算机视觉数据集

1. ImageNet

  • 网址ImageNet

  • 特点:

    • 1400万张标注图像,2万多个类别

    • 年度ILSVRC比赛的基础数据集

    • 需要注册申请访问权限

2. COCO (Common Objects in Context)

  • 网址COCO - Common Objects in Context

  • 特点:

    • 33万张图像,80个物体类别

    • 包含目标检测、分割、关键点标注

    • 提供标准的评估指标

3. Open Images Dataset

  • 网址Open Images V7

  • 特点:

    • Google提供的900万张图像数据集

    • 包含图像级标签、边界框和分割掩码

    • 6000个物体类别

三、自然语言处理数据集

1. Hugging Face Datasets

2. SQuAD (Stanford Question Answering Dataset)

3. GLUE Benchmark

  • 网址GLUE Benchmark

  • 特点:

    • 9个不同的NLP任务数据集

    • 用于评估模型的语言理解能力

    • 已被SuperGLUE基准取代

四、科学和学术数据集

1. Figshare

2. Dryad

3. Zenodo

  • 网址Zenodo

  • 特点:

    • 由CERN运营的开放研究数据平台

    • 支持50GB以内的数据集上传

    • 为每个数据集分配DOI

五、政府和公共数据

1. World Bank Open Data

  • 网址World Bank Open Data | Data

  • 特点:

    • 全球发展指标的权威来源

    • 包含3000+个经济和社会指标

    • 支持多种格式下载

2. NASA Open Data

  • 网址Welcome - NASA Open Data Portal

  • 特点:

    • 地球科学、航空航天等领域数据集

    • 包含卫星图像、气候数据等

    • 部分数据集实时更新

3. EU Open Data Portal

六、特定领域数据集

1. 医学和生物信息学

2. 地理空间数据

3. 金融和经济

完整示例(我的专业相关:WiFi 数据集,来自kaggleWi-Fi Indoor Localization Dataset (WILD-v2) | Kaggle

步骤一:数据预处理

import pandas as pd
import pandas as pd    #用于数据处理和分析,可处理表格数据。
import numpy as np     #用于数值计算,提供了高效的数组操作。
import matplotlib.pyplot as plt    #用于绘制各种类型的图表
import seaborn as sns   #基于matplotlib的高级绘图库,能绘制更美观的统计图形。
import warnings
warnings.filterwarnings("ignore")
 
 # 设置中文字体(解决中文显示问题)
plt.rcParams['font.sans-serif'] = ['SimHei']  # Windows系统常用黑体字体
plt.rcParams['axes.unicode_minus'] = False    # 正常显示负号
data = pd.read_csv('sample_solution.csv')    #读取数据
# Environment 1-0映射
Environment_mapping = {
    '4floor':0,
    '5floor':1    
}
data['Environment'] = data['Environment'].map(Environment_mapping)
data.rename(columns={'Environment4': 'Environment5'}, inplace=True) # 重命名列
continuous_features = data.select_dtypes(include=['int64', 'float64']).columns.tolist()  #把筛选出来的列名转换成列表
data.head()

# 最开始也说了 很多调参函数自带交叉验证,甚至是必选的参数,你如果想要不交叉反而实现起来会麻烦很多
# 所以这里我们还是只划分一次数据集
from sklearn.model_selection import train_test_split
X = data.drop(['Environment'], axis=1)  # 特征,axis=1表示按列删除
y = data['Environment'] # 标签
# 按照8:2划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)  # 80%训练集,20%测试集


步骤二 超参数优化

 基础超参数优化

from sklearn.ensemble import RandomForestClassifier #随机森林分类器

from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score # 用于评估分类器性能的指标
from sklearn.metrics import classification_report, confusion_matrix #用于生成分类报告和混淆矩阵
import warnings #用于忽略警告信息
warnings.filterwarnings("ignore") # 忽略所有警告信息
# --- 1. 默认参数的随机森林 ---
# 评估基准模型,这里确实不需要验证集
print("--- 1. 默认参数随机森林 (训练集 -> 测试集) ---")
import time # 这里介绍一个新的库,time库,主要用于时间相关的操作,因为调参需要很长时间,记录下会帮助后人知道大概的时长
start_time = time.time() # 记录开始时间
rf_model = RandomForestClassifier(random_state=42)
rf_model.fit(X_train, y_train) # 在训练集上训练
rf_pred = rf_model.predict(X_test) # 在测试集上预测
end_time = time.time() # 记录结束时间

print(f"训练与预测耗时: {end_time - start_time:.4f} 秒")
print("\n默认随机森林 在测试集上的分类报告:")
print(classification_report(y_test, rf_pred))
print("默认随机森林 在测试集上的混淆矩阵:")
print(confusion_matrix(y_test, rf_pred))

 

 退火算法对比性能

import random
# --- 2. 模拟退火算法优化随机森林 ---
print("\n--- 2. 模拟退火算法优化随机森林 (训练集 -> 测试集) ---")


# 定义适应度函数
def fitness_function(params): 
    n_estimators, max_depth, min_samples_split, min_samples_leaf = params
    model = RandomForestClassifier(n_estimators=int(n_estimators),
                                   max_depth=int(max_depth),
                                   min_samples_split=int(min_samples_split),
                                   min_samples_leaf=int(min_samples_leaf),
                                   random_state=42)
    model.fit(X_train, y_train)
    y_pred = model.predict(X_test)
    accuracy = accuracy_score(y_test, y_pred)
    return accuracy


# 模拟退火算法实现
def simulated_annealing(initial_solution, bounds, initial_temp, final_temp, alpha):
    current_solution = initial_solution
    current_fitness = fitness_function(current_solution)
    best_solution = current_solution
    best_fitness = current_fitness
    temp = initial_temp

    while temp > final_temp:
        # 生成邻域解
        neighbor_solution = []
        for i in range(len(current_solution)):
            new_val = current_solution[i] + random.uniform(-1, 1) * (bounds[i][1] - bounds[i][0]) * 0.1
            new_val = max(bounds[i][0], min(bounds[i][1], new_val))
            neighbor_solution.append(new_val)

        neighbor_fitness = fitness_function(neighbor_solution)
        delta_fitness = neighbor_fitness - current_fitness

        if delta_fitness > 0 or random.random() < np.exp(delta_fitness / temp):
            current_solution = neighbor_solution
            current_fitness = neighbor_fitness

        if current_fitness > best_fitness:
            best_solution = current_solution
            best_fitness = current_fitness

        temp *= alpha

    return best_solution, best_fitness


# 超参数范围
bounds = [(50, 200), (10, 30), (2, 10), (1, 4)]  # n_estimators, max_depth, min_samples_split, min_samples_leaf

# 模拟退火算法参数
initial_temp = 100 # 初始温度
final_temp = 0.1 # 终止温度
alpha = 0.95 # 温度衰减系数

# 初始化初始解
initial_solution = [random.uniform(bounds[i][0], bounds[i][1]) for i in range(len(bounds))]

start_time = time.time()
best_params, best_fitness = simulated_annealing(initial_solution, bounds, initial_temp, final_temp, alpha)
end_time = time.time()

print(f"模拟退火算法优化耗时: {end_time - start_time:.4f} 秒")
print("最佳参数: ", {
    'n_estimators': int(best_params[0]),
    'max_depth': int(best_params[1]),
    'min_samples_split': int(best_params[2]),
    'min_samples_leaf': int(best_params[3])
})

# 使用最佳参数的模型进行预测
best_model = RandomForestClassifier(n_estimators=int(best_params[0]),
                                    max_depth=int(best_params[1]),
                                    min_samples_split=int(best_params[2]),
                                    min_samples_leaf=int(best_params[3]),
                                    random_state=42)
best_model.fit(X_train, y_train)
best_pred = best_model.predict(X_test)

print("\n模拟退火算法优化后的随机森林 在测试集上的分类报告:")
print(classification_report(y_test, best_pred))
print("模拟退火算法优化后的随机森林 在测试集上的混淆矩阵:")
print(confusion_matrix(y_test, best_pred))

步骤三:shap库绘制图形

import lightgbm as lgb 
from sklearn.model_selection import train_test_split, StratifiedKFold
from sklearn.metrics import roc_auc_score 
from imblearn.over_sampling import SMOTE 
 
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) 
 
# 定义SMOTE对象
smote = SMOTE(random_state=42) 
 
# 定义LightGBM模型
lgb_model = lgb.LGBMClassifier(random_state=42) 
 
# 定义交叉验证对象
kfold = StratifiedKFold(n_splits=5, shuffle=True, random_state=42) 
 
# 存储每次交叉验证的AUC分数
cv_scores = [] 
 
# 进行交叉验证
for train_index, val_index in kfold.split(X_train, y_train):
    X_train_fold, X_val_fold = X_train.iloc[train_index], X_train.iloc[val_index]
    y_train_fold, y_val_fold = y_train.iloc[train_index], y_train.iloc[val_index]
 
    # 对训练集进行过采样
    X_train_resampled, y_train_resampled = smote.fit_resample(X_train_fold, y_train_fold) 
 
    # 训练模型
    lgb_model.fit(X_train_resampled, y_train_resampled) 
 
    # 在验证集上进行预测
    y_val_pred_proba = lgb_model.predict_proba(X_val_fold)[:, 1] 
 
    # 计算验证集的AUC分数
    val_auc = roc_auc_score(y_val_fold, y_val_pred_proba) 
    cv_scores.append(val_auc) 
 
# 输出交叉验证的平均AUC分数
print('交叉验证平均AUC: ', sum(cv_scores) / len(cv_scores)) 

import shap 
explainer = shap.Explainer(lgb_model) 
shap_values2 = explainer(X_test) 
# 输出shap.Explanation对象
shap_values = explainer.shap_values(X) # 输出numpy.array数组

import matplotlib.pyplot as plt
shap.plots.bar(shap_values2)
plt.show()  #plots.bar中的shap_values是 shap.Explanation对象
shap.summary_plot(shap_values,X, 
                  plot_type="bar")

shap.plots.bar(shap_values2[1], show_data=True)

# 绘制队列条形图
# 选择一个特征进行分组,这里以 LocationID 为例,当 LocationID 大于中位数时标记为 High Income,否则标记为 Low Income
import numpy as np
median_income = np.median(X_test['LocationID'])
income_group = ["High Income" if X_test['LocationID'].iloc[i] > median_income 
                else "Low Income" for i in range(X_test.shape[0])]
 
# 按分组计算绝对值的均值并绘制条形图
shap.plots.bar(shap_values2.cohorts(income_group).abs.mean(0))# 此处必须使用shap.Explanation 对象的函数。 shap.Explanation 对象才包含 cohorts 方法,而 numpy.ndarray 不包含。

from sklearn.tree import DecisionTreeRegressor
# 设置队列数量
N = 3
 
cohorts = shap.Explainer(lgb_model)(X_test).cohorts(N)
# 绘制分组后的 SHAP 条形图
shap.plots.bar(cohorts.abs.mean(0))

shap.summary_plot(shap_values, X)
shap.plots.beeswarm(shap_values2, 
                    order=shap_values2.abs.max(0)) #默认是按照平均值排序,但此处按最大绝对值排序。

import shap 
explainer = shap.Explainer(lgb_model) 
shap_values2 = explainer(X_test) 
# 选择要分析的样本索引,这里以第一个样本为例
sample_index = 0
 
# 绘制单个样本的 force plot
shap.force_plot(explainer.expected_value, shap_values2[sample_index].values, X_test.iloc[sample_index], matplotlib=True)
 

import shap 
# 创建解释器
explainer = shap.Explainer(lgb_model)
# 计算 SHAP 值
shap_values2 = explainer(X_test)
 
# 获取预期值,根据模型类型不同,预期值可能在不同位置
if isinstance(shap_values2, list):
    expected_value = explainer.expected_value[1]
    shap_values = shap_values2[1]
else:
    expected_value = explainer.expected_value
    shap_values = shap_values2.values
 
# 选择前 20 个样本进行可视化,可根据需求调整
sample_indices = range(20)
selected_shap_values = shap_values[sample_indices]
selected_features = X_test.iloc[sample_indices]
 
# 绘制 Decision plot
shap.decision_plot(expected_value, selected_shap_values, selected_features)

shap.plots.waterfall(shap_values2[5])

@浙大疏锦行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值