714 lines
23 KiB
Python
714 lines
23 KiB
Python
from __future__ import annotations
|
|
|
|
import os
|
|
from typing import TYPE_CHECKING, Final, Literal, overload
|
|
from urllib.request import urlretrieve
|
|
|
|
import numpy as np
|
|
import pandas as pd
|
|
import sklearn.datasets
|
|
|
|
import shap
|
|
|
|
if TYPE_CHECKING: # pragma: no cover
|
|
import scipy.sparse as ssp
|
|
|
|
github_data_url: Final[str] = "https://github.com/shap/shap/raw/master/data/"
|
|
|
|
|
|
def imagenet50(resolution: int = 224, n_points: int | None = None) -> tuple[np.ndarray, np.ndarray]:
|
|
"""Return a set of 50 images representative of ImageNet images.
|
|
|
|
Parameters
|
|
----------
|
|
resolution : int
|
|
The resolution of the images. At present, the only supported value is 224.
|
|
n_points : int, optional
|
|
Number of data points to sample. If None, the entire dataset is used.
|
|
|
|
Returns
|
|
-------
|
|
X : np.ndarray
|
|
Represents images from ImageNet of a certain resolution.
|
|
y : np.ndarray
|
|
The target variables, that is, the ImageNet classes.
|
|
|
|
Notes
|
|
-----
|
|
This dataset was collected by randomly finding a working ImageNet link and then pasting the
|
|
original ImageNet image into Google image search restricted to images licensed for reuse. A
|
|
similar image (now with rights to reuse) was downloaded as a rough replacement for the original
|
|
ImageNet image. The point is to have a random sample of ImageNet for use as a background
|
|
distribution for explaining models trained on ImageNet data.
|
|
|
|
Note that because the images are only rough replacements, the labels might no longer be correct.
|
|
|
|
Examples
|
|
--------
|
|
To get the processed images and labels::
|
|
|
|
images, labels = shap.datasets.imagenet50()
|
|
|
|
"""
|
|
prefix = github_data_url + "imagenet50_"
|
|
X: np.ndarray = np.load(cache(f"{prefix}{resolution}x{resolution}.npy")).astype(np.float32)
|
|
y: np.ndarray = np.loadtxt(cache(f"{prefix}labels.csv"))
|
|
|
|
if n_points is not None:
|
|
X = shap.utils.sample(X, n_points, random_state=0)
|
|
y = shap.utils.sample(y, n_points, random_state=0)
|
|
|
|
return X, y
|
|
|
|
|
|
def california(n_points: int | None = None) -> tuple[pd.DataFrame, np.ndarray]:
|
|
"""Return the California housing data in a tabular format.
|
|
|
|
Used in predictive regression tasks.
|
|
|
|
Parameters
|
|
----------
|
|
n_points : int, optional
|
|
Number of data points to sample. If provided, randomly samples the specified number of points.
|
|
|
|
Returns
|
|
-------
|
|
X : pd.DataFrame
|
|
The feature data.
|
|
y : np.ndarray
|
|
The target variable.
|
|
|
|
Notes
|
|
-----
|
|
The returned feature matrix ``X`` includes the following features:
|
|
|
|
- ``MedInc`` (float): Median income in block
|
|
- ``HouseAge`` (float): Median house age in block
|
|
- ``AveRooms`` (float): Average rooms in dwelling
|
|
- ``AveBedrms`` (float): Average bedrooms in dwelling
|
|
- ``Population`` (float): Block population
|
|
- ``AveOccup`` (float): Average house occupancy
|
|
- ``Latitude`` (float): House block latitude
|
|
- ``Longitude`` (float): House block longitude
|
|
|
|
The target column represents the median house value for California districts.
|
|
|
|
References
|
|
----------
|
|
California housing dataset: :external+scikit-learn:func:`sklearn.datasets.fetch_california_housing`
|
|
|
|
Examples
|
|
--------
|
|
To get the processed data and target labels::
|
|
|
|
data, target = shap.datasets.california()
|
|
|
|
"""
|
|
d = sklearn.datasets.fetch_california_housing()
|
|
df = pd.DataFrame(data=d.data, columns=d.feature_names)
|
|
target: np.ndarray = d.target
|
|
|
|
if n_points is not None:
|
|
df = shap.utils.sample(df, n_points, random_state=0)
|
|
target = shap.utils.sample(target, n_points, random_state=0)
|
|
|
|
return df, target
|
|
|
|
|
|
def linnerud(n_points: int | None = None) -> tuple[pd.DataFrame, pd.DataFrame]:
|
|
"""Return the Linnerud dataset in a convenient package for multi-target regression.
|
|
|
|
Parameters
|
|
----------
|
|
n_points : int, optional
|
|
Number of data points to sample. If provided, randomly samples the specified number
|
|
of points.
|
|
|
|
Returns
|
|
-------
|
|
X : pd.DataFrame
|
|
The feature data.
|
|
y : pd.DataFrame
|
|
The multiclass target variables.
|
|
|
|
Notes
|
|
-----
|
|
- The Linnerud dataset contains physiological and exercise data for 20 individuals.
|
|
- The feature matrix ``X`` includes three exercise variables: ``Chins``, ``Situps``, ``Jumps``.
|
|
- The target variables ``y`` include three physiological measurements: ``Weight``, ``Waist``, ``Pulse``.
|
|
|
|
More details: :external+scikit-learn:func:`sklearn.datasets.load_linnerud`
|
|
|
|
Examples
|
|
--------
|
|
To get the feature matrix and target variables::
|
|
|
|
features, targets = shap.datasets.linnerud()
|
|
|
|
To get a subset of the data::
|
|
|
|
subset_features, subset_targets = shap.datasets.linnerud(n_points=100)
|
|
|
|
"""
|
|
d = sklearn.datasets.load_linnerud()
|
|
X = pd.DataFrame(d.data, columns=d.feature_names)
|
|
y = pd.DataFrame(d.target, columns=d.target_names)
|
|
|
|
if n_points is not None:
|
|
X = shap.utils.sample(X, n_points, random_state=0)
|
|
y = shap.utils.sample(y, n_points, random_state=0)
|
|
|
|
return X, y
|
|
|
|
|
|
def imdb(n_points: int | None = None) -> tuple[list[str], np.ndarray]:
|
|
"""Return the classic IMDB sentiment analysis training data in a nice package.
|
|
|
|
Used in binary text classification tasks.
|
|
|
|
Parameters
|
|
----------
|
|
n_points : int, optional
|
|
Number of data points to sample. If provided, randomly samples the specified number of points.
|
|
|
|
Returns
|
|
-------
|
|
X : list of strings
|
|
Text data, where each string is a movie review.
|
|
y : np.ndarray
|
|
The target variable. Contains booleans, where True indicates a positive sentiment and False
|
|
indicates a negative sentiment.
|
|
|
|
Notes
|
|
-----
|
|
Full data is at: http://ai.stanford.edu/~amaas/data/sentiment/aclImdb_v1.tar.gz
|
|
|
|
Paper to cite when using the data is: http://www.aclweb.org/anthology/P11-1015
|
|
|
|
Examples
|
|
--------
|
|
To get the processed text data and labels::
|
|
|
|
text_data, labels = shap.datasets.imdb()
|
|
|
|
"""
|
|
with open(cache(github_data_url + "imdb_train.txt"), encoding="utf-8") as f:
|
|
data = f.readlines()
|
|
y = np.ones(25000, dtype=bool)
|
|
y[:12500] = 0
|
|
|
|
if n_points is not None:
|
|
data = shap.utils.sample(data, n_points, random_state=0)
|
|
y = shap.utils.sample(y, n_points, random_state=0)
|
|
|
|
return data, y
|
|
|
|
|
|
def communitiesandcrime(n_points: int | None = None) -> tuple[pd.DataFrame, np.ndarray]:
|
|
"""Predict the total number of violent crimes per 100K population.
|
|
|
|
This dataset is from the classic UCI Machine Learning repository:
|
|
https://archive.ics.uci.edu/ml/datasets/Communities+and+Crime+Unnormalized
|
|
|
|
Used in predictive regression tasks.
|
|
|
|
Parameters
|
|
----------
|
|
n_points : int, optional
|
|
Number of data points to sample. If provided, randomly samples the specified number of points.
|
|
|
|
Returns
|
|
-------
|
|
X : pd.DataFrame
|
|
The feature data.
|
|
y : np.ndarray
|
|
The target variable.
|
|
|
|
Examples
|
|
--------
|
|
To get the processed data and target labels::
|
|
|
|
data, target = shap.datasets.communitiesandcrime()
|
|
|
|
"""
|
|
raw_data = pd.read_csv(cache(github_data_url + "CommViolPredUnnormalizedData.txt"), na_values="?")
|
|
|
|
# find the indices where the total violent crimes are known
|
|
valid_inds = np.where(np.invert(np.isnan(raw_data.iloc[:, -2])))[0]
|
|
|
|
if n_points is not None:
|
|
valid_inds = shap.utils.sample(valid_inds, n_points, random_state=0)
|
|
|
|
y = np.array(raw_data.iloc[valid_inds, -2], dtype=float)
|
|
|
|
# extract the predictive features and remove columns with missing values
|
|
X = raw_data.iloc[valid_inds, 5:-18]
|
|
valid_cols = np.where(np.isnan(X.values).sum(0) == 0)[0]
|
|
X = X.iloc[:, valid_cols]
|
|
|
|
return X, y
|
|
|
|
|
|
def diabetes(n_points: int | None = None) -> tuple[pd.DataFrame, np.ndarray]:
|
|
"""Return the diabetes data in a nice package.
|
|
|
|
Used in predictive regression tasks.
|
|
|
|
Parameters
|
|
----------
|
|
n_points : int, optional
|
|
Number of data points to sample. If provided, randomly samples the specified number of points.
|
|
|
|
Returns
|
|
-------
|
|
X : pd.DataFrame
|
|
The feature data.
|
|
y : np.ndarray
|
|
The target variable.
|
|
|
|
Notes
|
|
-----
|
|
Feature Columns in ``X``:
|
|
|
|
- ``age`` (float): Age in years
|
|
- ``sex`` (float): Sex
|
|
- ``bmi`` (float): Body mass index
|
|
- ``bp`` (float): Average blood pressure
|
|
- ``s1`` (float): Total serum cholesterol
|
|
- ``s2`` (float): Low-density lipoproteins (LDL cholesterol)
|
|
- ``s3`` (float): High-density lipoproteins (HDL cholesterol)
|
|
- ``s4`` (float): Total cholesterol / HDL cholesterol ratio
|
|
- ``s5`` (float): Log of serum triglycerides level
|
|
- ``s6`` (float): Blood sugar level
|
|
|
|
Target ``y``:
|
|
|
|
- Progression of diabetes one year after baseline (float)
|
|
|
|
The diabetes dataset is a subset of the larger diabetes dataset from scikit-learn.
|
|
More details: :external+scikit-learn:func:`sklearn.datasets.load_diabetes`
|
|
|
|
Examples
|
|
--------
|
|
To get the processed data and target labels::
|
|
|
|
data, target = shap.datasets.diabetes()
|
|
|
|
"""
|
|
d = sklearn.datasets.load_diabetes()
|
|
df = pd.DataFrame(data=d.data, columns=d.feature_names)
|
|
target = d.target
|
|
|
|
if n_points is not None:
|
|
df = shap.utils.sample(df, n_points, random_state=0)
|
|
target = shap.utils.sample(target, n_points, random_state=0)
|
|
|
|
return df, target
|
|
|
|
|
|
@overload
|
|
def iris(display: Literal[False] = ..., n_points: int | None = ...) -> tuple[pd.DataFrame, np.ndarray]: ...
|
|
@overload
|
|
def iris(display: Literal[True] = ..., n_points: int | None = ...) -> tuple[pd.DataFrame, list[str]]: ...
|
|
|
|
|
|
def iris(display: bool = False, n_points: int | None = None) -> tuple[pd.DataFrame, np.ndarray | list[str]]:
|
|
"""Return the classic Iris dataset in a convenient package.
|
|
|
|
Parameters
|
|
----------
|
|
display : bool
|
|
If True, return the original feature matrix along with class labels (as strings). Default is False.
|
|
n_points : int, optional
|
|
Number of data points to sample. If provided, randomly samples the specified number of points.
|
|
|
|
Returns
|
|
-------
|
|
X : pd.DataFrame
|
|
The feature matrix.
|
|
y : np.ndarray or a list of strings
|
|
If ``display`` is False, a numpy array representing the class labels encoded as integers is returned.
|
|
If ``display`` is True, then a list of class labels is returned.
|
|
|
|
Notes
|
|
-----
|
|
- The dataset includes measurements of sepal length, sepal width, petal length, and petal width for three
|
|
species of iris flowers.
|
|
- Class labels are encoded as integers (0, 1, 2) representing the species (setosa, versicolor, virginica).
|
|
- If ``display`` is True, class labels are returned as strings.
|
|
|
|
Examples
|
|
--------
|
|
To get the feature matrix and class labels::
|
|
|
|
features, labels = shap.datasets.iris()
|
|
|
|
To get the feature matrix and class labels as strings::
|
|
|
|
features, class_labels = shap.datasets.iris(display=True)
|
|
|
|
"""
|
|
d = sklearn.datasets.load_iris()
|
|
df = pd.DataFrame(data=d.data, columns=d.feature_names)
|
|
target: np.ndarray = d.target
|
|
|
|
if n_points is not None:
|
|
df = shap.utils.sample(df, n_points, random_state=0)
|
|
target = shap.utils.sample(target, n_points, random_state=0)
|
|
|
|
if display:
|
|
return df, [str(d.target_names[v]) for v in target]
|
|
return df, target
|
|
|
|
|
|
def adult(display: bool = False, n_points: int | None = None) -> tuple[pd.DataFrame, np.ndarray]:
|
|
"""Return the Adult census data in a structured format.
|
|
|
|
Used in binary classification tasks.
|
|
|
|
Parameters
|
|
----------
|
|
display : bool, optional
|
|
If True, return the raw data without target and redundant columns.
|
|
n_points : int, optional
|
|
Number of data points to sample. If provided, randomly samples the specified number of points.
|
|
|
|
Returns
|
|
-------
|
|
X : pd.DataFrame
|
|
If ``display`` is True, ``X`` contains the raw data without the 'Education', 'Target', and 'fnlwgt' columns.
|
|
Otherwise, ``X`` contains the processed data without the 'Target' and 'fnlwgt' columns.
|
|
y : np.ndarray
|
|
The 'Target' column returned as an array.
|
|
|
|
Notes
|
|
-----
|
|
- The original data includes the following columns:
|
|
|
|
- ``Age`` (float) : Age in years.
|
|
- ``Workclass`` (category) : Type of employment.
|
|
- ``fnlwgt`` (float) : Final weight; the number of units in the target population that the record represents.
|
|
- ``Education`` (category) : Highest level of education achieved.
|
|
- ``Education-Num`` (float) : Numeric representation of education level.
|
|
- ``Marital Status`` (category) : Marital status of the individual.
|
|
- ``Occupation`` (category) : Type of occupation.
|
|
- ``Relationship`` (category) : Relationship status.
|
|
- ``Race`` (category) : Ethnicity of the individual.
|
|
- ``Sex`` (category) : Gender of the individual.
|
|
- ``Capital Gain`` (float) : Capital gains recorded.
|
|
- ``Capital Loss`` (float) : Capital losses recorded.
|
|
- ``Hours per week`` (float) : Number of hours worked per week.
|
|
- ``Country`` (category) : Country of origin.
|
|
- ``Target`` (category) : Binary target variable indicating whether the individual earns more than 50K.
|
|
|
|
- The Education' column is redundant with 'Education-Num' and is dropped for simplicity.
|
|
- The 'Target' column is converted to binary (True/False) where '>50K' is True and '<=50K' is False.
|
|
- Certain categorical columns are encoded for numerical representation.
|
|
|
|
Examples
|
|
--------
|
|
To get the processed data and target labels::
|
|
|
|
data, target = shap.datasets.adult()
|
|
|
|
To get the raw data for display::
|
|
|
|
raw_data, target = shap.datasets.adult(display=True)
|
|
|
|
"""
|
|
dtypes = [
|
|
("Age", "float32"),
|
|
("Workclass", "category"),
|
|
("fnlwgt", "float32"),
|
|
("Education", "category"),
|
|
("Education-Num", "float32"),
|
|
("Marital Status", "category"),
|
|
("Occupation", "category"),
|
|
("Relationship", "category"),
|
|
("Race", "category"),
|
|
("Sex", "category"),
|
|
("Capital Gain", "float32"),
|
|
("Capital Loss", "float32"),
|
|
("Hours per week", "float32"),
|
|
("Country", "category"),
|
|
("Target", "category"),
|
|
]
|
|
raw_data = pd.read_csv(
|
|
cache(github_data_url + "adult.data"), names=[d[0] for d in dtypes], na_values="?", dtype=dict(dtypes)
|
|
)
|
|
|
|
if n_points is not None:
|
|
raw_data = shap.utils.sample(raw_data, n_points, random_state=0)
|
|
|
|
data = raw_data.drop(["Education"], axis=1) # redundant with Education-Num
|
|
filt_dtypes = list(filter(lambda x: x[0] not in ["Target", "Education"], dtypes))
|
|
data["Target"] = data["Target"] == " >50K"
|
|
rcode = {"Not-in-family": 0, "Unmarried": 1, "Other-relative": 2, "Own-child": 3, "Husband": 4, "Wife": 5}
|
|
for k, dtype in filt_dtypes:
|
|
if dtype == "category":
|
|
if k == "Relationship":
|
|
data[k] = np.array([rcode[v.strip()] for v in data[k]])
|
|
else:
|
|
data[k] = data[k].cat.codes
|
|
|
|
if display:
|
|
return raw_data.drop(["Education", "Target", "fnlwgt"], axis=1), data["Target"].values
|
|
return data.drop(["Target", "fnlwgt"], axis=1), data["Target"].values
|
|
|
|
|
|
def nhanesi(display: bool = False, n_points: int | None = None) -> tuple[pd.DataFrame, np.ndarray]:
|
|
"""Return a nicely packaged version of NHANES I data with survival times as labels.
|
|
|
|
Used in survival analysis tasks.
|
|
|
|
Parameters
|
|
----------
|
|
display : bool, optional
|
|
If True, returns the features with a modified display. Default is False.
|
|
n_points : int, optional
|
|
Number of data points to sample. Default is None (returns the entire dataset).
|
|
|
|
Returns
|
|
-------
|
|
X : pd.DataFrame
|
|
The feature data matrix. If ``display`` is True, a modified version of the features for display
|
|
is returned as ``X`` instead.
|
|
y : np.ndarray
|
|
The target variables representing survival times.
|
|
|
|
Examples
|
|
--------
|
|
Usage example::
|
|
|
|
features, survival_times = shap.datasets.nhanesi(display=True, n_points=100)
|
|
|
|
"""
|
|
X = pd.read_csv(cache(github_data_url + "NHANESI_X.csv"), index_col=0)
|
|
y = pd.read_csv(cache(github_data_url + "NHANESI_y.csv"), index_col=0)["y"]
|
|
|
|
if n_points is not None:
|
|
X = shap.utils.sample(X, n_points, random_state=0)
|
|
y = shap.utils.sample(y, n_points, random_state=0)
|
|
|
|
if display:
|
|
X_display = X.copy()
|
|
# X_display["sex_isFemale"] = ["Female" if v else "Male" for v in X["sex_isFemale"]]
|
|
return X_display, np.array(y)
|
|
return X, np.array(y)
|
|
|
|
|
|
def corrgroups60(n_points: int = 1_000) -> tuple[pd.DataFrame, np.ndarray]:
|
|
"""Correlated Groups (60 features)
|
|
|
|
A synthetic dataset consisting of 60 features with tight correlations among distinct groups of features.
|
|
|
|
Parameters
|
|
----------
|
|
n_points : int, optional
|
|
Number of data points to generate. Default is 1,000.
|
|
|
|
Returns
|
|
-------
|
|
X : pd.DataFrame
|
|
The feature data matrix
|
|
y : np.ndarray
|
|
The target variables
|
|
|
|
Notes
|
|
-----
|
|
- The dataset is generated with known correlations among distinct groups of features.
|
|
- Each feature is a unit variance Gaussian random variable centred around 0.
|
|
- The labels are generated based on a linear function of the features with added random noise.
|
|
|
|
Examples
|
|
--------
|
|
.. code-block:: python
|
|
|
|
data, target = shap.datasets.corrgroups60()
|
|
|
|
"""
|
|
# set a constant seed
|
|
old_seed = np.random.seed()
|
|
np.random.seed(0)
|
|
|
|
# generate dataset with known correlation
|
|
N, M = n_points, 60
|
|
|
|
# set one coefficient from each group of 3 to 1
|
|
beta = np.zeros(M)
|
|
beta[0:30:3] = 1
|
|
|
|
# build a correlation matrix with groups of 3 tightly correlated features
|
|
C = np.eye(M)
|
|
for i in range(0, 30, 3):
|
|
C[i, i + 1] = C[i + 1, i] = 0.99
|
|
C[i, i + 2] = C[i + 2, i] = 0.99
|
|
C[i + 1, i + 2] = C[i + 2, i + 1] = 0.99
|
|
|
|
def f(X):
|
|
return np.matmul(X, beta)
|
|
|
|
# Make sure the sample correlation is a perfect match
|
|
X_start = np.random.randn(N, M)
|
|
X_centered = X_start - X_start.mean(0)
|
|
Sigma = np.matmul(X_centered.T, X_centered) / X_centered.shape[0]
|
|
W = np.linalg.cholesky(np.linalg.inv(Sigma)).T
|
|
X_white = np.matmul(X_centered, W.T)
|
|
assert (
|
|
np.linalg.norm(np.corrcoef(np.matmul(X_centered, W.T).T) - np.eye(M)) < 1e-6
|
|
) # ensure this decorrelates the data
|
|
|
|
# create the final data
|
|
X_final = np.matmul(X_white, np.linalg.cholesky(C).T)
|
|
X = X_final
|
|
y = f(X) + np.random.randn(N) * 1e-2
|
|
|
|
# restore the previous numpy random seed
|
|
np.random.seed(old_seed)
|
|
|
|
return pd.DataFrame(X), y
|
|
|
|
|
|
def independentlinear60(n_points: int = 1_000) -> tuple[pd.DataFrame, np.ndarray]:
|
|
"""Independent Linear (60 features)
|
|
|
|
A synthetic dataset consisting of 60 features.
|
|
|
|
Parameters
|
|
----------
|
|
n_points : int, optional
|
|
Number of data points to generate. Default is 1,000.
|
|
|
|
Returns
|
|
-------
|
|
X : pd.DataFrame
|
|
The feature data matrix
|
|
y : np.ndarray
|
|
The target variables
|
|
|
|
Notes
|
|
-----
|
|
- Each feature is a unit variance Gaussian random variable centred around 0.
|
|
- The labels are generated based on a linear function of the features with added random noise.
|
|
|
|
Examples
|
|
--------
|
|
.. code-block:: python
|
|
|
|
features, labels = shap.datasets.independentlinear60()
|
|
|
|
"""
|
|
# set a constant seed
|
|
old_seed = np.random.seed()
|
|
np.random.seed(0)
|
|
|
|
# generate dataset with known correlation
|
|
N, M = n_points, 60
|
|
|
|
# set one coefficient from each group of 3 to 1
|
|
beta = np.zeros(M)
|
|
beta[0:30:3] = 1
|
|
|
|
def f(X):
|
|
return np.matmul(X, beta)
|
|
|
|
# Make sure the sample correlation is a perfect match
|
|
X_start = np.random.randn(N, M)
|
|
X = X_start - X_start.mean(0)
|
|
y = f(X) + np.random.randn(N) * 1e-2
|
|
|
|
# restore the previous numpy random seed
|
|
np.random.seed(old_seed)
|
|
|
|
return pd.DataFrame(X), y
|
|
|
|
|
|
def a1a(n_points: int | None = None) -> tuple[ssp.csr_matrix, np.ndarray]:
|
|
"""
|
|
Return a sparse dataset in scipy csr matrix format.
|
|
|
|
Data Source: :external+scikit-learn:func:`sklearn.datasets.load_svmlight_file`
|
|
|
|
Parameters
|
|
----------
|
|
n_points : int, optional
|
|
Number of data points to sample. If None, returns the entire dataset. Default is None.
|
|
|
|
Returns
|
|
-------
|
|
X : scipy.sparse.csr_matrix
|
|
Sparse feature matrix.
|
|
y : np.ndarray
|
|
Target labels.
|
|
|
|
Examples
|
|
--------
|
|
.. code-block:: python
|
|
|
|
data, target = shap.datasets.a1a()
|
|
|
|
"""
|
|
data: ssp.csr_matrix
|
|
target: np.ndarray
|
|
data, target = sklearn.datasets.load_svmlight_file(cache(github_data_url + "a1a.svmlight"))
|
|
|
|
if n_points is not None:
|
|
data = shap.utils.sample(data, n_points, random_state=0)
|
|
target = shap.utils.sample(target, n_points, random_state=0)
|
|
|
|
return data, target
|
|
|
|
|
|
def rank() -> tuple[ssp.csr_matrix, np.ndarray, ssp.csr_matrix, np.ndarray, np.ndarray, np.ndarray]:
|
|
"""Return ranking datasets from the LightGBM repository.
|
|
|
|
Used in ranking tasks.
|
|
|
|
Returns
|
|
-------
|
|
x_train : scipy.sparse.csr_matrix
|
|
Training feature matrix.
|
|
y_train : numpy.ndarray
|
|
Training labels.
|
|
x_test : scipy.sparse.csr_matrix
|
|
Testing feature matrix.
|
|
y_test : numpy.ndarray
|
|
Testing labels.
|
|
q_train : numpy.ndarray
|
|
Training query information.
|
|
q_test : numpy.ndarray
|
|
Testing query information.
|
|
|
|
Notes
|
|
-----
|
|
Data Source: LightGBM repository https://github.com/lightgbm-org/LightGBM/tree/master/examples/lambdarank
|
|
|
|
Examples
|
|
--------
|
|
.. code-block:: python
|
|
|
|
x_train, y_train, x_test, y_test, q_train, q_test = shap.datasets.rank()
|
|
|
|
"""
|
|
rank_data_url = "https://raw.githubusercontent.com/lightgbm-org/LightGBM/master/examples/lambdarank/"
|
|
x_train, y_train = sklearn.datasets.load_svmlight_file(cache(rank_data_url + "rank.train"))
|
|
x_test, y_test = sklearn.datasets.load_svmlight_file(cache(rank_data_url + "rank.test"))
|
|
q_train = np.loadtxt(cache(rank_data_url + "rank.train.query"))
|
|
q_test = np.loadtxt(cache(rank_data_url + "rank.test.query"))
|
|
|
|
return x_train, y_train, x_test, y_test, q_train, q_test
|
|
|
|
|
|
def cache(url: str, file_name: str | None = None) -> str:
|
|
"""Loads a file from the URL and caches it locally."""
|
|
if file_name is None:
|
|
file_name = os.path.basename(url)
|
|
data_dir = os.path.join(os.path.dirname(__file__), "cached_data")
|
|
os.makedirs(data_dir, exist_ok=True)
|
|
|
|
file_path: str = os.path.join(data_dir, file_name)
|
|
if not os.path.isfile(file_path):
|
|
urlretrieve(url, file_path)
|
|
|
|
return file_path
|