chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 13:22:52 +08:00
commit 9d4c7d16ba
528 changed files with 740585 additions and 0 deletions
File diff suppressed because one or more lines are too long
@@ -0,0 +1,120 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Math behind LinearExplainer with correlation feature perturbation\n",
"\n",
"When we use `LinearExplainer(model, prior, feature_perturbation=\"correlation_dependent\")` we do not use $E[f(x) \\mid do(X_S = x_S)]$ to measure the impact of a set $S$ of features, but rather use $E[f(x) \\mid X_S = x_s]$ under the assumption that the random variable $X$ (representing the input features) follows a multivariate guassian distribution. To compute SHAP values this way we need to compute conditional expectations under the multivariate guassian distribution for all subset of features. This would be a lot of matrix match for an exponential number of terms, and it hence intractable for models with more than just a few features.\n",
"\n",
"This document briefly outlines the math we have used to precompute all of the required linear algebra using a sampling procedure that can be done just once, and then applied to as many samples as we like. This drastically speed up the computation compared to a brute force approach. Note that all these calculations depend on the fact that we are explaining a linear model $f(x) = \\beta x$."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The permutation definition of SHAP values in the interventional form used by most explainers is\n",
"\n",
"$$\n",
"\\phi_i = \\frac{1}{M!} \\sum_R E[f(X) \\mid do(X_{S_i^R \\cup i} = x_{S_i^R \\cup i})] - E[f(X) \\mid do(X_{S_i^R} = x_{S_i^R})]\n",
"$$\n",
"\n",
"but here we will use the non-interventional conditional expectation form (where we have simplified the notation by dropping the explicit reference to the random variable $X$).\n",
"\n",
"$$\n",
"\\phi_i = \\frac{1}{M!} \\sum_R E[f(x) \\mid x_{S_i^R \\cup i}] - E[f(x) \\mid x_{S_i^R}]\n",
"$$\n",
"\n",
"where $f(x) = \\beta x + b$ with $\\beta$ a row vector and $b$ a scalar."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If we replace f(x) with the linear function definition we get:\n",
"\n",
"\\begin{align}\n",
"\\phi_i = \\frac{1}{M!} \\sum_R E[\\beta x + b \\mid x_{S_i^R \\cup i}] - E[\\beta x + b \\mid x_{S_i^R}] \\\\\n",
" = \\beta \\frac{1}{M!} \\sum_R E[x \\mid x_{S_i^R \\cup i}] - E[x \\mid x_{S_i^R}]\n",
"\\end{align}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Assume the inputs $x$ follow a multivariate normal distribution with mean $\\mu$ and covariance $\\Sigma$. Denote the projection matrix that selects a set $S$ as $P_S$, then we get:\n",
"\n",
"\\begin{align}\n",
"E[x \\mid x_S] = [P_{\\bar S} \\mu + P_{\\bar S} \\Sigma P_S^T (P_S \\Sigma P_S^T)^{-1} ( P_S x - P_S \\mu)] P_{\\bar S} + x P_S^T P_S \\\\\n",
"= [P_{\\bar S} \\mu + P_{\\bar S} \\Sigma P_S^T (P_S \\Sigma P_S^T)^{-1} P_S (x - \\mu)] P_{\\bar S} + x P_S^T P_S \\\\\n",
"= [\\mu + \\Sigma P_S^T (P_S \\Sigma P_S^T)^{-1} P_S (x - \\mu)] P_{\\bar S}^T P_{\\bar S} + x P_S^T P_S \\\\\n",
"= P_{\\bar S}^T P_{\\bar S} [\\mu + \\Sigma P_S^T (P_S \\Sigma P_S^T)^{-1} P_S (x - \\mu)] + P_S^T P_S x \\\\\n",
"= P_{\\bar S}^T P_{\\bar S} \\mu + P_{\\bar S}^T P_{\\bar S} \\Sigma P_S^T (P_S \\Sigma P_S^T)^{-1} P_S x - P_{\\bar S}^T P_{\\bar S} \\Sigma P_S^T (P_S \\Sigma P_S^T)^{-1} P_S \\mu + P_S^T P_S x \\\\\n",
"= [P_{\\bar S}^T P_{\\bar S} - P_{\\bar S}^T P_{\\bar S} \\Sigma P_S^T (P_S \\Sigma P_S^T)^{-1} P_S] \\mu + [P_S^T P_S + P_{\\bar S}^T P_{\\bar S} \\Sigma P_S^T (P_S \\Sigma P_S^T)^{-1} P_S] x\n",
"\\end{align}\n",
"\n",
"if we let $R_S = P_{\\bar S}^T P_{\\bar S} \\Sigma P_S^T (P_S \\Sigma P_S^T)^{-1} P_S$ and $Q_S = P_S^T P_S$ then we can write\n",
"\n",
"\\begin{align}\n",
"E[x \\mid x_S] = [Q_{\\bar S} - R_S] \\mu + [Q_S + R_S] x\n",
"\\end{align}\n",
"\n",
"or\n",
"\n",
"\\begin{align}\n",
"E[x \\mid x_{S_i^R \\cup i}] = [Q_{\\bar{S_i^R \\cup i}} - R_{S_i^R \\cup i}] \\mu + [Q_{S_i^R \\cup i} + R_{S_i^R \\cup i}] x\n",
"\\end{align}\n",
"\n",
"leading to the Shapley equation of\n",
"\n",
"\\begin{align}\n",
"\\phi_i = \\beta \\frac{1}{M!} \\sum_R [Q_{\\bar{S_i^R \\cup i}} - R_{S_i^R \\cup i}] \\mu + [Q_{S_i^R \\cup i} + R_{S_i^R \\cup i}] x - [Q_{\\bar{S_i^R}} - R_{S_i^R}] \\mu - [Q_{S_i^R} + R_{S_i^R}] x \\\\\n",
"= \\beta \\frac{1}{M!} \\sum_R ([Q_{\\bar{S_i^R \\cup i}} - R_{S_i^R \\cup i}] - [Q_{\\bar{S_i^R}} - R_{S_i^R}]) \\mu + ([Q_{S_i^R \\cup i} + R_{S_i^R \\cup i}] - [Q_{S_i^R} + R_{S_i^R}]) x \\\\\n",
"= \\beta \\left [ \\frac{1}{M!} \\sum_R ([Q_{\\bar{S_i^R \\cup i}} - R_{S_i^R \\cup i}] - [Q_{\\bar{S_i^R}} - R_{S_i^R}]) \\right ] \\mu + \\beta \\left [ \\frac{1}{M!} \\sum_R ([Q_{S_i^R \\cup i} + R_{S_i^R \\cup i}] - [Q_{S_i^R} + R_{S_i^R}]) \\right ] x\n",
"\\end{align}\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"$$\n",
"\\phi = \\beta T x\n",
"$$"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This means that we can precompute the transform matrix $T$ by drawing random permutations $R$ many times and averaging our results. Once we have computed $T$ we can explain any number of samples (or models for that matter) by just using matrix multiplication."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.3"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
File diff suppressed because one or more lines are too long