Fast and Memory-efficient Routines for AUROC/AUPR/Pixel-AUPRO
Project description
ADEval: Fast and Memory-efficient Routines for AUROC/AUPR/Pixel-AUPRO
via Iterative-Accumulating Algorithm with Optional CUDA Acceleration
Requirement
-
CPython 3.8 or above is recommanded, CPython 3.6 should be compatible but not tested
-
Dependent packages
Pillow
opencv-python # for ground-truth mask processing and PRO's CCA
numpy
torch # Optional, for CUDA acceleration
- Optional dependent packages for comparing with reference implementation
scikit-learn
scipy
bisect
Commandline Usage
- Quick Start
# example 1: evaluate result of object 'audiojack' from Real-IAD under Multi-view UIAD setting
python3 -m adeval --sample_key_pat "([a-zA-Z][a-zA-Z0-9_]*_[0-9]{4}_[A-Z][A-Z_]*[A-Z])_C[0-9]_" real_iad-audiojack-Mv_UIAD.pkl
# example 2: evaluate 4 results of object 'audiojack' from Real-IAD under FUAD settings (i.e. NR = 0.0, 0.1, 0.2, 0.4)
python3 -m adeval --sample_key_pat "([a-zA-Z][a-zA-Z0-9_]*_[0-9]{4}_[A-Z][A-Z_]*[A-Z])_C[0-9]_" \
real_iad-audiojack-FUIAD0.pkl \
-a real_iad-audiojack-FUIAD1.pkl \
-a real_iad-audiojack-FUIAD2.pkl \
-a real_iad-audiojack-FUIAD4.pkl
- Detailed Description of Arguments
usage: python3 -m adeval [-h] [--remove_prefix REMOVE_PREFIX] [--add_prefix ADD_PREFIX] [--sample_key_pat SAMPLE_KEY_PAT] [--expected_views_per_sample EXPECTED_VIEWS_PER_SAMPLE] [-a MORE_ANOMAP] anomap
positional arguments:
anomap path to a pickle of a dict[str, tuple[ndarray, float, str | None]], whose key is path to image
of dataset, and values are predicted anomap, predicted image-level score and path to the ground
truth anomaly mask respectively
optional arguments:
-h, --help show this help message and exit
--remove_prefix REMOVE_PREFIX
remove prefix from path to image & mask first
--add_prefix ADD_PREFIX
add another prefix to path to image & mask
--evaluate_size EVALUATE_SIZE
calculate metrics at specific size rather than original size of images, can be [size] (a single integer) or a [w,h] (a tuple of integers)
--sample_key_pat SAMPLE_KEY_PAT
regex to capture the sample id from image path, for evaluating sample-level metrics
--expected_views_per_sample EXPECTED_VIEWS_PER_SAMPLE
if given, script will check if each sample has the expected views, and raise error if not
-a MORE_ANOMAP, --more_anomap MORE_ANOMAP
Here is a code snippet to construct anomap .pkl
file that can be passed to ADEval commandline tool
import numpy as np
import pickle
anomaps = {}
for image_path, mask_path in test_dataset:
assert isinstance(image_path, str)
assert mask_path is None or isinstance(mask_path, str)
img = load_image(image_path)
anomap, image_score = inference(img)
assert isinstance(image_score, float)
assert (isinstance(anomap, np.ndarray) and
anomap.ndim == 2 and
'float' in anomap.dtype.name)
anomaps[image_path] = (anomap, image_score, mask_path)
with open('/path/to/save/anomap.pkl', 'wb') as fp:
pickle.dump(anomaps, fp)
API Usage
Following the code snippet below to utilize the iterative style API, so we do not have to save ano-maps of all images in the test set.
from adeval import EvalAccumulatorCuda
# for cpu-only environment, use the class below and remove all cuda-related
# operation in the codes
from adeval import EvalAccumulator
def get_sample_id(path: str) -> str:
...
# get id string of sample from path of image
def validation(...):
# determin the lower & upper bound of image-level score according to your
# algorithm design, ensure that the scores of 99% of the images fall within
# the given lower & upper bound
score_min, score_max = ...
# also determine the lower & upper bound of values in anomap, or set to
# None to reuse bounds of image-level score
anomap_min, anomap_max = ...
accum = EvalAccumulatorCuda(score_min, score_max, anomap_min, anomap_max)
# the DataLoader of test set
test_loader = ...
image_scores: List[Tuple[str, float, int]] = []
for items in test_loader:
anomap, score = model(items['image'].cuda())
mask: Tensor = items['mask']
label: Tensor = items['label']
path: List[str] = items['path']
mask = mask.cuda(non_blocking=True)
accum.add_anomap_batch(anomap, mask)
accum.add_image(score, label)
image_scores += [(key, img_score.item(), img_label.item())
for key, img_score, img_label in
zip(path, score.reshape(-1), label.reshape(-1))]
sample_pairs = [([score for _, score, _ in views],
[label for _, _, label in views],
[path for path, _, _ in views], key)
for key, views in [(key, list(views)) for key, views in groupby(
sorted(image_scores, key=lambda tup: tup[0]), key=lambda tup: get_sample_id(tup[0])
)]]
accum.add_sample([max(score) for score, _, _, _ in sample_pairs],
[max(label) for _, label, _, _ in sample_pairs])
metrics = accum.summary()
print(metrics)
# contains:
# - sample-level auroc, aupr
# - image-level auroc, aupr
# - pixel-level auroc, aupr, aupro
And please refer to the functional example test.py for more details
For usage of direct APIs (i.e. auroc_and_aupr()
etc.), please following implementation of CLI
Acknowledgement
The team of Real-IAD dataset has contributed numerous invaluable insights to this project.
The reference implementations are from repos AnomalyDetection-SoftPatch and open-iad:
metrics.py
: reference of AUROC & AUPR based onscikit-learn
package from AnomalyDetection-SoftPatchau_pro
: reference of AUPRO from open-iad
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file adeval-1.1.0.tar.gz
.
File metadata
- Download URL: adeval-1.1.0.tar.gz
- Upload date:
- Size: 20.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.0.0 CPython/3.9.16
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | b36aadc7ebd96a0b49b430d6e995eeec6a1f79f240825db768ff214e1f93dcca |
|
MD5 | f3b4b25e88d8959b0be0c5f4a18e746f |
|
BLAKE2b-256 | c4d54b016d26a61279d468a4b2f12e73b717cfabb86df21c4bcfb82da190d6ec |
File details
Details for the file ADEval-1.1.0-py3-none-any.whl
.
File metadata
- Download URL: ADEval-1.1.0-py3-none-any.whl
- Upload date:
- Size: 26.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.0.0 CPython/3.9.16
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 125caf991037a668a1f072f7e99c81b6bdf86dc8c30cf1699c731d4b79e0bd6e |
|
MD5 | 41a27281f630b0d734f94885e036694b |
|
BLAKE2b-256 | 9d6456eb78b69199feb143633a21a4f585272616ba739e549e45715e13acd363 |