openvinotoolkit / anomalib

An anomaly detection library comprising state-of-the-art algorithms and features such as experiment management, hyper-parameter optimization, and edge inference.
https://anomalib.readthedocs.io/en/latest/
Apache License 2.0
3.82k stars 679 forks source link

[Bug]: v1: Default normalization method on certain datasets is not valid #1584

Closed willyfh closed 10 months ago

willyfh commented 10 months ago

Describe the bug

When attempting to train via CLI using the default normalization method on certain datasets (btech, kolektor, folder, mvtech_3d, folder_3d), the following error occurs:

'IMAGENET' is not a valid InputNormalizationMethod 

Dataset

Other (please specify in the text field below)

Model

PatchCore

Steps to reproduce the behavior

After installing the anomalib v1 version, try executing the following command:

anomalib train --model Patchcore --data anomalib.data.Kolektor

OS information

OS information:

Expected behavior

the default normalization method should be a valid InputNormalizationMethod

Screenshots

No response

Pip/GitHub

GitHub

What version/branch did you use?

v1

Configuration YAML

-

Logs

Could not find wandb. To use this feature, ensure that you have wandb installed.
Could not find openvino. To use this feature, ensure that you have openvino installed.
OpenVINO is not installed. Please install OpenVINO to use OpenVINOInferencer.
Could not find openvino. To use this feature, ensure that you have openvino installed.
Could not find wandb. To use this feature, ensure that you have wandb installed.
Could not find comet_ml. To use this feature, ensure that you have comet_ml installed.
Could not find torch. To use this feature, ensure that you have torch installed.
2024-01-08 01:47:03,229 - anomalib.utils.exceptions.imports - WARNING - Could not find wandb. To use this feature, ensure that you have wandb installed.
[01/08/24 01:47:03] WARNING  Could not find wandb. To use this feature, ensure that you have wandb installed.                                                                                 imports.py:25
2024-01-08 01:47:03,233 - anomalib.utils.exceptions.imports - WARNING - Could not find comet_ml. To use this feature, ensure that you have comet_ml installed.
                    WARNING  Could not find comet_ml. To use this feature, ensure that you have comet_ml installed.                                                                           imports.py:25
2024-01-08 01:47:03,366 - anomalib.cli.utils.openvino - INFO - OpenVINO is possibly not installed in the environment. Skipping adding it to parser.
                    INFO     OpenVINO is possibly not installed in the environment. Skipping adding it to parser.                                                                            openvino.py:32
[01/08/24 01:47:03] INFO     OpenVINO is possibly not installed in the environment. Skipping adding it to parser.                                                                            openvino.py:32
Seed set to 2071767861
2024-01-08 01:47:03,863 - anomalib.utils.config - WARNING - Anomalib currently does not support multi-gpu training. Setting devices to 1.
                    WARNING  Anomalib currently does not support multi-gpu training. Setting devices to 1.                                                                                    config.py:239
                    WARNING  Anomalib currently does not support multi-gpu training. Setting devices to 1.                                                                                    config.py:239
2024-01-08 01:47:03,866 - anomalib.utils.config - INFO -  Setting model input size (256, 256) to dataset size (256, 256).
                    INFO      Setting model input size (256, 256) to dataset size (256, 256).                                                                                                 config.py:180
                    INFO      Setting model input size (256, 256) to dataset size (256, 256).                                                                                                 config.py:180
2024-01-08 01:47:03,868 - anomalib.utils.config - INFO - Project path set to results/patchcore/kolektor
                    INFO     Project path set to results/patchcore/kolektor                                                                                                                   config.py:116
                    INFO     Project path set to results/patchcore/kolektor                                                                                                                   config.py:116
2024-01-08 01:47:03,934 - anomalib.models.components.base.anomaly_module - INFO - Initializing Patchcore model.
                    INFO     Initializing Patchcore model.                                                                                                                             anomaly_module.py:36
                    INFO     Initializing Patchcore model.                                                                                                                             anomaly_module.py:36
