chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
"""Unit tests for the Permutation explainer."""
|
||||
|
||||
import pickle
|
||||
|
||||
import numpy as np
|
||||
|
||||
import shap
|
||||
|
||||
from . import common
|
||||
|
||||
|
||||
def test_exact_second_order():
|
||||
"""This tests that the Perumtation explain gives exact answers for second order functions."""
|
||||
rs = np.random.RandomState(42)
|
||||
data = rs.randint(0, 2, size=(100, 5))
|
||||
|
||||
def model(data):
|
||||
return data[:, 0] * data[:, 2] + data[:, 1] + data[:, 2] + data[:, 2] * data[:, 3]
|
||||
|
||||
right_answer = np.zeros(data.shape)
|
||||
right_answer[:, 0] += (data[:, 0] * data[:, 2]) / 2
|
||||
right_answer[:, 2] += (data[:, 0] * data[:, 2]) / 2
|
||||
right_answer[:, 1] += data[:, 1]
|
||||
right_answer[:, 2] += data[:, 2]
|
||||
right_answer[:, 2] += (data[:, 2] * data[:, 3]) / 2
|
||||
right_answer[:, 3] += (data[:, 2] * data[:, 3]) / 2
|
||||
shap_values = shap.explainers.PermutationExplainer(model, np.zeros((1, 5)))(data)
|
||||
|
||||
assert np.allclose(right_answer, shap_values.values) # type: ignore[union-attr]
|
||||
|
||||
|
||||
# TODO: add baseline comparison once PermutationExplainer supports passing a numpy.random.Generator
|
||||
# for reproducible results (currently uses global np.random state)
|
||||
def test_tabular_single_output_auto_masker():
|
||||
model, data = common.basic_xgboost_scenario(100)
|
||||
common.test_additivity(shap.explainers.PermutationExplainer, model.predict, data, data)
|
||||
|
||||
|
||||
def test_tabular_multi_output_auto_masker():
|
||||
model, data = common.basic_xgboost_scenario(100)
|
||||
common.test_additivity(shap.explainers.PermutationExplainer, model.predict_proba, data, data)
|
||||
|
||||
|
||||
def test_tabular_single_output_partition_masker():
|
||||
model, data = common.basic_xgboost_scenario(100)
|
||||
common.test_additivity(shap.explainers.PermutationExplainer, model.predict, shap.maskers.Partition(data), data)
|
||||
|
||||
|
||||
def test_tabular_multi_output_partition_masker():
|
||||
model, data = common.basic_xgboost_scenario(100)
|
||||
common.test_additivity(
|
||||
shap.explainers.PermutationExplainer, model.predict_proba, shap.maskers.Partition(data), data
|
||||
)
|
||||
|
||||
|
||||
def test_tabular_single_output_independent_masker():
|
||||
model, data = common.basic_xgboost_scenario(100)
|
||||
common.test_additivity(shap.explainers.PermutationExplainer, model.predict, shap.maskers.Independent(data), data)
|
||||
|
||||
|
||||
def test_tabular_multi_output_independent_masker():
|
||||
model, data = common.basic_xgboost_scenario(100)
|
||||
common.test_additivity(
|
||||
shap.explainers.PermutationExplainer, model.predict_proba, shap.maskers.Independent(data), data
|
||||
)
|
||||
|
||||
|
||||
def test_serialization():
|
||||
model, data = common.basic_xgboost_scenario()
|
||||
common.test_serialization(
|
||||
shap.explainers.PermutationExplainer, model.predict, data, data, rtol=0.1, atol=0.05, max_evals=100000
|
||||
)
|
||||
|
||||
|
||||
def test_serialization_no_model_or_masker():
|
||||
model, data = common.basic_xgboost_scenario()
|
||||
common.test_serialization(
|
||||
shap.explainers.PermutationExplainer,
|
||||
model.predict,
|
||||
data,
|
||||
data,
|
||||
model_saver=False,
|
||||
masker_saver=False,
|
||||
model_loader=lambda _: model.predict,
|
||||
masker_loader=lambda _: data,
|
||||
rtol=0.1,
|
||||
atol=0.05,
|
||||
max_evals=100000,
|
||||
)
|
||||
|
||||
|
||||
def test_serialization_custom_model_save():
|
||||
model, data = common.basic_xgboost_scenario()
|
||||
common.test_serialization(
|
||||
shap.explainers.PermutationExplainer,
|
||||
model.predict,
|
||||
data,
|
||||
data,
|
||||
model_saver=pickle.dump,
|
||||
model_loader=pickle.load,
|
||||
rtol=0.1,
|
||||
atol=0.05,
|
||||
max_evals=100000,
|
||||
)
|
||||
Reference in New Issue
Block a user