Metadata-Version: 2.4
Name: counterplots
Version: 0.0.9
Summary: Add your description here
Home-page: https://github.com/ADMAntwerp/CounterPlots
Download-URL: https://pypi.org/project/counterplots/
Author: Raphael Mazzine Barbosa de Oliveira, Bjorge Meulemeester
Requires-Python: <3.11,>=3.8
Description-Content-Type: text/markdown
License-File: LICENSE.txt
Requires-Dist: anyio==3.6.2
Requires-Dist: argon2-cffi==21.3.0
Requires-Dist: argon2-cffi-bindings==21.2.0
Requires-Dist: arrow==1.2.3
Requires-Dist: asttokens==2.2.1
Requires-Dist: attrs==22.2.0
Requires-Dist: backcall==0.2.0
Requires-Dist: beautifulsoup4==4.11.1
Requires-Dist: bleach==5.0.1
Requires-Dist: cffi==1.15.1
Requires-Dist: cloudpickle==2.2.1
Requires-Dist: comm==0.1.2
Requires-Dist: commonmark==0.9.1
Requires-Dist: contourpy==1.0.6
Requires-Dist: cycler==0.11.0
Requires-Dist: debugpy==1.6.5
Requires-Dist: decorator==5.1.1
Requires-Dist: defusedxml==0.7.1
Requires-Dist: dice-ml>=0.11
Requires-Dist: docutils==0.19
Requires-Dist: entrypoints==0.4
Requires-Dist: executing==1.2.0
Requires-Dist: fastjsonschema==2.16.2
Requires-Dist: fonttools==4.38.0
Requires-Dist: fqdn==1.5.1
Requires-Dist: idna==3.4
Requires-Dist: imageio==2.25.0
Requires-Dist: importlib-metadata==6.0.0
Requires-Dist: importlib-resources==5.10.2
Requires-Dist: ipykernel==6.19.4
Requires-Dist: ipython==8.8.0
Requires-Dist: ipython-genutils==0.2.0
Requires-Dist: ipywidgets==8.0.4
Requires-Dist: isoduration==20.11.0
Requires-Dist: jedi==0.18.2
Requires-Dist: jeepney==0.8.0
Requires-Dist: jinja2==3.1.2
Requires-Dist: joblib==1.2.0
Requires-Dist: jsonpointer==2.3
Requires-Dist: jsonschema==4.17.3
Requires-Dist: jupyter==1.0.0
Requires-Dist: jupyter-client==7.4.8
Requires-Dist: jupyter-console==6.4.4
Requires-Dist: jupyter-core==5.1.2
Requires-Dist: jupyter-events==0.5.0
Requires-Dist: jupyter-server==2.0.6
Requires-Dist: jupyter-server-terminals==0.4.3
Requires-Dist: jupyterlab-pygments==0.2.2
Requires-Dist: jupyterlab-widgets==3.0.5
Requires-Dist: kiwisolver==1.4.4
Requires-Dist: lime==0.2.0.1
Requires-Dist: llvmlite==0.39.1
Requires-Dist: markupsafe==2.1.1
Requires-Dist: matplotlib==3.6.2
Requires-Dist: matplotlib-inline==0.1.6
Requires-Dist: mistune==2.0.4
Requires-Dist: nbclassic==0.4.8
Requires-Dist: nbclient==0.7.2
Requires-Dist: nbconvert==7.2.7
Requires-Dist: nbformat==5.7.1
Requires-Dist: nest-asyncio==1.5.6
Requires-Dist: networkx==3.0
Requires-Dist: nicex==0.2.3
Requires-Dist: notebook==6.5.2
Requires-Dist: notebook-shim==0.2.2
Requires-Dist: numba==0.56.4
Requires-Dist: numpy==1.23.5
Requires-Dist: packaging==23.0
Requires-Dist: pandas==1.5.2
Requires-Dist: pandocfilters==1.5.0
Requires-Dist: parso==0.8.3
Requires-Dist: pexpect==4.8.0
Requires-Dist: pickleshare==0.7.5
Requires-Dist: pillow==9.4.0
Requires-Dist: pkginfo==1.8.3
Requires-Dist: pkgutil-resolve-name==1.3.10
Requires-Dist: platformdirs==2.6.2
Requires-Dist: prometheus-client==0.15.0
Requires-Dist: prompt-toolkit==3.0.36
Requires-Dist: psutil==5.9.4
Requires-Dist: ptyprocess==0.7.0
Requires-Dist: pure-eval==0.2.2
Requires-Dist: pycparser==2.21
Requires-Dist: pygments==2.13.0
Requires-Dist: pyparsing==3.0.9
Requires-Dist: pyrsistent==0.19.3
Requires-Dist: python-dateutil==2.8.2
Requires-Dist: python-json-logger==2.0.4
Requires-Dist: pytz==2022.7
Requires-Dist: pywavelets==1.4.1
Requires-Dist: pyyaml==6.0
Requires-Dist: pyzmq==24.0.1
Requires-Dist: qtconsole==5.4.0
Requires-Dist: qtpy==2.3.0
Requires-Dist: readme-renderer==37.0
Requires-Dist: requests-toolbelt==0.9.1
Requires-Dist: rfc3339-validator==0.1.4
Requires-Dist: rfc3986==2.0.0
Requires-Dist: rfc3986-validator==0.1.1
Requires-Dist: rich==12.5.1
Requires-Dist: scikit-image==0.19.3
Requires-Dist: scikit-learn==1.2.0
Requires-Dist: scipy==1.10.0
Requires-Dist: seaborn==0.12.2
Requires-Dist: secretstorage==3.3.3
Requires-Dist: send2trash==1.8.0
Requires-Dist: shap==0.41.0
Requires-Dist: six==1.16.0
Requires-Dist: slicer==0.0.7
Requires-Dist: sniffio==1.3.0
Requires-Dist: soupsieve==2.3.2.post1
Requires-Dist: stack-data==0.6.2
Requires-Dist: terminado==0.17.1
Requires-Dist: threadpoolctl==3.1.0
Requires-Dist: tifffile==2023.2.2
Requires-Dist: tinycss2==1.2.1
Requires-Dist: tornado==6.2
Requires-Dist: tqdm==4.64.1
Requires-Dist: traitlets==5.8.0
Requires-Dist: twine==4.0.1
Requires-Dist: uri-template==1.2.0
Requires-Dist: wcwidth==0.2.5
Requires-Dist: webcolors==1.12
Requires-Dist: webencodings==0.5.1
Requires-Dist: websocket-client==1.4.2
Requires-Dist: widgetsnbextension==4.0.5
Requires-Dist: zipp==3.11.0
Dynamic: author
Dynamic: download-url
Dynamic: home-page
Dynamic: license-file

