Skip to main content

Location-aware tensor Mahalanobis anomaly detection

Project description

tensor-md

Location-aware tensor Mahalanobis anomaly detection for tensor-valued CNN patch descriptors. The package contains the reusable tensor detector, its separable covariance estimators, and the MVTec patch data loader. Exploratory notebooks, the official evaluator, and the thesis are kept in the repository but are not required to import the core package.

Install from source

python -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e ".[evaluation,cnn]"

For notebook support, use .[evaluation,cnn,notebooks]. The complete environment is also documented in REPRODUCIBILITY.md and environment.yml.

Public API

from tensor_md import (
    LocationAwareTensorMahalanobisDetector,
    NeighborhoodScoreLocationAwareTensorMahalanobisDetector,
    PatchExtractionConfig,
    extract_cnn_feature_maps,
    load_patch_datasets,
    load_normal_patches,
    load_image_patches,
    make_cnn_feature_extractor,
)

The detector is fitted using normal patches only. It stores a location-specific mean and separable covariance model and produces a scalar score for each test patch. The neighbourhood subclass optionally pools the already-computed scores on the spatial grid.

See examples/general_pipeline_diagnostics.ipynb for a complete directory-only walkthrough that fits the detector and writes train/test diagnostics.

The image loader is not tied to one CNN. Pass any callable (or model exposing predict) through cnn_feature_extractor; it receives a float32 image batch with shape (batch, height, width, 3) and values in [0, 1], and returns one feature-map batch or a list of feature-map batches in (batch, height, width, channels) format. PCA, spatial alignment, fusion, and tensor scoring then use those maps exactly as they do for the built-in adapters. PyTorch models can be wrapped with a small adapter that converts their NCHW output to NHWC.

def my_cnn(batch):
    with torch.no_grad():
        return torch_model(to_nchw(batch)).permute(0, 2, 3, 1)

config = PatchExtractionConfig(
    category="bottle",
    data_root="/path/to/mvtec",
    input_representation="cnn_features",
    cnn_feature_extractor=my_cnn,
)

ResNet50, WideResNet, and YOLO adapters remain available as conveniences; they are not requirements of the tensor detector.

The loader can also use ordinary folders instead of an MVTec category:

config = PatchExtractionConfig(
    category="custom",
    train_image_dir="data/normal_train",
    test_image_dir="data/test",  # subfolders named normal/good are label 0
    input_representation="cnn_features",
    cnn_feature_extractor=extractor,
)
datasets = load_patch_datasets(config)

Training images are all treated as normal. Test images in normal or good subfolders receive label 0; images in other test subfolders receive label 1.

For unsupervised use, no test split is needed:

normal = load_normal_patches(
    PatchExtractionConfig(
        train_image_dir="data/normal_images",
        input_representation="cnn_features",
        cnn_feature_extractor=extractor,
    )
)
detector.fit(normal)

The detector learns only from these normal patches. Later images are scored with load_image_patches(...) and detector.score(...); no labels are required:

other = load_image_patches("data/images_to_check", config)
scores = detector.score(other)

Optional diagnostics can be saved in only the formats a user wants:

detector.save_score_diagnostics(
    scores,
    "outputs/debug",
    grid_shape=(8, 8),
    formats=("npy", "json", "distribution", "heatmaps"),
)

To fit and save both distributions in one call:

detector.fit_and_save_diagnostics(
    normal,
    images_to_check,
    "outputs/debug",
    grid_shape=(8, 8),
)

This creates separate train/ and test/ outputs, including score arrays, histograms, heatmap previews, and TIFF score grids.

Available formats are npy, csv, json, tiff, distribution, and heatmaps. The tiff option writes one floating-point score grid per image; heatmaps writes a visual PNG montage. These files are for inspection only and do not replace the official evaluator.

For convenience, Keras and PyTorch models can be adapted without writing a layout-conversion wrapper:

extractor = make_cnn_feature_extractor(model, framework="pytorch")
config = PatchExtractionConfig(
    category="bottle",
    input_representation="cnn_features",
    cnn_feature_extractor=extractor,
)

Fitted detectors can be saved and restored, including all fitted means, covariance factors, shrinkage state, and score-calibration statistics:

detector.fit(train_patches)
detector.save("models/bottle.pkl")

restored = LocationAwareTensorMahalanobisDetector.load("models/bottle.pkl")
scores = restored.score(test_patches)

Model files use Python pickle and must only be loaded from a trusted source.

The MVTec dataset is not bundled with the package. See REPRODUCIBILITY.md for the expected layout and the official evaluator command. The loader accepts an explicit PatchExtractionConfig(data_root=...) or the MVTEC_DATA_ROOT environment variable.

Release

Build and test a distribution locally:

python -m pip install build twine
python -m build
python -m twine check dist/*

Publish to TestPyPI first, then PyPI:

python -m twine upload --repository testpypi dist/*
python -m twine upload dist/*

Use a PyPI API token through Twine's credential prompt or ~/.pypirc; never commit the token to the repository.

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

tensor_md-0.1.1.tar.gz (47.3 kB view details)

Uploaded Source

Built Distribution

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

tensor_md-0.1.1-py3-none-any.whl (46.0 kB view details)

Uploaded Python 3

File details

Details for the file tensor_md-0.1.1.tar.gz.

File metadata

  • Download URL: tensor_md-0.1.1.tar.gz
  • Upload date:
  • Size: 47.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for tensor_md-0.1.1.tar.gz
Algorithm Hash digest
SHA256 4024aeda8d7866638b562f65fd9cc392d1a2397cc31fd194c3d32e41cd807ba6
MD5 329560aa2369bd70d9e3391adb7f78fb
BLAKE2b-256 8228d2db7e60bb5a61571c5d8d6debc8c1a34ffd384abd6d546a26c0c7496a4c

See more details on using hashes here.

Provenance

The following attestation bundles were made for tensor_md-0.1.1.tar.gz:

Publisher: publish.yml on greinald/tensor-md

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file tensor_md-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: tensor_md-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 46.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for tensor_md-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 fe2803448f81f354b66c3711cc56165c2e5880b21cb21465e7ec3e7b38561e3f
MD5 de20a08b0c2d9473cc9124ae9b20d491
BLAKE2b-256 7c1d1eeb30c9122f6f02b98e46be074296ee5f6d0094ffe45e427b4828229434

See more details on using hashes here.

Provenance

The following attestation bundles were made for tensor_md-0.1.1-py3-none-any.whl:

Publisher: publish.yml on greinald/tensor-md

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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