case-explainer 0.1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- case_explainer-0.1.1/LICENSE +21 -0
- case_explainer-0.1.1/MANIFEST.in +22 -0
- case_explainer-0.1.1/PKG-INFO +424 -0
- case_explainer-0.1.1/README.md +380 -0
- case_explainer-0.1.1/assets/README.md +52 -0
- case_explainer-0.1.1/assets/data/hardware_trojan.csv +3 -0
- case_explainer-0.1.1/case_explainer/__init__.py +13 -0
- case_explainer-0.1.1/case_explainer/explainer.py +318 -0
- case_explainer-0.1.1/case_explainer/explanation.py +233 -0
- case_explainer-0.1.1/case_explainer/indexing.py +108 -0
- case_explainer-0.1.1/case_explainer/metrics.py +111 -0
- case_explainer-0.1.1/case_explainer.egg-info/SOURCES.txt +31 -0
- case_explainer-0.1.1/docs/DEPLOYMENT.md +104 -0
- case_explainer-0.1.1/docs/Makefile +22 -0
- case_explainer-0.1.1/docs/README.md +59 -0
- case_explainer-0.1.1/docs/api/explainer.rst +189 -0
- case_explainer-0.1.1/docs/api/explanation.rst +221 -0
- case_explainer-0.1.1/docs/api/metrics.rst +201 -0
- case_explainer-0.1.1/docs/citation.rst +44 -0
- case_explainer-0.1.1/docs/conf.py +91 -0
- case_explainer-0.1.1/docs/index.rst +115 -0
- case_explainer-0.1.1/docs/license.rst +52 -0
- case_explainer-0.1.1/notebooks/01_iris_tutorial.ipynb +663 -0
- case_explainer-0.1.1/notebooks/02_breast_cancer_tutorial.ipynb +752 -0
- case_explainer-0.1.1/notebooks/03_fraud_detection_tutorial.ipynb +859 -0
- case_explainer-0.1.1/notebooks/04_hardware_trojan_tutorial.ipynb +911 -0
- case_explainer-0.1.1/notebooks/README.md +113 -0
- case_explainer-0.1.1/pyproject.toml +61 -0
- case_explainer-0.1.1/setup.cfg +4 -0
- case_explainer-0.1.1/setup.py +50 -0
- case_explainer-0.1.1/tests/test_explainer.py +406 -0
- case_explainer-0.1.1/tests/test_explanation.py +278 -0
- case_explainer-0.1.1/tests/test_indexing.py +121 -0
- case_explainer-0.1.1/tests/test_metrics.py +195 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Paul Whitten, Francis Wolff, Chris Papachristou
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Include essential top-level files
|
|
2
|
+
include README.md
|
|
3
|
+
include LICENSE
|
|
4
|
+
include pyproject.toml
|
|
5
|
+
|
|
6
|
+
# Include notebooks
|
|
7
|
+
recursive-include notebooks *.ipynb *.md
|
|
8
|
+
|
|
9
|
+
# Include assets (data files used in examples)
|
|
10
|
+
recursive-include assets *.csv *.md
|
|
11
|
+
|
|
12
|
+
# Include documentation source
|
|
13
|
+
recursive-include docs *.rst *.py *.md Makefile
|
|
14
|
+
|
|
15
|
+
# Exclude build artifacts and caches
|
|
16
|
+
global-exclude __pycache__
|
|
17
|
+
global-exclude *.py[cod]
|
|
18
|
+
global-exclude *.so
|
|
19
|
+
global-exclude .DS_Store
|
|
20
|
+
prune dist
|
|
21
|
+
prune build
|
|
22
|
+
prune *.egg-info
|
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: case-explainer
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: General-purpose case-based explainability for machine learning
|
|
5
|
+
Home-page: https://github.com/paulwhitten/case-explainer
|
|
6
|
+
Author: Paul Whitten
|
|
7
|
+
Author-email: Paul Whitten <pcw@case.edu>
|
|
8
|
+
License: MIT
|
|
9
|
+
Project-URL: Homepage, https://github.com/paulwhitten/case-explainer
|
|
10
|
+
Project-URL: Documentation, https://paulwhitten.github.io/case-explainer/
|
|
11
|
+
Project-URL: Repository, https://github.com/paulwhitten/case-explainer
|
|
12
|
+
Project-URL: Bug Tracker, https://github.com/paulwhitten/case-explainer/issues
|
|
13
|
+
Keywords: explainability,interpretability,machine-learning,case-based-reasoning,nearest-neighbors
|
|
14
|
+
Classifier: Development Status :: 3 - Alpha
|
|
15
|
+
Classifier: Intended Audience :: Science/Research
|
|
16
|
+
Classifier: Intended Audience :: Developers
|
|
17
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
24
|
+
Requires-Python: >=3.8
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
License-File: LICENSE
|
|
27
|
+
Requires-Dist: numpy>=1.20.0
|
|
28
|
+
Requires-Dist: scipy>=1.7.0
|
|
29
|
+
Requires-Dist: scikit-learn>=1.0.0
|
|
30
|
+
Requires-Dist: matplotlib>=3.3.0
|
|
31
|
+
Requires-Dist: pandas>=1.3.0
|
|
32
|
+
Provides-Extra: dev
|
|
33
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
34
|
+
Requires-Dist: pytest-cov>=3.0.0; extra == "dev"
|
|
35
|
+
Requires-Dist: black>=22.0.0; extra == "dev"
|
|
36
|
+
Requires-Dist: flake8>=4.0.0; extra == "dev"
|
|
37
|
+
Requires-Dist: mypy>=0.950; extra == "dev"
|
|
38
|
+
Requires-Dist: build>=0.10.0; extra == "dev"
|
|
39
|
+
Requires-Dist: twine>=4.0.0; extra == "dev"
|
|
40
|
+
Dynamic: author
|
|
41
|
+
Dynamic: home-page
|
|
42
|
+
Dynamic: license-file
|
|
43
|
+
Dynamic: requires-python
|
|
44
|
+
|
|
45
|
+
# Case-Explainer: General-Purpose Case-Based Explainability
|
|
46
|
+
|
|
47
|
+
[](https://www.python.org/downloads/)
|
|
48
|
+
[](https://pypi.org/project/case-explainer/)
|
|
49
|
+
[](https://opensource.org/licenses/MIT)
|
|
50
|
+
[](https://paulwhitten.github.io/case-explainer/)
|
|
51
|
+
[](https://github.com/paulwhitten/case-explainer/actions/workflows/ci.yml)
|
|
52
|
+
|
|
53
|
+
Provides model-agnostic explanations through training set precedent and nearest neighbor correspondence.
|
|
54
|
+
|
|
55
|
+
**[Read the full documentation](https://paulwhitten.github.io/case-explainer/)**
|
|
56
|
+
|
|
57
|
+
## What is Case-Based Explainability?
|
|
58
|
+
|
|
59
|
+
While some explainability methods provide feature importance scores, case-based explainability answers: **"Why was this prediction made?"** by showing similar training examples.
|
|
60
|
+
|
|
61
|
+
Instead of: *"Feature X has importance 0.45"*
|
|
62
|
+
You get: *"This sample is classified as X because it resembles these 5 training examples"*
|
|
63
|
+
|
|
64
|
+
## Features
|
|
65
|
+
|
|
66
|
+
- **Model-agnostic**: Works with any classifier (sklearn, XGBoost, neural networks, etc.)
|
|
67
|
+
- **Correspondence metric**: Quantifies agreement between prediction and neighbors
|
|
68
|
+
- **Multiple indexing strategies**: K-D Tree, Ball Tree, or brute force
|
|
69
|
+
- **Automatic scaling**: Optional feature standardization
|
|
70
|
+
- **Metadata tracking**: Attach provenance data to training samples
|
|
71
|
+
- **Sklearn-compatible API**: Familiar interface for ML practitioners
|
|
72
|
+
- **Batch explanations**: Explain multiple predictions efficiently
|
|
73
|
+
|
|
74
|
+
## Installation
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
pip install case-explainer
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Or, to install the latest development version from source:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
git clone https://github.com/paulwhitten/case-explainer.git
|
|
84
|
+
cd case-explainer
|
|
85
|
+
pip install -e .
|
|
86
|
+
|
|
87
|
+
# With development/test dependencies (pytest, pytest-cov, etc.)
|
|
88
|
+
pip install -e ".[dev]"
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Quick Start
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
from case_explainer import CaseExplainer
|
|
95
|
+
from sklearn.datasets import load_iris
|
|
96
|
+
from sklearn.model_selection import train_test_split
|
|
97
|
+
from sklearn.ensemble import RandomForestClassifier
|
|
98
|
+
|
|
99
|
+
# Load data
|
|
100
|
+
X, y = load_iris(return_X_y=True)
|
|
101
|
+
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)
|
|
102
|
+
|
|
103
|
+
# Train classifier
|
|
104
|
+
clf = RandomForestClassifier()
|
|
105
|
+
clf.fit(X_train, y_train)
|
|
106
|
+
|
|
107
|
+
# Create explainer
|
|
108
|
+
explainer = CaseExplainer(
|
|
109
|
+
X_train=X_train,
|
|
110
|
+
y_train=y_train,
|
|
111
|
+
feature_names=['sepal_len', 'sepal_width', 'petal_len', 'petal_width'],
|
|
112
|
+
algorithm='kd_tree'
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
# Explain a prediction
|
|
116
|
+
explanation = explainer.explain_instance(X_test[0], k=5, model=clf)
|
|
117
|
+
print(f"Correspondence: {explanation.correspondence:.2%}")
|
|
118
|
+
print(explanation.summary())
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Core Concepts
|
|
122
|
+
|
|
123
|
+
### Correspondence Metric
|
|
124
|
+
|
|
125
|
+
Quantifies agreement between prediction and retrieved neighbors using inverse-cubed distance weighting:
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
w(c) = sum[ 1 / (distance + 1)^3 ] for neighbors with class c
|
|
129
|
+
Correspondence = w(predicted_class) / sum( w(all_classes) )
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
The `+1` offset in the denominator prevents division by zero when a test sample is identical to a training sample (distance = 0). In that case the weight is simply `1 / 1 = 1`.
|
|
133
|
+
|
|
134
|
+
**Example Interpretation Thresholds** (domain-dependent, not universal standards):
|
|
135
|
+
- **High (≥85%)**: Strong agreement with training precedent
|
|
136
|
+
- **Medium (70-85%)**: Moderate agreement
|
|
137
|
+
- **Low (<70%)**: Weak agreement, prediction may be uncertain
|
|
138
|
+
|
|
139
|
+
*Note: These thresholds are illustrative examples. Appropriate thresholds should be determined empirically for each specific domain and use case based on validation studies.*
|
|
140
|
+
|
|
141
|
+
### Indexing Strategies
|
|
142
|
+
|
|
143
|
+
- **`kd_tree`**: Fast for low-dimensional data (<20 features)
|
|
144
|
+
- **`ball_tree`**: Better for high-dimensional data
|
|
145
|
+
- **`brute`**: Exact search for small datasets (<10k samples)
|
|
146
|
+
|
|
147
|
+
## Examples
|
|
148
|
+
|
|
149
|
+
See `quickstart.py` for a complete working example:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
python quickstart.py
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Tutorial Notebooks
|
|
156
|
+
|
|
157
|
+
Interactive Jupyter notebooks for each validated domain:
|
|
158
|
+
|
|
159
|
+
- [Iris Classification](notebooks/01_iris_tutorial.ipynb) - Introductory multi-class example
|
|
160
|
+
- [Breast Cancer Diagnosis](notebooks/02_breast_cancer_tutorial.ipynb) - Medical diagnosis domain
|
|
161
|
+
- [Fraud Detection](notebooks/03_fraud_detection_tutorial.ipynb) - Financial security with extreme class imbalance
|
|
162
|
+
- [Hardware Trojan Detection](notebooks/04_hardware_trojan_tutorial.ipynb) - Large-scale security domain
|
|
163
|
+
|
|
164
|
+
### Benchmarking
|
|
165
|
+
|
|
166
|
+
Comprehensive performance benchmarks across multiple datasets:
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
python benchmark.py # Full benchmark including MNIST
|
|
170
|
+
python benchmark.py --no-mnist # Skip MNIST (faster)
|
|
171
|
+
python benchmark.py --help # See all options
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Results (single run on reference hardware):
|
|
175
|
+
- **Speed**: 14-37 ms per explanation depending on dataset size
|
|
176
|
+
- **Memory**: <1 MB to 131 MB (scales with data size and dimensionality)
|
|
177
|
+
- **Correspondence**: 87-100% neighbor agreement across validated domains
|
|
178
|
+
- **Scalability**: Tested up to 200k training samples
|
|
179
|
+
|
|
180
|
+
**Note on Correspondence**: This metric measures agreement between predictions and retrieved neighbors, not prediction accuracy or quality. High correspondence indicates consistency with training data patterns, not necessarily correct predictions.
|
|
181
|
+
|
|
182
|
+
### Documentation
|
|
183
|
+
|
|
184
|
+
**[View full API documentation online](https://paulwhitten.github.io/case-explainer/)**
|
|
185
|
+
|
|
186
|
+
Build and view documentation locally:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
# Build documentation
|
|
190
|
+
cd docs
|
|
191
|
+
make html
|
|
192
|
+
|
|
193
|
+
# View documentation locally
|
|
194
|
+
python3 -m http.server 8000 --directory docs/_build/html
|
|
195
|
+
# Then open http://localhost:8000 in your browser
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
The documentation includes:
|
|
199
|
+
- Complete API reference for all classes and functions
|
|
200
|
+
- Usage examples and code snippets
|
|
201
|
+
- Theory and mathematical foundations
|
|
202
|
+
- Configuration guides and best practices
|
|
203
|
+
|
|
204
|
+
## Security & Privacy Considerations
|
|
205
|
+
|
|
206
|
+
**IMPORTANT:** Case-based explanations expose actual training samples as evidence. This can leak sensitive information:
|
|
207
|
+
|
|
208
|
+
- **Medical domains:** Patient records, diagnoses, treatments
|
|
209
|
+
- **Financial domains:** Account details, transaction patterns
|
|
210
|
+
- **Security domains:** Attack signatures, system vulnerabilities
|
|
211
|
+
- **Personal data:** User behavior, preferences, demographics
|
|
212
|
+
|
|
213
|
+
**Before using in production with sensitive data:**
|
|
214
|
+
1. Implement feature masking for sensitive columns
|
|
215
|
+
2. Consider differential privacy mechanisms
|
|
216
|
+
3. Apply anonymization to metadata
|
|
217
|
+
4. Set up access control and audit logging
|
|
218
|
+
5. Review legal/regulatory requirements (GDPR, HIPAA, etc.)
|
|
219
|
+
|
|
220
|
+
**Privacy protection features are planned for Phase 2.** For now, use only with non-sensitive data or in controlled research environments.
|
|
221
|
+
|
|
222
|
+
Unlike LIME/SHAP which only show feature importance, case-explainer exposes training sample features. Evaluate whether this trade-off is acceptable for your use case.
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## API Overview
|
|
227
|
+
|
|
228
|
+
### CaseExplainer
|
|
229
|
+
|
|
230
|
+
```python
|
|
231
|
+
explainer = CaseExplainer(
|
|
232
|
+
X_train, # Training features
|
|
233
|
+
y_train, # Training labels
|
|
234
|
+
feature_names=None, # Optional feature names
|
|
235
|
+
class_names=None, # Optional class names {0: 'cat', 1: 'dog'}
|
|
236
|
+
algorithm='kd_tree', # Indexing strategy
|
|
237
|
+
scale_data=True, # Standardize features
|
|
238
|
+
metadata=None # Optional provenance data
|
|
239
|
+
)
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### Explain Single Instance
|
|
243
|
+
|
|
244
|
+
```python
|
|
245
|
+
explanation = explainer.explain_instance(
|
|
246
|
+
test_sample, # Sample to explain
|
|
247
|
+
k=5, # Number of neighbors
|
|
248
|
+
model=clf, # Trained classifier
|
|
249
|
+
true_class=None, # Optional true label
|
|
250
|
+
distance_weighted=True # Use distance weighting
|
|
251
|
+
)
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### Explain Batch
|
|
255
|
+
|
|
256
|
+
```python
|
|
257
|
+
explanations = explainer.explain_batch(
|
|
258
|
+
X_test, # Test samples
|
|
259
|
+
k=5, # Number of neighbors
|
|
260
|
+
y_test=None, # Optional true labels
|
|
261
|
+
model=clf # Trained classifier
|
|
262
|
+
)
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### Explanation Object
|
|
266
|
+
|
|
267
|
+
```python
|
|
268
|
+
explanation.correspondence # Correspondence score [0, 1]
|
|
269
|
+
explanation.correspondence_interpretation # 'high', 'medium', 'low'
|
|
270
|
+
explanation.neighbors # List of Neighbor objects
|
|
271
|
+
explanation.predicted_class # Predicted class
|
|
272
|
+
explanation.is_correct() # True if prediction matches label
|
|
273
|
+
explanation.summary() # Text summary
|
|
274
|
+
explanation.to_dict() # Export as dictionary
|
|
275
|
+
explanation.plot() # Visualize (bar plot)
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
## Validated Domains
|
|
279
|
+
|
|
280
|
+
**Hardware Trojan Detection** (56,959 samples, 5 features)
|
|
281
|
+
- 99.3% average correspondence across indexing methods
|
|
282
|
+
- High neighbor agreement on imbalanced security data
|
|
283
|
+
- 25.7 ms/sample explanation time (single run, reference hardware)
|
|
284
|
+
|
|
285
|
+
**Credit Card Fraud Detection** (284,807 samples, 30 features)
|
|
286
|
+
- 100% average correspondence (complete agreement with retrieved neighbors)
|
|
287
|
+
- Highly imbalanced dataset (268:1 normal:fraud ratio)
|
|
288
|
+
- 36.4 ms/sample explanation time (single run, reference hardware)
|
|
289
|
+
|
|
290
|
+
**Medical Diagnosis - Breast Cancer** (569 samples, 30 features)
|
|
291
|
+
- 93.3% average correspondence
|
|
292
|
+
- Correct predictions: 96.2% correspondence vs 47.3% for incorrect predictions
|
|
293
|
+
- 25.9 ms/sample explanation time (single run, reference hardware)
|
|
294
|
+
|
|
295
|
+
**Also Validated On:**
|
|
296
|
+
- Iris (92.7%), Wine (91.8%), Digits (94.9%), MNIST (87.5%)
|
|
297
|
+
- See `benchmark.py` for full results across 7 datasets
|
|
298
|
+
|
|
299
|
+
*Note: Correspondence measures neighbor agreement, not prediction quality. High correspondence with incorrect predictions indicates the model has learned incorrect patterns in the training data.*
|
|
300
|
+
|
|
301
|
+
## When to Use Case-Based Explainability
|
|
302
|
+
|
|
303
|
+
**Case-Explainer is well-suited for scenarios where:**
|
|
304
|
+
- Domain experts need to verify predictions against known training cases
|
|
305
|
+
- Precedent-based reasoning is valued (medical diagnosis, legal decisions, security analysis)
|
|
306
|
+
- Concrete examples are more intuitive than feature importance scores
|
|
307
|
+
- Training data has provenance or metadata worth surfacing to users
|
|
308
|
+
- Fast explanation generation is needed for real-time or interactive systems
|
|
309
|
+
|
|
310
|
+
**Alternative approaches (LIME, SHAP) may be preferable when:**
|
|
311
|
+
- Feature contributions are more relevant than training precedents
|
|
312
|
+
- Training data cannot be exposed due to privacy/security constraints
|
|
313
|
+
- Model debugging requires understanding feature-level behavior
|
|
314
|
+
|
|
315
|
+
### Comparison with LIME and SHAP
|
|
316
|
+
|
|
317
|
+
| Aspect | Case-Explainer | LIME | SHAP |
|
|
318
|
+
|--------|---------------|------|------|
|
|
319
|
+
| Explanation type | Training precedents (similar cases) | Local surrogate model (feature importance) | Shapley values (feature importance) |
|
|
320
|
+
| Output | k nearest neighbors + correspondence score | Per-feature importance for one prediction | Per-feature importance (local and global) |
|
|
321
|
+
| Privacy risk | High -- exposes actual training samples | Low -- uses synthetic perturbations | Low -- no sample exposure |
|
|
322
|
+
| Speed (pipeline, HW trojan) | ~13 ms/sample | ~25 ms/sample | ~1 ms/sample (TreeSHAP) |
|
|
323
|
+
| Model-agnostic | Yes | Yes | Yes (KernelSHAP); tree-specific variants are faster |
|
|
324
|
+
| Best for | Precedent-based reasoning, domain expert verification | Local feature contributions, model debugging | Global + local feature analysis, theoretical guarantees |
|
|
325
|
+
|
|
326
|
+
*Timing from the hardware trojan detection pipeline (XGBoost classifier, 5 features, ~57k samples). SHAP uses TreeSHAP which exploits tree structure for speed; KernelSHAP (model-agnostic) is substantially slower. LIME and Case-Explainer speeds are model-agnostic. Results will vary with dataset size, dimensionality, and hardware.*
|
|
327
|
+
|
|
328
|
+
## Limitations
|
|
329
|
+
|
|
330
|
+
**Privacy and Security**
|
|
331
|
+
- Exposes actual training samples, which may contain sensitive information
|
|
332
|
+
- Not suitable for sensitive data without additional privacy protection mechanisms
|
|
333
|
+
- Privacy-preserving features are planned for future releases
|
|
334
|
+
|
|
335
|
+
**Correspondence Metric**
|
|
336
|
+
- Measures neighbor agreement, not prediction correctness or quality
|
|
337
|
+
- High correspondence can occur with incorrect predictions if training data contains systematic errors
|
|
338
|
+
- Thresholds for "high/medium/low" must be validated per domain
|
|
339
|
+
|
|
340
|
+
**Performance Benchmarks**
|
|
341
|
+
- Timing and memory results are from single runs on reference hardware
|
|
342
|
+
- No statistical error bars or confidence intervals provided
|
|
343
|
+
- Results may vary significantly on different hardware and with different parameters
|
|
344
|
+
|
|
345
|
+
**Scalability**
|
|
346
|
+
- Memory usage scales linearly with training set size
|
|
347
|
+
- Very large datasets (>1M samples) may require approximate nearest neighbor methods (not yet implemented)
|
|
348
|
+
|
|
349
|
+
**Interpretability**
|
|
350
|
+
- Assumes users can meaningfully interpret feature values of retrieved neighbors
|
|
351
|
+
- Multi-feature patterns may be difficult to assess without domain expertise
|
|
352
|
+
- High-dimensional data may require dimensionality reduction for effective interpretation
|
|
353
|
+
|
|
354
|
+
## Development Status
|
|
355
|
+
|
|
356
|
+
### Core Functionality MVP
|
|
357
|
+
- [x] CaseExplainer class with sklearn-compatible API
|
|
358
|
+
- [x] Correspondence metric with distance weighting
|
|
359
|
+
- [x] Multiple indexing strategies (K-D tree, Ball tree, brute force)
|
|
360
|
+
- [x] Explanation object with summary and visualization
|
|
361
|
+
- [x] Metadata/provenance tracking
|
|
362
|
+
- [x] Batch explanation support
|
|
363
|
+
|
|
364
|
+
### Phase 1: Multi-Domain Validation
|
|
365
|
+
- [x] Hardware trojan detection (validated in JETTA paper)
|
|
366
|
+
- [x] Medical diagnosis (UCI Breast Cancer)
|
|
367
|
+
- [x] Fraud detection (Credit Card Fraud)
|
|
368
|
+
- [x] Benchmarking (time, memory, correspondence)
|
|
369
|
+
|
|
370
|
+
### Phase 2: Documentation - IN PROGRESS
|
|
371
|
+
- [x] API reference
|
|
372
|
+
- [x] Tutorial notebooks (4 domains)
|
|
373
|
+
- [x] Comparison guide (vs LIME/SHAP)
|
|
374
|
+
- [x] Code coverage >90%
|
|
375
|
+
|
|
376
|
+
### Phase 3: Testing & Quality
|
|
377
|
+
- [x] Unit test suite (pytest, >90% coverage)
|
|
378
|
+
- [x] Multi-Python version compatibility (3.8–3.12)
|
|
379
|
+
- [x] Integration tests across validated domains
|
|
380
|
+
- [ ] Privacy-preserving features (feature masking, differential privacy)
|
|
381
|
+
- [ ] Approximate nearest neighbors (Annoy, FAISS) for large-scale data
|
|
382
|
+
|
|
383
|
+
### Phase 4: Release & Distribution
|
|
384
|
+
- [x] PyPI package (`pip install case-explainer`)
|
|
385
|
+
- [x] GitHub Pages documentation (https://paulwhitten.github.io/case-explainer/)
|
|
386
|
+
- [x] CI/CD pipeline (GitHub Actions: test matrix, publish to PyPI)
|
|
387
|
+
- [ ] Zenodo DOI
|
|
388
|
+
|
|
389
|
+
## Citation
|
|
390
|
+
|
|
391
|
+
If you use this module in academic work, please cite:
|
|
392
|
+
|
|
393
|
+
```bibtex
|
|
394
|
+
@software{case_explainer2025,
|
|
395
|
+
author = {Whitten, Paul and Wolff, Francis and Papachristou, Chris},
|
|
396
|
+
title = {Case-Explainer: General-Purpose Case-Based Explainability},
|
|
397
|
+
year = {2025},
|
|
398
|
+
url = {https://github.com/paulwhitten/case-explainer}
|
|
399
|
+
}
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
## License
|
|
403
|
+
|
|
404
|
+
MIT License - see LICENSE file for details.
|
|
405
|
+
|
|
406
|
+
## Contributing
|
|
407
|
+
|
|
408
|
+
Contributions welcome! Core functionality and release infrastructure are complete.
|
|
409
|
+
|
|
410
|
+
**Priority areas:**
|
|
411
|
+
- Additional distance metrics (Manhattan, Cosine)
|
|
412
|
+
- Approximate nearest neighbors (Annoy, FAISS) for large-scale data
|
|
413
|
+
- Radar and parallel coordinate visualizations
|
|
414
|
+
- More comprehensive unit tests
|
|
415
|
+
|
|
416
|
+
## Contact
|
|
417
|
+
|
|
418
|
+
Questions? Issues? Open a GitHub issue or contact pcw@case.edu.
|
|
419
|
+
|
|
420
|
+
## Acknowledgments
|
|
421
|
+
|
|
422
|
+
- Inspired by Caruana et al. (1999) "Case-based explanation of non-case-based learning"
|
|
423
|
+
- Validated on hardware trojan detection research
|
|
424
|
+
- Built with scikit-learn, scipy, and matplotlib
|