From 64e871e5f8b8b381065154d24d0dc12870d5fafb Mon Sep 17 00:00:00 2001 From: Sungman Cho Date: Mon, 22 Jan 2024 09:55:24 +0900 Subject: [PATCH 01/10] Fix Hlabel and add medium test case (#2804) * Fix hlabel and add hlabel test cases and fix reg tests * Added missing things * Added missing things * Typo * Reflect review * Reflect comments add label_tree_edges information * Fix precommit * Fix unittest * Fix precommit --- .../classification/metrics/hlabel_accuracy.py | 10 +++++++++- src/otx/core/data/entity/classification.py | 16 ++++++++++++++++ tests/regression/test_regression.py | 19 +++++++++++++++++-- tests/unit/algo/classification/conftest.py | 8 ++++++++ 4 files changed, 50 insertions(+), 3 deletions(-) diff --git a/src/otx/algo/classification/metrics/hlabel_accuracy.py b/src/otx/algo/classification/metrics/hlabel_accuracy.py index 92151c8c8d6..5d3e3d43e68 100644 --- a/src/otx/algo/classification/metrics/hlabel_accuracy.py +++ b/src/otx/algo/classification/metrics/hlabel_accuracy.py @@ -5,7 +5,10 @@ from __future__ import annotations +from typing import Callable, Sequence + import torch +from torch import nn from torchmetrics import Metric from torchmetrics.classification import Accuracy, MultilabelAccuracy @@ -64,6 +67,12 @@ def _metric_to_device(self, metric: Metric, device: str) -> None: metric.to(device) self.flag = True + def _apply(self, fn: Callable, exclude_state: Sequence[str] = "") -> nn.Module: + self.multiclass_head_accuracy = [acc._apply(fn, exclude_state) for acc in self.multiclass_head_accuracy] # noqa: SLF001 + if self.num_multilabel_classes > 0: + self.multilabel_accuracy = self.multilabel_accuracy._apply(fn, exclude_state) # noqa: SLF001 + return self + def update(self, preds: torch.Tensor, target: torch.Tensor) -> None: """Update state with predictions and targets.""" # Split preds into multiclass and multilabel parts @@ -74,7 +83,6 @@ def update(self, preds: torch.Tensor, target: torch.Tensor) -> None: is_all_multiclass_ignored = not multiclass_mask.any() if not is_all_multiclass_ignored: - self._metric_to_device(self.multiclass_head_accuracy[head_idx], preds.device) self.multiclass_head_accuracy[head_idx].update( preds_multiclass[multiclass_mask], target_multiclass[multiclass_mask], diff --git a/src/otx/core/data/entity/classification.py b/src/otx/core/data/entity/classification.py index 4368154d388..20e7252f72f 100644 --- a/src/otx/core/data/entity/classification.py +++ b/src/otx/core/data/entity/classification.py @@ -195,6 +195,9 @@ class HLabelInfo: 'Triangle': 2, 'Non-Rigid': 3, 'Circle': 4 'Lion': 5, 'Panda': 6 } + label_tree_edges: [ + ["Rectangle", "Rigid"], ["Triangle", "Rigid"], ["Circle", "Non-Rigid"], + ] # NOTE, label_tree_edges format could be changed. empty_multiclass_head_indices: [] All of the member variables should be considered for the Model API. @@ -208,6 +211,7 @@ class HLabelInfo: class_to_group_idx: dict[str, tuple[int, int]] all_groups: list[list[str]] label_to_idx: dict[str, int] + label_tree_edges: list[list[str]] empty_multiclass_head_indices: list[int] @classmethod @@ -276,6 +280,17 @@ def put_key_values(src: dict, dst: dict) -> None: put_key_values(single_label_ctoi, class_to_idx) return class_to_idx + # NOTE, this information needs for the correct prediction from Model API side. + # However, need to check the correct format. <- TODO(sungman) + def get_label_tree_edges(dm_label_groups: list[LabelCategories.LabelGroup]) -> list[list[str]]: + """Get label tree edges information. Each edges represent [child, parent].""" + return [ + [label, label_group.name] + for label_group in dm_label_groups + for label in label_group.labels + if len(label_group.labels) > 1 + ] + all_groups = [label_group.labels for label_group in dm_label_categories.label_groups] exclusive_group_info = get_exclusive_group_info(all_groups) @@ -294,6 +309,7 @@ def put_key_values(src: dict, dst: dict) -> None: class_to_group_idx=merged_class_to_idx, all_groups=all_groups, label_to_idx=dm_label_categories._indices, # noqa: SLF001 + label_tree_edges=get_label_tree_edges(dm_label_categories.label_groups), empty_multiclass_head_indices=[], # consider the label removing case ) diff --git a/tests/regression/test_regression.py b/tests/regression/test_regression.py index bc8dc1194fb..c7c144e88b2 100644 --- a/tests/regression/test_regression.py +++ b/tests/regression/test_regression.py @@ -234,10 +234,25 @@ class TestHlabelCls(BaseTest): name=f"hlabel_CUB_small_{idx}", data_root=Path("hlabel_CUB_small") / f"{idx}", data_format="datumaro", - num_classes=3, - extra_overrides={"trainer.max_epochs": "20"}, + num_classes=6, + extra_overrides={ + "trainer.max_epochs": "20", + "model.otx_model.num_multiclass_heads": "3", + }, ) for idx in range(1, 4) + ] + [ + DatasetTestCase( + name=f"hlabel_CUB_medium", + data_root=Path("hlabel_CUB_medium"), + data_format="datumaro", + num_classes=102, + extra_overrides={ + "trainer.max_epochs": "20", + "model.otx_model.num_multiclass_heads": "23", + }, + ) + ] @pytest.mark.parametrize( diff --git a/tests/unit/algo/classification/conftest.py b/tests/unit/algo/classification/conftest.py index a387eba7b23..442d7b84e95 100644 --- a/tests/unit/algo/classification/conftest.py +++ b/tests/unit/algo/classification/conftest.py @@ -46,6 +46,14 @@ def fxt_hlabel_info() -> HLabelInfo: "4": 4, "5": 5, }, + label_tree_edges=[ + ["0", "0"], + ["1", "0"], + ["2", "1"], + ["3", "1"], + ["4", "2"], + ["5", "2"], + ], ) From bb6da254d0f5eb39c07fdabe201080b0e9db2f8d Mon Sep 17 00:00:00 2001 From: Sungman Cho Date: Mon, 22 Jan 2024 13:31:47 +0900 Subject: [PATCH 02/10] Fix hlabel regtest (#2820) --- tests/regression/test_regression.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/regression/test_regression.py b/tests/regression/test_regression.py index c7c144e88b2..5acb903e14f 100644 --- a/tests/regression/test_regression.py +++ b/tests/regression/test_regression.py @@ -238,6 +238,7 @@ class TestHlabelCls(BaseTest): extra_overrides={ "trainer.max_epochs": "20", "model.otx_model.num_multiclass_heads": "3", + "model.otx_model.num_multilabel_classes": "0", }, ) for idx in range(1, 4) @@ -250,6 +251,7 @@ class TestHlabelCls(BaseTest): extra_overrides={ "trainer.max_epochs": "20", "model.otx_model.num_multiclass_heads": "23", + "model.otx_model.num_multilabel_classes": "0", }, ) From 4c5575f3bac8e69e42135d84268e5cc87bbf8769 Mon Sep 17 00:00:00 2001 From: Prokofiev Kirill Date: Mon, 22 Jan 2024 06:49:17 +0100 Subject: [PATCH 03/10] Fix regression tests (#2813) * add raising an error when metric is None * added regression tests for segmentation * minor * fix tests * deterministic=False --- tests/regression/test_regression.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/regression/test_regression.py b/tests/regression/test_regression.py index 5acb903e14f..6575803b37b 100644 --- a/tests/regression/test_regression.py +++ b/tests/regression/test_regression.py @@ -358,13 +358,13 @@ def test_regression( class TestSemanticSegmentation(BaseTest): # Test case parametrization for model MODEL_TEST_CASES = [ # noqa: RUF012 - ModelTestCase(task="semantic_segmentation", name="litehrnet_18"), - ModelTestCase(task="semantic_segmentation", name="litehrnet_s"), - ModelTestCase(task="semantic_segmentation", name="litehrnet_x"), - ModelTestCase(task="semantic_segmentation", name="segnext_b"), - ModelTestCase(task="semantic_segmentation", name="segnext_s"), - ModelTestCase(task="semantic_segmentation", name="segnext_t"), - ModelTestCase(task="semantic_segmentation", name="dino_v2_seg"), + ModelTestCase(task="segmentation", name="litehrnet_18"), + ModelTestCase(task="segmentation", name="litehrnet_s"), + ModelTestCase(task="segmentation", name="litehrnet_x"), + ModelTestCase(task="segmentation", name="segnext_b"), + ModelTestCase(task="segmentation", name="segnext_s"), + ModelTestCase(task="segmentation", name="segnext_t"), + ModelTestCase(task="segmentation", name="dino_v2_seg"), ] # Test case parametrization for dataset DATASET_TEST_CASES = [ # noqa: RUF012 @@ -373,7 +373,7 @@ class TestSemanticSegmentation(BaseTest): data_root=Path("kvasir_small") / f"{idx}", data_format="common_semantic_segmentation_with_subset_dirs", num_classes=2, - extra_overrides={"trainer.max_epochs": "40", "trainer.deterministic": "True"}, + extra_overrides={"trainer.max_epochs": "40"}, ) for idx in range(1, 4) ] + [ @@ -382,14 +382,14 @@ class TestSemanticSegmentation(BaseTest): data_root="kvasir_medium", data_format="common_semantic_segmentation_with_subset_dirs", num_classes=2, - extra_overrides={"trainer.max_epochs": "40", "trainer.deterministic": "True"} + extra_overrides={"trainer.max_epochs": "40"} ), DatasetTestCase( name="kvasir_large", data_root="kvasir_large", data_format="common_semantic_segmentation_with_subset_dirs", num_classes=2, - extra_overrides={"trainer.max_epochs": "40", "trainer.deterministic": "True"} + extra_overrides={"trainer.max_epochs": "40"} ) ] From a81ca6fba1e1d65a87599f8e6827f4a3a9a3f690 Mon Sep 17 00:00:00 2001 From: Vinnam Kim Date: Mon, 22 Jan 2024 15:29:41 +0900 Subject: [PATCH 04/10] Update Datumaro version to 1.6.0rc1 (#2816) Signed-off-by: Kim, Vinnam --- pyproject.toml | 6 +-- src/otx/core/data/dataset/base.py | 67 +++++++++++++------------------ 2 files changed, 31 insertions(+), 42 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 74e1e2fa276..6f100bb52fa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,7 +28,7 @@ classifiers = [ "Programming Language :: Python :: 3.10", ] dependencies = [ - "datumaro", + "datumaro==1.6.0rc1", "omegaconf", "hydra-core", "rich", @@ -70,8 +70,8 @@ base = [ "lightning==2.1.2", "pytorchcv", "timm", - "openvino==2023.0.0", - "openvino-dev==2023.0.0", + "openvino==2023.2.0", + "openvino-dev==2023.2.0", "openvino-model-api==0.1.7", "onnx==1.13.0" ] diff --git a/src/otx/core/data/dataset/base.py b/src/otx/core/data/dataset/base.py index 1aab88d925b..ffcbac1a99d 100644 --- a/src/otx/core/data/dataset/base.py +++ b/src/otx/core/data/dataset/base.py @@ -6,15 +6,15 @@ from abc import abstractmethod from collections.abc import Iterable +from contextlib import contextmanager from dataclasses import dataclass -from io import BytesIO -from typing import TYPE_CHECKING, Callable, Generic, List, Union +from typing import TYPE_CHECKING, Callable, Generic, Iterator, List, Union import cv2 import numpy as np from datumaro.components.annotation import AnnotationType from datumaro.components.media import ImageFromFile -from PIL import Image as PILImage +from datumaro.util.image import _IMAGE_BACKEND, _IMAGE_BACKENDS, IMAGE_COLOR_SCALE, ImageColorScale from torch.utils.data import Dataset from torchvision.transforms.v2 import Compose @@ -30,6 +30,25 @@ Transforms = Union[Compose, Callable, List[Callable]] +@contextmanager +def image_decode_context() -> Iterator[None]: + """Change Datumaro image decode context. + + Use PIL Image decode because of performance issues. + With this context, `dm.Image.data` will return BGR numpy image tensor. + """ + ori_image_backend = _IMAGE_BACKEND.get() + ori_image_color_scale = IMAGE_COLOR_SCALE.get() + + _IMAGE_BACKEND.set(_IMAGE_BACKENDS.PIL) + IMAGE_COLOR_SCALE.set(ImageColorScale.COLOR) + + yield + + _IMAGE_BACKEND.set(ori_image_backend) + IMAGE_COLOR_SCALE.set(ori_image_color_scale) + + @dataclass class LabelInfo: """Object to represent label information.""" @@ -127,12 +146,12 @@ def _get_img_data_and_shape(self, img: Image) -> tuple[np.ndarray, tuple[int, in if (img_data := self.mem_cache_handler.get(key=key)[0]) is not None: return img_data, img_data.shape[:2] - # TODO(vinnamkim): This is a temporal approach - # There is an upcoming Datumaro patch here for this - # https://github.com/openvinotoolkit/datumaro/pull/1194 - img_data = ( - self._read_from_bytes(img_bytes) if (img_bytes := img.bytes) is not None else self._read_from_data(img.data) - ) + with image_decode_context(): + img_data = ( + cv2.cvtColor(img.data, cv2.COLOR_BGR2RGB) + if self.image_color_channel == ImageColorChannel.RGB + else img.data + ) if img_data is None: msg = "Cannot get image data" @@ -142,36 +161,6 @@ def _get_img_data_and_shape(self, img: Image) -> tuple[np.ndarray, tuple[int, in return img_data, img_data.shape[:2] - def _read_from_bytes(self, img_bytes: bytes) -> np.ndarray: - """Read an image from `img.bytes`.""" - img_data = np.asarray(PILImage.open(BytesIO(img_bytes)).convert("RGB")) - - if self.image_color_channel == ImageColorChannel.BGR: - return cv2.cvtColor(img_data, cv2.COLOR_RGB2BGR) - - return img_data - - def _read_from_data(self, img_data: np.ndarray | None) -> np.ndarray | None: - """This function is required for `img.data` (not read by PIL).""" - if img_data is None: - return None - - # TODO(vinnamki): dm.ImageFromData forces `img_data` to have `np.float32` type. #noqa: TD003 - # This behavior will be removed in the Datumaro side. - if img_data.dtype == np.float32: - img_data = img_data.astype(np.uint8) - - if img_data.shape[-1] == 4: - conversion = cv2.COLOR_BGRA2RGB if self.image_color_channel == ImageColorChannel.RGB else cv2.COLOR_BGRA2BGR - return cv2.cvtColor(img_data, conversion) - if len(img_data.shape) == 2: - conversion = cv2.COLOR_GRAY2RGB if self.image_color_channel == ImageColorChannel.RGB else cv2.COLOR_GRAY2BGR - return cv2.cvtColor(img_data, conversion) - if self.image_color_channel == ImageColorChannel.RGB: - return cv2.cvtColor(img_data, cv2.COLOR_BGR2RGB) - - return img_data - def _cache_img(self, key: str | int, img_data: np.ndarray) -> np.ndarray: """Cache an image after resizing. From 0b1a2d97123df2882f49e60b04fc8c903836d25e Mon Sep 17 00:00:00 2001 From: Vladislav Sovrasov Date: Mon, 22 Jan 2024 13:50:33 +0100 Subject: [PATCH 05/10] Remove center crop in cls configs (#2817) --- .../multiclass_classification/efficientnet_b0_light.yaml | 7 ++----- .../multiclass_classification/efficientnet_v2_light.yaml | 7 ++----- .../mobilenet_v3_large_light.yaml | 7 ++----- .../recipe/multiclass_classification/otx_deit_tiny.yaml | 7 ++----- .../multiclass_classification/otx_efficientnet_b0.yaml | 7 ++----- .../multiclass_classification/otx_efficientnet_v2.yaml | 7 ++----- .../multiclass_classification/otx_mobilenet_v3_large.yaml | 7 ++----- 7 files changed, 14 insertions(+), 35 deletions(-) diff --git a/src/otx/recipe/multiclass_classification/efficientnet_b0_light.yaml b/src/otx/recipe/multiclass_classification/efficientnet_b0_light.yaml index 6a53ceb5403..1cd97ce193e 100644 --- a/src/otx/recipe/multiclass_classification/efficientnet_b0_light.yaml +++ b/src/otx/recipe/multiclass_classification/efficientnet_b0_light.yaml @@ -29,11 +29,8 @@ data: transforms: - type: LoadImageFromFile - backend: cv2 - edge: short - scale: 256 - type: ResizeEdge - - crop_size: 224 - type: CenterCrop + scale: 224 + type: Resize - type: PackInputs model: otx_model: diff --git a/src/otx/recipe/multiclass_classification/efficientnet_v2_light.yaml b/src/otx/recipe/multiclass_classification/efficientnet_v2_light.yaml index 2490ac766d2..ece8bd4c3d0 100644 --- a/src/otx/recipe/multiclass_classification/efficientnet_v2_light.yaml +++ b/src/otx/recipe/multiclass_classification/efficientnet_v2_light.yaml @@ -32,11 +32,8 @@ data: transforms: - type: LoadImageFromFile - backend: cv2 - edge: short - scale: 256 - type: ResizeEdge - - crop_size: 224 - type: CenterCrop + scale: 224 + type: Resize - type: PackInputs model: otx_model: diff --git a/src/otx/recipe/multiclass_classification/mobilenet_v3_large_light.yaml b/src/otx/recipe/multiclass_classification/mobilenet_v3_large_light.yaml index 4bdcc22c2b6..84b67c7779b 100644 --- a/src/otx/recipe/multiclass_classification/mobilenet_v3_large_light.yaml +++ b/src/otx/recipe/multiclass_classification/mobilenet_v3_large_light.yaml @@ -32,11 +32,8 @@ data: transforms: - type: LoadImageFromFile - backend: cv2 - edge: short - scale: 256 - type: ResizeEdge - - crop_size: 224 - type: CenterCrop + scale: 224 + type: Resize - type: PackInputs model: otx_model: diff --git a/src/otx/recipe/multiclass_classification/otx_deit_tiny.yaml b/src/otx/recipe/multiclass_classification/otx_deit_tiny.yaml index ff11b2f3c6f..c2af42fa5f5 100644 --- a/src/otx/recipe/multiclass_classification/otx_deit_tiny.yaml +++ b/src/otx/recipe/multiclass_classification/otx_deit_tiny.yaml @@ -29,11 +29,8 @@ data: transforms: - type: LoadImageFromFile - backend: cv2 - edge: short - scale: 256 - type: ResizeEdge - - crop_size: 224 - type: CenterCrop + scale: 224 + type: Resize - type: PackInputs model: otx_model: diff --git a/src/otx/recipe/multiclass_classification/otx_efficientnet_b0.yaml b/src/otx/recipe/multiclass_classification/otx_efficientnet_b0.yaml index 7498be0bfb0..f2f6829a425 100644 --- a/src/otx/recipe/multiclass_classification/otx_efficientnet_b0.yaml +++ b/src/otx/recipe/multiclass_classification/otx_efficientnet_b0.yaml @@ -29,11 +29,8 @@ data: transforms: - type: LoadImageFromFile - backend: cv2 - edge: short - scale: 256 - type: ResizeEdge - - crop_size: 224 - type: CenterCrop + scale: 224 + type: Resize - type: PackInputs model: otx_model: diff --git a/src/otx/recipe/multiclass_classification/otx_efficientnet_v2.yaml b/src/otx/recipe/multiclass_classification/otx_efficientnet_v2.yaml index d5c6d454171..2337f657d7f 100644 --- a/src/otx/recipe/multiclass_classification/otx_efficientnet_v2.yaml +++ b/src/otx/recipe/multiclass_classification/otx_efficientnet_v2.yaml @@ -32,11 +32,8 @@ data: transforms: - type: LoadImageFromFile - backend: cv2 - edge: short - scale: 256 - type: ResizeEdge - - crop_size: 224 - type: CenterCrop + scale: 224 + type: Resize - type: PackInputs model: otx_model: diff --git a/src/otx/recipe/multiclass_classification/otx_mobilenet_v3_large.yaml b/src/otx/recipe/multiclass_classification/otx_mobilenet_v3_large.yaml index e6b749832ac..854ec629189 100644 --- a/src/otx/recipe/multiclass_classification/otx_mobilenet_v3_large.yaml +++ b/src/otx/recipe/multiclass_classification/otx_mobilenet_v3_large.yaml @@ -32,11 +32,8 @@ data: transforms: - type: LoadImageFromFile - backend: cv2 - edge: short - scale: 256 - type: ResizeEdge - - crop_size: 224 - type: CenterCrop + scale: 224 + type: Resize - type: PackInputs model: otx_model: From 6c35bf71d2d9b26e61df2be460c18a96d800f330 Mon Sep 17 00:00:00 2001 From: Evgeny Tsykunov Date: Mon, 22 Jan 2024 14:00:26 +0100 Subject: [PATCH 06/10] Fix predict checkpoint (#2819) --- src/otx/engine/engine.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/otx/engine/engine.py b/src/otx/engine/engine.py index f14db3b8195..11e74c08944 100644 --- a/src/otx/engine/engine.py +++ b/src/otx/engine/engine.py @@ -318,7 +318,7 @@ def predict( return self.trainer.predict( model=lit_module, datamodule=datamodule if datamodule is not None else self.datamodule, - ckpt_path=str(checkpoint) if checkpoint is not None else checkpoint, + ckpt_path=str(checkpoint) if checkpoint is not None else self.checkpoint, return_predictions=return_predictions, ) From 6b8b82e023f7d8507465edac013559698cd14522 Mon Sep 17 00:00:00 2001 From: Harim Kang Date: Tue, 23 Jan 2024 10:34:08 +0900 Subject: [PATCH 07/10] Refactor configuration & CLI (#2805) * Initial CLI commit * Align core module's arguments * Fix jsonargparse to recognize Trainer arguments * Refactor configuration files * Replace monkey-patching to contextmanager * Disable SAM intg test temporarily --- pyproject.toml | 14 +- src/otx/algo/detection/atss.py | 2 +- src/otx/algo/segmentation/litehrnet.py | 2 +- src/otx/cli/__init__.py | 70 +--- src/otx/cli/cli.py | 332 ++++++++++++++++++ src/otx/cli/test.py | 55 --- src/otx/cli/train.py | 92 ----- src/otx/cli/utils/__init__.py | 21 ++ src/otx/cli/utils/help_formatter.py | 224 ++++++++++++ src/otx/cli/utils/hydra.py | 40 --- src/otx/cli/utils/jsonargparse.py | 152 ++++++++ src/otx/config/__init__.py | 4 - .../config/base/action_classification.yaml | 4 - src/otx/config/base/action_detection.yaml | 4 - src/otx/config/base/classification.yaml | 4 - src/otx/config/base/default.yaml | 22 -- src/otx/config/base/detection.yaml | 4 - .../config/base/hlabel_classification.yaml | 4 - .../config/base/instance_segmentation.yaml | 4 - .../base/multilabel_classification.yaml | 4 - src/otx/config/base/segmentation.yaml | 4 - src/otx/config/base/visual_prompting.yaml | 4 - .../callbacks/action_classification.yaml | 15 - .../config/callbacks/action_detection.yaml | 15 - src/otx/config/callbacks/classification.yaml | 15 - src/otx/config/callbacks/default.yaml | 60 ---- src/otx/config/callbacks/detection.yaml | 15 - .../callbacks/hlabel_classification.yaml | 15 - .../callbacks/instance_segmentation.yaml | 15 - .../callbacks/multilabel_classification.yaml | 15 - src/otx/config/callbacks/segmentation.yaml | 15 - .../config/callbacks/visual_prompting.yaml | 16 - src/otx/config/data/default.yaml | 16 - src/otx/config/data/hlabel_mmpretrain.yaml | 16 - .../config/data/mmaction_classification.yaml | 16 - src/otx/config/data/mmaction_detection.yaml | 16 - src/otx/config/data/mmdet.yaml | 14 - src/otx/config/data/mmdet_inst_seg.yaml | 16 - .../config/data/mmdet_visual_prompting.yaml | 111 ------ .../config/data/multiclass_mmpretrain.yaml | 16 - .../config/data/multilabel_mmpretrain.yaml | 16 - src/otx/config/data/openvino.yaml | 20 -- src/otx/config/data/segmentation.yaml | 17 - src/otx/config/data/torchvision_cls.yaml | 49 --- .../data/torchvision_visual_prompting.yaml | 54 --- src/otx/config/debug/default.yaml | 35 -- src/otx/config/debug/fdr.yaml | 9 - src/otx/config/debug/intg_test.yaml | 19 - src/otx/config/debug/limit.yaml | 12 - src/otx/config/debug/overfit.yaml | 13 - src/otx/config/debug/profiler.yaml | 12 - src/otx/config/hydra/default.yaml | 19 - src/otx/config/hydra/help/otx.yaml | 39 -- src/otx/config/logger/aim.yaml | 28 -- src/otx/config/logger/comet.yaml | 12 - src/otx/config/logger/csv.yaml | 7 - src/otx/config/logger/many_loggers.yaml | 9 - src/otx/config/logger/mlflow.yaml | 12 - src/otx/config/logger/neptune.yaml | 9 - src/otx/config/logger/tensorboard.yaml | 10 - src/otx/config/logger/wandb.yaml | 16 - src/otx/config/model/default.yaml | 15 - src/otx/config/model/hlabel_mmpretrain.yaml | 13 - .../config/model/mmaction_classification.yaml | 11 - src/otx/config/model/mmaction_detection.yaml | 11 - src/otx/config/model/mmdet.yaml | 10 - src/otx/config/model/mmdet_inst_seg.yaml | 22 -- src/otx/config/model/mmseg.yaml | 19 - .../config/model/multiclass_mmpretrain.yaml | 11 - .../config/model/multilabel_mmpretrain.yaml | 11 - .../config/model/torch_classification.yaml | 11 - .../config/model/torch_visual_prompting.yaml | 10 - src/otx/config/test.yaml | 15 - src/otx/config/train.yaml | 23 -- src/otx/config/trainer/auto.yaml | 5 - src/otx/config/trainer/cpu.yaml | 6 - src/otx/config/trainer/ddp.yaml | 9 - src/otx/config/trainer/ddp_sim.yaml | 7 - src/otx/config/trainer/default.yaml | 21 -- src/otx/config/trainer/gpu.yaml | 5 - src/otx/config/trainer/mps.yaml | 5 - src/otx/core/config/__init__.py | 105 +++--- src/otx/core/config/base.py | 21 -- src/otx/core/config/callbacks.py | 4 - src/otx/core/config/data.py | 7 +- src/otx/core/config/debug.py | 4 - src/otx/core/config/hydra.py | 4 - src/otx/core/config/logger.py | 4 - src/otx/core/config/model.py | 17 - src/otx/core/config/trainer.py | 29 -- src/otx/core/data/factory.py | 4 +- src/otx/core/data/module.py | 4 +- .../core/data/transform_libs/torchvision.py | 4 +- .../model/module/action_classification.py | 16 +- src/otx/core/model/module/action_detection.py | 15 +- src/otx/core/model/module/base.py | 6 +- src/otx/core/model/module/classification.py | 35 +- src/otx/core/model/module/detection.py | 15 +- .../model/module/instance_segmentation.py | 15 +- src/otx/core/model/module/segmentation.py | 15 +- src/otx/core/utils/config.py | 3 +- src/otx/core/utils/instantiators.py | 118 ++++--- src/otx/core/utils/logging_utils.py | 82 ----- src/otx/core/utils/pylogger.py | 2 + src/otx/core/utils/rich_utils.py | 124 ------- src/otx/core/utils/utils.py | 144 -------- src/otx/engine/engine.py | 3 +- .../data/mmaction_base.yaml} | 31 +- src/otx/recipe/_base_/data/mmdet_base.yaml | 69 ++++ .../data/mmpretrain_base.yaml} | 37 +- .../data/mmseg_base.yaml} | 39 +- .../recipe/_base_/data/torchvision_base.yaml | 27 ++ src/otx/recipe/_base_/test.yaml | 26 ++ src/otx/recipe/_base_/train.yaml | 56 +++ .../action/action_classification/x3d.yaml | 26 ++ .../action/action_detection/x3d_fastrcnn.yaml | 93 +++++ .../recipe/action_classification/__init__.py | 7 - src/otx/recipe/action_detection/__init__.py | 4 - .../recipe/action_detection/x3d_fastrcnn.yaml | 80 ----- .../h_label_cls/efficientnet_b0_light.yaml | 32 ++ .../h_label_cls/efficientnet_v2_light.yaml | 44 +++ .../h_label_cls/mobilenet_v3_large_light.yaml | 44 +++ .../h_label_cls/otx_deit_tiny.yaml | 34 ++ .../efficientnet_b0_light.yaml | 28 ++ .../efficientnet_v2_light.yaml | 41 +++ .../mobilenet_v3_large_light.yaml | 41 +++ .../multi_class_cls/openvino_model.yaml | 43 +++ .../multi_class_cls/otx_deit_tiny.yaml | 27 ++ .../multi_class_cls/otx_dino_v2.yaml | 98 ++++++ .../otx_dino_v2_linear_probe.yaml | 100 ++++++ .../multi_class_cls/otx_efficientnet_b0.yaml | 28 ++ .../multi_class_cls/otx_efficientnet_v2.yaml | 41 +++ .../otx_mobilenet_v3_large.yaml | 41 +++ .../efficientnet_b0_light.yaml | 51 +++ .../efficientnet_v2_light.yaml | 56 +++ .../mobilenet_v3_large_light.yaml | 56 +++ .../multi_label_cls/otx_deit_tiny.yaml | 53 +++ src/otx/recipe/detection/__init__.py | 7 - .../recipe/detection/atss_mobilenetv2.yaml | 184 +++++----- src/otx/recipe/detection/atss_r50_fpn.yaml | 146 ++++---- src/otx/recipe/detection/atss_resnext101.yaml | 182 +++++----- src/otx/recipe/detection/openvino_model.yaml | 57 ++- src/otx/recipe/detection/rtmdet_tiny.yaml | 258 +++++++------- src/otx/recipe/detection/ssd_mobilenetv2.yaml | 196 ++++++----- src/otx/recipe/detection/yolox_l.yaml | 246 +++++++------ src/otx/recipe/detection/yolox_s.yaml | 246 +++++++------ src/otx/recipe/detection/yolox_tiny.yaml | 232 ++++++------ src/otx/recipe/detection/yolox_x.yaml | 246 +++++++------ .../efficientnet_b0_light.yaml | 46 --- .../efficientnet_v2_light.yaml | 52 --- .../mobilenet_v3_large_light.yaml | 52 --- .../hlabel_classification/otx_deit_tiny.yaml | 49 --- .../maskrcnn_efficientnetb2b.yaml | 154 ++++---- .../instance_segmentation/maskrcnn_r50.yaml | 154 ++++---- .../instance_segmentation/maskrcnn_swint.yaml | 154 ++++---- .../instance_segmentation/openvino_model.yaml | 56 ++- .../efficientnet_b0_light.yaml | 47 --- .../efficientnet_v2_light.yaml | 50 --- .../mobilenet_v3_large_light.yaml | 50 --- .../openvino_model.yaml | 23 -- .../otx_dino_v2.yaml | 83 ----- .../otx_dino_v2_linear_probe.yaml | 89 ----- .../otx_efficientnet_b0.yaml | 47 --- .../otx_efficientnet_v2.yaml | 50 --- .../otx_mobilenet_v3_large.yaml | 50 --- .../efficientnet_b0_light.yaml | 40 --- .../efficientnet_v2_light.yaml | 46 --- .../mobilenet_v3_large_light.yaml | 46 --- .../otx_deit_tiny.yaml | 43 --- src/otx/recipe/segmentation/__init__.py | 4 - src/otx/recipe/segmentation/dino_v2_seg.yaml | 67 ---- src/otx/recipe/segmentation/litehrnet_18.yaml | 70 ---- src/otx/recipe/segmentation/litehrnet_x.yaml | 70 ---- .../recipe/segmentation/openvino_model.yaml | 23 -- src/otx/recipe/segmentation/segnext_b.yaml | 62 ---- src/otx/recipe/segmentation/segnext_s.yaml | 62 ---- src/otx/recipe/segmentation/segnext_t.yaml | 62 ---- .../recipe/semantic_segmentation/dino_v2.yaml | 75 ++++ .../semantic_segmentation/litehrnet_18.yaml | 30 ++ .../semantic_segmentation/litehrnet_s.yaml | 30 ++ .../semantic_segmentation/litehrnet_x.yaml | 30 ++ .../semantic_segmentation/openvino_model.yaml | 39 ++ .../semantic_segmentation/segnext_b.yaml | 76 ++++ .../semantic_segmentation/segnext_s.yaml | 76 ++++ .../semantic_segmentation/segnext_t.yaml | 76 ++++ .../recipe/visual_prompting/sam_tiny_vit.yaml | 102 ++++-- tests/integration/cli/test_cli.py | 143 ++++---- tests/regression/test_regression.py | 174 ++++----- tests/unit/cli/test_cli.py | 74 +++- tests/unit/cli/utils/test_help_formatter.py | 138 ++++++++ tests/unit/cli/utils/test_hydra.py | 43 --- tests/unit/core/data/test_module.py | 3 +- tests/unit/core/data/test_transform_libs.py | 26 +- 193 files changed, 4426 insertions(+), 4803 deletions(-) create mode 100644 src/otx/cli/cli.py delete mode 100644 src/otx/cli/test.py delete mode 100644 src/otx/cli/train.py create mode 100644 src/otx/cli/utils/help_formatter.py delete mode 100644 src/otx/cli/utils/hydra.py create mode 100644 src/otx/cli/utils/jsonargparse.py delete mode 100644 src/otx/config/__init__.py delete mode 100644 src/otx/config/base/action_classification.yaml delete mode 100644 src/otx/config/base/action_detection.yaml delete mode 100644 src/otx/config/base/classification.yaml delete mode 100644 src/otx/config/base/default.yaml delete mode 100644 src/otx/config/base/detection.yaml delete mode 100644 src/otx/config/base/hlabel_classification.yaml delete mode 100644 src/otx/config/base/instance_segmentation.yaml delete mode 100644 src/otx/config/base/multilabel_classification.yaml delete mode 100644 src/otx/config/base/segmentation.yaml delete mode 100644 src/otx/config/base/visual_prompting.yaml delete mode 100644 src/otx/config/callbacks/action_classification.yaml delete mode 100644 src/otx/config/callbacks/action_detection.yaml delete mode 100644 src/otx/config/callbacks/classification.yaml delete mode 100644 src/otx/config/callbacks/default.yaml delete mode 100644 src/otx/config/callbacks/detection.yaml delete mode 100644 src/otx/config/callbacks/hlabel_classification.yaml delete mode 100644 src/otx/config/callbacks/instance_segmentation.yaml delete mode 100644 src/otx/config/callbacks/multilabel_classification.yaml delete mode 100644 src/otx/config/callbacks/segmentation.yaml delete mode 100644 src/otx/config/callbacks/visual_prompting.yaml delete mode 100644 src/otx/config/data/default.yaml delete mode 100644 src/otx/config/data/hlabel_mmpretrain.yaml delete mode 100644 src/otx/config/data/mmaction_classification.yaml delete mode 100644 src/otx/config/data/mmaction_detection.yaml delete mode 100644 src/otx/config/data/mmdet.yaml delete mode 100644 src/otx/config/data/mmdet_inst_seg.yaml delete mode 100644 src/otx/config/data/mmdet_visual_prompting.yaml delete mode 100644 src/otx/config/data/multiclass_mmpretrain.yaml delete mode 100644 src/otx/config/data/multilabel_mmpretrain.yaml delete mode 100644 src/otx/config/data/openvino.yaml delete mode 100644 src/otx/config/data/segmentation.yaml delete mode 100644 src/otx/config/data/torchvision_cls.yaml delete mode 100644 src/otx/config/data/torchvision_visual_prompting.yaml delete mode 100644 src/otx/config/debug/default.yaml delete mode 100644 src/otx/config/debug/fdr.yaml delete mode 100644 src/otx/config/debug/intg_test.yaml delete mode 100644 src/otx/config/debug/limit.yaml delete mode 100644 src/otx/config/debug/overfit.yaml delete mode 100644 src/otx/config/debug/profiler.yaml delete mode 100644 src/otx/config/hydra/default.yaml delete mode 100644 src/otx/config/hydra/help/otx.yaml delete mode 100644 src/otx/config/logger/aim.yaml delete mode 100644 src/otx/config/logger/comet.yaml delete mode 100644 src/otx/config/logger/csv.yaml delete mode 100644 src/otx/config/logger/many_loggers.yaml delete mode 100644 src/otx/config/logger/mlflow.yaml delete mode 100644 src/otx/config/logger/neptune.yaml delete mode 100644 src/otx/config/logger/tensorboard.yaml delete mode 100644 src/otx/config/logger/wandb.yaml delete mode 100644 src/otx/config/model/default.yaml delete mode 100644 src/otx/config/model/hlabel_mmpretrain.yaml delete mode 100644 src/otx/config/model/mmaction_classification.yaml delete mode 100644 src/otx/config/model/mmaction_detection.yaml delete mode 100644 src/otx/config/model/mmdet.yaml delete mode 100644 src/otx/config/model/mmdet_inst_seg.yaml delete mode 100644 src/otx/config/model/mmseg.yaml delete mode 100644 src/otx/config/model/multiclass_mmpretrain.yaml delete mode 100644 src/otx/config/model/multilabel_mmpretrain.yaml delete mode 100644 src/otx/config/model/torch_classification.yaml delete mode 100644 src/otx/config/model/torch_visual_prompting.yaml delete mode 100644 src/otx/config/test.yaml delete mode 100644 src/otx/config/train.yaml delete mode 100644 src/otx/config/trainer/auto.yaml delete mode 100644 src/otx/config/trainer/cpu.yaml delete mode 100644 src/otx/config/trainer/ddp.yaml delete mode 100644 src/otx/config/trainer/ddp_sim.yaml delete mode 100644 src/otx/config/trainer/default.yaml delete mode 100644 src/otx/config/trainer/gpu.yaml delete mode 100644 src/otx/config/trainer/mps.yaml delete mode 100644 src/otx/core/config/base.py delete mode 100644 src/otx/core/config/callbacks.py delete mode 100644 src/otx/core/config/debug.py delete mode 100644 src/otx/core/config/hydra.py delete mode 100644 src/otx/core/config/logger.py delete mode 100644 src/otx/core/config/model.py delete mode 100644 src/otx/core/config/trainer.py delete mode 100644 src/otx/core/utils/logging_utils.py delete mode 100644 src/otx/core/utils/rich_utils.py delete mode 100644 src/otx/core/utils/utils.py rename src/otx/recipe/{action_classification/x3d.yaml => _base_/data/mmaction_base.yaml} (81%) create mode 100644 src/otx/recipe/_base_/data/mmdet_base.yaml rename src/otx/recipe/{multiclass_classification/otx_deit_tiny.yaml => _base_/data/mmpretrain_base.yaml} (56%) rename src/otx/recipe/{segmentation/litehrnet_s.yaml => _base_/data/mmseg_base.yaml} (66%) create mode 100644 src/otx/recipe/_base_/data/torchvision_base.yaml create mode 100644 src/otx/recipe/_base_/test.yaml create mode 100644 src/otx/recipe/_base_/train.yaml create mode 100644 src/otx/recipe/action/action_classification/x3d.yaml create mode 100644 src/otx/recipe/action/action_detection/x3d_fastrcnn.yaml delete mode 100644 src/otx/recipe/action_classification/__init__.py delete mode 100644 src/otx/recipe/action_detection/__init__.py delete mode 100644 src/otx/recipe/action_detection/x3d_fastrcnn.yaml create mode 100644 src/otx/recipe/classification/h_label_cls/efficientnet_b0_light.yaml create mode 100644 src/otx/recipe/classification/h_label_cls/efficientnet_v2_light.yaml create mode 100644 src/otx/recipe/classification/h_label_cls/mobilenet_v3_large_light.yaml create mode 100644 src/otx/recipe/classification/h_label_cls/otx_deit_tiny.yaml create mode 100644 src/otx/recipe/classification/multi_class_cls/efficientnet_b0_light.yaml create mode 100644 src/otx/recipe/classification/multi_class_cls/efficientnet_v2_light.yaml create mode 100644 src/otx/recipe/classification/multi_class_cls/mobilenet_v3_large_light.yaml create mode 100644 src/otx/recipe/classification/multi_class_cls/openvino_model.yaml create mode 100644 src/otx/recipe/classification/multi_class_cls/otx_deit_tiny.yaml create mode 100644 src/otx/recipe/classification/multi_class_cls/otx_dino_v2.yaml create mode 100644 src/otx/recipe/classification/multi_class_cls/otx_dino_v2_linear_probe.yaml create mode 100644 src/otx/recipe/classification/multi_class_cls/otx_efficientnet_b0.yaml create mode 100644 src/otx/recipe/classification/multi_class_cls/otx_efficientnet_v2.yaml create mode 100644 src/otx/recipe/classification/multi_class_cls/otx_mobilenet_v3_large.yaml create mode 100644 src/otx/recipe/classification/multi_label_cls/efficientnet_b0_light.yaml create mode 100644 src/otx/recipe/classification/multi_label_cls/efficientnet_v2_light.yaml create mode 100644 src/otx/recipe/classification/multi_label_cls/mobilenet_v3_large_light.yaml create mode 100644 src/otx/recipe/classification/multi_label_cls/otx_deit_tiny.yaml delete mode 100644 src/otx/recipe/detection/__init__.py delete mode 100644 src/otx/recipe/hlabel_classification/efficientnet_b0_light.yaml delete mode 100644 src/otx/recipe/hlabel_classification/efficientnet_v2_light.yaml delete mode 100644 src/otx/recipe/hlabel_classification/mobilenet_v3_large_light.yaml delete mode 100644 src/otx/recipe/hlabel_classification/otx_deit_tiny.yaml delete mode 100644 src/otx/recipe/multiclass_classification/efficientnet_b0_light.yaml delete mode 100644 src/otx/recipe/multiclass_classification/efficientnet_v2_light.yaml delete mode 100644 src/otx/recipe/multiclass_classification/mobilenet_v3_large_light.yaml delete mode 100644 src/otx/recipe/multiclass_classification/openvino_model.yaml delete mode 100644 src/otx/recipe/multiclass_classification/otx_dino_v2.yaml delete mode 100644 src/otx/recipe/multiclass_classification/otx_dino_v2_linear_probe.yaml delete mode 100644 src/otx/recipe/multiclass_classification/otx_efficientnet_b0.yaml delete mode 100644 src/otx/recipe/multiclass_classification/otx_efficientnet_v2.yaml delete mode 100644 src/otx/recipe/multiclass_classification/otx_mobilenet_v3_large.yaml delete mode 100644 src/otx/recipe/multilabel_classification/efficientnet_b0_light.yaml delete mode 100644 src/otx/recipe/multilabel_classification/efficientnet_v2_light.yaml delete mode 100644 src/otx/recipe/multilabel_classification/mobilenet_v3_large_light.yaml delete mode 100644 src/otx/recipe/multilabel_classification/otx_deit_tiny.yaml delete mode 100644 src/otx/recipe/segmentation/__init__.py delete mode 100644 src/otx/recipe/segmentation/dino_v2_seg.yaml delete mode 100644 src/otx/recipe/segmentation/litehrnet_18.yaml delete mode 100644 src/otx/recipe/segmentation/litehrnet_x.yaml delete mode 100644 src/otx/recipe/segmentation/openvino_model.yaml delete mode 100644 src/otx/recipe/segmentation/segnext_b.yaml delete mode 100644 src/otx/recipe/segmentation/segnext_s.yaml delete mode 100644 src/otx/recipe/segmentation/segnext_t.yaml create mode 100644 src/otx/recipe/semantic_segmentation/dino_v2.yaml create mode 100644 src/otx/recipe/semantic_segmentation/litehrnet_18.yaml create mode 100644 src/otx/recipe/semantic_segmentation/litehrnet_s.yaml create mode 100644 src/otx/recipe/semantic_segmentation/litehrnet_x.yaml create mode 100644 src/otx/recipe/semantic_segmentation/openvino_model.yaml create mode 100644 src/otx/recipe/semantic_segmentation/segnext_b.yaml create mode 100644 src/otx/recipe/semantic_segmentation/segnext_s.yaml create mode 100644 src/otx/recipe/semantic_segmentation/segnext_t.yaml create mode 100644 tests/unit/cli/utils/test_help_formatter.py delete mode 100644 tests/unit/cli/utils/test_hydra.py diff --git a/pyproject.toml b/pyproject.toml index 6f100bb52fa..d8a8966304f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,13 +30,14 @@ classifiers = [ dependencies = [ "datumaro==1.6.0rc1", "omegaconf", - "hydra-core", "rich", "jsonargparse==4.27.1", "psutil", # Mem cache needs system checks "ftfy", "regex", - "importlib_resources" + "importlib_resources", + "docstring_parser", # CLI help-formatter + "rich_argparse", # CLI help-formatter ] [project.optional-dependencies] @@ -245,21 +246,12 @@ exclude = [ "tests/assets", # it will be cleaned up later - "src/otx/core/engine/utils/*", "src/otx/algo/classification/backbones/*", "for_developers/helpers.py", # Ruff complains it but don't know how to fix since it literally showed no useful logs. # https://github.com/openvinotoolkit/training_extensions/actions/runs/7176557723/job/19541622452?pr=2718#step:5:170 "tests/regression/*.py", - - # Temporarily disable it. This will be fixed in the next PR. - # [TODO] harimkang - "src/otx/core/utils/instantiators.py", - "src/otx/core/utils/logging_utils.py", - "src/otx/core/utils/pylogger.py", - "src/otx/core/utils/rich_utils.py", - "src/otx/core/utils/utils.py", ] # Same as Black. diff --git a/src/otx/algo/detection/atss.py b/src/otx/algo/detection/atss.py index 2062e21471d..c4da2d02016 100644 --- a/src/otx/algo/detection/atss.py +++ b/src/otx/algo/detection/atss.py @@ -12,7 +12,7 @@ class ATSS(MMDetCompatibleModel): """ATSS Model.""" - def __init__(self, num_classes: int, variant: Literal["mobilenetv2", "f50_fpn", "resnext101"]) -> None: + def __init__(self, num_classes: int, variant: Literal["mobilenetv2", "r50_fpn", "resnext101"]) -> None: model_name = f"atss_{variant}" config = read_mmconfig(model_name=model_name) super().__init__(num_classes=num_classes, config=config) diff --git a/src/otx/algo/segmentation/litehrnet.py b/src/otx/algo/segmentation/litehrnet.py index 118b0b8d3ed..19abe29f4d9 100644 --- a/src/otx/algo/segmentation/litehrnet.py +++ b/src/otx/algo/segmentation/litehrnet.py @@ -12,7 +12,7 @@ class LiteHRNet(MMSegCompatibleModel): """LiteHRNet Model.""" - def __init__(self, num_classes: int, variant: Literal["18", "s", "x"]) -> None: + def __init__(self, num_classes: int, variant: Literal["18", 18, "s", "x"]) -> None: model_name = f"litehrnet_{variant}" config = read_mmconfig(model_name=model_name) super().__init__(num_classes=num_classes, config=config) diff --git a/src/otx/cli/__init__.py b/src/otx/cli/__init__.py index 93095d6705a..e1aeb05e4d1 100644 --- a/src/otx/cli/__init__.py +++ b/src/otx/cli/__init__.py @@ -3,75 +3,7 @@ """CLI entrypoints.""" -from __future__ import annotations - -from jsonargparse import ArgumentParser - -from otx import __version__ - - -class OTXCLI: - """OTX CLI entrypoint.""" - - def __init__(self) -> None: - """Initialize OTX CLI.""" - self.parser = self.init_parser() - self.setup_subcommands() - self.config = self.parser.parse_args() - - self.run() - - def init_parser(self, **kwargs) -> ArgumentParser: - """Initialize the argument parser for the OTX CLI. - - Args: - **kwargs: Additional keyword arguments to pass to the ArgumentParser constructor. - - Returns: - ArgumentParser: The initialized argument parser. - """ - parser = ArgumentParser(description="OpenVINO Training-Extension command line tool", env_prefix="otx") - parser.add_argument( - "-V", - "--version", - action="version", - version=f"%(prog)s {__version__}", - help="Display OTX version number.", - ) - return parser - - def setup_subcommands(self) -> None: - """Setup subcommands for the OTX CLI.""" - parser_subcommands = self.parser.add_subcommands() - from otx.cli.install import add_install_parser - - add_install_parser(parser_subcommands) - - # otx train parser - train_parser = ArgumentParser() - train_parser.add_argument("overrides", help="overrides values", default=[], nargs="+") - parser_subcommands.add_subcommand("train", train_parser, help="Training subcommand for OTX") - - # otx test parser - test_parser = ArgumentParser() - test_parser.add_argument("overrides", help="overrides values", default=[], nargs="+") - parser_subcommands.add_subcommand("test", test_parser, help="Testing subcommand for OTX") - - def run(self) -> None: - """Run the OTX CLI.""" - subcommand = self.config["subcommand"] - if subcommand == "install": - from otx.cli.install import otx_install - - otx_install(**self.config["install"]) - elif subcommand == "train": - from otx.cli.train import otx_train - - otx_train(**self.config["train"]) - elif subcommand == "test": - from otx.cli.test import otx_test - - otx_test(**self.config["test"]) +from .cli import OTXCLI def main() -> None: diff --git a/src/otx/cli/cli.py b/src/otx/cli/cli.py new file mode 100644 index 00000000000..7d3f7cecf29 --- /dev/null +++ b/src/otx/cli/cli.py @@ -0,0 +1,332 @@ +"""CLI entrypoints.""" + +# Copyright (C) 2023 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + + +from __future__ import annotations + +from pathlib import Path +from typing import TYPE_CHECKING, Any + +import yaml +from jsonargparse import ActionConfigFile, ArgumentParser, Namespace, namespace_to_dict +from rich.console import Console + +from otx import OTX_LOGO, __version__ +from otx.cli.utils import get_otx_root_path +from otx.cli.utils.help_formatter import CustomHelpFormatter +from otx.cli.utils.jsonargparse import get_short_docstring, patch_update_configs + +if TYPE_CHECKING: + from jsonargparse._actions import _ActionSubCommands + +_ENGINE_AVAILABLE = True +try: + from otx.core.config import register_configs + from otx.engine import Engine + + register_configs() +except ImportError: + _ENGINE_AVAILABLE = False + + +class OTXCLI: + """OTX CLI entrypoint.""" + + def __init__(self) -> None: + """Initialize OTX CLI.""" + self.console = Console() + self._subcommand_method_arguments: dict[str, list[str]] = {} + with patch_update_configs(): + self.parser = self.init_parser() + self.add_subcommands() + self.config = self.parser.parse_args(_skip_check=True) + + self.subcommand = self.config["subcommand"] + self.run() + + def init_parser(self) -> ArgumentParser: + """Initialize the argument parser for the OTX CLI. + + Returns: + ArgumentParser: The initialized argument parser. + """ + parser = ArgumentParser( + description="OpenVINO Training-Extension command line tool", + env_prefix="otx", + parser_mode="omegaconf", + formatter_class=CustomHelpFormatter, + ) + parser.add_argument( + "-v", + "--version", + action="version", + version=f"%(prog)s {__version__}", + help="Display OTX version number.", + ) + return parser + + def subcommand_parser(self, **kwargs) -> ArgumentParser: + """Returns an ArgumentParser object for parsing command line arguments specific to a subcommand. + + Returns: + ArgumentParser: An ArgumentParser object configured with the specified arguments. + """ + parser = ArgumentParser( + formatter_class=CustomHelpFormatter, + parser_mode="omegaconf", + **kwargs, + ) + parser.add_argument( + "-v", + "--verbose", + action="count", + help="Verbose mode. This shows a configuration argument that allows for more specific overrides. \ + Multiple -v options increase the verbosity. The maximum is 2.", + ) + parser.add_argument( + "-c", + "--config", + action=ActionConfigFile, + help="Path to a configuration file in json or yaml format.", + ) + parser.add_argument( + "--data_root", + type=str, + help="Path to dataset root.", + ) + parser.add_argument( + "--task", + type=str, + help="Task Type.", + ) + parser.add_argument( + "--callback_monitor", + type=str, + help="The metric to monitor the model performance during training callbacks.", + ) + return parser + + @staticmethod + def engine_subcommands() -> dict[str, set[str]]: + """Returns dictionary the subcommands of engine, and whose value is the argument to be skipped in the CLI. + + This allows the CLI to skip duplicate keys when creating the Engine and when running the subcommand. + + Returns: + A dictionary where the keys are the subcommands and the values are sets of skipped arguments. + """ + device_kwargs = {"accelerator", "devices"} + return { + "train": device_kwargs, + "test": {"datamodule"}.union(device_kwargs), + "predict": {"datamodule"}.union(device_kwargs), + "export": device_kwargs, + } + + def add_subcommands(self) -> None: + """Adds subcommands to the CLI parser. + + This method initializes and configures subcommands for the OTX CLI parser. + It iterates over the available subcommands, adds arguments specific to each subcommand, + and registers them with the parser. + + Returns: + None + """ + self._subcommand_parsers: dict[str, ArgumentParser] = {} + parser_subcommands = self.parser.add_subcommands() + self._set_extension_subcommands_parser(parser_subcommands) + if not _ENGINE_AVAILABLE: + # If environment is not configured to use Engine, do not add a subcommand for Engine. + return + for subcommand in self.engine_subcommands(): + sub_parser = self.subcommand_parser() + engine_skip = {"model", "datamodule", "optimizer", "scheduler"} + sub_parser.add_class_arguments( + Engine, + "engine", + fail_untyped=False, + sub_configs=True, + instantiate=False, + skip=engine_skip, + ) + sub_parser.link_arguments("data_root", "engine.data_root") + + # Model Settings + from otx.core.model.entity.base import OTXModel + + model_kwargs: dict[str, Any] = {"fail_untyped": False} + + sub_parser.add_subclass_arguments( + OTXModel, + "model", + required=False, + **model_kwargs, + ) + # Datamodule Settings + from otx.core.data.module import OTXDataModule + + sub_parser.add_class_arguments( + OTXDataModule, + "data", + fail_untyped=False, + sub_configs=True, + ) + sub_parser.link_arguments("data_root", "data.config.data_root") + + # Optimizer & Scheduler Settings + from lightning.pytorch.cli import LRSchedulerTypeTuple + from torch.optim import Optimizer + + optim_kwargs = {"instantiate": False, "fail_untyped": False, "skip": {"params"}} + scheduler_kwargs = {"instantiate": False, "fail_untyped": False, "skip": {"optimizer"}} + sub_parser.add_subclass_arguments( + baseclass=(Optimizer,), + nested_key="optimizer", + **optim_kwargs, + ) + sub_parser.add_subclass_arguments( + baseclass=LRSchedulerTypeTuple, + nested_key="scheduler", + **scheduler_kwargs, + ) + + skip: set[str | int] = set(self.engine_subcommands()[subcommand]) + fn = getattr(Engine, subcommand) + description = get_short_docstring(fn) + added_arguments = sub_parser.add_method_arguments( + Engine, + subcommand, + skip=skip, + fail_untyped=False, + ) + + # Load default subcommand config file + default_config_file = get_otx_root_path() / "recipe" / "_base_" / f"{subcommand}.yaml" + if default_config_file.exists(): + with Path(default_config_file).open() as f: + default_config = yaml.safe_load(f) + sub_parser.set_defaults(**default_config) + + if "logger" in added_arguments: + sub_parser.link_arguments("engine.work_dir", "logger.init_args.save_dir") + if "callbacks" in added_arguments: + sub_parser.link_arguments("callback_monitor", "callbacks.init_args.monitor") + sub_parser.link_arguments("engine.work_dir", "callbacks.init_args.dirpath") + + self._subcommand_method_arguments[subcommand] = added_arguments + self._subcommand_parsers[subcommand] = sub_parser + parser_subcommands.add_subcommand(subcommand, sub_parser, help=description) + + def _set_extension_subcommands_parser(self, parser_subcommands: _ActionSubCommands) -> None: + from otx.cli.install import add_install_parser + + add_install_parser(parser_subcommands) + + def instantiate_classes(self) -> None: + """Instantiate the necessary classes based on the subcommand. + + This method checks if the subcommand is one of the engine subcommands. + If it is, it instantiates the necessary classes such as config, datamodule, model, and engine. + """ + if self.subcommand in self.engine_subcommands(): + self.config_init = self.parser.instantiate_classes(self.config) + self.datamodule = self.get_config_value(self.config_init, "data") + self.model, optimizer, scheduler = self.instantiate_model() + + engine_kwargs = self.get_config_value(self.config_init, "engine") + self.engine = Engine( + model=self.model, + optimizer=optimizer, + scheduler=scheduler, + datamodule=self.datamodule, + **engine_kwargs, + ) + + def instantiate_model(self) -> tuple: + """Instantiate the model based on the subcommand. + + This method checks if the subcommand is one of the engine subcommands. + If it is, it instantiates the model. + + Returns: + tuple: The model and optimizer and scheduler. + """ + model = self.get_config_value(self.config_init, "model") + optimizer_kwargs = namespace_to_dict(self.get_config_value(self.config_init, "optimizer", Namespace())) + scheduler_kwargs = namespace_to_dict(self.get_config_value(self.config_init, "scheduler", Namespace())) + from otx.core.utils.instantiators import partial_instantiate_class + + return model, partial_instantiate_class(optimizer_kwargs), partial_instantiate_class(scheduler_kwargs) + + def get_config_value(self, config: Namespace, key: str, default: Any = None) -> Any: # noqa: ANN401 + """Retrieves the value of a configuration key from the given config object. + + Args: + config (Namespace): The config object containing the configuration values. + key (str): The key of the configuration value to retrieve. + default (Any, optional): The default value to return if the key is not found. Defaults to None. + + Returns: + Any: The value of the configuration key, or the default value if the key is not found. + """ + return config.get(str(self.subcommand), config).get(key, default) + + def get_subcommand_parser(self, subcommand: str | None) -> ArgumentParser: + """Returns the argument parser for the specified subcommand. + + Args: + subcommand (str | None): The name of the subcommand. If None, returns the main parser. + + Returns: + ArgumentParser: The argument parser for the specified subcommand. + """ + if subcommand is None: + return self.parser + # return the subcommand parser for the subcommand passed + return self._subcommand_parsers[subcommand] + + def _prepare_subcommand_kwargs(self, subcommand: str) -> dict[str, Any]: + """Prepares the keyword arguments to pass to the subcommand to run.""" + return { + k: v for k, v in self.config_init[subcommand].items() if k in self._subcommand_method_arguments[subcommand] + } + + def save_config(self) -> None: + """Save the configuration for the specified subcommand. + + The configuration is saved as a YAML file in the engine's working directory. + """ + self.get_subcommand_parser(self.subcommand).save( + cfg=self.config.get(str(self.subcommand), self.config), + path=Path(self.engine.work_dir) / "configs.yaml", + overwrite=True, + multifile=False, + skip_check=True, + ) + + def run(self) -> None: + """Executes the specified subcommand. + + Raises: + ValueError: If the subcommand is not recognized. + """ + self.console.print(f"[blue]{OTX_LOGO}[/blue] ver.{__version__}", justify="center") + if self.subcommand == "install": + from otx.cli.install import otx_install + + otx_install(**self.config["install"]) + elif self.subcommand in self.engine_subcommands(): + self.instantiate_classes() + fn_kwargs = self._prepare_subcommand_kwargs(self.subcommand) + fn = getattr(self.engine, self.subcommand) + try: + fn(**fn_kwargs) + except Exception: + self.console.print_exception(width=self.console.width) + self.save_config() + else: + msg = f"Unrecognized subcommand: {self.subcommand}" + raise ValueError(msg) diff --git a/src/otx/cli/test.py b/src/otx/cli/test.py deleted file mode 100644 index 56b0fdcef3d..00000000000 --- a/src/otx/cli/test.py +++ /dev/null @@ -1,55 +0,0 @@ -# Copyright (C) 2023 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -"""CLI entrypoint for testing.""" -# ruff: noqa - -from __future__ import annotations - -import hydra -import logging as log -from hydra import compose, initialize -from otx.core.model.entity.base import OTXModel -from otx.cli.utils.hydra import configure_hydra_outputs - - -def otx_test(overrides: list[str]) -> None: - """Main entry point for testing. - - :param overrides: Override List values. - :return: Optional[float] with optimized metric value. - """ - from otx.core.config import register_configs - - # This should be in front of hydra.initialize() - register_configs() - - with initialize(config_path="../config", version_base="1.3", job_name="otx_test"): - cfg = compose(config_name="test", overrides=overrides, return_hydra_config=True) - configure_hydra_outputs(cfg) - - # test the model - from otx.core.data.module import OTXDataModule - - log.info(f"Instantiating datamodule <{cfg.data}>") - datamodule = OTXDataModule(task=cfg.base.task, config=cfg.data) - - log.info(f"Instantiating model <{cfg.model}>") - model: OTXModel = hydra.utils.instantiate(cfg.model.otx_model) - optimizer = hydra.utils.instantiate(cfg.model.optimizer) - scheduler = hydra.utils.instantiate(cfg.model.scheduler) - - from otx.engine import Engine - - trainer_kwargs = {**cfg.trainer} - engine = Engine( - task=cfg.base.task, - work_dir=cfg.base.output_dir, - model=model, - optimizer=optimizer, - scheduler=scheduler, - datamodule=datamodule, - checkpoint=cfg.checkpoint, - device=trainer_kwargs.pop("accelerator", "auto"), - ) - engine.test() diff --git a/src/otx/cli/train.py b/src/otx/cli/train.py deleted file mode 100644 index c2f1b33e782..00000000000 --- a/src/otx/cli/train.py +++ /dev/null @@ -1,92 +0,0 @@ -# Copyright (C) 2023 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -"""CLI entrypoint for training.""" -# ruff: noqa - -from __future__ import annotations - -import logging as log -from typing import TYPE_CHECKING, Any -import hydra -from hydra import compose, initialize -from otx.core.model.entity.base import OTXModel -from otx.cli.utils.hydra import configure_hydra_outputs - - -if TYPE_CHECKING: - from lightning import Callback - from lightning.pytorch.loggers import Logger - - -def otx_train(overrides: list[str]) -> dict[str, Any]: - """Main entry point for training. - - :param overrides: Override List values. - :return: Metrics values obtained from the model trainer. - """ - from otx.core.config import register_configs - - # This should be in front of hydra.initialize() - register_configs() - - with initialize(config_path="../config", version_base="1.3", job_name="otx_train"): - cfg = compose(config_name="train", overrides=overrides, return_hydra_config=True) - configure_hydra_outputs(cfg) - - # train the model - from lightning import seed_everything - - from otx.core.data.module import OTXDataModule - from otx.core.utils.instantiators import ( - instantiate_callbacks, - instantiate_loggers, - ) - - if cfg.seed is not None: - seed_everything(cfg.seed, workers=True) - - log.info(f"Instantiating datamodule <{cfg.data}>") - datamodule = OTXDataModule(task=cfg.base.task, config=cfg.data) - log.info(f"Instantiating model <{cfg.model}>") - model: OTXModel = hydra.utils.instantiate(cfg.model.otx_model) - optimizer = hydra.utils.instantiate(cfg.model.optimizer) - scheduler = hydra.utils.instantiate(cfg.model.scheduler) - - log.info("Instantiating callbacks...") - callbacks: list[Callback] = instantiate_callbacks(cfg.callbacks) - - log.info("Instantiating loggers...") - logger: list[Logger] = instantiate_loggers(cfg.logger) - - from otx.engine import Engine - - trainer_kwargs = {**cfg.trainer} - engine = Engine( - task=cfg.base.task, - work_dir=cfg.base.output_dir, - model=model, - optimizer=optimizer, - scheduler=scheduler, - datamodule=datamodule, - checkpoint=cfg.checkpoint, - device=trainer_kwargs.pop("accelerator", "auto"), - ) - - train_metrics = {} - - trainer_kwargs.pop("_target_", None) - trainer_kwargs.pop("default_root_dir", None) - if cfg.train: - train_metrics = engine.train( - callbacks=callbacks, - logger=logger, - resume=cfg.resume, - **trainer_kwargs, - ) - - test_metrics = {} - if cfg.test: - test_metrics = engine.test() - - return {**train_metrics, **test_metrics} diff --git a/src/otx/cli/utils/__init__.py b/src/otx/cli/utils/__init__.py index ab848f823da..2edd01537bc 100644 --- a/src/otx/cli/utils/__init__.py +++ b/src/otx/cli/utils/__init__.py @@ -2,3 +2,24 @@ # SPDX-License-Identifier: Apache-2.0 """CLI Utils.""" + +import importlib +import inspect +from pathlib import Path + + +def get_otx_root_path() -> Path: + """Return the root path of the otx module. + + Returns: + str: The root path of the otx module. + + Raises: + ModuleNotFoundError: If the otx module is not found. + """ + otx_module = importlib.import_module("otx") + if otx_module: + file_path = inspect.getfile(otx_module) + return Path(file_path).parent + msg = "Cannot found otx." + raise ModuleNotFoundError(msg) diff --git a/src/otx/cli/utils/help_formatter.py b/src/otx/cli/utils/help_formatter.py new file mode 100644 index 00000000000..e68ba7b8182 --- /dev/null +++ b/src/otx/cli/utils/help_formatter.py @@ -0,0 +1,224 @@ +"""Custom Help Formatters for OTX CLI.""" + +# Copyright (C) 2024 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +from __future__ import annotations + +import re +import sys +from typing import TYPE_CHECKING, Iterable + +from jsonargparse import DefaultHelpFormatter +from rich.markdown import Markdown +from rich.panel import Panel +from rich_argparse import RichHelpFormatter + +if TYPE_CHECKING: + import argparse + + from rich.console import RenderableType + + +BASE_ARGUMENTS = {"config", "print_config", "help", "engine", "model", "model.help", "task"} +ENGINE_ARGUMENTS = {"data_root", "engine.help", "engine.device", "engine.checkpoint", "engine.work_dir"} +REQUIRED_ARGUMENTS = { + "train": { + "data", + "optimizer", + "scheduler", + *BASE_ARGUMENTS, + *ENGINE_ARGUMENTS, + }, + "test": { + "data", + *BASE_ARGUMENTS, + *ENGINE_ARGUMENTS, + }, +} + + +def get_verbosity_subcommand() -> dict: + """Parse command line arguments and returns a dictionary of key-value pairs. + + Returns: + A dictionary containing the parsed command line arguments. + + Examples: + >>> import sys + >>> sys.argv = ['otx', 'train', '-h', '-v'] + >>> get_verbosity_subcommand() + {'subcommand': 'train', 'help': True, 'verbosity': 1} + """ + arguments: dict = {"subcommand": None, "help": False, "verbosity": 2} + if len(sys.argv) >= 2 and sys.argv[1] not in ("--help", "-h"): + arguments["subcommand"] = sys.argv[1] + if "--help" in sys.argv or "-h" in sys.argv: + arguments["help"] = True + if arguments["subcommand"] in REQUIRED_ARGUMENTS: + arguments["verbosity"] = 0 + if "-v" in sys.argv or "--verbose" in sys.argv: + arguments["verbosity"] = 1 + if "-vv" in sys.argv: + arguments["verbosity"] = 2 + return arguments + + +INTRO_MARKDOWN = ( + "# OpenVINO™ Training Extensions CLI Guide\n\n" + "Github Repository: [https://github.com/openvinotoolkit/training_extensions](https://github.com/openvinotoolkit/training_extensions)." + "\n\n" + "A better guide is provided by the [documentation](https://openvinotoolkit.github.io/training_extensions/stable/)." +) + +VERBOSE_USAGE = ( + "To get more overridable argument information, run the command below.\n" + "```python\n" + "# Verbosity Level 1\n" + "otx {subcommand} [optional_arguments] -h -v\n" + "# Verbosity Level 2\n" + "otx {subcommand} [optional_arguments] -h -vv\n" + "```" +) + +CLI_USAGE_PATTERN = r"CLI Usage:(.*?)(?=\n{2,}|\Z)" + + +def get_cli_usage_docstring(component: object | None) -> str | None: + r"""Get the cli usage from the docstring. + + Args: + component (Optional[object]): The component to get the docstring from + + Returns: + Optional[str]: The quick-start guide as Markdown format. + + Example: + component.__doc__ = ''' + + + CLI Usage: + 1. First Step. + 2. Second Step. + + + ''' + >>> get_cli_usage_docstring(component) + "1. First Step.\n2. Second Step." + """ + if component is None or component.__doc__ is None or "CLI Usage" not in component.__doc__: + return None + match = re.search(CLI_USAGE_PATTERN, component.__doc__, re.DOTALL) + if match: + contents = match.group(1).strip().split("\n") + return "\n".join([content.strip() for content in contents]) + return None + + +def render_guide(subcommand: str | None = None) -> list: + """Render a guide for the specified subcommand. + + Args: + subcommand (Optional[str]): The subcommand to render the guide for. + + Returns: + list: A list of contents to be displayed in the guide. + """ + if subcommand is None or subcommand in ("install"): + return [] + from otx.engine import Engine + + contents: list[Panel | Markdown] = [Markdown(INTRO_MARKDOWN)] + target_command = getattr(Engine, subcommand) + cli_usage = get_cli_usage_docstring(target_command) + if cli_usage is not None: + cli_usage += f"\n{VERBOSE_USAGE.format(subcommand=subcommand)}" + quick_start = Panel(Markdown(cli_usage), border_style="dim", title="Quick-Start", title_align="left") + contents.append(quick_start) + return contents + + +class CustomHelpFormatter(RichHelpFormatter, DefaultHelpFormatter): + """A custom help formatter for OTX CLI. + + This formatter extends the RichHelpFormatter and DefaultHelpFormatter classes to provide + a more detailed and customizable help output for OTX CLI. + + Attributes: + verbosity_level : int + The level of verbosity for the help output. + subcommand : str | None + The subcommand to render the guide for. + + Methods: + add_usage(usage, actions, *args, **kwargs) + Add usage information to the help output. + add_argument(action) + Add an argument to the help output. + format_help() + Format the help output. + """ + + verbosity_dict = get_verbosity_subcommand() + verbosity_level = verbosity_dict["verbosity"] + subcommand = verbosity_dict["subcommand"] + + def add_usage(self, usage: str | None, actions: Iterable[argparse.Action], *args, **kwargs) -> None: + """Add usage information to the formatter. + + Args: + usage (str | None): A string describing the usage of the program. + actions (Iterable[argparse.Action]): An list of argparse.Action objects. + *args (Any): Additional positional arguments to pass to the superclass method. + **kwargs (Any): Additional keyword arguments to pass to the superclass method. + + Returns: + None + """ + actions = [] if self.verbosity_level == 0 else actions + if self.subcommand in REQUIRED_ARGUMENTS and self.verbosity_level == 1: + actions = [action for action in actions if action.dest in REQUIRED_ARGUMENTS[self.subcommand]] + + super().add_usage(usage, actions, *args, **kwargs) + + def add_argument(self, action: argparse.Action) -> None: + """Add an argument to the help formatter. + + If the verbose level is set to 0, the argument is not added. + If the verbose level is set to 1 and the argument is not in the non-skip list, the argument is not added. + + Args: + action (argparse.Action): The action to add to the help formatter. + """ + if self.subcommand in REQUIRED_ARGUMENTS: + if self.verbosity_level == 0: + return + if self.verbosity_level == 1 and action.dest not in REQUIRED_ARGUMENTS[self.subcommand]: + return + super().add_argument(action) + + def format_help(self) -> str: + """Format the help message for the current command and returns it as a string. + + The help message includes information about the command's arguments and options, + as well as any additional information provided by the command's help guide. + + Returns: + str: A string containing the formatted help message. + """ + with self.console.capture() as capture: + section = self._root_section + rendered_content: RenderableType = section + if self.subcommand in REQUIRED_ARGUMENTS and self.verbosity_level in (0, 1) and len(section.rich_items) > 1: + contents = render_guide(self.subcommand) + for content in contents: + self.console.print(content) + if self.verbosity_level > 0: + if len(section.rich_items) > 1: + rendered_content = Panel(section, border_style="dim", title="Arguments", title_align="left") + self.console.print(rendered_content, highlight=False, soft_wrap=True) + help_msg = capture.get() + + if help_msg: + help_msg = self._long_break_matcher.sub("\n\n", help_msg).rstrip() + "\n" + return help_msg diff --git a/src/otx/cli/utils/hydra.py b/src/otx/cli/utils/hydra.py deleted file mode 100644 index a2b1b9fc52d..00000000000 --- a/src/otx/cli/utils/hydra.py +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright (C) 2023 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -"""Functions related to Hydra.""" - -from __future__ import annotations - -import copy -from pathlib import Path -from typing import TYPE_CHECKING - -from hydra.core.utils import _save_config, configure_log - -if TYPE_CHECKING: - from omegaconf import DictConfig - - -def configure_hydra_outputs(cfg: DictConfig) -> None: - """Configures the outputs for Hydra. - - Copied some of the log and output configuration code from run_job fucntion of 'hydra.core.utils'. - - Args: - cfg (DictConfig): The configuration dictionary. - - Returns: - None - """ - output_dir = Path(cfg.base.output_dir).resolve() - output_dir.mkdir(parents=True, exist_ok=True) - - # Configure Logger & logging outputs - configure_log(cfg.hydra.job_logging, cfg.hydra.verbose) - - # Configure .hydra output config files - if cfg.hydra.output_subdir is not None: - hydra_output = Path(cfg.hydra.runtime.output_dir) / Path(cfg.hydra.output_subdir) - task_cfg = copy.deepcopy(cfg) - _save_config(task_cfg, "config.yaml", hydra_output) - _save_config(cfg.hydra.overrides.task, "overrides.yaml", hydra_output) diff --git a/src/otx/cli/utils/jsonargparse.py b/src/otx/cli/utils/jsonargparse.py new file mode 100644 index 00000000000..c706babd124 --- /dev/null +++ b/src/otx/cli/utils/jsonargparse.py @@ -0,0 +1,152 @@ +"""Functions related to jsonargparse.""" + +# Copyright (C) 2023 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +from __future__ import annotations + +import ast +from contextlib import contextmanager +from pathlib import Path +from typing import Any, Iterator, TypeVar + +import docstring_parser +from jsonargparse import ActionConfigFile, ArgumentParser, Namespace, dict_to_namespace + + +def get_short_docstring(component: TypeVar) -> str: + """Get the short description from the docstring. + + Args: + component (TypeVar): The component to get the docstring from + + Returns: + str: The short description + """ + if component.__doc__ is None: + return "" + docstring = docstring_parser.parse(component.__doc__) + return docstring.short_description + + +def flatten_dict(config: dict, parent_key: str = "", sep: str = ".") -> dict: + """Flatten a nested dictionary into a single-level dictionary. + + Args: + d (dict): The dictionary to be flattened. + parent_key (str): The parent key to be used for nested keys. + sep (str): The separator to be used between parent and child keys. + + Returns: + dict: The flattened dictionary. + + """ + items: list = [] + for k, v in config.items(): + new_key = f"{parent_key}{sep}{k}" if parent_key else k + if isinstance(v, dict): + items.extend(flatten_dict(v, new_key, sep=sep).items()) + else: + items.append((new_key, v)) + return dict(items) + + +# [FIXME]: Overriding Namespce.update to match mmengine.Config (DictConfig | dict) +# and prevent int, float types from being converted to str +# https://github.com/omni-us/jsonargparse/issues/236 +def update( + self: Namespace, + value: Any, # noqa: ANN401 + key: str | None = None, + only_unset: bool = False, +) -> Namespace: + """Sets or replaces all items from the given nested namespace. + + Args: + value: A namespace to update multiple values or other type to set in a single key. + key: Branch key where to set the value. Required if value is not namespace. + only_unset: Whether to only set the value if not set in namespace. + """ + is_value_dict = False + if isinstance(value, dict): + # Dict -> Nested Namespace for overriding + is_value_dict = True + value = dict_to_namespace(value) + if not isinstance(value, (Namespace, dict)): + if not key: + msg = "Key is required if value not a Namespace." + raise KeyError(msg) + if not only_unset or key not in self: + if key not in self or value is not None: + if isinstance(value, str) and (value.isnumeric() or value in ("True", "False")): + value = ast.literal_eval(value) + self[key] = value + elif value is None: + del self[key] + else: + prefix = key + "." if key else "" + for _key, val in value.items(): + if not only_unset or prefix + _key not in self: + self.update(val, prefix + _key) + if is_value_dict and key is not None: + # Dict or Namespace -> Dict + self[key] = dict_to_namespace(self[key]).as_dict() + return self + + +# To provide overriding of the Config file +def apply_config(self: ActionConfigFile, parser: ArgumentParser, cfg: Namespace, dest: str, value: str) -> None: # noqa: ARG001 + """Applies the configuration to the parser. + + Args: + parser: The parser object. + cfg: The configuration object. + dest: The destination attribute. + value: The value to be applied. + + Returns: + None + """ + from jsonargparse._actions import _ActionSubCommands, previous_config_context + from jsonargparse._link_arguments import skip_apply_links + from jsonargparse._loaders_dumpers import get_loader_exceptions, load_value + from jsonargparse._optionals import get_config_read_mode + + with _ActionSubCommands.not_single_subcommand(), previous_config_context(cfg), skip_apply_links(): + kwargs = {"env": False, "defaults": False, "_skip_check": True, "_fail_no_subcommand": False} + try: + cfg_path: Path | None = Path(value, mode=get_config_read_mode()) + except TypeError: + try: + if isinstance(load_value(value), str): + raise + cfg_path = None + cfg_file = parser.parse_string(value, **kwargs) + except (TypeError, *get_loader_exceptions()) as ex_str: + msg = f'Parser key "{dest}": {ex_str}' + raise TypeError(msg) from ex_str + else: + cfg_file = parser.parse_path(value, **kwargs) + cfg_merged = parser.merge_config(cfg_file, cfg) + cfg.__dict__.update(cfg_merged.__dict__) + overrides = cfg.__dict__.pop("overrides", None) + if overrides is not None: + cfg.__dict__.update(overrides) + if cfg.get(dest) is None: + cfg[dest] = [] + cfg[dest].append(cfg_path) + + +@contextmanager +def patch_update_configs() -> Iterator[None]: + """Patch the update and apply_config methods of the given namespace and action_config_file objects.""" + original_update = Namespace.update + original_apply_config = ActionConfigFile.apply_config + + try: + Namespace.update = update + ActionConfigFile.apply_config = apply_config + yield + finally: + Namespace.update = original_update + ActionConfigFile.apply_config = original_apply_config diff --git a/src/otx/config/__init__.py b/src/otx/config/__init__.py deleted file mode 100644 index 1760e22620f..00000000000 --- a/src/otx/config/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -"""OTX default YAML configuration file collection. - -this file is needed here to include configs when building project as a package -""" diff --git a/src/otx/config/base/action_classification.yaml b/src/otx/config/base/action_classification.yaml deleted file mode 100644 index ab095aa223a..00000000000 --- a/src/otx/config/base/action_classification.yaml +++ /dev/null @@ -1,4 +0,0 @@ -defaults: - - default - -task: ACTION_CLASSIFICATION diff --git a/src/otx/config/base/action_detection.yaml b/src/otx/config/base/action_detection.yaml deleted file mode 100644 index 684e82927fd..00000000000 --- a/src/otx/config/base/action_detection.yaml +++ /dev/null @@ -1,4 +0,0 @@ -defaults: - - default - -task: ACTION_DETECTION diff --git a/src/otx/config/base/classification.yaml b/src/otx/config/base/classification.yaml deleted file mode 100644 index 21c3d0a771e..00000000000 --- a/src/otx/config/base/classification.yaml +++ /dev/null @@ -1,4 +0,0 @@ -defaults: - - default - -task: MULTI_CLASS_CLS diff --git a/src/otx/config/base/default.yaml b/src/otx/config/base/default.yaml deleted file mode 100644 index 59a7ac098a6..00000000000 --- a/src/otx/config/base/default.yaml +++ /dev/null @@ -1,22 +0,0 @@ -# OTX task enum -task: ??? - -# # simply provide checkpoint path to resume training -# ckpt_path: null - -# # seed for random number generators in pytorch, numpy and python.random -# seed: null - -# path to working directory -work_dir: ${hydra:runtime.cwd} - -# path to data directory -data_dir: ${base.work_dir}/data/ - -# path to logging directory -log_dir: ${base.work_dir}/logs/ - -# path to output directory, created dynamically by hydra -# path generation pattern is specified in `configs/hydra/default.yaml` -# use it to store all files generated during the run, like ckpts and metrics -output_dir: ${hydra:runtime.output_dir} diff --git a/src/otx/config/base/detection.yaml b/src/otx/config/base/detection.yaml deleted file mode 100644 index 109103ca3db..00000000000 --- a/src/otx/config/base/detection.yaml +++ /dev/null @@ -1,4 +0,0 @@ -defaults: - - default - -task: DETECTION diff --git a/src/otx/config/base/hlabel_classification.yaml b/src/otx/config/base/hlabel_classification.yaml deleted file mode 100644 index a588e7ceeae..00000000000 --- a/src/otx/config/base/hlabel_classification.yaml +++ /dev/null @@ -1,4 +0,0 @@ -defaults: - - default - -task: H_LABEL_CLS diff --git a/src/otx/config/base/instance_segmentation.yaml b/src/otx/config/base/instance_segmentation.yaml deleted file mode 100644 index fa61a527f5c..00000000000 --- a/src/otx/config/base/instance_segmentation.yaml +++ /dev/null @@ -1,4 +0,0 @@ -defaults: - - default - -task: INSTANCE_SEGMENTATION diff --git a/src/otx/config/base/multilabel_classification.yaml b/src/otx/config/base/multilabel_classification.yaml deleted file mode 100644 index 46db4512ce0..00000000000 --- a/src/otx/config/base/multilabel_classification.yaml +++ /dev/null @@ -1,4 +0,0 @@ -defaults: - - default - -task: MULTI_LABEL_CLS diff --git a/src/otx/config/base/segmentation.yaml b/src/otx/config/base/segmentation.yaml deleted file mode 100644 index edf53211df4..00000000000 --- a/src/otx/config/base/segmentation.yaml +++ /dev/null @@ -1,4 +0,0 @@ -defaults: - - default - -task: SEMANTIC_SEGMENTATION diff --git a/src/otx/config/base/visual_prompting.yaml b/src/otx/config/base/visual_prompting.yaml deleted file mode 100644 index 58e3572ab2a..00000000000 --- a/src/otx/config/base/visual_prompting.yaml +++ /dev/null @@ -1,4 +0,0 @@ -defaults: - - default - -task: VISUAL_PROMPTING diff --git a/src/otx/config/callbacks/action_classification.yaml b/src/otx/config/callbacks/action_classification.yaml deleted file mode 100644 index c9513b3049b..00000000000 --- a/src/otx/config/callbacks/action_classification.yaml +++ /dev/null @@ -1,15 +0,0 @@ -defaults: - - default - -model_checkpoint: - dirpath: ${base.output_dir}/checkpoints - filename: "epoch_{epoch:03d}" - monitor: "accuracy" - mode: "max" - save_last: True - auto_insert_metric_name: False - -early_stopping: - monitor: "accuracy" - patience: 100 - mode: "max" diff --git a/src/otx/config/callbacks/action_detection.yaml b/src/otx/config/callbacks/action_detection.yaml deleted file mode 100644 index 084a986e048..00000000000 --- a/src/otx/config/callbacks/action_detection.yaml +++ /dev/null @@ -1,15 +0,0 @@ -defaults: - - default - -model_checkpoint: - dirpath: ${base.output_dir}/checkpoints - filename: "epoch_{epoch:03d}" - monitor: "val/map_50" - mode: "max" - save_last: True - auto_insert_metric_name: False - -early_stopping: - monitor: "val/map_50" - patience: 100 - mode: "max" diff --git a/src/otx/config/callbacks/classification.yaml b/src/otx/config/callbacks/classification.yaml deleted file mode 100644 index fc712ff42c2..00000000000 --- a/src/otx/config/callbacks/classification.yaml +++ /dev/null @@ -1,15 +0,0 @@ -defaults: - - default - -model_checkpoint: - dirpath: ${base.output_dir}/checkpoints - filename: "epoch_{epoch:03d}" - monitor: "val/accuracy" - mode: "max" - save_last: True - auto_insert_metric_name: False - -early_stopping: - monitor: "val/accuracy" - patience: 100 - mode: "max" diff --git a/src/otx/config/callbacks/default.yaml b/src/otx/config/callbacks/default.yaml deleted file mode 100644 index 148627baed0..00000000000 --- a/src/otx/config/callbacks/default.yaml +++ /dev/null @@ -1,60 +0,0 @@ -# https://lightning.ai/docs/pytorch/stable/api/lightning.pytorch.callbacks.EarlyStopping.html -early_stopping: - _target_: lightning.pytorch.callbacks.EarlyStopping - monitor: ??? # quantity to be monitored, must be specified !!! - min_delta: 0. # minimum change in the monitored quantity to qualify as an improvement - patience: 3 # number of checks with no improvement after which training will be stopped - verbose: False # verbosity mode - mode: "min" # "max" means higher metric value is better, can be also "min" - strict: True # whether to crash the training if monitor is not found in the validation metrics - check_finite: True # when set True, stops training when the monitor becomes NaN or infinite - stopping_threshold: null # stop training immediately once the monitored quantity reaches this threshold - divergence_threshold: null # stop training as soon as the monitored quantity becomes worse than this threshold - check_on_train_epoch_end: false # run early stopping at the end of the validation epoch - # log_rank_zero_only: False # this keyword argument isn't available in stable version - -# https://lightning.ai/docs/pytorch/stable/api/lightning.pytorch.callbacks.ModelCheckpoint.html -model_checkpoint: - _target_: lightning.pytorch.callbacks.ModelCheckpoint - dirpath: null # directory to save the model file - filename: null # checkpoint filename - monitor: null # name of the logged metric which determines when model is improving - verbose: False # verbosity mode - save_last: null # additionally always save an exact copy of the last checkpoint to a file last.ckpt - save_top_k: 1 # save k best models (determined by above metric) - mode: "min" # "max" means higher metric value is better, can be also "min" - auto_insert_metric_name: True # when True, the checkpoints filenames will contain the metric name - save_weights_only: False # if True, then only the model’s weights will be saved - every_n_train_steps: null # number of training steps between checkpoints - train_time_interval: null # checkpoints are monitored at the specified time interval - every_n_epochs: null # number of epochs between checkpoints - save_on_train_epoch_end: null # whether to run checkpointing at the end of the training epoch or the end of validation - -# https://lightning.ai/docs/pytorch/stable/api/lightning.pytorch.callbacks.RichModelSummary.html -model_summary: - _target_: lightning.pytorch.callbacks.RichModelSummary - max_depth: 1 # the maximum depth of layer nesting that the summary will include - -# https://lightning.ai/docs/pytorch/latest/api/lightning.pytorch.callbacks.RichProgressBar.html -rich_progress_bar: - _target_: lightning.pytorch.callbacks.RichProgressBar - -# https://lightning.ai/docs/pytorch/stable/api/lightning.pytorch.callbacks.LearningRateMonitor.html -learning_rate_monitor: - _target_: lightning.pytorch.callbacks.LearningRateMonitor - logging_interval: epoch - log_momentum: True - -# OTX custom callbacks -# src/otx/algo/callbacks/iteration_timer.py -iteration_timer: - _target_: otx.algo.callbacks.iteration_timer.IterationTimer - prog_bar: True - on_step: False - on_epoch: True - -# src/otx/algo/callbacks/adaptive_train_scheduling.py -adaptive_train_scheduling: - _target_: otx.algo.callbacks.adaptive_train_scheduling.AdaptiveTrainScheduling - max_interval: 5 - decay: -0.025 diff --git a/src/otx/config/callbacks/detection.yaml b/src/otx/config/callbacks/detection.yaml deleted file mode 100644 index 084a986e048..00000000000 --- a/src/otx/config/callbacks/detection.yaml +++ /dev/null @@ -1,15 +0,0 @@ -defaults: - - default - -model_checkpoint: - dirpath: ${base.output_dir}/checkpoints - filename: "epoch_{epoch:03d}" - monitor: "val/map_50" - mode: "max" - save_last: True - auto_insert_metric_name: False - -early_stopping: - monitor: "val/map_50" - patience: 100 - mode: "max" diff --git a/src/otx/config/callbacks/hlabel_classification.yaml b/src/otx/config/callbacks/hlabel_classification.yaml deleted file mode 100644 index fc712ff42c2..00000000000 --- a/src/otx/config/callbacks/hlabel_classification.yaml +++ /dev/null @@ -1,15 +0,0 @@ -defaults: - - default - -model_checkpoint: - dirpath: ${base.output_dir}/checkpoints - filename: "epoch_{epoch:03d}" - monitor: "val/accuracy" - mode: "max" - save_last: True - auto_insert_metric_name: False - -early_stopping: - monitor: "val/accuracy" - patience: 100 - mode: "max" diff --git a/src/otx/config/callbacks/instance_segmentation.yaml b/src/otx/config/callbacks/instance_segmentation.yaml deleted file mode 100644 index 084a986e048..00000000000 --- a/src/otx/config/callbacks/instance_segmentation.yaml +++ /dev/null @@ -1,15 +0,0 @@ -defaults: - - default - -model_checkpoint: - dirpath: ${base.output_dir}/checkpoints - filename: "epoch_{epoch:03d}" - monitor: "val/map_50" - mode: "max" - save_last: True - auto_insert_metric_name: False - -early_stopping: - monitor: "val/map_50" - patience: 100 - mode: "max" diff --git a/src/otx/config/callbacks/multilabel_classification.yaml b/src/otx/config/callbacks/multilabel_classification.yaml deleted file mode 100644 index fc712ff42c2..00000000000 --- a/src/otx/config/callbacks/multilabel_classification.yaml +++ /dev/null @@ -1,15 +0,0 @@ -defaults: - - default - -model_checkpoint: - dirpath: ${base.output_dir}/checkpoints - filename: "epoch_{epoch:03d}" - monitor: "val/accuracy" - mode: "max" - save_last: True - auto_insert_metric_name: False - -early_stopping: - monitor: "val/accuracy" - patience: 100 - mode: "max" diff --git a/src/otx/config/callbacks/segmentation.yaml b/src/otx/config/callbacks/segmentation.yaml deleted file mode 100644 index 1bdc1f76f5d..00000000000 --- a/src/otx/config/callbacks/segmentation.yaml +++ /dev/null @@ -1,15 +0,0 @@ -defaults: - - default - -model_checkpoint: - dirpath: ${base.output_dir}/checkpoints - filename: "epoch_{epoch:03d}" - monitor: "val/mIoU" - mode: "max" - save_last: True - auto_insert_metric_name: False - -early_stopping: - monitor: "val/mIoU" - patience: 100 - mode: "max" diff --git a/src/otx/config/callbacks/visual_prompting.yaml b/src/otx/config/callbacks/visual_prompting.yaml deleted file mode 100644 index 6e23b158173..00000000000 --- a/src/otx/config/callbacks/visual_prompting.yaml +++ /dev/null @@ -1,16 +0,0 @@ -defaults: - - default - -model_checkpoint: - dirpath: ${base.output_dir}/checkpoints - filename: "epoch_{epoch:03d}" - monitor: "val/Dice" - mode: "max" - save_last: True - verbose: True - auto_insert_metric_name: False - -early_stopping: - monitor: "val/Dice" - mode: "max" - verbose: True diff --git a/src/otx/config/data/default.yaml b/src/otx/config/data/default.yaml deleted file mode 100644 index 6f5b31c0d75..00000000000 --- a/src/otx/config/data/default.yaml +++ /dev/null @@ -1,16 +0,0 @@ -data_format: ??? -data_root: ${base.data_dir} - -mem_cache_size: 1GB -mem_cache_img_max_size: null -image_color_channel: RGB - -train_subset: - subset_name: train - num_workers: 2 -val_subset: - subset_name: val - num_workers: 2 -test_subset: - subset_name: test - num_workers: 2 diff --git a/src/otx/config/data/hlabel_mmpretrain.yaml b/src/otx/config/data/hlabel_mmpretrain.yaml deleted file mode 100644 index 91f6329e0ce..00000000000 --- a/src/otx/config/data/hlabel_mmpretrain.yaml +++ /dev/null @@ -1,16 +0,0 @@ -defaults: - - default - -data_format: datumaro - -mem_cache_img_max_size: ${as_int_tuple:500,500} - -train_subset: - batch_size: 64 - transform_lib_type: MMPRETRAIN -val_subset: - batch_size: 64 - transform_lib_type: MMPRETRAIN -test_subset: - batch_size: 64 - transform_lib_type: MMPRETRAIN diff --git a/src/otx/config/data/mmaction_classification.yaml b/src/otx/config/data/mmaction_classification.yaml deleted file mode 100644 index 7b02b5e438c..00000000000 --- a/src/otx/config/data/mmaction_classification.yaml +++ /dev/null @@ -1,16 +0,0 @@ -defaults: - - default - -data_format: kinetics - -mem_cache_img_max_size: ${as_int_tuple:500,500} - -train_subset: - batch_size: 64 - transform_lib_type: MMACTION -val_subset: - batch_size: 64 - transform_lib_type: MMACTION -test_subset: - batch_size: 64 - transform_lib_type: MMACTION diff --git a/src/otx/config/data/mmaction_detection.yaml b/src/otx/config/data/mmaction_detection.yaml deleted file mode 100644 index 269bfce17cf..00000000000 --- a/src/otx/config/data/mmaction_detection.yaml +++ /dev/null @@ -1,16 +0,0 @@ -defaults: - - default - -data_format: ava - -mem_cache_img_max_size: ${as_int_tuple:500,500} - -train_subset: - batch_size: 64 - transform_lib_type: MMACTION -val_subset: - batch_size: 64 - transform_lib_type: MMACTION -test_subset: - batch_size: 64 - transform_lib_type: MMACTION diff --git a/src/otx/config/data/mmdet.yaml b/src/otx/config/data/mmdet.yaml deleted file mode 100644 index ffbaa23dc94..00000000000 --- a/src/otx/config/data/mmdet.yaml +++ /dev/null @@ -1,14 +0,0 @@ -defaults: - - default - -data_format: coco_instances - -train_subset: - batch_size: 8 - transform_lib_type: MMDET -val_subset: - batch_size: 8 - transform_lib_type: MMDET -test_subset: - batch_size: 8 - transform_lib_type: MMDET diff --git a/src/otx/config/data/mmdet_inst_seg.yaml b/src/otx/config/data/mmdet_inst_seg.yaml deleted file mode 100644 index a90ae034f4c..00000000000 --- a/src/otx/config/data/mmdet_inst_seg.yaml +++ /dev/null @@ -1,16 +0,0 @@ -defaults: - - default - - base_inst_seg - -data_format: coco_instances -include_polygons: true - -train_subset: - batch_size: 8 - transform_lib_type: MMDET -val_subset: - batch_size: 8 - transform_lib_type: MMDET -test_subset: - batch_size: 8 - transform_lib_type: MMDET diff --git a/src/otx/config/data/mmdet_visual_prompting.yaml b/src/otx/config/data/mmdet_visual_prompting.yaml deleted file mode 100644 index 049c1af1a20..00000000000 --- a/src/otx/config/data/mmdet_visual_prompting.yaml +++ /dev/null @@ -1,111 +0,0 @@ -defaults: - - default - - base_inst_seg - -data_format: coco_instances -include_polygons: false - -train_subset: - batch_size: 2 - num_workers: 4 - transform_lib_type: MMDET - transforms: - - type: LoadImageFromFile - backend_args: null - - type: LoadAnnotations - with_bbox: true - with_mask: false - - type: PerturbBoundingBoxes - offset: 0 # To be applied - - type: Resize - keep_ratio: true - scale: - - 1024 - - 1024 - - type: Pad - size: - - 1024 - - 1024 - - type: Normalize - to_rgb: False - mean: - - 123.675 - - 116.28 - - 103.53 - std: - - 58.395 - - 57.12 - - 57.375 - - type: PackDetInputs -val_subset: - batch_size: 1 - num_workers: 4 - transform_lib_type: MMDET - transforms: - - type: LoadImageFromFile - backend_args: null - - type: LoadAnnotations - with_bbox: true - with_mask: false - - type: Resize - keep_ratio: true - scale: - - 1024 - - 1024 - - type: Pad - size: - - 1024 - - 1024 - - type: Normalize - to_rgb: False - mean: - - 123.675 - - 116.28 - - 103.53 - std: - - 58.395 - - 57.12 - - 57.375 - - type: PackDetInputs - meta_keys: - - img_id - - img_path - - ori_shape - - img_shape - - scale_factor -test_subset: - batch_size: 1 - num_workers: 4 - transform_lib_type: MMDET - transforms: - - type: LoadImageFromFile - backend_args: null - - type: LoadAnnotations - with_bbox: true - with_mask: false - - type: Resize - keep_ratio: true - scale: - - 1024 - - 1024 - - type: Pad - size: - - 1024 - - 1024 - - type: Normalize - to_rgb: False - mean: - - 123.675 - - 116.28 - - 103.53 - std: - - 58.395 - - 57.12 - - 57.375 - - type: PackDetInputs - meta_keys: - - img_id - - img_path - - ori_shape - - img_shape - - scale_factor diff --git a/src/otx/config/data/multiclass_mmpretrain.yaml b/src/otx/config/data/multiclass_mmpretrain.yaml deleted file mode 100644 index 2621f7f05da..00000000000 --- a/src/otx/config/data/multiclass_mmpretrain.yaml +++ /dev/null @@ -1,16 +0,0 @@ -defaults: - - default - -data_format: imagenet_with_subset_dirs - -mem_cache_img_max_size: ${as_int_tuple:500,500} - -train_subset: - batch_size: 64 - transform_lib_type: MMPRETRAIN -val_subset: - batch_size: 64 - transform_lib_type: MMPRETRAIN -test_subset: - batch_size: 64 - transform_lib_type: MMPRETRAIN diff --git a/src/otx/config/data/multilabel_mmpretrain.yaml b/src/otx/config/data/multilabel_mmpretrain.yaml deleted file mode 100644 index 91f6329e0ce..00000000000 --- a/src/otx/config/data/multilabel_mmpretrain.yaml +++ /dev/null @@ -1,16 +0,0 @@ -defaults: - - default - -data_format: datumaro - -mem_cache_img_max_size: ${as_int_tuple:500,500} - -train_subset: - batch_size: 64 - transform_lib_type: MMPRETRAIN -val_subset: - batch_size: 64 - transform_lib_type: MMPRETRAIN -test_subset: - batch_size: 64 - transform_lib_type: MMPRETRAIN diff --git a/src/otx/config/data/openvino.yaml b/src/otx/config/data/openvino.yaml deleted file mode 100644 index 90710db5dea..00000000000 --- a/src/otx/config/data/openvino.yaml +++ /dev/null @@ -1,20 +0,0 @@ -defaults: - - default - -image_color_channel: BGR - -train_subset: - transform_lib_type: TORCHVISION - transforms: - - _target_: torchvision.transforms.v2.ToImage - batch_size: 1 -val_subset: - transform_lib_type: TORCHVISION - transforms: - - _target_: torchvision.transforms.v2.ToImage - batch_size: 1 -test_subset: - transform_lib_type: TORCHVISION - transforms: - - _target_: torchvision.transforms.v2.ToImage - batch_size: 1 diff --git a/src/otx/config/data/segmentation.yaml b/src/otx/config/data/segmentation.yaml deleted file mode 100644 index 9cc400c2428..00000000000 --- a/src/otx/config/data/segmentation.yaml +++ /dev/null @@ -1,17 +0,0 @@ -defaults: - - default - -data_format: common_semantic_segmentation_with_subset_dirs - -train_subset: - batch_size: 8 - num_workers: 4 - transform_lib_type: MMSEG -val_subset: - batch_size: 8 - num_workers: 4 - transform_lib_type: MMSEG -test_subset: - batch_size: 8 - num_workers: 4 - transform_lib_type: MMSEG diff --git a/src/otx/config/data/torchvision_cls.yaml b/src/otx/config/data/torchvision_cls.yaml deleted file mode 100644 index 846b4b43d4b..00000000000 --- a/src/otx/config/data/torchvision_cls.yaml +++ /dev/null @@ -1,49 +0,0 @@ -defaults: - - default - -data_format: imagenet_with_subset_dirs - -mem_cache_img_max_size: ${as_int_tuple:500,500} - -train_subset: - transform_lib_type: TORCHVISION - transforms: - - _target_: torchvision.transforms.v2.RandomResizedCrop - size: [224, 224] - antialias: True - - _target_: torchvision.transforms.v2.RandomHorizontalFlip - p: 0.5 - - _target_: torchvision.transforms.v2.ToDtype - dtype: ${as_torch_dtype:torch.float32} - scale: True - - _target_: torchvision.transforms.v2.Normalize - mean: [0.485, 0.456, 0.406] - std: [0.229, 0.224, 0.225] -val_subset: - transform_lib_type: TORCHVISION - transforms: - - _target_: torchvision.transforms.v2.Resize - size: [256, 256] - antialias: True - - _target_: torchvision.transforms.v2.CenterCrop - size: [224, 224] - - _target_: torchvision.transforms.v2.ToDtype - dtype: ${as_torch_dtype:torch.float32} - scale: True - - _target_: torchvision.transforms.v2.Normalize - mean: [0.485, 0.456, 0.406] - std: [0.229, 0.224, 0.225] -test_subset: - transform_lib_type: TORCHVISION - transforms: - - _target_: torchvision.transforms.v2.Resize - size: [256, 256] - antialias: True - - _target_: torchvision.transforms.v2.CenterCrop - size: [224, 224] - - _target_: torchvision.transforms.v2.ToDtype - dtype: ${as_torch_dtype:torch.float32} - scale: True - - _target_: torchvision.transforms.v2.Normalize - mean: [0.485, 0.456, 0.406] - std: [0.229, 0.224, 0.225] diff --git a/src/otx/config/data/torchvision_visual_prompting.yaml b/src/otx/config/data/torchvision_visual_prompting.yaml deleted file mode 100644 index 9b70abf0c41..00000000000 --- a/src/otx/config/data/torchvision_visual_prompting.yaml +++ /dev/null @@ -1,54 +0,0 @@ -defaults: - - default - - base_inst_seg - -data_format: coco_instances -include_polygons: false - -train_subset: - batch_size: 2 - num_workers: 0 - transform_lib_type: TORCHVISION - transforms: - # - _target_: otx.core.data.transform_libs.torchvision.PerturbBoundingBoxes - # offset: 20 - - _target_: torchvision.transforms.v2.Resize - size: 1023 - max_size: 1024 - - _target_: otx.core.data.transform_libs.torchvision.PadtoSquare - - _target_: torchvision.transforms.v2.ToDtype - dtype: ${as_torch_dtype:torch.float32} - scale: False - - _target_: torchvision.transforms.v2.Normalize - mean: [123.675, 116.28, 103.53] - std: [58.395, 57.12, 57.375] -val_subset: - batch_size: 1 - num_workers: 0 - transform_lib_type: TORCHVISION - transforms: - - _target_: torchvision.transforms.v2.Resize - size: 1023 - max_size: 1024 - - _target_: otx.core.data.transform_libs.torchvision.PadtoSquare - - _target_: torchvision.transforms.v2.ToDtype - dtype: ${as_torch_dtype:torch.float32} - scale: False - - _target_: torchvision.transforms.v2.Normalize - mean: [123.675, 116.28, 103.53] - std: [58.395, 57.12, 57.375] -test_subset: - batch_size: 1 - num_workers: 0 - transform_lib_type: TORCHVISION - transforms: - - _target_: torchvision.transforms.v2.Resize - size: 1023 - max_size: 1024 - - _target_: otx.core.data.transform_libs.torchvision.PadtoSquare - - _target_: torchvision.transforms.v2.ToDtype - dtype: ${as_torch_dtype:torch.float32} - scale: False - - _target_: torchvision.transforms.v2.Normalize - mean: [123.675, 116.28, 103.53] - std: [58.395, 57.12, 57.375] diff --git a/src/otx/config/debug/default.yaml b/src/otx/config/debug/default.yaml deleted file mode 100644 index 1886902b39f..00000000000 --- a/src/otx/config/debug/default.yaml +++ /dev/null @@ -1,35 +0,0 @@ -# @package _global_ - -# default debugging setup, runs 1 full epoch -# other debugging configs can inherit from this one - -# overwrite task name so debugging logs are stored in separate folder -task_name: "debug" - -# disable callbacks and loggers during debugging -callbacks: null -logger: null - -extras: - ignore_warnings: False - enforce_tags: False - -# sets level of all command line loggers to 'DEBUG' -# https://hydra.cc/docs/tutorials/basic/running_your_app/logging/ -hydra: - job_logging: - root: - level: DEBUG - - # use this to also set hydra loggers to 'DEBUG' - # verbose: True - -trainer: - max_epochs: 1 - accelerator: cpu # debuggers don't like gpus - devices: 1 # debuggers don't like multiprocessing - detect_anomaly: true # raise exception if NaN or +/-inf is detected in any tensor - -data: - num_workers: 0 # debuggers don't like multiprocessing - pin_memory: False # disable gpu memory pin diff --git a/src/otx/config/debug/fdr.yaml b/src/otx/config/debug/fdr.yaml deleted file mode 100644 index 7f2d34fa37c..00000000000 --- a/src/otx/config/debug/fdr.yaml +++ /dev/null @@ -1,9 +0,0 @@ -# @package _global_ - -# runs 1 train, 1 validation and 1 test step - -defaults: - - default - -trainer: - fast_dev_run: true diff --git a/src/otx/config/debug/intg_test.yaml b/src/otx/config/debug/intg_test.yaml deleted file mode 100644 index b89cc33ccd0..00000000000 --- a/src/otx/config/debug/intg_test.yaml +++ /dev/null @@ -1,19 +0,0 @@ -# @package _global_ - -# default Integration Test setup, runs 2 epochs - -# sets level of all command line loggers to 'DEBUG' -# https://hydra.cc/docs/tutorials/basic/running_your_app/logging/ -hydra: - job_logging: - root: - level: DEBUG - - # use this to also set hydra loggers to 'DEBUG' - # verbose: True - -trainer: - max_epochs: 2 - accelerator: gpu - check_val_every_n_epoch: 1 - devices: 1 diff --git a/src/otx/config/debug/limit.yaml b/src/otx/config/debug/limit.yaml deleted file mode 100644 index 514d77fbd14..00000000000 --- a/src/otx/config/debug/limit.yaml +++ /dev/null @@ -1,12 +0,0 @@ -# @package _global_ - -# uses only 1% of the training data and 5% of validation/test data - -defaults: - - default - -trainer: - max_epochs: 3 - limit_train_batches: 0.01 - limit_val_batches: 0.05 - limit_test_batches: 0.05 diff --git a/src/otx/config/debug/overfit.yaml b/src/otx/config/debug/overfit.yaml deleted file mode 100644 index 9906586a67a..00000000000 --- a/src/otx/config/debug/overfit.yaml +++ /dev/null @@ -1,13 +0,0 @@ -# @package _global_ - -# overfits to 3 batches - -defaults: - - default - -trainer: - max_epochs: 20 - overfit_batches: 3 - -# model ckpt and early stopping need to be disabled during overfitting -callbacks: null diff --git a/src/otx/config/debug/profiler.yaml b/src/otx/config/debug/profiler.yaml deleted file mode 100644 index 2bd7da87ae2..00000000000 --- a/src/otx/config/debug/profiler.yaml +++ /dev/null @@ -1,12 +0,0 @@ -# @package _global_ - -# runs with execution time profiling - -defaults: - - default - -trainer: - max_epochs: 1 - profiler: "simple" - # profiler: "advanced" - # profiler: "pytorch" diff --git a/src/otx/config/hydra/default.yaml b/src/otx/config/hydra/default.yaml deleted file mode 100644 index 5f617fbee8c..00000000000 --- a/src/otx/config/hydra/default.yaml +++ /dev/null @@ -1,19 +0,0 @@ -# https://hydra.cc/docs/configure_hydra/intro/ - -# enable color logging -defaults: - - override hydra_logging: colorlog - - override job_logging: colorlog - -# output directory, generated dynamically on each run -run: - dir: ${paths.log_dir}/${task_name}/runs/${now:%Y-%m-%d}_${now:%H-%M-%S} -sweep: - dir: ${paths.log_dir}/${task_name}/multiruns/${now:%Y-%m-%d}_${now:%H-%M-%S} - subdir: ${hydra.job.num} - -job_logging: - handlers: - file: - # Incorporates fix from https://github.com/facebookresearch/hydra/pull/2242 - filename: ${hydra.runtime.output_dir}/${hydra.job.name}.log diff --git a/src/otx/config/hydra/help/otx.yaml b/src/otx/config/hydra/help/otx.yaml deleted file mode 100644 index ed8ea283ed7..00000000000 --- a/src/otx/config/hydra/help/otx.yaml +++ /dev/null @@ -1,39 +0,0 @@ -# App name, override to match the name your app is known by -app_name: OTXv2 - -# Help header, customize to describe your app to your users -header: == ${hydra.help.app_name} == - -footer: |- - Powered by Hydra (https://hydra.cc) - Use --hydra-help to view Hydra specific help - -# Basic Hydra flags: -# $FLAGS_HELP -# -# Config groups, choose one of: -# $APP_CONFIG_GROUPS: All config groups that does not start with hydra/. -# $HYDRA_CONFIG_GROUPS: All the Hydra config groups (starts with hydra/) -# -# Configuration generated with overrides: -# $CONFIG : Generated config -# -template: |- - ${hydra.help.header} - - This is ${hydra.help.app_name}! - You can choose a db driver by appending - == Configuration groups == - Compose your configuration from those groups (db=mysql) - - $APP_CONFIG_GROUPS - - == Config == - This is the config generated for this run. - You can override everything, for example: - python my_app.py db.user=foo db.pass=bar - ------- - $CONFIG - ------- - - ${hydra.help.footer} diff --git a/src/otx/config/logger/aim.yaml b/src/otx/config/logger/aim.yaml deleted file mode 100644 index 8f9f6adad7f..00000000000 --- a/src/otx/config/logger/aim.yaml +++ /dev/null @@ -1,28 +0,0 @@ -# https://aimstack.io/ - -# example usage in lightning module: -# https://github.com/aimhubio/aim/blob/main/examples/pytorch_lightning_track.py - -# open the Aim UI with the following command (run in the folder containing the `.aim` folder): -# `aim up` - -aim: - _target_: aim.pytorch_lightning.AimLogger - repo: ${paths.root_dir} # .aim folder will be created here - # repo: "aim://ip_address:port" # can instead provide IP address pointing to Aim remote tracking server which manages the repo, see https://aimstack.readthedocs.io/en/latest/using/remote_tracking.html# - - # aim allows to group runs under experiment name - experiment: null # any string, set to "default" if not specified - - train_metric_prefix: "train/" - val_metric_prefix: "val/" - test_metric_prefix: "test/" - - # sets the tracking interval in seconds for system usage metrics (CPU, GPU, memory, etc.) - system_tracking_interval: 10 # set to null to disable system metrics tracking - - # enable/disable logging of system params such as installed packages, git info, env vars, etc. - log_system_params: true - - # enable/disable tracking console logs (default value is true) - capture_terminal_logs: false # set to false to avoid infinite console log loop issue https://github.com/aimhubio/aim/issues/2550 diff --git a/src/otx/config/logger/comet.yaml b/src/otx/config/logger/comet.yaml deleted file mode 100644 index e0789274e21..00000000000 --- a/src/otx/config/logger/comet.yaml +++ /dev/null @@ -1,12 +0,0 @@ -# https://www.comet.ml - -comet: - _target_: lightning.pytorch.loggers.comet.CometLogger - api_key: ${oc.env:COMET_API_TOKEN} # api key is loaded from environment variable - save_dir: "${paths.output_dir}" - project_name: "lightning-hydra-template" - rest_api_key: null - # experiment_name: "" - experiment_key: null # set to resume experiment - offline: False - prefix: "" diff --git a/src/otx/config/logger/csv.yaml b/src/otx/config/logger/csv.yaml deleted file mode 100644 index 650df0a85cf..00000000000 --- a/src/otx/config/logger/csv.yaml +++ /dev/null @@ -1,7 +0,0 @@ -# csv logger built in lightning - -csv: - _target_: lightning.pytorch.loggers.csv_logs.CSVLogger - save_dir: "${base.output_dir}" - name: "csv/" - prefix: "" diff --git a/src/otx/config/logger/many_loggers.yaml b/src/otx/config/logger/many_loggers.yaml deleted file mode 100644 index dd586800bdc..00000000000 --- a/src/otx/config/logger/many_loggers.yaml +++ /dev/null @@ -1,9 +0,0 @@ -# train with many loggers at once - -defaults: - # - comet - - csv - # - mlflow - # - neptune - - tensorboard - - wandb diff --git a/src/otx/config/logger/mlflow.yaml b/src/otx/config/logger/mlflow.yaml deleted file mode 100644 index f8fb7e685fa..00000000000 --- a/src/otx/config/logger/mlflow.yaml +++ /dev/null @@ -1,12 +0,0 @@ -# https://mlflow.org - -mlflow: - _target_: lightning.pytorch.loggers.mlflow.MLFlowLogger - # experiment_name: "" - # run_name: "" - tracking_uri: ${paths.log_dir}/mlflow/mlruns # run `mlflow ui` command inside the `logs/mlflow/` dir to open the UI - tags: null - # save_dir: "./mlruns" - prefix: "" - artifact_location: null - # run_id: "" diff --git a/src/otx/config/logger/neptune.yaml b/src/otx/config/logger/neptune.yaml deleted file mode 100644 index 8233c140018..00000000000 --- a/src/otx/config/logger/neptune.yaml +++ /dev/null @@ -1,9 +0,0 @@ -# https://neptune.ai - -neptune: - _target_: lightning.pytorch.loggers.neptune.NeptuneLogger - api_key: ${oc.env:NEPTUNE_API_TOKEN} # api key is loaded from environment variable - project: username/lightning-hydra-template - # name: "" - log_model_checkpoints: True - prefix: "" diff --git a/src/otx/config/logger/tensorboard.yaml b/src/otx/config/logger/tensorboard.yaml deleted file mode 100644 index fd57ccef5ef..00000000000 --- a/src/otx/config/logger/tensorboard.yaml +++ /dev/null @@ -1,10 +0,0 @@ -# https://www.tensorflow.org/tensorboard/ - -tensorboard: - _target_: lightning.pytorch.loggers.tensorboard.TensorBoardLogger - save_dir: "${base.output_dir}/tensorboard/" - name: null - log_graph: False - default_hp_metric: True - prefix: "" - # version: "" diff --git a/src/otx/config/logger/wandb.yaml b/src/otx/config/logger/wandb.yaml deleted file mode 100644 index ece165889b3..00000000000 --- a/src/otx/config/logger/wandb.yaml +++ /dev/null @@ -1,16 +0,0 @@ -# https://wandb.ai - -wandb: - _target_: lightning.pytorch.loggers.wandb.WandbLogger - # name: "" # name of the run (normally generated by wandb) - save_dir: "${paths.output_dir}" - offline: False - id: null # pass correct id to resume experiment! - anonymous: null # enable anonymous logging - project: "lightning-hydra-template" - log_model: False # upload lightning ckpts - prefix: "" # a string to put at the beginning of metric keys - # entity: "" # set to name of your wandb team - group: "" - tags: [] - job_type: "" diff --git a/src/otx/config/model/default.yaml b/src/otx/config/model/default.yaml deleted file mode 100644 index c938721f066..00000000000 --- a/src/otx/config/model/default.yaml +++ /dev/null @@ -1,15 +0,0 @@ -optimizer: - _target_: torch.optim.Adam - _partial_: true - lr: 1e-3 - weight_decay: 0.0 - -scheduler: - _target_: torch.optim.lr_scheduler.ReduceLROnPlateau - _partial_: true - mode: min - factor: 0.1 - patience: 10 - -otx_model: - num_classes: ??? diff --git a/src/otx/config/model/hlabel_mmpretrain.yaml b/src/otx/config/model/hlabel_mmpretrain.yaml deleted file mode 100644 index ba9ba3d6dd5..00000000000 --- a/src/otx/config/model/hlabel_mmpretrain.yaml +++ /dev/null @@ -1,13 +0,0 @@ -defaults: - - default - -_target_: otx.core.model.module.classification.OTXHlabelClsLitModule - -otx_model: - _target_: otx.core.model.entity.classification.MMPretrainHlabelClsModel - num_classes: ??? - num_multiclass_heads: ??? - num_multilabel_classes: ??? - -# compile model for faster training with pytorch 2.0 -torch_compile: false diff --git a/src/otx/config/model/mmaction_classification.yaml b/src/otx/config/model/mmaction_classification.yaml deleted file mode 100644 index 17b41f7784a..00000000000 --- a/src/otx/config/model/mmaction_classification.yaml +++ /dev/null @@ -1,11 +0,0 @@ -defaults: - - default - -_target_: otx.core.model.module.action_classification.OTXActionClsLitModule - -otx_model: - _target_: otx.core.model.entity.action_classification.MMActionCompatibleModel - num_classes: ??? - -# compile model for faster training with pytorch 2.0 -torch_compile: false diff --git a/src/otx/config/model/mmaction_detection.yaml b/src/otx/config/model/mmaction_detection.yaml deleted file mode 100644 index 6a8fe289b78..00000000000 --- a/src/otx/config/model/mmaction_detection.yaml +++ /dev/null @@ -1,11 +0,0 @@ -defaults: - - default - -_target_: otx.core.model.module.action_detection.OTXActionDetLitModule - -otx_model: - _target_: otx.core.model.entity.action_detection.MMActionCompatibleModel - num_classes: ??? - -# compile model for faster training with pytorch 2.0 -torch_compile: false diff --git a/src/otx/config/model/mmdet.yaml b/src/otx/config/model/mmdet.yaml deleted file mode 100644 index 3b4895a0126..00000000000 --- a/src/otx/config/model/mmdet.yaml +++ /dev/null @@ -1,10 +0,0 @@ -defaults: - - default - -_target_: otx.core.model.module.detection.OTXDetectionLitModule - -otx_model: - _target_: otx.core.model.entity.detection.MMDetCompatibleModel - -# compile model for faster training with pytorch 2.0 -torch_compile: false diff --git a/src/otx/config/model/mmdet_inst_seg.yaml b/src/otx/config/model/mmdet_inst_seg.yaml deleted file mode 100644 index 8a1bc66deb2..00000000000 --- a/src/otx/config/model/mmdet_inst_seg.yaml +++ /dev/null @@ -1,22 +0,0 @@ -defaults: - - default - -_target_: otx.core.model.module.instance_segmentation.OTXInstanceSegLitModule - -optimizer: - _target_: torch.optim.SGD - _partial_: true - lr: 0.01 - -scheduler: - _target_: torch.optim.lr_scheduler.ReduceLROnPlateau - _partial_: true - mode: min - factor: 0.1 - patience: 10 - -otx_model: - _target_: otx.core.model.entity.instance_segmentation.MMDetInstanceSegCompatibleModel - -# compile model for faster training with pytorch 2.0 -torch_compile: false diff --git a/src/otx/config/model/mmseg.yaml b/src/otx/config/model/mmseg.yaml deleted file mode 100644 index 0c7f6b93b70..00000000000 --- a/src/otx/config/model/mmseg.yaml +++ /dev/null @@ -1,19 +0,0 @@ -_target_: otx.core.model.module.segmentation.OTXSegmentationLitModule - -optimizer: - _target_: torch.optim.AdamW - _partial_: true - lr: 0.00006 - betas: [0.9, 0.999] - weight_decay: 0.01 - -scheduler: - _target_: torch.optim.lr_scheduler.PolynomialLR - _partial_: true - -otx_model: - _target_: otx.core.model.entity.segmentation.MMSegCompatibleModel - num_classes: ??? - -# compile model for faster training with pytorch 2.0 -torch_compile: false diff --git a/src/otx/config/model/multiclass_mmpretrain.yaml b/src/otx/config/model/multiclass_mmpretrain.yaml deleted file mode 100644 index b51b2832179..00000000000 --- a/src/otx/config/model/multiclass_mmpretrain.yaml +++ /dev/null @@ -1,11 +0,0 @@ -defaults: - - default - -_target_: otx.core.model.module.classification.OTXMulticlassClsLitModule - -otx_model: - _target_: otx.core.model.entity.classification.MMPretrainMulticlassClsModel - num_classes: ??? - -# compile model for faster training with pytorch 2.0 -torch_compile: false diff --git a/src/otx/config/model/multilabel_mmpretrain.yaml b/src/otx/config/model/multilabel_mmpretrain.yaml deleted file mode 100644 index 320007faa95..00000000000 --- a/src/otx/config/model/multilabel_mmpretrain.yaml +++ /dev/null @@ -1,11 +0,0 @@ -defaults: - - default - -_target_: otx.core.model.module.classification.OTXMultilabelClsLitModule - -otx_model: - _target_: otx.core.model.entity.classification.MMPretrainMultilabelClsModel - num_classes: ??? - -# compile model for faster training with pytorch 2.0 -torch_compile: false diff --git a/src/otx/config/model/torch_classification.yaml b/src/otx/config/model/torch_classification.yaml deleted file mode 100644 index 69c324a05dd..00000000000 --- a/src/otx/config/model/torch_classification.yaml +++ /dev/null @@ -1,11 +0,0 @@ -defaults: - - default - -_target_: otx.core.model.module.classification.OTXMulticlassClsLitModule - -otx_model: - _target_: otx.core.model.entity.classification.OTXMulticlassClsModel - config: ??? - -# compile model for faster training with pytorch 2.0 -torch_compile: false diff --git a/src/otx/config/model/torch_visual_prompting.yaml b/src/otx/config/model/torch_visual_prompting.yaml deleted file mode 100644 index 14c6fcd6e13..00000000000 --- a/src/otx/config/model/torch_visual_prompting.yaml +++ /dev/null @@ -1,10 +0,0 @@ -defaults: - - default - -_target_: otx.core.model.module.visual_prompting.OTXVisualPromptingLitModule - -otx_model: - _target_: otx.core.model.entity.visual_prompting.OTXVisualPromptingModel - -# compile model for faster training with pytorch 2.0 -torch_compile: false diff --git a/src/otx/config/test.yaml b/src/otx/config/test.yaml deleted file mode 100644 index 0a4ebc9b411..00000000000 --- a/src/otx/config/test.yaml +++ /dev/null @@ -1,15 +0,0 @@ -defaults: - - base_config - - base: default - - callbacks: null - - data: default - - trainer: default - - model: mmdet - - logger: csv - - _self_ - -hydra: - searchpath: - - pkg://otx - runtime: - output_dir: ${base.output_dir} diff --git a/src/otx/config/train.yaml b/src/otx/config/train.yaml deleted file mode 100644 index c124e45eeee..00000000000 --- a/src/otx/config/train.yaml +++ /dev/null @@ -1,23 +0,0 @@ -defaults: - - base_config - - base: default - - callbacks: default - - data: default - - trainer: default - - model: mmdet - - logger: csv - - _self_ - -train: true -test: false - -# If set it with an integer value, e.g. `seed: 1`, -# Lightning derives unique seeds across all dataloader workers and processes for torch, numpy and stdlib random number generators. -seed: null -checkpoint: null - -hydra: - searchpath: - - pkg://otx - runtime: - output_dir: ${base.output_dir} diff --git a/src/otx/config/trainer/auto.yaml b/src/otx/config/trainer/auto.yaml deleted file mode 100644 index 75e610db0c2..00000000000 --- a/src/otx/config/trainer/auto.yaml +++ /dev/null @@ -1,5 +0,0 @@ -defaults: - - default - -accelerator: auto -devices: 1 diff --git a/src/otx/config/trainer/cpu.yaml b/src/otx/config/trainer/cpu.yaml deleted file mode 100644 index 43e7f0b42fc..00000000000 --- a/src/otx/config/trainer/cpu.yaml +++ /dev/null @@ -1,6 +0,0 @@ -defaults: - - default - -accelerator: cpu -devices: 1 -precision: 32 diff --git a/src/otx/config/trainer/ddp.yaml b/src/otx/config/trainer/ddp.yaml deleted file mode 100644 index ab8f89004c3..00000000000 --- a/src/otx/config/trainer/ddp.yaml +++ /dev/null @@ -1,9 +0,0 @@ -defaults: - - default - -strategy: ddp - -accelerator: gpu -devices: 4 -num_nodes: 1 -sync_batchnorm: True diff --git a/src/otx/config/trainer/ddp_sim.yaml b/src/otx/config/trainer/ddp_sim.yaml deleted file mode 100644 index 8404419e5c2..00000000000 --- a/src/otx/config/trainer/ddp_sim.yaml +++ /dev/null @@ -1,7 +0,0 @@ -defaults: - - default - -# simulate DDP on CPU, useful for debugging -accelerator: cpu -devices: 2 -strategy: ddp_spawn diff --git a/src/otx/config/trainer/default.yaml b/src/otx/config/trainer/default.yaml deleted file mode 100644 index 9ba1432c0ab..00000000000 --- a/src/otx/config/trainer/default.yaml +++ /dev/null @@ -1,21 +0,0 @@ -_target_: lightning.pytorch.trainer.Trainer - -default_root_dir: ${base.output_dir} - -min_epochs: 1 # prevents early stopping -max_epochs: 10 - -accelerator: cpu -devices: 1 - -# mixed precision for extra speed-up -precision: 16 - -# perform a validation loop every N training epochs -check_val_every_n_epoch: 1 - -# set True to to ensure deterministic results -# makes training slower but gives more reproducibility than just setting seeds -deterministic: False - -gradient_clip_val: null diff --git a/src/otx/config/trainer/gpu.yaml b/src/otx/config/trainer/gpu.yaml deleted file mode 100644 index b2389510a90..00000000000 --- a/src/otx/config/trainer/gpu.yaml +++ /dev/null @@ -1,5 +0,0 @@ -defaults: - - default - -accelerator: gpu -devices: 1 diff --git a/src/otx/config/trainer/mps.yaml b/src/otx/config/trainer/mps.yaml deleted file mode 100644 index 1ecf6d5cc3a..00000000000 --- a/src/otx/config/trainer/mps.yaml +++ /dev/null @@ -1,5 +0,0 @@ -defaults: - - default - -accelerator: mps -devices: 1 diff --git a/src/otx/core/config/__init__.py b/src/otx/core/config/__init__.py index 60d59c154eb..a17d8a25607 100644 --- a/src/otx/core/config/__init__.py +++ b/src/otx/core/config/__init__.py @@ -4,47 +4,14 @@ """Config data type objects.""" from __future__ import annotations -from dataclasses import dataclass -from typing import TYPE_CHECKING, Optional +from typing import TYPE_CHECKING, Any, _SpecialForm -from .base import BaseConfig -from .data import DataModuleConfig, InstSegDataModuleConfig -from .model import ModelConfig -from .trainer import TrainerConfig +import yaml if TYPE_CHECKING: from torch import dtype -@dataclass -class TrainConfig: - """DTO for training. - - Attributes: - seed: If set it with an integer value, e.g. `seed=1`, - Lightning derives unique seeds across all dataloader workers and processes - for torch, numpy and stdlib random number generators. - checkpoint: The path to the checkpoint file. e.g. `checkpoint=outputs/checkpoints/epoch_000.ckpt` - Path/URL of the checkpoint from which training is resumed. - If there is no checkpoint file at the path, an exception is raised. - """ - - base: BaseConfig - callbacks: dict - data: DataModuleConfig - trainer: TrainerConfig - model: ModelConfig - logger: dict - recipe: Optional[str] - debug: Optional[str] - train: bool - test: bool - resume: bool = False - - seed: Optional[int] = None - checkpoint: Optional[str] = None - - def as_int_tuple(*args) -> tuple[int, ...]: """Resolve YAML list into Python integer tuple. @@ -66,9 +33,10 @@ def as_torch_dtype(arg: str) -> dtype: ```yaml transforms: - - _target_: torchvision.transforms.v2.ToDtype - dtype: ${as_torch_dtype:torch.float32} - scale: True + - class_path: torchvision.transforms.v2.ToDtype + init_args: + dtype: ${as_torch_dtype:torch.float32} + scale: True ``` """ import torch @@ -109,17 +77,66 @@ def as_torch_dtype(arg: str) -> dtype: return mapping[key] +def dtype_representer(dumper: yaml.Dumper | yaml.representer.SafeRepresenter, data: dtype) -> yaml.ScalarNode: + """Custom representer for converting dtype object to YAML sequence node. + + Args: + dumper (yaml.Dumper): The YAML dumper object. + data (dtype): The dtype object to be converted. + + Returns: + yaml.Node: The converted YAML node. + """ + return dumper.represent_str("${as_torch_dtype:" + str(data) + "}") + + +def any_representer(dumper: yaml.Dumper | yaml.representer.SafeRepresenter, data: Any) -> yaml.ScalarNode: # noqa: ANN401 + """Representer function that converts any data to a YAML node. + + Args: + dumper (yaml.Dumper | yaml.representer.SafeRepresenter): The YAML dumper or safe representer. + data (Any): The data to be represented. + + Returns: + yaml.Node: The YAML node representing the data. + """ + return dumper.represent_none(data) + + +def ignore_aliases(self: yaml.representer.SafeRepresenter, data: Any) -> bool: # noqa: ARG001, ANN401 + """Determine whether to ignore aliases in YAML representation. + + Args: + data: The data to check. + + Returns: + bool | None: True if aliases should be ignored, None otherwise. + """ + from torch import dtype + + if data is None: + return True + if isinstance(data, tuple) and data == (): + return True + if isinstance(data, (str, bytes, bool, int, float, dtype)): + return True + return None + + def register_configs() -> None: - """Register DTO as default and custom resolvers to hydra.""" - from hydra.core.config_store import ConfigStore + """Register custom resolvers.""" from omegaconf import OmegaConf - cs = ConfigStore.instance() - cs.store(name="base_config", node=TrainConfig) - cs.store(group="data", name="base_inst_seg", node=InstSegDataModuleConfig) - OmegaConf.register_new_resolver("as_int_tuple", as_int_tuple, replace=True) OmegaConf.register_new_resolver("as_torch_dtype", as_torch_dtype, replace=True) + from torch import dtype + + yaml.add_representer(dtype, dtype_representer) # For lightnig_logs + # For jsonargparse's SafeDumper + yaml.SafeDumper.add_representer(dtype, dtype_representer) + yaml.SafeDumper.add_representer(_SpecialForm, any_representer) # typing.Any for DictConfig + yaml.SafeDumper.ignore_aliases = ignore_aliases # type: ignore # noqa: PGH003 + register_configs() diff --git a/src/otx/core/config/base.py b/src/otx/core/config/base.py deleted file mode 100644 index ffaaacb62ef..00000000000 --- a/src/otx/core/config/base.py +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright (C) 2023 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 -# -"""Config data type objects for base.""" - -from dataclasses import dataclass -from pathlib import Path - -from otx.core.types.task import OTXTaskType - - -@dataclass -class BaseConfig: - """DTO for base configuration.""" - - task: OTXTaskType - - work_dir: Path - data_dir: Path - log_dir: Path - output_dir: Path diff --git a/src/otx/core/config/callbacks.py b/src/otx/core/config/callbacks.py deleted file mode 100644 index e19d8e1ed7a..00000000000 --- a/src/otx/core/config/callbacks.py +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright (C) 2023 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 -# -"""Config data type objects for callbacks.""" diff --git a/src/otx/core/config/data.py b/src/otx/core/config/data.py index 40411e8fbe1..cdb986d5807 100644 --- a/src/otx/core/config/data.py +++ b/src/otx/core/config/data.py @@ -39,9 +39,4 @@ class DataModuleConfig: mem_cache_img_max_size: Optional[Tuple[int, int]] = None image_color_channel: ImageColorChannel = ImageColorChannel.RGB - -@dataclass -class InstSegDataModuleConfig(DataModuleConfig): - """DTO for instance segmentation data module configuration.""" - - include_polygons: bool = True + include_polygons: bool = False diff --git a/src/otx/core/config/debug.py b/src/otx/core/config/debug.py deleted file mode 100644 index 49cf7a65b69..00000000000 --- a/src/otx/core/config/debug.py +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright (C) 2023 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 -# -"""Config data type objects for debug.""" diff --git a/src/otx/core/config/hydra.py b/src/otx/core/config/hydra.py deleted file mode 100644 index f27aaccef60..00000000000 --- a/src/otx/core/config/hydra.py +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright (C) 2023 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 -# -"""Config data type objects for hydra.""" diff --git a/src/otx/core/config/logger.py b/src/otx/core/config/logger.py deleted file mode 100644 index 548e4699a1e..00000000000 --- a/src/otx/core/config/logger.py +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright (C) 2023 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 -# -"""Config data type objects for logger.""" diff --git a/src/otx/core/config/model.py b/src/otx/core/config/model.py deleted file mode 100644 index f62ead935f7..00000000000 --- a/src/otx/core/config/model.py +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright (C) 2023 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 -# -"""Config data type objects for model.""" - -from dataclasses import dataclass - - -@dataclass -class ModelConfig: - """DTO for model configuration.""" - - _target_: str - optimizer: dict - scheduler: dict - otx_model: dict - torch_compile: bool diff --git a/src/otx/core/config/trainer.py b/src/otx/core/config/trainer.py deleted file mode 100644 index 4c23e45934a..00000000000 --- a/src/otx/core/config/trainer.py +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright (C) 2023 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 -# -"""Config data type objects for trainer.""" - -from __future__ import annotations - -from dataclasses import dataclass -from pathlib import Path # noqa: TCH003 -from typing import Optional - -from omegaconf import DictConfig - - -@dataclass -class TrainerConfig(DictConfig): - """DTO for trainer configuration.""" - - default_root_dir: Path - accelerator: str - precision: int - max_epochs: int - min_epochs: int - devices: int - check_val_every_n_epoch: int - deterministic: bool - gradient_clip_val: Optional[float] - - _target_: str = "lightning.pytorch.trainer.Trainer" diff --git a/src/otx/core/data/factory.py b/src/otx/core/data/factory.py index be7db3d1265..519b4a07580 100644 --- a/src/otx/core/data/factory.py +++ b/src/otx/core/data/factory.py @@ -15,7 +15,7 @@ if TYPE_CHECKING: from datumaro import DatasetSubset - from otx.core.config.data import DataModuleConfig, InstSegDataModuleConfig, SubsetConfig + from otx.core.config.data import DataModuleConfig, SubsetConfig from otx.core.data.mem_cache import MemCacheHandlerBase @@ -71,7 +71,7 @@ def create( dm_subset: DatasetSubset, mem_cache_handler: MemCacheHandlerBase, cfg_subset: SubsetConfig, - cfg_data_module: DataModuleConfig | InstSegDataModuleConfig, + cfg_data_module: DataModuleConfig, ) -> OTXDataset: """Create OTXDataset.""" transforms = TransformLibFactory.generate(cfg_subset) diff --git a/src/otx/core/data/module.py b/src/otx/core/data/module.py index 69b24771d7a..fc07554f919 100644 --- a/src/otx/core/data/module.py +++ b/src/otx/core/data/module.py @@ -23,7 +23,7 @@ if TYPE_CHECKING: from lightning.pytorch.utilities.parsing import AttributeDict - from otx.core.config.data import DataModuleConfig, InstSegDataModuleConfig + from otx.core.config.data import DataModuleConfig from otx.core.data.dataset.base import OTXDataset @@ -33,7 +33,7 @@ class OTXDataModule(LightningDataModule): def __init__( self, task: OTXTaskType, - config: DataModuleConfig | InstSegDataModuleConfig, + config: DataModuleConfig, ) -> None: """Constructor.""" super().__init__() diff --git a/src/otx/core/data/transform_libs/torchvision.py b/src/otx/core/data/transform_libs/torchvision.py index 71a18034581..b56a9ddcb13 100644 --- a/src/otx/core/data/transform_libs/torchvision.py +++ b/src/otx/core/data/transform_libs/torchvision.py @@ -8,9 +8,9 @@ from inspect import isclass from typing import TYPE_CHECKING, Any -import hydra import torch import torchvision.transforms.v2 as tvt_v2 +from lightning.pytorch.cli import instantiate_class from torchvision import tv_tensors from torchvision.transforms.v2 import functional as F # noqa: N812 @@ -79,7 +79,7 @@ def generate(cls, config: SubsetConfig) -> Compose: transforms = [] for cfg in config.transforms: - transform = hydra.utils.instantiate(cfg) + transform = instantiate_class(args=(), init=cfg) if type(transform) not in availables: msg = f"transform={transform} is not a valid TorchVision V2 transform" raise ValueError(msg) diff --git a/src/otx/core/model/module/action_classification.py b/src/otx/core/model/module/action_classification.py index e69b038360a..3dcfbc324f2 100644 --- a/src/otx/core/model/module/action_classification.py +++ b/src/otx/core/model/module/action_classification.py @@ -4,6 +4,8 @@ """Class definition for action classification lightning module used in OTX.""" from __future__ import annotations +from typing import TYPE_CHECKING + import torch from torch import Tensor from torchmetrics.classification.accuracy import Accuracy @@ -15,6 +17,9 @@ from otx.core.model.entity.action_classification import OTXActionClsModel from otx.core.model.module.base import OTXLitModule +if TYPE_CHECKING: + from lightning.pytorch.cli import LRSchedulerCallable, OptimizerCallable + class OTXActionClsLitModule(OTXLitModule): """Base class for the lightning module used in OTX detection task.""" @@ -22,11 +27,16 @@ class OTXActionClsLitModule(OTXLitModule): def __init__( self, otx_model: OTXActionClsModel, - optimizer: torch.optim.Optimizer, - scheduler: torch.optim.lr_scheduler.LRScheduler, torch_compile: bool, + optimizer: OptimizerCallable = lambda p: torch.optim.SGD(p, lr=0.01), + scheduler: LRSchedulerCallable = torch.optim.lr_scheduler.ConstantLR, ): - super().__init__(otx_model, optimizer, scheduler, torch_compile) + super().__init__( + otx_model=otx_model, + torch_compile=torch_compile, + optimizer=optimizer, + scheduler=scheduler, + ) num_classes = otx_model.config.get("cls_head", {}).get("num_classes", None) self.val_metric = Accuracy(task="multiclass", num_classes=num_classes) self.test_metric = Accuracy(task="multiclass", num_classes=num_classes) diff --git a/src/otx/core/model/module/action_detection.py b/src/otx/core/model/module/action_detection.py index e196c522ddc..3bc50e2486e 100644 --- a/src/otx/core/model/module/action_detection.py +++ b/src/otx/core/model/module/action_detection.py @@ -5,6 +5,7 @@ from __future__ import annotations import logging as log +from typing import TYPE_CHECKING import torch from torch import Tensor @@ -17,6 +18,9 @@ from otx.core.model.entity.action_detection import OTXActionDetModel from otx.core.model.module.base import OTXLitModule +if TYPE_CHECKING: + from lightning.pytorch.cli import LRSchedulerCallable, OptimizerCallable + class OTXActionDetLitModule(OTXLitModule): """Base class for the lightning module used in OTX detection task.""" @@ -24,11 +28,16 @@ class OTXActionDetLitModule(OTXLitModule): def __init__( self, otx_model: OTXActionDetModel, - optimizer: torch.optim.Optimizer, - scheduler: torch.optim.lr_scheduler.LRScheduler, torch_compile: bool, + optimizer: OptimizerCallable = lambda p: torch.optim.SGD(p, lr=0.01), + scheduler: LRSchedulerCallable = torch.optim.lr_scheduler.ConstantLR, ): - super().__init__(otx_model, optimizer, scheduler, torch_compile) + super().__init__( + otx_model=otx_model, + torch_compile=torch_compile, + optimizer=optimizer, + scheduler=scheduler, + ) self.val_metric = MeanAveragePrecision() self.test_metric = MeanAveragePrecision() diff --git a/src/otx/core/model/module/base.py b/src/otx/core/model/module/base.py index cde6566f065..19096f8634d 100644 --- a/src/otx/core/model/module/base.py +++ b/src/otx/core/model/module/base.py @@ -19,6 +19,8 @@ if TYPE_CHECKING: from pathlib import Path + from lightning.pytorch.cli import LRSchedulerCallable, OptimizerCallable + from otx.core.data.dataset.base import LabelInfo @@ -28,9 +30,9 @@ class OTXLitModule(LightningModule): def __init__( self, otx_model: OTXModel, - optimizer: torch.optim.Optimizer, - scheduler: torch.optim.lr_scheduler.LRScheduler, torch_compile: bool, + optimizer: OptimizerCallable = lambda p: torch.optim.SGD(p, lr=0.01), + scheduler: LRSchedulerCallable = torch.optim.lr_scheduler.ConstantLR, ): super().__init__() diff --git a/src/otx/core/model/module/classification.py b/src/otx/core/model/module/classification.py index 427e5a6b55d..aa35eede925 100644 --- a/src/otx/core/model/module/classification.py +++ b/src/otx/core/model/module/classification.py @@ -25,6 +25,8 @@ from otx.core.model.module.base import OTXLitModule if TYPE_CHECKING: + from lightning.pytorch.cli import LRSchedulerCallable, OptimizerCallable + from otx.core.data.dataset.base import LabelInfo @@ -34,11 +36,16 @@ class OTXMulticlassClsLitModule(OTXLitModule): def __init__( self, otx_model: OTXMulticlassClsModel, - optimizer: torch.optim.Optimizer, - scheduler: torch.optim.lr_scheduler.LRScheduler, torch_compile: bool, + optimizer: OptimizerCallable = lambda p: torch.optim.SGD(p, lr=0.01), + scheduler: LRSchedulerCallable = torch.optim.lr_scheduler.ConstantLR, ): - super().__init__(otx_model, optimizer, scheduler, torch_compile) + super().__init__( + otx_model=otx_model, + torch_compile=torch_compile, + optimizer=optimizer, + scheduler=scheduler, + ) num_classes = otx_model.config.get("head", {}).get("num_classes", None) self.val_metric = Accuracy(task="multiclass", num_classes=num_classes) self.test_metric = Accuracy(task="multiclass", num_classes=num_classes) @@ -123,11 +130,16 @@ class OTXMultilabelClsLitModule(OTXLitModule): def __init__( self, otx_model: OTXMultilabelClsModel, - optimizer: torch.optim.Optimizer, - scheduler: torch.optim.lr_scheduler.LRScheduler, torch_compile: bool, + optimizer: OptimizerCallable = lambda p: torch.optim.SGD(p, lr=0.01), + scheduler: LRSchedulerCallable = torch.optim.lr_scheduler.ConstantLR, ): - super().__init__(otx_model, optimizer, scheduler, torch_compile) + super().__init__( + otx_model=otx_model, + torch_compile=torch_compile, + optimizer=optimizer, + scheduler=scheduler, + ) self.num_labels = otx_model.config.get("head", {}).get("num_classes", None) self.val_metric = MultilabelAccuracy(num_labels=self.num_labels, threshold=0.5, average="micro") @@ -207,11 +219,16 @@ class OTXHlabelClsLitModule(OTXLitModule): def __init__( self, otx_model: OTXHlabelClsModel, - optimizer: torch.optim.Optimizer, - scheduler: torch.optim.lr_scheduler.LRScheduler, torch_compile: bool, + optimizer: OptimizerCallable = lambda p: torch.optim.SGD(p, lr=0.01), + scheduler: LRSchedulerCallable = torch.optim.lr_scheduler.ConstantLR, ): - super().__init__(otx_model, optimizer, scheduler, torch_compile) + super().__init__( + otx_model=otx_model, + torch_compile=torch_compile, + optimizer=optimizer, + scheduler=scheduler, + ) def _set_hlabel_setup(self) -> None: if not isinstance(self.meta_info, HLabelMetaInfo): diff --git a/src/otx/core/model/module/detection.py b/src/otx/core/model/module/detection.py index 20a65a76579..09f3d701e3b 100644 --- a/src/otx/core/model/module/detection.py +++ b/src/otx/core/model/module/detection.py @@ -5,6 +5,7 @@ from __future__ import annotations import logging as log +from typing import TYPE_CHECKING import torch from torch import Tensor @@ -17,6 +18,9 @@ from otx.core.model.entity.detection import OTXDetectionModel from otx.core.model.module.base import OTXLitModule +if TYPE_CHECKING: + from lightning.pytorch.cli import LRSchedulerCallable, OptimizerCallable + class OTXDetectionLitModule(OTXLitModule): """Base class for the lightning module used in OTX detection task.""" @@ -24,11 +28,16 @@ class OTXDetectionLitModule(OTXLitModule): def __init__( self, otx_model: OTXDetectionModel, - optimizer: torch.optim.Optimizer, - scheduler: torch.optim.lr_scheduler.LRScheduler, torch_compile: bool, + optimizer: OptimizerCallable = lambda p: torch.optim.SGD(p, lr=0.01), + scheduler: LRSchedulerCallable = torch.optim.lr_scheduler.ConstantLR, ): - super().__init__(otx_model, optimizer, scheduler, torch_compile) + super().__init__( + otx_model=otx_model, + torch_compile=torch_compile, + optimizer=optimizer, + scheduler=scheduler, + ) self.val_metric = MeanAveragePrecision() self.test_metric = MeanAveragePrecision() diff --git a/src/otx/core/model/module/instance_segmentation.py b/src/otx/core/model/module/instance_segmentation.py index 91ec7ff8cac..08e38a825da 100644 --- a/src/otx/core/model/module/instance_segmentation.py +++ b/src/otx/core/model/module/instance_segmentation.py @@ -5,6 +5,7 @@ from __future__ import annotations import logging as log +from typing import TYPE_CHECKING import torch from torch import Tensor @@ -19,6 +20,9 @@ from otx.core.model.module.base import OTXLitModule from otx.core.utils.mask_util import polygon_to_bitmap +if TYPE_CHECKING: + from lightning.pytorch.cli import LRSchedulerCallable, OptimizerCallable + class OTXInstanceSegLitModule(OTXLitModule): """Base class for the lightning module used in OTX instance segmentation task.""" @@ -26,11 +30,16 @@ class OTXInstanceSegLitModule(OTXLitModule): def __init__( self, otx_model: OTXInstanceSegModel, - optimizer: torch.optim.Optimizer, - scheduler: torch.optim.lr_scheduler.LRScheduler, torch_compile: bool, + optimizer: OptimizerCallable = lambda p: torch.optim.SGD(p, lr=0.01), + scheduler: LRSchedulerCallable = torch.optim.lr_scheduler.ConstantLR, ): - super().__init__(otx_model, optimizer, scheduler, torch_compile) + super().__init__( + otx_model=otx_model, + torch_compile=torch_compile, + optimizer=optimizer, + scheduler=scheduler, + ) self.val_metric = MeanAveragePrecision(iou_type="segm") self.test_metric = MeanAveragePrecision(iou_type="segm") diff --git a/src/otx/core/model/module/segmentation.py b/src/otx/core/model/module/segmentation.py index 84e92695482..0153f1df304 100644 --- a/src/otx/core/model/module/segmentation.py +++ b/src/otx/core/model/module/segmentation.py @@ -5,6 +5,7 @@ from __future__ import annotations import logging as log +from typing import TYPE_CHECKING import torch from torch import Tensor @@ -17,6 +18,9 @@ from otx.core.model.entity.segmentation import OTXSegmentationModel from otx.core.model.module.base import OTXLitModule +if TYPE_CHECKING: + from lightning.pytorch.cli import LRSchedulerCallable, OptimizerCallable + class OTXSegmentationLitModule(OTXLitModule): """Base class for the lightning module used in OTX segmentation task.""" @@ -24,11 +28,16 @@ class OTXSegmentationLitModule(OTXLitModule): def __init__( self, otx_model: OTXSegmentationModel, - optimizer: torch.optim.Optimizer, - scheduler: torch.optim.lr_scheduler.LRScheduler, torch_compile: bool, + optimizer: OptimizerCallable = lambda p: torch.optim.SGD(p, lr=0.01), + scheduler: LRSchedulerCallable = torch.optim.lr_scheduler.ConstantLR, ): - super().__init__(otx_model, optimizer, scheduler, torch_compile) + super().__init__( + otx_model=otx_model, + torch_compile=torch_compile, + optimizer=optimizer, + scheduler=scheduler, + ) num_classes = otx_model.config.get("decode_head", {}).get("num_classes", None) if num_classes is None: msg = """JaccardIndex metric cannot be used with num_classes = None. diff --git a/src/otx/core/utils/config.py b/src/otx/core/utils/config.py index 18a64e0caa3..249e50d5661 100644 --- a/src/otx/core/utils/config.py +++ b/src/otx/core/utils/config.py @@ -43,12 +43,13 @@ def to_list(dict_: dict) -> dict: def convert_conf_to_mmconfig_dict( - cfg: DictConfig, + cfg: DictConfig | dict, to: Literal["tuple", "list"] = "tuple", ) -> MMConfig: """Convert OTX format config object to MMEngine config object.""" from mmengine.config import Config as MMConfig + cfg = cfg if isinstance(cfg, DictConfig) else OmegaConf.create(cfg) dict_cfg = OmegaConf.to_container(cfg) if to == "tuple": diff --git a/src/otx/core/utils/instantiators.py b/src/otx/core/utils/instantiators.py index 6aaee6a5db2..897b03d15bc 100644 --- a/src/otx/core/utils/instantiators.py +++ b/src/otx/core/utils/instantiators.py @@ -1,81 +1,89 @@ -# MIT License - -# Copyright (c) 2023 Intel Corporation -# Copyright (c) 2021 ashleve - -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: - -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. - -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# -# This source code is borrowed from https://github.com/ashleve/lightning-hydra-template - -from typing import List - -import hydra -from lightning import Callback -from lightning.pytorch.loggers import Logger -from omegaconf import DictConfig +# Copyright (C) 2024 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +"""Instantiator functions for OTX engine components.""" + +from __future__ import annotations + +from functools import partial +from typing import TYPE_CHECKING + +from lightning.pytorch.cli import instantiate_class from . import pylogger +if TYPE_CHECKING: + from lightning import Callback + from lightning.pytorch.loggers import Logger + + log = pylogger.get_pylogger(__name__) -def instantiate_callbacks(callbacks_cfg: DictConfig) -> List[Callback]: - """Instantiates callbacks from config. +def instantiate_callbacks(callbacks_cfg: list) -> list[Callback]: + """Instantiate a list of callbacks based on the provided configuration. - :param callbacks_cfg: A DictConfig object containing callback configurations. - :return: A list of instantiated callbacks. + Args: + callbacks_cfg (list): A list of callback configurations. + + Returns: + list[Callback]: A list of instantiated callbacks. """ - callbacks: List[Callback] = [] + callbacks: list[Callback] = [] if not callbacks_cfg: log.warning("No callback configs found! Skipping..") return callbacks - if not isinstance(callbacks_cfg, DictConfig): - raise TypeError("Callbacks config must be a DictConfig!") - - for _, cb_conf in callbacks_cfg.items(): - if isinstance(cb_conf, DictConfig) and "_target_" in cb_conf: - log.info(f"Instantiating callback <{cb_conf._target_}>") - callbacks.append(hydra.utils.instantiate(cb_conf)) + for cb_conf in callbacks_cfg: + if isinstance(cb_conf, dict) and "class_path" in cb_conf: + log.info(f"Instantiating callback <{cb_conf['class_path']}>") + callbacks.append(instantiate_class(args=(), init=cb_conf)) return callbacks -def instantiate_loggers(logger_cfg: DictConfig) -> List[Logger]: - """Instantiates loggers from config. +def instantiate_loggers(logger_cfg: list | None) -> list[Logger]: + """Instantiate loggers based on the provided logger configuration. - :param logger_cfg: A DictConfig object containing logger configurations. - :return: A list of instantiated loggers. + Args: + logger_cfg (list | None): The logger configuration. + + Returns: + list[Logger]: The list of instantiated loggers. """ - logger: List[Logger] = [] + logger: list[Logger] = [] if not logger_cfg: log.warning("No logger configs found! Skipping...") return logger - if not isinstance(logger_cfg, DictConfig): - raise TypeError("Logger config must be a DictConfig!") - - for _, lg_conf in logger_cfg.items(): - if isinstance(lg_conf, DictConfig) and "_target_" in lg_conf: - log.info(f"Instantiating logger <{lg_conf._target_}>") - logger.append(hydra.utils.instantiate(lg_conf)) + for lg_conf in logger_cfg: + if isinstance(lg_conf, dict) and "class_path" in lg_conf: + log.info(f"Instantiating logger <{lg_conf['class_path']}>") + logger.append(instantiate_class(args=(), init=lg_conf)) return logger + + +def partial_instantiate_class(init: dict | None) -> partial | None: + """Partially instantiates a class with the given initialization arguments. + + Copy from lightning.pytorch.cli.instantiate_class and modify it to use partial. + + Args: + init (dict): A dictionary containing the initialization arguments. + It should have the following keys: + - "init_args" (dict): A dictionary of keyword arguments to be passed to the class constructor. + - "class_path" (str): The fully qualified path of the class to be instantiated. + + Returns: + partial: A partial object representing the partially instantiated class. + """ + if not init: + return None + kwargs = init.get("init_args", {}) + class_module, class_name = init["class_path"].rsplit(".", 1) + module = __import__(class_module, fromlist=[class_name]) + args_class = getattr(module, class_name) + return partial(args_class, **kwargs) diff --git a/src/otx/core/utils/logging_utils.py b/src/otx/core/utils/logging_utils.py deleted file mode 100644 index 436e2d4b2eb..00000000000 --- a/src/otx/core/utils/logging_utils.py +++ /dev/null @@ -1,82 +0,0 @@ -# MIT License - -# Copyright (c) 2023 Intel Corporation -# Copyright (c) 2021 ashleve - -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: - -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. - -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# -# This source code is borrowed from https://github.com/ashleve/lightning-hydra-template - -from typing import Any, Dict - -from lightning.pytorch.utilities import rank_zero_only -from omegaconf import OmegaConf - -from . import pylogger - -log = pylogger.get_pylogger(__name__) - - -@rank_zero_only -def log_hyperparameters(object_dict: Dict[str, Any]) -> None: - """Controls which config parts are saved by Lightning loggers. - - Additionally saves: - - Number of model parameters - - :param object_dict: A dictionary containing the following objects: - - `"cfg"`: A DictConfig object containing the main config. - - `"model"`: The Lightning model. - - `"trainer"`: The Lightning trainer. - """ - hparams = {} - - cfg = OmegaConf.to_container(object_dict["cfg"]) - model = object_dict["model"] - trainer = object_dict["trainer"] - - if not trainer.logger: - log.warning("Logger not found! Skipping hyperparameter logging...") - return - - hparams["model"] = cfg["model"] - - # save number of model parameters - hparams["model/params/total"] = sum(p.numel() for p in model.parameters()) - hparams["model/params/trainable"] = sum( - p.numel() for p in model.parameters() if p.requires_grad - ) - hparams["model/params/non_trainable"] = sum( - p.numel() for p in model.parameters() if not p.requires_grad - ) - - hparams["data"] = cfg["data"] - hparams["trainer"] = cfg["trainer"] - - hparams["callbacks"] = cfg.get("callbacks") - hparams["extras"] = cfg.get("extras") - - hparams["task_name"] = cfg.get("task_name") - hparams["tags"] = cfg.get("tags") - hparams["ckpt_path"] = cfg.get("ckpt_path") - hparams["seed"] = cfg.get("seed") - - # send hparams to all loggers - for logger in trainer.loggers: - logger.log_hyperparams(hparams) diff --git a/src/otx/core/utils/pylogger.py b/src/otx/core/utils/pylogger.py index 524bee354a9..7ab29881e22 100644 --- a/src/otx/core/utils/pylogger.py +++ b/src/otx/core/utils/pylogger.py @@ -1,3 +1,5 @@ +"""Pylogger for OTX logger.""" + # MIT License # Copyright (c) 2023 Intel Corporation diff --git a/src/otx/core/utils/rich_utils.py b/src/otx/core/utils/rich_utils.py deleted file mode 100644 index 4fba1403d8c..00000000000 --- a/src/otx/core/utils/rich_utils.py +++ /dev/null @@ -1,124 +0,0 @@ -# MIT License - -# Copyright (c) 2023 Intel Corporation -# Copyright (c) 2021 ashleve - -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: - -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. - -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# -# This source code is borrowed from https://github.com/ashleve/lightning-hydra-template - -from pathlib import Path -from typing import Sequence - -import rich -import rich.syntax -import rich.tree -from hydra.core.hydra_config import HydraConfig -from lightning.pytorch.utilities import rank_zero_only -from omegaconf import DictConfig, OmegaConf, open_dict -from rich.prompt import Prompt - -from . import pylogger - -log = pylogger.get_pylogger(__name__) - - -@rank_zero_only -def print_config_tree( - cfg: DictConfig, - print_order: Sequence[str] = ( - "data", - "model", - "callbacks", - "logger", - "trainer", - "paths", - "extras", - ), - resolve: bool = False, - save_to_file: bool = False, -) -> None: - """Prints the contents of a DictConfig as a tree structure using the Rich library. - - :param cfg: A DictConfig composed by Hydra. - :param print_order: Determines in what order config components are printed. Default is ``("data", "model", - "callbacks", "logger", "trainer", "paths", "extras")``. - :param resolve: Whether to resolve reference fields of DictConfig. Default is ``False``. - :param save_to_file: Whether to export config to the hydra output folder. Default is ``False``. - """ - style = "dim" - tree = rich.tree.Tree("CONFIG", style=style, guide_style=style) - - queue = [] - - # add fields from `print_order` to queue - for field in print_order: - queue.append(field) if field in cfg else log.warning( - f"Field '{field}' not found in config. Skipping '{field}' config printing...", - ) - - # add all the other fields to queue (not specified in `print_order`) - for field in cfg: - if field not in queue: - queue.append(field) - - # generate config tree from queue - for field in queue: - branch = tree.add(field, style=style, guide_style=style) - - config_group = cfg[field] - if isinstance(config_group, DictConfig): - branch_content = OmegaConf.to_yaml(config_group, resolve=resolve) - else: - branch_content = str(config_group) - - branch.add(rich.syntax.Syntax(branch_content, "yaml")) - - # print config tree - rich.print(tree) - - # save config tree to file - if save_to_file: - with open(Path(cfg.paths.output_dir, "config_tree.log"), "w") as file: - rich.print(tree, file=file) - - -@rank_zero_only -def enforce_tags(cfg: DictConfig, save_to_file: bool = False) -> None: - """Prompts user to input tags from command line if no tags are provided in config. - - :param cfg: A DictConfig composed by Hydra. - :param save_to_file: Whether to export tags to the hydra output folder. Default is ``False``. - """ - if not cfg.get("tags"): - if "id" in HydraConfig().cfg.hydra.job: - raise ValueError("Specify tags before launching a multirun!") - - log.warning("No tags provided in config. Prompting user to input tags...") - tags = Prompt.ask("Enter a list of comma separated tags", default="dev") - tags = [t.strip() for t in tags.split(",") if t != ""] - - with open_dict(cfg): - cfg.tags = tags - - log.info(f"Tags: {cfg.tags}") - - if save_to_file: - with open(Path(cfg.paths.output_dir, "tags.log"), "w") as file: - rich.print(cfg.tags, file=file) diff --git a/src/otx/core/utils/utils.py b/src/otx/core/utils/utils.py deleted file mode 100644 index 6c47f0c3b60..00000000000 --- a/src/otx/core/utils/utils.py +++ /dev/null @@ -1,144 +0,0 @@ -# MIT License - -# Copyright (c) 2023 Intel Corporation -# Copyright (c) 2021 ashleve - -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: - -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. - -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# -# This source code is borrowed from https://github.com/ashleve/lightning-hydra-template - -import warnings -from importlib.util import find_spec -from typing import Any, Callable, Dict, Optional, Tuple - -from omegaconf import DictConfig - -from . import pylogger, rich_utils - -log = pylogger.get_pylogger(__name__) - - -def extras(cfg: DictConfig) -> None: - """Applies optional utilities before the task is started. - - Utilities: - - Ignoring python warnings - - Setting tags from command line - - Rich config printing - - :param cfg: A DictConfig object containing the config tree. - """ - # return if no `extras` config - if not cfg.get("extras"): - log.warning("Extras config not found! ") - return - - # disable python warnings - if cfg.extras.get("ignore_warnings"): - log.info("Disabling python warnings! ") - warnings.filterwarnings("ignore") - - # prompt user to input tags from command line if none are provided in the config - if cfg.extras.get("enforce_tags"): - log.info("Enforcing tags! ") - rich_utils.enforce_tags(cfg, save_to_file=True) - - # pretty print config tree using Rich library - if cfg.extras.get("print_config"): - log.info("Printing config tree with Rich! ") - rich_utils.print_config_tree(cfg, resolve=True, save_to_file=True) - - -def task_wrapper(task_func: Callable) -> Callable: - """Optional decorator that controls the failure behavior when executing the task function. - - This wrapper can be used to: - - make sure loggers are closed even if the task function raises an exception (prevents multirun failure) - - save the exception to a `.log` file - - mark the run as failed with a dedicated file in the `logs/` folder (so we can find and rerun it later) - - etc. (adjust depending on your needs) - - Example: - ``` - @utils.task_wrapper - def train(cfg: DictConfig) -> Tuple[Dict[str, Any], Dict[str, Any]]: - ... - return metric_dict, object_dict - ``` - - :param task_func: The task function to be wrapped. - - :return: The wrapped task function. - """ - - def wrap(cfg: DictConfig) -> Tuple[Dict[str, Any], Dict[str, Any]]: - # execute the task - try: - metric_dict, object_dict = task_func(cfg=cfg) - - # things to do if exception occurs - except Exception as ex: - # save exception to `.log` file - log.exception("") - - # some hyperparameter combinations might be invalid or cause out-of-memory errors - # so when using hparam search plugins like Optuna, you might want to disable - # raising the below exception to avoid multirun failure - raise ex - - # things to always do after either success or exception - finally: - # display output dir path in terminal - log.info(f"Output dir: {cfg.paths.output_dir}") - - # always close wandb run (even if exception occurs so multirun won't fail) - if find_spec("wandb"): # check if wandb is installed - import wandb - - if wandb.run: - log.info("Closing wandb!") - wandb.finish() - - return metric_dict, object_dict - - return wrap - - -def get_metric_value(metric_dict: Dict[str, Any], metric_name: str) -> Optional[float]: - """Safely retrieves value of the metric logged in LightningModule. - - :param metric_dict: A dict containing metric values. - :param metric_name: The name of the metric to retrieve. - :return: The value of the metric. - """ - if not metric_name: - log.info("Metric name is None! Skipping metric value retrieval...") - return None - - if metric_name not in metric_dict: - raise Exception( - f"Metric value not found! \n" - "Make sure metric name logged in LightningModule is correct!\n" - "Make sure `optimized_metric` name in `hparams_search` config is correct!", - ) - - metric_value = metric_dict[metric_name].item() - log.info(f"Retrieved metric value! <{metric_name}={metric_value}>") - - return metric_value diff --git a/src/otx/engine/engine.py b/src/otx/engine/engine.py index 11e74c08944..04a7cd74ea3 100644 --- a/src/otx/engine/engine.py +++ b/src/otx/engine/engine.py @@ -348,7 +348,8 @@ def _build_trainer(self, **kwargs) -> None: """Instantiate the trainer based on the model parameters.""" if self._cache.requires_update(**kwargs) or self._trainer is None: self._cache.update(**kwargs) - self._trainer = Trainer(**self._cache.args) + kwargs = self._cache.args + self._trainer = Trainer(**kwargs) self.work_dir = self._trainer.default_root_dir @property diff --git a/src/otx/recipe/action_classification/x3d.yaml b/src/otx/recipe/_base_/data/mmaction_base.yaml similarity index 81% rename from src/otx/recipe/action_classification/x3d.yaml rename to src/otx/recipe/_base_/data/mmaction_base.yaml index 46f575e12d7..1e882a0665d 100644 --- a/src/otx/recipe/action_classification/x3d.yaml +++ b/src/otx/recipe/_base_/data/mmaction_base.yaml @@ -1,12 +1,16 @@ -# @package _global_ -defaults: - - override /base: action_classification - - override /callbacks: action_classification - - override /data: mmaction_classification - - override /model: mmaction_classification -data: +task: ACTION_CLASSIFICATION +config: + data_format: kinetics + mem_cache_size: 1GB + mem_cache_img_max_size: + - 500 + - 500 + image_color_channel: RGB train_subset: + subset_name: train + transform_lib_type: MMACTION batch_size: 8 + num_workers: 2 transforms: - type: LoadVideoForClassification - type: DecordInit @@ -31,7 +35,10 @@ data: - pad_shape - scale_factor val_subset: + subset_name: val + transform_lib_type: MMACTION batch_size: 8 + num_workers: 2 transforms: - type: LoadVideoForClassification - type: DecordInit @@ -54,7 +61,10 @@ data: - pad_shape - scale_factor test_subset: + subset_name: test + transform_lib_type: MMACTION batch_size: 8 + num_workers: 2 transforms: - type: LoadVideoForClassification - type: DecordInit @@ -76,10 +86,3 @@ data: - ori_shape - pad_shape - scale_factor -model: - otx_model: - _target_: otx.algo.action_classification.x3d.X3D - optimizer: - _target_: torch.optim.AdamW - lr: 0.001 - weight_decay: 0.0001 diff --git a/src/otx/recipe/_base_/data/mmdet_base.yaml b/src/otx/recipe/_base_/data/mmdet_base.yaml new file mode 100644 index 00000000000..12d0a868811 --- /dev/null +++ b/src/otx/recipe/_base_/data/mmdet_base.yaml @@ -0,0 +1,69 @@ +task: DETECTION +config: + mem_cache_size: 1GB + mem_cache_img_max_size: null + image_color_channel: RGB + data_format: coco_instances + include_polygons: false + train_subset: + subset_name: train + batch_size: 8 + num_workers: 2 + transform_lib_type: MMDET + transforms: + - backend_args: null + type: LoadImageFromFile + - type: LoadAnnotations + with_bbox: true + - keep_ratio: true + scale: + - 1333 + - 800 + type: Resize + - prob: 0.5 + type: RandomFlip + - type: PackDetInputs + val_subset: + subset_name: val + num_workers: 2 + batch_size: 1 + transform_lib_type: MMDET + transforms: + - backend_args: null + type: LoadImageFromFile + - keep_ratio: true + scale: + - 1333 + - 800 + type: Resize + - type: LoadAnnotations + with_bbox: true + - meta_keys: + - img_id + - img_path + - ori_shape + - img_shape + - scale_factor + type: PackDetInputs + test_subset: + subset_name: test + num_workers: 2 + batch_size: 1 + transform_lib_type: MMDET + transforms: + - backend_args: null + type: LoadImageFromFile + - keep_ratio: true + scale: + - 1333 + - 800 + type: Resize + - type: LoadAnnotations + with_bbox: true + - meta_keys: + - img_id + - img_path + - ori_shape + - img_shape + - scale_factor + type: PackDetInputs diff --git a/src/otx/recipe/multiclass_classification/otx_deit_tiny.yaml b/src/otx/recipe/_base_/data/mmpretrain_base.yaml similarity index 56% rename from src/otx/recipe/multiclass_classification/otx_deit_tiny.yaml rename to src/otx/recipe/_base_/data/mmpretrain_base.yaml index c2af42fa5f5..5b18005acd5 100644 --- a/src/otx/recipe/multiclass_classification/otx_deit_tiny.yaml +++ b/src/otx/recipe/_base_/data/mmpretrain_base.yaml @@ -1,12 +1,17 @@ -# @package _global_ -defaults: - - override /base: classification - - override /callbacks: classification - - override /data: multiclass_mmpretrain - - override /model: multiclass_mmpretrain -data: +task: MULTI_CLASS_CLS +config: + data_format: imagenet_with_subset_dirs + mem_cache_img_max_size: + - 500 + - 500 + mem_cache_size: 1GB + image_color_channel: RGB + include_polygons: false train_subset: + subset_name: train + num_workers: 2 batch_size: 64 + transform_lib_type: MMPRETRAIN transforms: - type: LoadImageFromFile - backend: cv2 @@ -14,7 +19,10 @@ data: type: RandomResizedCrop - type: PackInputs val_subset: + subset_name: val + num_workers: 2 batch_size: 64 + transform_lib_type: MMPRETRAIN transforms: - type: LoadImageFromFile - backend: cv2 @@ -25,22 +33,13 @@ data: type: CenterCrop - type: PackInputs test_subset: + subset_name: test + num_workers: 2 batch_size: 64 + transform_lib_type: MMPRETRAIN transforms: - type: LoadImageFromFile - backend: cv2 scale: 224 type: Resize - type: PackInputs -model: - otx_model: - _target_: otx.algo.classification.deit_tiny.DeitTinyForMulticlassCls - optimizer: - _target_: torch.optim.SGD - _partial_: true - lr: 0.0001 - momentum: 0.9 - weight_decay: 0.0001 - scheduler: - factor: 0.5 - patience: 1 diff --git a/src/otx/recipe/segmentation/litehrnet_s.yaml b/src/otx/recipe/_base_/data/mmseg_base.yaml similarity index 66% rename from src/otx/recipe/segmentation/litehrnet_s.yaml rename to src/otx/recipe/_base_/data/mmseg_base.yaml index c929ef36979..c955223458c 100644 --- a/src/otx/recipe/segmentation/litehrnet_s.yaml +++ b/src/otx/recipe/_base_/data/mmseg_base.yaml @@ -1,12 +1,15 @@ -# @package _global_ -defaults: - - override /base: segmentation - - override /callbacks: segmentation - - override /data: segmentation - - override /model: mmseg -data: +task: SEMANTIC_SEGMENTATION +config: + mem_cache_size: 1GB + mem_cache_img_max_size: null + image_color_channel: RGB + data_format: common_semantic_segmentation_with_subset_dirs + include_polygons: true train_subset: + subset_name: train batch_size: 8 + num_workers: 4 + transform_lib_type: MMSEG transforms: - type: LoadImageFromFile - reduce_zero_label: true @@ -29,7 +32,10 @@ data: - type: PhotoMetricDistortion - type: PackSegInputs val_subset: + subset_name: val + num_workers: 4 batch_size: 1 + transform_lib_type: MMSEG transforms: - type: LoadImageFromFile - keep_ratio: false @@ -41,7 +47,10 @@ data: type: LoadAnnotations - type: PackSegInputs test_subset: + subset_name: test + num_workers: 4 batch_size: 1 + transform_lib_type: MMSEG transforms: - type: LoadImageFromFile - keep_ratio: false @@ -52,19 +61,3 @@ data: - reduce_zero_label: true type: LoadAnnotations - type: PackSegInputs -model: - otx_model: - _target_: otx.algo.segmentation.litehrnet.LiteHRNet - variant: s - optimizer: - _target_: torch.optim.Adam - _partial_: true - lr: 0.001 - betas: [0.9, 0.999] - weight_decay: 0.0 - scheduler: - _target_: torch.optim.lr_scheduler.ReduceLROnPlateau - _partial_: true - mode: min - factor: 0.1 - patience: 10 diff --git a/src/otx/recipe/_base_/data/torchvision_base.yaml b/src/otx/recipe/_base_/data/torchvision_base.yaml new file mode 100644 index 00000000000..8a5a81a0db5 --- /dev/null +++ b/src/otx/recipe/_base_/data/torchvision_base.yaml @@ -0,0 +1,27 @@ +task: MULTI_CLASS_CLS +config: + mem_cache_size: 1GB + mem_cache_img_max_size: null + image_color_channel: RGB + data_format: imagenet_with_subset_dirs + train_subset: + subset_name: train + transform_lib_type: TORCHVISION + transforms: + - class_path: torchvision.transforms.v2.ToImage + batch_size: 1 + num_workers: 2 + val_subset: + subset_name: val + transform_lib_type: TORCHVISION + transforms: + - class_path: torchvision.transforms.v2.ToImage + batch_size: 1 + num_workers: 2 + test_subset: + subset_name: test + transform_lib_type: TORCHVISION + transforms: + - class_path: torchvision.transforms.v2.ToImage + batch_size: 1 + num_workers: 2 diff --git a/src/otx/recipe/_base_/test.yaml b/src/otx/recipe/_base_/test.yaml new file mode 100644 index 00000000000..22c157f8811 --- /dev/null +++ b/src/otx/recipe/_base_/test.yaml @@ -0,0 +1,26 @@ +callbacks: + - class_path: lightning.pytorch.callbacks.RichProgressBar + init_args: + refresh_rate: 1 + leave: false + - class_path: otx.algo.callbacks.iteration_timer.IterationTimer + init_args: + prog_bar: true + on_step: false + on_epoch: true + - class_path: lightning.pytorch.callbacks.RichModelSummary + init_args: + max_depth: 1 +logger: + - class_path: lightning.pytorch.loggers.csv_logs.CSVLogger + init_args: + save_dir: "" + name: "csv/" + prefix: "" + - class_path: lightning.pytorch.loggers.tensorboard.TensorBoardLogger + init_args: + save_dir: "" + name: "tensorboard/" + log_graph: false + default_hp_metric: true + prefix: "" diff --git a/src/otx/recipe/_base_/train.yaml b/src/otx/recipe/_base_/train.yaml new file mode 100644 index 00000000000..64ab9e551dc --- /dev/null +++ b/src/otx/recipe/_base_/train.yaml @@ -0,0 +1,56 @@ +max_epochs: 10 +min_epochs: 1 +callbacks: + - class_path: lightning.pytorch.callbacks.EarlyStopping + init_args: + monitor: null + mode: max + patience: 100 + check_on_train_epoch_end: false + - class_path: lightning.pytorch.callbacks.RichProgressBar + init_args: + refresh_rate: 1 + leave: false + - class_path: lightning.pytorch.callbacks.ModelCheckpoint + init_args: + dirpath: null + monitor: null + mode: max + save_top_k: 1 + save_last: true + auto_insert_metric_name: false + filename: "checkpoints/epoch_{epoch:03d}" + - class_path: otx.algo.callbacks.iteration_timer.IterationTimer + init_args: + prog_bar: true + on_step: false + on_epoch: true + - class_path: lightning.pytorch.callbacks.RichModelSummary + init_args: + max_depth: 1 + - class_path: lightning.pytorch.callbacks.LearningRateMonitor + init_args: + logging_interval: epoch + log_momentum: true + - class_path: otx.algo.callbacks.adaptive_train_scheduling.AdaptiveTrainScheduling + init_args: + max_interval: 5 + decay: -0.025 +logger: + - class_path: lightning.pytorch.loggers.csv_logs.CSVLogger + init_args: + save_dir: "" + name: "csv/" + prefix: "" + - class_path: lightning.pytorch.loggers.tensorboard.TensorBoardLogger + init_args: + save_dir: "" + name: "tensorboard/" + log_graph: false + default_hp_metric: true + prefix: "" +deterministic: false +seed: null +precision: 16 +check_val_every_n_epoch: 1 +gradient_clip_val: null diff --git a/src/otx/recipe/action/action_classification/x3d.yaml b/src/otx/recipe/action/action_classification/x3d.yaml new file mode 100644 index 00000000000..e4f73b58e6a --- /dev/null +++ b/src/otx/recipe/action/action_classification/x3d.yaml @@ -0,0 +1,26 @@ +model: + class_path: otx.algo.action_classification.x3d.X3D + init_args: + num_classes: 400 + +optimizer: + class_path: torch.optim.AdamW + init_args: + lr: 0.001 + weight_decay: 0.0001 + +scheduler: + class_path: lightning.pytorch.cli.ReduceLROnPlateau + init_args: + mode: min + factor: 0.1 + patience: 10 + monitor: train/loss + +engine: + task: ACTION_CLASSIFICATION + device: auto + +callback_monitor: accuracy + +data: ../../_base_/data/mmaction_base.yaml diff --git a/src/otx/recipe/action/action_detection/x3d_fastrcnn.yaml b/src/otx/recipe/action/action_detection/x3d_fastrcnn.yaml new file mode 100644 index 00000000000..ef5dab22269 --- /dev/null +++ b/src/otx/recipe/action/action_detection/x3d_fastrcnn.yaml @@ -0,0 +1,93 @@ +model: + class_path: otx.algo.action_detection.x3d_fastrcnn.X3DFastRCNN + init_args: + num_classes: 81 + topk: 3 + +optimizer: + class_path: torch.optim.SGD + init_args: + lr: 0.005 + momentum: 0.9 + weight_decay: 0.00001 + +scheduler: + class_path: lightning.pytorch.cli.ReduceLROnPlateau + init_args: + mode: min + factor: 0.1 + patience: 10 + monitor: train/loss + +engine: + task: ACTION_DETECTION + device: auto + +callback_monitor: val/map_50 + +data: ../../_base_/data/mmaction_base.yaml +overrides: + precision: 32 + data: + task: ACTION_DETECTION + config: + data_format: ava + train_subset: + transforms: + - type: LoadVideoForDetection + - type: LoadAnnotations + - type: SampleAVAFrames + clip_len: 32 + frame_interval: 2 + - type: RawFrameDecode + io_backend: disk + - type: RandomRescale + scale_range: + - 256 + - 320 + - type: RandomCrop + size: 256 + - type: Flip + flip_ratio: 0.5 + - type: FormatShape + input_format: NCTHW + collapse: true + - type: PackActionInputs + val_subset: + batch_size: 1 + transforms: + - type: LoadVideoForDetection + - type: LoadAnnotations + - type: SampleAVAFrames + clip_len: 32 + frame_interval: 2 + test_mode: true + - type: RawFrameDecode + io_backend: disk + - type: Resize + scale: + - -1 + - 256 + - type: FormatShape + input_format: NCTHW + collapse: true + - type: PackActionInputs + test_subset: + batch_size: 1 + transforms: + - type: LoadVideoForDetection + - type: LoadAnnotations + - type: SampleAVAFrames + clip_len: 32 + frame_interval: 2 + test_mode: true + - type: RawFrameDecode + io_backend: disk + - type: Resize + scale: + - -1 + - 256 + - type: FormatShape + input_format: NCTHW + collapse: true + - type: PackActionInputs diff --git a/src/otx/recipe/action_classification/__init__.py b/src/otx/recipe/action_classification/__init__.py deleted file mode 100644 index e6c4aa096dd..00000000000 --- a/src/otx/recipe/action_classification/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -# Copyright (C) 2023 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 -# -"""YAML file recipes for the action classification models OTX provides. - -this file is needed here to include configs when building project as a package -""" diff --git a/src/otx/recipe/action_detection/__init__.py b/src/otx/recipe/action_detection/__init__.py deleted file mode 100644 index d07fc64833c..00000000000 --- a/src/otx/recipe/action_detection/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright (C) 2023 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 -# -"""Recipe files for action detection task.""" diff --git a/src/otx/recipe/action_detection/x3d_fastrcnn.yaml b/src/otx/recipe/action_detection/x3d_fastrcnn.yaml deleted file mode 100644 index 10cdcbe11cf..00000000000 --- a/src/otx/recipe/action_detection/x3d_fastrcnn.yaml +++ /dev/null @@ -1,80 +0,0 @@ -# @package _global_ -defaults: - - override /trainer: default - - override /base: action_detection - - override /callbacks: action_detection - - override /data: mmaction_detection - - override /model: mmaction_detection -data: - train_subset: - batch_size: 8 - transforms: - - type: LoadVideoForDetection - - type: LoadAnnotations - - type: SampleAVAFrames - clip_len: 32 - frame_interval: 2 - - type: RawFrameDecode - io_backend: disk - - type: RandomRescale - scale_range: - - 256 - - 320 - - type: RandomCrop - size: 256 - - type: Flip - flip_ratio: 0.5 - - type: FormatShape - input_format: NCTHW - collapse: true - - type: PackActionInputs - val_subset: - batch_size: 1 - transforms: - - type: LoadVideoForDetection - - type: LoadAnnotations - - type: SampleAVAFrames - clip_len: 32 - frame_interval: 2 - test_mode: true - - type: RawFrameDecode - io_backend: disk - - type: Resize - scale: - - -1 - - 256 - - type: FormatShape - input_format: NCTHW - collapse: true - - type: PackActionInputs - test_subset: - batch_size: 1 - transforms: - - type: LoadVideoForDetection - - type: LoadAnnotations - - type: SampleAVAFrames - clip_len: 32 - frame_interval: 2 - test_mode: true - - type: RawFrameDecode - io_backend: disk - - type: Resize - scale: - - -1 - - 256 - - type: FormatShape - input_format: NCTHW - collapse: true - - type: PackActionInputs -model: - otx_model: - _target_: otx.algo.action_detection.x3d_fastrcnn.X3DFastRCNN - topk: ??? - - optimizer: - _target_: torch.optim.SGD - lr: 0.005 - momentum: 0.9 - weight_decay: 0.00001 -trainer: - precision: 32 diff --git a/src/otx/recipe/classification/h_label_cls/efficientnet_b0_light.yaml b/src/otx/recipe/classification/h_label_cls/efficientnet_b0_light.yaml new file mode 100644 index 00000000000..15b227439c1 --- /dev/null +++ b/src/otx/recipe/classification/h_label_cls/efficientnet_b0_light.yaml @@ -0,0 +1,32 @@ +model: + class_path: otx.algo.classification.efficientnet_b0.EfficientNetB0ForHLabelCls + init_args: + num_classes: 1000 + num_multiclass_heads: 0 + num_multilabel_classes: 0 + +optimizer: + class_path: torch.optim.SGD + init_args: + lr: 0.0049 + +scheduler: + class_path: lightning.pytorch.cli.ReduceLROnPlateau + init_args: + mode: min + factor: 0.5 + patience: 1 + monitor: train/loss + +engine: + task: H_LABEL_CLS + device: auto + +callback_monitor: val/accuracy + +data: ../../_base_/data/mmpretrain_base.yaml +overrides: + data: + task: H_LABEL_CLS + config: + data_format: datumaro diff --git a/src/otx/recipe/classification/h_label_cls/efficientnet_v2_light.yaml b/src/otx/recipe/classification/h_label_cls/efficientnet_v2_light.yaml new file mode 100644 index 00000000000..ef1bb885231 --- /dev/null +++ b/src/otx/recipe/classification/h_label_cls/efficientnet_v2_light.yaml @@ -0,0 +1,44 @@ +model: + class_path: otx.algo.classification.efficientnet_v2.EfficientNetV2ForHLabelCls + init_args: + num_classes: 1000 + num_multiclass_heads: 0 + num_multilabel_classes: 0 + +optimizer: + class_path: torch.optim.SGD + init_args: + lr: 0.0071 + momentum: 0.9 + weight_decay: 0.0001 + +scheduler: + class_path: lightning.pytorch.cli.ReduceLROnPlateau + init_args: + mode: min + factor: 0.5 + patience: 1 + monitor: train/loss + +engine: + task: H_LABEL_CLS + device: auto + +callback_monitor: val/accuracy + +data: ../../_base_/data/mmpretrain_base.yaml +overrides: + data: + task: H_LABEL_CLS + config: + data_format: datumaro + train_subset: + transforms: + - type: LoadImageFromFile + - backend: cv2 + scale: 224 + type: RandomResizedCrop + - direction: horizontal + prob: 0.5 + type: RandomFlip + - type: PackInputs diff --git a/src/otx/recipe/classification/h_label_cls/mobilenet_v3_large_light.yaml b/src/otx/recipe/classification/h_label_cls/mobilenet_v3_large_light.yaml new file mode 100644 index 00000000000..7a228daf568 --- /dev/null +++ b/src/otx/recipe/classification/h_label_cls/mobilenet_v3_large_light.yaml @@ -0,0 +1,44 @@ +model: + class_path: otx.algo.classification.mobilenet_v3_large.MobileNetV3ForHLabelCls + init_args: + num_classes: 1000 + num_multiclass_heads: 0 + num_multilabel_classes: 0 + +optimizer: + class_path: torch.optim.SGD + init_args: + lr: 0.0058 + momentum: 0.9 + weight_decay: 0.0001 + +scheduler: + class_path: lightning.pytorch.cli.ReduceLROnPlateau + init_args: + mode: min + factor: 0.5 + patience: 1 + monitor: train/loss + +engine: + task: H_LABEL_CLS + device: auto + +callback_monitor: val/accuracy + +data: ../../_base_/data/mmpretrain_base.yaml +overrides: + data: + task: H_LABEL_CLS + config: + data_format: datumaro + train_subset: + transforms: + - type: LoadImageFromFile + - backend: cv2 + scale: 224 + type: RandomResizedCrop + - direction: horizontal + prob: 0.5 + type: RandomFlip + - type: PackInputs diff --git a/src/otx/recipe/classification/h_label_cls/otx_deit_tiny.yaml b/src/otx/recipe/classification/h_label_cls/otx_deit_tiny.yaml new file mode 100644 index 00000000000..c3793e3570e --- /dev/null +++ b/src/otx/recipe/classification/h_label_cls/otx_deit_tiny.yaml @@ -0,0 +1,34 @@ +model: + class_path: otx.algo.classification.deit_tiny.DeitTinyForHLabelCls + init_args: + num_classes: 1000 + num_multiclass_heads: 0 + num_multilabel_classes: 0 + +optimizer: + class_path: torch.optim.SGD + init_args: + lr: 0.0001 + momentum: 0.9 + weight_decay: 0.0001 + +scheduler: + class_path: lightning.pytorch.cli.ReduceLROnPlateau + init_args: + mode: min + factor: 0.5 + patience: 1 + monitor: train/loss + +engine: + task: H_LABEL_CLS + device: auto + +callback_monitor: val/accuracy + +data: ../../_base_/data/mmpretrain_base.yaml +overrides: + data: + task: H_LABEL_CLS + config: + data_format: datumaro diff --git a/src/otx/recipe/classification/multi_class_cls/efficientnet_b0_light.yaml b/src/otx/recipe/classification/multi_class_cls/efficientnet_b0_light.yaml new file mode 100644 index 00000000000..8df02272111 --- /dev/null +++ b/src/otx/recipe/classification/multi_class_cls/efficientnet_b0_light.yaml @@ -0,0 +1,28 @@ +model: + class_path: otx.algo.classification.efficientnet_b0.EfficientNetB0ForMulticlassCls + init_args: + num_classes: 1000 + light: True + +optimizer: + class_path: torch.optim.SGD + init_args: + lr: 0.0049 + momentum: 0.9 + weight_decay: 0.0001 + +scheduler: + class_path: lightning.pytorch.cli.ReduceLROnPlateau + init_args: + mode: min + factor: 0.5 + patience: 1 + monitor: train/loss + +engine: + task: MULTI_CLASS_CLS + device: auto + +callback_monitor: val/accuracy + +data: ../../_base_/data/mmpretrain_base.yaml diff --git a/src/otx/recipe/classification/multi_class_cls/efficientnet_v2_light.yaml b/src/otx/recipe/classification/multi_class_cls/efficientnet_v2_light.yaml new file mode 100644 index 00000000000..1465d7ffe6d --- /dev/null +++ b/src/otx/recipe/classification/multi_class_cls/efficientnet_v2_light.yaml @@ -0,0 +1,41 @@ +model: + class_path: otx.algo.classification.efficientnet_v2.EfficientNetV2ForMulticlassCls + init_args: + num_classes: 1000 + light: True + +optimizer: + class_path: torch.optim.SGD + init_args: + lr: 0.0071 + momentum: 0.9 + weight_decay: 0.0001 + +scheduler: + class_path: lightning.pytorch.cli.ReduceLROnPlateau + init_args: + mode: min + factor: 0.5 + patience: 1 + monitor: train/loss + +engine: + task: MULTI_CLASS_CLS + device: auto + +callback_monitor: val/accuracy + +data: ../../_base_/data/mmpretrain_base.yaml +overrides: + data: + config: + train_subset: + transforms: + - type: LoadImageFromFile + - backend: cv2 + scale: 224 + type: RandomResizedCrop + - direction: horizontal + prob: 0.5 + type: RandomFlip + - type: PackInputs diff --git a/src/otx/recipe/classification/multi_class_cls/mobilenet_v3_large_light.yaml b/src/otx/recipe/classification/multi_class_cls/mobilenet_v3_large_light.yaml new file mode 100644 index 00000000000..25bf03cf8a3 --- /dev/null +++ b/src/otx/recipe/classification/multi_class_cls/mobilenet_v3_large_light.yaml @@ -0,0 +1,41 @@ +model: + class_path: otx.algo.classification.mobilenet_v3_large.MobileNetV3ForMulticlassCls + init_args: + num_classes: 1000 + light: True + +optimizer: + class_path: torch.optim.SGD + init_args: + lr: 0.0058 + momentum: 0.9 + weight_decay: 0.0001 + +scheduler: + class_path: lightning.pytorch.cli.ReduceLROnPlateau + init_args: + mode: min + factor: 0.5 + patience: 1 + monitor: train/loss + +engine: + task: MULTI_CLASS_CLS + device: auto + +callback_monitor: val/accuracy + +data: ../../_base_/data/mmpretrain_base.yaml +overrides: + data: + config: + train_subset: + transforms: + - type: LoadImageFromFile + - backend: cv2 + scale: 224 + type: RandomResizedCrop + - direction: horizontal + prob: 0.5 + type: RandomFlip + - type: PackInputs diff --git a/src/otx/recipe/classification/multi_class_cls/openvino_model.yaml b/src/otx/recipe/classification/multi_class_cls/openvino_model.yaml new file mode 100644 index 00000000000..9fd2da285f6 --- /dev/null +++ b/src/otx/recipe/classification/multi_class_cls/openvino_model.yaml @@ -0,0 +1,43 @@ +model: + class_path: otx.core.model.entity.classification.OVMulticlassClassificationModel + init_args: + num_classes: 1000 + config: + class_path: omegaconf.dictconfig.DictConfig + init_args: + content: + model_name: efficientnet-b0-pytorch + async_inference: True + use_throughput_mode: False + model_type: Classification + head: + num_classes: 1000 + +optimizer: + class_path: torch.optim.Adam + init_args: + lr: 1e-3 + weight_decay: 0.0 + +scheduler: + class_path: lightning.pytorch.cli.ReduceLROnPlateau + init_args: + mode: min + factor: 0.5 + patience: 1 + monitor: train/loss + +engine: + task: MULTI_CLASS_CLS + device: auto + +callback_monitor: val/accuracy + +data: ../../_base_/data/torchvision_base.yaml + +overrides: + data: + config: + image_color_channel: BGR + test_subset: + batch_size: 128 diff --git a/src/otx/recipe/classification/multi_class_cls/otx_deit_tiny.yaml b/src/otx/recipe/classification/multi_class_cls/otx_deit_tiny.yaml new file mode 100644 index 00000000000..b30efc7c60c --- /dev/null +++ b/src/otx/recipe/classification/multi_class_cls/otx_deit_tiny.yaml @@ -0,0 +1,27 @@ +model: + class_path: otx.algo.classification.deit_tiny.DeitTinyForMulticlassCls + init_args: + num_classes: 1000 + +optimizer: + class_path: torch.optim.SGD + init_args: + lr: 0.0001 + momentum: 0.9 + weight_decay: 0.0001 + +scheduler: + class_path: lightning.pytorch.cli.ReduceLROnPlateau + init_args: + mode: min + factor: 0.5 + patience: 1 + monitor: train/loss + +engine: + task: MULTI_CLASS_CLS + device: auto + +callback_monitor: val/accuracy + +data: ../../_base_/data/mmpretrain_base.yaml diff --git a/src/otx/recipe/classification/multi_class_cls/otx_dino_v2.yaml b/src/otx/recipe/classification/multi_class_cls/otx_dino_v2.yaml new file mode 100644 index 00000000000..dc338bcfcd8 --- /dev/null +++ b/src/otx/recipe/classification/multi_class_cls/otx_dino_v2.yaml @@ -0,0 +1,98 @@ +model: + class_path: otx.algo.classification.otx_dino_v2.DINOv2RegisterClassifier + init_args: + num_classes: 1000 + config: + class_path: omegaconf.dictconfig.DictConfig + init_args: + content: + backbone: + name: dinov2_vits14_reg + frozen: false + head: + in_channels: 384 + num_classes: 1000 + +optimizer: + class_path: torch.optim.AdamW + init_args: + lr: 1e-5 + +scheduler: + class_path: lightning.pytorch.cli.ReduceLROnPlateau + init_args: + mode: min + factor: 0.1 + patience: 10 + monitor: train/loss + +engine: + task: MULTI_CLASS_CLS + device: auto + +callback_monitor: val/accuracy + +data: ../../_base_/data/mmpretrain_base.yaml +overrides: + data: + config: + train_subset: + transforms: + - type: LoadImageFromFile + to_float32: true + - mean: + - 123.675 + - 116.28 + - 103.53 + std: + - 58.395 + - 57.12 + - 57.375 + to_rgb: true + type: Normalize + - backend: cv2 + scale: 224 + type: RandomResizedCrop + - type: PackInputs + val_subset: + transforms: + - type: LoadImageFromFile + to_float32: true + - mean: + - 123.675 + - 116.28 + - 103.53 + std: + - 58.395 + - 57.12 + - 57.375 + to_rgb: true + type: Normalize + - backend: cv2 + edge: short + scale: 256 + type: ResizeEdge + - crop_size: 224 + type: CenterCrop + - type: PackInputs + test_subset: + transforms: + - type: LoadImageFromFile + to_float32: true + - mean: + - 123.675 + - 116.28 + - 103.53 + std: + - 58.395 + - 57.12 + - 57.375 + to_rgb: true + type: Normalize + - backend: cv2 + edge: short + scale: 256 + type: ResizeEdge + - crop_size: 224 + type: CenterCrop + - type: PackInputs diff --git a/src/otx/recipe/classification/multi_class_cls/otx_dino_v2_linear_probe.yaml b/src/otx/recipe/classification/multi_class_cls/otx_dino_v2_linear_probe.yaml new file mode 100644 index 00000000000..4ea1f2d67bf --- /dev/null +++ b/src/otx/recipe/classification/multi_class_cls/otx_dino_v2_linear_probe.yaml @@ -0,0 +1,100 @@ +model: + class_path: otx.algo.classification.otx_dino_v2.DINOv2RegisterClassifier + init_args: + num_classes: 1000 + config: + class_path: omegaconf.dictconfig.DictConfig + init_args: + content: + backbone: + name: dinov2_vits14_reg + frozen: true + head: + in_channels: 384 + num_classes: 1000 + +optimizer: + class_path: torch.optim.SGD + init_args: + lr: 0.007 + momentum: 0.9 + weight_decay: 0.0001 + +scheduler: + class_path: lightning.pytorch.cli.ReduceLROnPlateau + init_args: + mode: min + factor: 0.5 + patience: 1 + monitor: train/loss + +engine: + task: MULTI_CLASS_CLS + device: auto + +callback_monitor: val/accuracy + +data: ../../_base_/data/mmpretrain_base.yaml +overrides: + data: + config: + train_subset: + transforms: + - type: LoadImageFromFile + to_float32: true + - mean: + - 123.675 + - 116.28 + - 103.53 + std: + - 58.395 + - 57.12 + - 57.375 + to_rgb: true + type: Normalize + - backend: cv2 + scale: 224 + type: RandomResizedCrop + - type: PackInputs + val_subset: + transforms: + - type: LoadImageFromFile + to_float32: true + - mean: + - 123.675 + - 116.28 + - 103.53 + std: + - 58.395 + - 57.12 + - 57.375 + to_rgb: true + type: Normalize + - backend: cv2 + edge: short + scale: 256 + type: ResizeEdge + - crop_size: 224 + type: CenterCrop + - type: PackInputs + test_subset: + transforms: + - type: LoadImageFromFile + to_float32: true + - mean: + - 123.675 + - 116.28 + - 103.53 + std: + - 58.395 + - 57.12 + - 57.375 + to_rgb: true + type: Normalize + - backend: cv2 + edge: short + scale: 256 + type: ResizeEdge + - crop_size: 224 + type: CenterCrop + - type: PackInputs diff --git a/src/otx/recipe/classification/multi_class_cls/otx_efficientnet_b0.yaml b/src/otx/recipe/classification/multi_class_cls/otx_efficientnet_b0.yaml new file mode 100644 index 00000000000..8526dc42b0d --- /dev/null +++ b/src/otx/recipe/classification/multi_class_cls/otx_efficientnet_b0.yaml @@ -0,0 +1,28 @@ +model: + class_path: otx.algo.classification.efficientnet_b0.EfficientNetB0ForMulticlassCls + init_args: + num_classes: 1000 + light: false + +optimizer: + class_path: torch.optim.SGD + init_args: + lr: 0.0049 + momentum: 0.9 + weight_decay: 0.0001 + +scheduler: + class_path: lightning.pytorch.cli.ReduceLROnPlateau + init_args: + mode: min + factor: 0.5 + patience: 1 + monitor: train/loss + +engine: + task: MULTI_CLASS_CLS + device: auto + +callback_monitor: val/accuracy + +data: ../../_base_/data/mmpretrain_base.yaml diff --git a/src/otx/recipe/classification/multi_class_cls/otx_efficientnet_v2.yaml b/src/otx/recipe/classification/multi_class_cls/otx_efficientnet_v2.yaml new file mode 100644 index 00000000000..1dee8cd1331 --- /dev/null +++ b/src/otx/recipe/classification/multi_class_cls/otx_efficientnet_v2.yaml @@ -0,0 +1,41 @@ +model: + class_path: otx.algo.classification.efficientnet_v2.EfficientNetV2ForMulticlassCls + init_args: + num_classes: 1000 + light: false + +optimizer: + class_path: torch.optim.SGD + init_args: + lr: 0.0071 + momentum: 0.9 + weight_decay: 0.0001 + +scheduler: + class_path: lightning.pytorch.cli.ReduceLROnPlateau + init_args: + mode: min + factor: 0.5 + patience: 1 + monitor: train/loss + +engine: + task: MULTI_CLASS_CLS + device: auto + +callback_monitor: val/accuracy + +data: ../../_base_/data/mmpretrain_base.yaml +overrides: + data: + config: + train_subset: + transforms: + - type: LoadImageFromFile + - backend: cv2 + scale: 224 + type: RandomResizedCrop + - direction: horizontal + prob: 0.5 + type: RandomFlip + - type: PackInputs diff --git a/src/otx/recipe/classification/multi_class_cls/otx_mobilenet_v3_large.yaml b/src/otx/recipe/classification/multi_class_cls/otx_mobilenet_v3_large.yaml new file mode 100644 index 00000000000..5c280d6b397 --- /dev/null +++ b/src/otx/recipe/classification/multi_class_cls/otx_mobilenet_v3_large.yaml @@ -0,0 +1,41 @@ +model: + class_path: otx.algo.classification.mobilenet_v3_large.MobileNetV3ForMulticlassCls + init_args: + num_classes: 1000 + light: false + +optimizer: + class_path: torch.optim.SGD + init_args: + lr: 0.0058 + momentum: 0.9 + weight_decay: 0.0001 + +scheduler: + class_path: lightning.pytorch.cli.ReduceLROnPlateau + init_args: + mode: min + factor: 0.5 + patience: 1 + monitor: train/loss + +engine: + task: MULTI_CLASS_CLS + device: auto + +callback_monitor: val/accuracy + +data: ../../_base_/data/mmpretrain_base.yaml +overrides: + data: + config: + train_subset: + transforms: + - type: LoadImageFromFile + - backend: cv2 + scale: 224 + type: RandomResizedCrop + - direction: horizontal + prob: 0.5 + type: RandomFlip + - type: PackInputs diff --git a/src/otx/recipe/classification/multi_label_cls/efficientnet_b0_light.yaml b/src/otx/recipe/classification/multi_label_cls/efficientnet_b0_light.yaml new file mode 100644 index 00000000000..84a29ac0e82 --- /dev/null +++ b/src/otx/recipe/classification/multi_label_cls/efficientnet_b0_light.yaml @@ -0,0 +1,51 @@ +model: + class_path: otx.algo.classification.efficientnet_b0.EfficientNetB0ForMultilabelCls + init_args: + num_classes: 1000 + +optimizer: + class_path: torch.optim.SGD + init_args: + lr: 0.0049 + +scheduler: + class_path: lightning.pytorch.cli.ReduceLROnPlateau + init_args: + mode: min + factor: 0.5 + patience: 1 + monitor: train/loss + +engine: + task: MULTI_LABEL_CLS + device: auto + +callback_monitor: val/accuracy + +data: ../../_base_/data/mmpretrain_base.yaml +overrides: + data: + task: MULTI_LABEL_CLS + config: + data_format: datumaro + train_subset: + transforms: + - type: LoadImageFromFile + - backend: cv2 + scale: 224 + type: Resize + - type: PackInputs + val_subset: + transforms: + - type: LoadImageFromFile + - backend: cv2 + scale: 224 + type: Resize + - type: PackInputs + test_subset: + transforms: + - type: LoadImageFromFile + - backend: cv2 + scale: 224 + type: Resize + - type: PackInputs diff --git a/src/otx/recipe/classification/multi_label_cls/efficientnet_v2_light.yaml b/src/otx/recipe/classification/multi_label_cls/efficientnet_v2_light.yaml new file mode 100644 index 00000000000..ab7e684de7b --- /dev/null +++ b/src/otx/recipe/classification/multi_label_cls/efficientnet_v2_light.yaml @@ -0,0 +1,56 @@ +model: + class_path: otx.algo.classification.efficientnet_v2.EfficientNetV2ForMultilabelCls + init_args: + num_classes: 1000 + +optimizer: + class_path: torch.optim.SGD + init_args: + lr: 0.0071 + momentum: 0.9 + weight_decay: 0.0001 + +scheduler: + class_path: lightning.pytorch.cli.ReduceLROnPlateau + init_args: + mode: min + factor: 0.5 + patience: 1 + monitor: train/loss + +engine: + task: MULTI_LABEL_CLS + device: auto + +callback_monitor: val/accuracy + +data: ../../_base_/data/mmpretrain_base.yaml +overrides: + data: + task: MULTI_LABEL_CLS + config: + data_format: datumaro + train_subset: + transforms: + - type: LoadImageFromFile + - backend: cv2 + scale: 224 + type: Resize + - direction: horizontal + prob: 0.5 + type: RandomFlip + - type: PackInputs + val_subset: + transforms: + - type: LoadImageFromFile + - backend: cv2 + scale: 224 + type: Resize + - type: PackInputs + test_subset: + transforms: + - type: LoadImageFromFile + - backend: cv2 + scale: 224 + type: Resize + - type: PackInputs diff --git a/src/otx/recipe/classification/multi_label_cls/mobilenet_v3_large_light.yaml b/src/otx/recipe/classification/multi_label_cls/mobilenet_v3_large_light.yaml new file mode 100644 index 00000000000..4da3832910e --- /dev/null +++ b/src/otx/recipe/classification/multi_label_cls/mobilenet_v3_large_light.yaml @@ -0,0 +1,56 @@ +model: + class_path: otx.algo.classification.mobilenet_v3_large.MobileNetV3ForMultilabelCls + init_args: + num_classes: 1000 + +optimizer: + class_path: torch.optim.SGD + init_args: + lr: 0.0058 + momentum: 0.9 + weight_decay: 0.0001 + +scheduler: + class_path: lightning.pytorch.cli.ReduceLROnPlateau + init_args: + mode: min + factor: 0.5 + patience: 1 + monitor: train/loss + +engine: + task: MULTI_LABEL_CLS + device: auto + +callback_monitor: val/accuracy + +data: ../../_base_/data/mmpretrain_base.yaml +overrides: + data: + task: MULTI_LABEL_CLS + config: + data_format: datumaro + train_subset: + transforms: + - type: LoadImageFromFile + - backend: cv2 + scale: 224 + type: Resize + - direction: horizontal + prob: 0.5 + type: RandomFlip + - type: PackInputs + val_subset: + transforms: + - type: LoadImageFromFile + - backend: cv2 + scale: 224 + type: Resize + - type: PackInputs + test_subset: + transforms: + - type: LoadImageFromFile + - backend: cv2 + scale: 224 + type: Resize + - type: PackInputs diff --git a/src/otx/recipe/classification/multi_label_cls/otx_deit_tiny.yaml b/src/otx/recipe/classification/multi_label_cls/otx_deit_tiny.yaml new file mode 100644 index 00000000000..725e03d39ef --- /dev/null +++ b/src/otx/recipe/classification/multi_label_cls/otx_deit_tiny.yaml @@ -0,0 +1,53 @@ +model: + class_path: otx.algo.classification.deit_tiny.DeitTinyForMultilabelCls + init_args: + num_classes: 1000 + +optimizer: + class_path: torch.optim.SGD + init_args: + lr: 0.0001 + momentum: 0.9 + weight_decay: 0.0001 + +scheduler: + class_path: lightning.pytorch.cli.ReduceLROnPlateau + init_args: + mode: min + factor: 0.5 + patience: 1 + monitor: train/loss + +engine: + task: MULTI_LABEL_CLS + device: auto + +callback_monitor: val/accuracy + +data: ../../_base_/data/mmpretrain_base.yaml +overrides: + data: + task: MULTI_LABEL_CLS + config: + data_format: datumaro + train_subset: + transforms: + - type: LoadImageFromFile + - backend: cv2 + scale: 224 + type: Resize + - type: PackInputs + val_subset: + transforms: + - type: LoadImageFromFile + - backend: cv2 + scale: 224 + type: Resize + - type: PackInputs + test_subset: + transforms: + - type: LoadImageFromFile + - backend: cv2 + scale: 224 + type: Resize + - type: PackInputs diff --git a/src/otx/recipe/detection/__init__.py b/src/otx/recipe/detection/__init__.py deleted file mode 100644 index bd6b35bd2d4..00000000000 --- a/src/otx/recipe/detection/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -# Copyright (C) 2023 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 -# -"""YAML file recipes for the detection models OTX provides. - -this file is needed here to include configs when building project as a package -""" diff --git a/src/otx/recipe/detection/atss_mobilenetv2.yaml b/src/otx/recipe/detection/atss_mobilenetv2.yaml index 8e931289c90..fc3cfbde3fa 100644 --- a/src/otx/recipe/detection/atss_mobilenetv2.yaml +++ b/src/otx/recipe/detection/atss_mobilenetv2.yaml @@ -1,91 +1,103 @@ -# @package _global_ -defaults: - - override /trainer: default - - override /base: detection - - override /callbacks: detection - - override /data: mmdet - - override /model: mmdet -data: - train_subset: - batch_size: 8 - transforms: - - type: LoadImageFromFile - - type: LoadAnnotations - with_bbox: true - - type: MinIoURandomCrop - min_ious: - - 0.1 - - 0.3 - - 0.5 - - 0.7 - - 0.9 - min_crop_size: 0.3 - - type: Resize - scale: - - 992 - - 736 - keep_ratio: false - - type: RandomFlip - prob: 0.5 - - type: PackDetInputs - meta_keys: - - ori_filename - - flip_direction - - scale_factor - - gt_ann_ids - - flip - - ignored_labels - - ori_shape - - filename - - img_shape - - pad_shape - val_subset: - batch_size: 8 - transforms: - - type: LoadImageFromFile - - type: Resize - scale: - - 992 - - 736 - keep_ratio: false - - type: LoadAnnotations - with_bbox: true - - type: PackDetInputs - meta_keys: - - ori_filename - - scale_factor - - ori_shape - - filename - - img_shape - - pad_shape - test_subset: - batch_size: 8 - transforms: - - type: LoadImageFromFile - - type: Resize - scale: - - 992 - - 736 - keep_ratio: false - - type: LoadAnnotations - with_bbox: true - - type: PackDetInputs - meta_keys: - - ori_filename - - scale_factor - - ori_shape - - filename - - img_shape - - pad_shape model: - otx_model: - _target_: otx.algo.detection.atss.ATSS + class_path: otx.algo.detection.atss.ATSS + init_args: + num_classes: 1000 variant: mobilenetv2 - optimizer: - _target_: torch.optim.SGD - _partial_: true + +optimizer: + class_path: torch.optim.SGD + init_args: lr: 0.004 - weight_decay: 0.0001 momentum: 0.9 -trainer: + weight_decay: 0.0001 + +scheduler: + class_path: lightning.pytorch.cli.ReduceLROnPlateau + init_args: + mode: min + factor: 0.1 + patience: 10 + monitor: train/loss + +engine: + task: DETECTION + device: auto + +callback_monitor: val/map_50 + +data: ../_base_/data/mmdet_base.yaml +overrides: gradient_clip_val: 35.0 + data: + config: + train_subset: + batch_size: 8 + transforms: + - type: LoadImageFromFile + - type: LoadAnnotations + with_bbox: true + - type: MinIoURandomCrop + min_ious: + - 0.1 + - 0.3 + - 0.5 + - 0.7 + - 0.9 + min_crop_size: 0.3 + - type: Resize + scale: + - 992 + - 736 + keep_ratio: false + - type: RandomFlip + prob: 0.5 + - type: PackDetInputs + meta_keys: + - ori_filename + - flip_direction + - scale_factor + - gt_ann_ids + - flip + - ignored_labels + - ori_shape + - filename + - img_shape + - pad_shape + val_subset: + batch_size: 8 + transforms: + - type: LoadImageFromFile + - type: Resize + scale: + - 992 + - 736 + keep_ratio: false + - type: LoadAnnotations + with_bbox: true + - type: PackDetInputs + meta_keys: + - ori_filename + - scale_factor + - ori_shape + - filename + - img_shape + - pad_shape + test_subset: + batch_size: 8 + transforms: + - type: LoadImageFromFile + - type: Resize + scale: + - 992 + - 736 + keep_ratio: false + - type: LoadAnnotations + with_bbox: true + - type: PackDetInputs + meta_keys: + - ori_filename + - scale_factor + - ori_shape + - filename + - img_shape + - pad_shape diff --git a/src/otx/recipe/detection/atss_r50_fpn.yaml b/src/otx/recipe/detection/atss_r50_fpn.yaml index 6b8590adf9f..5b477cddaf2 100644 --- a/src/otx/recipe/detection/atss_r50_fpn.yaml +++ b/src/otx/recipe/detection/atss_r50_fpn.yaml @@ -1,65 +1,85 @@ -# @package _global_ -defaults: - - override /base: detection - - override /callbacks: detection - - override /data: mmdet - - override /model: mmdet -recipe: detection/atss_r50_fpn -data: - train_subset: - batch_size: 2 - transforms: - - backend_args: null - type: LoadImageFromFile - - type: LoadAnnotations - with_bbox: true - - keep_ratio: true - scale: - - 1333 - - 800 - type: Resize - - prob: 0.5 - type: RandomFlip - - type: PackDetInputs - val_subset: - batch_size: 1 - transforms: - - backend_args: null - type: LoadImageFromFile - - keep_ratio: true - scale: - - 1333 - - 800 - type: Resize - - type: LoadAnnotations - with_bbox: true - - meta_keys: - - img_id - - img_path - - ori_shape - - img_shape - - scale_factor - type: PackDetInputs - test_subset: - batch_size: 1 - transforms: - - backend_args: null - type: LoadImageFromFile - - keep_ratio: true - scale: - - 1333 - - 800 - type: Resize - - type: LoadAnnotations - with_bbox: true - - meta_keys: - - img_id - - img_path - - ori_shape - - img_shape - - scale_factor - type: PackDetInputs model: - otx_model: - _target_: otx.algo.detection.atss.ATSS + class_path: otx.algo.detection.atss.ATSS + init_args: + num_classes: 1000 variant: r50_fpn + +optimizer: + class_path: torch.optim.Adam + init_args: + lr: 1e-3 + weight_decay: 0.0 + +scheduler: + class_path: lightning.pytorch.cli.ReduceLROnPlateau + init_args: + mode: min + factor: 0.1 + patience: 10 + monitor: train/loss + +engine: + task: DETECTION + device: auto + +callback_monitor: val/map_50 + +data: ../_base_/data/mmdet_base.yaml + +overrides: + gradient_clip_val: 35.0 + data: + config: + train_subset: + batch_size: 2 + transforms: + - backend_args: null + type: LoadImageFromFile + - type: LoadAnnotations + with_bbox: true + - keep_ratio: true + scale: + - 1333 + - 800 + type: Resize + - prob: 0.5 + type: RandomFlip + - type: PackDetInputs + val_subset: + batch_size: 1 + transforms: + - backend_args: null + type: LoadImageFromFile + - keep_ratio: true + scale: + - 1333 + - 800 + type: Resize + - type: LoadAnnotations + with_bbox: true + - meta_keys: + - img_id + - img_path + - ori_shape + - img_shape + - scale_factor + type: PackDetInputs + test_subset: + batch_size: 1 + transforms: + - backend_args: null + type: LoadImageFromFile + - keep_ratio: true + scale: + - 1333 + - 800 + type: Resize + - type: LoadAnnotations + with_bbox: true + - meta_keys: + - img_id + - img_path + - ori_shape + - img_shape + - scale_factor + type: PackDetInputs diff --git a/src/otx/recipe/detection/atss_resnext101.yaml b/src/otx/recipe/detection/atss_resnext101.yaml index 3ab953ba090..c310e6e8408 100644 --- a/src/otx/recipe/detection/atss_resnext101.yaml +++ b/src/otx/recipe/detection/atss_resnext101.yaml @@ -1,89 +1,103 @@ -# @package _global_ -defaults: - - override /trainer: default - - override /base: detection - - override /callbacks: detection - - override /data: mmdet - - override /model: mmdet -data: - train_subset: - batch_size: 4 - transforms: - - type: LoadImageFromFile - - type: LoadAnnotations - with_bbox: true - - type: MinIoURandomCrop - min_ious: - - 0.1 - - 0.3 - - 0.5 - - 0.7 - - 0.9 - min_crop_size: 0.3 - - type: Resize - scale: - - 992 - - 736 - keep_ratio: false - - type: RandomFlip - prob: 0.5 - - type: PackDetInputs - meta_keys: - - ori_filename - - flip_direction - - scale_factor - - gt_ann_ids - - flip - - ignored_labels - - ori_shape - - filename - - img_shape - - pad_shape - val_subset: - batch_size: 4 - transforms: - - type: LoadImageFromFile - - type: Resize - scale: - - 992 - - 736 - - type: LoadAnnotations - with_bbox: true - - type: PackDetInputs - meta_keys: - - ori_filename - - scale_factor - - ori_shape - - filename - - img_shape - - pad_shape - test_subset: - batch_size: 4 - transforms: - - type: LoadImageFromFile - - type: Resize - scale: - - 992 - - 736 - - type: LoadAnnotations - with_bbox: true - - type: PackDetInputs - meta_keys: - - ori_filename - - scale_factor - - ori_shape - - filename - - img_shape - - pad_shape model: - otx_model: - _target_: otx.algo.detection.atss.ATSS + class_path: otx.algo.detection.atss.ATSS + init_args: + num_classes: 1000 variant: resnext101 - optimizer: - _target_: torch.optim.SGD - _partial_: true + +optimizer: + class_path: torch.optim.SGD + init_args: lr: 0.004 - weight_decay: 0.0001 momentum: 0.9 -trainer: + weight_decay: 0.0001 + +scheduler: + class_path: lightning.pytorch.cli.ReduceLROnPlateau + init_args: + mode: min + factor: 0.1 + patience: 10 + monitor: train/loss + +engine: + task: DETECTION + device: auto + +callback_monitor: val/map_50 + +data: ../_base_/data/mmdet_base.yaml +overrides: gradient_clip_val: 35.0 + data: + config: + train_subset: + batch_size: 4 + transforms: + - type: LoadImageFromFile + - type: LoadAnnotations + with_bbox: true + - type: MinIoURandomCrop + min_ious: + - 0.1 + - 0.3 + - 0.5 + - 0.7 + - 0.9 + min_crop_size: 0.3 + - type: Resize + scale: + - 992 + - 736 + keep_ratio: false + - type: RandomFlip + prob: 0.5 + - type: PackDetInputs + meta_keys: + - ori_filename + - flip_direction + - scale_factor + - gt_ann_ids + - flip + - ignored_labels + - ori_shape + - filename + - img_shape + - pad_shape + val_subset: + batch_size: 4 + transforms: + - type: LoadImageFromFile + - type: Resize + scale: + - 992 + - 736 + keep_ratio: false + - type: LoadAnnotations + with_bbox: true + - type: PackDetInputs + meta_keys: + - ori_filename + - scale_factor + - ori_shape + - filename + - img_shape + - pad_shape + test_subset: + batch_size: 4 + transforms: + - type: LoadImageFromFile + - type: Resize + scale: + - 992 + - 736 + keep_ratio: false + - type: LoadAnnotations + with_bbox: true + - type: PackDetInputs + meta_keys: + - ori_filename + - scale_factor + - ori_shape + - filename + - img_shape + - pad_shape diff --git a/src/otx/recipe/detection/openvino_model.yaml b/src/otx/recipe/detection/openvino_model.yaml index 63805438ea7..6bfae234cfe 100644 --- a/src/otx/recipe/detection/openvino_model.yaml +++ b/src/otx/recipe/detection/openvino_model.yaml @@ -1,21 +1,42 @@ -# @package _global_ -defaults: - - override /base: detection - - override /callbacks: detection - - override /data: openvino - - override /model: mmdet +model: + class_path: otx.core.model.entity.detection.OVDetectionModel + init_args: + num_classes: 20 + config: + class_path: omegaconf.dictconfig.DictConfig + init_args: + content: + model_name: ssd300 + use_throughput_mode: True + model_type: "SSD" + async_inference: True -data: - data_format: coco_instances - test_subset: - batch_size: 64 +optimizer: + class_path: torch.optim.Adam + init_args: + lr: 1e-3 + weight_decay: 0.0 -model: - otx_model: - _target_: otx.core.model.entity.detection.OVDetectionModel +scheduler: + class_path: lightning.pytorch.cli.ReduceLROnPlateau + init_args: + mode: min + factor: 0.1 + patience: 10 + monitor: train/loss + +engine: + task: DETECTION + device: auto + +callback_monitor: val/map_50 + +data: ../_base_/data/torchvision_base.yaml +overrides: + data: + task: DETECTION config: - model_name: ssd300 - use_throughput_mode: True - model_type: "SSD" - async_inference: True - num_classes: 20 + image_color_channel: BGR + data_format: coco_instances + test_subset: + batch_size: 64 diff --git a/src/otx/recipe/detection/rtmdet_tiny.yaml b/src/otx/recipe/detection/rtmdet_tiny.yaml index 6b37edca010..f9662a15636 100644 --- a/src/otx/recipe/detection/rtmdet_tiny.yaml +++ b/src/otx/recipe/detection/rtmdet_tiny.yaml @@ -1,124 +1,140 @@ -# @package _global_ -defaults: - - override /trainer: default - - override /base: detection - - override /callbacks: detection - - override /data: mmdet - - override /model: mmdet -recipe: detection/rtmdet_tiny -data: - train_subset: - batch_size: 32 - transforms: - - backend_args: null - type: LoadImageFromFile - - type: LoadAnnotations - with_bbox: true - - img_scale: - - 640 - - 640 - max_cached_images: 20 - pad_val: 114.0 - random_pop: false - type: CachedMosaic - - keep_ratio: true - ratio_range: - - 0.5 - - 2.0 - scale: - - 1280 - - 1280 - type: RandomResize - - crop_size: - - 640 - - 640 - type: RandomCrop - - type: YOLOXHSVRandomAug - - prob: 0.5 - type: RandomFlip - - pad_val: - img: - - 114 - - 114 - - 114 - size: - - 640 - - 640 - type: Pad - - img_scale: - - 640 - - 640 - max_cached_images: 10 - pad_val: - - 114 - - 114 - - 114 - prob: 0.5 - random_pop: false - ratio_range: - - 1.0 - - 1.0 - type: CachedMixUp - - type: PackDetInputs - val_subset: - batch_size: 5 - transforms: - - backend_args: null - type: LoadImageFromFile - - keep_ratio: true - scale: - - 640 - - 640 - type: Resize - - pad_val: - img: - - 114 - - 114 - - 114 - size: - - 640 - - 640 - type: Pad - - type: LoadAnnotations - with_bbox: true - - meta_keys: - - img_id - - img_path - - ori_shape - - img_shape - - scale_factor - type: PackDetInputs - test_subset: - batch_size: 5 - transforms: - - backend_args: null - type: LoadImageFromFile - - keep_ratio: true - scale: - - 640 - - 640 - type: Resize - - pad_val: - img: - - 114 - - 114 - - 114 - size: - - 640 - - 640 - type: Pad - - type: LoadAnnotations - with_bbox: true - - meta_keys: - - img_id - - img_path - - ori_shape - - img_shape - - scale_factor - type: PackDetInputs model: - otx_model: - _target_: otx.algo.detection.rtmdet.RTMDet + class_path: otx.algo.detection.rtmdet.RTMDet + init_args: + num_classes: 80 variant: tiny -trainer: + +optimizer: + class_path: torch.optim.Adam + init_args: + lr: 1e-3 + weight_decay: 0.0 + +scheduler: + class_path: lightning.pytorch.cli.ReduceLROnPlateau + init_args: + mode: min + factor: 0.1 + patience: 10 + monitor: train/loss + +engine: + task: DETECTION + device: auto + +callback_monitor: val/map_50 + +data: ../_base_/data/mmdet_base.yaml +overrides: precision: 32 + data: + config: + train_subset: + batch_size: 32 + transforms: + - backend_args: null + type: LoadImageFromFile + - type: LoadAnnotations + with_bbox: true + - img_scale: + - 640 + - 640 + max_cached_images: 20 + pad_val: 114.0 + random_pop: false + type: CachedMosaic + - keep_ratio: true + ratio_range: + - 0.5 + - 2.0 + scale: + - 1280 + - 1280 + type: RandomResize + - crop_size: + - 640 + - 640 + type: RandomCrop + - type: YOLOXHSVRandomAug + - prob: 0.5 + type: RandomFlip + - pad_val: + img: + - 114 + - 114 + - 114 + size: + - 640 + - 640 + type: Pad + - img_scale: + - 640 + - 640 + max_cached_images: 10 + pad_val: + - 114 + - 114 + - 114 + prob: 0.5 + random_pop: false + ratio_range: + - 1.0 + - 1.0 + type: CachedMixUp + - type: PackDetInputs + val_subset: + batch_size: 5 + transforms: + - backend_args: null + type: LoadImageFromFile + - keep_ratio: true + scale: + - 640 + - 640 + type: Resize + - pad_val: + img: + - 114 + - 114 + - 114 + size: + - 640 + - 640 + type: Pad + - type: LoadAnnotations + with_bbox: true + - meta_keys: + - img_id + - img_path + - ori_shape + - img_shape + - scale_factor + type: PackDetInputs + test_subset: + batch_size: 5 + transforms: + - backend_args: null + type: LoadImageFromFile + - keep_ratio: true + scale: + - 640 + - 640 + type: Resize + - pad_val: + img: + - 114 + - 114 + - 114 + size: + - 640 + - 640 + type: Pad + - type: LoadAnnotations + with_bbox: true + - meta_keys: + - img_id + - img_path + - ori_shape + - img_shape + - scale_factor + type: PackDetInputs diff --git a/src/otx/recipe/detection/ssd_mobilenetv2.yaml b/src/otx/recipe/detection/ssd_mobilenetv2.yaml index be4e8528a6c..46f726c277a 100644 --- a/src/otx/recipe/detection/ssd_mobilenetv2.yaml +++ b/src/otx/recipe/detection/ssd_mobilenetv2.yaml @@ -1,97 +1,109 @@ -# @package _global_ -defaults: - - override /trainer: default - - override /base: detection - - override /callbacks: detection - - override /data: mmdet - - override /model: mmdet -data: - train_subset: - batch_size: 8 - transforms: - - type: LoadImageFromFile - - type: LoadAnnotations - with_bbox: true - - type: PhotoMetricDistortion - brightness_delta: 32 - contrast_range: - - 0.5 - - 1.5 - hue_delta: 18 - - type: MinIoURandomCrop - min_ious: - - 0.1 - - 0.3 - - 0.5 - - 0.7 - - 0.9 - min_crop_size: 0.3 - - type: Resize - scale: - - 864 - - 864 - keep_ratio: false - - type: RandomFlip - prob: 0.5 - - type: PackDetInputs - meta_keys: - - ori_filename - - flip_direction - - scale_factor - - gt_ann_ids - - flip - - ignored_labels - - ori_shape - - filename - - img_shape - - pad_shape - val_subset: - batch_size: 8 - transforms: - - type: LoadImageFromFile - - type: Resize - scale: - - 864 - - 864 - keep_ratio: false - - type: LoadAnnotations - with_bbox: true - - type: PackDetInputs - meta_keys: - - ori_filename - - scale_factor - - ori_shape - - filename - - img_shape - - pad_shape - test_subset: - batch_size: 8 - transforms: - - type: LoadImageFromFile - - type: Resize - scale: - - 864 - - 864 - keep_ratio: false - - type: LoadAnnotations - with_bbox: true - - type: PackDetInputs - meta_keys: - - ori_filename - - scale_factor - - ori_shape - - filename - - img_shape - - pad_shape model: - otx_model: - _target_: otx.algo.detection.ssd.SSD + class_path: otx.algo.detection.ssd.SSD + init_args: + num_classes: 80 variant: mobilenetv2 - optimizer: - _target_: torch.optim.SGD - _partial_: true + +optimizer: + class_path: torch.optim.SGD + init_args: lr: 0.01 - weight_decay: 0.0001 momentum: 0.9 -trainer: + weight_decay: 0.0001 + +scheduler: + class_path: lightning.pytorch.cli.ReduceLROnPlateau + init_args: + mode: min + factor: 0.1 + patience: 10 + monitor: train/loss + +engine: + task: DETECTION + device: auto + +callback_monitor: val/map_50 + +data: ../_base_/data/mmdet_base.yaml +overrides: gradient_clip_val: 35.0 + data: + config: + train_subset: + batch_size: 8 + transforms: + - type: LoadImageFromFile + - type: LoadAnnotations + with_bbox: true + - type: PhotoMetricDistortion + brightness_delta: 32 + contrast_range: + - 0.5 + - 1.5 + hue_delta: 18 + - type: MinIoURandomCrop + min_ious: + - 0.1 + - 0.3 + - 0.5 + - 0.7 + - 0.9 + min_crop_size: 0.3 + - type: Resize + scale: + - 864 + - 864 + keep_ratio: false + - type: RandomFlip + prob: 0.5 + - type: PackDetInputs + meta_keys: + - ori_filename + - flip_direction + - scale_factor + - gt_ann_ids + - flip + - ignored_labels + - ori_shape + - filename + - img_shape + - pad_shape + val_subset: + batch_size: 8 + transforms: + - type: LoadImageFromFile + - type: Resize + scale: + - 864 + - 864 + keep_ratio: false + - type: LoadAnnotations + with_bbox: true + - type: PackDetInputs + meta_keys: + - ori_filename + - scale_factor + - ori_shape + - filename + - img_shape + - pad_shape + test_subset: + batch_size: 8 + transforms: + - type: LoadImageFromFile + - type: Resize + scale: + - 864 + - 864 + keep_ratio: false + - type: LoadAnnotations + with_bbox: true + - type: PackDetInputs + meta_keys: + - ori_filename + - scale_factor + - ori_shape + - filename + - img_shape + - pad_shape diff --git a/src/otx/recipe/detection/yolox_l.yaml b/src/otx/recipe/detection/yolox_l.yaml index 1d96f0e2263..0900c6030ab 100644 --- a/src/otx/recipe/detection/yolox_l.yaml +++ b/src/otx/recipe/detection/yolox_l.yaml @@ -1,122 +1,134 @@ -# @package _global_ -defaults: - - override /trainer: default - - override /base: detection - - override /callbacks: detection - - override /data: mmdet - - override /model: mmdet -data: - image_color_channel: BGR - train_subset: - batch_size: 8 - transforms: - - type: LoadImageFromFile - - type: LoadAnnotations - with_bbox: true - - type: CachedMosaic - random_pop: false - pad_val: 114.0 - max_cached_images: 20 - img_scale: - - 640 - - 640 - - type: RandomAffine - scaling_ratio_range: - - 0.1 - - 2.0 - border: - - -320 - - -320 - - type: CachedMixUp - img_scale: - - 640 - - 640 - ratio_range: - - 1.0 - - 1.0 - prob: 0.5 - random_pop: false - pad_val: - - 114 - - 114 - - 114 - max_cached_images: 10 - - type: YOLOXHSVRandomAug - - type: Resize - scale: - - 640 - - 640 - keep_ratio: true - - type: RandomFlip - prob: 0.5 - - type: Pad - pad_to_square: true - pad_val: 114 - - type: PackDetInputs - meta_keys: - - ori_filename - - flip_direction - - scale_factor - - gt_ann_ids - - flip - - ignored_labels - - ori_shape - - filename - - img_shape - - pad_shape - val_subset: - batch_size: 8 - transforms: - - type: LoadImageFromFile - - type: Resize - scale: - - 640 - - 640 - keep_ratio: True - - type: Pad - pad_to_square: true - pad_val: 114 - - type: LoadAnnotations - with_bbox: true - - type: PackDetInputs - meta_keys: - - ori_filename - - scale_factor - - ori_shape - - filename - - img_shape - - pad_shape - test_subset: - batch_size: 8 - transforms: - - type: LoadImageFromFile - - type: Resize - scale: - - 640 - - 640 - keep_ratio: True - - type: Pad - pad_to_square: true - pad_val: 114 - - type: LoadAnnotations - with_bbox: true - - type: PackDetInputs - meta_keys: - - ori_filename - - scale_factor - - ori_shape - - filename - - img_shape - - pad_shape model: - otx_model: - _target_: otx.algo.detection.yolox.YoloX + class_path: otx.algo.detection.yolox.YoloX + init_args: + num_classes: 80 variant: l - optimizer: - _target_: torch.optim.SGD - _partial_: true + +optimizer: + class_path: torch.optim.SGD + init_args: lr: 0.001 - weight_decay: 0.0001 momentum: 0.9 -trainer: + weight_decay: 0.0001 + +scheduler: + class_path: lightning.pytorch.cli.ReduceLROnPlateau + init_args: + mode: min + factor: 0.1 + patience: 10 + monitor: train/loss + +engine: + task: DETECTION + device: auto + +callback_monitor: val/map_50 + +data: ../_base_/data/mmdet_base.yaml +overrides: gradient_clip_val: 35.0 + data: + config: + image_color_channel: BGR + train_subset: + batch_size: 8 + transforms: + - type: LoadImageFromFile + - type: LoadAnnotations + with_bbox: true + - type: CachedMosaic + random_pop: false + pad_val: 114.0 + max_cached_images: 20 + img_scale: + - 640 + - 640 + - type: RandomAffine + scaling_ratio_range: + - 0.1 + - 2.0 + border: + - -320 + - -320 + - type: CachedMixUp + img_scale: + - 640 + - 640 + ratio_range: + - 1.0 + - 1.0 + prob: 0.5 + random_pop: false + pad_val: + - 114 + - 114 + - 114 + max_cached_images: 10 + - type: YOLOXHSVRandomAug + - type: Resize + scale: + - 640 + - 640 + keep_ratio: true + - type: RandomFlip + prob: 0.5 + - type: Pad + pad_to_square: true + pad_val: 114 + - type: PackDetInputs + meta_keys: + - ori_filename + - flip_direction + - scale_factor + - gt_ann_ids + - flip + - ignored_labels + - ori_shape + - filename + - img_shape + - pad_shape + val_subset: + batch_size: 8 + transforms: + - type: LoadImageFromFile + - type: Resize + scale: + - 640 + - 640 + keep_ratio: true + - type: Pad + pad_to_square: true + pad_val: 114 + - type: LoadAnnotations + with_bbox: true + - type: PackDetInputs + meta_keys: + - ori_filename + - scale_factor + - ori_shape + - filename + - img_shape + - pad_shape + test_subset: + batch_size: 8 + transforms: + - type: LoadImageFromFile + - type: Resize + scale: + - 640 + - 640 + keep_ratio: true + - type: Pad + pad_to_square: true + pad_val: 114 + - type: LoadAnnotations + with_bbox: true + - type: PackDetInputs + meta_keys: + - ori_filename + - scale_factor + - ori_shape + - filename + - img_shape + - pad_shape diff --git a/src/otx/recipe/detection/yolox_s.yaml b/src/otx/recipe/detection/yolox_s.yaml index d2808149c5f..1f4f2a51104 100644 --- a/src/otx/recipe/detection/yolox_s.yaml +++ b/src/otx/recipe/detection/yolox_s.yaml @@ -1,122 +1,134 @@ -# @package _global_ -defaults: - - override /trainer: default - - override /base: detection - - override /callbacks: detection - - override /data: mmdet - - override /model: mmdet -data: - image_color_channel: BGR - train_subset: - batch_size: 8 - transforms: - - type: LoadImageFromFile - - type: LoadAnnotations - with_bbox: true - - type: CachedMosaic - random_pop: false - pad_val: 114.0 - max_cached_images: 20 - img_scale: - - 640 - - 640 - - type: RandomAffine - scaling_ratio_range: - - 0.1 - - 2.0 - border: - - -320 - - -320 - - type: CachedMixUp - img_scale: - - 640 - - 640 - ratio_range: - - 1.0 - - 1.0 - prob: 0.5 - random_pop: false - pad_val: - - 114 - - 114 - - 114 - max_cached_images: 10 - - type: YOLOXHSVRandomAug - - type: Resize - scale: - - 640 - - 640 - keep_ratio: True - - type: RandomFlip - prob: 0.5 - - type: Pad - pad_to_square: true - pad_val: 114 - - type: PackDetInputs - meta_keys: - - ori_filename - - flip_direction - - scale_factor - - gt_ann_ids - - flip - - ignored_labels - - ori_shape - - filename - - img_shape - - pad_shape - val_subset: - batch_size: 8 - transforms: - - type: LoadImageFromFile - - type: Resize - scale: - - 640 - - 640 - keep_ratio: True - - type: Pad - pad_to_square: true - pad_val: 114 - - type: LoadAnnotations - with_bbox: true - - type: PackDetInputs - meta_keys: - - ori_filename - - scale_factor - - ori_shape - - filename - - img_shape - - pad_shape - test_subset: - batch_size: 8 - transforms: - - type: LoadImageFromFile - - type: Resize - scale: - - 640 - - 640 - keep_ratio: True - - type: Pad - pad_to_square: true - pad_val: 114 - - type: LoadAnnotations - with_bbox: true - - type: PackDetInputs - meta_keys: - - ori_filename - - scale_factor - - ori_shape - - filename - - img_shape - - pad_shape model: - otx_model: - _target_: otx.algo.detection.yolox.YoloX + class_path: otx.algo.detection.yolox.YoloX + init_args: + num_classes: 80 variant: s - optimizer: - _target_: torch.optim.SGD - _partial_: true + +optimizer: + class_path: torch.optim.SGD + init_args: lr: 0.001 - weight_decay: 0.0001 momentum: 0.9 -trainer: + weight_decay: 0.0001 + +scheduler: + class_path: lightning.pytorch.cli.ReduceLROnPlateau + init_args: + mode: min + factor: 0.1 + patience: 10 + monitor: train/loss + +engine: + task: DETECTION + device: auto + +callback_monitor: val/map_50 + +data: ../_base_/data/mmdet_base.yaml +overrides: gradient_clip_val: 35.0 + data: + config: + image_color_channel: BGR + train_subset: + batch_size: 8 + transforms: + - type: LoadImageFromFile + - type: LoadAnnotations + with_bbox: true + - type: CachedMosaic + random_pop: false + pad_val: 114.0 + max_cached_images: 20 + img_scale: + - 640 + - 640 + - type: RandomAffine + scaling_ratio_range: + - 0.1 + - 2.0 + border: + - -320 + - -320 + - type: CachedMixUp + img_scale: + - 640 + - 640 + ratio_range: + - 1.0 + - 1.0 + prob: 0.5 + random_pop: false + pad_val: + - 114 + - 114 + - 114 + max_cached_images: 10 + - type: YOLOXHSVRandomAug + - type: Resize + scale: + - 640 + - 640 + keep_ratio: True + - type: RandomFlip + prob: 0.5 + - type: Pad + pad_to_square: true + pad_val: 114 + - type: PackDetInputs + meta_keys: + - ori_filename + - flip_direction + - scale_factor + - gt_ann_ids + - flip + - ignored_labels + - ori_shape + - filename + - img_shape + - pad_shape + val_subset: + batch_size: 8 + transforms: + - type: LoadImageFromFile + - type: Resize + scale: + - 640 + - 640 + keep_ratio: True + - type: Pad + pad_to_square: true + pad_val: 114 + - type: LoadAnnotations + with_bbox: true + - type: PackDetInputs + meta_keys: + - ori_filename + - scale_factor + - ori_shape + - filename + - img_shape + - pad_shape + test_subset: + batch_size: 8 + transforms: + - type: LoadImageFromFile + - type: Resize + scale: + - 640 + - 640 + keep_ratio: True + - type: Pad + pad_to_square: true + pad_val: 114 + - type: LoadAnnotations + with_bbox: true + - type: PackDetInputs + meta_keys: + - ori_filename + - scale_factor + - ori_shape + - filename + - img_shape + - pad_shape diff --git a/src/otx/recipe/detection/yolox_tiny.yaml b/src/otx/recipe/detection/yolox_tiny.yaml index e81cd3eaa98..ed09b2cb371 100644 --- a/src/otx/recipe/detection/yolox_tiny.yaml +++ b/src/otx/recipe/detection/yolox_tiny.yaml @@ -1,115 +1,127 @@ -# @package _global_ -defaults: - - override /trainer: default - - override /base: detection - - override /callbacks: detection - - override /data: mmdet - - override /model: mmdet -data: - train_subset: - batch_size: 8 - transforms: - - type: LoadImageFromFile - - type: LoadAnnotations - with_bbox: true - - type: CachedMosaic - random_pop: false - pad_val: 114.0 - max_cached_images: 20 - img_scale: - - 640 - - 640 - - type: RandomAffine - scaling_ratio_range: - - 0.5 - - 1.5 - border: - - -320 - - -320 - - type: PhotoMetricDistortion - brightness_delta: 32 - contrast_range: - - 0.5 - - 1.5 - saturation_range: - - 0.5 - - 1.5 - hue_delta: 18 - - type: Resize - scale: - - 640 - - 640 - keep_ratio: True - - type: RandomFlip - prob: 0.5 - - type: Pad - pad_to_square: true - pad_val: 114 - - type: PackDetInputs - meta_keys: - - ori_filename - - flip_direction - - scale_factor - - gt_ann_ids - - flip - - ignored_labels - - ori_shape - - filename - - img_shape - - pad_shape - val_subset: - batch_size: 8 - transforms: - - type: LoadImageFromFile - - type: Resize - scale: - - 416 - - 416 - keep_ratio: True - - type: Pad - pad_to_square: true - pad_val: 114 - - type: LoadAnnotations - with_bbox: true - - type: PackDetInputs - meta_keys: - - ori_filename - - scale_factor - - ori_shape - - filename - - img_shape - - pad_shape - test_subset: - batch_size: 8 - transforms: - - type: LoadImageFromFile - - type: Resize - scale: - - 416 - - 416 - keep_ratio: True - - type: Pad - pad_to_square: true - pad_val: 114 - - type: LoadAnnotations - with_bbox: true - - type: PackDetInputs - meta_keys: - - ori_filename - - scale_factor - - ori_shape - - filename - - img_shape - - pad_shape model: - otx_model: - _target_: otx.algo.detection.yolox.YoloX + class_path: otx.algo.detection.yolox.YoloX + init_args: + num_classes: 80 variant: tiny - optimizer: - _target_: torch.optim.SGD - _partial_: true + +optimizer: + class_path: torch.optim.SGD + init_args: lr: 0.0002 - weight_decay: 0.0001 momentum: 0.9 -trainer: + weight_decay: 0.0001 + +scheduler: + class_path: lightning.pytorch.cli.ReduceLROnPlateau + init_args: + mode: min + factor: 0.1 + patience: 10 + monitor: train/loss + +engine: + task: DETECTION + device: auto + +callback_monitor: val/map_50 + +data: ../_base_/data/mmdet_base.yaml +overrides: gradient_clip_val: 35.0 + data: + config: + train_subset: + batch_size: 8 + transforms: + - type: LoadImageFromFile + - type: LoadAnnotations + with_bbox: true + - type: CachedMosaic + random_pop: false + pad_val: 114.0 + max_cached_images: 20 + img_scale: + - 640 + - 640 + - type: RandomAffine + scaling_ratio_range: + - 0.5 + - 1.5 + border: + - -320 + - -320 + - type: PhotoMetricDistortion + brightness_delta: 32 + contrast_range: + - 0.5 + - 1.5 + saturation_range: + - 0.5 + - 1.5 + hue_delta: 18 + - type: Resize + scale: + - 640 + - 640 + keep_ratio: True + - type: RandomFlip + prob: 0.5 + - type: Pad + pad_to_square: true + pad_val: 114 + - type: PackDetInputs + meta_keys: + - ori_filename + - flip_direction + - scale_factor + - gt_ann_ids + - flip + - ignored_labels + - ori_shape + - filename + - img_shape + - pad_shape + val_subset: + batch_size: 8 + transforms: + - type: LoadImageFromFile + - type: Resize + scale: + - 416 + - 416 + keep_ratio: True + - type: Pad + pad_to_square: true + pad_val: 114 + - type: LoadAnnotations + with_bbox: true + - type: PackDetInputs + meta_keys: + - ori_filename + - scale_factor + - ori_shape + - filename + - img_shape + - pad_shape + test_subset: + batch_size: 8 + transforms: + - type: LoadImageFromFile + - type: Resize + scale: + - 416 + - 416 + keep_ratio: True + - type: Pad + pad_to_square: true + pad_val: 114 + - type: LoadAnnotations + with_bbox: true + - type: PackDetInputs + meta_keys: + - ori_filename + - scale_factor + - ori_shape + - filename + - img_shape + - pad_shape diff --git a/src/otx/recipe/detection/yolox_x.yaml b/src/otx/recipe/detection/yolox_x.yaml index aab0f0a4307..453d078bbc7 100644 --- a/src/otx/recipe/detection/yolox_x.yaml +++ b/src/otx/recipe/detection/yolox_x.yaml @@ -1,122 +1,134 @@ -# @package _global_ -defaults: - - override /trainer: default - - override /base: detection - - override /callbacks: detection - - override /data: mmdet - - override /model: mmdet -data: - image_color_channel: BGR - train_subset: - batch_size: 4 - transforms: - - type: LoadImageFromFile - - type: LoadAnnotations - with_bbox: true - - type: CachedMosaic - random_pop: false - pad_val: 114.0 - max_cached_images: 20 - img_scale: - - 640 - - 640 - - type: RandomAffine - scaling_ratio_range: - - 0.1 - - 2.0 - border: - - -320 - - -320 - - type: CachedMixUp - img_scale: - - 640 - - 640 - ratio_range: - - 1.0 - - 1.0 - prob: 0.5 - random_pop: false - pad_val: - - 114 - - 114 - - 114 - max_cached_images: 10 - - type: YOLOXHSVRandomAug - - type: Resize - scale: - - 640 - - 640 - keep_ratio: true - - type: RandomFlip - prob: 0.5 - - type: Pad - pad_to_square: true - pad_val: 114 - - type: PackDetInputs - meta_keys: - - ori_filename - - flip_direction - - scale_factor - - gt_ann_ids - - flip - - ignored_labels - - ori_shape - - filename - - img_shape - - pad_shape - val_subset: - batch_size: 4 - transforms: - - type: LoadImageFromFile - - type: Resize - scale: - - 640 - - 640 - keep_ratio: True - - type: Pad - pad_to_square: true - pad_val: 114 - - type: LoadAnnotations - with_bbox: true - - type: PackDetInputs - meta_keys: - - ori_filename - - scale_factor - - ori_shape - - filename - - img_shape - - pad_shape - test_subset: - batch_size: 4 - transforms: - - type: LoadImageFromFile - - type: Resize - scale: - - 640 - - 640 - keep_ratio: True - - type: Pad - pad_to_square: true - pad_val: 114 - - type: LoadAnnotations - with_bbox: true - - type: PackDetInputs - meta_keys: - - ori_filename - - scale_factor - - ori_shape - - filename - - img_shape - - pad_shape model: - otx_model: - _target_: otx.algo.detection.yolox.YoloX + class_path: otx.algo.detection.yolox.YoloX + init_args: + num_classes: 80 variant: x - optimizer: - _target_: torch.optim.SGD - _partial_: true + +optimizer: + class_path: torch.optim.SGD + init_args: lr: 0.001 - weight_decay: 0.0001 momentum: 0.9 -trainer: + weight_decay: 0.0001 + +scheduler: + class_path: lightning.pytorch.cli.ReduceLROnPlateau + init_args: + mode: min + factor: 0.1 + patience: 10 + monitor: train/loss + +engine: + task: DETECTION + device: auto + +callback_monitor: val/map_50 + +data: ../_base_/data/mmdet_base.yaml +overrides: gradient_clip_val: 35.0 + data: + config: + image_color_channel: BGR + train_subset: + batch_size: 4 + transforms: + - type: LoadImageFromFile + - type: LoadAnnotations + with_bbox: true + - type: CachedMosaic + random_pop: false + pad_val: 114.0 + max_cached_images: 20 + img_scale: + - 640 + - 640 + - type: RandomAffine + scaling_ratio_range: + - 0.5 + - 1.5 + border: + - -320 + - -320 + - type: CachedMixUp + img_scale: + - 640 + - 640 + ratio_range: + - 1.0 + - 1.0 + prob: 0.5 + random_pop: false + pad_val: + - 114 + - 114 + - 114 + max_cached_images: 10 + - type: YOLOXHSVRandomAug + - type: Resize + scale: + - 640 + - 640 + keep_ratio: True + - type: RandomFlip + prob: 0.5 + - type: Pad + pad_to_square: true + pad_val: 114 + - type: PackDetInputs + meta_keys: + - ori_filename + - flip_direction + - scale_factor + - gt_ann_ids + - flip + - ignored_labels + - ori_shape + - filename + - img_shape + - pad_shape + val_subset: + batch_size: 4 + transforms: + - type: LoadImageFromFile + - type: Resize + scale: + - 640 + - 640 + keep_ratio: True + - type: Pad + pad_to_square: true + pad_val: 114 + - type: LoadAnnotations + with_bbox: true + - type: PackDetInputs + meta_keys: + - ori_filename + - scale_factor + - ori_shape + - filename + - img_shape + - pad_shape + test_subset: + batch_size: 4 + transforms: + - type: LoadImageFromFile + - type: Resize + scale: + - 640 + - 640 + keep_ratio: True + - type: Pad + pad_to_square: true + pad_val: 114 + - type: LoadAnnotations + with_bbox: true + - type: PackDetInputs + meta_keys: + - ori_filename + - scale_factor + - ori_shape + - filename + - img_shape + - pad_shape diff --git a/src/otx/recipe/hlabel_classification/efficientnet_b0_light.yaml b/src/otx/recipe/hlabel_classification/efficientnet_b0_light.yaml deleted file mode 100644 index 2f8b3d1e64d..00000000000 --- a/src/otx/recipe/hlabel_classification/efficientnet_b0_light.yaml +++ /dev/null @@ -1,46 +0,0 @@ -# @package _global_ -defaults: - - override /base: hlabel_classification - - override /callbacks: hlabel_classification - - override /data: hlabel_mmpretrain - - override /model: hlabel_mmpretrain -data: - train_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - - backend: cv2 - scale: 224 - type: RandomResizedCrop - - type: PackInputs - val_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - - backend: cv2 - edge: short - scale: 256 - type: ResizeEdge - - crop_size: 224 - type: CenterCrop - - type: PackInputs - test_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - - backend: cv2 - edge: short - scale: 256 - type: ResizeEdge - - crop_size: 224 - type: CenterCrop - - type: PackInputs -model: - otx_model: - _target_: otx.algo.classification.efficientnet_b0.EfficientNetB0ForHLabelCls - optimizer: - _target_: torch.optim.SGD - lr: 0.0049 - scheduler: - factor: 0.5 - patience: 1 diff --git a/src/otx/recipe/hlabel_classification/efficientnet_v2_light.yaml b/src/otx/recipe/hlabel_classification/efficientnet_v2_light.yaml deleted file mode 100644 index 38545bdaa9c..00000000000 --- a/src/otx/recipe/hlabel_classification/efficientnet_v2_light.yaml +++ /dev/null @@ -1,52 +0,0 @@ -# @package _global_ -defaults: - - override /base: hlabel_classification - - override /callbacks: hlabel_classification - - override /data: hlabel_mmpretrain - - override /model: hlabel_mmpretrain -data: - train_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - - backend: cv2 - scale: 224 - type: RandomResizedCrop - - direction: horizontal - prob: 0.5 - type: RandomFlip - - type: PackInputs - val_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - - backend: cv2 - edge: short - scale: 256 - type: ResizeEdge - - crop_size: 224 - type: CenterCrop - - type: PackInputs - test_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - - backend: cv2 - edge: short - scale: 256 - type: ResizeEdge - - crop_size: 224 - type: CenterCrop - - type: PackInputs -model: - otx_model: - _target_: otx.algo.classification.efficientnet_v2.EfficientNetV2ForHLabelCls - optimizer: - _target_: torch.optim.SGD - _partial_: true - lr: 0.0071 - momentum: 0.9 - weight_decay: 0.0001 - scheduler: - factor: 0.5 - patience: 1 diff --git a/src/otx/recipe/hlabel_classification/mobilenet_v3_large_light.yaml b/src/otx/recipe/hlabel_classification/mobilenet_v3_large_light.yaml deleted file mode 100644 index 52c5089ac72..00000000000 --- a/src/otx/recipe/hlabel_classification/mobilenet_v3_large_light.yaml +++ /dev/null @@ -1,52 +0,0 @@ -# @package _global_ -defaults: - - override /base: hlabel_classification - - override /callbacks: hlabel_classification - - override /data: hlabel_mmpretrain - - override /model: hlabel_mmpretrain -data: - train_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - - backend: cv2 - scale: 224 - type: RandomResizedCrop - - direction: horizontal - prob: 0.5 - type: RandomFlip - - type: PackInputs - val_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - - backend: cv2 - edge: short - scale: 256 - type: ResizeEdge - - crop_size: 224 - type: CenterCrop - - type: PackInputs - test_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - - backend: cv2 - edge: short - scale: 256 - type: ResizeEdge - - crop_size: 224 - type: CenterCrop - - type: PackInputs -model: - otx_model: - _target_: otx.algo.classification.mobilenet_v3_large.MobileNetV3ForHLabelCls - optimizer: - _target_: torch.optim.SGD - _partial_: true - lr: 0.0058 - momentum: 0.9 - weight_decay: 0.0001 - scheduler: - factor: 0.5 - patience: 1 diff --git a/src/otx/recipe/hlabel_classification/otx_deit_tiny.yaml b/src/otx/recipe/hlabel_classification/otx_deit_tiny.yaml deleted file mode 100644 index ec37e0d30c2..00000000000 --- a/src/otx/recipe/hlabel_classification/otx_deit_tiny.yaml +++ /dev/null @@ -1,49 +0,0 @@ -# @package _global_ -defaults: - - override /base: hlabel_classification - - override /callbacks: hlabel_classification - - override /data: hlabel_mmpretrain - - override /model: hlabel_mmpretrain -data: - train_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - - backend: cv2 - scale: 224 - type: RandomResizedCrop - - type: PackInputs - val_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - - backend: cv2 - edge: short - scale: 256 - type: ResizeEdge - - crop_size: 224 - type: CenterCrop - - type: PackInputs - test_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - - backend: cv2 - edge: short - scale: 256 - type: ResizeEdge - - crop_size: 224 - type: CenterCrop - - type: PackInputs -model: - otx_model: - _target_: otx.algo.classification.deit_tiny.DeitTinyForHLabelCls - optimizer: - _target_: torch.optim.SGD - _partial_: true - lr: 0.0001 - momentum: 0.9 - weight_decay: 0.0001 - scheduler: - factor: 0.5 - patience: 1 diff --git a/src/otx/recipe/instance_segmentation/maskrcnn_efficientnetb2b.yaml b/src/otx/recipe/instance_segmentation/maskrcnn_efficientnetb2b.yaml index 446996a4a07..17ac63e28b7 100644 --- a/src/otx/recipe/instance_segmentation/maskrcnn_efficientnetb2b.yaml +++ b/src/otx/recipe/instance_segmentation/maskrcnn_efficientnetb2b.yaml @@ -1,73 +1,89 @@ -# @package _global_ -defaults: - - override /base: instance_segmentation - - override /callbacks: instance_segmentation - - override /data: mmdet_inst_seg - - override /model: mmdet_inst_seg - -data: - train_subset: - batch_size: 4 - transforms: - - type: LoadImageFromFile - backend_args: null - - type: LoadAnnotations - with_bbox: true - with_mask: true - - type: Resize - keep_ratio: true - scale: - - 1024 - - 1024 - - type: RandomFlip - prob: 0.5 - - type: PackDetInputs - val_subset: - batch_size: 1 - transforms: - - type: LoadImageFromFile - backend_args: null - - type: Resize - keep_ratio: true - scale: - - 1024 - - 1024 - - type: LoadAnnotations - with_bbox: true - with_mask: true - - type: PackDetInputs - meta_keys: - - img_id - - img_path - - ori_shape - - img_shape - - scale_factor - test_subset: - batch_size: 1 - transforms: - - type: LoadImageFromFile - backend_args: null - - type: Resize - keep_ratio: true - scale: - - 1024 - - 1024 - - type: LoadAnnotations - with_bbox: true - with_mask: true - - type: PackDetInputs - meta_keys: - - img_id - - img_path - - ori_shape - - img_shape - - scale_factor - model: - otx_model: - _target_: otx.algo.instance_segmentation.maskrcnn.MaskRCNN + class_path: otx.algo.instance_segmentation.maskrcnn.MaskRCNN + init_args: + num_classes: 80 variant: efficientnetb2b - optimizer: + +optimizer: + class_path: torch.optim.SGD + init_args: lr: 0.007 - weight_decay: 0.001 momentum: 0.9 + weight_decay: 0.001 + +scheduler: + class_path: lightning.pytorch.cli.ReduceLROnPlateau + init_args: + mode: min + factor: 0.1 + patience: 10 + monitor: train/loss + +engine: + task: INSTANCE_SEGMENTATION + device: auto + +callback_monitor: val/map_50 + +data: ../_base_/data/mmdet_base.yaml +overrides: + data: + task: INSTANCE_SEGMENTATION + config: + include_polygons: true + train_subset: + batch_size: 4 + transforms: + - type: LoadImageFromFile + backend_args: null + - type: LoadAnnotations + with_bbox: true + with_mask: true + - type: Resize + keep_ratio: true + scale: + - 1024 + - 1024 + - type: RandomFlip + prob: 0.5 + - type: PackDetInputs + val_subset: + batch_size: 1 + transforms: + - type: LoadImageFromFile + backend_args: null + - type: Resize + keep_ratio: true + scale: + - 1024 + - 1024 + - type: LoadAnnotations + with_bbox: true + with_mask: true + - type: PackDetInputs + meta_keys: + - img_id + - img_path + - ori_shape + - img_shape + - scale_factor + test_subset: + batch_size: 1 + transforms: + - type: LoadImageFromFile + backend_args: null + - type: Resize + keep_ratio: true + scale: + - 1024 + - 1024 + - type: LoadAnnotations + with_bbox: true + with_mask: true + - type: PackDetInputs + meta_keys: + - img_id + - img_path + - ori_shape + - img_shape + - scale_factor diff --git a/src/otx/recipe/instance_segmentation/maskrcnn_r50.yaml b/src/otx/recipe/instance_segmentation/maskrcnn_r50.yaml index 03181a9a483..e1665243327 100644 --- a/src/otx/recipe/instance_segmentation/maskrcnn_r50.yaml +++ b/src/otx/recipe/instance_segmentation/maskrcnn_r50.yaml @@ -1,73 +1,89 @@ -# @package _global_ -defaults: - - override /base: instance_segmentation - - override /callbacks: instance_segmentation - - override /data: mmdet_inst_seg - - override /model: mmdet_inst_seg - -data: - train_subset: - batch_size: 4 - transforms: - - type: LoadImageFromFile - backend_args: null - - type: LoadAnnotations - with_bbox: true - with_mask: true - - type: Resize - keep_ratio: true - scale: - - 1024 - - 1024 - - type: RandomFlip - prob: 0.5 - - type: PackDetInputs - val_subset: - batch_size: 1 - transforms: - - type: LoadImageFromFile - backend_args: null - - type: Resize - keep_ratio: true - scale: - - 1024 - - 1024 - - type: LoadAnnotations - with_bbox: true - with_mask: true - - type: PackDetInputs - meta_keys: - - img_id - - img_path - - ori_shape - - img_shape - - scale_factor - test_subset: - batch_size: 1 - transforms: - - type: LoadImageFromFile - backend_args: null - - type: Resize - keep_ratio: true - scale: - - 1024 - - 1024 - - type: LoadAnnotations - with_bbox: true - with_mask: true - - type: PackDetInputs - meta_keys: - - img_id - - img_path - - ori_shape - - img_shape - - scale_factor - model: - otx_model: - _target_: otx.algo.instance_segmentation.maskrcnn.MaskRCNN + class_path: otx.algo.instance_segmentation.maskrcnn.MaskRCNN + init_args: + num_classes: 80 variant: r50 - optimizer: + +optimizer: + class_path: torch.optim.SGD + init_args: lr: 0.007 - weight_decay: 0.001 momentum: 0.9 + weight_decay: 0.001 + +scheduler: + class_path: lightning.pytorch.cli.ReduceLROnPlateau + init_args: + mode: min + factor: 0.1 + patience: 10 + monitor: train/loss + +engine: + task: INSTANCE_SEGMENTATION + device: auto + +callback_monitor: val/map_50 + +data: ../_base_/data/mmdet_base.yaml +overrides: + data: + task: INSTANCE_SEGMENTATION + config: + include_polygons: true + train_subset: + batch_size: 4 + transforms: + - type: LoadImageFromFile + backend_args: null + - type: LoadAnnotations + with_bbox: true + with_mask: true + - type: Resize + keep_ratio: true + scale: + - 1024 + - 1024 + - type: RandomFlip + prob: 0.5 + - type: PackDetInputs + val_subset: + batch_size: 1 + transforms: + - type: LoadImageFromFile + backend_args: null + - type: Resize + keep_ratio: true + scale: + - 1024 + - 1024 + - type: LoadAnnotations + with_bbox: true + with_mask: true + - type: PackDetInputs + meta_keys: + - img_id + - img_path + - ori_shape + - img_shape + - scale_factor + test_subset: + batch_size: 1 + transforms: + - type: LoadImageFromFile + backend_args: null + - type: Resize + keep_ratio: true + scale: + - 1024 + - 1024 + - type: LoadAnnotations + with_bbox: true + with_mask: true + - type: PackDetInputs + meta_keys: + - img_id + - img_path + - ori_shape + - img_shape + - scale_factor diff --git a/src/otx/recipe/instance_segmentation/maskrcnn_swint.yaml b/src/otx/recipe/instance_segmentation/maskrcnn_swint.yaml index f933b053765..5de05403938 100644 --- a/src/otx/recipe/instance_segmentation/maskrcnn_swint.yaml +++ b/src/otx/recipe/instance_segmentation/maskrcnn_swint.yaml @@ -1,74 +1,88 @@ -# @package _global_ -defaults: - - override /base: instance_segmentation - - override /callbacks: instance_segmentation - - override /data: mmdet_inst_seg - - override /model: mmdet_inst_seg - -data: - train_subset: - batch_size: 4 - transforms: - - type: LoadImageFromFile - backend_args: null - - type: LoadAnnotations - with_bbox: true - with_mask: true - - type: Resize - keep_ratio: true - scale: - - 1344 - - 1344 - - type: RandomFlip - prob: 0.5 - - type: PackDetInputs - val_subset: - batch_size: 1 - transforms: - - type: LoadImageFromFile - backend_args: null - - type: Resize - keep_ratio: true - scale: - - 1344 - - 1344 - - type: LoadAnnotations - with_bbox: true - with_mask: true - - type: PackDetInputs - meta_keys: - - img_id - - img_path - - ori_shape - - img_shape - - scale_factor - test_subset: - batch_size: 1 - transforms: - - type: LoadImageFromFile - backend_args: null - - type: Resize - keep_ratio: true - scale: - - 1344 - - 1344 - - type: LoadAnnotations - with_bbox: true - with_mask: true - - type: PackDetInputs - meta_keys: - - img_id - - img_path - - ori_shape - - img_shape - - scale_factor - model: - otx_model: - _target_: otx.algo.instance_segmentation.maskrcnn.MaskRCNN + class_path: otx.algo.instance_segmentation.maskrcnn.MaskRCNN + init_args: + num_classes: 80 variant: swint - optimizer: - _target_: torch.optim.AdamW - _partial_: true + +optimizer: + class_path: torch.optim.AdamW + init_args: lr: 0.0001 weight_decay: 0.05 + +scheduler: + class_path: lightning.pytorch.cli.ReduceLROnPlateau + init_args: + mode: min + factor: 0.1 + patience: 10 + monitor: train/loss + +engine: + task: INSTANCE_SEGMENTATION + device: auto + +callback_monitor: val/map_50 + +data: ../_base_/data/mmdet_base.yaml +overrides: + data: + task: INSTANCE_SEGMENTATION + config: + include_polygons: true + train_subset: + batch_size: 4 + transforms: + - type: LoadImageFromFile + backend_args: null + - type: LoadAnnotations + with_bbox: true + with_mask: true + - type: Resize + keep_ratio: true + scale: + - 1344 + - 1344 + - type: RandomFlip + prob: 0.5 + - type: PackDetInputs + val_subset: + batch_size: 1 + transforms: + - type: LoadImageFromFile + backend_args: null + - type: Resize + keep_ratio: true + scale: + - 1344 + - 1344 + - type: LoadAnnotations + with_bbox: true + with_mask: true + - type: PackDetInputs + meta_keys: + - img_id + - img_path + - ori_shape + - img_shape + - scale_factor + test_subset: + batch_size: 1 + transforms: + - type: LoadImageFromFile + backend_args: null + - type: Resize + keep_ratio: true + scale: + - 1344 + - 1344 + - type: LoadAnnotations + with_bbox: true + with_mask: true + - type: PackDetInputs + meta_keys: + - img_id + - img_path + - ori_shape + - img_shape + - scale_factor diff --git a/src/otx/recipe/instance_segmentation/openvino_model.yaml b/src/otx/recipe/instance_segmentation/openvino_model.yaml index 979e2746d99..e758baeed4b 100644 --- a/src/otx/recipe/instance_segmentation/openvino_model.yaml +++ b/src/otx/recipe/instance_segmentation/openvino_model.yaml @@ -1,21 +1,41 @@ -# @package _global_ -defaults: - - override /base: instance_segmentation - - override /callbacks: instance_segmentation - - override /data: openvino - - override /model: mmdet_inst_seg +model: + class_path: otx.core.model.entity.instance_segmentation.OVInstanceSegmentationModel + init_args: + num_classes: 80 + config: + class_path: omegaconf.dictconfig.DictConfig + init_args: + content: + model_name: /home/kprokofi/training_extensions/otx-workspace-INSTANCE_SEGMENTATION/outputs/20240109_072818_export/openvino/openvino.xml + model_type: MaskRCNN + async_inference: True + use_throughput_mode: True -data: - data_format: coco_instances - test_subset: - batch_size: 2 +optimizer: + class_path: torch.optim.SGD + init_args: + lr: 0.01 -model: - otx_model: - _target_: otx.core.model.entity.instance_segmentation.OVInstanceSegmentationModel +scheduler: + class_path: lightning.pytorch.cli.ReduceLROnPlateau + init_args: + mode: min + factor: 0.1 + patience: 10 + monitor: train/loss + +engine: + task: INSTANCE_SEGMENTATION + device: auto + +callback_monitor: val/map_50 + +data: ../_base_/data/torchvision_base.yaml +overrides: + data: + task: INSTANCE_SEGMENTATION config: - model_name: /home/kprokofi/training_extensions/otx-workspace-INSTANCE_SEGMENTATION/outputs/20240109_072818_export/openvino/openvino.xml - model_type: MaskRCNN - async_inference: True - use_throughput_mode: True - num_classes: 80 + image_color_channel: BGR + data_format: coco_instances + test_subset: + batch_size: 2 diff --git a/src/otx/recipe/multiclass_classification/efficientnet_b0_light.yaml b/src/otx/recipe/multiclass_classification/efficientnet_b0_light.yaml deleted file mode 100644 index 1cd97ce193e..00000000000 --- a/src/otx/recipe/multiclass_classification/efficientnet_b0_light.yaml +++ /dev/null @@ -1,47 +0,0 @@ -# @package _global_ -defaults: - - override /base: classification - - override /callbacks: classification - - override /data: multiclass_mmpretrain - - override /model: multiclass_mmpretrain -data: - train_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - - backend: cv2 - scale: 224 - type: RandomResizedCrop - - type: PackInputs - val_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - - backend: cv2 - edge: short - scale: 256 - type: ResizeEdge - - crop_size: 224 - type: CenterCrop - - type: PackInputs - test_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - - backend: cv2 - scale: 224 - type: Resize - - type: PackInputs -model: - otx_model: - _target_: otx.algo.classification.efficientnet_b0.EfficientNetB0ForMulticlassCls - light: True - optimizer: - _target_: torch.optim.SGD - _partial_: true - lr: 0.0049 - momentum: 0.9 - weight_decay: 0.0001 - scheduler: - factor: 0.5 - patience: 1 diff --git a/src/otx/recipe/multiclass_classification/efficientnet_v2_light.yaml b/src/otx/recipe/multiclass_classification/efficientnet_v2_light.yaml deleted file mode 100644 index ece8bd4c3d0..00000000000 --- a/src/otx/recipe/multiclass_classification/efficientnet_v2_light.yaml +++ /dev/null @@ -1,50 +0,0 @@ -# @package _global_ -defaults: - - override /base: classification - - override /callbacks: classification - - override /data: multiclass_mmpretrain - - override /model: multiclass_mmpretrain -data: - train_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - - backend: cv2 - scale: 224 - type: RandomResizedCrop - - direction: horizontal - prob: 0.5 - type: RandomFlip - - type: PackInputs - val_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - - backend: cv2 - edge: short - scale: 256 - type: ResizeEdge - - crop_size: 224 - type: CenterCrop - - type: PackInputs - test_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - - backend: cv2 - scale: 224 - type: Resize - - type: PackInputs -model: - otx_model: - _target_: otx.algo.classification.efficientnet_v2.EfficientNetV2ForMulticlassCls - light: True - optimizer: - _target_: torch.optim.SGD - _partial_: true - lr: 0.0071 - momentum: 0.9 - weight_decay: 0.0001 - scheduler: - factor: 0.5 - patience: 1 diff --git a/src/otx/recipe/multiclass_classification/mobilenet_v3_large_light.yaml b/src/otx/recipe/multiclass_classification/mobilenet_v3_large_light.yaml deleted file mode 100644 index 84b67c7779b..00000000000 --- a/src/otx/recipe/multiclass_classification/mobilenet_v3_large_light.yaml +++ /dev/null @@ -1,50 +0,0 @@ -# @package _global_ -defaults: - - override /base: classification - - override /callbacks: classification - - override /data: multiclass_mmpretrain - - override /model: multiclass_mmpretrain -data: - train_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - - backend: cv2 - scale: 224 - type: RandomResizedCrop - - direction: horizontal - prob: 0.5 - type: RandomFlip - - type: PackInputs - val_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - - backend: cv2 - edge: short - scale: 256 - type: ResizeEdge - - crop_size: 224 - type: CenterCrop - - type: PackInputs - test_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - - backend: cv2 - scale: 224 - type: Resize - - type: PackInputs -model: - otx_model: - _target_: otx.algo.classification.mobilenet_v3_large.MobileNetV3ForMulticlassCls - light: True - optimizer: - _target_: torch.optim.SGD - _partial_: true - lr: 0.0058 - momentum: 0.9 - weight_decay: 0.0001 - scheduler: - factor: 0.5 - patience: 1 diff --git a/src/otx/recipe/multiclass_classification/openvino_model.yaml b/src/otx/recipe/multiclass_classification/openvino_model.yaml deleted file mode 100644 index ea0d922772f..00000000000 --- a/src/otx/recipe/multiclass_classification/openvino_model.yaml +++ /dev/null @@ -1,23 +0,0 @@ -# @package _global_ -defaults: - - override /base: classification - - override /callbacks: classification - - override /data: openvino - - override /model: torch_classification - -data: - data_format: imagenet_with_subset_dirs - test_subset: - batch_size: 128 - -model: - otx_model: - _target_: otx.core.model.entity.classification.OVMulticlassClassificationModel - config: - model_name: efficientnet-b0-pytorch - async_inference: True - use_throughput_mode: False - model_type: Classification - head: - num_classes: 1000 - num_classes: 1000 diff --git a/src/otx/recipe/multiclass_classification/otx_dino_v2.yaml b/src/otx/recipe/multiclass_classification/otx_dino_v2.yaml deleted file mode 100644 index 991606423d7..00000000000 --- a/src/otx/recipe/multiclass_classification/otx_dino_v2.yaml +++ /dev/null @@ -1,83 +0,0 @@ -# @package _global_ -defaults: - - override /base: classification - - override /callbacks: classification - - override /data: multiclass_mmpretrain - - override /model: torch_classification -data: - train_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - to_float32: true - - mean: - - 123.675 - - 116.28 - - 103.53 - std: - - 58.395 - - 57.12 - - 57.375 - to_rgb: true - type: Normalize - - backend: cv2 - scale: 224 - type: RandomResizedCrop - - type: PackInputs - val_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - to_float32: true - - mean: - - 123.675 - - 116.28 - - 103.53 - std: - - 58.395 - - 57.12 - - 57.375 - to_rgb: true - type: Normalize - - backend: cv2 - edge: short - scale: 256 - type: ResizeEdge - - crop_size: 224 - type: CenterCrop - - type: PackInputs - test_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - to_float32: true - - mean: - - 123.675 - - 116.28 - - 103.53 - std: - - 58.395 - - 57.12 - - 57.375 - to_rgb: true - type: Normalize - - backend: cv2 - edge: short - scale: 256 - type: ResizeEdge - - crop_size: 224 - type: CenterCrop - - type: PackInputs -model: - otx_model: - _target_: otx.algo.classification.otx_dino_v2.DINOv2RegisterClassifier - config: - backbone: - name: dinov2_vits14_reg - frozen: false - head: - in_channels: 384 - num_classes: 1000 - optimizer: - _target_: torch.optim.AdamW - lr: 1e-5 diff --git a/src/otx/recipe/multiclass_classification/otx_dino_v2_linear_probe.yaml b/src/otx/recipe/multiclass_classification/otx_dino_v2_linear_probe.yaml deleted file mode 100644 index 29ee69cd310..00000000000 --- a/src/otx/recipe/multiclass_classification/otx_dino_v2_linear_probe.yaml +++ /dev/null @@ -1,89 +0,0 @@ -# @package _global_ -defaults: - - override /base: classification - - override /callbacks: classification - - override /data: multiclass_mmpretrain - - override /model: torch_classification -data: - train_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - to_float32: true - - mean: - - 123.675 - - 116.28 - - 103.53 - std: - - 58.395 - - 57.12 - - 57.375 - to_rgb: true - type: Normalize - - backend: cv2 - scale: 224 - type: RandomResizedCrop - - type: PackInputs - val_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - to_float32: true - - mean: - - 123.675 - - 116.28 - - 103.53 - std: - - 58.395 - - 57.12 - - 57.375 - to_rgb: true - type: Normalize - - backend: cv2 - edge: short - scale: 256 - type: ResizeEdge - - crop_size: 224 - type: CenterCrop - - type: PackInputs - test_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - to_float32: true - - mean: - - 123.675 - - 116.28 - - 103.53 - std: - - 58.395 - - 57.12 - - 57.375 - to_rgb: true - type: Normalize - - backend: cv2 - edge: short - scale: 256 - type: ResizeEdge - - crop_size: 224 - type: CenterCrop - - type: PackInputs -model: - otx_model: - _target_: otx.algo.classification.otx_dino_v2.DINOv2RegisterClassifier - config: - backbone: - name: dinov2_vits14_reg - frozen: true - head: - in_channels: 384 - num_classes: 1000 - optimizer: - _target_: torch.optim.SGD - _partial_: true - lr: 0.007 - momentum: 0.9 - weight_decay: 0.0001 - scheduler: - factor: 0.5 - patience: 1 diff --git a/src/otx/recipe/multiclass_classification/otx_efficientnet_b0.yaml b/src/otx/recipe/multiclass_classification/otx_efficientnet_b0.yaml deleted file mode 100644 index f2f6829a425..00000000000 --- a/src/otx/recipe/multiclass_classification/otx_efficientnet_b0.yaml +++ /dev/null @@ -1,47 +0,0 @@ -# @package _global_ -defaults: - - override /base: classification - - override /callbacks: classification - - override /data: multiclass_mmpretrain - - override /model: multiclass_mmpretrain -data: - train_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - - backend: cv2 - scale: 224 - type: RandomResizedCrop - - type: PackInputs - val_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - - backend: cv2 - edge: short - scale: 256 - type: ResizeEdge - - crop_size: 224 - type: CenterCrop - - type: PackInputs - test_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - - backend: cv2 - scale: 224 - type: Resize - - type: PackInputs -model: - otx_model: - _target_: otx.algo.classification.efficientnet_b0.EfficientNetB0ForMulticlassCls - light: false - optimizer: - _target_: torch.optim.SGD - _partial_: true - lr: 0.0049 - momentum: 0.9 - weight_decay: 0.0001 - scheduler: - factor: 0.5 - patience: 1 diff --git a/src/otx/recipe/multiclass_classification/otx_efficientnet_v2.yaml b/src/otx/recipe/multiclass_classification/otx_efficientnet_v2.yaml deleted file mode 100644 index 2337f657d7f..00000000000 --- a/src/otx/recipe/multiclass_classification/otx_efficientnet_v2.yaml +++ /dev/null @@ -1,50 +0,0 @@ -# @package _global_ -defaults: - - override /base: classification - - override /callbacks: classification - - override /data: multiclass_mmpretrain - - override /model: multiclass_mmpretrain -data: - train_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - - backend: cv2 - scale: 224 - type: RandomResizedCrop - - direction: horizontal - prob: 0.5 - type: RandomFlip - - type: PackInputs - val_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - - backend: cv2 - edge: short - scale: 256 - type: ResizeEdge - - crop_size: 224 - type: CenterCrop - - type: PackInputs - test_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - - backend: cv2 - scale: 224 - type: Resize - - type: PackInputs -model: - otx_model: - _target_: otx.algo.classification.efficientnet_v2.EfficientNetV2ForMulticlassCls - light: false - optimizer: - _target_: torch.optim.SGD - _partial_: true - lr: 0.0071 - momentum: 0.9 - weight_decay: 0.0001 - scheduler: - factor: 0.5 - patience: 1 diff --git a/src/otx/recipe/multiclass_classification/otx_mobilenet_v3_large.yaml b/src/otx/recipe/multiclass_classification/otx_mobilenet_v3_large.yaml deleted file mode 100644 index 854ec629189..00000000000 --- a/src/otx/recipe/multiclass_classification/otx_mobilenet_v3_large.yaml +++ /dev/null @@ -1,50 +0,0 @@ -# @package _global_ -defaults: - - override /base: classification - - override /callbacks: classification - - override /data: multiclass_mmpretrain - - override /model: multiclass_mmpretrain -data: - train_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - - backend: cv2 - scale: 224 - type: RandomResizedCrop - - direction: horizontal - prob: 0.5 - type: RandomFlip - - type: PackInputs - val_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - - backend: cv2 - edge: short - scale: 256 - type: ResizeEdge - - crop_size: 224 - type: CenterCrop - - type: PackInputs - test_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - - backend: cv2 - scale: 224 - type: Resize - - type: PackInputs -model: - otx_model: - _target_: otx.algo.classification.mobilenet_v3_large.MobileNetV3ForMulticlassCls - light: false - optimizer: - _target_: torch.optim.SGD - _partial_: true - lr: 0.0058 - momentum: 0.9 - weight_decay: 0.0001 - scheduler: - factor: 0.5 - patience: 1 diff --git a/src/otx/recipe/multilabel_classification/efficientnet_b0_light.yaml b/src/otx/recipe/multilabel_classification/efficientnet_b0_light.yaml deleted file mode 100644 index 107a3db5c1f..00000000000 --- a/src/otx/recipe/multilabel_classification/efficientnet_b0_light.yaml +++ /dev/null @@ -1,40 +0,0 @@ -# @package _global_ -defaults: - - override /base: multilabel_classification - - override /callbacks: multilabel_classification - - override /data: multilabel_mmpretrain - - override /model: multilabel_mmpretrain -data: - train_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - - backend: cv2 - scale: 224 - type: Resize - - type: PackInputs - val_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - - backend: cv2 - scale: 224 - type: Resize - - type: PackInputs - test_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - - backend: cv2 - scale: 224 - type: Resize - - type: PackInputs -model: - otx_model: - _target_: otx.algo.classification.efficientnet_b0.EfficientNetB0ForMultilabelCls - optimizer: - _target_: torch.optim.SGD - lr: 0.0049 - scheduler: - factor: 0.5 - patience: 1 diff --git a/src/otx/recipe/multilabel_classification/efficientnet_v2_light.yaml b/src/otx/recipe/multilabel_classification/efficientnet_v2_light.yaml deleted file mode 100644 index d629cd3126a..00000000000 --- a/src/otx/recipe/multilabel_classification/efficientnet_v2_light.yaml +++ /dev/null @@ -1,46 +0,0 @@ -# @package _global_ -defaults: - - override /base: multilabel_classification - - override /callbacks: multilabel_classification - - override /data: multilabel_mmpretrain - - override /model: multilabel_mmpretrain -data: - train_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - - backend: cv2 - scale: 224 - type: Resize - - direction: horizontal - prob: 0.5 - type: RandomFlip - - type: PackInputs - val_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - - backend: cv2 - scale: 224 - type: Resize - - type: PackInputs - test_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - - backend: cv2 - scale: 224 - type: Resize - - type: PackInputs -model: - otx_model: - _target_: otx.algo.classification.efficientnet_v2.EfficientNetV2ForMultilabelCls - optimizer: - _target_: torch.optim.SGD - _partial_: true - lr: 0.0071 - momentum: 0.9 - weight_decay: 0.0001 - scheduler: - factor: 0.5 - patience: 1 diff --git a/src/otx/recipe/multilabel_classification/mobilenet_v3_large_light.yaml b/src/otx/recipe/multilabel_classification/mobilenet_v3_large_light.yaml deleted file mode 100644 index 997bbc53796..00000000000 --- a/src/otx/recipe/multilabel_classification/mobilenet_v3_large_light.yaml +++ /dev/null @@ -1,46 +0,0 @@ -# @package _global_ -defaults: - - override /base: multilabel_classification - - override /callbacks: multilabel_classification - - override /data: multilabel_mmpretrain - - override /model: multilabel_mmpretrain -data: - train_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - - backend: cv2 - scale: 224 - type: Resize - - direction: horizontal - prob: 0.5 - type: RandomFlip - - type: PackInputs - val_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - - backend: cv2 - scale: 224 - type: Resize - - type: PackInputs - test_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - - backend: cv2 - scale: 224 - type: Resize - - type: PackInputs -model: - otx_model: - _target_: otx.algo.classification.mobilenet_v3_large.MobileNetV3ForMultilabelCls - optimizer: - _target_: torch.optim.SGD - _partial_: true - lr: 0.0058 - momentum: 0.9 - weight_decay: 0.0001 - scheduler: - factor: 0.5 - patience: 1 diff --git a/src/otx/recipe/multilabel_classification/otx_deit_tiny.yaml b/src/otx/recipe/multilabel_classification/otx_deit_tiny.yaml deleted file mode 100644 index fe870c40d05..00000000000 --- a/src/otx/recipe/multilabel_classification/otx_deit_tiny.yaml +++ /dev/null @@ -1,43 +0,0 @@ -# @package _global_ -defaults: - - override /base: multilabel_classification - - override /callbacks: multilabel_classification - - override /data: multilabel_mmpretrain - - override /model: multilabel_mmpretrain -data: - train_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - - backend: cv2 - scale: 224 - type: Resize - - type: PackInputs - val_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - - backend: cv2 - scale: 224 - type: Resize - - type: PackInputs - test_subset: - batch_size: 64 - transforms: - - type: LoadImageFromFile - - backend: cv2 - scale: 224 - type: Resize - - type: PackInputs -model: - otx_model: - _target_: otx.algo.classification.deit_tiny.DeitTinyForMultilabelCls - optimizer: - _target_: torch.optim.SGD - _partial_: true - lr: 0.0001 - momentum: 0.9 - weight_decay: 0.0001 - scheduler: - factor: 0.5 - patience: 1 diff --git a/src/otx/recipe/segmentation/__init__.py b/src/otx/recipe/segmentation/__init__.py deleted file mode 100644 index 7e0c554c4c5..00000000000 --- a/src/otx/recipe/segmentation/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright (C) 2023 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 -# -"""YAML file recipes for the segmentation models OTX provides.""" diff --git a/src/otx/recipe/segmentation/dino_v2_seg.yaml b/src/otx/recipe/segmentation/dino_v2_seg.yaml deleted file mode 100644 index de024e1a678..00000000000 --- a/src/otx/recipe/segmentation/dino_v2_seg.yaml +++ /dev/null @@ -1,67 +0,0 @@ -# @package _global_ -defaults: - - override /base: segmentation - - override /callbacks: segmentation - - override /data: segmentation - - override /model: mmseg -data: - train_subset: - batch_size: 8 - transforms: - - type: LoadImageFromFile - - reduce_zero_label: true - type: LoadAnnotations - - keep_ratio: false - ratio_range: - - 0.5 - - 2.0 - scale: - - 640 - - 640 - type: RandomResize - - cat_max_ratio: 0.75 - crop_size: - - 560 - - 560 - type: RandomCrop - - prob: 0.5 - type: RandomFlip - - type: PhotoMetricDistortion - - type: PackSegInputs - val_subset: - batch_size: 1 - transforms: - - type: LoadImageFromFile - - keep_ratio: false - scale: - - 560 - - 560 - type: Resize - - reduce_zero_label: true - type: LoadAnnotations - - type: PackSegInputs - test_subset: - batch_size: 1 - transforms: - - type: LoadImageFromFile - - keep_ratio: false - scale: - - 560 - - 560 - type: Resize - - reduce_zero_label: true - type: LoadAnnotations - - type: PackSegInputs -model: - otx_model: - _target_: otx.algo.segmentation.dino_v2_seg.DinoV2Seg - optimizer: - _target_: torch.optim.AdamW - _partial_: true - lr: 0.001 - betas: [0.9, 0.999] - weight_decay: 0.0001 - scheduler: - total_iters: 100 - power: 0.9 - last_epoch: -1 diff --git a/src/otx/recipe/segmentation/litehrnet_18.yaml b/src/otx/recipe/segmentation/litehrnet_18.yaml deleted file mode 100644 index 16222ab17d5..00000000000 --- a/src/otx/recipe/segmentation/litehrnet_18.yaml +++ /dev/null @@ -1,70 +0,0 @@ -# @package _global_ -defaults: - - override /base: segmentation - - override /callbacks: segmentation - - override /data: segmentation - - override /model: mmseg -data: - train_subset: - batch_size: 8 - transforms: - - type: LoadImageFromFile - - reduce_zero_label: true - type: LoadAnnotations - - keep_ratio: false - ratio_range: - - 0.5 - - 2.0 - scale: - - 544 - - 544 - type: RandomResize - - cat_max_ratio: 0.75 - crop_size: - - 512 - - 512 - type: RandomCrop - - prob: 0.5 - type: RandomFlip - - type: PhotoMetricDistortion - - type: PackSegInputs - val_subset: - batch_size: 1 - transforms: - - type: LoadImageFromFile - - keep_ratio: false - scale: - - 544 - - 544 - type: Resize - - reduce_zero_label: true - type: LoadAnnotations - - type: PackSegInputs - test_subset: - batch_size: 1 - transforms: - - type: LoadImageFromFile - - keep_ratio: false - scale: - - 544 - - 544 - type: Resize - - reduce_zero_label: true - type: LoadAnnotations - - type: PackSegInputs -model: - otx_model: - _target_: otx.algo.segmentation.litehrnet.LiteHRNet - variant: 18 - optimizer: - _target_: torch.optim.Adam - _partial_: true - lr: 0.001 - betas: [0.9, 0.999] - weight_decay: 0.0 - scheduler: - _target_: torch.optim.lr_scheduler.ReduceLROnPlateau - _partial_: true - mode: min - factor: 0.1 - patience: 10 diff --git a/src/otx/recipe/segmentation/litehrnet_x.yaml b/src/otx/recipe/segmentation/litehrnet_x.yaml deleted file mode 100644 index 533697b5bfb..00000000000 --- a/src/otx/recipe/segmentation/litehrnet_x.yaml +++ /dev/null @@ -1,70 +0,0 @@ -# @package _global_ -defaults: - - override /base: segmentation - - override /callbacks: segmentation - - override /data: segmentation - - override /model: mmseg -data: - train_subset: - batch_size: 8 - transforms: - - type: LoadImageFromFile - - reduce_zero_label: true - type: LoadAnnotations - - keep_ratio: false - ratio_range: - - 0.5 - - 2.0 - scale: - - 544 - - 544 - type: RandomResize - - cat_max_ratio: 0.75 - crop_size: - - 512 - - 512 - type: RandomCrop - - prob: 0.5 - type: RandomFlip - - type: PhotoMetricDistortion - - type: PackSegInputs - val_subset: - batch_size: 1 - transforms: - - type: LoadImageFromFile - - keep_ratio: false - scale: - - 544 - - 544 - type: Resize - - reduce_zero_label: true - type: LoadAnnotations - - type: PackSegInputs - test_subset: - batch_size: 1 - transforms: - - type: LoadImageFromFile - - keep_ratio: false - scale: - - 544 - - 544 - type: Resize - - reduce_zero_label: true - type: LoadAnnotations - - type: PackSegInputs -model: - otx_model: - _target_: otx.algo.segmentation.litehrnet.LiteHRNet - variant: x - optimizer: - _target_: torch.optim.Adam - _partial_: true - lr: 0.001 - betas: [0.9, 0.999] - weight_decay: 0.0 - scheduler: - _target_: torch.optim.lr_scheduler.ReduceLROnPlateau - _partial_: true - mode: min - factor: 0.1 - patience: 10 diff --git a/src/otx/recipe/segmentation/openvino_model.yaml b/src/otx/recipe/segmentation/openvino_model.yaml deleted file mode 100644 index 7751abfdaca..00000000000 --- a/src/otx/recipe/segmentation/openvino_model.yaml +++ /dev/null @@ -1,23 +0,0 @@ -# @package _global_ -defaults: - - override /base: segmentation - - override /callbacks: segmentation - - override /data: openvino - - override /model: mmseg - -data: - data_format: common_semantic_segmentation_with_subset_dirs - test_subset: - batch_size: 64 - -model: - otx_model: - _target_: otx.core.model.entity.segmentation.OVSegmentationModel - config: - model_name: drn-d-38 - async_inference: True - use_throughput_mode: True - model_type: "Segmentation" - decode_head: - num_classes: 19 - num_classes: 19 diff --git a/src/otx/recipe/segmentation/segnext_b.yaml b/src/otx/recipe/segmentation/segnext_b.yaml deleted file mode 100644 index 5d2168bc44f..00000000000 --- a/src/otx/recipe/segmentation/segnext_b.yaml +++ /dev/null @@ -1,62 +0,0 @@ -# @package _global_ -defaults: - - override /base: segmentation - - override /callbacks: segmentation - - override /data: segmentation - - override /model: mmseg -data: - train_subset: - batch_size: 8 - transforms: - - type: LoadImageFromFile - - reduce_zero_label: true - type: LoadAnnotations - - keep_ratio: true - ratio_range: - - 0.5 - - 2.0 - scale: - - 544 - - 544 - type: RandomResize - - cat_max_ratio: 0.75 - crop_size: - - 512 - - 512 - type: RandomCrop - - prob: 0.5 - type: RandomFlip - - type: PhotoMetricDistortion - - type: PackSegInputs - val_subset: - batch_size: 1 - transforms: - - type: LoadImageFromFile - - keep_ratio: true - scale: - - 544 - - 544 - type: Resize - - reduce_zero_label: true - type: LoadAnnotations - - type: PackSegInputs - test_subset: - batch_size: 1 - transforms: - - type: LoadImageFromFile - - keep_ratio: true - scale: - - 544 - - 544 - type: Resize - - reduce_zero_label: true - type: LoadAnnotations - - type: PackSegInputs -model: - otx_model: - _target_: otx.algo.segmentation.segnext.SegNext - variant: b - scheduler: - total_iters: 100 - power: 0.9 - last_epoch: -1 diff --git a/src/otx/recipe/segmentation/segnext_s.yaml b/src/otx/recipe/segmentation/segnext_s.yaml deleted file mode 100644 index 08d75b5947a..00000000000 --- a/src/otx/recipe/segmentation/segnext_s.yaml +++ /dev/null @@ -1,62 +0,0 @@ -# @package _global_ -defaults: - - override /base: segmentation - - override /callbacks: segmentation - - override /data: segmentation - - override /model: mmseg -data: - train_subset: - batch_size: 8 - transforms: - - type: LoadImageFromFile - - reduce_zero_label: true - type: LoadAnnotations - - keep_ratio: true - ratio_range: - - 0.5 - - 2.0 - scale: - - 544 - - 544 - type: RandomResize - - cat_max_ratio: 0.75 - crop_size: - - 512 - - 512 - type: RandomCrop - - prob: 0.5 - type: RandomFlip - - type: PhotoMetricDistortion - - type: PackSegInputs - val_subset: - batch_size: 1 - transforms: - - type: LoadImageFromFile - - keep_ratio: true - scale: - - 544 - - 544 - type: Resize - - reduce_zero_label: true - type: LoadAnnotations - - type: PackSegInputs - test_subset: - batch_size: 1 - transforms: - - type: LoadImageFromFile - - keep_ratio: true - scale: - - 544 - - 544 - type: Resize - - reduce_zero_label: true - type: LoadAnnotations - - type: PackSegInputs -model: - otx_model: - _target_: otx.algo.segmentation.segnext.SegNext - variant: s - scheduler: - total_iters: 100 - power: 0.9 - last_epoch: -1 diff --git a/src/otx/recipe/segmentation/segnext_t.yaml b/src/otx/recipe/segmentation/segnext_t.yaml deleted file mode 100644 index 3767fdd3495..00000000000 --- a/src/otx/recipe/segmentation/segnext_t.yaml +++ /dev/null @@ -1,62 +0,0 @@ -# @package _global_ -defaults: - - override /base: segmentation - - override /callbacks: segmentation - - override /data: segmentation - - override /model: mmseg -data: - train_subset: - batch_size: 8 - transforms: - - type: LoadImageFromFile - - reduce_zero_label: true - type: LoadAnnotations - - keep_ratio: true - ratio_range: - - 0.5 - - 2.0 - scale: - - 544 - - 544 - type: RandomResize - - cat_max_ratio: 0.75 - crop_size: - - 512 - - 512 - type: RandomCrop - - prob: 0.5 - type: RandomFlip - - type: PhotoMetricDistortion - - type: PackSegInputs - val_subset: - batch_size: 1 - transforms: - - type: LoadImageFromFile - - keep_ratio: true - scale: - - 544 - - 544 - type: Resize - - reduce_zero_label: true - type: LoadAnnotations - - type: PackSegInputs - test_subset: - batch_size: 1 - transforms: - - type: LoadImageFromFile - - keep_ratio: true - scale: - - 544 - - 544 - type: Resize - - reduce_zero_label: true - type: LoadAnnotations - - type: PackSegInputs -model: - otx_model: - _target_: otx.algo.segmentation.segnext.SegNext - variant: t - scheduler: - total_iters: 100 - power: 0.9 - last_epoch: -1 diff --git a/src/otx/recipe/semantic_segmentation/dino_v2.yaml b/src/otx/recipe/semantic_segmentation/dino_v2.yaml new file mode 100644 index 00000000000..0941d47edc6 --- /dev/null +++ b/src/otx/recipe/semantic_segmentation/dino_v2.yaml @@ -0,0 +1,75 @@ +model: + class_path: otx.algo.segmentation.dino_v2_seg.DinoV2Seg + init_args: + num_classes: 2 + +optimizer: + class_path: torch.optim.AdamW + init_args: + lr: 0.001 + betas: + - 0.9 + - 0.999 + weight_decay: 0.0001 + +scheduler: + class_path: torch.optim.lr_scheduler.PolynomialLR + init_args: + total_iters: 100 + power: 0.9 + last_epoch: -1 + +engine: + task: SEMANTIC_SEGMENTATION + device: auto + +callback_monitor: val/mIoU + +data: ../_base_/data/mmseg_base.yaml +overrides: + data: + config: + train_subset: + transforms: + - type: LoadImageFromFile + - reduce_zero_label: true + type: LoadAnnotations + - keep_ratio: false + ratio_range: + - 0.5 + - 2.0 + scale: + - 640 + - 640 + type: RandomResize + - cat_max_ratio: 0.75 + crop_size: + - 560 + - 560 + type: RandomCrop + - prob: 0.5 + type: RandomFlip + - type: PhotoMetricDistortion + - type: PackSegInputs + val_subset: + transforms: + - type: LoadImageFromFile + - keep_ratio: false + scale: + - 560 + - 560 + type: Resize + - reduce_zero_label: true + type: LoadAnnotations + - type: PackSegInputs + test_subset: + transforms: + - type: LoadImageFromFile + - keep_ratio: false + scale: + - 560 + - 560 + type: Resize + - reduce_zero_label: true + type: LoadAnnotations + - type: PackSegInputs diff --git a/src/otx/recipe/semantic_segmentation/litehrnet_18.yaml b/src/otx/recipe/semantic_segmentation/litehrnet_18.yaml new file mode 100644 index 00000000000..426a96e5d5f --- /dev/null +++ b/src/otx/recipe/semantic_segmentation/litehrnet_18.yaml @@ -0,0 +1,30 @@ +model: + class_path: otx.algo.segmentation.litehrnet.LiteHRNet + init_args: + num_classes: 2 + variant: 18 + +optimizer: + class_path: torch.optim.Adam + init_args: + lr: 0.001 + betas: + - 0.9 + - 0.999 + weight_decay: 0.0 + +scheduler: + class_path: lightning.pytorch.cli.ReduceLROnPlateau + init_args: + mode: min + factor: 0.1 + patience: 10 + monitor: train/loss + +engine: + task: SEMANTIC_SEGMENTATION + device: auto + +callback_monitor: val/mIoU + +data: ../_base_/data/mmseg_base.yaml diff --git a/src/otx/recipe/semantic_segmentation/litehrnet_s.yaml b/src/otx/recipe/semantic_segmentation/litehrnet_s.yaml new file mode 100644 index 00000000000..2435d191483 --- /dev/null +++ b/src/otx/recipe/semantic_segmentation/litehrnet_s.yaml @@ -0,0 +1,30 @@ +model: + class_path: otx.algo.segmentation.litehrnet.LiteHRNet + init_args: + num_classes: 2 + variant: s + +optimizer: + class_path: torch.optim.Adam + init_args: + lr: 0.001 + betas: + - 0.9 + - 0.999 + weight_decay: 0.0 + +scheduler: + class_path: lightning.pytorch.cli.ReduceLROnPlateau + init_args: + mode: min + factor: 0.1 + patience: 10 + monitor: train/loss + +engine: + task: SEMANTIC_SEGMENTATION + device: auto + +callback_monitor: val/mIoU + +data: ../_base_/data/mmseg_base.yaml diff --git a/src/otx/recipe/semantic_segmentation/litehrnet_x.yaml b/src/otx/recipe/semantic_segmentation/litehrnet_x.yaml new file mode 100644 index 00000000000..0337fa2b4f6 --- /dev/null +++ b/src/otx/recipe/semantic_segmentation/litehrnet_x.yaml @@ -0,0 +1,30 @@ +model: + class_path: otx.algo.segmentation.litehrnet.LiteHRNet + init_args: + num_classes: 2 + variant: x + +optimizer: + class_path: torch.optim.Adam + init_args: + lr: 0.001 + betas: + - 0.9 + - 0.999 + weight_decay: 0.0 + +scheduler: + class_path: lightning.pytorch.cli.ReduceLROnPlateau + init_args: + mode: min + factor: 0.1 + patience: 10 + monitor: train/loss + +engine: + task: SEMANTIC_SEGMENTATION + device: auto + +callback_monitor: val/mIoU + +data: ../_base_/data/mmseg_base.yaml diff --git a/src/otx/recipe/semantic_segmentation/openvino_model.yaml b/src/otx/recipe/semantic_segmentation/openvino_model.yaml new file mode 100644 index 00000000000..b3f01cac96b --- /dev/null +++ b/src/otx/recipe/semantic_segmentation/openvino_model.yaml @@ -0,0 +1,39 @@ +model: + class_path: otx.core.model.entity.segmentation.OVSegmentationModel + init_args: + num_classes: 19 + config: + class_path: omegaconf.dictconfig.DictConfig + init_args: + content: + model_name: drn-d-38 + decode_head: + num_classes: 19 + async_inference: True + use_throughput_mode: True + model_type: "Segmentation" + +optimizer: + class_path: torch.optim.Adam + init_args: + lr: 1e-3 + weight_decay: 0.0 + +scheduler: + class_path: torch.optim.lr_scheduler.PolynomialLR + +engine: + task: SEMANTIC_SEGMENTATION + device: auto + +callback_monitor: val/mIoU + +data: ../_base_/data/torchvision_base.yaml +overrides: + data: + task: SEMANTIC_SEGMENTATION + config: + image_color_channel: BGR + data_format: common_semantic_segmentation_with_subset_dirs + test_subset: + batch_size: 64 diff --git a/src/otx/recipe/semantic_segmentation/segnext_b.yaml b/src/otx/recipe/semantic_segmentation/segnext_b.yaml new file mode 100644 index 00000000000..a0e43dbdede --- /dev/null +++ b/src/otx/recipe/semantic_segmentation/segnext_b.yaml @@ -0,0 +1,76 @@ +model: + class_path: otx.algo.segmentation.segnext.SegNext + init_args: + num_classes: 2 + variant: b + +optimizer: + class_path: torch.optim.AdamW + init_args: + lr: 0.00006 + betas: + - 0.9 + - 0.999 + weight_decay: 0.01 + +scheduler: + class_path: torch.optim.lr_scheduler.PolynomialLR + init_args: + total_iters: 100 + power: 0.9 + last_epoch: -1 + +engine: + task: SEMANTIC_SEGMENTATION + device: auto + +callback_monitor: val/mIoU + +data: ../_base_/data/mmseg_base.yaml +overrides: + data: + config: + train_subset: + transforms: + - type: LoadImageFromFile + - reduce_zero_label: true + type: LoadAnnotations + - keep_ratio: true + ratio_range: + - 0.5 + - 2.0 + scale: + - 544 + - 544 + type: RandomResize + - cat_max_ratio: 0.75 + crop_size: + - 512 + - 512 + type: RandomCrop + - prob: 0.5 + type: RandomFlip + - type: PhotoMetricDistortion + - type: PackSegInputs + val_subset: + transforms: + - type: LoadImageFromFile + - keep_ratio: true + scale: + - 544 + - 544 + type: Resize + - reduce_zero_label: true + type: LoadAnnotations + - type: PackSegInputs + test_subset: + transforms: + - type: LoadImageFromFile + - keep_ratio: true + scale: + - 544 + - 544 + type: Resize + - reduce_zero_label: true + type: LoadAnnotations + - type: PackSegInputs diff --git a/src/otx/recipe/semantic_segmentation/segnext_s.yaml b/src/otx/recipe/semantic_segmentation/segnext_s.yaml new file mode 100644 index 00000000000..7d011991715 --- /dev/null +++ b/src/otx/recipe/semantic_segmentation/segnext_s.yaml @@ -0,0 +1,76 @@ +model: + class_path: otx.algo.segmentation.segnext.SegNext + init_args: + num_classes: 2 + variant: s + +optimizer: + class_path: torch.optim.AdamW + init_args: + lr: 0.00006 + betas: + - 0.9 + - 0.999 + weight_decay: 0.01 + +scheduler: + class_path: torch.optim.lr_scheduler.PolynomialLR + init_args: + total_iters: 100 + power: 0.9 + last_epoch: -1 + +engine: + task: SEMANTIC_SEGMENTATION + device: auto + +callback_monitor: val/mIoU + +data: ../_base_/data/mmseg_base.yaml +overrides: + data: + config: + train_subset: + transforms: + - type: LoadImageFromFile + - reduce_zero_label: true + type: LoadAnnotations + - keep_ratio: true + ratio_range: + - 0.5 + - 2.0 + scale: + - 544 + - 544 + type: RandomResize + - cat_max_ratio: 0.75 + crop_size: + - 512 + - 512 + type: RandomCrop + - prob: 0.5 + type: RandomFlip + - type: PhotoMetricDistortion + - type: PackSegInputs + val_subset: + transforms: + - type: LoadImageFromFile + - keep_ratio: true + scale: + - 544 + - 544 + type: Resize + - reduce_zero_label: true + type: LoadAnnotations + - type: PackSegInputs + test_subset: + transforms: + - type: LoadImageFromFile + - keep_ratio: true + scale: + - 544 + - 544 + type: Resize + - reduce_zero_label: true + type: LoadAnnotations + - type: PackSegInputs diff --git a/src/otx/recipe/semantic_segmentation/segnext_t.yaml b/src/otx/recipe/semantic_segmentation/segnext_t.yaml new file mode 100644 index 00000000000..3d3b79ab6d4 --- /dev/null +++ b/src/otx/recipe/semantic_segmentation/segnext_t.yaml @@ -0,0 +1,76 @@ +model: + class_path: otx.algo.segmentation.segnext.SegNext + init_args: + num_classes: 2 + variant: t + +optimizer: + class_path: torch.optim.AdamW + init_args: + lr: 0.00006 + betas: + - 0.9 + - 0.999 + weight_decay: 0.01 + +scheduler: + class_path: torch.optim.lr_scheduler.PolynomialLR + init_args: + total_iters: 100 + power: 0.9 + last_epoch: -1 + +engine: + task: SEMANTIC_SEGMENTATION + device: auto + +callback_monitor: val/mIoU + +data: ../_base_/data/mmseg_base.yaml +overrides: + data: + config: + train_subset: + transforms: + - type: LoadImageFromFile + - reduce_zero_label: true + type: LoadAnnotations + - keep_ratio: true + ratio_range: + - 0.5 + - 2.0 + scale: + - 544 + - 544 + type: RandomResize + - cat_max_ratio: 0.75 + crop_size: + - 512 + - 512 + type: RandomCrop + - prob: 0.5 + type: RandomFlip + - type: PhotoMetricDistortion + - type: PackSegInputs + val_subset: + transforms: + - type: LoadImageFromFile + - keep_ratio: true + scale: + - 544 + - 544 + type: Resize + - reduce_zero_label: true + type: LoadAnnotations + - type: PackSegInputs + test_subset: + transforms: + - type: LoadImageFromFile + - keep_ratio: true + scale: + - 544 + - 544 + type: Resize + - reduce_zero_label: true + type: LoadAnnotations + - type: PackSegInputs diff --git a/src/otx/recipe/visual_prompting/sam_tiny_vit.yaml b/src/otx/recipe/visual_prompting/sam_tiny_vit.yaml index 9ee25af7e44..2be13a45dee 100644 --- a/src/otx/recipe/visual_prompting/sam_tiny_vit.yaml +++ b/src/otx/recipe/visual_prompting/sam_tiny_vit.yaml @@ -1,33 +1,87 @@ -# @package _global_ -defaults: - - override /base: visual_prompting - - override /callbacks: visual_prompting - # - override /data: mmdet_visual_prompting - - override /data: torchvision_visual_prompting - - override /model: torch_visual_prompting -data: - train_subset: - batch_size: 2 - val_subset: - batch_size: 1 - test_subset: - batch_size: 1 model: - otx_model: - _target_: otx.algo.visual_prompting.segment_anything.OTXSegmentAnything + class_path: otx.algo.visual_prompting.segment_anything.OTXSegmentAnything + init_args: backbone: tiny_vit - num_classes: 0 # to avoid MissingMandatoryValue error + num_classes: 0 freeze_image_encoder: true freeze_prompt_encoder: true freeze_mask_decoder: false - optimizer: - _target_: torch.optim.Adam - _partial_: true + +optimizer: + class_path: torch.optim.Adam + init_args: lr: 0.00001 - scheduler: - _target_: torch.optim.lr_scheduler.ConstantLR - _partial_: true + +scheduler: + class_path: torch.optim.lr_scheduler.ConstantLR + init_args: factor: 1 total_iters: -1 -trainer: + +engine: + task: VISUAL_PROMPTING + device: auto + +callback_monitor: val/Dice + +data: ../_base_/data/torchvision_base.yaml +overrides: max_epochs: 100 + data: + task: VISUAL_PROMPTING + config: + data_format: coco_instances + include_polygons: false + train_subset: + batch_size: 2 + num_workers: 0 + transforms: + # - _target_: otx.core.data.transform_libs.torchvision.PerturbBoundingBoxes + # offset: 20 + - class_path: torchvision.transforms.v2.Resize + init_args: + size: 1023 + max_size: 1024 + - class_path: otx.core.data.transform_libs.torchvision.PadtoSquare + - class_path: torchvision.transforms.v2.ToDtype + init_args: + dtype: ${as_torch_dtype:torch.float32} + scale: False + - class_path: torchvision.transforms.v2.Normalize + init_args: + mean: [123.675, 116.28, 103.53] + std: [58.395, 57.12, 57.375] + val_subset: + batch_size: 1 + num_workers: 0 + transforms: + - class_path: torchvision.transforms.v2.Resize + init_args: + size: 1023 + max_size: 1024 + - class_path: otx.core.data.transform_libs.torchvision.PadtoSquare + - class_path: torchvision.transforms.v2.ToDtype + init_args: + dtype: ${as_torch_dtype:torch.float32} + scale: False + - class_path: torchvision.transforms.v2.Normalize + init_args: + mean: [123.675, 116.28, 103.53] + std: [58.395, 57.12, 57.375] + test_subset: + batch_size: 1 + num_workers: 0 + transforms: + - class_path: torchvision.transforms.v2.Resize + init_args: + size: 1023 + max_size: 1024 + - class_path: otx.core.data.transform_libs.torchvision.PadtoSquare + - class_path: torchvision.transforms.v2.ToDtype + init_args: + dtype: ${as_torch_dtype:torch.float32} + scale: False + - class_path: torchvision.transforms.v2.Normalize + init_args: + mean: [123.675, 116.28, 103.53] + std: [58.395, 57.12, 57.375] diff --git a/tests/integration/cli/test_cli.py b/tests/integration/cli/test_cli.py index b3a9fe6fc56..939a667921e 100644 --- a/tests/integration/cli/test_cli.py +++ b/tests/integration/cli/test_cli.py @@ -13,63 +13,60 @@ # This assumes have OTX installed in environment. otx_module = importlib.import_module("otx") RECIPE_PATH = Path(inspect.getfile(otx_module)).parent / "recipe" -ALL_RECIPE_LIST = [str(_.relative_to(RECIPE_PATH)) for _ in RECIPE_PATH.glob("**/*.yaml")] -RECIPE_OV_LIST = [str(_.relative_to(RECIPE_PATH)) for _ in RECIPE_PATH.glob("**/openvino_model.yaml")] -RECIPE_LIST = set(ALL_RECIPE_LIST) - set(RECIPE_OV_LIST) +RECIPE_LIST = [str(p) for p in RECIPE_PATH.glob("**/*.yaml") if "_base_" not in p.parts] +RECIPE_OV_LIST = [str(p) for p in RECIPE_PATH.glob("**/openvino_model.yaml") if "_base_" not in p.parts] +RECIPE_LIST = set(RECIPE_LIST) - set(RECIPE_OV_LIST) + # [TODO]: This is a temporary approach. DATASET = { - "multiclass_classification": { - "data_dir": "tests/assets/classification_dataset", - "overrides": [ - "model.otx_model.num_classes=2", - ], + "multi_class_cls": { + "data_root": "tests/assets/classification_dataset", + "overrides": ["--model.num_classes", "2"], }, - "multilabel_classification": { - "data_dir": "tests/assets/multilabel_classification", - "overrides": [ - "model.otx_model.num_classes=2", - ], + "multi_label_cls": { + "data_root": "tests/assets/multilabel_classification", + "overrides": ["--model.num_classes", "2"], }, - "hlabel_classification": { - "data_dir": "tests/assets/hlabel_classification", + "h_label_cls": { + "data_root": "tests/assets/hlabel_classification", "overrides": [ - "model.otx_model.num_classes=7", - "model.otx_model.num_multiclass_heads=2", - "model.otx_model.num_multilabel_classes=3", + "--model.num_classes", + "7", + "--model.num_multiclass_heads", + "2", + "--model.num_multilabel_classes", + "3", ], }, "detection": { - "data_dir": "tests/assets/car_tree_bug", - "overrides": ["model.otx_model.num_classes=3"], + "data_root": "tests/assets/car_tree_bug", + "overrides": ["--model.num_classes", "3"], }, "instance_segmentation": { - "data_dir": "tests/assets/car_tree_bug", - "overrides": [ - "model.otx_model.num_classes=3", - ], + "data_root": "tests/assets/car_tree_bug", + "overrides": ["--model.num_classes", "3"], }, - "segmentation": { - "data_dir": "tests/assets/common_semantic_segmentation_dataset/supervised", - "overrides": ["model.otx_model.num_classes=2"], + "semantic_segmentation": { + "data_root": "tests/assets/common_semantic_segmentation_dataset/supervised", + "overrides": ["--model.num_classes", "2"], }, "action_classification": { - "data_dir": "tests/assets/action_classification_dataset/", - "overrides": ["model.otx_model.num_classes=2"], + "data_root": "tests/assets/action_classification_dataset/", + "overrides": ["--model.num_classes", "2"], }, "action_detection": { - "data_dir": "tests/assets/action_detection_dataset/", + "data_root": "tests/assets/action_detection_dataset/", "overrides": [ - "model.otx_model.num_classes=5", - "model.otx_model.topk=3", + "--model.num_classes", + "5", + "--model.topk", + "3", ], }, "visual_prompting": { - "data_dir": "tests/assets/car_tree_bug", - "overrides": [ - "~model.scheduler.mode", - "~model.scheduler.patience", - ], + "data_root": "tests/assets/car_tree_bug", + "overrides": [], }, } @@ -89,19 +86,28 @@ def test_otx_e2e(recipe: str, tmp_path: Path, fxt_accelerator: str) -> None: Returns: None """ - task = recipe.split("/")[0] - model_name = recipe.split("/")[1].split(".")[0] + if recipe.endswith("visual_prompting/sam_tiny_vit.yaml"): + # found an issue where the current process is not terminating, so disable it. + # Issue with process not ending if the recipe and openvino_model.yaml test are performed in order + pytest.skip("Skip this one for a bit because we found an issue with the memory cache.") + task = recipe.split("/")[-2] + model_name = recipe.split("/")[-1].split(".")[0] # 1) otx train tmp_path_train = tmp_path / f"otx_train_{model_name}" command_cfg = [ "otx", "train", - f"+recipe={recipe}", - f"base.data_dir={DATASET[task]['data_dir']}", - f"base.work_dir={tmp_path_train}", - f"base.output_dir={tmp_path_train / 'outputs'}", - "+debug=intg_test", + "--config", + recipe, + "--data_root", + DATASET[task]["data_root"], + "--engine.work_dir", + str(tmp_path_train / "outputs"), + "--engine.device", + fxt_accelerator, + "--max_epochs", + "2", *DATASET[task]["overrides"], ] @@ -110,9 +116,8 @@ def test_otx_e2e(recipe: str, tmp_path: Path, fxt_accelerator: str) -> None: # Currently, a simple output check assert (tmp_path_train / "outputs").exists() - assert (tmp_path_train / "outputs" / "otx_train.log").exists() + assert (tmp_path_train / "outputs" / "configs.yaml").exists() assert (tmp_path_train / "outputs" / "csv").exists() - assert (tmp_path_train / "outputs").exists() assert (tmp_path_train / "outputs" / "checkpoints").exists() ckpt_files = list((tmp_path_train / "outputs" / "checkpoints").glob(pattern="epoch_*.ckpt")) assert len(ckpt_files) > 0 @@ -122,21 +127,24 @@ def test_otx_e2e(recipe: str, tmp_path: Path, fxt_accelerator: str) -> None: command_cfg = [ "otx", "test", - f"+recipe={recipe}", - f"base.data_dir={DATASET[task]['data_dir']}", - f"base.work_dir={tmp_path_test}", - f"base.output_dir={tmp_path_test / 'outputs'}", - f"trainer={fxt_accelerator}", + "--config", + recipe, + "--data_root", + DATASET[task]["data_root"], + "--engine.work_dir", + str(tmp_path_test / "outputs"), + "--engine.device", + fxt_accelerator, *DATASET[task]["overrides"], - f"checkpoint={ckpt_files[-1]}", + "--checkpoint", + str(ckpt_files[-1]), ] with patch("sys.argv", command_cfg): main() assert (tmp_path_test / "outputs").exists() - assert (tmp_path_test / "outputs" / "otx_test.log").exists() - assert (tmp_path_test / "outputs" / "lightning_logs").exists() + assert (tmp_path_test / "outputs" / "csv").exists() @pytest.mark.parametrize("recipe", RECIPE_OV_LIST) @@ -153,28 +161,33 @@ def test_otx_ov_test(recipe: str, tmp_path: Path) -> None: Returns: None """ - if recipe == "instance_segmentation/openvino_model.yaml": + task = recipe.split("/")[-2] + model_name = recipe.split("/")[-1].split(".")[0] + + if task == "instance_segmentation": # OMZ doesn't have proper model for Pytorch MaskRCNN interface # TODO(Kirill): Need to change this test when export enabled #noqa: TD003 pytest.skip("OMZ doesn't have proper model for Pytorch MaskRCNN interface.") - task = recipe.split("/")[0] - model_name = recipe.split("/")[1].split(".")[0] - # otx test - tmp_path_test = tmp_path / f"otx_test_{model_name}" + tmp_path_test = tmp_path / f"otx_test_{task}_{model_name}" command_cfg = [ "otx", "test", - f"+recipe={recipe}", - f"base.data_dir={DATASET[task]['data_dir']}", - f"base.work_dir={tmp_path_test}", - f"base.output_dir={tmp_path_test / 'outputs'}", + "--config", + recipe, + "--data_root", + DATASET[task]["data_root"], + "--engine.work_dir", + str(tmp_path_test / "outputs"), + "--engine.device", + "cpu", ] with patch("sys.argv", command_cfg): main() assert (tmp_path_test / "outputs").exists() - assert (tmp_path_test / "outputs" / "otx_test.log").exists() - assert (tmp_path_test / "outputs" / "lightning_logs").exists() + assert (tmp_path_test / "outputs" / "csv").exists() + metric_result = list((tmp_path_test / "outputs" / "csv").glob(pattern="**/metrics.csv")) + assert len(metric_result) > 0 diff --git a/tests/regression/test_regression.py b/tests/regression/test_regression.py index 6575803b37b..8e93aa872ba 100644 --- a/tests/regression/test_regression.py +++ b/tests/regression/test_regression.py @@ -8,7 +8,8 @@ from pathlib import Path import pytest -from otx.cli.train import otx_train +from otx.cli.cli import OTXCLI +from unittest.mock import patch import mlflow @@ -63,25 +64,36 @@ def _test_regression( } data_root = ( fxt_dataset_root_dir - / test_case.model.task + # / test_case.model.task / test_case.dataset.data_root ) with mlflow.start_run(tags=tags, run_name=run_name): - overrides = [ - f"+recipe={test_case.model.task}/{test_case.model.name}", - f"model.otx_model.num_classes={test_case.dataset.num_classes}", - f"data.data_root={data_root}", - f"data.data_format={test_case.dataset.data_format}", - f"base.output_dir={test_case.output_dir}", - f"seed={seed}", - f"trainer={fxt_accelerator}", - "test=true", - "trainer=gpu", - ] + [ - f"{key}={value}" - for key, value in test_case.dataset.extra_overrides.items() + command_cfg = [ + "otx", "train", + "--config", f"src/otx/recipe/{test_case.model.task}/{test_case.model.name}.yaml", + "--model.num_classes", str(test_case.dataset.num_classes), + "--data_root", str(data_root), + "--data.config.data_format", test_case.dataset.data_format, + "--engine.work_dir", str(test_case.output_dir), + "--engine.device", fxt_accelerator, ] - metrics = otx_train(overrides) + deterministic = test_case.dataset.extra_overrides.pop("deterministic", "False") + for key, value in test_case.dataset.extra_overrides.items(): + command_cfg.append(f"--{key}") + command_cfg.append(str(value)) + train_cfg = command_cfg.copy() + train_cfg.extend(["--seed", str(seed)]) + train_cfg.extend(["--deterministic", deterministic]) + with patch("sys.argv", train_cfg): + cli = OTXCLI() + train_metrics = cli.engine.trainer.callback_metrics + checkpoint = cli.engine.checkpoint + command_cfg[1] = "test" + command_cfg += ["--checkpoint", checkpoint] + with patch("sys.argv", command_cfg): + cli = OTXCLI() + test_metrics = cli.engine.trainer.callback_metrics + metrics = {**train_metrics, **test_metrics} # Submit metrics to MLFlow Tracker server mlflow.log_metrics(metrics) @@ -90,36 +102,36 @@ def _test_regression( class TestMultiClassCls(BaseTest): # Test case parametrization for model MODEL_TEST_CASES = [ # noqa: RUF012 - ModelTestCase(task="multiclass_classification", name="otx_deit_tiny"), - ModelTestCase(task="multiclass_classification", name="otx_dino_v2"), - ModelTestCase(task="multiclass_classification", name="otx_efficientnet_b0"), - ModelTestCase(task="multiclass_classification", name="otx_efficientnet_v2"), - ModelTestCase(task="multiclass_classification", name="otx_mobilenet_v3_large"), + ModelTestCase(task="classification/multi_class_cls", name="otx_deit_tiny"), + ModelTestCase(task="classification/multi_class_cls", name="otx_dino_v2"), + ModelTestCase(task="classification/multi_class_cls", name="otx_efficientnet_b0"), + ModelTestCase(task="classification/multi_class_cls", name="otx_efficientnet_v2"), + ModelTestCase(task="classification/multi_class_cls", name="otx_mobilenet_v3_large"), ] # Test case parametrization for dataset DATASET_TEST_CASES = [ # noqa: RUF012 DatasetTestCase( name=f"multiclass_CUB_small_{idx}", - data_root=Path("multiclass_CUB_small") / f"{idx}", + data_root=Path("multiclass_classification/multiclass_CUB_small") / f"{idx}", data_format="imagenet_with_subset_dirs", num_classes=2, - extra_overrides={"trainer.max_epochs": "20"}, + extra_overrides={"max_epochs": "20"}, ) for idx in range(1, 4) ] + [ DatasetTestCase( name=f"multiclass_CUB_medium", - data_root=Path("multiclass_CUB_medium"), + data_root=Path("multiclass_classification/multiclass_CUB_medium"), data_format="imagenet_with_subset_dirs", num_classes=67, - extra_overrides={"trainer.max_epochs": "20"}, + extra_overrides={"max_epochs": "20"}, ), DatasetTestCase( name=f"multiclass_food101_large", - data_root=Path("multiclass_food101_large"), + data_root=Path("multiclass_classification/multiclass_food101_large"), data_format="imagenet_with_subset_dirs", num_classes=20, - extra_overrides={"trainer.max_epochs": "20"}, + extra_overrides={"max_epochs": "20"}, ) ] @@ -157,35 +169,35 @@ def test_regression( class TestMultilabelCls(BaseTest): # Test case parametrization for model MODEL_TEST_CASES = [ # noqa: RUF012 - ModelTestCase(task="multilabel_classification", name="efficientnet_b0_light"), - ModelTestCase(task="multilabel_classification", name="efficientnet_v2_light"), - ModelTestCase(task="multilabel_classification", name="mobilenet_v3_large_light"), - ModelTestCase(task="multilabel_classification", name="otx_deit_tiny"), + ModelTestCase(task="classification/multi_label_cls", name="efficientnet_b0_light"), + ModelTestCase(task="classification/multi_label_cls", name="efficientnet_v2_light"), + ModelTestCase(task="classification/multi_label_cls", name="mobilenet_v3_large_light"), + ModelTestCase(task="classification/multi_label_cls", name="otx_deit_tiny"), ] # Test case parametrization for dataset DATASET_TEST_CASES = [ # noqa: RUF012 DatasetTestCase( name=f"multilabel_CUB_small_{idx}", - data_root=Path("multilabel_CUB_small") / f"{idx}", + data_root=Path("multilabel_classification/multilabel_CUB_small") / f"{idx}", data_format="datumaro", num_classes=3, - extra_overrides={"trainer.max_epochs": "20"}, + extra_overrides={"max_epochs": "20"}, ) for idx in range(1, 4) ] + [ DatasetTestCase( name=f"multilabel_CUB_medium", - data_root=Path("multilabel_CUB_medium"), + data_root=Path("multilabel_classification/multilabel_CUB_medium"), data_format="datumaro", num_classes=68, - extra_overrides={"trainer.max_epochs": "20"}, + extra_overrides={"max_epochs": "20"}, ), DatasetTestCase( name=f"multilabel_food101_large", - data_root=Path("multilabel_food101_large"), + data_root=Path("multilabel_classification/multilabel_food101_large"), data_format="datumaro", num_classes=21, - extra_overrides={"trainer.max_epochs": "20"}, + extra_overrides={"max_epochs": "20"}, ) ] @@ -223,35 +235,35 @@ def test_regression( class TestHlabelCls(BaseTest): # Test case parametrization for model MODEL_TEST_CASES = [ # noqa: RUF012 - ModelTestCase(task="hlabel_classification", name="efficientnet_b0_light"), - ModelTestCase(task="hlabel_classification", name="efficientnet_v2_light"), - ModelTestCase(task="hlabel_classification", name="mobilenet_v3_large_light"), - ModelTestCase(task="hlabel_classification", name="otx_deit_tiny"), + ModelTestCase(task="classification/h_label_cls", name="efficientnet_b0_light"), + ModelTestCase(task="classification/h_label_cls", name="efficientnet_v2_light"), + ModelTestCase(task="classification/h_label_cls", name="mobilenet_v3_large_light"), + ModelTestCase(task="classification/h_label_cls", name="otx_deit_tiny"), ] # Test case parametrization for dataset DATASET_TEST_CASES = [ # noqa: RUF012 DatasetTestCase( name=f"hlabel_CUB_small_{idx}", - data_root=Path("hlabel_CUB_small") / f"{idx}", + data_root=Path("hlabel_classification/hlabel_CUB_small") / f"{idx}", data_format="datumaro", num_classes=6, extra_overrides={ - "trainer.max_epochs": "20", - "model.otx_model.num_multiclass_heads": "3", - "model.otx_model.num_multilabel_classes": "0", + "max_epochs": "20", + "model.num_multiclass_heads": "3", + "model.num_multilabel_classes": "0", }, ) for idx in range(1, 4) ] + [ DatasetTestCase( name=f"hlabel_CUB_medium", - data_root=Path("hlabel_CUB_medium"), + data_root=Path("hlabel_classification/hlabel_CUB_medium"), data_format="datumaro", num_classes=102, extra_overrides={ - "trainer.max_epochs": "20", - "model.otx_model.num_multiclass_heads": "23", - "model.otx_model.num_multilabel_classes": "0", + "max_epochs": "20", + "model.num_multiclass_heads": "23", + "model.num_multilabel_classes": "0", }, ) @@ -287,6 +299,7 @@ def test_regression( tmpdir=tmpdir, ) + class TestObjectDetection(BaseTest): # Test case parametrization for model MODEL_TEST_CASES = [ # noqa: RUF012 @@ -302,26 +315,26 @@ class TestObjectDetection(BaseTest): DATASET_TEST_CASES = [ # noqa: RUF012 DatasetTestCase( name=f"pothole_small_{idx}", - data_root=Path("pothole_small") / f"{idx}", + data_root=Path("detection/pothole_small") / f"{idx}", data_format="coco", num_classes=1, - extra_overrides={"trainer.max_epochs": "40", "trainer.deterministic": "True"}, + extra_overrides={"max_epochs": "40", "deterministic": "True"}, ) for idx in range(1, 4) ] + [ DatasetTestCase( name="pothole_medium", - data_root="pothole_medium", + data_root=Path("detection/pothole_medium"), data_format="coco", num_classes=1, - extra_overrides={"trainer.max_epochs": "40", "trainer.deterministic": "True"} + extra_overrides={"max_epochs": "40", "deterministic": "True"} ), DatasetTestCase( name="vitens_large", - data_root="vitens_large", + data_root=Path("detection/vitens_large"), data_format="coco", num_classes=1, - extra_overrides={"trainer.max_epochs": "40", "trainer.deterministic": "True"} + extra_overrides={"max_epochs": "40", "deterministic": "True"} ) ] @@ -358,38 +371,38 @@ def test_regression( class TestSemanticSegmentation(BaseTest): # Test case parametrization for model MODEL_TEST_CASES = [ # noqa: RUF012 - ModelTestCase(task="segmentation", name="litehrnet_18"), - ModelTestCase(task="segmentation", name="litehrnet_s"), - ModelTestCase(task="segmentation", name="litehrnet_x"), - ModelTestCase(task="segmentation", name="segnext_b"), - ModelTestCase(task="segmentation", name="segnext_s"), - ModelTestCase(task="segmentation", name="segnext_t"), - ModelTestCase(task="segmentation", name="dino_v2_seg"), + ModelTestCase(task="semantic_segmentation", name="litehrnet_18"), + ModelTestCase(task="semantic_segmentation", name="litehrnet_s"), + ModelTestCase(task="semantic_segmentation", name="litehrnet_x"), + ModelTestCase(task="semantic_segmentation", name="segnext_b"), + ModelTestCase(task="semantic_segmentation", name="segnext_s"), + ModelTestCase(task="semantic_segmentation", name="segnext_t"), + ModelTestCase(task="semantic_segmentation", name="dino_v2"), ] # Test case parametrization for dataset DATASET_TEST_CASES = [ # noqa: RUF012 DatasetTestCase( name=f"kvasir_small_{idx}", - data_root=Path("kvasir_small") / f"{idx}", + data_root=Path("semantic_seg/kvasir_small") / f"{idx}", data_format="common_semantic_segmentation_with_subset_dirs", num_classes=2, - extra_overrides={"trainer.max_epochs": "40"}, + extra_overrides={"max_epochs": "40"}, ) for idx in range(1, 4) ] + [ DatasetTestCase( name="kvasir_medium", - data_root="kvasir_medium", + data_root=Path("semantic_seg/kvasir_medium"), data_format="common_semantic_segmentation_with_subset_dirs", num_classes=2, - extra_overrides={"trainer.max_epochs": "40"} + extra_overrides={"max_epochs": "40"} ), DatasetTestCase( name="kvasir_large", - data_root="kvasir_large", + data_root=Path("semantic_seg/kvasir_large"), data_format="common_semantic_segmentation_with_subset_dirs", num_classes=2, - extra_overrides={"trainer.max_epochs": "40"} + extra_overrides={"max_epochs": "40"} ) ] @@ -423,7 +436,6 @@ def test_regression( tmpdir=tmpdir, ) - class TestInstanceSegmentation(BaseTest): # Test case parametrization for model MODEL_TEST_CASES = [ # noqa: RUF012 @@ -435,26 +447,26 @@ class TestInstanceSegmentation(BaseTest): DATASET_TEST_CASES = [ # noqa: RUF012 DatasetTestCase( name=f"wgisd_small_{idx}", - data_root=Path("wgisd_small") / f"{idx}", + data_root=Path("instance_seg/wgisd_small") / f"{idx}", data_format="coco", num_classes=5, - extra_overrides={"trainer.max_epochs": "20", "trainer.deterministic": "True"}, + extra_overrides={"max_epochs": "20", "deterministic": "True"}, ) for idx in range(1, 4) ] + [ DatasetTestCase( name="coco_car_person_medium", - data_root="coco_car_person_medium", + data_root=Path("instance_seg/coco_car_person_medium"), data_format="coco", num_classes=2, - extra_overrides={"trainer.max_epochs": "20", "trainer.deterministic": "True"} + extra_overrides={"max_epochs": "20", "deterministic": "True"} ), DatasetTestCase( name="vitens_coliform", - data_root="Vitens-Coliform-coco", + data_root=Path("instance_seg/Vitens-Coliform-coco"), data_format="coco", num_classes=1, - extra_overrides={"trainer.max_epochs": "20", "trainer.deterministic": "True"} + extra_overrides={"max_epochs": "20", "deterministic": "True"} ) ] @@ -498,26 +510,26 @@ class TestVisualPrompting(BaseTest): DATASET_TEST_CASES = [ # noqa: RUF012 DatasetTestCase( name=f"wgisd_small_{idx}", - data_root=Path("wgisd_small") / f"{idx}", + data_root=Path("visual_prompting/wgisd_small") / f"{idx}", data_format="coco", num_classes=5, - extra_overrides={"trainer.max_epochs": "20", "trainer.deterministic": "True"}, + extra_overrides={"max_epochs": "20", "deterministic": "True"}, ) for idx in range(1, 4) ] + [ DatasetTestCase( name="coco_car_person_medium", - data_root="coco_car_person_medium", + data_root=Path("visual_prompting/coco_car_person_medium"), data_format="coco", num_classes=2, - extra_overrides={"trainer.max_epochs": "20", "trainer.deterministic": "True"} + extra_overrides={"max_epochs": "20", "deterministic": "True"} ), DatasetTestCase( name="vitens_coliform", - data_root="Vitens-Coliform-coco", + data_root=Path("visual_prompting/Vitens-Coliform-coco"), data_format="coco", num_classes=1, - extra_overrides={"trainer.max_epochs": "20", "trainer.deterministic": "True"} + extra_overrides={"max_epochs": "20", "deterministic": "True"} ) ] diff --git a/tests/unit/cli/test_cli.py b/tests/unit/cli/test_cli.py index d053a225ab9..6306e5644d8 100644 --- a/tests/unit/cli/test_cli.py +++ b/tests/unit/cli/test_cli.py @@ -5,7 +5,7 @@ import sys import pytest -from otx.cli import OTXCLI +from otx.cli import OTXCLI, main class TestOTXCLI: @@ -19,6 +19,15 @@ def test_init(self, mocker) -> None: with mocker.patch.object(sys, "argv", argv) and pytest.raises(SystemExit, match="0"): OTXCLI() + def test_main(self, mocker) -> None: + argv = ["otx"] + with mocker.patch.object(sys, "argv", argv) and pytest.raises(SystemExit, match="2"): + main() + + argv = ["otx", "-h"] + with mocker.patch.object(sys, "argv", argv) and pytest.raises(SystemExit, match="0"): + main() + @pytest.fixture() def fxt_train_help_command(self, monkeypatch) -> None: argv = ["otx", "train", "-h"] @@ -29,27 +38,66 @@ def test_train_help_command(self, fxt_train_help_command) -> None: with pytest.raises(SystemExit, match="0"): OTXCLI() + def test_init_parser(self, mocker) -> None: + mocker.patch("otx.cli.cli.OTXCLI.__init__", return_value=None) + cli = OTXCLI() + parser = cli.init_parser() + assert parser.__class__.__name__ == "ArgumentParser" + argument_list = [action.dest for action in parser._actions] + expected_argument = ["help", "version"] + assert argument_list == expected_argument + + def test_subcommand_parser(self, mocker) -> None: + mocker.patch("otx.cli.cli.OTXCLI.__init__", return_value=None) + cli = OTXCLI() + parser = cli.subcommand_parser() + assert parser.__class__.__name__ == "ArgumentParser" + argument_list = [action.dest for action in parser._actions] + expected_argument = ["help", "verbose", "config", "print_config", "data_root", "task", "callback_monitor"] + assert sorted(argument_list) == sorted(expected_argument) + + def test_add_subcommands(self, mocker) -> None: + mocker.patch("otx.cli.cli.OTXCLI.__init__", return_value=None) + cli = OTXCLI() + cli.parser = cli.init_parser() + cli._subcommand_method_arguments = {} + cli.add_subcommands() + assert cli._subcommand_method_arguments.keys() == cli.engine_subcommands().keys() + @pytest.fixture() def fxt_train_command(self, monkeypatch, tmpdir) -> list[str]: argv = [ "otx", "train", - "+recipe=multiclass_classification/otx_mobilenet_v3_large", - "checkpoint=my_checkpoint", - f"base.output_dir={tmpdir}", + "--config", + "src/otx/recipe/detection/atss_mobilenetv2.yaml", + "--data_root", + "tests/assets/car_tree_bug", + "--model.num_classes", + "3", + "--engine.work_dir", + str(tmpdir), ] monkeypatch.setattr("sys.argv", argv) return argv - def test_train_command(self, fxt_train_command, mocker, tmpdir) -> None: - # Test that main function runs with help -> return 0 - mock_otx_train = mocker.patch("otx.cli.train.otx_train") + def test_instantiate_classes(self, fxt_train_command, mocker) -> None: + mock_run = mocker.patch("otx.cli.OTXCLI.run") cli = OTXCLI() + assert mock_run.call_count == 1 + cli.instantiate_classes() + + from otx.core.model.entity.base import OTXModel + + assert isinstance(cli.model, OTXModel) + + from otx.core.data.module import OTXDataModule + + assert isinstance(cli.datamodule, OTXDataModule) + + from otx.engine import Engine - assert cli.config["subcommand"] == "train" - assert "overrides" in cli.config["train"] - assert cli.config["train"]["overrides"] == fxt_train_command[2:] + assert isinstance(cli.engine, Engine) - assert mock_otx_train.call_count == 1 - assert "overrides" in mock_otx_train.call_args.kwargs - assert mock_otx_train.call_args.kwargs["overrides"] == fxt_train_command[2:] + assert cli.datamodule == cli.engine.datamodule + assert cli.model == cli.engine.model diff --git a/tests/unit/cli/utils/test_help_formatter.py b/tests/unit/cli/utils/test_help_formatter.py new file mode 100644 index 00000000000..61a05a6e27b --- /dev/null +++ b/tests/unit/cli/utils/test_help_formatter.py @@ -0,0 +1,138 @@ +"""Tests for Custom Help Formatter.""" + +# Copyright (C) 2023 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +import sys +from unittest.mock import patch + +import pytest +from jsonargparse import ArgumentParser +from otx.cli.utils.help_formatter import ( + CustomHelpFormatter, + get_cli_usage_docstring, + get_verbosity_subcommand, + render_guide, +) + + +def test_get_verbosity_subcommand() -> None: + """Test if the verbosity level and subcommand are correctly parsed.""" + argv = ["otx", "train", "-h"] + with patch.object(sys, "argv", argv): + result = get_verbosity_subcommand() + assert result["subcommand"] == "train" + assert result["verbosity"] == 0 + + argv = ["otx", "train", "-h", "-v"] + with patch.object(sys, "argv", argv): + result = get_verbosity_subcommand() + assert result["subcommand"] == "train" + assert result["verbosity"] == 1 + + argv = ["otx", "train", "-h", "-vv"] + with patch.object(sys, "argv", argv): + result = get_verbosity_subcommand() + assert result["subcommand"] == "train" + assert result["verbosity"] == 2 + + argv = ["otx", "-h"] + with patch.object(sys, "argv", argv): + result = get_verbosity_subcommand() + assert result["subcommand"] is None + assert result["verbosity"] == 2 + + +def test_get_cli_usage_docstring() -> None: + """Test if the CLI usage docstring is correctly parsed.""" + assert get_cli_usage_docstring(None) is None + + class Component: + """. + + CLI Usage: + 1. First Step. + 2. Second Step. + + + """ + + assert get_cli_usage_docstring(Component) == "1. First Step.\n2. Second Step." + + class Component2: + """. + + CLI Usage-Test: + test: test. + + + """ + + assert get_cli_usage_docstring(Component2) is None + + +def test_render_guide() -> None: + """Test if the guide is correctly rendered.""" + subcommand = "train" + contents = render_guide(subcommand) + assert len(contents) == 2 + assert contents[0].__class__.__name__ == "Markdown" + assert "# OpenVINO™ Training Extensions CLI Guide" in contents[0].markup + assert contents[1].__class__.__name__ == "Panel" + assert "otx train" in contents[1].renderable.markup + assert render_guide(None) == [] + + +class TestCustomHelpFormatter: + """Test Custom Help Formatter.""" + + @pytest.fixture() + def fxt_parser(self) -> ArgumentParser: + """Mock ArgumentParser.""" + parser = ArgumentParser(env_prefix="otx", formatter_class=CustomHelpFormatter) + parser.formatter_class.subcommand = "train" + parser.add_argument( + "-t", + "--test", + action="count", + help="add_usage test.", + ) + parser.add_argument( + "--model", + action="count", + help="never_skip test.", + ) + return parser + + def test_verbose_0(self, capfd: "pytest.CaptureFixture", fxt_parser: ArgumentParser) -> None: + """Test verbose level 0.""" + argv = ["otx", "train", "-h"] + assert fxt_parser.formatter_class == CustomHelpFormatter + fxt_parser.formatter_class.verbosity_level = 0 + with pytest.raises(SystemExit, match="0"): + fxt_parser.parse_args(argv) + out, _ = capfd.readouterr() + assert "Quick-Start" in out + assert "Arguments" not in out + + def test_verbose_1(self, capfd: "pytest.CaptureFixture", fxt_parser: ArgumentParser) -> None: + """Test verbose level 1.""" + argv = ["otx", "train", "-h", "-v"] + assert fxt_parser.formatter_class == CustomHelpFormatter + fxt_parser.formatter_class.verbosity_level = 1 + with pytest.raises(SystemExit, match="0"): + fxt_parser.parse_args(argv) + out, _ = capfd.readouterr() + assert "Quick-Start" in out + assert "Arguments" in out + + def test_verbose_2(self, capfd: "pytest.CaptureFixture", fxt_parser: ArgumentParser) -> None: + """Test verbose level 2.""" + argv = ["otx", "train", "-h", "-vv"] + assert fxt_parser.formatter_class == CustomHelpFormatter + fxt_parser.formatter_class.verbosity_level = 2 + with pytest.raises(SystemExit, match="0"): + fxt_parser.parse_args(argv) + out, _ = capfd.readouterr() + assert "Quick-Start" not in out + assert "Arguments" in out diff --git a/tests/unit/cli/utils/test_hydra.py b/tests/unit/cli/utils/test_hydra.py deleted file mode 100644 index 0742c7abf4e..00000000000 --- a/tests/unit/cli/utils/test_hydra.py +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright (C) 2023 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - - -from omegaconf import DictConfig -from otx.cli.utils.hydra import configure_hydra_outputs - - -def test_configure_hydra_outputs(mocker, tmp_path) -> None: - # Mock hydra functions - mock_configure_log = mocker.patch("otx.cli.utils.hydra.configure_log") - mock_save_config = mocker.patch("otx.cli.utils.hydra._save_config") - - cfg = DictConfig( - { - "hydra": { - "job": {"name": "test"}, - "output_subdir": "${base.output_dir}", - "runtime": {"output_dir": "${base.output_dir}"}, - "overrides": {"task": "test"}, - "verbose": False, - "job_logging": { - "handlers": { - "file": { - "class": "logging.FileHandler", - "formatter": "simple", - "filename": "${hydra.runtime.output_dir}/${hydra.job.name}.log", - }, - }, - }, - }, - "base": { - "work_dir": str(tmp_path / "work_dir"), - "data_dir": "inputs/dataset_dir", - "log_dir": "${base.work_dir}/logs/", - "output_dir": str(tmp_path / "outputs"), - }, - }, - ) - configure_hydra_outputs(cfg) - mock_configure_log.assert_called_once_with(cfg.hydra.job_logging, False) - - assert mock_save_config.call_count == 2 diff --git a/tests/unit/core/data/test_module.py b/tests/unit/core/data/test_module.py index 3158a7e230d..e94824b2e3e 100644 --- a/tests/unit/core/data/test_module.py +++ b/tests/unit/core/data/test_module.py @@ -67,8 +67,9 @@ def test_init( @pytest.fixture() def fxt_real_tv_cls_config(self) -> DictConfig: - cfg_path = files("otx") / "config" / "data" / "torchvision_cls.yaml" + cfg_path = files("otx") / "recipe" / "_base_" / "data" / "torchvision_base.yaml" cfg = OmegaConf.load(cfg_path) + cfg = cfg.config cfg.data_root = "." cfg.train_subset.subset_name = "train" cfg.train_subset.num_workers = 0 diff --git a/tests/unit/core/data/test_transform_libs.py b/tests/unit/core/data/test_transform_libs.py index 40342b427c5..407c6366fed 100644 --- a/tests/unit/core/data/test_transform_libs.py +++ b/tests/unit/core/data/test_transform_libs.py @@ -85,17 +85,21 @@ def fxt_config(self) -> list[dict[str, Any]]: prefix = "torchvision.transforms.v2" cfg = f""" transforms: - - _target_: {prefix}.RandomResizedCrop - size: [224, 224] - antialias: True - - _target_: {prefix}.RandomHorizontalFlip - p: 0.5 - - _target_: {prefix}.ToDtype - dtype: ${{as_torch_dtype:torch.float32}} - scale: True - - _target_: {prefix}.Normalize - mean: [0.485, 0.456, 0.406] - std: [0.229, 0.224, 0.225] + - class_path: {prefix}.RandomResizedCrop + init_args: + size: [224, 224] + antialias: True + - class_path: {prefix}.RandomHorizontalFlip + init_args: + p: 0.5 + - class_path: {prefix}.ToDtype + init_args: + dtype: ${{as_torch_dtype:torch.float32}} + scale: True + - class_path: {prefix}.Normalize + init_args: + mean: [0.485, 0.456, 0.406] + std: [0.229, 0.224, 0.225] """ return OmegaConf.create(cfg) From 22c1185b92a7fad95f705476ab9c21098f7a00cf Mon Sep 17 00:00:00 2001 From: Vinnam Kim Date: Tue, 23 Jan 2024 10:55:49 +0900 Subject: [PATCH 08/10] Fix cyclic import (#2827) Signed-off-by: Kim, Vinnam --- src/otx/core/model/entity/classification.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/otx/core/model/entity/classification.py b/src/otx/core/model/entity/classification.py index 49252bf3936..0ed17864353 100644 --- a/src/otx/core/model/entity/classification.py +++ b/src/otx/core/model/entity/classification.py @@ -9,7 +9,6 @@ import torch -from otx.algo.hooks.recording_forward_hook import ReciproCAMHook from otx.core.data.entity.base import OTXBatchLossEntity, T_OTXBatchDataEntity, T_OTXBatchPredEntity from otx.core.data.entity.classification import ( HlabelClsBatchDataEntity, @@ -47,6 +46,8 @@ def backbone(self) -> nn.Module: def register_explain_hook(self) -> None: """Register explain hook at the model backbone output.""" + from otx.algo.hooks.recording_forward_hook import ReciproCAMHook + self.explain_hook = ReciproCAMHook.create_and_register_hook( self.backbone, self.head_forward_fn, From 5f1559d7c6e9ba8038fe8c29b89373b849a184c0 Mon Sep 17 00:00:00 2001 From: Sungman Cho Date: Tue, 23 Jan 2024 15:23:15 +0900 Subject: [PATCH 09/10] Introduce the logic to load the OTX1.X checkpoints (Det, iSeg, sSeg, Action cls, det) (#2812) * Init * Apply recent changes * Update for all tasks except for classification * Fix precommit * Reflect reviews * Reflect reviews: change the name of util function and edit the detection load_weight * Fix segmentation load name * Add unit test for load_prev_otx function --- src/otx/core/model/module/base.py | 23 +++++++++- src/otx/core/model/module/detection.py | 8 ++++ .../model/module/instance_segmentation.py | 8 ++++ src/otx/core/model/module/segmentation.py | 8 ++++ src/otx/core/utils/utils.py | 28 +++++++++++ src/otx/engine/engine.py | 3 +- .../unit/core/model/module/test_detection.py | 46 +++++++++++++++++++ .../module/test_instance_segmentation.py | 46 +++++++++++++++++++ .../core/model/module/test_segmentation.py | 38 ++++++++++++++- 9 files changed, 205 insertions(+), 3 deletions(-) create mode 100644 src/otx/core/utils/utils.py create mode 100644 tests/unit/core/model/module/test_detection.py create mode 100644 tests/unit/core/model/module/test_instance_segmentation.py diff --git a/src/otx/core/model/module/base.py b/src/otx/core/model/module/base.py index 19096f8634d..21d878dbad0 100644 --- a/src/otx/core/model/module/base.py +++ b/src/otx/core/model/module/base.py @@ -15,6 +15,7 @@ from otx.core.data.entity.base import OTXBatchDataEntity from otx.core.model.entity.base import OTXModel from otx.core.types.export import OTXExportFormat +from otx.core.utils.utils import is_ckpt_for_finetuning, is_ckpt_from_otx_v1 if TYPE_CHECKING: from pathlib import Path @@ -135,12 +136,32 @@ def state_dict(self) -> dict[str, Any]: state_dict["meta_info"] = self.meta_info return state_dict - def load_state_dict(self, state_dict: dict[str, Any], *args, **kwargs) -> None: + def _load_from_prev_otx_ckpt(self, state_dict: dict[str, Any]) -> dict[str, Any]: + """Attach the model.model prefix to load without problem.""" + msg = "Trying to load the model checkpoint created by OTX 1.X. it will be converted to OTX2.0 format." + warnings.warn(msg, stacklevel=1) + for key in list(state_dict.keys()): + value = state_dict.pop(key) + new_key = "model.model." + key + state_dict[new_key] = value + return state_dict + + def load_state_dict(self, ckpt: dict[str, Any], *args, **kwargs) -> None: """Load state dictionary from checkpoint state dictionary. + It successfully loads the checkpoint from OTX v1.x and for finetune and for resume. + If checkpoint's meta_info and OTXLitModule's meta_info are different, load_state_pre_hook for smart weight loading will be registered. """ + if is_ckpt_from_otx_v1(ckpt): + model_state_dict = ckpt["model"]["state_dict"] + state_dict = self._load_from_prev_otx_ckpt(model_state_dict) + elif is_ckpt_for_finetuning(ckpt): + state_dict = ckpt["state_dict"] + else: + state_dict = ckpt + ckpt_meta_info = state_dict.pop("meta_info", None) if ckpt_meta_info and self.meta_info is None: diff --git a/src/otx/core/model/module/detection.py b/src/otx/core/model/module/detection.py index 09f3d701e3b..4f909d2bf9a 100644 --- a/src/otx/core/model/module/detection.py +++ b/src/otx/core/model/module/detection.py @@ -142,3 +142,11 @@ def test_step(self, inputs: DetBatchDataEntity, batch_idx: int) -> None: def lr_scheduler_monitor_key(self) -> str: """Metric name that the learning rate scheduler monitor.""" return "train/loss" + + def _load_from_prev_otx_ckpt(self, ckpt: dict) -> dict: + """Get the state_dict, supporting the backward compatibility.""" + state_dict = super()._load_from_prev_otx_ckpt(ckpt) + for key in list(state_dict.keys()): + if key.startswith("model.model.ema_"): + state_dict.pop(key) + return state_dict diff --git a/src/otx/core/model/module/instance_segmentation.py b/src/otx/core/model/module/instance_segmentation.py index 08e38a825da..363e8736ed2 100644 --- a/src/otx/core/model/module/instance_segmentation.py +++ b/src/otx/core/model/module/instance_segmentation.py @@ -170,3 +170,11 @@ def test_step(self, inputs: InstanceSegBatchDataEntity, batch_idx: int) -> None: def lr_scheduler_monitor_key(self) -> str: """Metric name that the learning rate scheduler monitor.""" return "train/loss" + + def _load_from_prev_otx_ckpt(self, ckpt: dict) -> dict: + """Get the state_dict, supporting the backward compatibility.""" + state_dict = super()._load_from_prev_otx_ckpt(ckpt) + for key in list(state_dict.keys()): + if key.startswith("model.model.ema_"): + state_dict.pop(key) + return state_dict diff --git a/src/otx/core/model/module/segmentation.py b/src/otx/core/model/module/segmentation.py index 0153f1df304..a4869427c0c 100644 --- a/src/otx/core/model/module/segmentation.py +++ b/src/otx/core/model/module/segmentation.py @@ -135,3 +135,11 @@ def test_step(self, inputs: SegBatchDataEntity, batch_idx: int) -> None: def lr_scheduler_monitor_key(self) -> str: """Metric name that the learning rate scheduler monitor.""" return "train/loss" + + def _load_from_prev_otx_ckpt(self, ckpt: dict) -> dict: + """Get the state_dict, supporting the backward compatibility.""" + state_dict = super()._load_from_prev_otx_ckpt(ckpt) + for key in list(state_dict.keys()): + if "ham.bases" in key or "decode_head.aggregator.projects" in key: + state_dict.pop(key) + return state_dict diff --git a/src/otx/core/utils/utils.py b/src/otx/core/utils/utils.py new file mode 100644 index 00000000000..27cc5d5c92a --- /dev/null +++ b/src/otx/core/utils/utils.py @@ -0,0 +1,28 @@ +# Copyright (c) 2024 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# +"""Utility functions.""" + + +def is_ckpt_from_otx_v1(ckpt: dict) -> bool: + """Check the checkpoint where it comes from. + + Args: + ckpt (dict): the checkpoint file + + Returns: + bool: True means the checkpoint comes from otx1 + """ + return "model" in ckpt and ckpt["VERSION"] == 1 + + +def is_ckpt_for_finetuning(ckpt: dict) -> bool: + """Check the checkpoint will be used to finetune. + + Args: + ckpt (dict): the checkpoint file + + Returns: + bool: True means the checkpoint will be used to finetune. + """ + return "state_dict" in ckpt diff --git a/src/otx/engine/engine.py b/src/otx/engine/engine.py index 04a7cd74ea3..2a2c7e17f29 100644 --- a/src/otx/engine/engine.py +++ b/src/otx/engine/engine.py @@ -205,7 +205,8 @@ def train( fit_kwargs["ckpt_path"] = self.checkpoint elif self.checkpoint is not None: loaded_checkpoint = torch.load(self.checkpoint) - lit_module.load_state_dict(loaded_checkpoint["state_dict"]) + # loaded checkpoint have keys (OTX1.5): model, config, labels, input_size, VERSION + lit_module.load_state_dict(loaded_checkpoint) self.trainer.fit( model=lit_module, diff --git a/tests/unit/core/model/module/test_detection.py b/tests/unit/core/model/module/test_detection.py new file mode 100644 index 00000000000..4b712332d86 --- /dev/null +++ b/tests/unit/core/model/module/test_detection.py @@ -0,0 +1,46 @@ +# Copyright (C) 2024 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# +"""Unit tests for detection model module.""" + +from __future__ import annotations + +from unittest.mock import MagicMock + +import pytest +import torch +from otx.core.model.module.detection import OTXDetectionLitModule + + +class TestOTXDetectionModule: + @pytest.fixture() + def fxt_model_ckpt(self) -> dict[str, torch.Tensor]: + return { + "model.model.backbone.1.weight": torch.randn(3, 10), + "model.model.backbone.1.bias": torch.randn(3, 10), + "model.model.head.1.weight": torch.randn(10, 2), + "model.model.head.1.bias": torch.randn(10, 2), + } + + @pytest.fixture() + def fxt_model(self) -> OTXDetectionLitModule: + return OTXDetectionLitModule( + otx_model=MagicMock(spec=OTXDetectionLitModule), + optimizer=MagicMock, + scheduler=MagicMock, + torch_compile=False, + ) + + def test_load_from_prev_otx_ckpt(self, fxt_model, fxt_model_ckpt) -> None: + ckpt_otx_v1 = { + "backbone.1.weight": torch.randn(3, 10), + "backbone.1.bias": torch.randn(3, 10), + "head.1.weight": torch.randn(10, 2), + "head.1.bias": torch.randn(10, 2), + "ema_model_t.1": torch.randn(3, 10), + } + converted_ckpt = fxt_model._load_from_prev_otx_ckpt(ckpt_otx_v1) + + assert fxt_model_ckpt.keys() == converted_ckpt.keys() + for src_value, dst_value in zip(converted_ckpt.values(), fxt_model_ckpt.values()): + assert src_value.shape == dst_value.shape diff --git a/tests/unit/core/model/module/test_instance_segmentation.py b/tests/unit/core/model/module/test_instance_segmentation.py new file mode 100644 index 00000000000..5e916d2df50 --- /dev/null +++ b/tests/unit/core/model/module/test_instance_segmentation.py @@ -0,0 +1,46 @@ +# Copyright (C) 2024 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# +"""Unit tests for instance segmentation model module.""" + +from __future__ import annotations + +from unittest.mock import MagicMock + +import pytest +import torch +from otx.core.model.module.instance_segmentation import OTXInstanceSegLitModule + + +class TestOTXInstanceSegModule: + @pytest.fixture() + def fxt_model_ckpt(self) -> dict[str, torch.Tensor]: + return { + "model.model.backbone.1.weight": torch.randn(3, 10), + "model.model.backbone.1.bias": torch.randn(3, 10), + "model.model.head.1.weight": torch.randn(10, 2), + "model.model.head.1.bias": torch.randn(10, 2), + } + + @pytest.fixture() + def fxt_model(self) -> OTXInstanceSegLitModule: + return OTXInstanceSegLitModule( + otx_model=MagicMock(spec=OTXInstanceSegLitModule), + optimizer=MagicMock, + scheduler=MagicMock, + torch_compile=False, + ) + + def test_load_from_prev_otx_ckpt(self, fxt_model, fxt_model_ckpt) -> None: + ckpt_otx_v1 = { + "backbone.1.weight": torch.randn(3, 10), + "backbone.1.bias": torch.randn(3, 10), + "head.1.weight": torch.randn(10, 2), + "head.1.bias": torch.randn(10, 2), + "ema_model_t.1": torch.randn(3, 10), + } + converted_ckpt = fxt_model._load_from_prev_otx_ckpt(ckpt_otx_v1) + + assert fxt_model_ckpt.keys() == converted_ckpt.keys() + for src_value, dst_value in zip(converted_ckpt.values(), fxt_model_ckpt.values()): + assert src_value.shape == dst_value.shape diff --git a/tests/unit/core/model/module/test_segmentation.py b/tests/unit/core/model/module/test_segmentation.py index 02b191eee48..50446ee34a8 100644 --- a/tests/unit/core/model/module/test_segmentation.py +++ b/tests/unit/core/model/module/test_segmentation.py @@ -28,7 +28,16 @@ def __call__(self, *args, **kwargs) -> SegBatchPredEntity: return SegBatchPredEntity(**self.input_dict, scores=[]) -class TestOTXSegmentationModel: +class TestOTXSegmentationModule: + @pytest.fixture() + def fxt_model_ckpt(self) -> dict[str, torch.Tensor]: + return { + "model.model.backbone.1.weight": torch.randn(3, 10), + "model.model.backbone.1.bias": torch.randn(3, 10), + "model.model.head.1.weight": torch.randn(10, 2), + "model.model.head.1.bias": torch.randn(10, 2), + } + @pytest.fixture() def model(self, mocker, fxt_seg_data_entity) -> OTXSegmentationLitModule: # define otx model @@ -59,3 +68,30 @@ def test_convert_pred_entity_to_compute_metric(self, model, fxt_seg_data_entity) assert "preds" in out[-1] assert "target" in out[-1] assert out[-1]["preds"].sum() == out[-1]["target"].sum() + + def test_load_from_prev_otx_ckpt(self, model, fxt_model_ckpt) -> None: + segnext_ckpt_otx_v1 = { + "backbone.1.weight": torch.randn(3, 10), + "backbone.1.bias": torch.randn(3, 10), + "head.1.weight": torch.randn(10, 2), + "head.1.bias": torch.randn(10, 2), + "ham.bases.1": torch.randn(3, 10), + } + converted_ckpt = model._load_from_prev_otx_ckpt(segnext_ckpt_otx_v1) + + assert fxt_model_ckpt.keys() == converted_ckpt.keys() + for src_value, dst_value in zip(converted_ckpt.values(), fxt_model_ckpt.values()): + assert src_value.shape == dst_value.shape + + litehr_ckpt_otx_v1 = { + "backbone.1.weight": torch.randn(3, 10), + "backbone.1.bias": torch.randn(3, 10), + "head.1.weight": torch.randn(10, 2), + "head.1.bias": torch.randn(10, 2), + "decode_head.aggregator.projects.1": torch.randn(3, 10), + } + converted_ckpt = model._load_from_prev_otx_ckpt(litehr_ckpt_otx_v1) + + assert fxt_model_ckpt.keys() == converted_ckpt.keys() + for src_value, dst_value in zip(converted_ckpt.values(), fxt_model_ckpt.values()): + assert src_value.shape == dst_value.shape From b75185c1a4cd60c504028039baae37ce0ebbe222 Mon Sep 17 00:00:00 2001 From: Harim Kang Date: Tue, 23 Jan 2024 18:04:22 +0900 Subject: [PATCH 10/10] Update for_developer md files (#2829) * Update documents * Update conda install step --- for_developers/cli_guide.md | 198 ++++++++++++++++++++++++++++++++ for_developers/dir_structure.md | 6 +- for_developers/setup_guide.md | 36 ++---- 3 files changed, 211 insertions(+), 29 deletions(-) create mode 100644 for_developers/cli_guide.md diff --git a/for_developers/cli_guide.md b/for_developers/cli_guide.md new file mode 100644 index 00000000000..90703e185e2 --- /dev/null +++ b/for_developers/cli_guide.md @@ -0,0 +1,198 @@ +# How to use OTX CLI + +## Installation + +Please see [setup_guide.md](setup_guide.md). + +## otx help + +```console +otx --help +``` + +```powershell +╭─ Arguments ─────────────────────────────────────────────────────────────────────────────────────╮ +│ Usage: otx [-h] [-v] {install,train,test,predict,export} ... │ +│ │ +│ │ +│ OpenVINO Training-Extension command line tool │ +│ │ +│ │ +│ Options: │ +│ -h, --help Show this help message and exit. │ +│ -v, --version Display OTX version number. │ +│ │ +│ Subcommands: │ +│ For more details of each subcommand, add it as an argument followed by --help. │ +│ │ +│ │ +│ Available subcommands: │ +│ install Install OTX requirements. │ +│ train Trains the model using the provided LightningModule and OTXDataModule. │ +│ test Run the testing phase of the engine. │ +│ predict Run predictions using the specified model and data. │ +│ export Export the trained model to OpenVINO Intermediate Representation (IR) o │ +│ ONNX formats. │ +│ │ +╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ +``` + +The subcommand can get help output in the following way. +For basic subcommand help, the Verbosity Level is 0. In this case, the CLI provides a Quick-Guide in markdown. + +```console +# otx {subcommand} --help +otx train --help +``` + +```powershell +┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ +┃ OpenVINO™ Training Extensions CLI Guide ┃ +┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ + +Github Repository: +https://github.com/openvinotoolkit/training_extensions. + +A better guide is provided by the documentation. +╭─ Quick-Start ─────────────────────────────────────────────────────────╮ +│ │ +│ 1 you can train with data_root only. then OTX will provide default │ +│ model. │ +│ │ +│ │ +│ otx train --data_root │ +│ │ +│ │ +│ 2 you can pick a model or datamodule as Config file or Class. │ +│ │ +│ │ +│ otx train │ +│ --data_root │ +│ --model --data │ +│ │ +│ │ +│ 3 Of course, you can override the various values with commands. │ +│ │ +│ │ +│ otx train │ +│ --data_root │ +│ --max_epochs --checkpoint │ +│ │ +│ │ +│ 4 If you have a complete configuration file, run it like this. │ +│ │ +│ │ +│ otx train --data_root --config │ +│ │ +│ │ +│ To get more overridable argument information, run the command below. │ +│ │ +│ │ +│ # Verbosity Level 1 │ +│ otx train [optional_arguments] -h -v │ +│ # Verbosity Level 2 │ +│ otx train [optional_arguments] -h -vv │ +│ │ +╰───────────────────────────────────────────────────────────────────────╯ +``` + +For Verbosity Level 1, it shows Quick-Guide & the essential arguments. + +```console +otx train --help -v +``` + +```powershell +┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ +┃ OpenVINO™ Training Extensions CLI Guide ┃ +┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ + +Github Repository: +https://github.com/openvinotoolkit/training_extensions. + +A better guide is provided by the documentation. +╭─ Quick-Start ─────────────────────────────────────────────────────────╮ +│ ... │ +╰───────────────────────────────────────────────────────────────────────╯ +╭─ Arguments ─────────────────────────────────────────────────────────────────────────────────────╮ +│ Usage: otx [options] train [-h] [-c CONFIG] [--print_config [=flags]] │ +│ [--data_root DATA_ROOT] [--task TASK] │ +│ [--engine CONFIG] │ +│ [--engine.work_dir WORK_DIR] │ +│ [--engine.checkpoint CHECKPOINT] │ +│ [--engine.device {auto,gpu,cpu,tpu,ipu,hpu,mps}] │ +│ [--model.help CLASS_PATH_OR_NAME] │ +│ [--model CONFIG | CLASS_PATH_OR_NAME | .INIT_ARG_NAME VALUE] │ +│ [--data CONFIG] │ +│ [--optimizer CONFIG | CLASS_PATH_OR_NAME | .INIT_ARG_NAME VALUE] │ +│ [--scheduler CONFIG | CLASS_PATH_OR_NAME | .INIT_ARG_NAME VALUE] │ +│ │ +... +``` + +For Verbosity Level 2, it shows all available arguments. + +```console +otx train --help -vv +``` + +## otx {subcommand} --print_config + +Preview all configuration values that will be executed through that command line. + +```console +otx train --config --print_config +``` + +```yaml +data_root: tests/assets/car_tree_bug +callback_monitor: val/map_50 +engine: + task: DETECTION + work_dir: ./otx-workspace + device: auto +model: + class_path: otx.algo.detection.atss.ATSS + init_args: + num_classes: 1000 + variant: mobilenetv2 +optimizer: ... +scheduler: ... +data: + task: DETECTION + config: + data_format: coco_instances + train_subset: ... + val_subset: ... + test_subset: ... + mem_cache_size: 1GB + mem_cache_img_max_size: null + image_color_channel: RGB + include_polygons: false +max_epochs: 2 +deterministic: false +precision: 16 +callbacks: ... +logger: ... +``` + +Users can also pre-generate a config file with an example like the one below. + +```console +otx train --config --print_config > config.yaml +``` + +## otx {subcommand} + +Use Configuration file + +```console +otx train --config --data_root +``` + +Override Parameters + +```console +otx train ... --model.num_classes --max_epochs +``` diff --git a/for_developers/dir_structure.md b/for_developers/dir_structure.md index e3fcb0de04e..18e5033e9ec 100644 --- a/for_developers/dir_structure.md +++ b/for_developers/dir_structure.md @@ -2,7 +2,7 @@ root/ algo/ # Custom algo (e.g., hierarchical_cls_head) cli/ # CLI entrypoints - config/ # Default YAML config files + engine/ # OTX Engine with Entry Point core/ config/ # Structured data type object for configurations data/ # Data related things @@ -17,9 +17,6 @@ root/ transform_libs/ # To support transform libraries (e.g., MMCV) factory.py # Factory to instantiate data related objects module.py # OTXDataModule - engine/ # PyTorchLightning engine - train.py - ... model/ # Model related things entity/ # OTXModel base.py @@ -32,6 +29,7 @@ root/ types/ # Enum definitions (e.g. OTXTaskType) utils/ # Utility functions recipe/ # Recipe YAML config for each model we support + _base_/ # Default YAML config files detection/ # (e.g., rtmdet_tiny) ... tools/ # Python runnable scripts for some TBD use cases diff --git a/for_developers/setup_guide.md b/for_developers/setup_guide.md index be1ce55e983..fa9162cd3ff 100644 --- a/for_developers/setup_guide.md +++ b/for_developers/setup_guide.md @@ -12,15 +12,11 @@ conda activate otx-v2 # Install PyTorch and TorchVision conda install pytorch torchvision torchaudio pytorch-cuda=11.8 -c pytorch -c nvidia -# Install core dependency -pip install lightning datumaro omegaconf hydra-core - -# Install mmcv (mmdet) -pip install -U openmim -mim install mmengine "mmcv>=2.0.0" mmdet - -# Install this package +# Install otx with core requirements pip install -e . + +# otx install (install mmX) +otx install -v ``` ### With PIP & 'otx install' @@ -37,12 +33,8 @@ pip install -e . otx --help # Install torch & lightning base on user environments -otx install -# or 'otx install -v' (Verbose mode) - -# Install other mmlab library or optional-dependencies -otx install --option dev -# or 'otx install --option mmpretrain' +otx install -v +# or 'otx install' (Not verbose mode) ``` Please see [requirements-lock.txt](requirements-lock.txt). This is what I got after the above installation steps by `pip freeze`. @@ -52,31 +44,25 @@ Please see [requirements-lock.txt](requirements-lock.txt). This is what I got af - Launch detection task ATSS-R50-FPN template ```console - otx train +recipe=detection/atss_r50_fpn base.data_dir=tests/assets/car_tree_bug model.otx_model.config.bbox_head.num_classes=3 trainer.max_epochs=50 trainer.check_val_every_n_epoch=10 trainer=gpu base.work_dir=outputs/test_work_dir base.output_dir=outputs/test_output_dir + otx train --config src/otx/recipe/detection/atss_r50_fpn.yaml --data_root tests/assets/car_tree_bug --model.num_classes=3 --max_epochs=50 --check_val_every_n_epoch=10 --engine.device gpu --engine.work_dir ./otx-workspace ``` - Change subset names, e.g., "train" -> "train_16" (for training) ```console - otx train ... data.train_subset.subset_name= data.val_subset.subset_name= data.test_subset.subset_name= - ``` - -- Do test with the best validation model checkpoint - - ```console - otx train ... test=true + otx train ... --data.config.train_subset.subset_name --data.config.val_subset.subset_name --data.config.test_subset.subset_name ``` - Do train with the existing model checkpoint for resume ```console - otx train ... checkpoint= + otx train ... --checkpoint ``` - Do experiment with deterministic operations and the fixed seed ```console - otx train ... trainer.deterministic=True seed= + otx train ... --deterministic True --seed ``` - Do test with the existing model checkpoint @@ -85,4 +71,4 @@ Please see [requirements-lock.txt](requirements-lock.txt). This is what I got af otx test ... checkpoint= ``` - `trainer.deterministic=True` might affect to the model performance. Please see [this link](https://lightning.ai/docs/pytorch/stable/common/trainer.html#deterministic). Therefore, it is not recommended to turn on this option for the model performance comparison. + `--deterministic True` might affect to the model performance. Please see [this link](https://lightning.ai/docs/pytorch/stable/common/trainer.html#deterministic). Therefore, it is not recommended to turn on this option for the model performance comparison.