case-explainer 0.1.1__tar.gz → 0.2.0__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.2.0/CHANGELOG.md +43 -0
- {case_explainer-0.1.1 → case_explainer-0.2.0}/MANIFEST.in +4 -0
- {case_explainer-0.1.1 → case_explainer-0.2.0}/PKG-INFO +158 -61
- {case_explainer-0.1.1 → case_explainer-0.2.0}/README.md +153 -51
- case_explainer-0.2.0/case_explainer/__init__.py +77 -0
- case_explainer-0.2.0/case_explainer/_compat.py +19 -0
- case_explainer-0.2.0/case_explainer/activations.py +789 -0
- case_explainer-0.2.0/case_explainer/explainer.py +948 -0
- {case_explainer-0.1.1 → case_explainer-0.2.0}/case_explainer/explanation.py +88 -62
- {case_explainer-0.1.1 → case_explainer-0.2.0}/case_explainer/indexing.py +25 -25
- {case_explainer-0.1.1 → case_explainer-0.2.0}/case_explainer/metrics.py +22 -22
- case_explainer-0.2.0/case_explainer/py.typed +0 -0
- {case_explainer-0.1.1 → case_explainer-0.2.0}/case_explainer.egg-info/SOURCES.txt +9 -1
- case_explainer-0.2.0/docs/api/explainer.rst +412 -0
- {case_explainer-0.1.1 → case_explainer-0.2.0}/docs/api/explanation.rst +0 -3
- {case_explainer-0.1.1 → case_explainer-0.2.0}/docs/conf.py +2 -5
- {case_explainer-0.1.1 → case_explainer-0.2.0}/docs/index.rst +1 -0
- case_explainer-0.2.0/docs/migration.rst +80 -0
- case_explainer-0.2.0/notebooks/02_breast_cancer_tutorial.ipynb +1487 -0
- {case_explainer-0.1.1 → case_explainer-0.2.0}/notebooks/03_fraud_detection_tutorial.ipynb +136 -0
- {case_explainer-0.1.1 → case_explainer-0.2.0}/notebooks/04_hardware_trojan_tutorial.ipynb +130 -0
- {case_explainer-0.1.1 → case_explainer-0.2.0}/pyproject.toml +27 -5
- case_explainer-0.2.0/setup.py +6 -0
- case_explainer-0.2.0/tests/test_activations.py +1290 -0
- case_explainer-0.2.0/tests/test_benchmark.py +98 -0
- {case_explainer-0.1.1 → case_explainer-0.2.0}/tests/test_explainer.py +54 -37
- {case_explainer-0.1.1 → case_explainer-0.2.0}/tests/test_explanation.py +20 -4
- {case_explainer-0.1.1 → case_explainer-0.2.0}/tests/test_indexing.py +26 -15
- {case_explainer-0.1.1 → case_explainer-0.2.0}/tests/test_metrics.py +26 -12
- case_explainer-0.2.0/tests/test_notebooks.py +25 -0
- case_explainer-0.1.1/case_explainer/__init__.py +0 -13
- case_explainer-0.1.1/case_explainer/explainer.py +0 -318
- case_explainer-0.1.1/docs/api/explainer.rst +0 -189
- case_explainer-0.1.1/notebooks/02_breast_cancer_tutorial.ipynb +0 -752
- case_explainer-0.1.1/setup.py +0 -50
- {case_explainer-0.1.1 → case_explainer-0.2.0}/LICENSE +0 -0
- {case_explainer-0.1.1 → case_explainer-0.2.0}/assets/README.md +0 -0
- {case_explainer-0.1.1 → case_explainer-0.2.0}/assets/data/hardware_trojan.csv +0 -0
- {case_explainer-0.1.1 → case_explainer-0.2.0}/docs/DEPLOYMENT.md +0 -0
- {case_explainer-0.1.1 → case_explainer-0.2.0}/docs/Makefile +0 -0
- {case_explainer-0.1.1 → case_explainer-0.2.0}/docs/README.md +0 -0
- {case_explainer-0.1.1 → case_explainer-0.2.0}/docs/api/metrics.rst +0 -0
- {case_explainer-0.1.1 → case_explainer-0.2.0}/docs/citation.rst +0 -0
- {case_explainer-0.1.1 → case_explainer-0.2.0}/docs/license.rst +0 -0
- {case_explainer-0.1.1 → case_explainer-0.2.0}/notebooks/01_iris_tutorial.ipynb +0 -0
- {case_explainer-0.1.1 → case_explainer-0.2.0}/notebooks/README.md +0 -0
- {case_explainer-0.1.1 → case_explainer-0.2.0}/setup.cfg +0 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Case Explainer Changelog
|
|
3
|
+
description: Release history and migration schedule for Case Explainer
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## 0.2.0 (2026-09-02)
|
|
7
|
+
|
|
8
|
+
* Added the unified ``similarity=`` constructor parameter as the single knob
|
|
9
|
+
for retrieval mode, accepting a string shorthand (``"features"``,
|
|
10
|
+
``"activations"``) or a strategy object
|
|
11
|
+
* Added intent-named similarity strategies: ``Features``, ``HiddenActivations``,
|
|
12
|
+
``CustomActivations``, ``TreeLeaf``, ``ForestProximity``, and ``Blend``
|
|
13
|
+
* Added predicted-class activation weighting for multiclass classifiers
|
|
14
|
+
* Added support for arbitrary hashable classifier labels
|
|
15
|
+
* Added a PEP 561 ``py.typed`` marker so downstream users receive the package's
|
|
16
|
+
type hints
|
|
17
|
+
* Deprecated the ``retrieval=`` parameter and the ``*Retrieval`` configuration
|
|
18
|
+
classes in favor of ``similarity=`` and the strategy classes above
|
|
19
|
+
* Deprecated the legacy `activation_extractor`, `activation_layer`,
|
|
20
|
+
`blend_alpha`, and `use_output_weights` constructor parameters
|
|
21
|
+
|
|
22
|
+
The deprecated parameters and classes remain functional throughout the `0.2.x`
|
|
23
|
+
series. Use `similarity=` with the strategy classes for new integrations.
|
|
24
|
+
|
|
25
|
+
### Removal checklist for 0.3.0
|
|
26
|
+
|
|
27
|
+
* Remove the deprecated constructor parameters (`activation_extractor`,
|
|
28
|
+
`activation_layer`, `blend_alpha`, `use_output_weights`) and the
|
|
29
|
+
``retrieval=`` parameter along with the ``*Retrieval`` classes
|
|
30
|
+
* Remove tests that assert legacy and strategy-based equivalence
|
|
31
|
+
* Retain a clear `TypeError` for removed parameter usage when practical
|
|
32
|
+
* Update examples and API reference pages to show only ``similarity=``
|
|
33
|
+
* Add a migration note with before-and-after constructor examples
|
|
34
|
+
* Verify the package version, runtime version, and Sphinx release stay aligned
|
|
35
|
+
|
|
36
|
+
The runtime warning contract is centralized in ``case_explainer._compat`` and
|
|
37
|
+
the migration examples are maintained in ``docs/migration.rst``. Complete the
|
|
38
|
+
checklist only when preparing the 0.3.0 release; version 0.2.x must continue to
|
|
39
|
+
accept the deprecated parameters.
|
|
40
|
+
|
|
41
|
+
## 0.1.1
|
|
42
|
+
|
|
43
|
+
* Published the initial general-purpose feature-space case explainer
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
# Include essential top-level files
|
|
2
2
|
include README.md
|
|
3
3
|
include LICENSE
|
|
4
|
+
include CHANGELOG.md
|
|
4
5
|
include pyproject.toml
|
|
5
6
|
|
|
7
|
+
# Include the PEP 561 typing marker
|
|
8
|
+
include case_explainer/py.typed
|
|
9
|
+
|
|
6
10
|
# Include notebooks
|
|
7
11
|
recursive-include notebooks *.ipynb *.md
|
|
8
12
|
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: case-explainer
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: General-purpose case-based explainability for machine learning
|
|
5
|
-
Home-page: https://github.com/paulwhitten/case-explainer
|
|
6
|
-
Author: Paul Whitten
|
|
7
5
|
Author-email: Paul Whitten <pcw@case.edu>
|
|
8
6
|
License: MIT
|
|
9
7
|
Project-URL: Homepage, https://github.com/paulwhitten/case-explainer
|
|
@@ -11,7 +9,7 @@ Project-URL: Documentation, https://paulwhitten.github.io/case-explainer/
|
|
|
11
9
|
Project-URL: Repository, https://github.com/paulwhitten/case-explainer
|
|
12
10
|
Project-URL: Bug Tracker, https://github.com/paulwhitten/case-explainer/issues
|
|
13
11
|
Keywords: explainability,interpretability,machine-learning,case-based-reasoning,nearest-neighbors
|
|
14
|
-
Classifier: Development Status ::
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
15
13
|
Classifier: Intended Audience :: Science/Research
|
|
16
14
|
Classifier: Intended Audience :: Developers
|
|
17
15
|
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
@@ -32,15 +30,12 @@ Requires-Dist: pandas>=1.3.0
|
|
|
32
30
|
Provides-Extra: dev
|
|
33
31
|
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
34
32
|
Requires-Dist: pytest-cov>=3.0.0; extra == "dev"
|
|
35
|
-
Requires-Dist: black
|
|
36
|
-
Requires-Dist:
|
|
37
|
-
Requires-Dist: mypy
|
|
33
|
+
Requires-Dist: black==24.8.0; extra == "dev"
|
|
34
|
+
Requires-Dist: ruff==0.16.5; extra == "dev"
|
|
35
|
+
Requires-Dist: mypy==1.11.2; extra == "dev"
|
|
38
36
|
Requires-Dist: build>=0.10.0; extra == "dev"
|
|
39
37
|
Requires-Dist: twine>=4.0.0; extra == "dev"
|
|
40
|
-
Dynamic: author
|
|
41
|
-
Dynamic: home-page
|
|
42
38
|
Dynamic: license-file
|
|
43
|
-
Dynamic: requires-python
|
|
44
39
|
|
|
45
40
|
# Case-Explainer: General-Purpose Case-Based Explainability
|
|
46
41
|
|
|
@@ -70,6 +65,7 @@ You get: *"This sample is classified as X because it resembles these 5 training
|
|
|
70
65
|
- **Metadata tracking**: Attach provenance data to training samples
|
|
71
66
|
- **Sklearn-compatible API**: Familiar interface for ML practitioners
|
|
72
67
|
- **Batch explanations**: Explain multiple predictions efficiently
|
|
68
|
+
- **Model-informed similarity**: Retrieve cases from a neural network's learned representation or a decision tree's matching leaf
|
|
73
69
|
|
|
74
70
|
## Installation
|
|
75
71
|
|
|
@@ -120,11 +116,44 @@ print(explanation.summary())
|
|
|
120
116
|
|
|
121
117
|
## Core Concepts
|
|
122
118
|
|
|
119
|
+
### Traditional Feature-Space Precedent
|
|
120
|
+
|
|
121
|
+
By default, Case-Explainer retrieves training cases that are nearest to the
|
|
122
|
+
query in the original feature space. Numeric features are standardized by
|
|
123
|
+
default so a feature with a large numerical range does not dominate Euclidean
|
|
124
|
+
distance. Set `scale_data=False` only when the inputs are already on a
|
|
125
|
+
meaningful common scale or when custom scaling has been applied.
|
|
126
|
+
|
|
127
|
+
```python
|
|
128
|
+
feature_explainer = CaseExplainer(
|
|
129
|
+
X_train,
|
|
130
|
+
y_train,
|
|
131
|
+
feature_names=feature_names,
|
|
132
|
+
scale_data=True,
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
explanation = feature_explainer.explain_instance(
|
|
136
|
+
X_test[0],
|
|
137
|
+
model=classifier,
|
|
138
|
+
)
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
This model-agnostic explanation answers: "Which observed training samples have
|
|
142
|
+
the most similar measured attributes?" It is useful when input features have a
|
|
143
|
+
domain meaning that a reviewer can inspect directly. Feature-space proximity
|
|
144
|
+
does not imply that the model used those features in the same way, and it can
|
|
145
|
+
be misleading when irrelevant, redundant, or high-dimensional inputs dominate
|
|
146
|
+
the distance.
|
|
147
|
+
|
|
148
|
+
The returned neighbors retain their original feature values, labels, indexes,
|
|
149
|
+
and optional metadata. Correspondence then measures how strongly their labels
|
|
150
|
+
agree with the model prediction; it does not measure feature importance.
|
|
151
|
+
|
|
123
152
|
### Correspondence Metric
|
|
124
153
|
|
|
125
154
|
Quantifies agreement between prediction and retrieved neighbors using inverse-cubed distance weighting:
|
|
126
155
|
|
|
127
|
-
```
|
|
156
|
+
```text
|
|
128
157
|
w(c) = sum[ 1 / (distance + 1)^3 ] for neighbors with class c
|
|
129
158
|
Correspondence = w(predicted_class) / sum( w(all_classes) )
|
|
130
159
|
```
|
|
@@ -132,6 +161,7 @@ Correspondence = w(predicted_class) / sum( w(all_classes) )
|
|
|
132
161
|
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
162
|
|
|
134
163
|
**Example Interpretation Thresholds** (domain-dependent, not universal standards):
|
|
164
|
+
|
|
135
165
|
- **High (≥85%)**: Strong agreement with training precedent
|
|
136
166
|
- **Medium (70-85%)**: Moderate agreement
|
|
137
167
|
- **Low (<70%)**: Weak agreement, prediction may be uncertain
|
|
@@ -144,6 +174,91 @@ The `+1` offset in the denominator prevents division by zero when a test sample
|
|
|
144
174
|
- **`ball_tree`**: Better for high-dimensional data
|
|
145
175
|
- **`brute`**: Exact search for small datasets (<10k samples)
|
|
146
176
|
|
|
177
|
+
### Activation-Based Similarity (Neural Networks)
|
|
178
|
+
|
|
179
|
+
For sklearn `MLPClassifier` models, you can retrieve neighbors by hidden-layer
|
|
180
|
+
activations instead of raw input features. The resulting cases show consequences
|
|
181
|
+
of the model's learned representation. They do not expose the model's complete
|
|
182
|
+
internal reasoning.
|
|
183
|
+
|
|
184
|
+
```python
|
|
185
|
+
from sklearn.neural_network import MLPClassifier
|
|
186
|
+
from case_explainer import CaseExplainer, HiddenActivations, Blend
|
|
187
|
+
|
|
188
|
+
mlp = MLPClassifier(hidden_layer_sizes=(64, 32, 16), random_state=42)
|
|
189
|
+
mlp.fit(X_train, y_train)
|
|
190
|
+
|
|
191
|
+
# Last hidden layer, based on Caruana et al. (1999)
|
|
192
|
+
explainer = CaseExplainer(
|
|
193
|
+
X_train, y_train,
|
|
194
|
+
similarity=HiddenActivations(model=mlp),
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
# All hidden layers with position weighting, a library extension
|
|
198
|
+
explainer_deep = CaseExplainer(
|
|
199
|
+
X_train, y_train,
|
|
200
|
+
similarity=HiddenActivations(model=mlp, layer="all_hidden"),
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
# Hybrid: blend features (30%) and activations (70%)
|
|
204
|
+
explainer_hybrid = CaseExplainer(
|
|
205
|
+
X_train, y_train,
|
|
206
|
+
similarity=Blend(HiddenActivations(model=mlp), features=0.3),
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
# Multiclass: weight units using the predicted class's output connections
|
|
210
|
+
explainer_class_weighted = CaseExplainer(
|
|
211
|
+
X_train, y_train,
|
|
212
|
+
similarity=HiddenActivations(
|
|
213
|
+
model=mlp,
|
|
214
|
+
output_weighting="predicted_class",
|
|
215
|
+
),
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
# The construction model is reused for prediction.
|
|
219
|
+
explanation = explainer.explain_instance(X_test[0])
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
If the MLP was trained on transformed inputs, pass its fitted transformer as
|
|
223
|
+
`input_transform`. The explainer applies it both when extracting activations
|
|
224
|
+
and when asking the model for a prediction.
|
|
225
|
+
|
|
226
|
+
The legacy `activation_extractor`, `activation_layer`, `use_output_weights`,
|
|
227
|
+
and `blend_alpha` constructor path, along with the `retrieval=` parameter,
|
|
228
|
+
remains supported but emits `DeprecationWarning`. Prefer `similarity=` with the
|
|
229
|
+
strategy classes (`HiddenActivations`, `CustomActivations`, `TreeLeaf`,
|
|
230
|
+
`ForestProximity`, `Blend`).
|
|
231
|
+
|
|
232
|
+
For sklearn random forests, use shared-leaf proximity rather than treating
|
|
233
|
+
leaf identifiers as numeric coordinates:
|
|
234
|
+
|
|
235
|
+
```python
|
|
236
|
+
from case_explainer import ForestProximity
|
|
237
|
+
|
|
238
|
+
forest_explainer = CaseExplainer(
|
|
239
|
+
X_train, y_train,
|
|
240
|
+
similarity=ForestProximity(model=forest),
|
|
241
|
+
)
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
See [notebooks/02_breast_cancer_tutorial.ipynb](notebooks/02_breast_cancer_tutorial.ipynb) for a full worked comparison.
|
|
245
|
+
|
|
246
|
+
### Choosing a Retrieval Space
|
|
247
|
+
|
|
248
|
+
| Retrieval space | Meaning of a similar case | Best suited to | Main limitation |
|
|
249
|
+
| --- | --- | --- | --- |
|
|
250
|
+
| Features (default) | Nearby observed input attributes | Model-agnostic review and domain-readable measurements | May not reflect the model's learned notion of similarity |
|
|
251
|
+
| Hidden activations | Nearby learned neural-network representations | Inspecting precedents that the MLP represents similarly | Model-specific and less directly interpretable |
|
|
252
|
+
| Feature/activation hybrid | Nearby under a weighted combination of both spaces | Balancing domain similarity with model representation | The blend weight is an analyst choice that requires validation |
|
|
253
|
+
| Decision-tree leaf | Cases following the same tree path to a leaf | Exact precedent within a fitted decision tree | A leaf may contain fewer than `k` retained cases |
|
|
254
|
+
| Random-forest proximity | Cases sharing leaves across many trees | Model-informed precedent for fitted random forests | Requires comparison with the retained case base at query time |
|
|
255
|
+
|
|
256
|
+
All modes retrieve actual training cases. The retrieval space changes what
|
|
257
|
+
"like samples" means; the explanation and correspondence interfaces remain the
|
|
258
|
+
same. Use feature retrieval when observed attributes define the comparison you
|
|
259
|
+
want to defend. Use model-informed retrieval when the model's internal
|
|
260
|
+
partitioning or representation is the relevant basis for precedent.
|
|
261
|
+
|
|
147
262
|
## Examples
|
|
148
263
|
|
|
149
264
|
See `quickstart.py` for a complete working example:
|
|
@@ -172,6 +287,7 @@ python benchmark.py --help # See all options
|
|
|
172
287
|
```
|
|
173
288
|
|
|
174
289
|
Results (single run on reference hardware):
|
|
290
|
+
|
|
175
291
|
- **Speed**: 14-37 ms per explanation depending on dataset size
|
|
176
292
|
- **Memory**: <1 MB to 131 MB (scales with data size and dimensionality)
|
|
177
293
|
- **Correspondence**: 87-100% neighbor agreement across validated domains
|
|
@@ -196,6 +312,7 @@ python3 -m http.server 8000 --directory docs/_build/html
|
|
|
196
312
|
```
|
|
197
313
|
|
|
198
314
|
The documentation includes:
|
|
315
|
+
|
|
199
316
|
- Complete API reference for all classes and functions
|
|
200
317
|
- Usage examples and code snippets
|
|
201
318
|
- Theory and mathematical foundations
|
|
@@ -211,13 +328,14 @@ The documentation includes:
|
|
|
211
328
|
- **Personal data:** User behavior, preferences, demographics
|
|
212
329
|
|
|
213
330
|
**Before using in production with sensitive data:**
|
|
331
|
+
|
|
214
332
|
1. Implement feature masking for sensitive columns
|
|
215
333
|
2. Consider differential privacy mechanisms
|
|
216
334
|
3. Apply anonymization to metadata
|
|
217
335
|
4. Set up access control and audit logging
|
|
218
336
|
5. Review legal/regulatory requirements (GDPR, HIPAA, etc.)
|
|
219
337
|
|
|
220
|
-
|
|
338
|
+
Privacy-preserving features are not yet available. Use only with non-sensitive data or in controlled research environments.
|
|
221
339
|
|
|
222
340
|
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
341
|
|
|
@@ -229,13 +347,15 @@ Unlike LIME/SHAP which only show feature importance, case-explainer exposes trai
|
|
|
229
347
|
|
|
230
348
|
```python
|
|
231
349
|
explainer = CaseExplainer(
|
|
232
|
-
X_train,
|
|
233
|
-
y_train,
|
|
234
|
-
feature_names=None,
|
|
235
|
-
class_names=None,
|
|
236
|
-
algorithm='kd_tree',
|
|
237
|
-
scale_data=True,
|
|
238
|
-
metadata=None
|
|
350
|
+
X_train, # Training features
|
|
351
|
+
y_train, # Training labels
|
|
352
|
+
feature_names=None, # Optional feature names
|
|
353
|
+
class_names=None, # Optional class names {0: 'cat', 1: 'dog'}
|
|
354
|
+
algorithm='kd_tree', # Indexing strategy
|
|
355
|
+
scale_data=True, # Standardize features
|
|
356
|
+
metadata=None, # Optional provenance data
|
|
357
|
+
# Explicit strategy object for hidden activations, tree leaves, or forests
|
|
358
|
+
retrieval=None,
|
|
239
359
|
)
|
|
240
360
|
```
|
|
241
361
|
|
|
@@ -278,21 +398,25 @@ explanation.plot() # Visualize (bar plot)
|
|
|
278
398
|
## Validated Domains
|
|
279
399
|
|
|
280
400
|
**Hardware Trojan Detection** (56,959 samples, 5 features)
|
|
401
|
+
|
|
281
402
|
- 99.3% average correspondence across indexing methods
|
|
282
403
|
- High neighbor agreement on imbalanced security data
|
|
283
404
|
- 25.7 ms/sample explanation time (single run, reference hardware)
|
|
284
405
|
|
|
285
406
|
**Credit Card Fraud Detection** (284,807 samples, 30 features)
|
|
407
|
+
|
|
286
408
|
- 100% average correspondence (complete agreement with retrieved neighbors)
|
|
287
409
|
- Highly imbalanced dataset (268:1 normal:fraud ratio)
|
|
288
410
|
- 36.4 ms/sample explanation time (single run, reference hardware)
|
|
289
411
|
|
|
290
412
|
**Medical Diagnosis - Breast Cancer** (569 samples, 30 features)
|
|
413
|
+
|
|
291
414
|
- 93.3% average correspondence
|
|
292
415
|
- Correct predictions: 96.2% correspondence vs 47.3% for incorrect predictions
|
|
293
416
|
- 25.9 ms/sample explanation time (single run, reference hardware)
|
|
294
417
|
|
|
295
418
|
**Also Validated On:**
|
|
419
|
+
|
|
296
420
|
- Iris (92.7%), Wine (91.8%), Digits (94.9%), MNIST (87.5%)
|
|
297
421
|
- See `benchmark.py` for full results across 7 datasets
|
|
298
422
|
|
|
@@ -301,6 +425,7 @@ explanation.plot() # Visualize (bar plot)
|
|
|
301
425
|
## When to Use Case-Based Explainability
|
|
302
426
|
|
|
303
427
|
**Case-Explainer is well-suited for scenarios where:**
|
|
428
|
+
|
|
304
429
|
- Domain experts need to verify predictions against known training cases
|
|
305
430
|
- Precedent-based reasoning is valued (medical diagnosis, legal decisions, security analysis)
|
|
306
431
|
- Concrete examples are more intuitive than feature importance scores
|
|
@@ -308,6 +433,7 @@ explanation.plot() # Visualize (bar plot)
|
|
|
308
433
|
- Fast explanation generation is needed for real-time or interactive systems
|
|
309
434
|
|
|
310
435
|
**Alternative approaches (LIME, SHAP) may be preferable when:**
|
|
436
|
+
|
|
311
437
|
- Feature contributions are more relevant than training precedents
|
|
312
438
|
- Training data cannot be exposed due to privacy/security constraints
|
|
313
439
|
- Model debugging requires understanding feature-level behavior
|
|
@@ -315,7 +441,7 @@ explanation.plot() # Visualize (bar plot)
|
|
|
315
441
|
### Comparison with LIME and SHAP
|
|
316
442
|
|
|
317
443
|
| Aspect | Case-Explainer | LIME | SHAP |
|
|
318
|
-
|
|
444
|
+
| -------- | --------------- | ------ | ------ |
|
|
319
445
|
| Explanation type | Training precedents (similar cases) | Local surrogate model (feature importance) | Shapley values (feature importance) |
|
|
320
446
|
| Output | k nearest neighbors + correspondence score | Per-feature importance for one prediction | Per-feature importance (local and global) |
|
|
321
447
|
| Privacy risk | High -- exposes actual training samples | Low -- uses synthetic perturbations | Low -- no sample exposure |
|
|
@@ -327,65 +453,35 @@ explanation.plot() # Visualize (bar plot)
|
|
|
327
453
|
|
|
328
454
|
## Limitations
|
|
329
455
|
|
|
330
|
-
|
|
456
|
+
### Privacy and Security
|
|
457
|
+
|
|
331
458
|
- Exposes actual training samples, which may contain sensitive information
|
|
332
459
|
- Not suitable for sensitive data without additional privacy protection mechanisms
|
|
333
460
|
- Privacy-preserving features are planned for future releases
|
|
334
461
|
|
|
335
|
-
|
|
462
|
+
### Correspondence Metric Limitations
|
|
463
|
+
|
|
336
464
|
- Measures neighbor agreement, not prediction correctness or quality
|
|
337
465
|
- High correspondence can occur with incorrect predictions if training data contains systematic errors
|
|
338
466
|
- Thresholds for "high/medium/low" must be validated per domain
|
|
339
467
|
|
|
340
|
-
|
|
468
|
+
### Performance Benchmark Limitations
|
|
469
|
+
|
|
341
470
|
- Timing and memory results are from single runs on reference hardware
|
|
342
471
|
- No statistical error bars or confidence intervals provided
|
|
343
472
|
- Results may vary significantly on different hardware and with different parameters
|
|
344
473
|
|
|
345
|
-
|
|
474
|
+
### Scalability Limitations
|
|
475
|
+
|
|
346
476
|
- Memory usage scales linearly with training set size
|
|
347
477
|
- Very large datasets (>1M samples) may require approximate nearest neighbor methods (not yet implemented)
|
|
348
478
|
|
|
349
|
-
|
|
479
|
+
### Interpretability Limitations
|
|
480
|
+
|
|
350
481
|
- Assumes users can meaningfully interpret feature values of retrieved neighbors
|
|
351
482
|
- Multi-feature patterns may be difficult to assess without domain expertise
|
|
352
483
|
- High-dimensional data may require dimensionality reduction for effective interpretation
|
|
353
484
|
|
|
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
485
|
## Citation
|
|
390
486
|
|
|
391
487
|
If you use this module in academic work, please cite:
|
|
@@ -408,6 +504,7 @@ MIT License - see LICENSE file for details.
|
|
|
408
504
|
Contributions welcome! Core functionality and release infrastructure are complete.
|
|
409
505
|
|
|
410
506
|
**Priority areas:**
|
|
507
|
+
|
|
411
508
|
- Additional distance metrics (Manhattan, Cosine)
|
|
412
509
|
- Approximate nearest neighbors (Annoy, FAISS) for large-scale data
|
|
413
510
|
- Radar and parallel coordinate visualizations
|
|
@@ -415,7 +512,7 @@ Contributions welcome! Core functionality and release infrastructure are complet
|
|
|
415
512
|
|
|
416
513
|
## Contact
|
|
417
514
|
|
|
418
|
-
Questions? Issues? Open a GitHub issue or contact pcw@case.edu
|
|
515
|
+
Questions? Issues? Open a GitHub issue or contact <pcw@case.edu>.
|
|
419
516
|
|
|
420
517
|
## Acknowledgments
|
|
421
518
|
|