Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ jobs:
python -m tiny_anomaly_lab --output ci_output
test -f ci_output/report.html
test -f ci_output/model_card.md
test -f ci_output/scores.csv
test -f ci_output/flagged_rows.csv
- name: Run the Mahalanobis detector demo
run: |
python -m tiny_anomaly_lab --detector mahalanobis --output ci_output_mah
test -f ci_output_mah/report.html
test -f ci_output_mah/flagged_rows.csv

- name: Upload artifacts
if: always()
Expand Down
76 changes: 62 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ An explainable anomaly-detection workbench for small time-series datasets.

It runs one leakage-safe experiment on bundled data and writes a reproducible
interactive report. The lab shows feature pipelines, evaluation without leakage,
model cards and interactive visualization.
model cards, per-feature contributions and interactive visualization.

## Scope

Expand All @@ -28,17 +28,18 @@ secret or network call is needed for the demo or for the tests.
| `data.py` | Loads the bundled CSV and validates the schema. |
| `features.py` | Builds causal rolling and lag features. |
| `split.py` | Splits the feature frame by time only. |
| `models.py` | Holds the detector registry and the scorers. |
| `models.py` | Holds the detector registry, scorers and contributions. |
| `evaluate.py` | Computes ranking and threshold metrics. |
| `export.py` | Writes scores and flagged rows to CSV. |
| `model_card.py` | Renders a Markdown model card. |
| `report.py` | Writes a self-contained Plotly HTML report. |
| `experiment.py` | Runs one experiment from start to finish. |
| `__main__.py` | Exposes the command line interface. |

The experiment pulls these modules into one pipeline. The data step loads the
CSV. The feature step adds causal rows. The split step cuts by time. The model
step fits the detector. The evaluate step scores and flags rows. The report step
writes the artifacts.
step fits the detector and the contribution method. The evaluate step scores
and flags rows. The report and export steps write the artifacts.

## Leakage-safety model

Expand Down Expand Up @@ -87,22 +88,47 @@ Or call the package as a module.
python -m tiny_anomaly_lab --output output
```

The command writes `output/report.html` and `output/model_card.md`. Open the
report in a web browser. No server and no network are needed.
The command writes `output/report.html`, `output/model_card.md`,
`output/scores.csv` and `output/flagged_rows.csv`. Open the report in a web
browser. No server and no network are needed.

## Detectors

Two detectors ship with the lab.
Three detectors ship with the lab.

- `isolation_forest` wraps the scikit-learn Isolation Forest.
- `zscore_rule` scores the largest standardised residual.
- `mahalanobis` scores the correlation-aware Mahalanobis distance.

Pick the detector with a flag.

```bash
tiny-anomaly-lab --detector zscore_rule --output output
tiny-anomaly-lab --detector mahalanobis --output output
```

## Local feature contribution

Each detector can attribute its row score to the input features. The lab uses
this in two places: a contribution panel in the report and a `top_feature`
column in the flagged-rows CSV.

- `zscore_rule`: contribution is the absolute standardised residual. The
largest value marks the feature that drove the score.
- `mahalanobis`: contribution is a signed exact split of the squared distance.
Row contributions sum to the squared score. A negative value shows a feature
that offsets the distance through correlation.
- `isolation_forest`: no additive decomposition ships with the lab. The report
omits the contribution panel for this detector.

## CSV export

Two CSV files sit next to the report.

- `scores.csv` holds every feature-frame row with its score, flag and a
`contrib_` column per feature.
- `flagged_rows.csv` holds the flagged evaluation rows with the raw value
columns, the score, the threshold and the dominant contributor.

## Configuration

| Flag | Default | Meaning |
Expand Down Expand Up @@ -139,6 +165,8 @@ ROC AUC: 0.7082 Average precision: 0.3970
Flagged 9 rows in evaluation (TP=3, FP=6).
Report: output\report.html
Model card: output\model_card.md
Scores: output\scores.csv
Flagged rows: output\flagged_rows.csv
```

