Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor anomaly score computation #111

Merged
merged 7 commits into from
Apr 10, 2024
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 BREAKING_CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
# Breaking Changes
All the breaking changes will be documented in this file.

### [2.1.0]

#### Changed

- Change the way anomaly scores are normalized by default, instead of using a [0-1] range with a 0.5 threshold, the scores are now normalized to a [0-1000] range with a threshold of 100, the new score represents the distance from the selected threshold, for example, a score of 200 means that the anomaly score is 100% of the threshold above the threshold itself, a score of 50 means that the anomaly score is 50% of the threshold below. This change is intended to make the scores more interpretable and easier to understand, also it makes the score independent from the min and max
scores in the dataset.

### [2.0.0]

#### Changed
Expand Down
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,18 @@
# Changelog
All notable changes to this project will be documented in this file.

### [2.1.0]

#### Updated

- Change the way anomaly scores are normalized by default, instead of using a [0-1] range with a 0.5 threshold, the scores are now normalized to a [0-1000] range with a threshold of 100, the new score represents the distance from the selected threshold, for example, a score of 200 means that the anomaly score is 100% of the threshold above the threshold itself, a score of 50 means that the anomaly score is 50% of the threshold below.
- Change the default normalization config name for anomaly from `min_max_normalization` to `score_normalization`.

#### Fixed

- Fix the output heatmaps and preditions of anomaly inference tasks not being saved properly when images belonged to
different classes but had the same name.

### [2.0.4]

