SHAP - 机器学习模型可解释性工具

github地址:shap/docs/index.rst at master · shap/shap (github.com)

SHAP使用文档:欢迎使用 SHAP 文档 — SHAP 最新文档

SHAP介绍 

        SHAP(SHapley Additive exPlanations)是一种用于解释预测结果的方法,它基于Shapley值理论,通过将预测结果分解为每个特征的影响,为模型提供全局和局部的可解释性。

        SHAP的核心思想是将特征值的的贡献分配到不同的特征中,计算每个特征的Shapley值,并将其与特征值相乘得到该特征对于预测结果的贡献,SHAP可以用于机器学习模型,包括分类和回归模型,可以生成图像化和定量的解释结果,帮助用户解释模型的决策过程。

        SHAP的优点包括可解释性强、精度高、适用于各个模型和特征类型等。它可以帮助用户更好地理解机器学习模型地预测结果,识别模型地弱点并改进模型,也可以帮助用户更好地理解机器学习模型地预测结果,识别模型地弱点并改进模型,也可以帮助用户进行特征工程和数据预处理,提高模型地预测能力。

SHAP安装

SHAP 可以从 PyPI 或 conda-forge 安装:

pip install shap
or
conda install -c conda-forge shap

具有 Shapley 值的可解释 AI 简介

这是使用 Shapley 值解释机器学习模型的介绍。Shapley 值是合作博弈论中一种广泛使用的方法,具有理想的属性。本教程旨在帮助学生深入了解如何计算和插入基于 Shapley 的机器学习模型解释。我们将采用实用的动手方法,使用 Python 包来解释逐渐更复杂的模型。这是一份活生生的文件,服务于 作为 Python 包的介绍。因此,如果您有反馈或贡献,请提出问题或拉取请求,以使本教程更好!shapshap

大纲

  • 解释线性回归模型

  • 解释广义加性回归模型

  • 解释非加性提升树模型

  • 解释线性逻辑回归模型

  • 解释非加性提升树逻辑回归模型

  • 处理相关的输入要素

  • 解释 transformers NLP 模型

解释线性回归模型

在使用 Shapley 值解释复杂模型之前,了解它们如何适用于简单模型会很有帮助。最简单的模型类型之一是标准线性回归,因此下面我们在加利福尼亚住房数据集上训练线性回归模型。该数据集由 20 年加利福尼亚州的 640,1990 个房屋街区组成,我们的目标是预测 8 个不同房价中位数的自然对数 特征:

  1. MedInc - 区块组的收入中位数

  2. HouseAge - 区块组的房屋年龄中位数

  3. AveRooms - 每户平均房间数

  4. AveBedrms - 每户平均卧室数

  5. population - 区块组人口

  6. AveOccup - 平均家庭成员人数

  7. Latitude - 块组纬度

  8. Longitude - 块组经度