This output comes from the z-score rule run.
Expand All @@ -149,11 +177,22 @@ ROC AUC: 0.7151 Average precision: 0.5175
Flagged 4 rows in evaluation (TP=3, FP=1).
```

This output comes from the Mahalanobis run.

```text
Detector: mahalanobis
ROC AUC: 0.6938 Average precision: 0.4756
Flagged 6 rows in evaluation (TP=3, FP=3).
```

A committed sample lives under `examples/sample_run/`. Open
`examples/sample_run/report.html` to view the interactive figure.
`examples/sample_run/report.html` to view the interactive figure. The
`examples/sample_run_mahalanobis/` folder holds the same artifacts for the
Mahalanobis detector, including a contribution panel and signed contributions
in `flagged_rows.csv`.

The model card records the detector, the data windows, the leakage controls, the
metrics, the intended use and the limitations.
metrics, the per-feature contribution method, the intended use and the limitations.

## Tests

Expand All @@ -170,14 +209,18 @@ ruff check .
```

The suite covers data loading, causal features, the split, the metrics, the
detectors, the experiment, the model card and the report.
detectors, the per-feature contributions, the CSV export, the experiment, the
model card and the report.

## Limitations

The bundled dataset is synthetic and small. Results are illustrative. Isolation
Forest scores shift when the random state or the scikit-learn version changes.
Causal rolling features lag true change points by the window length. The
detector assumes the calibration window is close to normal operation.
detector assumes the calibration window is close to normal operation. The
Mahalanobis covariance uses a shrinkage estimate that trades bias for stability
on small windows, and its signed contributions can hide a feature behind a
correlated partner.

## Project layout

Expand All @@ -194,10 +237,15 @@ examples/ Committed sample artifacts.

Later releases stay independent of this one.

Done in this release:

- Add a multivariate detector beside the two current scorers.
- Add a stream evaluation that replays rows one at a time.
- Add local feature contribution for the z-score rule.
- Add local feature contribution for the z-score rule and the new detector.
- Add CSV export of the flagged rows and the scores.

Still open:

- Add a stream evaluation that replays rows one at a time.
- Add a container image for a fully reproducible run.

## License
Expand Down
10 changes: 10 additions & 0 deletions examples/sample_run/flagged_rows.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
timestamp,temperature,pressure,is_anomaly,score,threshold,top_feature,top_contribution
2024-05-08T23:00:00.000000,20.6558,100.7938,0,0.009341502065532858,-1.973247953923618e-17,temperature_resid,0.0
2024-05-11T22:00:00.000000,17.4403,102.5557,1,0.05595914490488485,-1.973247953923618e-17,temperature_resid,0.0
2024-05-11T23:00:00.000000,18.0048,98.5259,1,0.06060271102137793,-1.973247953923618e-17,temperature_resid,0.0
2024-05-12T00:00:00.000000,19.062,102.5169,1,0.014676161592953041,-1.973247953923618e-17,temperature_resid,0.0
2024-05-12T21:00:00.000000,15.7843,100.8118,0,0.03643460189011305,-1.973247953923618e-17,temperature_resid,0.0
2024-05-12T22:00:00.000000,17.0782,100.4592,0,0.025249986865079732,-1.973247953923618e-17,temperature_resid,0.0
2024-05-12T23:00:00.000000,17.6438,100.8774,0,0.005199350558301674,-1.973247953923618e-17,temperature_resid,0.0
2024-05-13T17:00:00.000000,14.0389,99.96,0,0.03554997145410932,-1.973247953923618e-17,temperature_resid,0.0
2024-05-13T18:00:00.000000,14.735,100.764,0,0.013833939210193269,-1.973247953923618e-17,temperature_resid,0.0
7 changes: 6 additions & 1 deletion examples/sample_run/model_card.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Model card: isolation_forest

Generated: 2026-07-28 UTC.
Generated: 2026-07-29 UTC.

## Overview

Expand Down Expand Up @@ -54,6 +54,10 @@ Derived features (8): temperature_resid, temperature_z, temperature_lag_1, tempe
| true_positives | 3 |
| false_positives | 6 |

## Local feature contribution

No native additive decomposition ships with the lab. The contribution panel is omitted for this detector.

## Intended use

Use this card to reproduce a leakage-safe anomaly experiment on small time-series datasets. Treat the output as a teaching and review artifact, not as a production control.
Expand All @@ -64,3 +68,4 @@ Use this card to reproduce a leakage-safe anomaly experiment on small time-serie
- Isolation Forest scores shift when the random state or scikit-learn version changes.
- Causal rolling features lag true change points by the window length.
- The detector assumes the calibration window is close to normal operation.
- Mahalanobis contributions are signed; correlated features can offset each other.
2 changes: 1 addition & 1 deletion examples/sample_run/report.html

Large diffs are not rendered by default.

Loading
Loading