<img src="https://github.com/ADMAntwerp/CounterPlots/blob/main/_static/counterplots_logo.svg"><br>

--------------------------------------

CounterPlots: Plotting tool for counterfactual explanations
=======================================

[![PyPI Version](https://img.shields.io/pypi/v/counterplots.svg)](https://pypi.org/project/counterplots/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![example workflow](https://github.com/ADMAntwerp/CounterPlots/actions/workflows/deployment.yml/badge.svg)](https://github.com/ADMAntwerp/CounterPlots/actions)
[![Code Coverage](https://codecov.io/gh/rmazzine/counterplotcoverage/branch/main/graph/badge.svg?token=TQYJSGEMP1)](https://codecov.io/gh/rmazzine/counterplotcoverage)
[![Known Vulnerabilities](https://snyk.io/test/github/ADMAntwerp/CounterPlots/badge.svg)](https://snyk.io/test/github/ADMAntwerp/CounterPlots)

Counterplots is a Python package that allows you to plot counterfactuals with easy integration with any counterfactual generation algorithm.

[Medium Post with full tutorial](https://medium.com/@mazzine/measuring-counterfactual-explanations-feature-importance-with-counterplots-41359bc85aea)

[Preprint Article](https://arxiv.org/abs/2306.06506)

## Plot examples

### Greedy Plot

The greedy plot shows the greediest (feature change with the highest impact towards the opposite class) path from the factual instance until it reaches the counterfactual.

<img src="https://github.com/ADMAntwerp/CounterPlots/blob/main/_static/counterplots_example_greedy.png">

### CounterShapley Plot

This chart shows each counterfactual feature change contribution to the counterfactual prediction. It uses Shapley values to calculate the contribution of each feature change.

<img src="https://github.com/ADMAntwerp/CounterPlots/blob/main/_static/counterplots_example_countershapley.png">

### Constellation Plot

This chart shows the prediction score change for all possible feature change combinations.

<img src="https://github.com/ADMAntwerp/CounterPlots/blob/main/_static/counterplots_example_constellation.png">

## Requirements
CounterPlots requires Python 3.8 or higher.

## Installation
With pip:
```bash
pip install counterplots
```

## Usage
To use CounterPlots, you just need the machine learning model predictor, and the factual and counterfactual points.
The example below uses a simple mock model:
```python
from counterplots import CreatePlot
import numpy as np

# Simple mock model for the predict_proba function which returns a probability for each input instance
def mock_predict_proba(data):
    out = []
    for x in data:
        if list(x) == [0.0, 0.0, 0.0]:
            out.append(0.0)
        elif list(x) == [1.0, 0.0, 0.0]:
            out.append(0.44)
        elif list(x) == [0.0, 1.0, 0.0]:
            out.append(0.4)
        elif list(x) == [0.0, 0.0, 1.0]:
            out.append(0.2)
        elif list(x) == [1.0, 1.0, 0.0]:
            out.append(0.3)
        elif list(x) == [0.0, 1.0, 1.0]:
            out.append(0.25)
        elif list(x) == [1.0, 0.0, 1.0]:
            out.append(0.4)
        elif list(x) == [1.0, 1.0, 1.0]:
            out.append(1.0)
    return np.array(out)

# Factual Instance
factual = np.array([0, 0, 0])
# Counterfactual Instance
cf = np.array([1, 1, 1])

# Create the plot object
cf_plots = CreatePlot(
    factual,
    cf,
    mock_predict_proba)

# Create the greedy plot
cf_plots.greedy('greedy_plot.png')
# Create the countershapley plot
cf_plots.countershapley('countershapley_plot.png')
# Create the constellation plot
cf_plots.constellation('constellation_plot.png')

# Print the countershapley values
print(cf_plots.countershapley_values())
```

In case you want to add custom names to the features, use the optional argument `feature_names`:
```python
cf_plots = CreatePlot(
    factual,
    cf,
    mock_predict_proba,
    feature_names=['feature1', 'feature2', 'feature3'])
```

In case you want to add custom labels to the factual and counterfactual points, use the optional argument `class_names`:
```python
cf_plots = CreatePlot(
    factual,
    cf,
    mock_predict_proba,
    class_names=['Factual', 'Counterfactual'])
```

## Using with Scikit-Learn

CounterPlots can be used with any machine learning model that has a `predict_proba` function. For example, with Scikit-Learn:
<details>

```python
import numpy as np
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_iris

from counterplots import CreatePlot

iris = load_iris()

X = iris.data
y = [0 if l == 0 else 1 for l in iris.target] # Makes it a binary classification problem

clf = RandomForestClassifier(max_depth=2, random_state=0)
clf.fit(X, y)

preds = clf.predict(X)

# For the factual point, takes an instance with 0 classification
factual = X[np.argwhere(preds == 0)[0]][0]
# For the counterfactual point, takes an instance with 1 classification
cf = X[np.argwhere(preds == 1)[0]][0]

cf_plots = CreatePlot(
    factual,
    cf,
    clf.predict_proba,
    feature_names=iris.feature_names,
    class_names={0: 'Setosa', 1: 'Non-Setosa'}
)


# Create the greedy plot
cf_plots.greedy('iris_greedy_plot.png')
# Create the countershapley plot
cf_plots.countershapley('iris_countershapley_plot.png')
# Create the constellation plot
cf_plots.constellation('iris_constellation_plot.png')

# Print the countershapley values
print(cf_plots.countershapley_values())
```
</details>

## Citation
If you use CounterPlots in your research, please cite the following paper:
```bibtex
@misc{meulemeester2023calculating,
      title={Calculating and Visualizing Counterfactual Feature Importance Values}, 
      author={Bjorge Meulemeester and Raphael Mazzine Barbosa De Oliveira and David Martens},
      year={2023},
      eprint={2306.06506},
      archivePrefix={arXiv},
      primaryClass={cs.LG}
}
```