import sklearnimport shap# a classic housing price dataset
X, y = shap.datasets.california(n_points=1000)X100 = shap.utils.sample(X, 100)  # 100 instances for use as the background distribution# a simple linear model
model = sklearn.linear_model.LinearRegression()
model.fit(X, y
 检查模型系数

理解线性模型的最常见方法是检查为每个特征学习的系数。这些系数告诉我们,当我们更改每个输入特征时,模型输出的变化程度:

print("Model coefficients:\n")
for i in range(X.shape[1]):print(X.columns[i], "=", model.coef_[i].round(5))

虽然系数非常适合告诉我们当我们更改输入特征的值时会发生什么,但它们本身并不是衡量特征整体重要性的好方法。这是因为每个系数的值取决于输入要素的比例。例如,如果我们以分钟而不是年为单位来测量房屋的年龄,则 HouseAge 特征的系数将变为 0.0115 / (365∗24∗60) = 2.18e-8。显然是自房子以来的年数 构建并不比分钟数更重要,但它的系数值要大得多。这意味着系数的大小不一定是线性模型中特征重要性的良好度量。

使用部分依赖图获得更完整的图片

要了解特征在模型中的重要性,必须了解更改该特征如何影响模型的输出,以及该特征值的分布。为了可视化线性模型,我们可以构建一个经典的部分依赖图,并将特征值的分布显示为 x 轴上的直方图:

shap.partial_dependence_plot("MedInc",model.predict,X100,ice=False,model_expected_value=True,feature_expected_value=True,
)

 上图中的灰色水平线表示模型应用于加州住房数据集时的预期值。垂直灰线表示收入中位数要素的平均值。请注意,蓝色部分依赖性图线(当我们将收入中位数特征固定为给定值时,模型输出的平均值)始终穿过两条灰色期望值线的交点。我们可以将这个交点视为“中心” 关于数据分布的部分依赖图。当我们接下来转向Shapley值时,这种集中的影响将变得清晰。

从部分依赖图中读取 SHAP 值

Shapley基于价值的机器学习模型解释背后的核心思想是使用合作博弈论的公平分配结果,在其输入特征中分配模型输出的功劳。为了将博弈论与机器学习模型联系起来,既要将模型的输入特征与游戏中的玩家进行匹配,又要将模型函数与游戏规则进行匹配。由于在博弈论中,玩家可以加入或不加入游戏,因此我们需要一种方法 用于“连接”或“不连接”模型的特征。定义特征“连接”模型意味着什么的最常见方法是,当我们知道该特征的值时,该特征已“加入模型”,而当我们不知道该特征的值时,它尚未加入模型。为了评估现有模型,当模型中只有一部分特征时,我们使用条件期望值公式将其他特征积分出来。这种配方可以采取两个 形式:

\[E[f(X) \mid X_S = x_S]\]

\[E[f(X) \mid do(X_S = x_S)]\]

在第一种形式中,我们知道 S 中特征的值,因为我们观察它们。在第二种形式中,我们知道 S 中特征的值,因为我们设置了它们。一般来说,第二种形式通常是可取的,因为它告诉我们如果我们要干预和改变其输入,模型将如何表现,也因为它更容易计算。在本教程中,我们将完全专注于第二种公式。我们还将使用更具体的术语“SHAP 值”来指代 应用于机器学习模型的条件期望函数的 Shapley 值。

SHAP 值的计算可能非常复杂(它们通常是 NP 困难的),但线性模型非常简单,我们可以直接从部分依赖图中读取 SHAP 值。当我们解释预测时,特定特征的 SHAP 值只是预期模型输出与特征值处的部分依赖图之间的差值:

# compute the SHAP values for the linear model
explainer = shap.Explainer(model.predict, X100)
shap_values = explainer(X)# make a standard partial dependence plot
sample_ind = 20
shap.partial_dependence_plot("MedInc",model.predict,X100,model_expected_value=True,feature_expected_value=True,ice=False,shap_values=shap_values[sample_ind : sample_ind + 1, :],
)

经典部分依赖图和 SHAP 值之间的紧密对应关系意味着,如果我们在整个数据集中绘制特定特征的 SHAP 值,我们将精确地跟踪出该特征的部分依赖图的均值中心版本:

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

Shapley值的累加性

Shapley 值的基本属性之一是,它们总是汇总所有玩家在场时的游戏结果与没有玩家在场时的游戏结果之间的差异。对于机器学习模型,这意味着所有输入特征的 SHAP 值将始终相加为基线(预期)模型输出与所解释预测的当前模型输出之间的差值。最简单的方法是通过瀑布图,从我们的 背景 对房价的先验预期 ,然后一次添加一个特征,直到我们达到当前模型输出:

# the waterfall_plot shows how we get from shap_values.base_values to model.predict(X)[sample_ind]
shap.plots.waterfall(shap_values[sample_ind], max_display=14)

解释加性回归模型 

线性模型的偏相关图与 SHAP 值具有如此紧密的联系的原因是,模型中的每个特征都独立于其他所有特征进行处理(效应只是相加而已)。我们可以保持这种累加性,同时放宽直线的线性要求。这导致了众所周知的一类广义加法模型 (GAM)。虽然有很多方法可以训练这些类型的模型(例如将 XGBoost 模型设置为 depth-1),但我们将 使用专门为此设计的 InterpretML 可解释的提升机器。

# fit a GAM model to the data
import interpret.glassboxmodel_ebm = interpret.glassbox.ExplainableBoostingRegressor(interactions=0)
model_ebm.fit(X, y)# explain the GAM model with SHAP
explainer_ebm = shap.Explainer(model_ebm.predict, X100)
shap_values_ebm = explainer_ebm(X)# make a standard partial dependence plot with a single SHAP value overlaid
fig, ax = shap.partial_dependence_plot("MedInc",model_ebm.predict,X100,model_expected_value=True,feature_expected_value=True,show=False,ice=False,shap_values=shap_values_ebm[sample_ind : sample_ind + 1, :],
)

shap.plots.scatter(shap_values_ebm[:, "MedInc"])

# the waterfall_plot shows how we get from explainer.expected_value to model.predict(X)[sample_ind]
shap.plots.waterfall(shap_values_ebm[sample_ind])

 

# the waterfall_plot shows how we get from explainer.expected_value to model.predict(X)[sample_ind]
shap.plots.beeswarm(shap_values_ebm)

 解释非加性提升树模型

# train XGBoost model
import xgboostmodel_xgb = xgboost.XGBRegressor(n_estimators=100, max_depth=2).fit(X, y)# explain the GAM model with SHAP
explainer_xgb = shap.Explainer(model_xgb, X100)
shap_values_xgb = explainer_xgb(X)# make a standard partial dependence plot with a single SHAP value overlaid
fig, ax = shap.partial_dependence_plot("MedInc",model_xgb.predict,X100,model_expected_value=True,feature_expected_value=True,show=False,ice=False,shap_values=shap_values_xgb[sample_ind : sample_ind + 1, :],
)

shap.plots.scatter(shap_values_xgb[:, "MedInc"])

shap.plots.scatter(shap_values_xgb[:, "MedInc"], color=shap_values)

 解释线性逻辑回归模型

# a classic adult census dataset price dataset
X_adult, y_adult = shap.datasets.adult()# a simple linear logistic model
model_adult = sklearn.linear_model.LogisticRegression(max_iter=10000)
model_adult.fit(X_adult, y_adult)def model_adult_proba(x):return model_adult.predict_proba(x)[:, 1]def model_adult_log_odds(x):p = model_adult.predict_log_proba(x)return p[:, 1] - p[:, 0]

 请注意,解释线性逻辑回归模型的概率在输入中不是线性的。

# make a standard partial dependence plot
sample_ind = 18
fig, ax = shap.partial_dependence_plot("Capital Gain",model_adult_proba,X_adult,model_expected_value=True,feature_expected_value=True,show=False,ice=False,
)

 如果我们使用 SHAP 来解释线性逻辑回归模型的概率,我们会看到很强的交互效应。这是因为线性逻辑回归模型在概率空间中不是累加的。

# compute the SHAP values for the linear model
background_adult = shap.maskers.Independent(X_adult, max_samples=100)
explainer = shap.Explainer(model_adult_proba, background_adult)
shap_values_adult = explainer(X_adult[:1000])
shap.plots.scatter(shap_values_adult[:, "Age"])

如果我们解释模型的对数赔率输出,我们会看到模型输入和模型输出之间存在完美的线性关系。重要的是要记住要解释的模型的单位是什么,解释不同的模型输出可能会导致模型行为的非常不同的观点。

# compute the SHAP values for the linear model
explainer_log_odds = shap.Explainer(model_adult_log_odds, background_adult)
shap_values_adult_log_odds = explainer_log_odds(X_adult[:1000])
shap.plots.scatter(shap_values_adult_log_odds[:, "Age"])

# make a standard partial dependence plot
sample_ind = 18
fig, ax = shap.partial_dependence_plot("Age",model_adult_log_odds,X_adult,model_expected_value=True,feature_expected_value=True,show=False,ice=False,
)

 解释非加性提升树逻辑回归模型

# train XGBoost model
model = xgboost.XGBClassifier(n_estimators=100, max_depth=2).fit(X_adult, y_adult * 1, eval_metric="logloss"
)# compute SHAP values
explainer = shap.Explainer(model, background_adult)
shap_values = explainer(X_adult)# set a display version of the data to use for plotting (has string values)
shap_values.display_data = shap.datasets.adult(display=True)[0].values

默认情况下,SHAP 条形图将采用数据集所有实例(行)上每个要素的平均绝对值。

shap.plots.bar(shap_values)

但平均绝对值并不是创建特征重要性的全局度量的唯一方法,我们可以使用任意数量的变换。在这里,我们将展示如何使用最大绝对值来突出资本收益和资本损失特征,因为它们具有不常见但高幅度的影响。

shap.plots.bar(shap_values.abs.max(0))

如果我们愿意处理更复杂的问题,我们可以使用蜂群图来总结每个特征的 SHAP 值的整个分布。

shap.plots.beeswarm(shap_values)

 

通过取绝对值并使用纯色,我们可以在条形图和完整蜂群图的复杂性之间达成折衷。请注意,上面的条形图只是下面蜂群图中显示的值的汇总统计数据。

shap.plots.beeswarm(shap_values.abs, color="shap_red")

shap.plots.heatmap(shap_values[:1000])

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

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

shap.plots.scatter(shap_values[:, "Age"], color=shap_values[:, "Capital Gain"])

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

处理相关特征

clustering = shap.utils.hclust(X_adult, y_adult)
shap.plots.bar(shap_values, clustering=clustering)

shap.plots.bar(shap_values, clustering=clustering, clustering_cutoff=0.8)

shap.plots.bar(shap_values, clustering=clustering, clustering_cutoff=1.8)

解释一个 transformers NLP 模型

这演示了如何将 SHAP 应用于具有高度结构化输入的复杂模型类型。

import datasets
import numpy as np
import scipy as sp
import torch
import transformers# load a BERT sentiment analysis model
tokenizer = transformers.DistilBertTokenizerFast.from_pretrained("distilbert-base-uncased"
)
model = transformers.DistilBertForSequenceClassification.from_pretrained("distilbert-base-uncased-finetuned-sst-2-english"
).cuda()# define a prediction function
def f(x):tv = torch.tensor([tokenizer.encode(v, padding="max_length", max_length=500, truncation=True)for v in x]).cuda()outputs = model(tv)[0].detach().cpu().numpy()scores = (np.exp(outputs).T / np.exp(outputs).sum(-1)).Tval = sp.special.logit(scores[:, 1])  # use one vs rest logit unitsreturn val# build an explainer using a token masker
explainer = shap.Explainer(f, tokenizer)# explain the model's predictions on IMDB reviews
imdb_train = datasets.load_dataset("imdb")["train"]
shap_values = explainer(imdb_train[:10], fixed_context=1, batch_size=2)
# plot a sentence's explanation
shap.plots.text(shap_values[2])

shap.plots.bar(shap_values.abs.mean(0))

shap.plots.bar(shap_values.abs.sum(0))

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/161768.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

实现el-input-number数字框带单位

实现的效果展示&#xff0c;可以是前缀单位&#xff0c;也可以是后缀单位。实现的思路就是动态修改伪元素 ::before 和 ::after 的 content值 实现二次封装数字框的代码如下&#xff1a; <template><el-input-numberref"inputNumber"v-model"inputVal…

opencv-直方图

直方图是一种对图像亮度分布的统计表示&#xff0c;它显示了图像中每个灰度级别的像素数量。在OpenCV中&#xff0c;你可以使用cv2.calcHist() 函数计算直方图。 以下是一个简单的示例&#xff0c;演示如何计算和绘制图像的直方图&#xff1a; import cv2 import numpy as np …

【C++容器】优先级队列 仿函数 反向迭代器

优先级队列&#xff0c;仿函数&#xff0c;反向迭代器 优先级队列认识优先级队列模拟实现优先级队列 浅谈仿函数仿函数的大致了解仿函数的实现 反向迭代器什么是反向迭代器&#xff1f;反向迭代器的实现 结语 优先级队列 认识优先级队列 优先级队列&#xff08;priority_queue…

低成本打造便携式无线网络攻防学习环境

1.摘要 一直以来, 无线网络安全问题与大众的个人隐私息息相关, 例如: 为了节省流量, 连接到一个看似安全的免费WiFi, 在使用过程中泄露自己的各类密码信息甚至银行卡账号密码信息。随着家用智能电器的普及, 家中的各类智能设备连入家里的无线网络, 却突然失灵, 甚至无法正常连…

@Scheduled注解 定时任务讲解

用于在Java Spring框架中定时执行特定任务的注解 Scheduled&#xff0c;它能够指定方法在特定时间间隔或特定时间点执行。默认参数是cron&#xff0c;cron参数被用来定义一个Cron表达式&#xff0c;它代表了任务执行的时间规则 参数如下 Cron 这是是一种时间表达式&#xff…

【应用程序启动过程-三种加载控制器的方式-上午内容复习 Objective-C语言】

一、我们先来回忆一下,上午所有内容 1.首先呢,我们先说的是这个“应用程序启动过程”, 应用程序启动过程里面,有三方面内容 1)UIApplication对象介绍 2)AppDelegate对象介绍 3)应用程序启动过程 现在不知道大家对这个应用程序启动过程有印象吗, 2.首先,这个UIAp…

