Git Product home page Git Product logo

crillab / pyxai Goto Github PK

View Code? Open in Web Editor NEW
22.0 4.0 2.0 75.4 MB

PyXAI (Python eXplainable AI) is a Python library (version 3.6 or later) allowing to bring formal explanations suited to (regression or classification) tree-based ML models (Decision Trees, Random Forests, Boosted Trees, ...).

Home Page: https://www.cril.univ-artois.fr/pyxai

License: MIT License

Python 88.01% Shell 0.02% CMake 0.10% C++ 11.49% Dockerfile 0.18% Jupyter Notebook 0.20%
python xai boosted-trees classification decision-tree random-forest regression

pyxai's Introduction

pyxai

PyXAI - Python eXplainable AI

What is PyXAI ?

PyXAI (Python eXplainable AI) is a Python library (version 3.6 or later) allowing to bring formal explanations suited to (regression or classification) tree-based ML models (Decision Trees, Random Forests, Boosted Trees, ...). PyXAI generates explanations that are post-hoc and local. In contrast to many popular approaches to XAI (SHAP, LIME, ...), PyXAI generates explanations that are also correct. Being correct (aka sound or faithful) indicates that the explanations that are provided actually reflect the exact behaviour of the model by guaranteeing certain properties about the explanations generated. They can be of several types:

  • Abductive explanations for an instance $X$ are intended to explain why $X$ has been classified in the way it has been classified by the ML model (thus, addressing the “Why?” question). In the regression case, abductive explanations for $X$ are intended to explain why the regression value of $X$ belongs to a given interval.
  • Contrastive explanations for $X$ are intended to explain why $X$ has not been classified by the ML model as the user expected it (thus, addressing the “Why not?” question).

PyXAI also includes algorithms for correcting tree-based models when their predictions conflict with pieces of user knowledge. This more tricky facet of XAI is seldom offered by existing XAI systems. When some domain knowledge is available and a prediction (or an explanation) contradicts it, the model must be corrected. Rectification is a principled approach for such a correction operation.

New features in version 1.1:

  • Rectification for DT (Decision Tree) and RF (Random Forest) models dedicated to binary classification.
  • Visualization displayed in a notebook or on screen, and now also for time series problems.
  • Enhanced compatibility with Mac OS and Windows

New features in version 1.0:

  • Regression for Boosted Trees with XGBoost or LightGBM
  • Adding Theories (knowledge about the dataset)
  • Easier model import (automatic detection of model types)
  • PyXAI's Graphical User Interface (GUI): displaying, loading and saving explanations.
  • Supports multiple image formats for imaging datasets
  • Supports data pre-processing (tool for preparing and cleansing a dataset)
  • Unit Tests with the unittest module

pyxai

User interaction with PyXAI.

pyxai

PyXAI's Graphical User Interface (GUI) for visualizing explanations.

pyxai

Visualization in a notebook of an explanation for an instance from a time series problem.

What is the difference between PyXAI and other methods ?

The most popular approaches (SHAP, LIME, ...) to XAI are model-agnostic, but they do not offer any guarantees of rigor. A number of works by Marques-Silva and Huang, Ignatiev have highlighted several misconceptions about such approaches to XAI. Correctness is paramount when dealing with high-risk or sensitive applications, which is the type of applications that are targeted by PyXAI. When the correctness property is not satisfied, one can find ”counterexamples” for the explanations that are generated, i.e., pairs of instances sharing an explanation but leading to distinct predictions. Contrastingly, PyXAI algorithms rely on logic-based, model-precise approaches for computing explanations. Although formal explainability has a number of drawbacks, particularly in terms of the computational complexity of logical reasoning needed to derive explanations, steady progress has been made since its inception.

Which models can be explained with PyXAI ?

Models are the resulting objects of an experimental ML protocol through a chosen cross-validation method (for example, the result of a training phase on a classifier). Importantly, in PyXAI, there is a complete separation between the learning phase and the explaining phase: you produce/load/save models, and you find explanations for some instances given such models. Currently, with PyXAI, you can use methods to find explanations suited to different ML models for classification or regression tasks:

In addition to finding explanations, PyXAI also provides methods that perform operations (production, saving, loading) on models and instances. Currently, these methods are available for three ML libraries:

  • Scikit-learn: a software machine learning library
  • XGBoost: an optimized distributed gradient boosting library
  • LightGBM: a gradient boosting framework that uses tree based learning algorithms

It is possible to also leverage PyXAI to find explanations suited to models learned using other libraries.

What does this website offer ?

In this website, you can find all what you need to know about PyXAI, with more than 10 Jupyter Notebooks, including:

How to use PyXAI ?

