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.69k stars 655 forks source link

Does `_setup_transform()` in `Engine.fit` use the train transforms properly? #2176

Closed CarlosNacher closed 2 months ago

CarlosNacher commented 2 months ago

Discussed in https://github.com/openvinotoolkit/anomalib/discussions/2100

Originally posted by **CarlosNacher** May 31, 2024 Hi, I was looking the `Engine.fit()` method and I realised that maybe we are incorrectly using `eval_transform` for train instead of `train_transform`; or maybe I have misunderstood the code structure. I mean: If you look into the `fit()` method of the `Engine` (`engine.py line 441` ) the method `_setup_transform()` is called. And that method (`line 311` of `engine.py`) does: ``` # get transform if datamodule and datamodule.transform: # a transform passed explicitly to the datamodule takes precedence transform = datamodule.transform ``` And if you go to datamodule (`datamodule.py line 232` in the `transform` property): ``` def transform(self) -> Transform: """Property that returns the user-specified transform for the datamodule, if any. This property is accessed by the engine to set the transform for the model. The eval_transform takes precedence over the train_transform, because the transform that we store in the model is the one that should be used during inference. """ if self._eval_transform: return self._eval_transform if self._train_transform: return self._train_transform return None ``` it seems that even in `fit` method, the `eval_transform` takes precedence over `train_transform`. But if you are fitting, you want `train_transform`, not eval one. Am I misunderstanding anything? Thank you so much in advance!
alexriedel1 commented 2 months ago

Whats happening in _setup_transform is setting the evaluation transform as the models default image transformation method. This is intended because during inference you want to use the eval transform only. The eval transform is stored to the model and saved in the model export file.

During training and validation the images are not transformed by the model transforms, but by the transforms that are defined in the respective datamodules.

samet-akcay commented 2 months ago

In addition to what @alexriedel1 described, i could add the following: if the user does not provide any custom transforms, the datamodule will use the transforms pre-defined by the model. These are the default ones that are reported in their respective papers.

If the user wants to provide custom transforms, the datamodule takes those into account. At the end of the training they will be wrapped within the exported model. The idea behind is that a user should be able to pass a raw image to the inference model without requiring any additional pre-processing stages. All of this will be handled by the inference model.

samet-akcay commented 2 months ago

I'm moving this to Q&A, from which we could continue to discuss.