#### Fixed
Expand Down
12 changes: 6 additions & 6 deletions docs/tutorials/examples/anomaly_detection.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,8 @@ What can be useful to customize are the default callbacks:
```yaml
callbacks:
# Anomalib specific callbacks
min_max_normalization:
_target_: anomalib.utils.callbacks.min_max_normalization.MinMaxNormalizationCallback
score_normalization:
_target_: quadra.utils.anomaly.ThresholdNormalizationCallback
threshold_type: image
post_processing_configuration:
_target_: anomalib.utils.callbacks.post_processing_configuration.PostProcessingConfigurationCallback
Expand All @@ -122,7 +122,7 @@ callbacks:
_target_: quadra.callbacks.anomalib.VisualizerCallback
inputs_are_normalized: true
output_path: anomaly_output
threshold_type: ${callbacks.min_max_normalization.threshold_type}
threshold_type: ${callbacks.score_normalization.threshold_type}
disable: true
plot_only_wrong: false
plot_raw_outputs: false
Expand All @@ -140,13 +140,13 @@ callbacks:

By default lightning batch_size_finder callback is disabled. This callback will automatically try to infer the maximum batch size that can be used for training without running out of memory. We've experimented runtime errors with this callback on some machines due to a Pytorch/CUDNN incompatibility so be careful when using it.

The min_max_normalization callback is used to normalize the anomaly maps to the range [0, 1] such that the threshold will become 0.5.
The score_normalization callback is used to normalize the anomaly maps to the range [0, 1000] such that the threshold will become 100.

The threshold_type can be either "image" or "pixel" and it indicates which threshold to use to normalize the pixel level threshold, if no masks are available for segmentation this should always be "image", otherwise the normalization will use the threshold computed without masks which would result in wrong segmentations.

The post processing configuration allow to specify the method used to compute the threshold, methods and manual metrics are generally specified in the model configuration and should not be changed here.

The visualizer callback is used to produce a visualization of the results on the test data, when the min_max_normalization callback is used the input_are_normalized flag must be set to true and the threshold_type should match the one used for normalization. By default it is disabled as it may take a while to compute, to enable just set `disable: false`.
The visualizer callback is used to produce a visualization of the results on the test data, when the score_normalization callback is used the input_are_normalized flag must be set to true and the threshold_type should match the one used for normalization. By default it is disabled as it may take a while to compute, to enable just set `disable: false`.

In the context where many images are supplied to our model, we may be more interested in restricting the output images that are generated to only the cases where the result is not correct. By default it is disabled, to enable just set `plot_only_wrong: true`.

Expand Down Expand Up @@ -224,7 +224,7 @@ datamodule:
good_number: 9

callbacks:
min_max_normalization:
score_normalization:
threshold_type: "image"

print_config: false
Expand Down
21 changes: 10 additions & 11 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "quadra"
version = "2.0.4"
version = "2.1.0"
description = "Deep Learning experiment orchestration library"
authors = [
"Federico Belotti <[email protected]>",
Expand Down Expand Up @@ -82,6 +82,7 @@ segmentation_models_pytorch = { git = "https://github.com/qubvel/segmentation_mo
anomalib = { git = "https://github.com/orobix/anomalib.git", tag = "v0.7.0+obx.1.3.0" }
xxhash = "~3.2"
torchinfo = "~1.8"
typing_extensions = { version = "4.11.0", python = "<3.10" }

# ONNX dependencies
onnx = { version = "1.15.0", optional = true }
Expand Down
2 changes: 1 addition & 1 deletion quadra/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = "2.0.4"
__version__ = "2.1.0"


def get_version():
Expand Down
2 changes: 1 addition & 1 deletion quadra/callbacks/anomalib.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ class VisualizerCallback(Callback):
Args:
task: either 'segmentation' or 'classification'
output_path: location where the images will be saved.
inputs_are_normalized: whether the input images are normalized (i.e using MinMax callback).
inputs_are_normalized: whether the input images are normalized (like when using MinMax or Treshold callback).
threshold_type: Either 'pixel' or 'image'. If 'pixel', the threshold is computed on the pixel-level.
disable: whether to disable the callback.
plot_only_wrong: whether to plot only the images that are not correctly predicted.
Expand Down
6 changes: 3 additions & 3 deletions quadra/configs/callbacks/default_anomalib.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Anomalib specific callbacks
min_max_normalization:
_target_: anomalib.utils.callbacks.min_max_normalization.MinMaxNormalizationCallback
score_normalization:
_target_: quadra.utils.anomaly.ThresholdNormalizationCallback
threshold_type: image
post_processing_configuration:
_target_: anomalib.utils.callbacks.post_processing_configuration.PostProcessingConfigurationCallback
Expand All @@ -16,7 +16,7 @@ visualizer:
_target_: quadra.callbacks.anomalib.VisualizerCallback
inputs_are_normalized: true
output_path: anomaly_output
threshold_type: ${callbacks.min_max_normalization.threshold_type}
threshold_type: ${callbacks.score_normalization.threshold_type}
disable: true
plot_only_wrong: false
plot_raw_outputs: false
Expand Down
2 changes: 1 addition & 1 deletion quadra/configs/experiment/generic/mnist/anomaly/cfa.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ datamodule:
good_number: 9

callbacks:
min_max_normalization:
score_normalization:
threshold_type: "image"
early_stopping:
patience: 2
Expand Down
2 changes: 1 addition & 1 deletion quadra/configs/experiment/generic/mnist/anomaly/cflow.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ datamodule:
good_number: 9

callbacks:
min_max_normalization:
score_normalization:
threshold_type: "image"
early_stopping:
patience: 2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ datamodule:
good_number: 9

callbacks:
min_max_normalization:
score_normalization:
threshold_type: "image"
early_stopping:
patience: 3
Expand Down
2 changes: 1 addition & 1 deletion quadra/configs/experiment/generic/mnist/anomaly/draem.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ datamodule:
good_number: 9

callbacks:
min_max_normalization:
score_normalization:
threshold_type: "image"
early_stopping:
patience: 20
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ datamodule:
good_number: 9

callbacks:
min_max_normalization:
score_normalization:
threshold_type: "image"
print_config: false

Expand Down
2 changes: 1 addition & 1 deletion quadra/configs/experiment/generic/mnist/anomaly/padim.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ datamodule:
good_number: 9

callbacks:
min_max_normalization:
score_normalization:
threshold_type: "image"

print_config: false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ datamodule:
good_number: 9

callbacks:
min_max_normalization:
score_normalization:
threshold_type: "image"

print_config: false
Expand Down
2 changes: 1 addition & 1 deletion quadra/configs/experiment/generic/mvtec/anomaly/cfa.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ datamodule:
category: bottle

callbacks:
min_max_normalization:
score_normalization:
threshold_type: "pixel"
early_stopping:
patience: 2
Expand Down
2 changes: 1 addition & 1 deletion quadra/configs/experiment/generic/mvtec/anomaly/cflow.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ datamodule:
category: bottle

callbacks:
min_max_normalization:
score_normalization:
threshold_type: "pixel"
early_stopping:
patience: 2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ datamodule:
category: bottle

callbacks:
min_max_normalization:
score_normalization:
threshold_type: "pixel"
early_stopping:
patience: 3
Expand Down
2 changes: 1 addition & 1 deletion quadra/configs/experiment/generic/mvtec/anomaly/draem.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ datamodule:
category: bottle

callbacks:
min_max_normalization:
score_normalization:
threshold_type: "pixel"
early_stopping:
patience: 20
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ datamodule:
category: hazelnut

callbacks:
min_max_normalization:
score_normalization:
threshold_type: "pixel"

print_config: false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ datamodule:
category: bottle

callbacks:
min_max_normalization:
score_normalization:
threshold_type: "pixel"
print_config: false

Expand Down
2 changes: 1 addition & 1 deletion quadra/configs/experiment/generic/mvtec/anomaly/padim.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ datamodule:
category: bottle

callbacks:
min_max_normalization:
score_normalization:
threshold_type: "pixel"

print_config: false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ datamodule:
category: bottle

callbacks:
min_max_normalization:
score_normalization:
threshold_type: "pixel"

print_config: false
Expand Down
Loading
Loading