SeldonIO / alibi

Algorithms for explaining machine learning models
https://docs.seldon.io/projects/alibi/en/stable/
Other
2.41k stars 252 forks source link

How to use Counterfactual Explanations for classic shallow ML model for structured data? #172

Closed SSMK-wq closed 4 years ago

SSMK-wq commented 4 years ago

Hello Everyone,

1) I am working on a binary classification problem using Xgboost. I would like to interpret my model predictions better using Alibi's Counterfactual Explanations. However I see that in docs, you only have examples for deep learning models using Tensorflow and keras etc and MNIST . Does this work for a normal STRUCTURED DATA ANALYSIS problem like mine?\

2) Is counterfactual instances different from counterfactual guided by prototypes?

arnaudvl commented 4 years ago

Hi @SSMK-wq ,

It does. In your case, the method uses numerical gradients. This is documented here for counterfactuals and here for counterfactuals guided by prototypes.

Counterfactuals guided by prototypes speed up the counterfactual search process and generally lead to more in-distribution counterfactuals by guiding the counterfactual instance towards a prototype of a specific class. It follows the approach of this paper. So if you have some data to fit the prototypes on (either via an autoencoder or k-d trees), then this could be preferable over vanilla counterfactuals. As shown in the example here, using the prototypes can significantly speed up the search process for black box (e.g. Xgboost) models.

Hope this helps!

firmai commented 4 years ago

@arnaudvl I have been trying my best do do the same for LightGBM. I am somehow failing, I have tried everything. I have included a fully reproducible example (1 min running time). If ou can help out, it would be much appreciated.

https://colab.research.google.com/drive/18GxXLqtpT8XCIlvTxyEif9RJ0S5YwjmO

X = test.drop([y],axis=1).iloc[0,:].values.reshape((1,) + test.drop([y],axis=1).iloc[0,:].values.shape)
shape = X.shape
# shape = (1,) + train.shape[1:]

### You can use auto-encoder with a different prediction .
from alibi.explainers import CounterFactualProto

predict_fn = lambda x: model.predict(x)

cf = CounterFactualProto(predict_fn, shape, use_kdtree=True, theta=10., feature_range=(train.min(axis=0), train.max(axis=0)))
cf.fit(train.drop([y],axis=1), trustscore_kwargs=None)
explanation = cf.explain(X, k=2)
firmai commented 4 years ago

Thanks for the advice, I have tried a few alternatives, I still can't seem to get it work. If we can somehow get a full example of a non-nn model, it would be greatly appreciated. Again attached a file for reproducibility.

https://colab.research.google.com/drive/18GxXLqtpT8XCIlvTxyEif9RJ0S5YwjmO

arnaudvl commented 4 years ago

Hi @firmai . The output of the predict function of the classifier should be [batch size, number of classes], so [batch size, 2] for your binary classification problem. If I am not mistaken, the colab notebook shows that the predict function output is hardcoded to be of shape [2, 1].