MySQL数据库时间计算的用法

今天给大家分享如何通过MySQL内置函数实现时间的转换和计算&#xff0c;在工作当中&#xff0c;测试人员经常需要查询数据库表的日期时间&#xff0c;但发现开发人员存入数据库表的形式都是时间戳形式&#xff0c;不利于测试人员查看&#xff0c;测试人员只能利用工具对时间戳进…

【 顺序表经典算法—移除元素和合并两个有序数组】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 经典算法OJ题1&#xff1a; 移除元素 解法一、逐个判断 解法二、双指针覆盖 经典算法OJ题2&#xff1a; 合并两个有序数组 OJ题分为两个类型&#xff1a; 总结 前言…

MAX/MSP SDK学习07:list传递

实现自定义Obejct&#xff0c;要求将传入的一组数据100后传出。 #include "ext.h" #include "ext_obex.h" typedef struct _listTrans {t_object ob;void* outLet;t_atom* fArr;long listNum;} t_listTrans;void* listTrans_new(t_symbol* s, long arg…

Bug等级划分

Bug是指在程序或系统中存在的错误、缺陷或异常&#xff0c;是由于编码错误、设计问题、逻辑错误或其他因素导致的。 常见的Bug分类方法 功能性Bug与软件的功能有关&#xff0c;软件无法正常工作、功能与需求不符或功能执行不正确。 用户界面Bug与软件的用户界面有关&#xff…

