Masking Models for Outlier Explanation
Project description
$\text{M}^2 \text{OE}$ - Masking Models for Outlier Explanation
This repository provides a Python implementation of the Masking Models for Outlier Explanation ($\text{M}^2 \text{OE}$) method and its extensions, namely, $\text{M}^2\text{OE-groups} and $\text{M}^2\text{OE}_e$, tailored to explain groups of outliers and evolving outliers, respectively. Given the normal samples of a tabular dataset, defined over continuous features, and an outlier, or a group of outliers, either a sequential outlier belonging to the dataset, the method learns which features to change (choice) and by how much (mask) to transform an outlier into a nearby normal point. The transformation is applied only to the chosen subspace, producing an interpretable counterfactual. Multiple explanations can be outputed for the same outlier to figure out alternative ways to restore the outlier.
The package includes ready-to-use explainers for:
- Single outliers - per-sample explanations
- Groups of outliers - shared feature choices across a set of outliers and indipendent patches
- Evolving outliers - explanation for evolving outliers, with preference-guided stability
All those explainers work with continuous tabular data.
References
Further information about the here implemented approaches are reported in the following papers. If you you our work, please cite them.
Single outliers
@article{angiulli2024explaining,
title={Explaining outliers and anomalous groups via subspace density contrastive loss},
author={Angiulli, Fabrizio and Fassetti, Fabio and Nistic{\`o}, Simona and Palopoli, Luigi},
journal={Machine Learning},
volume={113},
number={10},
pages={7565--7589},
year={2024},
publisher={Springer}
}
@inproceedings{angiulli2023counterfactuals,
title={Counterfactuals explanations for outliers via subspaces density contrastive loss},
author={Angiulli, Fabrizio and Fassetti, Fabio and Nistic{\'o}, Simona and Palopoli, Luigi},
booktitle={International Conference on Discovery Science},
pages={159--173},
year={2023},
organization={Springer}
}
Group Explanations
@article{angiulli2024explaining,
title={Explaining outliers and anomalous groups via subspace density contrastive loss},
author={Angiulli, Fabrizio and Fassetti, Fabio and Nistic{\`o}, Simona and Palopoli, Luigi},
journal={Machine Learning},
volume={113},
number={10},
pages={7565--7589},
year={2024},
publisher={Springer}
}
Explanations for evolving tabular data
@article{angiulli2025explaining,
title={Explaining evolving outliers for uncovering key aspects of the green comparative advantage},
author={Angiulli, Fabrizio and Fassetti, Fabio and Nistic{\`o}, Simona and Palopoli, Luigi},
journal={Array},
pages={100518},
year={2025},
publisher={Elsevier}
}
Installation
You can install our package by cloning this repository or using pip.
# clone
git clone https://github.com/AIDALab-DIMES/M2OE.git
cd M2OE
pip install -e .
# pip
pip install M2OE
Simple usages exaples
Single outlier (TabularExplainer)
import numpy as np
import M2OE
import M2OE.explainers.TabularExplainer as TE
# Create a random dataset (values in the [0,1] range) with 20 features
X = np.random.rand(100,20).astype(np.float32)
# Create a simple outlier
X[0,[4,5,6]] = 2
out = X[:1]
exp = TE.TabularExplainer([1.0, 1.2, 0.3], 0.001, 30, 16)
res = exp.compute_explanation(out, X[1:], 30)
for dims, patched in res:
print("chosen features:", dims) # indices of the chosen subspace
print("counterfactual patch:", patched) # patched sample o' (same shape as outlier)
Groups of outliers (TabularGroupExplainer)
import numpy as np
import M2OE
import M2OE.explainers.TabularGroupExplainer as TGE
# Create a random dataset (values in the [0,1] range) with 20 features
X = np.random.rand(100,20).astype(np.float32)
# Create three simple outliers
X[0,[4,5,6]] = 2
X[1,[3,4,5]] = 2
X[2,[5,6,7]] = 2
out = X[:3]
exp = TGE.TabularGroupExplainer([1.0, 1.0, 0.5], 0.001, 30, 16)
res = exp.compute_explanation(out, X[3:], 30)
# For each resulting group, you get a list of (dims, patched) per outlier -- the set of dims is unique for each group
for g, expls_for_group in enumerate(res):
print(f"Group {g}:")
print("shared chosen features:", dims)
for dims, patched in expls_for_group[0]: # explanations for the first outlier in group g
print("group counterfactual patch (example outlier):", patched)
Evolving outliers (TabularSequentialExplainer)
import numpy as np
import M2OE
import M2OE.explainers.TabularSequentialExplainer as TSE
# Create a data collection including three (T=3) snapshots with 20 features
X = np.random.rand(3, 100, 20).astype(np.float32)
# Generate a simple outlier
X[:,0,[4,5,6]] = 2
out = X[:, 0]
exp = TSE.TabularSequentialExplainer([1.0, 1.0, 0.5], 0.001, 30, 16)
res = exp.compute_explanation(out, X[:, 1:], 30)
# res is a list of length T; each item is a list of (dims_t, patched_t) -- the set of dims is unique for each snapshot
for t, exps_t in enumerate(res):
for dims_t, patched_t in exps_t:
print(f"[t={t}] chosen features:", dims_t, " patched:", patched_t)
Package structure
This module consists of two sub-packages: one (models/), which groups all the alternative neural networks used to produce the patches, and another (explainers/) containing the explainers, responsible for managing the entire explanation pipeline. The current structure is as follows.
models/MaskingModel(abstract base)TabularMM- single-sample masking modelTabularMM_SC- shared-choice masking model (groups)TabularMM_Pref- preference-guided shared-choice masking model (sequences)
explainers/TabularExplainer- single outlierTabularGroupExplainer- multiple outliers with shared choicesTabularSequentialExplainer- evolving outlier across time
If you want to extend our module you can either
add a new neural architecture by creating a new class in the
models/folder (must inherit from the MaskingModel abstract class)
or
create a new explanation pipeline by creating a new class in the
explainers/folder (must inherit from the Explainer abstract class)
Need help?
If you find any bugs, have questions, need help modifying $\text{M}^2\text{OE}$, or want to get in touch, feel free to write us an email!
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file m2oe-0.0.1.tar.gz.
File metadata
- Download URL: m2oe-0.0.1.tar.gz
- Upload date:
- Size: 15.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1e192d18d581f25ef116d11c284c71799dc319ac3733653a7f44f1a4694bec63
|
|
| MD5 |
98e30cfe652ebbf0c0043d96ee2900bd
|
|
| BLAKE2b-256 |
8e89f10aeaa307124a71a055f222abfab777c7e6f60b0012d86a9114aaa9256a
|
Provenance
The following attestation bundles were made for m2oe-0.0.1.tar.gz:
Publisher:
python-publish.yml on AIDALab-DIMES/M2OE
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
m2oe-0.0.1.tar.gz -
Subject digest:
1e192d18d581f25ef116d11c284c71799dc319ac3733653a7f44f1a4694bec63 - Sigstore transparency entry: 656312883
- Sigstore integration time:
-
Permalink:
AIDALab-DIMES/M2OE@925c96ec0abca1e4cfd934d486f1217623184c7f -
Branch / Tag:
refs/tags/v0.0.1 - Owner: https://github.com/AIDALab-DIMES
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@925c96ec0abca1e4cfd934d486f1217623184c7f -
Trigger Event:
release
-
Statement type:
File details
Details for the file m2oe-0.0.1-py3-none-any.whl.
File metadata
- Download URL: m2oe-0.0.1-py3-none-any.whl
- Upload date:
- Size: 28.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9370ca055a49c3f3a43919953868225636a0448c886b79da76a9fb04d653a5fa
|
|
| MD5 |
4a273a817136afb524060576a3f2c65c
|
|
| BLAKE2b-256 |
1c29f6ddc80c193ae18b052b8da6d630e30124e1d566ffe71a1417039b228d1e
|
Provenance
The following attestation bundles were made for m2oe-0.0.1-py3-none-any.whl:
Publisher:
python-publish.yml on AIDALab-DIMES/M2OE
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
m2oe-0.0.1-py3-none-any.whl -
Subject digest:
9370ca055a49c3f3a43919953868225636a0448c886b79da76a9fb04d653a5fa - Sigstore transparency entry: 656312929
- Sigstore integration time:
-
Permalink:
AIDALab-DIMES/M2OE@925c96ec0abca1e4cfd934d486f1217623184c7f -
Branch / Tag:
refs/tags/v0.0.1 - Owner: https://github.com/AIDALab-DIMES
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@925c96ec0abca1e4cfd934d486f1217623184c7f -
Trigger Event:
release
-
Statement type: