Repository: shap/shap

Issue #1991: background data size limited to 100, xgboost
Created: 2021-05-11T10:58:32Z
Hi, I am working with a XGBoost model.
I was trying to feed different background data samples to estimate the largest size I could feed the explainer while keeping runtime reasonable, when I noticed that TreeExplainer apparently limits the size to 100 samples max?
This is weird, because I did not find any reference in the source code for  class Tree(Explainer):, but accessing the data through explainer.data seems to indicate this.
I reproduced this behavior with a simple available shap dataset as below:
import pandas as pd
import shap
import xgboost 

X_adult,y_adult = shap.datasets.adult()
model = xgboost.XGBClassifier(n_estimators=100, max_depth=2).fit(X_adult, y_adult)

for i in [1,10,20,50,100,200,300,400,1000,10000]:
    explainer = shap.TreeExplainer(model,X_adult[:i],feature_perturbation='interventional',model_output='probability')
    print(f"expected size: {i}, actual size: {explainer.data.shape[0]}")

which returns
expected size: 1, actual size: 1
expected size: 10, actual size: 10
expected size: 20, actual size: 20
expected size: 50, actual size: 50
expected size: 100, actual size: 100
expected size: 200, actual size: 100
expected size: 300, actual size: 100
expected size: 400, actual size: 100
expected size: 1000, actual size: 100
expected size: 10000, actual size: 100

Also, the code contains a warning that should be triggered when the data size is > 1000:
elif feature_perturbation == "interventional" and self.data.shape[0] > 1000:
                warnings.warn("Passing "+str(self.data.shape[0]) + " background samples may lead to slow runtimes. Consider "
                    "using shap.sample(data, 100) to create a smaller background data set.")

but it is never triggered in my case

Duplicate issue #2027: Background dataset is the training set, but shap says it does not use all leaves
Created: 2021-06-06T00:16:54Z
I understand the need for the tree_path_dependent pertubation algorithm to use all of the leaves in the model, but I am getting this error:
AssertionError: The background dataset you provided does not cover all the leaves in the model, so TreeExplainer cannot run with the feature_perturbation="tree_path_dependent" option! Try providing a larger background dataset, or using feature_perturbation="interventional".
when I pass the model training data in as the background set. This should be impossible, because that would mean a leaf was grown without any samples during training. Unfortunately I can't provide a reproduceable example. I have managed to discover that running the following:
explainer = shap.TreeExplainer(
    model=lgbmodel,
    data=training_features,
    feature_perturbation="tree_path_dependent",
    model_output="raw"
)
print(explainer.model.fully_defined_weighting)

returns False. However, the following:
model = TreeEnsemble(
    model=lgbmodel, 
    data=training_features.values, 
    data_missing=pd.isna(training_features), 
    model_output="raw"
)
print(model.fully_defined_weighting)

returns True. I'm at a loss of what could be going on here - as far as I can tell, this line defines self.model as a TreeEnsemble. The attribute fully_defined_weighting is never touched after that. Any ideas on what could be going on here? lgbmodel is a lightgbm model created with:
lgbmodel = lgb.train(
    params=lgbpars,
    train_set=dtrain,
    num_boost_round=best_iters,
    verbose_eval=True
)

If it matters, the lgbpars are:
lgbpars = {
    'objective': 'binary',
    'learning_rate': 0.01,
    'num_leaves': 45,
    'min_sum_hessian_in_leaf': 2698,
    'bagging_fraction': 0.7829,
    'bagging_freq': 1,
    'feature_fraction_bynode': 0.6285,
    'min_gain_to_split': 5.3470,
    'min_data_in_leaf': 1965,
    # 'scale_pos_weight': 1,
    'verbose': -1,
}

Closing comment (2021-06-07T18:55:38Z): It looks like this is because the default behavior is to only use 100 samples when a pd.DataFrame is passed to data. This is a dupe of #1991