2024-01-08 01:47:03,937 - anomalib.models.components.feature_extractors.timm - WARNING - FeatureExtractor is deprecated. Use TimmFeatureExtractor instead. Both FeatureExtractor and TimmFeatureExtractor will be removed in a future release.
                    WARNING  FeatureExtractor is deprecated. Use TimmFeatureExtractor instead. Both FeatureExtractor and TimmFeatureExtractor will be removed in a future release.              timm.py:137
                    WARNING  FeatureExtractor is deprecated. Use TimmFeatureExtractor instead. Both FeatureExtractor and TimmFeatureExtractor will be removed in a future release.              timm.py:137
2024-01-08 01:47:05,793 - timm.models.helpers - INFO - Loading pretrained weights from url (https://github.com/rwightman/pytorch-image-models/releases/download/v0.1-weights/wide_resnet50_racm-8234f177.pth)
[01/08/24 01:47:05] INFO     Loading pretrained weights from url (https://github.com/rwightman/pytorch-image-models/releases/download/v0.1-weights/wide_resnet50_racm-8234f177.pth)          helpers.py:247
[01/08/24 01:47:05] INFO     Loading pretrained weights from url (https://github.com/rwightman/pytorch-image-models/releases/download/v0.1-weights/wide_resnet50_racm-8234f177.pth)          helpers.py:247
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ /home/willy/anaconda3/envs/anomalib_dev/bin/anomalib:8 in <module>                               │
│                                                                                                  │
│   5 from anomalib.cli.cli import main                                                            │
│   6 if __name__ == '__main__':                                                                   │
│   7 │   sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])                         │
│ ❱ 8 │   sys.exit(main())                                                                         │
│   9                                                                                              │
│                                                                                                  │
│ /home/willy/Desktop/anomalib/anomalib/src/anomalib/cli/cli.py:330 in main                        │
│                                                                                                  │
│   327 def main() -> None:                                                                        │
│   328 │   """Trainer via Anomalib CLI."""                                                        │
│   329 │   configure_logger()                                                                     │
│ ❱ 330 │   AnomalibCLI()                                                                          │
│   331                                                                                            │
│   332                                                                                            │
│   333 if __name__ == "__main__":                                                                 │
│                                                                                                  │
│ /home/willy/Desktop/anomalib/anomalib/src/anomalib/cli/cli.py:61 in __init__                     │
│                                                                                                  │
│    58 │   │   run: bool = True,                                                                  │
│    59 │   │   auto_configure_optimizers: bool = True,                                            │
│    60 │   ) -> None:                                                                             │
│ ❱  61 │   │   super().__init__(                                                                  │
│    62 │   │   │   AnomalyModule,                                                                 │
│    63 │   │   │   AnomalibDataModule,                                                            │
│    64 │   │   │   save_config_callback,                                                          │
│                                                                                                  │
│ /home/willy/anaconda3/envs/anomalib_dev/lib/python3.10/site-packages/lightning/pytorch/cli.py:38 │
│ 3 in __init__                                                                                    │
│                                                                                                  │
│   380 │   │   self._set_seed()                                                                   │
│   381 │   │                                                                                      │
│   382 │   │   self.before_instantiate_classes()                                                  │
│ ❱ 383 │   │   self.instantiate_classes()                                                         │
│   384 │   │                                                                                      │
│   385 │   │   if self.subcommand is not None:                                                    │
│   386 │   │   │   self._run_subcommand(self.subcommand)                                          │
│                                                                                                  │
│ /home/willy/Desktop/anomalib/anomalib/src/anomalib/cli/cli.py:219 in instantiate_classes         │
│                                                                                                  │
│   216 │   │   │   self._add_configure_optimizers_method_to_model(self.subcommand)                │
│   217 │   │   │   self.engine = self.instantiate_engine()                                        │
│   218 │   │   else:                                                                              │
│ ❱ 219 │   │   │   self.config_init = self.parser.instantiate_classes(self.config)                │
│   220 │   │   │   subcommand = self.config["subcommand"]                                         │
│   221 │   │   │   if subcommand in ("train", "export"):                                          │
│   222 │   │   │   │   self.engine = self.instantiate_engine()                                    │
│                                                                                                  │
│ /home/willy/anaconda3/envs/anomalib_dev/lib/python3.10/site-packages/jsonargparse/_deprecated.py │
│ :140 in patched_instantiate_classes                                                              │
│                                                                                                  │
│   137 │   ) -> Union[Namespace, Dict[str, Any]]:                                                 │
│   138 │   │   if isinstance(cfg, dict):                                                          │
│   139 │   │   │   cfg = self._apply_actions(cfg)                                                 │
│ ❱ 140 │   │   cfg = self._unpatched_instantiate_classes(cfg, **kwargs)                           │
│   141 │   │   return cfg.as_dict() if self._parse_as_dict else cfg                               │
│   142 │                                                                                          │
│   143 │   ArgumentParser._unpatched_instantiate_classes = ArgumentParser.instantiate_classes     │
│                                                                                                  │
│ /home/willy/anaconda3/envs/anomalib_dev/lib/python3.10/site-packages/jsonargparse/_core.py:1182  │
│ in instantiate_classes                                                                           │
│                                                                                                  │
│   1179 │   │                                                                                     │
│   1180 │   │   subcommand, subparser = _ActionSubCommands.get_subcommand(self, cfg, fail_no_sub  │
│   1181 │   │   if subcommand is not None and subparser is not None:                              │
│ ❱ 1182 │   │   │   cfg[subcommand] = subparser.instantiate_classes(cfg[subcommand], instantiate  │
│   1183 │   │                                                                                     │
│   1184 │   │   return cfg                                                                        │
│   1185                                                                                           │
│                                                                                                  │
│ /home/willy/anaconda3/envs/anomalib_dev/lib/python3.10/site-packages/jsonargparse/_deprecated.py │
│ :140 in patched_instantiate_classes                                                              │
│                                                                                                  │
│   137 │   ) -> Union[Namespace, Dict[str, Any]]:                                                 │
│   138 │   │   if isinstance(cfg, dict):                                                          │
│   139 │   │   │   cfg = self._apply_actions(cfg)                                                 │
│ ❱ 140 │   │   cfg = self._unpatched_instantiate_classes(cfg, **kwargs)                           │
│   141 │   │   return cfg.as_dict() if self._parse_as_dict else cfg                               │
│   142 │                                                                                          │
│   143 │   ArgumentParser._unpatched_instantiate_classes = ArgumentParser.instantiate_classes     │
│                                                                                                  │
│ /home/willy/anaconda3/envs/anomalib_dev/lib/python3.10/site-packages/jsonargparse/_core.py:1173  │
│ in instantiate_classes                                                                           │
│                                                                                                  │
│   1170 │   │   │   │   │   │   │   nested_links=ActionLink.get_nested_links(self, component),    │
│   1171 │   │   │   │   │   │   │   class_instantiators=self._get_instantiators(),                │
│   1172 │   │   │   │   │   │   ):                                                                │
│ ❱ 1173 │   │   │   │   │   │   │   parent[key] = component.instantiate_classes(value)            │
│   1174 │   │   │   else:                                                                         │
│   1175 │   │   │   │   with parser_context(load_value_mode=self.parser_mode, class_instantiator  │
│   1176 │   │   │   │   │   component.instantiate_class(component, cfg)                           │
│                                                                                                  │
│ /home/willy/anaconda3/envs/anomalib_dev/lib/python3.10/site-packages/jsonargparse/_typehints.py: │
│ 526 in instantiate_classes                                                                       │
│                                                                                                  │
│    523 │   │   │   value = [value]                                                               │
│    524 │   │   sub_add_kwargs = getattr(self, "sub_add_kwargs", {})                              │
│    525 │   │   for num, val in enumerate(value):                                                 │
│ ❱  526 │   │   │   value[num] = adapt_typehints(val, self._typehint, instantiate_classes=True,   │
│    527 │   │   return value if islist else value[0]                                              │
│    528 │                                                                                         │
│    529 │   @staticmethod                                                                         │
│                                                                                                  │
│ /home/willy/anaconda3/envs/anomalib_dev/lib/python3.10/site-packages/jsonargparse/_typehints.py: │
│ 882 in adapt_typehints                                                                           │
│                                                                                                  │
│    879 │   │   │   │   │   f'Import path {val["class_path"]} does not correspond to a subclass   │
│    880 │   │   │   │   )                                                                         │
│    881 │   │   │   val["class_path"] = get_import_path(val_class)                                │
│ ❱  882 │   │   │   val = adapt_class_type(val, serialize, instantiate_classes, sub_add_kwargs,   │
│    883 │   │   except (ImportError, AttributeError, AssertionError, ArgumentError) as ex:        │
│    884 │   │   │   class_path = val if isinstance(val, str) else val["class_path"]               │
│    885 │   │   │   error = indent_text(str(ex))                                                  │
│                                                                                                  │
│ /home/willy/anaconda3/envs/anomalib_dev/lib/python3.10/site-packages/jsonargparse/_typehints.py: │
│ 1100 in adapt_class_type                                                                         │
│                                                                                                  │
│   1097 │   │   │   │   return instantiator_fn(val_class, *args, **{**init_args, **dict_kwargs})  │
│   1098 │   │   │                                                                                 │
│   1099 │   │   │   return partial_instance                                                       │
│ ❱ 1100 │   │   return instantiator_fn(val_class, **{**init_args, **dict_kwargs})                 │
│   1101 │                                                                                         │
│   1102 │   prev_init_args = prev_val.get("init_args") if isinstance(prev_val, Namespace) else N  │
│   1103                                                                                           │
│                                                                                                  │
│ /home/willy/anaconda3/envs/anomalib_dev/lib/python3.10/site-packages/jsonargparse/_common.py:109 │
│ in default_class_instantiator                                                                    │
│                                                                                                  │
│   106                                                                                            │
│   107                                                                                            │
│   108 def default_class_instantiator(class_type: Type[ClassType], *args, **kwargs) -> ClassTyp   │
│ ❱ 109 │   return class_type(*args, **kwargs)                                                     │
│   110                                                                                            │
│   111                                                                                            │
│   112 class ClassInstantiator:                                                                   │
│                                                                                                  │
│ /home/willy/Desktop/anomalib/anomalib/src/anomalib/data/image/kolektor.py:282 in __init__        │
│                                                                                                  │
│   279 │   │   │   config=transform_config_train,                                                 │
│   280 │   │   │   image_size=image_size,                                                         │
│   281 │   │   │   center_crop=center_crop,                                                       │
│ ❱ 282 │   │   │   normalization=InputNormalizationMethod(normalization),                         │
│   283 │   │   )                                                                                  │
│   284 │   │   transform_eval = get_transforms(                                                   │
│   285 │   │   │   config=transform_config_eval,                                                  │
│                                                                                                  │
│ /home/willy/anaconda3/envs/anomalib_dev/lib/python3.10/enum.py:385 in __call__                   │
│                                                                                                  │
│    382 │   │   `type`, if set, will be mixed in as the first base class.                         │
│    383 │   │   """                                                                               │
│    384 │   │   if names is None:  # simple value lookup                                          │
│ ❱  385 │   │   │   return cls.__new__(cls, value)                                                │
│    386 │   │   # otherwise, functional API: we're creating a new Enum type                       │
│    387 │   │   return cls._create_(                                                              │
│    388 │   │   │   │   value,                                                                    │
│                                                                                                  │
│ /home/willy/anaconda3/envs/anomalib_dev/lib/python3.10/enum.py:710 in __new__                    │
│                                                                                                  │
│    707 │   │   │   else:                                                                         │
│    708 │   │   │   │   ve_exc = ValueError("%r is not a valid %s" % (value, cls.__qualname__))   │
│    709 │   │   │   │   if result is None and exc is None:                                        │
│ ❱  710 │   │   │   │   │   raise ve_exc                                                          │
│    711 │   │   │   │   elif exc is None:                                                         │
│    712 │   │   │   │   │   exc = TypeError(                                                      │
│    713 │   │   │   │   │   │   │   'error in %s._missing_: returned %r instead of None or a val  │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
ValueError: 'IMAGENET' is not a valid InputNormalizationMethod

Code of Conduct

willyfh commented 10 months ago

Addressed in #1583