<img src="https://raw.githubusercontent.com/ADMAntwerp/CounterPlots/main/_static/counterplots_logo.svg"><br>
--------------------------------------
CounterPlots: Plotting tool for counterfactuals
=======================================
[![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.
## 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://raw.githubusercontent.com/ADMAntwerp/CounterPlots/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://raw.githubusercontent.com/ADMAntwerp/CounterPlots/main/_static/counterplots_example_countershapley.png">
### Constellation Plot
This chart shows the prediction score change for all possible feature change combinations.
<img src="https://raw.githubusercontent.com/ADMAntwerp/CounterPlots/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
```
Raw data
{
"_id": null,
"home_page": "https://github.com/ADMAntwerp/CounterPlots",
"name": "counterplots",
"maintainer": "",
"docs_url": null,
"requires_python": "",
"maintainer_email": "",
"keywords": "Counterfactual Explanations,Visualization,Plotting,Explainable Artificial Intelligence,XAI,Machine Learning",
"author": "Raphael Mazzine Barbosa de Oliveira, Bjorge Meulemeester",
"author_email": "",
"download_url": "https://files.pythonhosted.org/packages/d7/10/4350dcb4bbe49c50901e4427eb0ca98f1e322539d5d91af44cffc108fc04/counterplots-0.0.7.tar.gz",
"platform": null,
"description": "<img src=\"https://raw.githubusercontent.com/ADMAntwerp/CounterPlots/main/_static/counterplots_logo.svg\"><br>\n\n--------------------------------------\n\nCounterPlots: Plotting tool for counterfactuals\n=======================================\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![example workflow](https://github.com/ADMAntwerp/CounterPlots/actions/workflows/deployment.yml/badge.svg)](https://github.com/ADMAntwerp/CounterPlots/actions)\n[![Code Coverage](https://codecov.io/gh/rmazzine/counterplotcoverage/branch/main/graph/badge.svg?token=TQYJSGEMP1)](https://codecov.io/gh/rmazzine/counterplotcoverage)\n[![Known Vulnerabilities](https://snyk.io/test/github/ADMAntwerp/CounterPlots/badge.svg)](https://snyk.io/test/github/ADMAntwerp/CounterPlots)\n\nCounterplots is a Python package that allows you to plot counterfactuals with easy integration with any counterfactual generation algorithm.\n\n## Plot examples\n\n### Greedy Plot\n\nThe 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.\n\n<img src=\"https://raw.githubusercontent.com/ADMAntwerp/CounterPlots/main/_static/counterplots_example_greedy.png\">\n\n### CounterShapley Plot\n\nThis chart shows each counterfactual feature change contribution to the counterfactual prediction. It uses Shapley values to calculate the contribution of each feature change.\n\n<img src=\"https://raw.githubusercontent.com/ADMAntwerp/CounterPlots/main/_static/counterplots_example_countershapley.png\">\n\n### Constellation Plot\n\nThis chart shows the prediction score change for all possible feature change combinations.\n\n<img src=\"https://raw.githubusercontent.com/ADMAntwerp/CounterPlots/main/_static/counterplots_example_constellation.png\">\n\n## Requirements\nCounterPlots requires Python 3.8 or higher.\n\n## Installation\nWith pip:\n```bash\npip install counterplots\n```\n\n## Usage\nTo use CounterPlots, you just need the machine learning model predictor, and the factual and counterfactual points.\nThe example below uses a simple mock model:\n```python\nfrom counterplots import CreatePlot\nimport numpy as np\n\n# Simple mock model for the predict_proba function which returns a probability for each input instance\ndef mock_predict_proba(data):\n out = []\n for x in data:\n if list(x) == [0.0, 0.0, 0.0]:\n out.append(0.0)\n elif list(x) == [1.0, 0.0, 0.0]:\n out.append(0.44)\n elif list(x) == [0.0, 1.0, 0.0]:\n out.append(0.4)\n elif list(x) == [0.0, 0.0, 1.0]:\n out.append(0.2)\n elif list(x) == [1.0, 1.0, 0.0]:\n out.append(0.3)\n elif list(x) == [0.0, 1.0, 1.0]:\n out.append(0.25)\n elif list(x) == [1.0, 0.0, 1.0]:\n out.append(0.4)\n elif list(x) == [1.0, 1.0, 1.0]:\n out.append(1.0)\n return np.array(out)\n\n# Factual Instance\nfactual = np.array([0, 0, 0])\n# Counterfactual Instance\ncf = np.array([1, 1, 1])\n\n# Create the plot object\ncf_plots = CreatePlot(\n factual,\n cf,\n mock_predict_proba)\n\n# Create the greedy plot\ncf_plots.greedy('greedy_plot.png')\n# Create the countershapley plot\ncf_plots.countershapley('countershapley_plot.png')\n# Create the constellation plot\ncf_plots.constellation('constellation_plot.png')\n\n# Print the countershapley values\nprint(cf_plots.countershapley_values())\n```\n\nIn case you want to add custom names to the features, use the optional argument `feature_names`:\n```python\ncf_plots = CreatePlot(\n factual,\n cf,\n mock_predict_proba,\n feature_names=['feature1', 'feature2', 'feature3'])\n```\n\nIn case you want to add custom labels to the factual and counterfactual points, use the optional argument `class_names`:\n```python\ncf_plots = CreatePlot(\n factual,\n cf,\n mock_predict_proba,\n class_names=['Factual', 'Counterfactual'])\n```\n\n## Using with Scikit-Learn\n\nCounterPlots can be used with any machine learning model that has a `predict_proba` function. For example, with Scikit-Learn:\n<details>\n\n```python\nimport numpy as np\nfrom sklearn.ensemble import RandomForestClassifier\nfrom sklearn.datasets import load_iris\n\nfrom counterplots import CreatePlot\n\niris = load_iris()\n\nX = iris.data\ny = [0 if l == 0 else 1 for l in iris.target] # Makes it a binary classification problem\n\nclf = RandomForestClassifier(max_depth=2, random_state=0)\nclf.fit(X, y)\n\npreds = clf.predict(X)\n\n# For the factual point, takes an instance with 0 classification\nfactual = X[np.argwhere(preds == 0)[0]][0]\n# For the counterfactual point, takes an instance with 1 classification\ncf = X[np.argwhere(preds == 1)[0]][0]\n\ncf_plots = CreatePlot(\n factual,\n cf,\n clf.predict_proba,\n feature_names=iris.feature_names,\n class_names={0: 'Setosa', 1: 'Non-Setosa'}\n)\n\n\n# Create the greedy plot\ncf_plots.greedy('iris_greedy_plot.png')\n# Create the countershapley plot\ncf_plots.countershapley('iris_countershapley_plot.png')\n# Create the constellation plot\ncf_plots.constellation('iris_constellation_plot.png')\n\n# Print the countershapley values\nprint(cf_plots.countershapley_values())\n```\n</details>\n\n## Citation\nIf you use CounterPlots in your research, please cite the following paper:\n```bibtex\n```",
"bugtrack_url": null,
"license": "MIT",
"summary": "Plotting tool for counterfactual explanations",
"version": "0.0.7",
"project_urls": {
"Download": "https://pypi.org/project/counterplots/",
"Homepage": "https://github.com/ADMAntwerp/CounterPlots"
},
"split_keywords": [
"counterfactual explanations",
"visualization",
"plotting",
"explainable artificial intelligence",
"xai",
"machine learning"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "d7104350dcb4bbe49c50901e4427eb0ca98f1e322539d5d91af44cffc108fc04",
"md5": "3738c3b7e59798b76e67395b805ebe72",
"sha256": "1cc80ad3d555c762a988cb973e1c880716ce138328f6555534f7c9f4148eecba"
},
"downloads": -1,
"filename": "counterplots-0.0.7.tar.gz",
"has_sig": false,
"md5_digest": "3738c3b7e59798b76e67395b805ebe72",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 15948,
"upload_time": "2023-06-10T20:47:57",
"upload_time_iso_8601": "2023-06-10T20:47:57.437335Z",
"url": "https://files.pythonhosted.org/packages/d7/10/4350dcb4bbe49c50901e4427eb0ca98f1e322539d5d91af44cffc108fc04/counterplots-0.0.7.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-06-10 20:47:57",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "ADMAntwerp",
"github_project": "CounterPlots",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"requirements": [],
"lcname": "counterplots"
}