Here is an example (it comes from the Quick Start page):

PyXAI in action

from pyxai import Learning, Explainer

learner = Learning.Scikitlearn("tests/iris.csv", learner_type=Learning.CLASSIFICATION)
model = learner.evaluate(method=Learning.HOLD_OUT, output=Learning.DT)
instance, prediction = learner.get_instances(model, n=1, correct=True, predictions=[0])

explainer = Explainer.initialize(model, instance)
print("instance:", instance)
print("binary representation:", explainer.binary_representation)

sufficient_reason = explainer.sufficient_reason(n=1)
print("sufficient_reason:", sufficient_reason)
print("to_features:", explainer.to_features(sufficient_reason))

instance, prediction = learner.get_instances(model, n=1, correct=False)
explainer.set_instance(instance)
contrastive_reason = explainer.contrastive_reason()
print("contrastive reason", contrastive_reason)
print("to_features:", explainer.to_features(contrastive_reason, contrastive=True))

explainer.visualisation.screen(instance, contrastive_reason, contrastive=True)

pyxai

As illustrated by this example, with a few lines of code, PyXAI allows you to train a model, extract instances, and get explanations about the classifications made.



pyxai's People

Contributors

audemard avatar gildasmorvan avatar szczepanskinicolas avatar xcsp3team avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

pyxai's Issues

Command docker

In the installation page, the command for Windows is not with a "$PWD", but wiht a %cd%.
image

Linux GitHub Installation Problem

For an Installation by Cloning the GitHub repository:

python3 setup.py install --user

can given:

SetuptoolsDeprecationWarning: setup.py install is deprecated. Use build and pip and other standards-based tools.
with some errors during the docplex 2.25.236 package installation:

File "/home/nicolas/pyxai/env/lib/python3.11/site-packages/setuptools/_distutils/cmd.py", line 107, in __getattr__
    raise AttributeError(attr)
AttributeError: install_layout

The solution is to install pyxai using pip:

git clone https://github.com/crillab/pyxai.git
cd pyxai
python3 -m pip install -e .
cd pyxai 
export PYTHONPATH="${PYTHONPATH}:${PWD}/.."
python3 -m pyxai

The documentation will be updated shortly.

python3 -m pip install -e .
executes the setup.py inside the pyxai directory and installs dependencies.

When using the explainer, labels may be displayed as int instead of str

When using the explainer, labels may be displayed as int instead of str.
The bug seems hard to replicate and happens randomly.

For instance, one run can give:

TreeDensity <= 67.56380844116211 PropagaProba > 0.03809056989848614

while another gives:

0 <= 67.56380844116211 1 > 0.03809056989848614

I'll check if it happens again in versions > 1.09

Note : Problem happens when explaining classifiers or regressors.

pyXAI GUI crashing on Debian 12

pyXAI GUI crashes on Debian 12 under virtualBox

Here is the log:

Python version:  3.11.2
PyXAI version:  1.0.8

PyXAI location:  /home/morvan/learn_and_explain_agent_based_models/lib/python3.11/site-packages/pyxai
Traceback (most recent call last):
  File "/home/morvan/learn_and_explain_agent_based_models/lib/python3.11/site-packages/pyxai/sources/core/tools/GUIQT.py", line 206, in mouseMoveEventLeft
    if self.pressed:
       ^^^^^^^^^^^^
AttributeError: 'GraphicalInterface' object has no attribute 'pressed'
  ``

Classification: Inconsistent labelling of learner predictions

The problem occurs when running the predict method of the Learner class:

prediction = explainer.predict(instance)

In this case, labels predicted by the learner are not the labels themselves but the order in which they appear in the dataset.

For example, if the first label in the dataset is 1 and the second is 0, then the learner will respectively predict 0 and 1. Conversely if the first label in the dataset is 0 and the second is 1, then the learner will respectively predict 0 and 1 as expected.

XGBOOSTClassifier

There is a problem with boolean condition when I want to import a model of XGBOOSTClassifier

I trained a XGBOOSTClassifier with some booleans features (with true and false and not 1 and 0 as possible values)

After the training, XGBOOST didn't registered a "split_condition" that pyxai try to read since it's implicit to check is the bool is set to true or not and pyxai failed to import my model

