Skip to main content

Subset-contrast unsupervised model selection for anomaly detection

Project description

subselect

Subset-contrast unsupervised model selection for anomaly detection.

Given a pool of trained anomaly-detection models with no ground-truth labels, pick the best one by measuring the contrast between each model's top-ranked points (predicted anomalies) and the rest of the data.

Why

In anomaly detection, practitioners must choose among many models (Isolation Forest, LOF, kNN, OCSVM, ...) with different hyperparameters. The standard way to evaluate models is supervised, using metrics like ROC-AUC that require labelled anomalies. In practice, labelled anomalies are rarely available; if they were, the problem would already be partly solved.

subselect selects a model from a pool without any labels. A good model concentrates real anomalies at the top of its score ranking, so its top subset looks distinct from the rest of the data in feature space; a bad model's top subset looks like ordinary data. Measuring that contrast with a density or distance metric gives an unsupervised ranking that correlates with the hidden supervised ROC-AUC ranking.

Install

pip install subselect

Requires Python 3.10+ with numpy, scipy, pandas, and scikit-learn.

Quickstart

import subselect as ss

# scores: (n_samples, n_models) anomaly score per (sample, model); higher = more anomalous
# X:      (n_samples, n_features) original feature matrix
# model_names: length-n_models identifiers aligned with the columns of scores
best = ss.Evaluator().select(scores=scores, X=X, model_names=model_names)
print("Picked:", model_names[best])

Evaluator() selects with a single default metric (Mahalanobis distance). Pass a list of metrics and ensemble=True to combine several and add their rank-aggregated ensemble (the strongest configuration in our benchmarks):

ev = ss.Evaluator(metrics=["mahalanobis_distance", "gmm_likelihood"], ensemble=True)
results = ev.evaluate(scores, X, model_names)
print(results.selected_per_metric)   # pick per metric, plus 'ensemble'

Shipped metrics

Five contrast metrics across the density and distance families:

name family direction
mahalanobis_distance distance, global covariance higher = better
knn_avg_distance distance, local higher = better
lof_score local density (LOF) higher = better
kde_log_likelihood density, non-parametric lower = better
gmm_likelihood density, parametric lower = better

ss.list_metrics() lists them and ss.metric_sets["core"] is all five.

Custom contrast metric

Three ways to add your own:

# 1. Subclass - most flexible
class MyMetric(ss.ContrastMetric):
    direction = +1                          # higher value -> better model
    kind = "per-point"

    def fit_reference(self, X_ref):         # fit on the complement (the reference)
        return self

    def score_subset(self, X_sub):
        return {"mean": ..., "std": ..., "median": ...}

# 2. Decorator - one function
@ss.contrast_metric(direction=+1, kind="per-point", name="my_metric")
def my_metric(subset_X, reference_X):
    return float(...)

# 3. Inline callable - quickest
ss.Evaluator(metrics=[(my_metric_callable, +1)]).select(scores, X, model_names)

Citation

See CITATION.cff. A paper describing the method is forthcoming.

License

MIT. See LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

subselect-0.0.1.tar.gz (3.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

subselect-0.0.1-py3-none-any.whl (4.4 kB view details)

Uploaded Python 3

File details

Details for the file subselect-0.0.1.tar.gz.

File metadata

  • Download URL: subselect-0.0.1.tar.gz
  • Upload date:
  • Size: 3.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for subselect-0.0.1.tar.gz
Algorithm Hash digest
SHA256 dba3ec4fe73c153c6ab98dd1a575528d81e75b709b9023296c72b3479627f47f
MD5 910b46448c661d07194c936370b97084
BLAKE2b-256 2b79094e6ab9ef8faebf5878ad4e61441f8eaa8794838933f24be851d814c3d7

See more details on using hashes here.

File details

Details for the file subselect-0.0.1-py3-none-any.whl.

File metadata

  • Download URL: subselect-0.0.1-py3-none-any.whl
  • Upload date:
  • Size: 4.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for subselect-0.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 7d4ee0207a002361f0df0fa5fe399f2f2428a5e0680100ed274f6d81c8f51e6d
MD5 ea0cdd065fa3288296e6f7d18870c3d0
BLAKE2b-256 ae08f248ed44077c089a61e6335c801a017c44618cf486fa31df69149f7e1264

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page