Unity中Shader双向反射分布函数BRDF

文章目录 前言一、渲染方程二、什么是BxDF1、BSSRDF2、BRDF3、BTDF4、BSDF 三、迪士尼原则的BRDF四、迪士尼原则的BRDF的参数五、在Unity中看一下默认Shader的这些参数六、在这里记录一下使用 Blender 和 SubstancePainter 的流程1、在Blender中导出模型为 .obj 格式2、在Subst…

Go 实现网络代理

使用 Go 语言开发网络代理服务可以通过以下步骤完成。这里&#xff0c;我们将使用 golang.org/x/net/proxy 包来创建一个简单的 SOCKS5 代理服务作为示例。 步骤 1. 安装 golang.org/x/net/proxy 包 使用以下命令安装 golang.org/x/net 包&#xff0c;该包包含 proxy 子包&am…

天软特色因子看板 (2023.11 第12期)

该因子看板跟踪天软特色因子A05006(近一月单笔流入流出金额之比(%)&#xff0c;该因子为近一个月单笔流入流出金额之比(%)均值因子&#xff0c;用以刻画在 市场日内分时成交中流入、流出成交金额的差异性特点&#xff0c;发掘市场主力资金的作用机制。 今日为该因子跟踪第12期&…

Windows平台Unity下实现camera场景推送RTMP|轻量级RTSP服务|实时录像

技术背景 我们在对接Unity平台camera场景采集的时候&#xff0c;除了常规的RTMP推送、录像外&#xff0c;还有一些开发者&#xff0c;需要能实现轻量级RTSP服务&#xff0c;对外提供个拉流的RTSP URL。 目前我们在Windows平台Unity下数据源可采集到以下部分&#xff1a; 采集…

@PostConstruct虽好,请勿乱用

1.问题说明 在日常的业务开发中&#xff0c;有时会利用PostConstruct在容器启动时执行一些任务。例如&#xff1a; PostConstruct public void init(){System.out.println("service 初始化..............."); }一般情况这没什么问题&#xff0c;但最近一个同事在做…

ui5使用echart

相关的代码已经发布到github上。 展示下相关的实现功能 1、柱状图-1 2、柱状图-2 3.折线图 4.饼状图 如何使用&#xff1a; 使用git clone项目到本地 git clone https://github.com/linhuang0405/com.joker.Zechart找到index.html。在vscode里右键选择Open with Live Serve…

BLE通用广播包

文章目录 1、蓝牙广播数据格式2、扫描响应数据 1、蓝牙广播数据格式 蓝牙广播包的最大长度是37个字节&#xff0c;其中设备地址占用了6个字节&#xff0c;只有31个字节是可用的。这31个可用的字节又按照一定的格式来组织&#xff0c;被分割为n个AD Structure。如下图所示&…

VS Code 如何搭建C/C++环境

目录 一、VS Code是什么&#xff1f; 二、VS Code下载和安装 2.1下载 2.2安装 2.3环境介绍 三、Vs Code配置C/C环境 3.1下载和配置MinGW-w64编译器套件 3.1.1下载 3.1.2配置 一、VS Code是什么&#xff1f; 跨平台&#xff0c;免费且开源的现代轻量级代码编辑器 Vis…

【MATLAB源码-第85期】基于farrow结构的滤波器仿真,截止频率等参数可调。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 Farrow结构是一种用于实现可变数字滤波器的方法&#xff0c;尤其适用于数字信号处理中的采样率转换和时变滤波。它通过多项式近似来实现对滤波器系数的平滑变化&#xff0c;使得滤波器具有可变的群延时或其他参数。 Farrow结…

mysql中数据是如何被用B+树查询到的

innoDB是按照页为单位读写的 那页中有很多行数据&#xff0c;是怎么执行查询的呢&#xff0c;首先我们肯定&#xff0c;是以单向列表形式存储的&#xff0c;提高了增删的效率&#xff0c;但是查询效率低。所以实际上对页中的行数据进行了优化&#xff0c;能以二分的方式进行查…