Virtual Machines (WSL, Docker, ..) do not support PyQT6 (for the PyXAI's GUI)

Under Windows by simulating Ubuntu with WSL :

import pyxai

gives:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/nicolas/pyxai/pyxai/__init__.py", line 8, in <module>
    from pyxai.sources.core.tools.GUIQT import GraphicalInterface
  File "/home/nicolas/pyxai/pyxai/sources/core/tools/GUIQT.py", line 3, in <module>
    from PyQt6.QtWidgets import QSplitter, QApplication, QAbstractItemView, QHeaderView, QBoxLayout, QFrame, QMessageBox, QFileDialog, QLabel, QSizePolicy, QScrollArea,  QStyleFactory, QMainWindow, QTableWidgetItem, QHBoxLayout, QMenu, QGroupBox, QListWidget, QWidget, QVBoxLayout, QGridLayout, QTableWidget
ImportError: libQt6Core.so.6: cannot open shared object file: No such file or directory

A solution for deactivating the GUI during installation and import is currently being implemented.

Meanwhile, for imports:

Solution from Here

LD_DEBUG=libs python3 allows us to locate the library.

cd /home/nicolas/.local/lib/python3.10/site-packages/PyQt6/Qt6/lib

strip --remove-section=.note.ABI-tag libQt6Core.so.6

Now import pyxai will works but a new problem appear with python3 -m pyxai:

qt.core.plugin.factoryloader: Got keys from plugin meta data QList("xcb")
qt.core.plugin.factoryloader: checking directory path "/usr/bin/platforms" ...
qt.core.library: "/home/nicolas/.local/lib/python3.10/site-packages/PyQt6/Qt6/plugins/platforms/libqxcb.so" cannot load: Cannot load library /home/nicolas/.local/lib/python3.10/site-packages/PyQt6/Qt6/plugins/platforms/libqxcb.so: (/usr/lib/x86_64-linux-gnu/libQt6XcbQpa.so.6: undefined symbol: _ZNK21QPlatformBackingStore9toTextureERK7QRegionP5QSizeP6QFlagsINS_11TextureFlagEE, version Qt_6_PRIVATE_API)
qt.core.plugin.loader: QLibraryPrivate::loadPlugin failed on "/home/nicolas/.local/lib/python3.10/site-packages/PyQt6/Qt6/plugins/platforms/libqxcb.so" : "Cannot load library /home/nicolas/.local/lib/python3.10/site-packages/PyQt6/Qt6/plugins/platforms/libqxcb.so: (/usr/lib/x86_64-linux-gnu/libQt6XcbQpa.so.6: undefined symbol: _ZNK21QPlatformBackingStore9toTextureERK7QRegionP5QSizeP6QFlagsINS_11TextureFlagEE, version Qt_6_PRIVATE_API)"
qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found.
This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.

Available platform plugins are: eglfs, linuxfb, minimal, minimalegl, offscreen, vkkhrdisplay, vnc, wayland-egl, wayland, xcb.

Aborted (core dumped)

Dealing with empty trees in Random Forests

When you have an empty tree in a Random Forest model, Learning.import_models() fails with

    px_learner, px_model = Learning.import_models(rf, feature_names=feature_names)
  File "/opt/conda/lib/python3.9/site-packages/pyxai/Learning.py", line 105, in import_models
    result_output = learner.convert_model(evaluation_output, learner_information)
  File "/opt/conda/lib/python3.9/site-packages/pyxai/sources/learning/learner.py", line 266, in convert_model
    return self.to_RF_CLS(self.learner_information)
  File "/opt/conda/lib/python3.9/site-packages/pyxai/sources/learning/scikitlearn.py", line 105, in to_RF_CLS
    decision_trees.append(self.classifier_to_DT(sk_tree, sk_raw_tree, id_solver_results))
  File "/opt/conda/lib/python3.9/site-packages/pyxai/sources/learning/scikitlearn.py", line 142, in classifier_to_DT
    root = nodes[0] if 0 in nodes else DecisionNode(1, 0, sk_raw_tree.value[0][0])
TypeError: __init__() takes 2 positional arguments but 4 were given

This happens when you have an empty tree, e.g.

sk_raw_tree.node_count
Out[1]: 1
nodes
Out[2]: {}
sk_raw_tree.feature
Out[3]: array([-2], dtype=int64)

Now, looking at the __init__ of DecisionNode in https://github.com/crillab/pyxai/blob/main/pyxai/sources/core/structure/decisionNode.py#L61, I realized left and right are missing from this call
https://github.com/crillab/pyxai/blob/main/pyxai/sources/learning/scikitlearn.py#L142C9-L142C87

So I changed this part from

root = nodes[0] if 0 in nodes else DecisionNode(1, 0, sk_raw_tree.value[0][0])

to

root = nodes[0] if 0 in nodes else DecisionNode(1, left=None, right=None)

to make this error go away.

But shouldn't this tree be skipped in the first place, since it is empty anyway?
Or perhaps an empty decision node root is valid and this is just a regression when you changed the DecisionNode.
I'd love to hear what you think should happen in this case. Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.