From 0abdf10828f416b403e3ffd97792b42e4f5c1965 Mon Sep 17 00:00:00 2001 From: kprokofi Date: Sun, 14 Jan 2024 23:05:38 +0900 Subject: [PATCH 01/42] add raising an error when metric is None --- src/otx/core/model/module/action_classification.py | 4 ++++ src/otx/core/model/module/action_detection.py | 4 ++++ src/otx/core/model/module/classification.py | 4 ++++ src/otx/core/model/module/detection.py | 4 ++++ src/otx/core/model/module/instance_segmentation.py | 4 ++++ src/otx/core/model/module/segmentation.py | 9 ++++++--- 6 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/otx/core/model/module/action_classification.py b/src/otx/core/model/module/action_classification.py index a1b2206f71b..e69b038360a 100644 --- a/src/otx/core/model/module/action_classification.py +++ b/src/otx/core/model/module/action_classification.py @@ -49,6 +49,10 @@ def on_test_epoch_end(self) -> None: def _log_metrics(self, meter: Accuracy, key: str) -> None: results = meter.compute() + if results is None: + msg = f"{meter} has no data to compute metric or there is an error computing metric" + raise RuntimeError(msg) + self.log("accuracy", results.item(), sync_dist=True, prog_bar=True) def validation_step(self, inputs: ActionClsBatchDataEntity, batch_idx: int) -> None: diff --git a/src/otx/core/model/module/action_detection.py b/src/otx/core/model/module/action_detection.py index 037e7467c21..e196c522ddc 100644 --- a/src/otx/core/model/module/action_detection.py +++ b/src/otx/core/model/module/action_detection.py @@ -50,6 +50,10 @@ def on_test_epoch_end(self) -> None: def _log_metrics(self, meter: MeanAveragePrecision, key: str) -> None: results = meter.compute() + if results is None: + msg = f"{meter} has no data to compute metric or there is an error computing metric" + raise RuntimeError(msg) + for k, v in results.items(): if not isinstance(v, Tensor): log.debug("Cannot log item which is not Tensor") diff --git a/src/otx/core/model/module/classification.py b/src/otx/core/model/module/classification.py index 97a22cf5189..427e5a6b55d 100644 --- a/src/otx/core/model/module/classification.py +++ b/src/otx/core/model/module/classification.py @@ -61,6 +61,10 @@ def on_test_epoch_end(self) -> None: def _log_metrics(self, meter: Accuracy, key: str) -> None: results = meter.compute() + if results is None: + msg = f"{meter} has no data to compute metric or there is an error computing metric" + raise RuntimeError(msg) + self.log(f"{key}/accuracy", results.item(), sync_dist=True, prog_bar=True) def validation_step(self, inputs: MulticlassClsBatchDataEntity, batch_idx: int) -> None: diff --git a/src/otx/core/model/module/detection.py b/src/otx/core/model/module/detection.py index 8e23bf9629e..20a65a76579 100644 --- a/src/otx/core/model/module/detection.py +++ b/src/otx/core/model/module/detection.py @@ -51,6 +51,10 @@ def on_test_epoch_end(self) -> None: def _log_metrics(self, meter: MeanAveragePrecision, key: str) -> None: results = meter.compute() + if results is None: + msg = f"{meter} has no data to compute metric or there is an error computing metric" + raise RuntimeError(msg) + for k, v in results.items(): if not isinstance(v, Tensor): log.debug("Cannot log item which is not Tensor") diff --git a/src/otx/core/model/module/instance_segmentation.py b/src/otx/core/model/module/instance_segmentation.py index 8f0fe95d647..91ec7ff8cac 100644 --- a/src/otx/core/model/module/instance_segmentation.py +++ b/src/otx/core/model/module/instance_segmentation.py @@ -55,6 +55,10 @@ def on_test_epoch_end(self) -> None: def _log_metrics(self, meter: MeanAveragePrecision, subset_name: str) -> None: results = meter.compute() + if results is None: + msg = f"{meter} has no data to compute metric or there is an error computing metric" + raise RuntimeError(msg) + for metric, value in results.items(): if not isinstance(value, Tensor): log.debug("Cannot log item which is not Tensor") diff --git a/src/otx/core/model/module/segmentation.py b/src/otx/core/model/module/segmentation.py index 9e29de93f7c..84e92695482 100644 --- a/src/otx/core/model/module/segmentation.py +++ b/src/otx/core/model/module/segmentation.py @@ -62,6 +62,9 @@ def on_test_epoch_end(self) -> None: def _log_metrics(self, meter: JaccardIndex, key: str) -> None: results = meter.compute() + if results is None: + msg = f"{meter} has no data to compute metric or there is an error computing metric" + raise RuntimeError(msg) if isinstance(results, Tensor): if results.numel() != 1: @@ -88,9 +91,9 @@ def validation_step(self, inputs: SegBatchDataEntity, batch_idx: int) -> None: if not isinstance(preds, SegBatchPredEntity): raise TypeError(preds) - pred_list = self._convert_pred_entity_to_compute_metric(preds, inputs) - for prediction in pred_list: - self.test_metric.update(**prediction) + predictions = self._convert_pred_entity_to_compute_metric(preds, inputs) + for prediction in predictions: + self.val_metric.update(**prediction) def _convert_pred_entity_to_compute_metric( self, From 96104fc42a133b9b0a243b5ac90e6eecfd373594 Mon Sep 17 00:00:00 2001 From: kprokofi Date: Wed, 13 Mar 2024 05:48:04 +0900 Subject: [PATCH 02/42] added accelerators --- src/otx/algo/__init__.py | 4 +- src/otx/algo/accelerators/__init__.py | 8 ++ src/otx/algo/accelerators/xpu.py | 60 ++++++++++ src/otx/algo/plugins/__init__.py | 8 ++ src/otx/algo/plugins/xpu_precision.py | 110 ++++++++++++++++++ src/otx/algo/strategies/__init__.py | 8 ++ src/otx/algo/strategies/xpu_single.py | 60 ++++++++++ src/otx/core/model/module/base.py | 1 + src/otx/core/types/device.py | 3 +- src/otx/engine/engine.py | 5 + .../efficientnet_b0_light.yaml | 2 +- src/otx/utils/utils.py | 16 +++ 12 files changed, 281 insertions(+), 4 deletions(-) create mode 100644 src/otx/algo/accelerators/__init__.py create mode 100644 src/otx/algo/accelerators/xpu.py create mode 100644 src/otx/algo/plugins/__init__.py create mode 100644 src/otx/algo/plugins/xpu_precision.py create mode 100644 src/otx/algo/strategies/__init__.py create mode 100644 src/otx/algo/strategies/xpu_single.py diff --git a/src/otx/algo/__init__.py b/src/otx/algo/__init__.py index 968d579e5f7..417fd5fb4f8 100644 --- a/src/otx/algo/__init__.py +++ b/src/otx/algo/__init__.py @@ -3,6 +3,6 @@ # """Module for OTX custom algorithms, e.g., model, losses, hook, etc...""" -from . import action_classification, classification, detection, segmentation, visual_prompting +from . import action_classification, classification, detection, segmentation, visual_prompting, strategies, accelerators, plugins -__all__ = ["action_classification", "classification", "detection", "segmentation", "visual_prompting"] +__all__ = ["action_classification", "classification", "detection", "segmentation", "visual_prompting", "strategies", "accelerators", "plugins"] diff --git a/src/otx/algo/accelerators/__init__.py b/src/otx/algo/accelerators/__init__.py new file mode 100644 index 00000000000..d9d8844a02e --- /dev/null +++ b/src/otx/algo/accelerators/__init__.py @@ -0,0 +1,8 @@ +# Copyright (C) 2024 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# +"""Lightning accelerator for XPU device.""" + +from .xpu import XPUAccelerator + +__all__ = ["XPUAccelerator"] \ No newline at end of file diff --git a/src/otx/algo/accelerators/xpu.py b/src/otx/algo/accelerators/xpu.py new file mode 100644 index 00000000000..631db2bb6a6 --- /dev/null +++ b/src/otx/algo/accelerators/xpu.py @@ -0,0 +1,60 @@ +"""Lightning accelerator for XPU device.""" +# Copyright (C) 2023 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# + +from typing import Any, Dict, Union + +import torch +from lightning.accelerators import AcceleratorRegistry +from lightning.pytorch.accelerators.accelerator import Accelerator + +from otx.utils.utils import is_xpu_available + + +class XPUAccelerator(Accelerator): + """Support for a XPU, optimized for large-scale machine learning.""" + + accelerator_name = "xpu" + + def setup_device(self, device: torch.device) -> None: + """Sets up the specified device.""" + if device.type != "xpu": + raise RuntimeError(f"Device should be xpu, got {device} instead") + + torch.xpu.set_device(device) + + @staticmethod + def parse_devices(devices: Any) -> Any: + """Parses devices for multi-GPU training.""" + if isinstance(devices, list): + return devices + return [devices] + + @staticmethod + def get_parallel_devices(devices: Any) -> Any: + """Generates a list of parrallel devices.""" + return [torch.device("xpu", idx) for idx in devices] + + @staticmethod + def auto_device_count() -> int: + """Returns number of XPU devices available.""" + return torch.xpu.device_count() + + @staticmethod + def is_available() -> bool: + """Checks if XPU available.""" + return is_xpu_available() + + def get_device_stats(self, device: Union[str, torch.device]) -> Dict[str, Any]: + """Returns XPU devices stats.""" + return {} + + def teardown(self) -> None: + """Cleans-up XPU-related resources.""" + pass + + +AcceleratorRegistry.register( + XPUAccelerator.accelerator_name, XPUAccelerator, description="Accelerator supports XPU devices" +) diff --git a/src/otx/algo/plugins/__init__.py b/src/otx/algo/plugins/__init__.py new file mode 100644 index 00000000000..91be640aea6 --- /dev/null +++ b/src/otx/algo/plugins/__init__.py @@ -0,0 +1,8 @@ +# Copyright (C) 2024 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# +"""Plugin for mixed-precision training on XPU.""" + +from .xpu_precision import MixedPrecisionXPUPlugin + +__all__ = ["MixedPrecisionXPUPlugin"] diff --git a/src/otx/algo/plugins/xpu_precision.py b/src/otx/algo/plugins/xpu_precision.py new file mode 100644 index 00000000000..cd54253ae67 --- /dev/null +++ b/src/otx/algo/plugins/xpu_precision.py @@ -0,0 +1,110 @@ +# Copyright (C) 2024 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# +"""Plugin for mixed-precision training on XPU.""" + + +from contextlib import contextmanager +from typing import Any, Callable, Dict, Generator, Optional, Union + +import pytorch_lightning as pl +import torch +from lightning_fabric.utilities.types import Optimizable +from pytorch_lightning.plugins.precision.precision_plugin import PrecisionPlugin +from pytorch_lightning.utilities import GradClipAlgorithmType +from pytorch_lightning.utilities.exceptions import MisconfigurationException +from torch import Tensor +from torch.optim import LBFGS, Optimizer + + +class MixedPrecisionXPUPlugin(PrecisionPlugin): + """Plugin for Automatic Mixed Precision (AMP) training with ``torch.xpu.autocast``. + + Args: + scaler: An optional :class:`torch.cuda.amp.GradScaler` to use. + """ + + def __init__(self, scaler: Optional[Any] = None) -> None: + self.scaler = scaler + + def pre_backward(self, tensor: Tensor, module: "pl.LightningModule") -> Tensor: + """Apply grad scaler before backward.""" + if self.scaler is not None: + tensor = self.scaler.scale(tensor) + return super().pre_backward(tensor, module) + + def optimizer_step( # type: ignore[override] + self, + optimizer: Optimizable, + model: "pl.LightningModule", + optimizer_idx: int, + closure: Callable[[], Any], + **kwargs: Any, + ) -> Any: + """Make an optimizer step using scaler if it was passed.""" + if self.scaler is None: + # skip scaler logic, as bfloat16 does not require scaler + return super().optimizer_step( + optimizer, model=model, optimizer_idx=optimizer_idx, closure=closure, **kwargs + ) + if isinstance(optimizer, LBFGS): + raise MisconfigurationException( + f"Native AMP and the LBFGS optimizer are not compatible (optimizer {optimizer_idx})." + ) + closure_result = closure() + + if not _optimizer_handles_unscaling(optimizer): + # Unscaling needs to be performed here in case we are going to apply gradient clipping. + # Optimizers that perform unscaling in their `.step()` method are not supported (e.g., fused Adam). + # Note: `unscale` happens after the closure is executed, but before the `on_before_optimizer_step` hook. + self.scaler.unscale_(optimizer) + + self._after_closure(model, optimizer, optimizer_idx) + skipped_backward = closure_result is None + # in manual optimization, the closure does not return a value + if not model.automatic_optimization or not skipped_backward: + # note: the scaler will skip the `optimizer.step` if nonfinite gradients are found + step_output = self.scaler.step(optimizer, **kwargs) + self.scaler.update() + return step_output + return closure_result + + def clip_gradients( + self, + optimizer: Optimizer, + clip_val: Union[int, float] = 0.0, + gradient_clip_algorithm: GradClipAlgorithmType = GradClipAlgorithmType.NORM, + ) -> None: + """Handle grad clipping with scaler.""" + if clip_val > 0 and _optimizer_handles_unscaling(optimizer): + raise RuntimeError( + f"The current optimizer, {type(optimizer).__qualname__}, does not allow for gradient clipping" + " because it performs unscaling of gradients internally. HINT: Are you using a 'fused' optimizer?" + ) + super().clip_gradients(optimizer=optimizer, clip_val=clip_val, gradient_clip_algorithm=gradient_clip_algorithm) + + @contextmanager + def forward_context(self) -> Generator[None, None, None]: + """Enable autocast context.""" + with torch.xpu.autocast(True): + yield + + def state_dict(self) -> Dict[str, Any]: + """Returns state dict of the plugin.""" + if self.scaler is not None: + return self.scaler.state_dict() + return {} + + def load_state_dict(self, state_dict: Dict[str, Any]) -> None: + """Loads state dict to the plugin.""" + if self.scaler is not None: + self.scaler.load_state_dict(state_dict) + + +def _optimizer_handles_unscaling(optimizer: Any) -> bool: + """Determines if a PyTorch optimizer handles unscaling gradients in the step method ratherthan through the scaler. + + Since, the current implementation of this function checks a PyTorch internal variable on the optimizer, the return + value will only be reliable for built-in PyTorch optimizers. + """ + return getattr(optimizer, "_step_supports_amp_scaling", False) diff --git a/src/otx/algo/strategies/__init__.py b/src/otx/algo/strategies/__init__.py new file mode 100644 index 00000000000..392a1b82b22 --- /dev/null +++ b/src/otx/algo/strategies/__init__.py @@ -0,0 +1,8 @@ +# Copyright (C) 2024 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# +"""Lightning strategy for single XPU device.""" + +from .xpu_single import SingleXPUStrategy + +__all__ = ["SingleXPUStrategy"] diff --git a/src/otx/algo/strategies/xpu_single.py b/src/otx/algo/strategies/xpu_single.py new file mode 100644 index 00000000000..f8a1d4e5217 --- /dev/null +++ b/src/otx/algo/strategies/xpu_single.py @@ -0,0 +1,60 @@ +"""Lightning strategy for single XPU device.""" + +# Copyright (C) 2023 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# + +from typing import Optional + +import pytorch_lightning as pl +import torch +from lightning_fabric.plugins import CheckpointIO +from lightning_fabric.utilities.types import _DEVICE +from lightning.plugins.precision import PrecisionPlugin +from lightning.strategies import StrategyRegistry +from lightning.strategies.single_device import SingleDeviceStrategy +from lightning.utilities.exceptions import MisconfigurationException + +from otx.utils.utils import is_xpu_available + + +class SingleXPUStrategy(SingleDeviceStrategy): + """Strategy for training on single XPU device.""" + + strategy_name = "xpu_single" + + def __init__( + self, + device: _DEVICE = "xpu:0", + accelerator: Optional["pl.accelerators.Accelerator"] = None, + checkpoint_io: Optional[CheckpointIO] = None, + precision_plugin: Optional[PrecisionPlugin] = None, + ): + if not is_xpu_available(): + raise MisconfigurationException("`SingleXPUStrategy` requires XPU devices to run") + + super().__init__( + accelerator=accelerator, + device=device, + checkpoint_io=checkpoint_io, + precision_plugin=precision_plugin, + ) + + @property + def is_distributed(self) -> bool: + """Returns true if the strategy supports distributed training.""" + return False + + def setup_optimizers(self, trainer: "pl.Trainer") -> None: + """Sets up optimizers.""" + super().setup_optimizers(trainer) + if len(self.optimizers) != 1: # type: ignore + raise RuntimeError("XPU strategy doesn't support multiple optimizers") + model, optimizer = torch.xpu.optimize(trainer.model, optimizer=self.optimizers[0]) # type: ignore + self.optimizers = [optimizer] + trainer.model = model + + +StrategyRegistry.register( + SingleXPUStrategy.strategy_name, SingleXPUStrategy, description="Strategy that enables training on single XPU" +) diff --git a/src/otx/core/model/module/base.py b/src/otx/core/model/module/base.py index c573cad2cbd..6aa9bd7b51c 100644 --- a/src/otx/core/model/module/base.py +++ b/src/otx/core/model/module/base.py @@ -60,6 +60,7 @@ def __init__( def training_step(self, inputs: OTXBatchDataEntity, batch_idx: int) -> Tensor: """Step for model training.""" + train_loss = self.model(inputs) if isinstance(train_loss, Tensor): diff --git a/src/otx/core/types/device.py b/src/otx/core/types/device.py index 0d11e0393f7..bd87a5721df 100644 --- a/src/otx/core/types/device.py +++ b/src/otx/core/types/device.py @@ -10,7 +10,7 @@ class DeviceType(str, Enum): """OTX Device type definition.""" - # ("cpu", "gpu", "tpu", "ipu", "hpu", "mps", "auto") + # ("cpu", "gpu", "tpu", "ipu", "hpu", "mps", "xpu", "auto") auto = "auto" gpu = "gpu" @@ -19,3 +19,4 @@ class DeviceType(str, Enum): ipu = "ipu" hpu = "hpu" mps = "mps" + xpu = "xpu" diff --git a/src/otx/engine/engine.py b/src/otx/engine/engine.py index 48daf0b760b..5f16242e627 100644 --- a/src/otx/engine/engine.py +++ b/src/otx/engine/engine.py @@ -40,6 +40,8 @@ from otx.core.metrics import MetricCallable + + LITMODULE_PER_TASK = { OTXTaskType.MULTI_CLASS_CLS: "otx.core.model.module.classification.OTXMulticlassClsLitModule", OTXTaskType.MULTI_LABEL_CLS: "otx.core.model.module.classification.OTXMultilabelClsLitModule", @@ -740,6 +742,9 @@ def _build_trainer(self, **kwargs) -> None: if self._cache.requires_update(**kwargs) or self._trainer is None: self._cache.update(**kwargs) kwargs = self._cache.args + # breakpoint() + # kwargs["strategy"] = "single_xpu" + # kwargs["accelerator"] = "xpu" self._trainer = Trainer(**kwargs) self.work_dir = self._trainer.default_root_dir 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 index f943fa1485e..0fba0f31437 100644 --- a/src/otx/recipe/classification/multi_class_cls/efficientnet_b0_light.yaml +++ b/src/otx/recipe/classification/multi_class_cls/efficientnet_b0_light.yaml @@ -27,7 +27,7 @@ metric: engine: task: MULTI_CLASS_CLS - device: auto + device: xpu callback_monitor: val/accuracy diff --git a/src/otx/utils/utils.py b/src/otx/utils/utils.py index 89cf03a2c79..80896a72e43 100644 --- a/src/otx/utils/utils.py +++ b/src/otx/utils/utils.py @@ -6,11 +6,19 @@ from __future__ import annotations from decimal import Decimal +import torch from typing import TYPE_CHECKING, Any if TYPE_CHECKING: from pathlib import Path +XPU_AVAILABLE = None +try: + import intel_extension_for_pytorch as ipex +except ImportError: + XPU_AVAILABLE = False + ipex = None + def get_using_dot_delimited_key(key: str, target: Any) -> Any: # noqa: ANN401 """Get values of attribute in target object using dot delimited key. @@ -114,3 +122,11 @@ def remove_matched_files(directory: Path, pattern: str, file_to_leave: Path | No for weight in directory.rglob(pattern): if weight != file_to_leave: weight.unlink() + + +def is_xpu_available() -> bool: + """Checks if XPU device is available.""" + global XPU_AVAILABLE # noqa: PLW0603 + if XPU_AVAILABLE is None: + XPU_AVAILABLE = hasattr(torch, "xpu") and torch.xpu.is_available() + return XPU_AVAILABLE From d09392cde1e094209e19918717d37006395476a3 Mon Sep 17 00:00:00 2001 From: kprokofi Date: Wed, 13 Mar 2024 06:06:55 +0900 Subject: [PATCH 03/42] fix packages --- src/otx/algo/accelerators/xpu.py | 2 +- src/otx/algo/strategies/xpu_single.py | 10 +++++----- src/otx/engine/engine.py | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/otx/algo/accelerators/xpu.py b/src/otx/algo/accelerators/xpu.py index 631db2bb6a6..1b615026d4c 100644 --- a/src/otx/algo/accelerators/xpu.py +++ b/src/otx/algo/accelerators/xpu.py @@ -6,7 +6,7 @@ from typing import Any, Dict, Union import torch -from lightning.accelerators import AcceleratorRegistry +from lightning.pytorch.accelerators import AcceleratorRegistry from lightning.pytorch.accelerators.accelerator import Accelerator from otx.utils.utils import is_xpu_available diff --git a/src/otx/algo/strategies/xpu_single.py b/src/otx/algo/strategies/xpu_single.py index f8a1d4e5217..83d580de411 100644 --- a/src/otx/algo/strategies/xpu_single.py +++ b/src/otx/algo/strategies/xpu_single.py @@ -6,14 +6,14 @@ from typing import Optional -import pytorch_lightning as pl +import lightning.pytorch as pl import torch from lightning_fabric.plugins import CheckpointIO from lightning_fabric.utilities.types import _DEVICE -from lightning.plugins.precision import PrecisionPlugin -from lightning.strategies import StrategyRegistry -from lightning.strategies.single_device import SingleDeviceStrategy -from lightning.utilities.exceptions import MisconfigurationException +from lightning.pytorch.plugins.precision import PrecisionPlugin +from lightning.pytorch.strategies import StrategyRegistry +from lightning.pytorch.strategies.single_device import SingleDeviceStrategy +from lightning.pytorch.utilities.exceptions import MisconfigurationException from otx.utils.utils import is_xpu_available diff --git a/src/otx/engine/engine.py b/src/otx/engine/engine.py index 5f16242e627..aecb2988323 100644 --- a/src/otx/engine/engine.py +++ b/src/otx/engine/engine.py @@ -743,8 +743,8 @@ def _build_trainer(self, **kwargs) -> None: self._cache.update(**kwargs) kwargs = self._cache.args # breakpoint() - # kwargs["strategy"] = "single_xpu" - # kwargs["accelerator"] = "xpu" + kwargs["strategy"] = "xpu_single" + kwargs["accelerator"] = "xpu" self._trainer = Trainer(**kwargs) self.work_dir = self._trainer.default_root_dir From 8c59e04e73aa9c9cce36d6cb5e380394ee36b00c Mon Sep 17 00:00:00 2001 From: Emily Date: Wed, 13 Mar 2024 15:10:07 +0000 Subject: [PATCH 04/42] fix assigning model --- src/otx/algo/strategies/xpu_single.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/otx/algo/strategies/xpu_single.py b/src/otx/algo/strategies/xpu_single.py index 83d580de411..f51634ec4e8 100644 --- a/src/otx/algo/strategies/xpu_single.py +++ b/src/otx/algo/strategies/xpu_single.py @@ -52,7 +52,7 @@ def setup_optimizers(self, trainer: "pl.Trainer") -> None: raise RuntimeError("XPU strategy doesn't support multiple optimizers") model, optimizer = torch.xpu.optimize(trainer.model, optimizer=self.optimizers[0]) # type: ignore self.optimizers = [optimizer] - trainer.model = model + self.model = model StrategyRegistry.register( From 57b0f33512471a16b9985902b9010a6f4a60391c Mon Sep 17 00:00:00 2001 From: kprokofi Date: Thu, 14 Mar 2024 00:07:00 +0900 Subject: [PATCH 05/42] debug on MAX --- src/otx/algo/plugins/xpu_precision.py | 8 ++++---- src/otx/core/model/module/base.py | 1 + src/otx/core/model/module/classification.py | 1 + src/otx/core/model/module/detection.py | 1 + src/otx/engine/engine.py | 10 +++++++--- .../multi_class_cls/efficientnet_b0_light.yaml | 2 +- 6 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/otx/algo/plugins/xpu_precision.py b/src/otx/algo/plugins/xpu_precision.py index cd54253ae67..fd4e9b6d43a 100644 --- a/src/otx/algo/plugins/xpu_precision.py +++ b/src/otx/algo/plugins/xpu_precision.py @@ -7,12 +7,12 @@ from contextlib import contextmanager from typing import Any, Callable, Dict, Generator, Optional, Union -import pytorch_lightning as pl +import lightning.pytorch as pl import torch from lightning_fabric.utilities.types import Optimizable -from pytorch_lightning.plugins.precision.precision_plugin import PrecisionPlugin -from pytorch_lightning.utilities import GradClipAlgorithmType -from pytorch_lightning.utilities.exceptions import MisconfigurationException +from lightning.pytorch.plugins.precision import PrecisionPlugin +from lightning.pytorch.utilities import GradClipAlgorithmType +from lightning.pytorch.utilities.exceptions import MisconfigurationException from torch import Tensor from torch.optim import LBFGS, Optimizer diff --git a/src/otx/core/model/module/base.py b/src/otx/core/model/module/base.py index 6aa9bd7b51c..4d65ec59f7d 100644 --- a/src/otx/core/model/module/base.py +++ b/src/otx/core/model/module/base.py @@ -62,6 +62,7 @@ def training_step(self, inputs: OTXBatchDataEntity, batch_idx: int) -> Tensor: """Step for model training.""" train_loss = self.model(inputs) + print(train_loss["loss_bbox"].device, inputs.images.device, self.device) if isinstance(train_loss, Tensor): self.log( diff --git a/src/otx/core/model/module/classification.py b/src/otx/core/model/module/classification.py index 4f7eedd9d02..0bc92aa06eb 100644 --- a/src/otx/core/model/module/classification.py +++ b/src/otx/core/model/module/classification.py @@ -81,6 +81,7 @@ def validation_step(self, inputs: MulticlassClsBatchDataEntity, batch_idx: int) :param batch_idx: The index of the current batch. """ preds = self.model(inputs) + print(inputs.images.device, self.device, preds.scores[0].device) if not isinstance(preds, (MulticlassClsBatchPredEntity, MulticlassClsBatchPredEntityWithXAI)): raise TypeError(preds) diff --git a/src/otx/core/model/module/detection.py b/src/otx/core/model/module/detection.py index 8d5ea504ad0..c8a51062162 100644 --- a/src/otx/core/model/module/detection.py +++ b/src/otx/core/model/module/detection.py @@ -98,6 +98,7 @@ def validation_step(self, inputs: DetBatchDataEntity, batch_idx: int) -> None: :param batch_idx: The index of the current batch. """ preds = self.model(inputs) + print(inputs.images.device, self.device, preds.scores[0].device) if not isinstance(preds, (DetBatchPredEntity, DetBatchPredEntityWithXAI)): raise TypeError(preds) diff --git a/src/otx/engine/engine.py b/src/otx/engine/engine.py index aecb2988323..b6d1b77401a 100644 --- a/src/otx/engine/engine.py +++ b/src/otx/engine/engine.py @@ -25,6 +25,7 @@ from otx.core.types.precision import OTXPrecisionType from otx.core.types.task import OTXTaskType from otx.core.utils.cache import TrainerArgumentsCache +from otx.algo.plugins import MixedPrecisionXPUPlugin from .hpo import execute_hpo, update_hyper_parameter from .utils.auto_configurator import AutoConfigurator @@ -741,10 +742,13 @@ 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) + # set up xpu device + if self._device.accelerator == DeviceType.xpu: + self._cache.update(strategy="xpu_single") + # add plugin for Automatic Mixed Precision on XPU + if kwargs["precision"] == 16: + self._cache.update(plugins=[MixedPrecisionXPUPlugin()]) kwargs = self._cache.args - # breakpoint() - kwargs["strategy"] = "xpu_single" - kwargs["accelerator"] = "xpu" self._trainer = Trainer(**kwargs) self.work_dir = self._trainer.default_root_dir 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 index 0fba0f31437..f943fa1485e 100644 --- a/src/otx/recipe/classification/multi_class_cls/efficientnet_b0_light.yaml +++ b/src/otx/recipe/classification/multi_class_cls/efficientnet_b0_light.yaml @@ -27,7 +27,7 @@ metric: engine: task: MULTI_CLASS_CLS - device: xpu + device: auto callback_monitor: val/accuracy From 1471fbbf825b804c57e28ce3647b4e713df059ee Mon Sep 17 00:00:00 2001 From: kprokofi Date: Thu, 14 Mar 2024 00:17:28 +0900 Subject: [PATCH 06/42] change precision --- src/otx/engine/engine.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/otx/engine/engine.py b/src/otx/engine/engine.py index b6d1b77401a..62b326ea1eb 100644 --- a/src/otx/engine/engine.py +++ b/src/otx/engine/engine.py @@ -748,6 +748,8 @@ def _build_trainer(self, **kwargs) -> None: # add plugin for Automatic Mixed Precision on XPU if kwargs["precision"] == 16: self._cache.update(plugins=[MixedPrecisionXPUPlugin()]) + self._cache.update(precision=None) + kwargs = self._cache.args self._trainer = Trainer(**kwargs) self.work_dir = self._trainer.default_root_dir From 0a4a69a811ad900fa37a72f64f48c8e627412ed0 Mon Sep 17 00:00:00 2001 From: kprokofi Date: Thu, 14 Mar 2024 00:29:14 +0900 Subject: [PATCH 07/42] update MixedPrecisionXPUPlugin --- src/otx/algo/plugins/xpu_precision.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/otx/algo/plugins/xpu_precision.py b/src/otx/algo/plugins/xpu_precision.py index fd4e9b6d43a..8d078d7b810 100644 --- a/src/otx/algo/plugins/xpu_precision.py +++ b/src/otx/algo/plugins/xpu_precision.py @@ -10,14 +10,14 @@ import lightning.pytorch as pl import torch from lightning_fabric.utilities.types import Optimizable -from lightning.pytorch.plugins.precision import PrecisionPlugin +from lightning.pytorch.plugins.precision.precision import Precision from lightning.pytorch.utilities import GradClipAlgorithmType from lightning.pytorch.utilities.exceptions import MisconfigurationException from torch import Tensor from torch.optim import LBFGS, Optimizer -class MixedPrecisionXPUPlugin(PrecisionPlugin): +class MixedPrecisionXPUPlugin(Precision): """Plugin for Automatic Mixed Precision (AMP) training with ``torch.xpu.autocast``. Args: @@ -37,7 +37,6 @@ def optimizer_step( # type: ignore[override] self, optimizer: Optimizable, model: "pl.LightningModule", - optimizer_idx: int, closure: Callable[[], Any], **kwargs: Any, ) -> Any: @@ -45,11 +44,11 @@ def optimizer_step( # type: ignore[override] if self.scaler is None: # skip scaler logic, as bfloat16 does not require scaler return super().optimizer_step( - optimizer, model=model, optimizer_idx=optimizer_idx, closure=closure, **kwargs + optimizer, model=model, closure=closure, **kwargs ) if isinstance(optimizer, LBFGS): raise MisconfigurationException( - f"Native AMP and the LBFGS optimizer are not compatible (optimizer {optimizer_idx})." + f"Native AMP and the LBFGS optimizer are not compatible." ) closure_result = closure() @@ -59,7 +58,7 @@ def optimizer_step( # type: ignore[override] # Note: `unscale` happens after the closure is executed, but before the `on_before_optimizer_step` hook. self.scaler.unscale_(optimizer) - self._after_closure(model, optimizer, optimizer_idx) + self._after_closure(model, optimizer) skipped_backward = closure_result is None # in manual optimization, the closure does not return a value if not model.automatic_optimization or not skipped_backward: From d77b84b66d3ae74b4f445575ffa787192fcbe656 Mon Sep 17 00:00:00 2001 From: kprokofi Date: Wed, 13 Mar 2024 16:07:30 +0000 Subject: [PATCH 08/42] debug --- src/otx/core/model/module/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/otx/core/model/module/base.py b/src/otx/core/model/module/base.py index 4d65ec59f7d..89ca4a4ea6b 100644 --- a/src/otx/core/model/module/base.py +++ b/src/otx/core/model/module/base.py @@ -62,7 +62,7 @@ def training_step(self, inputs: OTXBatchDataEntity, batch_idx: int) -> Tensor: """Step for model training.""" train_loss = self.model(inputs) - print(train_loss["loss_bbox"].device, inputs.images.device, self.device) + print(train_loss[list(train_loss.keys())[0]].device, inputs.images.device, self.device) if isinstance(train_loss, Tensor): self.log( From 79ec10861a86451cea3f310c7ff48aaf4339e788 Mon Sep 17 00:00:00 2001 From: kprokofi Date: Thu, 14 Mar 2024 06:33:32 +0900 Subject: [PATCH 09/42] added monkey patching --- pyproject.toml | 5 +- src/otx/algo/detection/utils/__init__.py | 8 +++ .../algo/detection/utils/mmcv_patched_ops.py | 53 +++++++++++++++++++ src/otx/engine/engine.py | 8 +++ 4 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 src/otx/algo/detection/utils/__init__.py create mode 100644 src/otx/algo/detection/utils/mmcv_patched_ops.py diff --git a/pyproject.toml b/pyproject.toml index 09f521cbc57..5c765c693b1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -66,7 +66,10 @@ docs = [ "nbsphinx", ] base = [ - "torch==2.1.1", + "torch==2.1.0a0", + "torchvision==0.16.0a0", + "torchaudio==2.1.0a0", + "intel-extension-for-pytorch==2.1.10+xpu", "lightning==2.1.2", "pytorchcv", "timm", diff --git a/src/otx/algo/detection/utils/__init__.py b/src/otx/algo/detection/utils/__init__.py new file mode 100644 index 00000000000..c5ac0f3e450 --- /dev/null +++ b/src/otx/algo/detection/utils/__init__.py @@ -0,0 +1,8 @@ +# Copyright (C) 2023 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# +"""utils for detection task""" + +from .mmcv_patched_ops import monkey_patched_nms, monkey_patched_roi_align + +__all__ = ["monkey_patched_nms", "monkey_patched_roi_align"] diff --git a/src/otx/algo/detection/utils/mmcv_patched_ops.py b/src/otx/algo/detection/utils/mmcv_patched_ops.py new file mode 100644 index 00000000000..5c15cbcf767 --- /dev/null +++ b/src/otx/algo/detection/utils/mmcv_patched_ops.py @@ -0,0 +1,53 @@ +import torch +from torchvision.ops import nms as tv_nms +from torchvision.ops import roi_align as tv_roi_align +from mmcv.utils import ext_loader + +ext_module = ext_loader.load_ext("_ext", ["nms", "softnms", "nms_match", "nms_rotated", "nms_quadri"]) + + +def monkey_patched_nms(ctx, bboxes, scores, iou_threshold, offset, score_threshold, max_num): + """Runs MMCVs NMS with torchvision.nms, or forces NMS from MMCV to run on CPU.""" + is_filtering_by_score = score_threshold > 0 + if is_filtering_by_score: + valid_mask = scores > score_threshold + bboxes, scores = bboxes[valid_mask], scores[valid_mask] + valid_inds = torch.nonzero(valid_mask, as_tuple=False).squeeze(dim=1) + + if bboxes.dtype == torch.bfloat16: + bboxes = bboxes.to(torch.float32) + if scores.dtype == torch.bfloat16: + scores = scores.to(torch.float32) + + if offset == 0: + inds = tv_nms(bboxes, scores, float(iou_threshold)) + else: + device = bboxes.device + bboxes = bboxes.to("cpu") + scores = scores.to("cpu") + inds = ext_module.nms(bboxes, scores, iou_threshold=float(iou_threshold), offset=offset) + bboxes = bboxes.to(device) + scores = scores.to(device) + + if max_num > 0: + inds = inds[:max_num] + if is_filtering_by_score: + inds = valid_inds[inds] + return inds + + +def monkey_patched_roi_align(self, input, rois): + """Replaces MMCVs roi align with the one from torchvision. + + Args: + self: patched instance + input: NCHW images + rois: Bx5 boxes. First column is the index into N. The other 4 columns are xyxy. + """ + + if "aligned" in tv_roi_align.__code__.co_varnames: + return tv_roi_align(input, rois, self.output_size, self.spatial_scale, self.sampling_ratio, self.aligned) + else: + if self.aligned: + rois -= rois.new_tensor([0.0] + [0.5 / self.spatial_scale] * 4) + return tv_roi_align(input, rois, self.output_size, self.spatial_scale, self.sampling_ratio) diff --git a/src/otx/engine/engine.py b/src/otx/engine/engine.py index 62b326ea1eb..3ea76518440 100644 --- a/src/otx/engine/engine.py +++ b/src/otx/engine/engine.py @@ -138,6 +138,14 @@ def __init__( label_info=self._datamodule.label_info if self._datamodule is not None else None, ) ) + if self.task == OTXTaskType.DETECTION and self.device == DeviceType.xpu: + from mmcv.ops.nms import NMSop + from mmcv.ops.roi_align import RoIAlign + from otx.algo.detection.utils import monkey_patched_nms, monkey_patched_roi_align + + NMSop.forward = monkey_patched_nms + RoIAlign.forward = monkey_patched_roi_align + self.optimizer: list[OptimizerCallable] | OptimizerCallable | None = ( optimizer if optimizer is not None else self._auto_configurator.get_optimizer() ) From 1558295eb1980d59b5c2ef20b87c4a309f667315 Mon Sep 17 00:00:00 2001 From: kprokofi Date: Thu, 14 Mar 2024 06:36:21 +0900 Subject: [PATCH 10/42] minor --- 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 3ea76518440..2d27a2742bc 100644 --- a/src/otx/engine/engine.py +++ b/src/otx/engine/engine.py @@ -756,7 +756,7 @@ def _build_trainer(self, **kwargs) -> None: # add plugin for Automatic Mixed Precision on XPU if kwargs["precision"] == 16: self._cache.update(plugins=[MixedPrecisionXPUPlugin()]) - self._cache.update(precision=None) + self._cache.args["precision"] = None kwargs = self._cache.args self._trainer = Trainer(**kwargs) From d71492ac96bc450c548306acb0dd438ce38a3602 Mon Sep 17 00:00:00 2001 From: kprokofi Date: Thu, 14 Mar 2024 07:03:14 +0900 Subject: [PATCH 11/42] minor --- src/otx/core/model/module/base.py | 2 +- src/otx/engine/engine.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/otx/core/model/module/base.py b/src/otx/core/model/module/base.py index 4d65ec59f7d..89ca4a4ea6b 100644 --- a/src/otx/core/model/module/base.py +++ b/src/otx/core/model/module/base.py @@ -62,7 +62,7 @@ def training_step(self, inputs: OTXBatchDataEntity, batch_idx: int) -> Tensor: """Step for model training.""" train_loss = self.model(inputs) - print(train_loss["loss_bbox"].device, inputs.images.device, self.device) + print(train_loss[list(train_loss.keys())[0]].device, inputs.images.device, self.device) if isinstance(train_loss, Tensor): self.log( diff --git a/src/otx/engine/engine.py b/src/otx/engine/engine.py index 2d27a2742bc..033e2bdf001 100644 --- a/src/otx/engine/engine.py +++ b/src/otx/engine/engine.py @@ -138,7 +138,7 @@ def __init__( label_info=self._datamodule.label_info if self._datamodule is not None else None, ) ) - if self.task == OTXTaskType.DETECTION and self.device == DeviceType.xpu: + if self.task == OTXTaskType.DETECTION and self.device.accelerator == DeviceType.xpu: from mmcv.ops.nms import NMSop from mmcv.ops.roi_align import RoIAlign from otx.algo.detection.utils import monkey_patched_nms, monkey_patched_roi_align From bac7e72b75b641cb763688644ee51016ed9b5250 Mon Sep 17 00:00:00 2001 From: kprokofi Date: Fri, 15 Mar 2024 05:54:43 +0900 Subject: [PATCH 12/42] added patch for mmengine --- src/otx/engine/engine.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/otx/engine/engine.py b/src/otx/engine/engine.py index 033e2bdf001..81c81d072a4 100644 --- a/src/otx/engine/engine.py +++ b/src/otx/engine/engine.py @@ -138,11 +138,14 @@ def __init__( label_info=self._datamodule.label_info if self._datamodule is not None else None, ) ) - if self.task == OTXTaskType.DETECTION and self.device.accelerator == DeviceType.xpu: + if self.task == OTXTaskType.DETECTION: from mmcv.ops.nms import NMSop from mmcv.ops.roi_align import RoIAlign from otx.algo.detection.utils import monkey_patched_nms, monkey_patched_roi_align + from mmengine.structures import instance_data + instance_data.LongTypeTensor = [torch.LongTensor, torch.xpu.LongTensor] + instance_data.BoolTypeTensor = [torch.BoolTensor, torch.xpu.BoolTensor] NMSop.forward = monkey_patched_nms RoIAlign.forward = monkey_patched_roi_align From 0df569ad92a2bc83120da29d08b52a00643ac182 Mon Sep 17 00:00:00 2001 From: kprokofi Date: Fri, 15 Mar 2024 13:24:26 +0000 Subject: [PATCH 13/42] fix OD and IS --- src/otx/algo/detection/utils/mmcv_patched_ops.py | 1 + src/otx/engine/engine.py | 10 ++++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/otx/algo/detection/utils/mmcv_patched_ops.py b/src/otx/algo/detection/utils/mmcv_patched_ops.py index 5c15cbcf767..5cb6ca372f8 100644 --- a/src/otx/algo/detection/utils/mmcv_patched_ops.py +++ b/src/otx/algo/detection/utils/mmcv_patched_ops.py @@ -33,6 +33,7 @@ def monkey_patched_nms(ctx, bboxes, scores, iou_threshold, offset, score_thresho inds = inds[:max_num] if is_filtering_by_score: inds = valid_inds[inds] + print(inds) return inds diff --git a/src/otx/engine/engine.py b/src/otx/engine/engine.py index 81c81d072a4..d830ec59c88 100644 --- a/src/otx/engine/engine.py +++ b/src/otx/engine/engine.py @@ -7,7 +7,7 @@ import inspect from pathlib import Path -from typing import TYPE_CHECKING, Any, Iterable, Literal +from typing import TYPE_CHECKING, Any, Iterable, Literal, Union from warnings import warn import torch @@ -138,14 +138,16 @@ def __init__( label_info=self._datamodule.label_info if self._datamodule is not None else None, ) ) - if self.task == OTXTaskType.DETECTION: + if self.task in [OTXTaskType.DETECTION, OTXTaskType.INSTANCE_SEGMENTATION] and self.device.accelerator == "xpu": from mmcv.ops.nms import NMSop from mmcv.ops.roi_align import RoIAlign from otx.algo.detection.utils import monkey_patched_nms, monkey_patched_roi_align from mmengine.structures import instance_data + import numpy as np - instance_data.LongTypeTensor = [torch.LongTensor, torch.xpu.LongTensor] - instance_data.BoolTypeTensor = [torch.BoolTensor, torch.xpu.BoolTensor] + LongTypeTensor = Union[torch.LongTensor, torch.xpu.LongTensor] + BoolTypeTensor = Union[torch.BoolTensor, torch.xpu.BoolTensor] + instance_data.IndexType = Union[str, slice, int, list, np.ndarray, LongTypeTensor, BoolTypeTensor] NMSop.forward = monkey_patched_nms RoIAlign.forward = monkey_patched_roi_align From 1292d1ceaa4efe8a116756aa4dc7146142ba6bb9 Mon Sep 17 00:00:00 2001 From: kprokofi Date: Sat, 16 Mar 2024 00:56:07 +0900 Subject: [PATCH 14/42] benchmark debug --- src/otx/engine/engine.py | 10 +-- .../maskrcnn_efficientnetb2b_tile.yaml | 2 +- .../instance_segmentation/maskrcnn_r50.yaml | 2 +- .../maskrcnn_r50_tile.yaml | 2 +- .../rtmdet_inst_tiny.yaml | 2 +- tests/perf/benchmark.py | 1 + tests/perf/test_classification.py | 62 ++++++++++++++----- tests/perf/test_detection.py | 27 ++++++-- tests/perf/test_instance_segmentation.py | 12 ++-- tests/perf/test_semantic_segmentation.py | 33 +++++++--- 10 files changed, 111 insertions(+), 42 deletions(-) diff --git a/src/otx/engine/engine.py b/src/otx/engine/engine.py index 81c81d072a4..8691dbd69b6 100644 --- a/src/otx/engine/engine.py +++ b/src/otx/engine/engine.py @@ -7,7 +7,7 @@ import inspect from pathlib import Path -from typing import TYPE_CHECKING, Any, Iterable, Literal +from typing import TYPE_CHECKING, Any, Iterable, Literal, Union from warnings import warn import torch @@ -138,14 +138,16 @@ def __init__( label_info=self._datamodule.label_info if self._datamodule is not None else None, ) ) - if self.task == OTXTaskType.DETECTION: + if self.task in [OTXTaskType.DETECTION, OTXTaskType.INSTANCE_SEGMENTATION] and self.device.accelerator == "xpu": from mmcv.ops.nms import NMSop from mmcv.ops.roi_align import RoIAlign from otx.algo.detection.utils import monkey_patched_nms, monkey_patched_roi_align from mmengine.structures import instance_data + import numpy as np - instance_data.LongTypeTensor = [torch.LongTensor, torch.xpu.LongTensor] - instance_data.BoolTypeTensor = [torch.BoolTensor, torch.xpu.BoolTensor] + LongTypeTensor = Union[torch.LongTensor, torch.xpu.LongTensor] + BoolTypeTensor = Union[torch.BoolTensor, torch.xpu.BoolTensor] + instance_data.IndexType = Union[str, slice, int, list, LongTypeTensor, BoolTypeTensor, np.ndarray] NMSop.forward = monkey_patched_nms RoIAlign.forward = monkey_patched_roi_align diff --git a/src/otx/recipe/instance_segmentation/maskrcnn_efficientnetb2b_tile.yaml b/src/otx/recipe/instance_segmentation/maskrcnn_efficientnetb2b_tile.yaml index 93030f8cf59..7e8dd412bc9 100644 --- a/src/otx/recipe/instance_segmentation/maskrcnn_efficientnetb2b_tile.yaml +++ b/src/otx/recipe/instance_segmentation/maskrcnn_efficientnetb2b_tile.yaml @@ -37,7 +37,7 @@ callback_monitor: val/map_50 data: ../_base_/data/mmdet_base.yaml overrides: max_epochs: 100 - gradient_clip_val: 35.0 + # gradient_clip_val: 35.0 data: task: INSTANCE_SEGMENTATION config: diff --git a/src/otx/recipe/instance_segmentation/maskrcnn_r50.yaml b/src/otx/recipe/instance_segmentation/maskrcnn_r50.yaml index fc70a4c51fd..178bafb76c6 100644 --- a/src/otx/recipe/instance_segmentation/maskrcnn_r50.yaml +++ b/src/otx/recipe/instance_segmentation/maskrcnn_r50.yaml @@ -37,7 +37,7 @@ callback_monitor: val/map_50 data: ../_base_/data/mmdet_base.yaml overrides: max_epochs: 100 - gradient_clip_val: 35.0 + # gradient_clip_val: 35.0 data: task: INSTANCE_SEGMENTATION config: diff --git a/src/otx/recipe/instance_segmentation/maskrcnn_r50_tile.yaml b/src/otx/recipe/instance_segmentation/maskrcnn_r50_tile.yaml index 047b18e67e2..16d831fab56 100644 --- a/src/otx/recipe/instance_segmentation/maskrcnn_r50_tile.yaml +++ b/src/otx/recipe/instance_segmentation/maskrcnn_r50_tile.yaml @@ -37,7 +37,7 @@ callback_monitor: val/map_50 data: ../_base_/data/mmdet_base.yaml overrides: max_epochs: 100 - gradient_clip_val: 35.0 + # gradient_clip_val: 35.0 data: task: INSTANCE_SEGMENTATION config: diff --git a/src/otx/recipe/instance_segmentation/rtmdet_inst_tiny.yaml b/src/otx/recipe/instance_segmentation/rtmdet_inst_tiny.yaml index 486dbed5f63..f4656186c98 100644 --- a/src/otx/recipe/instance_segmentation/rtmdet_inst_tiny.yaml +++ b/src/otx/recipe/instance_segmentation/rtmdet_inst_tiny.yaml @@ -38,7 +38,7 @@ data: ../_base_/data/mmdet_base.yaml overrides: precision: 32 # 16/"16-true" does not work max_epochs: 100 - gradient_clip_val: 35.0 + # gradient_clip_val: 35.0 data: task: INSTANCE_SEGMENTATION config: diff --git a/tests/perf/benchmark.py b/tests/perf/benchmark.py index 1d85332b15a..37cfa83bd49 100644 --- a/tests/perf/benchmark.py +++ b/tests/perf/benchmark.py @@ -125,6 +125,7 @@ def run( num_repeat = self.num_repeat # Override by global setting for seed in range(num_repeat): + seed = 42 sub_work_dir = work_dir / str(seed) tags["seed"] = str(seed) extra_metrics = {} diff --git a/tests/perf/test_classification.py b/tests/perf/test_classification.py index 236fa07614e..19abc226e36 100644 --- a/tests/perf/test_classification.py +++ b/tests/perf/test_classification.py @@ -27,31 +27,58 @@ class TestPerfSingleLabelClassification(PerfTestBase): DATASET_TEST_CASES = [ Benchmark.Dataset( name=f"multiclass_CUB_small_{idx}", - path=Path("multiclass_classification/multiclass_CUB_small") / f"{idx}", + path=Path("classification/single_label/multiclass_CUB_small") / f"{idx}", size="small", data_format="imagenet_with_subset_dirs", num_classes=2, - num_repeat=5, + num_repeat=1, extra_overrides={}, ) for idx in (1, 2, 3) ] + [ Benchmark.Dataset( name="multiclass_CUB_medium", - path=Path("multiclass_classification/multiclass_CUB_medium"), + path=Path("classification/single_label/multiclass_CUB_medium"), size="medium", data_format="imagenet_with_subset_dirs", num_classes=67, - num_repeat=5, + num_repeat=1, extra_overrides={}, ), Benchmark.Dataset( name="multiclass_food101_large", - path=Path("multiclass_classification/multiclass_food101_large"), + path=Path("classification/single_label/multiclass_food101_large"), size="large", data_format="imagenet_with_subset_dirs", num_classes=20, - num_repeat=5, + num_repeat=1, + extra_overrides={}, + ), + Benchmark.Dataset( + name="cars", + path=Path("car_data/car_data"), + size="large", + data_format="imagenet_with_subset_dirs", + num_classes=196, + num_repeat=1, + extra_overrides={}, + ), + Benchmark.Dataset( + name="flowers", + path=Path("flowers"), + size="large", + data_format="imagenet_with_subset_dirs", + num_classes=102, + num_repeat=1, + extra_overrides={}, + ), + Benchmark.Dataset( + name="skin", + path=Path("skin"), + size="large", + data_format="imagenet_with_subset_dirs", + num_classes=14, + num_repeat=1, extra_overrides={}, ), ] @@ -87,6 +114,7 @@ def test_perf( fxt_dataset: Benchmark.Dataset, fxt_benchmark: Benchmark, ): + fxt_benchmark.accelerator = "gpu" self._test_perf( model=fxt_model, dataset=fxt_dataset, @@ -108,31 +136,31 @@ class TestPerfMultiLabelClassification(PerfTestBase): DATASET_TEST_CASES = [ Benchmark.Dataset( name=f"multilabel_CUB_small_{idx}", - path=Path("multilabel_classification/multilabel_CUB_small") / f"{idx}", + path=Path("classification/multi_label/multilabel_CUB_small") / f"{idx}", size="small", data_format="datumaro", num_classes=3, - num_repeat=5, + num_repeat=1, extra_overrides={}, ) for idx in (1, 2, 3) ] + [ Benchmark.Dataset( name="multilabel_CUB_medium", - path=Path("multilabel_classification/multilabel_CUB_medium"), + path=Path("classification/multi_label/multilabel_CUB_medium"), size="medium", data_format="datumaro", num_classes=68, - num_repeat=5, + num_repeat=1, extra_overrides={}, ), Benchmark.Dataset( name="multilabel_food101_large", - path=Path("multilabel_classification/multilabel_food101_large"), + path=Path("classification/multi_label/multilabel_food101_large"), size="large", data_format="datumaro", num_classes=21, - num_repeat=5, + num_repeat=1, extra_overrides={}, ), ] @@ -168,6 +196,7 @@ def test_perf( fxt_dataset: Benchmark.Dataset, fxt_benchmark: Benchmark, ): + fxt_benchmark.accelerator = "gpu" self._test_perf( model=fxt_model, dataset=fxt_dataset, @@ -189,11 +218,11 @@ class TestPerfHierarchicalLabelClassification(PerfTestBase): DATASET_TEST_CASES = [ Benchmark.Dataset( name=f"hlabel_CUB_small_{idx}", - path=Path("hlabel_classification/hlabel_CUB_small") / f"{idx}", + path=Path("classification/h_label/hlabel_CUB_small") / f"{idx}", size="small", data_format="datumaro", num_classes=6, - num_repeat=5, + num_repeat=1, extra_overrides={ "model.num_multiclass_heads": "3", "model.num_multilabel_classes": "0", @@ -203,11 +232,11 @@ class TestPerfHierarchicalLabelClassification(PerfTestBase): ] + [ Benchmark.Dataset( name="hlabel_CUB_medium", - path=Path("hlabel_classification/hlabel_CUB_medium"), + path=Path("classification/h_label/hlabel_CUB_medium"), size="medium", data_format="datumaro", num_classes=102, - num_repeat=5, + num_repeat=1, extra_overrides={ "model.num_multiclass_heads": "23", "model.num_multilabel_classes": "0", @@ -247,6 +276,7 @@ def test_perf( fxt_dataset: Benchmark.Dataset, fxt_benchmark: Benchmark, ): + fxt_benchmark.accelerator = "gpu" self._test_perf( model=fxt_model, dataset=fxt_dataset, diff --git a/tests/perf/test_detection.py b/tests/perf/test_detection.py index b86372862f2..70e0cd2892b 100644 --- a/tests/perf/test_detection.py +++ b/tests/perf/test_detection.py @@ -33,9 +33,9 @@ class TestPerfObjectDetection(PerfTestBase): size="small", data_format="coco", num_classes=1, - num_repeat=5, + num_repeat=1, extra_overrides={ - "deterministic": "True", + # "deterministic": "True", "metric": "otx.core.metrics.fmeasure.FMeasure", "callback_monitor": "val/f1-score", "scheduler.monitor": "val/f1-score", @@ -49,9 +49,9 @@ class TestPerfObjectDetection(PerfTestBase): size="medium", data_format="coco", num_classes=1, - num_repeat=5, + num_repeat=1, extra_overrides={ - "deterministic": "True", + # "deterministic": "True", "metric": "otx.core.metrics.fmeasure.FMeasure", "callback_monitor": "val/f1-score", "scheduler.monitor": "val/f1-score", @@ -63,9 +63,23 @@ class TestPerfObjectDetection(PerfTestBase): size="large", data_format="coco", num_classes=1, - num_repeat=5, + num_repeat=1, extra_overrides={ - "deterministic": "True", + # "deterministic": "True", + "metric": "otx.core.metrics.fmeasure.FMeasure", + "callback_monitor": "val/f1-score", + "scheduler.monitor": "val/f1-score", + }, + ), + Benchmark.Dataset( + name="pascal_tiny", + path=Path("pascal_tiny/coco_otx"), + size="large", + data_format="coco", + num_classes=20, + num_repeat=1, + extra_overrides={ + # "deterministic": "True", "metric": "otx.core.metrics.fmeasure.FMeasure", "callback_monitor": "val/f1-score", "scheduler.monitor": "val/f1-score", @@ -104,6 +118,7 @@ def test_perf( fxt_dataset: Benchmark.Dataset, fxt_benchmark: Benchmark, ): + fxt_benchmark.accelerator = "gpu" self._test_perf( model=fxt_model, dataset=fxt_dataset, diff --git a/tests/perf/test_instance_segmentation.py b/tests/perf/test_instance_segmentation.py index 20faa367460..d3afcd4310b 100644 --- a/tests/perf/test_instance_segmentation.py +++ b/tests/perf/test_instance_segmentation.py @@ -29,7 +29,7 @@ class TestPerfInstanceSegmentation(PerfTestBase): size="small", data_format="coco", num_classes=5, - num_repeat=5, + num_repeat=1, extra_overrides={ "deterministic": "True", "metric": "otx.core.metrics.fmeasure.FMeasure", @@ -45,7 +45,7 @@ class TestPerfInstanceSegmentation(PerfTestBase): size="medium", data_format="coco", num_classes=2, - num_repeat=5, + num_repeat=1, extra_overrides={ "deterministic": "True", "metric": "otx.core.metrics.fmeasure.FMeasure", @@ -59,7 +59,7 @@ class TestPerfInstanceSegmentation(PerfTestBase): size="large", data_format="coco", num_classes=1, - num_repeat=5, + num_repeat=1, extra_overrides={ "deterministic": "True", "metric": "otx.core.metrics.fmeasure.FMeasure", @@ -100,6 +100,7 @@ def test_perf( fxt_dataset: Benchmark.Dataset, fxt_benchmark: Benchmark, ): + fxt_benchmark.accelerator = "gpu" self._test_perf( model=fxt_model, dataset=fxt_dataset, @@ -124,7 +125,7 @@ class TestPerfTilingInstanceSegmentation(PerfTestBase): size="small", data_format="coco", num_classes=1, - num_repeat=5, + num_repeat=1, extra_overrides={ "deterministic": "True", "metric": "otx.core.metrics.fmeasure.FMeasure", @@ -140,7 +141,7 @@ class TestPerfTilingInstanceSegmentation(PerfTestBase): size="medium", data_format="coco", num_classes=1, - num_repeat=5, + num_repeat=1, extra_overrides={ "deterministic": "True", "metric": "otx.core.metrics.fmeasure.FMeasure", @@ -182,6 +183,7 @@ def test_perf( fxt_dataset: Benchmark.Dataset, fxt_benchmark: Benchmark, ): + fxt_benchmark.accelerator = "gpu" self._test_perf( model=fxt_model, dataset=fxt_dataset, diff --git a/tests/perf/test_semantic_segmentation.py b/tests/perf/test_semantic_segmentation.py index 4dd64298002..8df729f9804 100644 --- a/tests/perf/test_semantic_segmentation.py +++ b/tests/perf/test_semantic_segmentation.py @@ -33,7 +33,7 @@ class TestPerfSemanticSegmentation(PerfTestBase): size="small", data_format="common_semantic_segmentation_with_subset_dirs", num_classes=2, - num_repeat=5, + num_repeat=1, extra_overrides={}, ) for idx in (1, 2, 3) @@ -44,7 +44,7 @@ class TestPerfSemanticSegmentation(PerfTestBase): size="medium", data_format="common_semantic_segmentation_with_subset_dirs", num_classes=2, - num_repeat=5, + num_repeat=1, extra_overrides={}, ), Benchmark.Dataset( @@ -53,9 +53,28 @@ class TestPerfSemanticSegmentation(PerfTestBase): size="large", data_format="common_semantic_segmentation_with_subset_dirs", num_classes=2, - num_repeat=5, + num_repeat=1, extra_overrides={}, ), + Benchmark.Dataset( + name="kitti", + path=Path("kitti_full"), + size="medium", + data_format="common_semantic_segmentation_with_subset_dirs", + num_classes=19, + num_repeat=1, + extra_overrides={}, + ), + Benchmark.Dataset( + name="voc_otx_cut", + path=Path("voc_otx_cut"), + size="large", + data_format="common_semantic_segmentation_with_subset_dirs", + num_classes=21, + num_repeat=1, + extra_overrides={}, + ), + ] BENCHMARK_CRITERIA = [ # noqa: RUF012 @@ -63,12 +82,12 @@ class TestPerfSemanticSegmentation(PerfTestBase): Benchmark.Criterion(name="train/e2e_time", summary="max", compare="<", margin=0.1), Benchmark.Criterion(name="val/Dice", summary="max", compare=">", margin=0.1), Benchmark.Criterion(name="test/Dice", summary="max", compare=">", margin=0.1), - Benchmark.Criterion(name="export/Dice", summary="max", compare=">", margin=0.1), - Benchmark.Criterion(name="optimize/Dice", summary="max", compare=">", margin=0.1), + # Benchmark.Criterion(name="export/Dice", summary="max", compare=">", margin=0.1), + # Benchmark.Criterion(name="optimize/Dice", summary="max", compare=">", margin=0.1), Benchmark.Criterion(name="train/iter_time", summary="mean", compare="<", margin=0.1), Benchmark.Criterion(name="test/iter_time", summary="mean", compare="<", margin=0.1), - Benchmark.Criterion(name="export/iter_time", summary="mean", compare="<", margin=0.1), - Benchmark.Criterion(name="optimize/iter_time", summary="mean", compare="<", margin=0.1), + # Benchmark.Criterion(name="export/iter_time", summary="mean", compare="<", margin=0.1), + # Benchmark.Criterion(name="optimize/iter_time", summary="mean", compare="<", margin=0.1), ] @pytest.mark.parametrize( From 9e64563a55f414b3d2d4529ceeffb895d19ce050 Mon Sep 17 00:00:00 2001 From: kprokofi Date: Sun, 17 Mar 2024 07:52:16 +0900 Subject: [PATCH 15/42] change device --- tests/perf/test_classification.py | 6 +++--- tests/perf/test_detection.py | 2 +- tests/perf/test_instance_segmentation.py | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/perf/test_classification.py b/tests/perf/test_classification.py index 19abc226e36..873fd82c9ef 100644 --- a/tests/perf/test_classification.py +++ b/tests/perf/test_classification.py @@ -114,7 +114,7 @@ def test_perf( fxt_dataset: Benchmark.Dataset, fxt_benchmark: Benchmark, ): - fxt_benchmark.accelerator = "gpu" + fxt_benchmark.accelerator = "xpu" self._test_perf( model=fxt_model, dataset=fxt_dataset, @@ -196,7 +196,7 @@ def test_perf( fxt_dataset: Benchmark.Dataset, fxt_benchmark: Benchmark, ): - fxt_benchmark.accelerator = "gpu" + fxt_benchmark.accelerator = "xpu" self._test_perf( model=fxt_model, dataset=fxt_dataset, @@ -276,7 +276,7 @@ def test_perf( fxt_dataset: Benchmark.Dataset, fxt_benchmark: Benchmark, ): - fxt_benchmark.accelerator = "gpu" + fxt_benchmark.accelerator = "xpu" self._test_perf( model=fxt_model, dataset=fxt_dataset, diff --git a/tests/perf/test_detection.py b/tests/perf/test_detection.py index 70e0cd2892b..51c6803100b 100644 --- a/tests/perf/test_detection.py +++ b/tests/perf/test_detection.py @@ -118,7 +118,7 @@ def test_perf( fxt_dataset: Benchmark.Dataset, fxt_benchmark: Benchmark, ): - fxt_benchmark.accelerator = "gpu" + fxt_benchmark.accelerator = "xpu" self._test_perf( model=fxt_model, dataset=fxt_dataset, diff --git a/tests/perf/test_instance_segmentation.py b/tests/perf/test_instance_segmentation.py index d3afcd4310b..b71405484e9 100644 --- a/tests/perf/test_instance_segmentation.py +++ b/tests/perf/test_instance_segmentation.py @@ -100,7 +100,7 @@ def test_perf( fxt_dataset: Benchmark.Dataset, fxt_benchmark: Benchmark, ): - fxt_benchmark.accelerator = "gpu" + fxt_benchmark.accelerator = "xpu" self._test_perf( model=fxt_model, dataset=fxt_dataset, @@ -183,7 +183,7 @@ def test_perf( fxt_dataset: Benchmark.Dataset, fxt_benchmark: Benchmark, ): - fxt_benchmark.accelerator = "gpu" + fxt_benchmark.accelerator = "xpu" self._test_perf( model=fxt_model, dataset=fxt_dataset, From defbf9e79dece29aa4c4171b55ce232a5f5db05b Mon Sep 17 00:00:00 2001 From: kprokofi Date: Sun, 17 Mar 2024 07:56:14 +0900 Subject: [PATCH 16/42] quick fix for instance seg --- tests/perf/test_instance_segmentation.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/perf/test_instance_segmentation.py b/tests/perf/test_instance_segmentation.py index b71405484e9..6c41834be77 100644 --- a/tests/perf/test_instance_segmentation.py +++ b/tests/perf/test_instance_segmentation.py @@ -31,7 +31,7 @@ class TestPerfInstanceSegmentation(PerfTestBase): num_classes=5, num_repeat=1, extra_overrides={ - "deterministic": "True", + # "deterministic": "True", "metric": "otx.core.metrics.fmeasure.FMeasure", "callback_monitor": "val/f1-score", "scheduler.monitor": "val/f1-score", @@ -47,21 +47,21 @@ class TestPerfInstanceSegmentation(PerfTestBase): num_classes=2, num_repeat=1, extra_overrides={ - "deterministic": "True", + # "deterministic": "True", "metric": "otx.core.metrics.fmeasure.FMeasure", "callback_monitor": "val/f1-score", "scheduler.monitor": "val/f1-score", }, ), Benchmark.Dataset( - name="vitens_coliform", - path=Path("instance_seg/Vitens-Coliform-coco"), + name="bdd_large", + path=Path("instance_seg/bdd_large"), size="large", data_format="coco", num_classes=1, num_repeat=1, extra_overrides={ - "deterministic": "True", + # "deterministic": "True", "metric": "otx.core.metrics.fmeasure.FMeasure", "callback_monitor": "val/f1-score", "scheduler.monitor": "val/f1-score", @@ -127,7 +127,7 @@ class TestPerfTilingInstanceSegmentation(PerfTestBase): num_classes=1, num_repeat=1, extra_overrides={ - "deterministic": "True", + # "deterministic": "True", "metric": "otx.core.metrics.fmeasure.FMeasure", "callback_monitor": "val/f1-score", "scheduler.monitor": "val/f1-score", @@ -143,7 +143,7 @@ class TestPerfTilingInstanceSegmentation(PerfTestBase): num_classes=1, num_repeat=1, extra_overrides={ - "deterministic": "True", + # "deterministic": "True", "metric": "otx.core.metrics.fmeasure.FMeasure", "callback_monitor": "val/f1-score", "scheduler.monitor": "val/f1-score", From 509a22606874b0c081bc62c2e5aaac57c9ae3656 Mon Sep 17 00:00:00 2001 From: kprokofi Date: Tue, 19 Mar 2024 16:52:31 +0900 Subject: [PATCH 17/42] clean the code --- docker/download_pretrained_weights.py | 1 + src/otx/algo/__init__.py | 22 ++- src/otx/algo/accelerators/__init__.py | 2 +- src/otx/algo/accelerators/xpu.py | 17 ++- src/otx/algo/detection/utils/__init__.py | 4 +- .../algo/detection/utils/mmcv_patched_ops.py | 40 ++++-- src/otx/algo/plugins/xpu_precision.py | 42 +++--- src/otx/algo/strategies/xpu_single.py | 36 +++-- src/otx/core/model/module/base.py | 2 - src/otx/core/model/module/classification.py | 1 - src/otx/core/model/module/detection.py | 1 - src/otx/engine/engine.py | 15 +- .../maskrcnn_efficientnetb2b_tile.yaml | 2 +- .../instance_segmentation/maskrcnn_r50.yaml | 2 +- .../maskrcnn_r50_tile.yaml | 2 +- .../rtmdet_inst_tiny.yaml | 2 +- src/otx/utils/utils.py | 6 +- tests/conftest.py | 3 +- .../api/test_auto_configuration.py | 1 + tests/integration/api/test_engine_api.py | 1 + tests/integration/api/test_xai.py | 1 + .../cli/test_auto_configuration.py | 2 +- tests/integration/cli/test_cli.py | 2 +- tests/integration/conftest.py | 1 + tests/integration/detection/conftest.py | 1 + tests/integration/detection/test_model.py | 1 + tests/integration/test_tiling.py | 1 + tests/perf/benchmark.py | 131 ++++++++++++++---- tests/perf/test_classification.py | 78 ++++------- tests/perf/test_detection.py | 33 ++--- tests/perf/test_instance_segmentation.py | 36 +++-- tests/perf/test_semantic_segmentation.py | 39 ++---- .../backbones/test_movinet.py | 1 + .../heads/test_movinet_head.py | 1 + .../recognizers/test_movinet_recognizer.py | 1 + .../test_adaptive_train_scheduling.py | 3 +- .../algo/callbacks/test_iteration_timer.py | 1 + .../backbones/test_otx_efficientnet.py | 1 + .../backbones/test_otx_efficientnet_v2.py | 1 + .../backbones/test_otx_mobilenet_v3.py | 1 + tests/unit/algo/classification/conftest.py | 3 +- .../heads/test_custom_hlabel_cls_head.py | 3 +- .../heads/test_custom_multilabel_cls_head.py | 1 + .../losses/test_asymmetric_multilabel.py | 1 + .../algo/classification/test_otx_dino_v2.py | 1 + .../classification/test_torchvision_model.py | 1 + .../backbones/test_pytorchcv_backbones.py | 3 +- .../heads/test_class_incremental_mixin.py | 1 + .../heads/test_custom_anchor_generator.py | 1 + .../detection/heads/test_custom_ssd_head.py | 1 + tests/unit/algo/detection/test_ssd.py | 1 + .../algo/hooks/test_saliency_map_dumping.py | 1 + .../hooks/test_saliency_map_processing.py | 1 + tests/unit/algo/hooks/test_xai_hooks.py | 5 +- .../heads/test_custom_roi_head.py | 1 + .../instance_segmentation/test_evaluation.py | 3 +- .../algo/samplers/test_balanced_sampler.py | 1 + .../test_class_incremental_sampler.py | 1 + .../algo/segmentation/backbones/litehrnet.py | 1 + .../heads/test_class_incremental_mixin.py | 1 + tests/unit/algo/utils/test_support_otx_v1.py | 1 + .../backbones/test_tiny_vit.py | 3 +- .../visual_prompting/backbones/test_vit.py | 3 +- tests/unit/algo/visual_prompting/conftest.py | 3 +- .../decoders/test_sam_mask_decoder.py | 3 +- .../encoders/test_sam_image_encoder.py | 1 + .../encoders/test_sam_prompt_encoder.py | 3 +- .../visual_prompting/test_openvino_models.py | 1 + .../visual_prompting/test_segment_anything.py | 5 +- .../test_zero_shot_segment_anything.py | 5 +- .../utils/test_layer_norm_2d.py | 1 + tests/unit/cli/test_cli.py | 1 + tests/unit/cli/test_install.py | 3 +- tests/unit/cli/utils/test_help_formatter.py | 1 + tests/unit/cli/utils/test_installation.py | 5 +- tests/unit/cli/utils/test_jsonargparse.py | 1 + tests/unit/core/conftest.py | 3 +- tests/unit/core/data/conftest.py | 4 +- .../data/dataset/test_visual_prompting.py | 5 +- tests/unit/core/data/entity/conftest.py | 5 +- tests/unit/core/data/entity/test_base.py | 1 + tests/unit/core/data/entity/test_detection.py | 5 +- .../core/data/entity/test_visual_prompting.py | 5 +- tests/unit/core/data/test_factory.py | 1 + tests/unit/core/data/test_mem_cache.py | 1 + tests/unit/core/data/test_module.py | 1 + tests/unit/core/data/test_pre_filtering.py | 1 + tests/unit/core/data/test_transform_libs.py | 5 +- .../core/data/transform_libs/test_mmcv.py | 1 + .../core/data/transform_libs/test_mmdet.py | 5 +- .../core/data/transform_libs/test_mmseg.py | 1 + tests/unit/core/metrics/test_accuracy.py | 1 + tests/unit/core/metrics/test_fmeasure.py | 1 + tests/unit/core/model/entity/test_base.py | 1 + .../core/model/entity/test_segmentation.py | 2 + .../model/entity/test_visual_prompting.py | 3 +- tests/unit/core/model/module/test_base.py | 3 +- .../unit/core/model/module/test_detection.py | 3 +- .../core/model/module/test_segmentation.py | 3 +- tests/unit/core/utils/test_mask_utils.py | 3 +- tests/unit/core/utils/test_tile.py | 1 + tests/unit/core/utils/test_utils.py | 1 + tests/unit/engine/utils/test_api.py | 1 + .../engine/utils/test_auto_configurator.py | 1 + tests/unit/hpo/test_hpo_base.py | 1 + tests/unit/hpo/test_hyperband.py | 1 + tests/unit/hpo/test_resource_manager.py | 1 + tests/unit/hpo/test_search_space.py | 1 + tests/unit/utils/test_utils.py | 1 + 109 files changed, 414 insertions(+), 269 deletions(-) diff --git a/docker/download_pretrained_weights.py b/docker/download_pretrained_weights.py index 7fee845239e..ea9eafaaaba 100644 --- a/docker/download_pretrained_weights.py +++ b/docker/download_pretrained_weights.py @@ -8,6 +8,7 @@ from importlib_resources import files from omegaconf import OmegaConf + from otx.core.utils.instantiators import partial_instantiate_class logging.basicConfig( diff --git a/src/otx/algo/__init__.py b/src/otx/algo/__init__.py index 417fd5fb4f8..29312f92f25 100644 --- a/src/otx/algo/__init__.py +++ b/src/otx/algo/__init__.py @@ -3,6 +3,24 @@ # """Module for OTX custom algorithms, e.g., model, losses, hook, etc...""" -from . import action_classification, classification, detection, segmentation, visual_prompting, strategies, accelerators, plugins +from . import ( + accelerators, + action_classification, + classification, + detection, + plugins, + segmentation, + strategies, + visual_prompting, +) -__all__ = ["action_classification", "classification", "detection", "segmentation", "visual_prompting", "strategies", "accelerators", "plugins"] +__all__ = [ + "action_classification", + "classification", + "detection", + "segmentation", + "visual_prompting", + "strategies", + "accelerators", + "plugins", +] diff --git a/src/otx/algo/accelerators/__init__.py b/src/otx/algo/accelerators/__init__.py index d9d8844a02e..5fc4b9d9d1d 100644 --- a/src/otx/algo/accelerators/__init__.py +++ b/src/otx/algo/accelerators/__init__.py @@ -5,4 +5,4 @@ from .xpu import XPUAccelerator -__all__ = ["XPUAccelerator"] \ No newline at end of file +__all__ = ["XPUAccelerator"] diff --git a/src/otx/algo/accelerators/xpu.py b/src/otx/algo/accelerators/xpu.py index 1b615026d4c..b9f861df627 100644 --- a/src/otx/algo/accelerators/xpu.py +++ b/src/otx/algo/accelerators/xpu.py @@ -2,8 +2,9 @@ # Copyright (C) 2023 Intel Corporation # SPDX-License-Identifier: Apache-2.0 # +from __future__ import annotations -from typing import Any, Dict, Union +from typing import Any import torch from lightning.pytorch.accelerators import AcceleratorRegistry @@ -20,19 +21,20 @@ class XPUAccelerator(Accelerator): def setup_device(self, device: torch.device) -> None: """Sets up the specified device.""" if device.type != "xpu": - raise RuntimeError(f"Device should be xpu, got {device} instead") + msg = f"Device should be xpu, got {device} instead" + raise RuntimeError(msg) torch.xpu.set_device(device) @staticmethod - def parse_devices(devices: Any) -> Any: + def parse_devices(devices: str | list | torch.device) -> list: """Parses devices for multi-GPU training.""" if isinstance(devices, list): return devices return [devices] @staticmethod - def get_parallel_devices(devices: Any) -> Any: + def get_parallel_devices(devices: list) -> list[torch.device]: """Generates a list of parrallel devices.""" return [torch.device("xpu", idx) for idx in devices] @@ -46,15 +48,16 @@ def is_available() -> bool: """Checks if XPU available.""" return is_xpu_available() - def get_device_stats(self, device: Union[str, torch.device]) -> Dict[str, Any]: + def get_device_stats(self, device: str | torch.device) -> dict[str, Any]: """Returns XPU devices stats.""" return {} def teardown(self) -> None: """Cleans-up XPU-related resources.""" - pass AcceleratorRegistry.register( - XPUAccelerator.accelerator_name, XPUAccelerator, description="Accelerator supports XPU devices" + XPUAccelerator.accelerator_name, + XPUAccelerator, + description="Accelerator supports XPU devices", ) diff --git a/src/otx/algo/detection/utils/__init__.py b/src/otx/algo/detection/utils/__init__.py index c5ac0f3e450..2ab46a64ac4 100644 --- a/src/otx/algo/detection/utils/__init__.py +++ b/src/otx/algo/detection/utils/__init__.py @@ -1,7 +1,7 @@ -# Copyright (C) 2023 Intel Corporation +# Copyright (C) 2024 Intel Corporation # SPDX-License-Identifier: Apache-2.0 # -"""utils for detection task""" +"""utils for detection task.""" from .mmcv_patched_ops import monkey_patched_nms, monkey_patched_roi_align diff --git a/src/otx/algo/detection/utils/mmcv_patched_ops.py b/src/otx/algo/detection/utils/mmcv_patched_ops.py index 5c15cbcf767..ec3a884232d 100644 --- a/src/otx/algo/detection/utils/mmcv_patched_ops.py +++ b/src/otx/algo/detection/utils/mmcv_patched_ops.py @@ -1,13 +1,35 @@ +# Copyright (C) 2024 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# +"""utils for detection task.""" + +from __future__ import annotations + +from typing import TYPE_CHECKING + import torch +from mmcv.utils import ext_loader from torchvision.ops import nms as tv_nms from torchvision.ops import roi_align as tv_roi_align -from mmcv.utils import ext_loader + +if TYPE_CHECKING: + from mmcv.ops.nms import NMSop + from mmcv.ops.roi_align import RoIAlign ext_module = ext_loader.load_ext("_ext", ["nms", "softnms", "nms_match", "nms_rotated", "nms_quadri"]) -def monkey_patched_nms(ctx, bboxes, scores, iou_threshold, offset, score_threshold, max_num): +def monkey_patched_nms( + ctx: NMSop, + bboxes: torch.Tensor, + scores: torch.Tensor, + iou_threshold: float, + offset: float, + score_threshold: float, + max_num: int, +) -> torch.Tensor: """Runs MMCVs NMS with torchvision.nms, or forces NMS from MMCV to run on CPU.""" + _ = ctx is_filtering_by_score = score_threshold > 0 if is_filtering_by_score: valid_mask = scores > score_threshold @@ -36,18 +58,16 @@ def monkey_patched_nms(ctx, bboxes, scores, iou_threshold, offset, score_thresho return inds -def monkey_patched_roi_align(self, input, rois): +def monkey_patched_roi_align(self: RoIAlign, _input: torch.Tensor, rois: torch.Tensor) -> torch.Tensor: """Replaces MMCVs roi align with the one from torchvision. Args: self: patched instance - input: NCHW images + _input: NCHW images rois: Bx5 boxes. First column is the index into N. The other 4 columns are xyxy. """ - if "aligned" in tv_roi_align.__code__.co_varnames: - return tv_roi_align(input, rois, self.output_size, self.spatial_scale, self.sampling_ratio, self.aligned) - else: - if self.aligned: - rois -= rois.new_tensor([0.0] + [0.5 / self.spatial_scale] * 4) - return tv_roi_align(input, rois, self.output_size, self.spatial_scale, self.sampling_ratio) + return tv_roi_align(_input, rois, self.output_size, self.spatial_scale, self.sampling_ratio, self.aligned) + if self.aligned: + rois -= rois.new_tensor([0.0] + [0.5 / self.spatial_scale] * 4) + return tv_roi_align(_input, rois, self.output_size, self.spatial_scale, self.sampling_ratio) diff --git a/src/otx/algo/plugins/xpu_precision.py b/src/otx/algo/plugins/xpu_precision.py index 8d078d7b810..fb2a08eb182 100644 --- a/src/otx/algo/plugins/xpu_precision.py +++ b/src/otx/algo/plugins/xpu_precision.py @@ -3,19 +3,22 @@ # """Plugin for mixed-precision training on XPU.""" +from __future__ import annotations from contextlib import contextmanager -from typing import Any, Callable, Dict, Generator, Optional, Union +from typing import TYPE_CHECKING, Any, Callable, Generator -import lightning.pytorch as pl import torch -from lightning_fabric.utilities.types import Optimizable from lightning.pytorch.plugins.precision.precision import Precision from lightning.pytorch.utilities import GradClipAlgorithmType from lightning.pytorch.utilities.exceptions import MisconfigurationException from torch import Tensor from torch.optim import LBFGS, Optimizer +if TYPE_CHECKING: + import lightning.pytorch as pl + from lightning_fabric.utilities.types import Optimizable + class MixedPrecisionXPUPlugin(Precision): """Plugin for Automatic Mixed Precision (AMP) training with ``torch.xpu.autocast``. @@ -24,10 +27,10 @@ class MixedPrecisionXPUPlugin(Precision): scaler: An optional :class:`torch.cuda.amp.GradScaler` to use. """ - def __init__(self, scaler: Optional[Any] = None) -> None: + def __init__(self, scaler: torch.cuda.amp.GradScaler | None = None) -> None: self.scaler = scaler - def pre_backward(self, tensor: Tensor, module: "pl.LightningModule") -> Tensor: + def pre_backward(self, tensor: Tensor, module: pl.LightningModule) -> Tensor: """Apply grad scaler before backward.""" if self.scaler is not None: tensor = self.scaler.scale(tensor) @@ -36,19 +39,23 @@ def pre_backward(self, tensor: Tensor, module: "pl.LightningModule") -> Tensor: def optimizer_step( # type: ignore[override] self, optimizer: Optimizable, - model: "pl.LightningModule", - closure: Callable[[], Any], - **kwargs: Any, - ) -> Any: + model: pl.LightningModule, + closure: Callable, + **kwargs: dict, + ) -> None | dict: """Make an optimizer step using scaler if it was passed.""" if self.scaler is None: # skip scaler logic, as bfloat16 does not require scaler return super().optimizer_step( - optimizer, model=model, closure=closure, **kwargs + optimizer, + model=model, + closure=closure, + **kwargs, ) if isinstance(optimizer, LBFGS): + msg = "Native AMP and the LBFGS optimizer are not compatible." raise MisconfigurationException( - f"Native AMP and the LBFGS optimizer are not compatible." + msg, ) closure_result = closure() @@ -71,14 +78,15 @@ def optimizer_step( # type: ignore[override] def clip_gradients( self, optimizer: Optimizer, - clip_val: Union[int, float] = 0.0, + clip_val: int | float = 0.0, gradient_clip_algorithm: GradClipAlgorithmType = GradClipAlgorithmType.NORM, ) -> None: """Handle grad clipping with scaler.""" if clip_val > 0 and _optimizer_handles_unscaling(optimizer): + msg = f"The current optimizer, {type(optimizer).__qualname__}, does not allow for gradient clipping" + " because it performs unscaling of gradients internally. HINT: Are you using a 'fused' optimizer?" raise RuntimeError( - f"The current optimizer, {type(optimizer).__qualname__}, does not allow for gradient clipping" - " because it performs unscaling of gradients internally. HINT: Are you using a 'fused' optimizer?" + msg, ) super().clip_gradients(optimizer=optimizer, clip_val=clip_val, gradient_clip_algorithm=gradient_clip_algorithm) @@ -88,19 +96,19 @@ def forward_context(self) -> Generator[None, None, None]: with torch.xpu.autocast(True): yield - def state_dict(self) -> Dict[str, Any]: + def state_dict(self) -> dict[str, Any]: """Returns state dict of the plugin.""" if self.scaler is not None: return self.scaler.state_dict() return {} - def load_state_dict(self, state_dict: Dict[str, Any]) -> None: + def load_state_dict(self, state_dict: dict[str, torch.Tensor]) -> None: """Loads state dict to the plugin.""" if self.scaler is not None: self.scaler.load_state_dict(state_dict) -def _optimizer_handles_unscaling(optimizer: Any) -> bool: +def _optimizer_handles_unscaling(optimizer: torch.optim.Optimizer) -> bool: """Determines if a PyTorch optimizer handles unscaling gradients in the step method ratherthan through the scaler. Since, the current implementation of this function checks a PyTorch internal variable on the optimizer, the return diff --git a/src/otx/algo/strategies/xpu_single.py b/src/otx/algo/strategies/xpu_single.py index f51634ec4e8..808f7e27bf3 100644 --- a/src/otx/algo/strategies/xpu_single.py +++ b/src/otx/algo/strategies/xpu_single.py @@ -4,19 +4,23 @@ # SPDX-License-Identifier: Apache-2.0 # -from typing import Optional +from __future__ import annotations + +from typing import TYPE_CHECKING -import lightning.pytorch as pl import torch -from lightning_fabric.plugins import CheckpointIO -from lightning_fabric.utilities.types import _DEVICE -from lightning.pytorch.plugins.precision import PrecisionPlugin from lightning.pytorch.strategies import StrategyRegistry from lightning.pytorch.strategies.single_device import SingleDeviceStrategy from lightning.pytorch.utilities.exceptions import MisconfigurationException from otx.utils.utils import is_xpu_available +if TYPE_CHECKING: + import lightning.pytorch as pl + from lightning.pytorch.plugins.precision import PrecisionPlugin + from lightning_fabric.plugins import CheckpointIO + from lightning_fabric.utilities.types import _DEVICE + class SingleXPUStrategy(SingleDeviceStrategy): """Strategy for training on single XPU device.""" @@ -26,12 +30,13 @@ class SingleXPUStrategy(SingleDeviceStrategy): def __init__( self, device: _DEVICE = "xpu:0", - accelerator: Optional["pl.accelerators.Accelerator"] = None, - checkpoint_io: Optional[CheckpointIO] = None, - precision_plugin: Optional[PrecisionPlugin] = None, + accelerator: pl.accelerators.Accelerator | None = None, + checkpoint_io: CheckpointIO | None = None, + precision_plugin: PrecisionPlugin | None = None, ): if not is_xpu_available(): - raise MisconfigurationException("`SingleXPUStrategy` requires XPU devices to run") + msg = "`SingleXPUStrategy` requires XPU devices to run" + raise MisconfigurationException(msg) super().__init__( accelerator=accelerator, @@ -45,16 +50,19 @@ def is_distributed(self) -> bool: """Returns true if the strategy supports distributed training.""" return False - def setup_optimizers(self, trainer: "pl.Trainer") -> None: + def setup_optimizers(self, trainer: pl.Trainer) -> None: """Sets up optimizers.""" super().setup_optimizers(trainer) - if len(self.optimizers) != 1: # type: ignore - raise RuntimeError("XPU strategy doesn't support multiple optimizers") - model, optimizer = torch.xpu.optimize(trainer.model, optimizer=self.optimizers[0]) # type: ignore + if len(self.optimizers) != 1: # type: ignore[has-type] + msg = "XPU strategy doesn't support multiple optimizers" + raise RuntimeError(msg) + model, optimizer = torch.xpu.optimize(trainer.model, optimizer=self.optimizers[0]) # type: ignore[has-type] self.optimizers = [optimizer] self.model = model StrategyRegistry.register( - SingleXPUStrategy.strategy_name, SingleXPUStrategy, description="Strategy that enables training on single XPU" + SingleXPUStrategy.strategy_name, + SingleXPUStrategy, + description="Strategy that enables training on single XPU", ) diff --git a/src/otx/core/model/module/base.py b/src/otx/core/model/module/base.py index 89ca4a4ea6b..c573cad2cbd 100644 --- a/src/otx/core/model/module/base.py +++ b/src/otx/core/model/module/base.py @@ -60,9 +60,7 @@ def __init__( def training_step(self, inputs: OTXBatchDataEntity, batch_idx: int) -> Tensor: """Step for model training.""" - train_loss = self.model(inputs) - print(train_loss[list(train_loss.keys())[0]].device, inputs.images.device, self.device) if isinstance(train_loss, Tensor): self.log( diff --git a/src/otx/core/model/module/classification.py b/src/otx/core/model/module/classification.py index 0bc92aa06eb..4f7eedd9d02 100644 --- a/src/otx/core/model/module/classification.py +++ b/src/otx/core/model/module/classification.py @@ -81,7 +81,6 @@ def validation_step(self, inputs: MulticlassClsBatchDataEntity, batch_idx: int) :param batch_idx: The index of the current batch. """ preds = self.model(inputs) - print(inputs.images.device, self.device, preds.scores[0].device) if not isinstance(preds, (MulticlassClsBatchPredEntity, MulticlassClsBatchPredEntityWithXAI)): raise TypeError(preds) diff --git a/src/otx/core/model/module/detection.py b/src/otx/core/model/module/detection.py index c8a51062162..8d5ea504ad0 100644 --- a/src/otx/core/model/module/detection.py +++ b/src/otx/core/model/module/detection.py @@ -98,7 +98,6 @@ def validation_step(self, inputs: DetBatchDataEntity, batch_idx: int) -> None: :param batch_idx: The index of the current batch. """ preds = self.model(inputs) - print(inputs.images.device, self.device, preds.scores[0].device) if not isinstance(preds, (DetBatchPredEntity, DetBatchPredEntityWithXAI)): raise TypeError(preds) diff --git a/src/otx/engine/engine.py b/src/otx/engine/engine.py index 8691dbd69b6..5016ce1bc16 100644 --- a/src/otx/engine/engine.py +++ b/src/otx/engine/engine.py @@ -13,6 +13,7 @@ import torch from lightning import Trainer, seed_everything +from otx.algo.plugins import MixedPrecisionXPUPlugin from otx.core.config.device import DeviceConfig from otx.core.config.explain import ExplainConfig from otx.core.config.hpo import HpoConfig @@ -25,7 +26,6 @@ from otx.core.types.precision import OTXPrecisionType from otx.core.types.task import OTXTaskType from otx.core.utils.cache import TrainerArgumentsCache -from otx.algo.plugins import MixedPrecisionXPUPlugin from .hpo import execute_hpo, update_hyper_parameter from .utils.auto_configurator import AutoConfigurator @@ -41,8 +41,6 @@ from otx.core.metrics import MetricCallable - - LITMODULE_PER_TASK = { OTXTaskType.MULTI_CLASS_CLS: "otx.core.model.module.classification.OTXMulticlassClsLitModule", OTXTaskType.MULTI_LABEL_CLS: "otx.core.model.module.classification.OTXMultilabelClsLitModule", @@ -139,15 +137,16 @@ def __init__( ) ) if self.task in [OTXTaskType.DETECTION, OTXTaskType.INSTANCE_SEGMENTATION] and self.device.accelerator == "xpu": + import numpy as np from mmcv.ops.nms import NMSop from mmcv.ops.roi_align import RoIAlign - from otx.algo.detection.utils import monkey_patched_nms, monkey_patched_roi_align from mmengine.structures import instance_data - import numpy as np - LongTypeTensor = Union[torch.LongTensor, torch.xpu.LongTensor] - BoolTypeTensor = Union[torch.BoolTensor, torch.xpu.BoolTensor] - instance_data.IndexType = Union[str, slice, int, list, LongTypeTensor, BoolTypeTensor, np.ndarray] + from otx.algo.detection.utils import monkey_patched_nms, monkey_patched_roi_align + + long_type_tensor = Union[torch.LongTensor, torch.xpu.LongTensor] + bool_type_tensor = Union[torch.BoolTensor, torch.xpu.BoolTensor] + instance_data.IndexType = Union[str, slice, int, list, long_type_tensor, bool_type_tensor, np.ndarray] NMSop.forward = monkey_patched_nms RoIAlign.forward = monkey_patched_roi_align diff --git a/src/otx/recipe/instance_segmentation/maskrcnn_efficientnetb2b_tile.yaml b/src/otx/recipe/instance_segmentation/maskrcnn_efficientnetb2b_tile.yaml index 7e8dd412bc9..93030f8cf59 100644 --- a/src/otx/recipe/instance_segmentation/maskrcnn_efficientnetb2b_tile.yaml +++ b/src/otx/recipe/instance_segmentation/maskrcnn_efficientnetb2b_tile.yaml @@ -37,7 +37,7 @@ callback_monitor: val/map_50 data: ../_base_/data/mmdet_base.yaml overrides: max_epochs: 100 - # gradient_clip_val: 35.0 + gradient_clip_val: 35.0 data: task: INSTANCE_SEGMENTATION config: diff --git a/src/otx/recipe/instance_segmentation/maskrcnn_r50.yaml b/src/otx/recipe/instance_segmentation/maskrcnn_r50.yaml index 178bafb76c6..fc70a4c51fd 100644 --- a/src/otx/recipe/instance_segmentation/maskrcnn_r50.yaml +++ b/src/otx/recipe/instance_segmentation/maskrcnn_r50.yaml @@ -37,7 +37,7 @@ callback_monitor: val/map_50 data: ../_base_/data/mmdet_base.yaml overrides: max_epochs: 100 - # gradient_clip_val: 35.0 + gradient_clip_val: 35.0 data: task: INSTANCE_SEGMENTATION config: diff --git a/src/otx/recipe/instance_segmentation/maskrcnn_r50_tile.yaml b/src/otx/recipe/instance_segmentation/maskrcnn_r50_tile.yaml index 16d831fab56..047b18e67e2 100644 --- a/src/otx/recipe/instance_segmentation/maskrcnn_r50_tile.yaml +++ b/src/otx/recipe/instance_segmentation/maskrcnn_r50_tile.yaml @@ -37,7 +37,7 @@ callback_monitor: val/map_50 data: ../_base_/data/mmdet_base.yaml overrides: max_epochs: 100 - # gradient_clip_val: 35.0 + gradient_clip_val: 35.0 data: task: INSTANCE_SEGMENTATION config: diff --git a/src/otx/recipe/instance_segmentation/rtmdet_inst_tiny.yaml b/src/otx/recipe/instance_segmentation/rtmdet_inst_tiny.yaml index f4656186c98..486dbed5f63 100644 --- a/src/otx/recipe/instance_segmentation/rtmdet_inst_tiny.yaml +++ b/src/otx/recipe/instance_segmentation/rtmdet_inst_tiny.yaml @@ -38,7 +38,7 @@ data: ../_base_/data/mmdet_base.yaml overrides: precision: 32 # 16/"16-true" does not work max_epochs: 100 - # gradient_clip_val: 35.0 + gradient_clip_val: 35.0 data: task: INSTANCE_SEGMENTATION config: diff --git a/src/otx/utils/utils.py b/src/otx/utils/utils.py index 80896a72e43..bca60c4b5b4 100644 --- a/src/otx/utils/utils.py +++ b/src/otx/utils/utils.py @@ -6,18 +6,18 @@ from __future__ import annotations from decimal import Decimal -import torch from typing import TYPE_CHECKING, Any +import torch + if TYPE_CHECKING: from pathlib import Path XPU_AVAILABLE = None try: - import intel_extension_for_pytorch as ipex + import intel_extension_for_pytorch # noqa: F401 except ImportError: XPU_AVAILABLE = False - ipex = None def get_using_dot_delimited_key(key: str, target: Any) -> Any: # noqa: ANN401 diff --git a/tests/conftest.py b/tests/conftest.py index 9474bd8fc57..2b8f119e2c8 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -4,10 +4,11 @@ import pytest import torch +from torchvision.tv_tensors import Image, Mask + from otx.core.data.entity.base import ImageInfo from otx.core.data.entity.segmentation import SegBatchDataEntity, SegBatchPredEntity, SegDataEntity from otx.core.data.mem_cache import MemCacheHandlerSingleton -from torchvision.tv_tensors import Image, Mask @pytest.fixture(scope="session") diff --git a/tests/integration/api/test_auto_configuration.py b/tests/integration/api/test_auto_configuration.py index 1b45bdf423b..8ee1f29f120 100644 --- a/tests/integration/api/test_auto_configuration.py +++ b/tests/integration/api/test_auto_configuration.py @@ -4,6 +4,7 @@ from pathlib import Path import pytest + from otx.core.data.module import OTXDataModule from otx.core.model.entity.base import OTXModel from otx.core.types.task import OTXTaskType diff --git a/tests/integration/api/test_engine_api.py b/tests/integration/api/test_engine_api.py index 13d3b6888e2..36d28ec36b8 100644 --- a/tests/integration/api/test_engine_api.py +++ b/tests/integration/api/test_engine_api.py @@ -7,6 +7,7 @@ import pytest from openvino.model_api.tilers import Tiler + from otx.core.data.module import OTXDataModule from otx.core.model.entity.base import OTXModel from otx.core.types.task import OTXTaskType diff --git a/tests/integration/api/test_xai.py b/tests/integration/api/test_xai.py index 577782b3b09..a75d202b6ae 100644 --- a/tests/integration/api/test_xai.py +++ b/tests/integration/api/test_xai.py @@ -6,6 +6,7 @@ import numpy as np import openvino.runtime as ov import pytest + from otx.core.data.entity.classification import ( MulticlassClsBatchPredEntity, MulticlassClsBatchPredEntityWithXAI, diff --git a/tests/integration/cli/test_auto_configuration.py b/tests/integration/cli/test_auto_configuration.py index 069e54ca2c6..33ae8543a98 100644 --- a/tests/integration/cli/test_auto_configuration.py +++ b/tests/integration/cli/test_auto_configuration.py @@ -5,9 +5,9 @@ from pathlib import Path import pytest + from otx.core.types.task import OTXTaskType from otx.engine.utils.auto_configurator import DEFAULT_CONFIG_PER_TASK - from tests.integration.cli.utils import run_main diff --git a/tests/integration/cli/test_cli.py b/tests/integration/cli/test_cli.py index 295043fac0a..96d041f63ec 100644 --- a/tests/integration/cli/test_cli.py +++ b/tests/integration/cli/test_cli.py @@ -7,8 +7,8 @@ import numpy as np import pytest import yaml -from otx.engine.utils.auto_configurator import DEFAULT_CONFIG_PER_TASK +from otx.engine.utils.auto_configurator import DEFAULT_CONFIG_PER_TASK from tests.integration.cli.utils import run_main diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 3c9d706c307..5c162ea4a3a 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -9,6 +9,7 @@ import pytest from mmengine.config import Config as MMConfig + from otx.core.types.task import OTXTaskType diff --git a/tests/integration/detection/conftest.py b/tests/integration/detection/conftest.py index 1464fc7d5ac..f1464ea5b43 100644 --- a/tests/integration/detection/conftest.py +++ b/tests/integration/detection/conftest.py @@ -7,6 +7,7 @@ import pytest from omegaconf import DictConfig + from otx.core.config.data import ( DataModuleConfig, SubsetConfig, diff --git a/tests/integration/detection/test_model.py b/tests/integration/detection/test_model.py index cd450d595ae..d5f1c67360c 100644 --- a/tests/integration/detection/test_model.py +++ b/tests/integration/detection/test_model.py @@ -3,6 +3,7 @@ # import pytest from omegaconf import DictConfig + from otx.core.data.module import OTXDataModule from otx.core.model.entity.detection import MMDetCompatibleModel from otx.core.utils.config import mmconfig_dict_to_dict diff --git a/tests/integration/test_tiling.py b/tests/integration/test_tiling.py index 574d8db14eb..b4913031312 100644 --- a/tests/integration/test_tiling.py +++ b/tests/integration/test_tiling.py @@ -8,6 +8,7 @@ import pytest from datumaro import Dataset as DmDataset from omegaconf import DictConfig, OmegaConf + from otx.core.config.data import ( DataModuleConfig, SubsetConfig, diff --git a/tests/perf/benchmark.py b/tests/perf/benchmark.py index 37cfa83bd49..95bb0e76de1 100644 --- a/tests/perf/benchmark.py +++ b/tests/perf/benchmark.py @@ -14,6 +14,7 @@ from time import time from typing import Any +import numpy as np import pandas as pd log = logging.getLogger(__name__) @@ -37,6 +38,7 @@ class Benchmark: dry_run (bool): Whether to just print the OTX command without execution. Defaults to False. deterministic (bool): Whether to turn on deterministic training mode. Defaults to False. accelerator (str): Accelerator device on which to run benchmark. Defaults to gpu. + reference_results (pd.DataFrame): Reference benchmark results for performance checking. """ @dataclass @@ -53,7 +55,7 @@ class Dataset: name: str path: Path - size: str + group: str data_format: str num_classes: int num_repeat: int = 1 @@ -68,6 +70,19 @@ class Criterion: compare: str margin: float + def __call__(self, result_entry: pd.Series, target_entry: pd.Series) -> None: + """Check result against given target.""" + if self.name not in result_entry or result_entry[self.name] is None or np.isnan(result_entry[self.name]): + return + if self.name not in target_entry or target_entry[self.name] is None or np.isnan(target_entry[self.name]): + return + if self.compare == "==": + assert abs(result_entry[self.name] - target_entry[self.name]) < target_entry[self.name] * self.margin + elif self.compare == "<": + assert result_entry[self.name] < target_entry[self.name] * (1.0 + self.margin) + elif self.compare == ">": + assert result_entry[self.name] > target_entry[self.name] * (1.0 - self.margin) + def __init__( self, data_root: Path = Path("data"), @@ -79,6 +94,7 @@ def __init__( dry_run: bool = False, deterministic: bool = False, accelerator: str = "gpu", + reference_results: pd.DataFrame | None = None, ): self.data_root = data_root self.output_root = output_root @@ -89,6 +105,7 @@ def __init__( self.dry_run = dry_run self.deterministic = deterministic self.accelerator = accelerator + self.reference_results = reference_results def run( self, @@ -114,9 +131,9 @@ def run( tags = { "task": model.task, - "data_size": dataset.size, + "data_group": dataset.group, "model": model.name, - "dataset": dataset.name, + "data": dataset.name, **self.tags, } @@ -125,10 +142,8 @@ def run( num_repeat = self.num_repeat # Override by global setting for seed in range(num_repeat): - seed = 42 sub_work_dir = work_dir / str(seed) tags["seed"] = str(seed) - extra_metrics = {} # Train & test command = [ @@ -156,8 +171,14 @@ def run( command.extend(["--max_epochs", str(self.num_epoch)]) start_time = time() self._run_command(command) - extra_metrics["train/e2e_time"] = time() - start_time + extra_metrics = {"train/e2e_time": time() - start_time} self._rename_raw_data(work_dir=sub_work_dir / ".latest" / "train", replaces={"epoch": "train/epoch"}) + self._log_metrics( + work_dir=sub_work_dir / ".latest" / "train", + tags=tags, + criteria=criteria, + extra_metrics=extra_metrics, + ) command = [ "otx", @@ -166,6 +187,7 @@ def run( str(sub_work_dir), ] self._run_command(command) + self._log_metrics(work_dir=sub_work_dir / ".latest" / "test", tags=tags, criteria=criteria) # Export & test if self.eval_upto in ["export", "optimize"]: @@ -177,19 +199,24 @@ def run( ] self._run_command(command) + exported_model_path = sub_work_dir / ".latest" / "export" / "exported_model.xml" + if not exported_model_path.exists(): + exported_model_path = sub_work_dir / ".latest" / "export" / "exported_model_decoder.xml" + command = [ # NOTE: not working for h_label_cls. to be fixed "otx", "test", "--config", - str(sub_work_dir / ".latest" / "export" / "configs.yaml"), + f"src/otx/recipe/{model.task}/openvino_model.yaml", "--checkpoint", - str(sub_work_dir / ".latest" / "export" / "exported_model.xml"), + str(exported_model_path), "--work_dir", str(sub_work_dir), ] self._run_command(command) self._rename_raw_data(work_dir=sub_work_dir / ".latest" / "test", replaces={"test": "export"}) + self._log_metrics(work_dir=sub_work_dir / ".latest" / "test", tags=tags, criteria=criteria) # Optimize & test if self.eval_upto == "optimize": @@ -200,12 +227,16 @@ def run( "--config", f"src/otx/recipe/{model.task}/openvino_model.yaml", "--checkpoint", - str(sub_work_dir / ".latest" / "export" / "exported_model.xml"), + str(exported_model_path), "--work_dir", str(sub_work_dir), ] self._run_command(command) + optimized_model_path = sub_work_dir / ".latest" / "optimize" / "optimized_model.xml" + if not optimized_model_path.exists(): + optimized_model_path = sub_work_dir / ".latest" / "optimize" / "optimized_model_decoder.xml" + command = [ "otx", "test", @@ -213,21 +244,20 @@ def run( "--config", f"src/otx/recipe/{model.task}/openvino_model.yaml", "--checkpoint", - str(sub_work_dir / ".latest" / "optimize" / "optimized_model.xml"), + str(optimized_model_path), "--work_dir", str(sub_work_dir), ] self._run_command(command) self._rename_raw_data(work_dir=sub_work_dir / ".latest" / "test", replaces={"test": "optimize"}) - - # Parse raw data into raw metrics - self._log_metrics(work_dir=sub_work_dir, tags=tags, criteria=criteria, extra_metrics=extra_metrics) + self._log_metrics(work_dir=sub_work_dir / ".latest" / "test", tags=tags, criteria=criteria) # Force memory clean up gc.collect() - return self.load_result(work_dir) + result = self.load_result(work_dir) + return self.average_result(result, keys=["task", "model", "data_group", "data"]) def _run_command(self, command: list[str]) -> None: if self.dry_run: @@ -239,8 +269,8 @@ def _log_metrics( self, work_dir: Path, tags: dict[str, str], - criteria: list[Benchmark.Criterion], - extra_metrics: dict[str, Any], + criteria: list[Criterion], + extra_metrics: dict[str, Any] | None = None, ) -> None: if not work_dir.exists(): return @@ -249,8 +279,9 @@ def _log_metrics( csv_files = work_dir.glob("**/metrics.csv") raw_data = [pd.read_csv(csv_file) for csv_file in csv_files] raw_data = pd.concat(raw_data, ignore_index=True) - for k, v in extra_metrics.items(): - raw_data[k] = v + if extra_metrics: + for k, v in extra_metrics.items(): + raw_data[k] = v # Summarize metrics = [] @@ -303,20 +334,60 @@ def load_result(result_path: Path) -> pd.DataFrame | None: results = [pd.read_csv(csv_file) for csv_file in csv_files] if len(results) == 0: return None - # Merge data - data = pd.concat(results, ignore_index=True) - # Average by unique group - grouped = data.groupby(["task", "data_size", "model"]) + + return pd.concat(results, ignore_index=True).set_index(["task", "model", "data_group", "data"]) + + @staticmethod + def average_result(data: pd.DataFrame, keys: list[str]) -> pd.DataFrame: + """Average result w.r.t. given keys + + Args: + result (pd.DataFrame): Result data frame + keys (list[str]): Keys to summarize whole data + + Retruns: + pd.DataFrame: Averaged result table + """ + # Flatten index + index_names = data.index.names + column_names = data.columns + data = data.reset_index() + # Average by keys + grouped = data.groupby(keys) aggregated = grouped.mean(numeric_only=True) + # Merge index columns + idx_columns = set(index_names) - set(keys) + for col in idx_columns: + aggregated[col] = "all" # Merge tag columns (non-numeric & non-index) - tag_columns = set(data.columns) - set(aggregated.columns) - set(grouped.keys) + tag_columns = set(column_names) - set(aggregated.columns) - set(keys) for col in tag_columns: # Take common string prefix such as: ["data/1", "data/2", "data/3"] -> "data/" aggregated[col] = grouped[col].agg(lambda x: os.path.commonprefix(x.tolist())) - # Average by task - task_grouped = data.groupby(["task"], as_index=False) - task_aggregated = task_grouped.mean(numeric_only=True) - task_aggregated["data_size"] = "all" - task_aggregated["model"] = "all" - task_aggregated = task_aggregated.set_index(["task", "data_size", "model"]) - return pd.concat([aggregated, task_aggregated]) + # Recover index + return aggregated.reset_index().set_index(index_names) + + def check(self, result: pd.DataFrame, criteria: list[Criterion]): + """Check result w.r.t. reference data. + + Args: + result (pd.DataFrame): Result data frame + criteria (list[Criterion]): Criteria to check results + """ + if result is None: + return + + if self.reference_results is None: + print("No benchmark references loaded. Skipping result checking.") + return + + for key, result_entry in result.iterrows(): + if key not in self.reference_results.index: + print(f"No benchmark reference for {key} loaded. Skipping result checking.") + continue + target_entry = self.reference_results.loc[key] + if isinstance(target_entry, pd.DataFrame): + target_entry = target_entry.iloc[0] # 1-row pd.DataFrame to pd.Series + + for criterion in criteria: + criterion(result_entry, target_entry) diff --git a/tests/perf/test_classification.py b/tests/perf/test_classification.py index 873fd82c9ef..ceb5574002e 100644 --- a/tests/perf/test_classification.py +++ b/tests/perf/test_classification.py @@ -27,58 +27,31 @@ class TestPerfSingleLabelClassification(PerfTestBase): DATASET_TEST_CASES = [ Benchmark.Dataset( name=f"multiclass_CUB_small_{idx}", - path=Path("classification/single_label/multiclass_CUB_small") / f"{idx}", - size="small", + path=Path("multiclass_classification/multiclass_CUB_small") / f"{idx}", + group="small", data_format="imagenet_with_subset_dirs", num_classes=2, - num_repeat=1, + num_repeat=5, extra_overrides={}, ) for idx in (1, 2, 3) ] + [ Benchmark.Dataset( name="multiclass_CUB_medium", - path=Path("classification/single_label/multiclass_CUB_medium"), - size="medium", + path=Path("multiclass_classification/multiclass_CUB_medium"), + group="medium", data_format="imagenet_with_subset_dirs", num_classes=67, - num_repeat=1, + num_repeat=5, extra_overrides={}, ), Benchmark.Dataset( name="multiclass_food101_large", - path=Path("classification/single_label/multiclass_food101_large"), - size="large", + path=Path("multiclass_classification/multiclass_food101_large"), + group="large", data_format="imagenet_with_subset_dirs", num_classes=20, - num_repeat=1, - extra_overrides={}, - ), - Benchmark.Dataset( - name="cars", - path=Path("car_data/car_data"), - size="large", - data_format="imagenet_with_subset_dirs", - num_classes=196, - num_repeat=1, - extra_overrides={}, - ), - Benchmark.Dataset( - name="flowers", - path=Path("flowers"), - size="large", - data_format="imagenet_with_subset_dirs", - num_classes=102, - num_repeat=1, - extra_overrides={}, - ), - Benchmark.Dataset( - name="skin", - path=Path("skin"), - size="large", - data_format="imagenet_with_subset_dirs", - num_classes=14, - num_repeat=1, + num_repeat=5, extra_overrides={}, ), ] @@ -114,7 +87,6 @@ def test_perf( fxt_dataset: Benchmark.Dataset, fxt_benchmark: Benchmark, ): - fxt_benchmark.accelerator = "xpu" self._test_perf( model=fxt_model, dataset=fxt_dataset, @@ -136,31 +108,31 @@ class TestPerfMultiLabelClassification(PerfTestBase): DATASET_TEST_CASES = [ Benchmark.Dataset( name=f"multilabel_CUB_small_{idx}", - path=Path("classification/multi_label/multilabel_CUB_small") / f"{idx}", - size="small", + path=Path("multilabel_classification/multilabel_CUB_small") / f"{idx}", + group="small", data_format="datumaro", num_classes=3, - num_repeat=1, + num_repeat=5, extra_overrides={}, ) for idx in (1, 2, 3) ] + [ Benchmark.Dataset( name="multilabel_CUB_medium", - path=Path("classification/multi_label/multilabel_CUB_medium"), - size="medium", + path=Path("multilabel_classification/multilabel_CUB_medium"), + group="medium", data_format="datumaro", num_classes=68, - num_repeat=1, + num_repeat=5, extra_overrides={}, ), Benchmark.Dataset( name="multilabel_food101_large", - path=Path("classification/multi_label/multilabel_food101_large"), - size="large", + path=Path("multilabel_classification/multilabel_food101_large"), + group="large", data_format="datumaro", num_classes=21, - num_repeat=1, + num_repeat=5, extra_overrides={}, ), ] @@ -196,7 +168,6 @@ def test_perf( fxt_dataset: Benchmark.Dataset, fxt_benchmark: Benchmark, ): - fxt_benchmark.accelerator = "xpu" self._test_perf( model=fxt_model, dataset=fxt_dataset, @@ -218,11 +189,11 @@ class TestPerfHierarchicalLabelClassification(PerfTestBase): DATASET_TEST_CASES = [ Benchmark.Dataset( name=f"hlabel_CUB_small_{idx}", - path=Path("classification/h_label/hlabel_CUB_small") / f"{idx}", - size="small", + path=Path("hlabel_classification/hlabel_CUB_small") / f"{idx}", + group="small", data_format="datumaro", num_classes=6, - num_repeat=1, + num_repeat=5, extra_overrides={ "model.num_multiclass_heads": "3", "model.num_multilabel_classes": "0", @@ -232,11 +203,11 @@ class TestPerfHierarchicalLabelClassification(PerfTestBase): ] + [ Benchmark.Dataset( name="hlabel_CUB_medium", - path=Path("classification/h_label/hlabel_CUB_medium"), - size="medium", + path=Path("hlabel_classification/hlabel_CUB_medium"), + group="medium", data_format="datumaro", num_classes=102, - num_repeat=1, + num_repeat=5, extra_overrides={ "model.num_multiclass_heads": "23", "model.num_multilabel_classes": "0", @@ -276,7 +247,6 @@ def test_perf( fxt_dataset: Benchmark.Dataset, fxt_benchmark: Benchmark, ): - fxt_benchmark.accelerator = "xpu" self._test_perf( model=fxt_model, dataset=fxt_dataset, diff --git a/tests/perf/test_detection.py b/tests/perf/test_detection.py index 51c6803100b..ce282a29749 100644 --- a/tests/perf/test_detection.py +++ b/tests/perf/test_detection.py @@ -30,12 +30,12 @@ class TestPerfObjectDetection(PerfTestBase): Benchmark.Dataset( name=f"pothole_small_{idx}", path=Path("detection/pothole_small") / f"{idx}", - size="small", + group="small", data_format="coco", num_classes=1, - num_repeat=1, + num_repeat=5, extra_overrides={ - # "deterministic": "True", + "deterministic": "True", "metric": "otx.core.metrics.fmeasure.FMeasure", "callback_monitor": "val/f1-score", "scheduler.monitor": "val/f1-score", @@ -46,12 +46,12 @@ class TestPerfObjectDetection(PerfTestBase): Benchmark.Dataset( name="pothole_medium", path=Path("detection/pothole_medium"), - size="medium", + group="medium", data_format="coco", num_classes=1, - num_repeat=1, + num_repeat=5, extra_overrides={ - # "deterministic": "True", + "deterministic": "True", "metric": "otx.core.metrics.fmeasure.FMeasure", "callback_monitor": "val/f1-score", "scheduler.monitor": "val/f1-score", @@ -60,26 +60,12 @@ class TestPerfObjectDetection(PerfTestBase): Benchmark.Dataset( name="vitens_large", path=Path("detection/vitens_large"), - size="large", + group="large", data_format="coco", num_classes=1, - num_repeat=1, + num_repeat=5, extra_overrides={ - # "deterministic": "True", - "metric": "otx.core.metrics.fmeasure.FMeasure", - "callback_monitor": "val/f1-score", - "scheduler.monitor": "val/f1-score", - }, - ), - Benchmark.Dataset( - name="pascal_tiny", - path=Path("pascal_tiny/coco_otx"), - size="large", - data_format="coco", - num_classes=20, - num_repeat=1, - extra_overrides={ - # "deterministic": "True", + "deterministic": "True", "metric": "otx.core.metrics.fmeasure.FMeasure", "callback_monitor": "val/f1-score", "scheduler.monitor": "val/f1-score", @@ -118,7 +104,6 @@ def test_perf( fxt_dataset: Benchmark.Dataset, fxt_benchmark: Benchmark, ): - fxt_benchmark.accelerator = "xpu" self._test_perf( model=fxt_model, dataset=fxt_dataset, diff --git a/tests/perf/test_instance_segmentation.py b/tests/perf/test_instance_segmentation.py index 6c41834be77..0ec701950d8 100644 --- a/tests/perf/test_instance_segmentation.py +++ b/tests/perf/test_instance_segmentation.py @@ -26,12 +26,12 @@ class TestPerfInstanceSegmentation(PerfTestBase): Benchmark.Dataset( name=f"wgisd_small_{idx}", path=Path("instance_seg/wgisd_small") / f"{idx}", - size="small", + group="small", data_format="coco", num_classes=5, - num_repeat=1, + num_repeat=5, extra_overrides={ - # "deterministic": "True", + "deterministic": "True", "metric": "otx.core.metrics.fmeasure.FMeasure", "callback_monitor": "val/f1-score", "scheduler.monitor": "val/f1-score", @@ -42,26 +42,26 @@ class TestPerfInstanceSegmentation(PerfTestBase): Benchmark.Dataset( name="coco_car_person_medium", path=Path("instance_seg/coco_car_person_medium"), - size="medium", + group="medium", data_format="coco", num_classes=2, - num_repeat=1, + num_repeat=5, extra_overrides={ - # "deterministic": "True", + "deterministic": "True", "metric": "otx.core.metrics.fmeasure.FMeasure", "callback_monitor": "val/f1-score", "scheduler.monitor": "val/f1-score", }, ), Benchmark.Dataset( - name="bdd_large", - path=Path("instance_seg/bdd_large"), - size="large", + name="vitens_coliform", + path=Path("instance_seg/Vitens-Coliform-coco"), + group="large", data_format="coco", num_classes=1, - num_repeat=1, + num_repeat=5, extra_overrides={ - # "deterministic": "True", + "deterministic": "True", "metric": "otx.core.metrics.fmeasure.FMeasure", "callback_monitor": "val/f1-score", "scheduler.monitor": "val/f1-score", @@ -100,7 +100,6 @@ def test_perf( fxt_dataset: Benchmark.Dataset, fxt_benchmark: Benchmark, ): - fxt_benchmark.accelerator = "xpu" self._test_perf( model=fxt_model, dataset=fxt_dataset, @@ -122,12 +121,12 @@ class TestPerfTilingInstanceSegmentation(PerfTestBase): Benchmark.Dataset( name=f"vitens_aeromonas_small_{idx}", path=Path("tiling_instance_seg/vitens_aeromonas_small") / f"{idx}", - size="small", + group="small", data_format="coco", num_classes=1, - num_repeat=1, + num_repeat=5, extra_overrides={ - # "deterministic": "True", + "deterministic": "True", "metric": "otx.core.metrics.fmeasure.FMeasure", "callback_monitor": "val/f1-score", "scheduler.monitor": "val/f1-score", @@ -138,12 +137,12 @@ class TestPerfTilingInstanceSegmentation(PerfTestBase): Benchmark.Dataset( name="vitens_aeromonas_medium", path=Path("tiling_instance_seg/vitens_aeromonas_medium"), - size="medium", + group="medium", data_format="coco", num_classes=1, - num_repeat=1, + num_repeat=5, extra_overrides={ - # "deterministic": "True", + "deterministic": "True", "metric": "otx.core.metrics.fmeasure.FMeasure", "callback_monitor": "val/f1-score", "scheduler.monitor": "val/f1-score", @@ -183,7 +182,6 @@ def test_perf( fxt_dataset: Benchmark.Dataset, fxt_benchmark: Benchmark, ): - fxt_benchmark.accelerator = "xpu" self._test_perf( model=fxt_model, dataset=fxt_dataset, diff --git a/tests/perf/test_semantic_segmentation.py b/tests/perf/test_semantic_segmentation.py index 8df729f9804..d0614dbc498 100644 --- a/tests/perf/test_semantic_segmentation.py +++ b/tests/perf/test_semantic_segmentation.py @@ -30,10 +30,10 @@ class TestPerfSemanticSegmentation(PerfTestBase): Benchmark.Dataset( name=f"kvasir_small_{idx}", path=Path("semantic_seg/kvasir_small") / f"{idx}", - size="small", + group="small", data_format="common_semantic_segmentation_with_subset_dirs", num_classes=2, - num_repeat=1, + num_repeat=5, extra_overrides={}, ) for idx in (1, 2, 3) @@ -41,40 +41,21 @@ class TestPerfSemanticSegmentation(PerfTestBase): Benchmark.Dataset( name="kvasir_medium", path=Path("semantic_seg/kvasir_medium"), - size="medium", + group="medium", data_format="common_semantic_segmentation_with_subset_dirs", num_classes=2, - num_repeat=1, + num_repeat=5, extra_overrides={}, ), Benchmark.Dataset( name="kvasir_large", path=Path("semantic_seg/kvasir_large"), - size="large", + group="large", data_format="common_semantic_segmentation_with_subset_dirs", num_classes=2, - num_repeat=1, + num_repeat=5, extra_overrides={}, ), - Benchmark.Dataset( - name="kitti", - path=Path("kitti_full"), - size="medium", - data_format="common_semantic_segmentation_with_subset_dirs", - num_classes=19, - num_repeat=1, - extra_overrides={}, - ), - Benchmark.Dataset( - name="voc_otx_cut", - path=Path("voc_otx_cut"), - size="large", - data_format="common_semantic_segmentation_with_subset_dirs", - num_classes=21, - num_repeat=1, - extra_overrides={}, - ), - ] BENCHMARK_CRITERIA = [ # noqa: RUF012 @@ -82,12 +63,12 @@ class TestPerfSemanticSegmentation(PerfTestBase): Benchmark.Criterion(name="train/e2e_time", summary="max", compare="<", margin=0.1), Benchmark.Criterion(name="val/Dice", summary="max", compare=">", margin=0.1), Benchmark.Criterion(name="test/Dice", summary="max", compare=">", margin=0.1), - # Benchmark.Criterion(name="export/Dice", summary="max", compare=">", margin=0.1), - # Benchmark.Criterion(name="optimize/Dice", summary="max", compare=">", margin=0.1), + Benchmark.Criterion(name="export/Dice", summary="max", compare=">", margin=0.1), + Benchmark.Criterion(name="optimize/Dice", summary="max", compare=">", margin=0.1), Benchmark.Criterion(name="train/iter_time", summary="mean", compare="<", margin=0.1), Benchmark.Criterion(name="test/iter_time", summary="mean", compare="<", margin=0.1), - # Benchmark.Criterion(name="export/iter_time", summary="mean", compare="<", margin=0.1), - # Benchmark.Criterion(name="optimize/iter_time", summary="mean", compare="<", margin=0.1), + Benchmark.Criterion(name="export/iter_time", summary="mean", compare="<", margin=0.1), + Benchmark.Criterion(name="optimize/iter_time", summary="mean", compare="<", margin=0.1), ] @pytest.mark.parametrize( diff --git a/tests/unit/algo/action_classification/backbones/test_movinet.py b/tests/unit/algo/action_classification/backbones/test_movinet.py index 792387d52e2..fc22758e9bb 100644 --- a/tests/unit/algo/action_classification/backbones/test_movinet.py +++ b/tests/unit/algo/action_classification/backbones/test_movinet.py @@ -4,6 +4,7 @@ import pytest import torch + from otx.algo.action_classification.backbones.movinet import OTXMoViNet diff --git a/tests/unit/algo/action_classification/heads/test_movinet_head.py b/tests/unit/algo/action_classification/heads/test_movinet_head.py index 5d1f9568a1e..14e73e0050b 100644 --- a/tests/unit/algo/action_classification/heads/test_movinet_head.py +++ b/tests/unit/algo/action_classification/heads/test_movinet_head.py @@ -5,6 +5,7 @@ import pytest import torch + from otx.algo.action_classification.heads.movinet_head import MoViNetHead diff --git a/tests/unit/algo/action_classification/recognizers/test_movinet_recognizer.py b/tests/unit/algo/action_classification/recognizers/test_movinet_recognizer.py index 861e4ab97ec..15b354f8e3c 100644 --- a/tests/unit/algo/action_classification/recognizers/test_movinet_recognizer.py +++ b/tests/unit/algo/action_classification/recognizers/test_movinet_recognizer.py @@ -5,6 +5,7 @@ import pytest import torch + from otx.algo.action_classification.recognizers.movinet_recognizer import MoViNetRecognizer diff --git a/tests/unit/algo/callbacks/test_adaptive_train_scheduling.py b/tests/unit/algo/callbacks/test_adaptive_train_scheduling.py index 85eb23f8e85..bde70063804 100644 --- a/tests/unit/algo/callbacks/test_adaptive_train_scheduling.py +++ b/tests/unit/algo/callbacks/test_adaptive_train_scheduling.py @@ -8,9 +8,10 @@ from lightning.pytorch.callbacks.early_stopping import EarlyStopping from lightning.pytorch.cli import ReduceLROnPlateau from lightning.pytorch.utilities.types import LRSchedulerConfig -from otx.algo.callbacks.adaptive_train_scheduling import AdaptiveTrainScheduling from torch.utils.data import DataLoader +from otx.algo.callbacks.adaptive_train_scheduling import AdaptiveTrainScheduling + class TestAdaptiveTrainScheduling: def test_callback(self, caplog) -> None: diff --git a/tests/unit/algo/callbacks/test_iteration_timer.py b/tests/unit/algo/callbacks/test_iteration_timer.py index c17de5dab66..48957fe0b12 100644 --- a/tests/unit/algo/callbacks/test_iteration_timer.py +++ b/tests/unit/algo/callbacks/test_iteration_timer.py @@ -4,6 +4,7 @@ from unittest.mock import MagicMock, patch import pytest + from otx.algo.callbacks.iteration_timer import IterationTimer diff --git a/tests/unit/algo/classification/backbones/test_otx_efficientnet.py b/tests/unit/algo/classification/backbones/test_otx_efficientnet.py index 3d4adefa7b5..241c68410fe 100644 --- a/tests/unit/algo/classification/backbones/test_otx_efficientnet.py +++ b/tests/unit/algo/classification/backbones/test_otx_efficientnet.py @@ -4,6 +4,7 @@ import pytest import torch + from otx.algo.classification.backbones.otx_efficientnet import OTXEfficientNet diff --git a/tests/unit/algo/classification/backbones/test_otx_efficientnet_v2.py b/tests/unit/algo/classification/backbones/test_otx_efficientnet_v2.py index 8dcdeb3698a..e01e7f9f11b 100644 --- a/tests/unit/algo/classification/backbones/test_otx_efficientnet_v2.py +++ b/tests/unit/algo/classification/backbones/test_otx_efficientnet_v2.py @@ -2,6 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 import torch + from otx.algo.classification.backbones.otx_efficientnet_v2 import OTXEfficientNetV2 diff --git a/tests/unit/algo/classification/backbones/test_otx_mobilenet_v3.py b/tests/unit/algo/classification/backbones/test_otx_mobilenet_v3.py index 51e3a235022..4d70156cd8c 100644 --- a/tests/unit/algo/classification/backbones/test_otx_mobilenet_v3.py +++ b/tests/unit/algo/classification/backbones/test_otx_mobilenet_v3.py @@ -2,6 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 import torch + from otx.algo.classification.backbones.otx_mobilenet_v3 import OTXMobileNetV3 diff --git a/tests/unit/algo/classification/conftest.py b/tests/unit/algo/classification/conftest.py index bf536b62815..3349c1021fd 100644 --- a/tests/unit/algo/classification/conftest.py +++ b/tests/unit/algo/classification/conftest.py @@ -7,9 +7,10 @@ import torch from mmpretrain.structures import DataSample from omegaconf import DictConfig +from torchvision import tv_tensors + from otx.core.data.dataset.classification import HLabelInfo, MulticlassClsBatchDataEntity from otx.core.data.entity.base import ImageInfo -from torchvision import tv_tensors @pytest.fixture() diff --git a/tests/unit/algo/classification/heads/test_custom_hlabel_cls_head.py b/tests/unit/algo/classification/heads/test_custom_hlabel_cls_head.py index fe7533c1cda..047fa00036a 100644 --- a/tests/unit/algo/classification/heads/test_custom_hlabel_cls_head.py +++ b/tests/unit/algo/classification/heads/test_custom_hlabel_cls_head.py @@ -9,9 +9,10 @@ import pytest import torch from mmpretrain.structures import DataSample +from torch import nn + from otx.algo.classification.heads.custom_hlabel_linear_cls_head import CustomHierarchicalLinearClsHead from otx.algo.classification.heads.custom_hlabel_non_linear_cls_head import CustomHierarchicalNonLinearClsHead -from torch import nn @pytest.fixture() diff --git a/tests/unit/algo/classification/heads/test_custom_multilabel_cls_head.py b/tests/unit/algo/classification/heads/test_custom_multilabel_cls_head.py index 0499a013cd0..b0f49c8ea44 100644 --- a/tests/unit/algo/classification/heads/test_custom_multilabel_cls_head.py +++ b/tests/unit/algo/classification/heads/test_custom_multilabel_cls_head.py @@ -7,6 +7,7 @@ import pytest import torch from mmpretrain.structures import DataSample + from otx.algo.classification.heads import CustomMultiLabelLinearClsHead, CustomMultiLabelNonLinearClsHead from otx.algo.classification.losses import AsymmetricAngularLossWithIgnore diff --git a/tests/unit/algo/classification/losses/test_asymmetric_multilabel.py b/tests/unit/algo/classification/losses/test_asymmetric_multilabel.py index 70159dbf0ee..b34ed5719ec 100644 --- a/tests/unit/algo/classification/losses/test_asymmetric_multilabel.py +++ b/tests/unit/algo/classification/losses/test_asymmetric_multilabel.py @@ -4,6 +4,7 @@ import pytest import torch + from otx.algo.classification.losses import AsymmetricAngularLossWithIgnore diff --git a/tests/unit/algo/classification/test_otx_dino_v2.py b/tests/unit/algo/classification/test_otx_dino_v2.py index 2ec0100bb55..0aba348da92 100644 --- a/tests/unit/algo/classification/test_otx_dino_v2.py +++ b/tests/unit/algo/classification/test_otx_dino_v2.py @@ -7,6 +7,7 @@ import pytest import torch + from otx.algo.classification import DINOv2 diff --git a/tests/unit/algo/classification/test_torchvision_model.py b/tests/unit/algo/classification/test_torchvision_model.py index ee6dee37b76..9413f55e08b 100644 --- a/tests/unit/algo/classification/test_torchvision_model.py +++ b/tests/unit/algo/classification/test_torchvision_model.py @@ -1,5 +1,6 @@ import pytest import torch + from otx.algo.classification.torchvision_model import OTXTVModel, TVModelWithLossComputation from otx.core.data.entity.base import ImageInfo, OTXBatchLossEntity from otx.core.data.entity.classification import ( diff --git a/tests/unit/algo/detection/backbones/test_pytorchcv_backbones.py b/tests/unit/algo/detection/backbones/test_pytorchcv_backbones.py index 7fb49351a58..48eef7d4954 100644 --- a/tests/unit/algo/detection/backbones/test_pytorchcv_backbones.py +++ b/tests/unit/algo/detection/backbones/test_pytorchcv_backbones.py @@ -5,6 +5,8 @@ from __future__ import annotations import torch +from torch import nn + from otx.algo.detection.backbones.pytorchcv_backbones import ( _build_model_including_pytorchcv, multioutput_forward, @@ -12,7 +14,6 @@ replace_norm, train, ) -from torch import nn class MockModule(nn.Module): diff --git a/tests/unit/algo/detection/heads/test_class_incremental_mixin.py b/tests/unit/algo/detection/heads/test_class_incremental_mixin.py index 370a070f403..9e886a96b66 100644 --- a/tests/unit/algo/detection/heads/test_class_incremental_mixin.py +++ b/tests/unit/algo/detection/heads/test_class_incremental_mixin.py @@ -3,6 +3,7 @@ """Test of ClassIncrementalMixin.""" import torch + from otx.algo.detection.atss import ATSS diff --git a/tests/unit/algo/detection/heads/test_custom_anchor_generator.py b/tests/unit/algo/detection/heads/test_custom_anchor_generator.py index 484d81c1dc8..b2828b150c2 100644 --- a/tests/unit/algo/detection/heads/test_custom_anchor_generator.py +++ b/tests/unit/algo/detection/heads/test_custom_anchor_generator.py @@ -4,6 +4,7 @@ import pytest import torch + from otx.algo.detection.heads.custom_anchor_generator import SSDAnchorGeneratorClustered diff --git a/tests/unit/algo/detection/heads/test_custom_ssd_head.py b/tests/unit/algo/detection/heads/test_custom_ssd_head.py index 1d4e1f19d33..244d0948ea4 100644 --- a/tests/unit/algo/detection/heads/test_custom_ssd_head.py +++ b/tests/unit/algo/detection/heads/test_custom_ssd_head.py @@ -3,6 +3,7 @@ """Test of CustomSSDHead.""" from mmdet.models.losses.cross_entropy_loss import CrossEntropyLoss + from otx.algo.detection.heads.custom_ssd_head import CustomSSDHead diff --git a/tests/unit/algo/detection/test_ssd.py b/tests/unit/algo/detection/test_ssd.py index 9a21a1a570d..1744068c45e 100644 --- a/tests/unit/algo/detection/test_ssd.py +++ b/tests/unit/algo/detection/test_ssd.py @@ -3,6 +3,7 @@ """Test of OTX SSD architecture.""" import pytest + from otx.algo.detection.ssd import SSD diff --git a/tests/unit/algo/hooks/test_saliency_map_dumping.py b/tests/unit/algo/hooks/test_saliency_map_dumping.py index 28c9d3254cf..78759454d0f 100644 --- a/tests/unit/algo/hooks/test_saliency_map_dumping.py +++ b/tests/unit/algo/hooks/test_saliency_map_dumping.py @@ -5,6 +5,7 @@ import cv2 import numpy as np + from otx.algo.utils.xai_utils import dump_saliency_maps from otx.core.config.explain import ExplainConfig from otx.core.data.entity.base import ImageInfo diff --git a/tests/unit/algo/hooks/test_saliency_map_processing.py b/tests/unit/algo/hooks/test_saliency_map_processing.py index 628649925b0..273c0ccabc2 100644 --- a/tests/unit/algo/hooks/test_saliency_map_processing.py +++ b/tests/unit/algo/hooks/test_saliency_map_processing.py @@ -3,6 +3,7 @@ import numpy as np import pytest import torch + from otx.algo.utils.xai_utils import process_saliency_maps, process_saliency_maps_in_pred_entity from otx.core.config.explain import ExplainConfig from otx.core.data.entity.base import ImageInfo diff --git a/tests/unit/algo/hooks/test_xai_hooks.py b/tests/unit/algo/hooks/test_xai_hooks.py index 3f642d4ffce..5e7d2ad53ae 100644 --- a/tests/unit/algo/hooks/test_xai_hooks.py +++ b/tests/unit/algo/hooks/test_xai_hooks.py @@ -2,6 +2,9 @@ # SPDX-License-Identifier: Apache-2.0 import torch from datumaro import Polygon +from torch import LongTensor +from torchvision import tv_tensors + from otx.algo.hooks.recording_forward_hook import ( ActivationMapHook, DetClassProbabilityMapHook, @@ -11,8 +14,6 @@ ) from otx.core.data.entity.base import ImageInfo from otx.core.data.entity.instance_segmentation import InstanceSegBatchPredEntity -from torch import LongTensor -from torchvision import tv_tensors def test_activationmap() -> None: diff --git a/tests/unit/algo/instance_segmentation/heads/test_custom_roi_head.py b/tests/unit/algo/instance_segmentation/heads/test_custom_roi_head.py index 9ed6683250a..55f41892f28 100644 --- a/tests/unit/algo/instance_segmentation/heads/test_custom_roi_head.py +++ b/tests/unit/algo/instance_segmentation/heads/test_custom_roi_head.py @@ -10,6 +10,7 @@ import torch from mmdet.structures import DetDataSample from mmengine.structures import InstanceData + from otx.algo.instance_segmentation.heads.custom_roi_head import CustomRoIHead from otx.algo.instance_segmentation.maskrcnn import MaskRCNN diff --git a/tests/unit/algo/instance_segmentation/test_evaluation.py b/tests/unit/algo/instance_segmentation/test_evaluation.py index 06ae5a4772c..bb4b472d730 100644 --- a/tests/unit/algo/instance_segmentation/test_evaluation.py +++ b/tests/unit/algo/instance_segmentation/test_evaluation.py @@ -1,7 +1,8 @@ import torch +from torchmetrics.detection.mean_ap import MeanAveragePrecision + from otx.algo.instance_segmentation.otx_instseg_evaluation import OTXMaskRLEMeanAveragePrecision from otx.core.utils.mask_util import encode_rle -from torchmetrics.detection.mean_ap import MeanAveragePrecision def test_custom_rle_map_metric(num_masks=50, h=10, w=10): diff --git a/tests/unit/algo/samplers/test_balanced_sampler.py b/tests/unit/algo/samplers/test_balanced_sampler.py index 587f9d61990..276359cfc05 100644 --- a/tests/unit/algo/samplers/test_balanced_sampler.py +++ b/tests/unit/algo/samplers/test_balanced_sampler.py @@ -7,6 +7,7 @@ from datumaro.components.annotation import Label from datumaro.components.dataset import Dataset as DmDataset from datumaro.components.dataset_base import DatasetItem + from otx.algo.samplers.balanced_sampler import BalancedSampler from otx.core.data.dataset.base import OTXDataset from otx.core.utils.utils import get_idx_list_per_classes diff --git a/tests/unit/algo/samplers/test_class_incremental_sampler.py b/tests/unit/algo/samplers/test_class_incremental_sampler.py index 2482c9c1f1d..54b2ad69302 100644 --- a/tests/unit/algo/samplers/test_class_incremental_sampler.py +++ b/tests/unit/algo/samplers/test_class_incremental_sampler.py @@ -5,6 +5,7 @@ from datumaro.components.annotation import Label from datumaro.components.dataset import Dataset as DmDataset from datumaro.components.dataset_base import DatasetItem + from otx.algo.samplers.class_incremental_sampler import ClassIncrementalSampler from otx.core.data.dataset.base import OTXDataset from otx.core.utils.utils import get_idx_list_per_classes diff --git a/tests/unit/algo/segmentation/backbones/litehrnet.py b/tests/unit/algo/segmentation/backbones/litehrnet.py index 97b075b25fa..d95e79d1e07 100644 --- a/tests/unit/algo/segmentation/backbones/litehrnet.py +++ b/tests/unit/algo/segmentation/backbones/litehrnet.py @@ -2,6 +2,7 @@ import pytest import torch + from otx.algo.segmentation.model.backbones.litehrnet import LiteHRNet, NeighbourSupport, SpatialWeightingV2, StemV2 diff --git a/tests/unit/algo/segmentation/heads/test_class_incremental_mixin.py b/tests/unit/algo/segmentation/heads/test_class_incremental_mixin.py index 7b16a0b94f6..6b7c25624fe 100644 --- a/tests/unit/algo/segmentation/heads/test_class_incremental_mixin.py +++ b/tests/unit/algo/segmentation/heads/test_class_incremental_mixin.py @@ -5,6 +5,7 @@ from typing import ClassVar import torch + from otx.algo.segmentation.litehrnet import LiteHRNet diff --git a/tests/unit/algo/utils/test_support_otx_v1.py b/tests/unit/algo/utils/test_support_otx_v1.py index 57eeca84ea2..c0c0ab005ae 100644 --- a/tests/unit/algo/utils/test_support_otx_v1.py +++ b/tests/unit/algo/utils/test_support_otx_v1.py @@ -6,6 +6,7 @@ import pytest import torch + from otx.algo.utils.support_otx_v1 import OTXv1Helper diff --git a/tests/unit/algo/visual_prompting/backbones/test_tiny_vit.py b/tests/unit/algo/visual_prompting/backbones/test_tiny_vit.py index 334ec8d3ec4..d87d31d8e4a 100644 --- a/tests/unit/algo/visual_prompting/backbones/test_tiny_vit.py +++ b/tests/unit/algo/visual_prompting/backbones/test_tiny_vit.py @@ -5,6 +5,8 @@ import pytest import torch +from torch import nn + from otx.algo.visual_prompting.backbones.tiny_vit import ( Attention, BasicLayer, @@ -17,7 +19,6 @@ TinyViT, TinyViTBlock, ) -from torch import nn class TestConv2d_BN: # noqa: N801 diff --git a/tests/unit/algo/visual_prompting/backbones/test_vit.py b/tests/unit/algo/visual_prompting/backbones/test_vit.py index 92dcb8c4a3e..018b3bdfe05 100644 --- a/tests/unit/algo/visual_prompting/backbones/test_vit.py +++ b/tests/unit/algo/visual_prompting/backbones/test_vit.py @@ -5,6 +5,8 @@ import pytest import torch +from torch import Tensor, nn + from otx.algo.visual_prompting.backbones.vit import ( Attention, Block, @@ -16,7 +18,6 @@ window_unpartition, ) from otx.algo.visual_prompting.utils import MLPBlock -from torch import Tensor, nn class TestViT: diff --git a/tests/unit/algo/visual_prompting/conftest.py b/tests/unit/algo/visual_prompting/conftest.py index f9567775649..427c42f7edf 100644 --- a/tests/unit/algo/visual_prompting/conftest.py +++ b/tests/unit/algo/visual_prompting/conftest.py @@ -5,6 +5,8 @@ import pytest import torch +from torchvision import tv_tensors + from otx.core.data.entity.base import ImageInfo, Points from otx.core.data.entity.visual_prompting import ( VisualPromptingBatchDataEntity, @@ -14,7 +16,6 @@ ZeroShotVisualPromptingBatchPredEntity, ZeroShotVisualPromptingDataEntity, ) -from torchvision import tv_tensors @pytest.fixture(scope="session") diff --git a/tests/unit/algo/visual_prompting/decoders/test_sam_mask_decoder.py b/tests/unit/algo/visual_prompting/decoders/test_sam_mask_decoder.py index 2aa5a998690..e3e75d4575e 100644 --- a/tests/unit/algo/visual_prompting/decoders/test_sam_mask_decoder.py +++ b/tests/unit/algo/visual_prompting/decoders/test_sam_mask_decoder.py @@ -5,6 +5,8 @@ import pytest import torch +from torch import nn + from otx.algo.visual_prompting.decoders.sam_mask_decoder import ( MLP, Attention, @@ -13,7 +15,6 @@ TwoWayTransformer, ) from otx.algo.visual_prompting.utils.mlp_block import MLPBlock -from torch import nn class TestSAMMaskDecoder: diff --git a/tests/unit/algo/visual_prompting/encoders/test_sam_image_encoder.py b/tests/unit/algo/visual_prompting/encoders/test_sam_image_encoder.py index f1f87b81ffa..4d5c414e575 100644 --- a/tests/unit/algo/visual_prompting/encoders/test_sam_image_encoder.py +++ b/tests/unit/algo/visual_prompting/encoders/test_sam_image_encoder.py @@ -2,6 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 import pytest + from otx.algo.visual_prompting.encoders.sam_image_encoder import SAMImageEncoder diff --git a/tests/unit/algo/visual_prompting/encoders/test_sam_prompt_encoder.py b/tests/unit/algo/visual_prompting/encoders/test_sam_prompt_encoder.py index dbb57cb74ea..cb11f25afb9 100644 --- a/tests/unit/algo/visual_prompting/encoders/test_sam_prompt_encoder.py +++ b/tests/unit/algo/visual_prompting/encoders/test_sam_prompt_encoder.py @@ -5,9 +5,10 @@ import pytest import torch -from otx.algo.visual_prompting.encoders.sam_prompt_encoder import PositionEmbeddingRandom, SAMPromptEncoder from torch import nn +from otx.algo.visual_prompting.encoders.sam_prompt_encoder import PositionEmbeddingRandom, SAMPromptEncoder + class TestSAMPromptEncoder: @pytest.fixture(autouse=True) diff --git a/tests/unit/algo/visual_prompting/test_openvino_models.py b/tests/unit/algo/visual_prompting/test_openvino_models.py index bd821b1f60c..b5849db1b59 100644 --- a/tests/unit/algo/visual_prompting/test_openvino_models.py +++ b/tests/unit/algo/visual_prompting/test_openvino_models.py @@ -10,6 +10,7 @@ from openvino.model_api.adapters.openvino_adapter import OpenvinoAdapter from openvino.model_api.models import ImageModel, SegmentationModel from openvino.model_api.models.types import NumericalValue + from otx.algo.visual_prompting.openvino_models import VisualPromptingDecoder, VisualPromptingImageEncoder diff --git a/tests/unit/algo/visual_prompting/test_segment_anything.py b/tests/unit/algo/visual_prompting/test_segment_anything.py index 329289e976a..c14bb57881c 100644 --- a/tests/unit/algo/visual_prompting/test_segment_anything.py +++ b/tests/unit/algo/visual_prompting/test_segment_anything.py @@ -5,11 +5,12 @@ import pytest import torch +from torch import Tensor +from torchvision import tv_tensors + from otx.algo.visual_prompting.segment_anything import OTXSegmentAnything, SegmentAnything from otx.core.data.entity.base import Points from otx.core.data.entity.visual_prompting import VisualPromptingBatchPredEntity -from torch import Tensor -from torchvision import tv_tensors class TestSegmentAnything: diff --git a/tests/unit/algo/visual_prompting/test_zero_shot_segment_anything.py b/tests/unit/algo/visual_prompting/test_zero_shot_segment_anything.py index 95578b3de69..f09c2bd229c 100644 --- a/tests/unit/algo/visual_prompting/test_zero_shot_segment_anything.py +++ b/tests/unit/algo/visual_prompting/test_zero_shot_segment_anything.py @@ -8,6 +8,9 @@ import pytest import torch +from torch import Tensor +from torchvision import tv_tensors + from otx.algo.visual_prompting.zero_shot_segment_anything import ( OTXZeroShotSegmentAnything, PromptGetter, @@ -15,8 +18,6 @@ ) from otx.core.data.entity.base import Points from otx.core.data.entity.visual_prompting import ZeroShotVisualPromptingBatchPredEntity -from torch import Tensor -from torchvision import tv_tensors class TestPromptGetter: diff --git a/tests/unit/algo/visual_prompting/utils/test_layer_norm_2d.py b/tests/unit/algo/visual_prompting/utils/test_layer_norm_2d.py index 93718efc71b..9ba3ef8200a 100644 --- a/tests/unit/algo/visual_prompting/utils/test_layer_norm_2d.py +++ b/tests/unit/algo/visual_prompting/utils/test_layer_norm_2d.py @@ -3,6 +3,7 @@ import torch + from otx.algo.visual_prompting.utils.layer_norm_2d import LayerNorm2d diff --git a/tests/unit/cli/test_cli.py b/tests/unit/cli/test_cli.py index 0eea9f1bc57..1e1cedddbea 100644 --- a/tests/unit/cli/test_cli.py +++ b/tests/unit/cli/test_cli.py @@ -6,6 +6,7 @@ import pytest import yaml + from otx.cli import OTXCLI, main diff --git a/tests/unit/cli/test_install.py b/tests/unit/cli/test_install.py index a55c587a8a9..26f5be00851 100644 --- a/tests/unit/cli/test_install.py +++ b/tests/unit/cli/test_install.py @@ -4,10 +4,11 @@ import pytest from _pytest.monkeypatch import MonkeyPatch from jsonargparse import ArgumentParser -from otx.cli.install import add_install_parser, otx_install from pkg_resources import Requirement from pytest_mock.plugin import MockerFixture +from otx.cli.install import add_install_parser, otx_install + class TestInstall: @pytest.fixture(autouse=True) diff --git a/tests/unit/cli/utils/test_help_formatter.py b/tests/unit/cli/utils/test_help_formatter.py index 61a05a6e27b..53e4ffc06a4 100644 --- a/tests/unit/cli/utils/test_help_formatter.py +++ b/tests/unit/cli/utils/test_help_formatter.py @@ -8,6 +8,7 @@ import pytest from jsonargparse import ArgumentParser + from otx.cli.utils.help_formatter import ( CustomHelpFormatter, get_cli_usage_docstring, diff --git a/tests/unit/cli/utils/test_installation.py b/tests/unit/cli/utils/test_installation.py index ecdc1552279..c2cfb148053 100644 --- a/tests/unit/cli/utils/test_installation.py +++ b/tests/unit/cli/utils/test_installation.py @@ -7,6 +7,9 @@ import pkg_resources import pytest +from pkg_resources import Requirement +from pytest_mock import MockerFixture + from otx.cli.utils.installation import ( add_hardware_suffix_to_torch, get_cuda_suffix, @@ -20,8 +23,6 @@ parse_requirements, update_cuda_version_with_available_torch_cuda_build, ) -from pkg_resources import Requirement -from pytest_mock import MockerFixture @pytest.fixture() diff --git a/tests/unit/cli/utils/test_jsonargparse.py b/tests/unit/cli/utils/test_jsonargparse.py index 2137d76526e..468937b9991 100644 --- a/tests/unit/cli/utils/test_jsonargparse.py +++ b/tests/unit/cli/utils/test_jsonargparse.py @@ -3,6 +3,7 @@ import pytest from jsonargparse import Namespace + from otx.cli.utils.jsonargparse import ( flatten_dict, get_configuration, diff --git a/tests/unit/core/conftest.py b/tests/unit/core/conftest.py index 5ef50e9eff9..84136b2bd82 100644 --- a/tests/unit/core/conftest.py +++ b/tests/unit/core/conftest.py @@ -9,6 +9,8 @@ from datumaro.components.annotation import AnnotationType, LabelCategories from datumaro.components.dataset import Dataset, DatasetItem from datumaro.components.media import Image +from torchvision import tv_tensors + from otx.core.config import register_configs from otx.core.data.dataset.base import LabelInfo from otx.core.data.dataset.classification import HLabelInfo @@ -21,7 +23,6 @@ ZeroShotVisualPromptingBatchPredEntity, ZeroShotVisualPromptingDataEntity, ) -from torchvision import tv_tensors @pytest.fixture(scope="session", autouse=True) diff --git a/tests/unit/core/data/conftest.py b/tests/unit/core/data/conftest.py index f9105cefb6d..522c35337a2 100644 --- a/tests/unit/core/data/conftest.py +++ b/tests/unit/core/data/conftest.py @@ -12,6 +12,7 @@ from datumaro.components.dataset import DatasetSubset from datumaro.components.dataset_base import DatasetItem from datumaro.components.media import Image + from otx.core.data.dataset.classification import ( MulticlassClsDataEntity, OTXMulticlassClsDataset, @@ -27,9 +28,10 @@ from otx.core.data.mem_cache import MemCacheHandlerSingleton if TYPE_CHECKING: + from pytest_mock import MockerFixture + from otx.core.data.dataset.base import OTXDataset, T_OTXDataEntity from otx.core.data.mem_cache import MemCacheHandlerBase - from pytest_mock import MockerFixture @pytest.fixture() diff --git a/tests/unit/core/data/dataset/test_visual_prompting.py b/tests/unit/core/data/dataset/test_visual_prompting.py index 51795c0f861..edd32027e11 100644 --- a/tests/unit/core/data/dataset/test_visual_prompting.py +++ b/tests/unit/core/data/dataset/test_visual_prompting.py @@ -7,12 +7,13 @@ import numpy as np import pytest from datumaro import Dataset as DmDataset -from otx.core.data.dataset.visual_prompting import OTXVisualPromptingDataset, OTXZeroShotVisualPromptingDataset -from otx.core.data.entity.base import ImageInfo, Points from torch import Tensor from torchvision.transforms.v2 import Identity, Transform from torchvision.tv_tensors import BoundingBoxes, Image, Mask +from otx.core.data.dataset.visual_prompting import OTXVisualPromptingDataset, OTXZeroShotVisualPromptingDataset +from otx.core.data.entity.base import ImageInfo, Points + class TestOTXVisualPromptingDataset: @pytest.fixture() diff --git a/tests/unit/core/data/entity/conftest.py b/tests/unit/core/data/entity/conftest.py index 00e31e2cd7e..53f0995bb1b 100644 --- a/tests/unit/core/data/entity/conftest.py +++ b/tests/unit/core/data/entity/conftest.py @@ -6,11 +6,12 @@ import pytest import torch from datumaro import Polygon -from otx.core.data.entity.base import ImageInfo, OTXDataEntity, Points -from otx.core.data.entity.visual_prompting import VisualPromptingDataEntity from torch import LongTensor from torchvision import tv_tensors +from otx.core.data.entity.base import ImageInfo, OTXDataEntity, Points +from otx.core.data.entity.visual_prompting import VisualPromptingDataEntity + @pytest.fixture() def fxt_numpy_data_entity() -> OTXDataEntity: diff --git a/tests/unit/core/data/entity/test_base.py b/tests/unit/core/data/entity/test_base.py index 7515327135d..033c8c5eb87 100644 --- a/tests/unit/core/data/entity/test_base.py +++ b/tests/unit/core/data/entity/test_base.py @@ -7,6 +7,7 @@ import torch import torchvision.transforms.v2 as tvt import torchvision.transforms.v2.functional as F # noqa: N812 + from otx.core.data.entity.base import ImageType, OTXBatchDataEntity, OTXDataEntity, Points from otx.core.data.entity.visual_prompting import VisualPromptingDataEntity diff --git a/tests/unit/core/data/entity/test_detection.py b/tests/unit/core/data/entity/test_detection.py index 28dcfc7cdf9..0bddfb77704 100644 --- a/tests/unit/core/data/entity/test_detection.py +++ b/tests/unit/core/data/entity/test_detection.py @@ -3,11 +3,12 @@ """Unit tests of detection data entity.""" import torch +from torch import LongTensor +from torchvision import tv_tensors + from otx.core.data.entity.base import ImageInfo from otx.core.data.entity.detection import DetBatchDataEntity, DetDataEntity from otx.core.types.task import OTXTaskType -from torch import LongTensor -from torchvision import tv_tensors class TestDetDataEntity: diff --git a/tests/unit/core/data/entity/test_visual_prompting.py b/tests/unit/core/data/entity/test_visual_prompting.py index 94ece5a86a6..0a2f6fb0d03 100644 --- a/tests/unit/core/data/entity/test_visual_prompting.py +++ b/tests/unit/core/data/entity/test_visual_prompting.py @@ -5,6 +5,9 @@ import torch from datumaro import Polygon +from torch import LongTensor +from torchvision import tv_tensors + from otx.core.data.entity.base import ImageInfo, Points from otx.core.data.entity.visual_prompting import ( VisualPromptingBatchDataEntity, @@ -13,8 +16,6 @@ ZeroShotVisualPromptingDataEntity, ) from otx.core.types.task import OTXTaskType -from torch import LongTensor -from torchvision import tv_tensors class TestVisualPromptingDataEntity: diff --git a/tests/unit/core/data/test_factory.py b/tests/unit/core/data/test_factory.py index 328ad03d173..eef222fa29a 100644 --- a/tests/unit/core/data/test_factory.py +++ b/tests/unit/core/data/test_factory.py @@ -4,6 +4,7 @@ """Test Factory classes for dataset and transforms.""" import pytest + from otx.core.config.data import DataModuleConfig, SubsetConfig, TileConfig, VisualPromptingConfig from otx.core.data.dataset.classification import OTXMulticlassClsDataset from otx.core.data.dataset.detection import OTXDetectionDataset diff --git a/tests/unit/core/data/test_mem_cache.py b/tests/unit/core/data/test_mem_cache.py index 9172978bfe0..e4f44807d36 100644 --- a/tests/unit/core/data/test_mem_cache.py +++ b/tests/unit/core/data/test_mem_cache.py @@ -8,6 +8,7 @@ import numpy as np import psutil import pytest + from otx.core.data.mem_cache import ( MemCacheHandlerSingleton, parse_mem_cache_size_to_int, diff --git a/tests/unit/core/data/test_module.py b/tests/unit/core/data/test_module.py index 9746e79789f..c1703b83c2d 100644 --- a/tests/unit/core/data/test_module.py +++ b/tests/unit/core/data/test_module.py @@ -8,6 +8,7 @@ from importlib_resources import files from lightning.pytorch.loggers import CSVLogger from omegaconf import DictConfig, OmegaConf + from otx.core.config.data import ( DataModuleConfig, SubsetConfig, diff --git a/tests/unit/core/data/test_pre_filtering.py b/tests/unit/core/data/test_pre_filtering.py index f3f9ccf2d18..eedc26330c6 100644 --- a/tests/unit/core/data/test_pre_filtering.py +++ b/tests/unit/core/data/test_pre_filtering.py @@ -5,6 +5,7 @@ from datumaro.components.annotation import Label from datumaro.components.dataset import Dataset as DmDataset from datumaro.components.dataset_base import DatasetItem + from otx.core.data.pre_filtering import pre_filtering diff --git a/tests/unit/core/data/test_transform_libs.py b/tests/unit/core/data/test_transform_libs.py index 0d9aac017e3..0d63ba44ed3 100644 --- a/tests/unit/core/data/test_transform_libs.py +++ b/tests/unit/core/data/test_transform_libs.py @@ -9,6 +9,9 @@ import torch from lightning.pytorch.cli import instantiate_class from omegaconf import OmegaConf +from torchvision import tv_tensors +from torchvision.transforms import v2 + from otx.core.config.data import SubsetConfig from otx.core.data.entity.base import Points from otx.core.data.transform_libs.torchvision import ( @@ -18,8 +21,6 @@ TorchVisionTransformLib, ) from otx.core.types.image import ImageColorChannel -from torchvision import tv_tensors -from torchvision.transforms import v2 class TestPerturbBoundingBoxes: diff --git a/tests/unit/core/data/transform_libs/test_mmcv.py b/tests/unit/core/data/transform_libs/test_mmcv.py index 06ab7e79724..bad160694ae 100644 --- a/tests/unit/core/data/transform_libs/test_mmcv.py +++ b/tests/unit/core/data/transform_libs/test_mmcv.py @@ -5,6 +5,7 @@ import numpy as np import pytest from mmcv.transforms.builder import TRANSFORMS + from otx.core.config.data import SubsetConfig from otx.core.data.entity.base import ImageInfo, OTXDataEntity from otx.core.data.transform_libs.mmcv import LoadImageFromFile, MMCVTransformLib diff --git a/tests/unit/core/data/transform_libs/test_mmdet.py b/tests/unit/core/data/transform_libs/test_mmdet.py index 0815a0ef976..c29bba49cd5 100644 --- a/tests/unit/core/data/transform_libs/test_mmdet.py +++ b/tests/unit/core/data/transform_libs/test_mmdet.py @@ -7,6 +7,9 @@ import numpy as np import pytest import torch +from torch import LongTensor +from torchvision import tv_tensors + from otx.core.config.data import SubsetConfig from otx.core.data.entity.base import ImageInfo from otx.core.data.entity.detection import DetDataEntity @@ -14,8 +17,6 @@ from otx.core.data.transform_libs.mmcv import LoadImageFromFile from otx.core.data.transform_libs.mmdet import LoadAnnotations, MMDetTransformLib, PackDetInputs, PerturbBoundingBoxes from otx.core.types.transformer_libs import TransformLibType -from torch import LongTensor -from torchvision import tv_tensors class TestLoadAnnotations: diff --git a/tests/unit/core/data/transform_libs/test_mmseg.py b/tests/unit/core/data/transform_libs/test_mmseg.py index df420569fa3..6edff99b27f 100644 --- a/tests/unit/core/data/transform_libs/test_mmseg.py +++ b/tests/unit/core/data/transform_libs/test_mmseg.py @@ -5,6 +5,7 @@ from __future__ import annotations import pytest + from otx.core.data.entity.segmentation import SegDataEntity from otx.core.data.transform_libs.mmcv import LoadImageFromFile from otx.core.data.transform_libs.mmseg import LoadAnnotations, PackSegInputs diff --git a/tests/unit/core/metrics/test_accuracy.py b/tests/unit/core/metrics/test_accuracy.py index 47c72b7f8b8..fe06af7b5a9 100644 --- a/tests/unit/core/metrics/test_accuracy.py +++ b/tests/unit/core/metrics/test_accuracy.py @@ -5,6 +5,7 @@ import pytest import torch + from otx.core.data.dataset.base import LabelInfo from otx.core.data.dataset.classification import HLabelInfo from otx.core.metrics.accuracy import ( diff --git a/tests/unit/core/metrics/test_fmeasure.py b/tests/unit/core/metrics/test_fmeasure.py index 0f364fa1654..7513bf57b92 100644 --- a/tests/unit/core/metrics/test_fmeasure.py +++ b/tests/unit/core/metrics/test_fmeasure.py @@ -7,6 +7,7 @@ import pytest import torch + from otx.core.metrics.fmeasure import FMeasure diff --git a/tests/unit/core/model/entity/test_base.py b/tests/unit/core/model/entity/test_base.py index 9a96a36f45a..243d588ca7c 100644 --- a/tests/unit/core/model/entity/test_base.py +++ b/tests/unit/core/model/entity/test_base.py @@ -2,6 +2,7 @@ import pytest import torch from openvino.model_api.models.utils import ClassificationResult + from otx.core.data.entity.base import OTXBatchDataEntity from otx.core.model.entity.base import OTXModel, OVModel diff --git a/tests/unit/core/model/entity/test_segmentation.py b/tests/unit/core/model/entity/test_segmentation.py index 288e09e4014..a63daba9020 100644 --- a/tests/unit/core/model/entity/test_segmentation.py +++ b/tests/unit/core/model/entity/test_segmentation.py @@ -11,6 +11,7 @@ import torch from importlib_resources import files from omegaconf import OmegaConf + from otx.core.model.entity.segmentation import MMSegCompatibleModel if TYPE_CHECKING: @@ -44,6 +45,7 @@ def test_customize_inputs(self, model, fxt_seg_data_entity) -> None: def test_customize_outputs(self, model, fxt_seg_data_entity) -> None: from mmengine.structures import PixelData from mmseg.structures import SegDataSample + from otx.core.data.entity.base import OTXBatchLossEntity from otx.core.data.entity.segmentation import SegBatchPredEntity diff --git a/tests/unit/core/model/entity/test_visual_prompting.py b/tests/unit/core/model/entity/test_visual_prompting.py index 7373b31fb11..e15671db4b7 100644 --- a/tests/unit/core/model/entity/test_visual_prompting.py +++ b/tests/unit/core/model/entity/test_visual_prompting.py @@ -11,6 +11,8 @@ import numpy as np import pytest import torch +from torchvision import tv_tensors + from otx.core.data.entity.visual_prompting import VisualPromptingBatchPredEntity from otx.core.exporter.visual_prompting import OTXVisualPromptingModelExporter from otx.core.model.entity.visual_prompting import ( @@ -18,7 +20,6 @@ OVVisualPromptingModel, OVZeroShotVisualPromptingModel, ) -from torchvision import tv_tensors class TestOTXVisualPromptingModel: diff --git a/tests/unit/core/model/module/test_base.py b/tests/unit/core/model/module/test_base.py index 9e294ddadb7..45d0cdc34ba 100644 --- a/tests/unit/core/model/module/test_base.py +++ b/tests/unit/core/model/module/test_base.py @@ -10,10 +10,11 @@ import pytest from lightning.pytorch.cli import ReduceLROnPlateau from lightning.pytorch.trainer import Trainer +from torch.optim import Optimizer + from otx.algo.schedulers.warmup_schedulers import LinearWarmupScheduler from otx.core.model.entity.base import OTXModel from otx.core.model.module.base import OTXLitModule -from torch.optim import Optimizer class TestOTXLitModule: diff --git a/tests/unit/core/model/module/test_detection.py b/tests/unit/core/model/module/test_detection.py index f694a2864f5..afe691a9da0 100644 --- a/tests/unit/core/model/module/test_detection.py +++ b/tests/unit/core/model/module/test_detection.py @@ -10,12 +10,13 @@ import pytest from lightning.pytorch.cli import ReduceLROnPlateau +from torch.optim import Optimizer + from otx.algo.schedulers.warmup_schedulers import LinearWarmupScheduler from otx.core.metrics.fmeasure import FMeasure from otx.core.model.entity.detection import OTXDetectionModel from otx.core.model.module.base import OTXLitModule from otx.core.model.module.detection import OTXDetectionLitModule -from torch.optim import Optimizer class TestOTXLitModule: diff --git a/tests/unit/core/model/module/test_segmentation.py b/tests/unit/core/model/module/test_segmentation.py index edb40c697a4..a1529f62aba 100644 --- a/tests/unit/core/model/module/test_segmentation.py +++ b/tests/unit/core/model/module/test_segmentation.py @@ -9,10 +9,11 @@ import pytest import torch +from torchmetrics.metric import Metric + from otx.core.data.entity.segmentation import SegBatchPredEntity from otx.core.model.entity.segmentation import MMSegCompatibleModel from otx.core.model.module.segmentation import OTXSegmentationLitModule -from torchmetrics.metric import Metric class MockMetric(torch.nn.Module): diff --git a/tests/unit/core/utils/test_mask_utils.py b/tests/unit/core/utils/test_mask_utils.py index 5f32eca07a9..965485e5fec 100644 --- a/tests/unit/core/utils/test_mask_utils.py +++ b/tests/unit/core/utils/test_mask_utils.py @@ -1,8 +1,9 @@ import numpy as np import torch -from otx.core.utils.mask_util import encode_rle from pycocotools import mask as mask_utils +from otx.core.utils.mask_util import encode_rle + def test_encode_rle(num_test_cases=30): """Test encode_rle function. diff --git a/tests/unit/core/utils/test_tile.py b/tests/unit/core/utils/test_tile.py index a32a13cf91f..2ba455fd2f5 100644 --- a/tests/unit/core/utils/test_tile.py +++ b/tests/unit/core/utils/test_tile.py @@ -11,6 +11,7 @@ from datumaro.plugins.tiling.util import xywh_to_x1y1x2y2 from openvino.model_api.models import Model from openvino.model_api.tilers import Tiler + from otx.core.data.dataset.tile import OTXTileTransform diff --git a/tests/unit/core/utils/test_utils.py b/tests/unit/core/utils/test_utils.py index 917c2e421ed..a7bd53cd2c4 100644 --- a/tests/unit/core/utils/test_utils.py +++ b/tests/unit/core/utils/test_utils.py @@ -1,4 +1,5 @@ import pytest + from otx.core.utils import utils as target_file from otx.core.utils.utils import get_adaptive_num_workers diff --git a/tests/unit/engine/utils/test_api.py b/tests/unit/engine/utils/test_api.py index e136058d463..f173c2e0c63 100644 --- a/tests/unit/engine/utils/test_api.py +++ b/tests/unit/engine/utils/test_api.py @@ -2,6 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 import pytest + from otx.core.types.task import OTXTaskType from otx.engine.utils.api import RECIPE_PATH, list_models diff --git a/tests/unit/engine/utils/test_auto_configurator.py b/tests/unit/engine/utils/test_auto_configurator.py index 028ea79177d..4fbbf37ea32 100644 --- a/tests/unit/engine/utils/test_auto_configurator.py +++ b/tests/unit/engine/utils/test_auto_configurator.py @@ -5,6 +5,7 @@ from pathlib import Path import pytest + from otx.core.data.dataset.base import LabelInfo from otx.core.data.module import OTXDataModule from otx.core.model.entity.base import OTXModel diff --git a/tests/unit/hpo/test_hpo_base.py b/tests/unit/hpo/test_hpo_base.py index 14b574b1d93..b169ecc4e81 100644 --- a/tests/unit/hpo/test_hpo_base.py +++ b/tests/unit/hpo/test_hpo_base.py @@ -2,6 +2,7 @@ from pathlib import Path import pytest + from otx.hpo.hpo_base import Trial diff --git a/tests/unit/hpo/test_hyperband.py b/tests/unit/hpo/test_hyperband.py index 00dad36d58c..63bf577c71d 100644 --- a/tests/unit/hpo/test_hyperband.py +++ b/tests/unit/hpo/test_hyperband.py @@ -12,6 +12,7 @@ from tempfile import TemporaryDirectory import pytest + from otx.hpo import hyperband from otx.hpo.hpo_base import TrialStatus from otx.hpo.hyperband import AshaTrial, Bracket, HyperBand, Rung diff --git a/tests/unit/hpo/test_resource_manager.py b/tests/unit/hpo/test_resource_manager.py index f1688931750..e7b35cfbfbb 100644 --- a/tests/unit/hpo/test_resource_manager.py +++ b/tests/unit/hpo/test_resource_manager.py @@ -1,4 +1,5 @@ import pytest + from otx.hpo.resource_manager import ( CPUResourceManager, GPUResourceManager, diff --git a/tests/unit/hpo/test_search_space.py b/tests/unit/hpo/test_search_space.py index d72b76c1eba..b1e422d0471 100644 --- a/tests/unit/hpo/test_search_space.py +++ b/tests/unit/hpo/test_search_space.py @@ -2,6 +2,7 @@ import math import pytest + from otx.hpo.search_space import SearchSpace, SingleSearchSpace ALL_TYPE = ["uniform", "loguniform", "quniform", "qloguniform", "choice"] diff --git a/tests/unit/utils/test_utils.py b/tests/unit/utils/test_utils.py index 10a6a939257..45b04862204 100644 --- a/tests/unit/utils/test_utils.py +++ b/tests/unit/utils/test_utils.py @@ -3,6 +3,7 @@ from pathlib import Path import pytest + from otx.utils.utils import ( find_file_recursively, get_decimal_point, From df7d89e7d144ab8b26b9efae2b04bcec76c15006 Mon Sep 17 00:00:00 2001 From: kprokofi Date: Mon, 18 Mar 2024 23:32:35 +0000 Subject: [PATCH 18/42] fix pre-commit --- docker/download_pretrained_weights.py | 1 - .../heads/custom_multilabel_non_linear_cls_head.py | 3 ++- src/otx/algo/detection/backbones/pytorchcv_backbones.py | 3 ++- src/otx/algo/detection/utils/mmcv_patched_ops.py | 3 ++- src/otx/algo/segmentation/backbones/litehrnet.py | 2 +- src/otx/algo/utils/segmentation.py | 3 ++- src/otx/core/data/transform_libs/mmaction.py | 2 +- src/otx/core/data/transform_libs/mmcv.py | 2 +- src/otx/core/data/transform_libs/mmdet.py | 2 +- src/otx/engine/engine.py | 4 ++-- tests/conftest.py | 3 +-- tests/integration/api/test_auto_configuration.py | 1 - tests/integration/api/test_engine_api.py | 1 - tests/integration/cli/test_auto_configuration.py | 2 +- tests/integration/cli/test_cli.py | 2 +- tests/integration/conftest.py | 1 - tests/integration/detection/conftest.py | 1 - tests/integration/detection/test_model.py | 1 - tests/integration/test_tiling.py | 1 - .../algo/action_classification/backbones/test_movinet.py | 1 - .../algo/action_classification/heads/test_movinet_head.py | 1 - .../recognizers/test_movinet_recognizer.py | 1 - tests/unit/algo/callbacks/test_adaptive_train_scheduling.py | 3 +-- tests/unit/algo/callbacks/test_iteration_timer.py | 1 - .../algo/classification/backbones/test_otx_efficientnet.py | 1 - .../classification/backbones/test_otx_efficientnet_v2.py | 1 - .../algo/classification/backbones/test_otx_mobilenet_v3.py | 1 - tests/unit/algo/classification/conftest.py | 3 +-- .../algo/classification/heads/test_custom_hlabel_cls_head.py | 3 +-- .../classification/heads/test_custom_multilabel_cls_head.py | 1 - .../algo/classification/losses/test_asymmetric_multilabel.py | 1 - tests/unit/algo/classification/test_otx_dino_v2.py | 1 - tests/unit/algo/classification/test_torchvision_model.py | 1 - .../algo/detection/backbones/test_pytorchcv_backbones.py | 3 +-- .../algo/detection/heads/test_class_incremental_mixin.py | 1 - .../algo/detection/heads/test_custom_anchor_generator.py | 1 - tests/unit/algo/detection/heads/test_custom_ssd_head.py | 1 - tests/unit/algo/detection/test_ssd.py | 1 - tests/unit/algo/hooks/test_saliency_map_dumping.py | 1 - tests/unit/algo/hooks/test_saliency_map_processing.py | 1 - tests/unit/algo/hooks/test_xai_hooks.py | 5 ++--- .../algo/instance_segmentation/heads/test_custom_roi_head.py | 1 - tests/unit/algo/instance_segmentation/test_evaluation.py | 3 +-- tests/unit/algo/samplers/test_balanced_sampler.py | 1 - tests/unit/algo/samplers/test_class_incremental_sampler.py | 1 - .../algo/segmentation/heads/test_class_incremental_mixin.py | 1 - tests/unit/algo/utils/test_support_otx_v1.py | 1 - tests/unit/algo/visual_prompting/backbones/test_tiny_vit.py | 3 +-- tests/unit/algo/visual_prompting/backbones/test_vit.py | 3 +-- tests/unit/algo/visual_prompting/conftest.py | 3 +-- .../algo/visual_prompting/decoders/test_sam_mask_decoder.py | 3 +-- .../algo/visual_prompting/encoders/test_sam_image_encoder.py | 1 - .../visual_prompting/encoders/test_sam_prompt_encoder.py | 3 +-- tests/unit/algo/visual_prompting/test_openvino_models.py | 1 - tests/unit/algo/visual_prompting/test_segment_anything.py | 5 ++--- .../algo/visual_prompting/test_zero_shot_segment_anything.py | 5 ++--- tests/unit/algo/visual_prompting/utils/test_layer_norm_2d.py | 1 - tests/unit/cli/test_cli.py | 1 - tests/unit/cli/test_install.py | 3 +-- tests/unit/cli/utils/test_help_formatter.py | 1 - tests/unit/cli/utils/test_installation.py | 5 ++--- tests/unit/cli/utils/test_jsonargparse.py | 1 - tests/unit/core/conftest.py | 3 +-- tests/unit/core/data/conftest.py | 4 +--- tests/unit/core/data/dataset/test_visual_prompting.py | 5 ++--- tests/unit/core/data/entity/conftest.py | 5 ++--- tests/unit/core/data/entity/test_base.py | 1 - tests/unit/core/data/entity/test_detection.py | 5 ++--- tests/unit/core/data/entity/test_visual_prompting.py | 5 ++--- tests/unit/core/data/test_factory.py | 1 - tests/unit/core/data/test_mem_cache.py | 1 - tests/unit/core/data/test_module.py | 1 - tests/unit/core/data/test_pre_filtering.py | 1 - tests/unit/core/data/test_transform_libs.py | 5 ++--- tests/unit/core/data/transform_libs/test_mmcv.py | 4 ++-- tests/unit/core/data/transform_libs/test_mmdet.py | 5 ++--- tests/unit/core/data/transform_libs/test_mmseg.py | 1 - tests/unit/core/metrics/test_accuracy.py | 1 - tests/unit/core/metrics/test_fmeasure.py | 1 - tests/unit/core/model/entity/test_base.py | 1 - tests/unit/core/model/entity/test_segmentation.py | 2 -- tests/unit/core/model/entity/test_visual_prompting.py | 3 +-- tests/unit/core/model/module/test_base.py | 3 +-- tests/unit/core/model/module/test_detection.py | 3 +-- tests/unit/core/model/module/test_segmentation.py | 3 +-- tests/unit/core/utils/test_mask_utils.py | 3 +-- tests/unit/core/utils/test_tile.py | 1 - tests/unit/core/utils/test_utils.py | 1 - tests/unit/engine/utils/test_api.py | 1 - tests/unit/engine/utils/test_auto_configurator.py | 1 - tests/unit/hpo/test_hpo_base.py | 1 - tests/unit/hpo/test_hyperband.py | 1 - tests/unit/hpo/test_resource_manager.py | 1 - tests/unit/hpo/test_search_space.py | 1 - tests/unit/utils/test_utils.py | 1 - 95 files changed, 57 insertions(+), 138 deletions(-) diff --git a/docker/download_pretrained_weights.py b/docker/download_pretrained_weights.py index ea9eafaaaba..7fee845239e 100644 --- a/docker/download_pretrained_weights.py +++ b/docker/download_pretrained_weights.py @@ -8,7 +8,6 @@ from importlib_resources import files from omegaconf import OmegaConf - from otx.core.utils.instantiators import partial_instantiate_class logging.basicConfig( diff --git a/src/otx/algo/classification/heads/custom_multilabel_non_linear_cls_head.py b/src/otx/algo/classification/heads/custom_multilabel_non_linear_cls_head.py index dda7800a3fc..853ebf3c7ad 100644 --- a/src/otx/algo/classification/heads/custom_multilabel_non_linear_cls_head.py +++ b/src/otx/algo/classification/heads/custom_multilabel_non_linear_cls_head.py @@ -8,12 +8,13 @@ from typing import TYPE_CHECKING import torch -from mmcv.cnn import build_activation_layer from mmengine.model import constant_init, normal_init from mmpretrain.models.heads import MultiLabelClsHead from mmpretrain.registry import MODELS from torch import nn +from mmcv.cnn import build_activation_layer + from .custom_multilabel_linear_cls_head import AnglularLinear if TYPE_CHECKING: diff --git a/src/otx/algo/detection/backbones/pytorchcv_backbones.py b/src/otx/algo/detection/backbones/pytorchcv_backbones.py index fd10250dc00..643b784420b 100644 --- a/src/otx/algo/detection/backbones/pytorchcv_backbones.py +++ b/src/otx/algo/detection/backbones/pytorchcv_backbones.py @@ -9,7 +9,6 @@ from typing import TYPE_CHECKING import torch -from mmcv.cnn import build_activation_layer, build_norm_layer from mmdet.registry import MODELS from mmengine.dist import get_dist_info from pytorchcv.model_provider import _models @@ -17,6 +16,8 @@ from torch import distributed, nn from torch.nn.modules.batchnorm import _BatchNorm +from mmcv.cnn import build_activation_layer, build_norm_layer + if TYPE_CHECKING: from mmdet.registry import Registry from mmengine.config import Config, ConfigDict diff --git a/src/otx/algo/detection/utils/mmcv_patched_ops.py b/src/otx/algo/detection/utils/mmcv_patched_ops.py index 4ea42163f16..c43b9088c5f 100644 --- a/src/otx/algo/detection/utils/mmcv_patched_ops.py +++ b/src/otx/algo/detection/utils/mmcv_patched_ops.py @@ -8,10 +8,11 @@ from typing import TYPE_CHECKING import torch -from mmcv.utils import ext_loader from torchvision.ops import nms as tv_nms from torchvision.ops import roi_align as tv_roi_align +from mmcv.utils import ext_loader + if TYPE_CHECKING: from mmcv.ops.nms import NMSop from mmcv.ops.roi_align import RoIAlign diff --git a/src/otx/algo/segmentation/backbones/litehrnet.py b/src/otx/algo/segmentation/backbones/litehrnet.py index b503f5a65c3..05bac2aa5d0 100644 --- a/src/otx/algo/segmentation/backbones/litehrnet.py +++ b/src/otx/algo/segmentation/backbones/litehrnet.py @@ -12,13 +12,13 @@ import torch import torch.utils.checkpoint as cp -from mmcv.cnn import ConvModule, build_conv_layer, build_norm_layer from mmengine.model import BaseModule from mmengine.utils import is_tuple_of from mmseg.registry import MODELS from torch import nn from torch.nn import functional +from mmcv.cnn import ConvModule, build_conv_layer, build_norm_layer from otx.algo.utils.segmentation import ( AsymmetricPositionAttentionModule, IterativeAggregator, diff --git a/src/otx/algo/utils/segmentation.py b/src/otx/algo/utils/segmentation.py index af40ce316dd..bb2ae2acce4 100644 --- a/src/otx/algo/utils/segmentation.py +++ b/src/otx/algo/utils/segmentation.py @@ -9,10 +9,11 @@ import torch import torch.nn.functional as f -from mmcv.cnn import ConvModule, DepthwiseSeparableConvModule from torch import nn from torch.nn import AdaptiveAvgPool2d, AdaptiveMaxPool2d +from mmcv.cnn import ConvModule, DepthwiseSeparableConvModule + def channel_shuffle(x: torch.Tensor, groups: int) -> torch.Tensor: """Channel Shuffle operation. diff --git a/src/otx/core/data/transform_libs/mmaction.py b/src/otx/core/data/transform_libs/mmaction.py index f1f2f6994f1..2d61ce7c967 100644 --- a/src/otx/core/data/transform_libs/mmaction.py +++ b/src/otx/core/data/transform_libs/mmaction.py @@ -10,7 +10,6 @@ from pathlib import Path from typing import TYPE_CHECKING, Any, Callable -import mmcv import numpy as np from mmaction.datasets.transforms import PackActionInputs as MMPackActionInputs from mmaction.datasets.transforms import RawFrameDecode as MMRawFrameDecode @@ -18,6 +17,7 @@ from mmengine.fileio import FileClient from torchvision import tv_tensors +import mmcv from otx.core.data.entity.action_classification import ActionClsDataEntity from otx.core.data.entity.action_detection import ActionDetDataEntity from otx.core.utils.config import convert_conf_to_mmconfig_dict diff --git a/src/otx/core/data/transform_libs/mmcv.py b/src/otx/core/data/transform_libs/mmcv.py index f763aee3be4..755a691ce92 100644 --- a/src/otx/core/data/transform_libs/mmcv.py +++ b/src/otx/core/data/transform_libs/mmcv.py @@ -8,9 +8,9 @@ from typing import TYPE_CHECKING, Callable import numpy as np + from mmcv.transforms import LoadImageFromFile as MMCVLoadImageFromFile from mmcv.transforms.builder import TRANSFORMS - from otx.core.data.entity.base import OTXDataEntity from otx.core.utils.config import convert_conf_to_mmconfig_dict diff --git a/src/otx/core/data/transform_libs/mmdet.py b/src/otx/core/data/transform_libs/mmdet.py index 68353b4c4d8..93ddf24a031 100644 --- a/src/otx/core/data/transform_libs/mmdet.py +++ b/src/otx/core/data/transform_libs/mmdet.py @@ -12,7 +12,6 @@ import numpy as np import torch from datumaro import Polygon -from mmcv.transforms import BaseTransform from mmdet.datasets.transforms import LoadAnnotations as MMDetLoadAnnotations from mmdet.datasets.transforms import PackDetInputs as MMDetPackDetInputs from mmdet.registry import TRANSFORMS as MMDET_TRANSFORMS @@ -20,6 +19,7 @@ from mmengine.registry import Registry from torchvision import tv_tensors +from mmcv.transforms import BaseTransform from otx.core.data.entity.base import ImageInfo from otx.core.data.entity.detection import DetDataEntity from otx.core.data.entity.instance_segmentation import InstanceSegDataEntity diff --git a/src/otx/engine/engine.py b/src/otx/engine/engine.py index 096c8d2a86f..5e3f8720da6 100644 --- a/src/otx/engine/engine.py +++ b/src/otx/engine/engine.py @@ -138,10 +138,10 @@ def __init__( ) if self.task in [OTXTaskType.DETECTION, OTXTaskType.INSTANCE_SEGMENTATION] and self.device.accelerator == "xpu": import numpy as np - from mmcv.ops.nms import NMSop - from mmcv.ops.roi_align import RoIAlign from mmengine.structures import instance_data + from mmcv.ops.nms import NMSop + from mmcv.ops.roi_align import RoIAlign from otx.algo.detection.utils import monkey_patched_nms, monkey_patched_roi_align long_type_tensor = Union[torch.LongTensor, torch.xpu.LongTensor] diff --git a/tests/conftest.py b/tests/conftest.py index 2b8f119e2c8..9474bd8fc57 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -4,11 +4,10 @@ import pytest import torch -from torchvision.tv_tensors import Image, Mask - from otx.core.data.entity.base import ImageInfo from otx.core.data.entity.segmentation import SegBatchDataEntity, SegBatchPredEntity, SegDataEntity from otx.core.data.mem_cache import MemCacheHandlerSingleton +from torchvision.tv_tensors import Image, Mask @pytest.fixture(scope="session") diff --git a/tests/integration/api/test_auto_configuration.py b/tests/integration/api/test_auto_configuration.py index 1c2c82d107f..217a1e38688 100644 --- a/tests/integration/api/test_auto_configuration.py +++ b/tests/integration/api/test_auto_configuration.py @@ -4,7 +4,6 @@ from pathlib import Path import pytest - from otx.core.data.module import OTXDataModule from otx.core.model.entity.base import OTXModel from otx.core.types.task import OTXTaskType diff --git a/tests/integration/api/test_engine_api.py b/tests/integration/api/test_engine_api.py index 66d3d9ecf01..92b766d7371 100644 --- a/tests/integration/api/test_engine_api.py +++ b/tests/integration/api/test_engine_api.py @@ -7,7 +7,6 @@ import pytest from openvino.model_api.tilers import Tiler - from otx.core.data.module import OTXDataModule from otx.core.model.entity.base import OTXModel from otx.core.types.task import OTXTaskType diff --git a/tests/integration/cli/test_auto_configuration.py b/tests/integration/cli/test_auto_configuration.py index 33ae8543a98..069e54ca2c6 100644 --- a/tests/integration/cli/test_auto_configuration.py +++ b/tests/integration/cli/test_auto_configuration.py @@ -5,9 +5,9 @@ from pathlib import Path import pytest - from otx.core.types.task import OTXTaskType from otx.engine.utils.auto_configurator import DEFAULT_CONFIG_PER_TASK + from tests.integration.cli.utils import run_main diff --git a/tests/integration/cli/test_cli.py b/tests/integration/cli/test_cli.py index 81b318331a7..b438feff008 100644 --- a/tests/integration/cli/test_cli.py +++ b/tests/integration/cli/test_cli.py @@ -7,8 +7,8 @@ import numpy as np import pytest import yaml - from otx.engine.utils.auto_configurator import DEFAULT_CONFIG_PER_TASK + from tests.integration.cli.utils import run_main diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 3642fe74122..b4dcbd6f1b8 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -9,7 +9,6 @@ import pytest from mmengine.config import Config as MMConfig - from otx.core.types.task import OTXTaskType diff --git a/tests/integration/detection/conftest.py b/tests/integration/detection/conftest.py index f1464ea5b43..1464fc7d5ac 100644 --- a/tests/integration/detection/conftest.py +++ b/tests/integration/detection/conftest.py @@ -7,7 +7,6 @@ import pytest from omegaconf import DictConfig - from otx.core.config.data import ( DataModuleConfig, SubsetConfig, diff --git a/tests/integration/detection/test_model.py b/tests/integration/detection/test_model.py index b380b835e39..b88a02bf725 100644 --- a/tests/integration/detection/test_model.py +++ b/tests/integration/detection/test_model.py @@ -3,7 +3,6 @@ # import pytest from omegaconf import DictConfig - from otx.core.data.module import OTXDataModule from otx.core.model.entity.detection import MMDetCompatibleModel from otx.core.utils.config import mmconfig_dict_to_dict diff --git a/tests/integration/test_tiling.py b/tests/integration/test_tiling.py index b4913031312..574d8db14eb 100644 --- a/tests/integration/test_tiling.py +++ b/tests/integration/test_tiling.py @@ -8,7 +8,6 @@ import pytest from datumaro import Dataset as DmDataset from omegaconf import DictConfig, OmegaConf - from otx.core.config.data import ( DataModuleConfig, SubsetConfig, diff --git a/tests/unit/algo/action_classification/backbones/test_movinet.py b/tests/unit/algo/action_classification/backbones/test_movinet.py index fc22758e9bb..792387d52e2 100644 --- a/tests/unit/algo/action_classification/backbones/test_movinet.py +++ b/tests/unit/algo/action_classification/backbones/test_movinet.py @@ -4,7 +4,6 @@ import pytest import torch - from otx.algo.action_classification.backbones.movinet import OTXMoViNet diff --git a/tests/unit/algo/action_classification/heads/test_movinet_head.py b/tests/unit/algo/action_classification/heads/test_movinet_head.py index 14e73e0050b..5d1f9568a1e 100644 --- a/tests/unit/algo/action_classification/heads/test_movinet_head.py +++ b/tests/unit/algo/action_classification/heads/test_movinet_head.py @@ -5,7 +5,6 @@ import pytest import torch - from otx.algo.action_classification.heads.movinet_head import MoViNetHead diff --git a/tests/unit/algo/action_classification/recognizers/test_movinet_recognizer.py b/tests/unit/algo/action_classification/recognizers/test_movinet_recognizer.py index 15b354f8e3c..861e4ab97ec 100644 --- a/tests/unit/algo/action_classification/recognizers/test_movinet_recognizer.py +++ b/tests/unit/algo/action_classification/recognizers/test_movinet_recognizer.py @@ -5,7 +5,6 @@ import pytest import torch - from otx.algo.action_classification.recognizers.movinet_recognizer import MoViNetRecognizer diff --git a/tests/unit/algo/callbacks/test_adaptive_train_scheduling.py b/tests/unit/algo/callbacks/test_adaptive_train_scheduling.py index bde70063804..85eb23f8e85 100644 --- a/tests/unit/algo/callbacks/test_adaptive_train_scheduling.py +++ b/tests/unit/algo/callbacks/test_adaptive_train_scheduling.py @@ -8,9 +8,8 @@ from lightning.pytorch.callbacks.early_stopping import EarlyStopping from lightning.pytorch.cli import ReduceLROnPlateau from lightning.pytorch.utilities.types import LRSchedulerConfig -from torch.utils.data import DataLoader - from otx.algo.callbacks.adaptive_train_scheduling import AdaptiveTrainScheduling +from torch.utils.data import DataLoader class TestAdaptiveTrainScheduling: diff --git a/tests/unit/algo/callbacks/test_iteration_timer.py b/tests/unit/algo/callbacks/test_iteration_timer.py index 48957fe0b12..c17de5dab66 100644 --- a/tests/unit/algo/callbacks/test_iteration_timer.py +++ b/tests/unit/algo/callbacks/test_iteration_timer.py @@ -4,7 +4,6 @@ from unittest.mock import MagicMock, patch import pytest - from otx.algo.callbacks.iteration_timer import IterationTimer diff --git a/tests/unit/algo/classification/backbones/test_otx_efficientnet.py b/tests/unit/algo/classification/backbones/test_otx_efficientnet.py index 241c68410fe..3d4adefa7b5 100644 --- a/tests/unit/algo/classification/backbones/test_otx_efficientnet.py +++ b/tests/unit/algo/classification/backbones/test_otx_efficientnet.py @@ -4,7 +4,6 @@ import pytest import torch - from otx.algo.classification.backbones.otx_efficientnet import OTXEfficientNet diff --git a/tests/unit/algo/classification/backbones/test_otx_efficientnet_v2.py b/tests/unit/algo/classification/backbones/test_otx_efficientnet_v2.py index e01e7f9f11b..8dcdeb3698a 100644 --- a/tests/unit/algo/classification/backbones/test_otx_efficientnet_v2.py +++ b/tests/unit/algo/classification/backbones/test_otx_efficientnet_v2.py @@ -2,7 +2,6 @@ # SPDX-License-Identifier: Apache-2.0 import torch - from otx.algo.classification.backbones.otx_efficientnet_v2 import OTXEfficientNetV2 diff --git a/tests/unit/algo/classification/backbones/test_otx_mobilenet_v3.py b/tests/unit/algo/classification/backbones/test_otx_mobilenet_v3.py index 4d70156cd8c..51e3a235022 100644 --- a/tests/unit/algo/classification/backbones/test_otx_mobilenet_v3.py +++ b/tests/unit/algo/classification/backbones/test_otx_mobilenet_v3.py @@ -2,7 +2,6 @@ # SPDX-License-Identifier: Apache-2.0 import torch - from otx.algo.classification.backbones.otx_mobilenet_v3 import OTXMobileNetV3 diff --git a/tests/unit/algo/classification/conftest.py b/tests/unit/algo/classification/conftest.py index 3349c1021fd..bf536b62815 100644 --- a/tests/unit/algo/classification/conftest.py +++ b/tests/unit/algo/classification/conftest.py @@ -7,10 +7,9 @@ import torch from mmpretrain.structures import DataSample from omegaconf import DictConfig -from torchvision import tv_tensors - from otx.core.data.dataset.classification import HLabelInfo, MulticlassClsBatchDataEntity from otx.core.data.entity.base import ImageInfo +from torchvision import tv_tensors @pytest.fixture() diff --git a/tests/unit/algo/classification/heads/test_custom_hlabel_cls_head.py b/tests/unit/algo/classification/heads/test_custom_hlabel_cls_head.py index 047fa00036a..fe7533c1cda 100644 --- a/tests/unit/algo/classification/heads/test_custom_hlabel_cls_head.py +++ b/tests/unit/algo/classification/heads/test_custom_hlabel_cls_head.py @@ -9,10 +9,9 @@ import pytest import torch from mmpretrain.structures import DataSample -from torch import nn - from otx.algo.classification.heads.custom_hlabel_linear_cls_head import CustomHierarchicalLinearClsHead from otx.algo.classification.heads.custom_hlabel_non_linear_cls_head import CustomHierarchicalNonLinearClsHead +from torch import nn @pytest.fixture() diff --git a/tests/unit/algo/classification/heads/test_custom_multilabel_cls_head.py b/tests/unit/algo/classification/heads/test_custom_multilabel_cls_head.py index b0f49c8ea44..0499a013cd0 100644 --- a/tests/unit/algo/classification/heads/test_custom_multilabel_cls_head.py +++ b/tests/unit/algo/classification/heads/test_custom_multilabel_cls_head.py @@ -7,7 +7,6 @@ import pytest import torch from mmpretrain.structures import DataSample - from otx.algo.classification.heads import CustomMultiLabelLinearClsHead, CustomMultiLabelNonLinearClsHead from otx.algo.classification.losses import AsymmetricAngularLossWithIgnore diff --git a/tests/unit/algo/classification/losses/test_asymmetric_multilabel.py b/tests/unit/algo/classification/losses/test_asymmetric_multilabel.py index b34ed5719ec..70159dbf0ee 100644 --- a/tests/unit/algo/classification/losses/test_asymmetric_multilabel.py +++ b/tests/unit/algo/classification/losses/test_asymmetric_multilabel.py @@ -4,7 +4,6 @@ import pytest import torch - from otx.algo.classification.losses import AsymmetricAngularLossWithIgnore diff --git a/tests/unit/algo/classification/test_otx_dino_v2.py b/tests/unit/algo/classification/test_otx_dino_v2.py index 0aba348da92..2ec0100bb55 100644 --- a/tests/unit/algo/classification/test_otx_dino_v2.py +++ b/tests/unit/algo/classification/test_otx_dino_v2.py @@ -7,7 +7,6 @@ import pytest import torch - from otx.algo.classification import DINOv2 diff --git a/tests/unit/algo/classification/test_torchvision_model.py b/tests/unit/algo/classification/test_torchvision_model.py index 9413f55e08b..ee6dee37b76 100644 --- a/tests/unit/algo/classification/test_torchvision_model.py +++ b/tests/unit/algo/classification/test_torchvision_model.py @@ -1,6 +1,5 @@ import pytest import torch - from otx.algo.classification.torchvision_model import OTXTVModel, TVModelWithLossComputation from otx.core.data.entity.base import ImageInfo, OTXBatchLossEntity from otx.core.data.entity.classification import ( diff --git a/tests/unit/algo/detection/backbones/test_pytorchcv_backbones.py b/tests/unit/algo/detection/backbones/test_pytorchcv_backbones.py index 48eef7d4954..7fb49351a58 100644 --- a/tests/unit/algo/detection/backbones/test_pytorchcv_backbones.py +++ b/tests/unit/algo/detection/backbones/test_pytorchcv_backbones.py @@ -5,8 +5,6 @@ from __future__ import annotations import torch -from torch import nn - from otx.algo.detection.backbones.pytorchcv_backbones import ( _build_model_including_pytorchcv, multioutput_forward, @@ -14,6 +12,7 @@ replace_norm, train, ) +from torch import nn class MockModule(nn.Module): diff --git a/tests/unit/algo/detection/heads/test_class_incremental_mixin.py b/tests/unit/algo/detection/heads/test_class_incremental_mixin.py index 9e886a96b66..370a070f403 100644 --- a/tests/unit/algo/detection/heads/test_class_incremental_mixin.py +++ b/tests/unit/algo/detection/heads/test_class_incremental_mixin.py @@ -3,7 +3,6 @@ """Test of ClassIncrementalMixin.""" import torch - from otx.algo.detection.atss import ATSS diff --git a/tests/unit/algo/detection/heads/test_custom_anchor_generator.py b/tests/unit/algo/detection/heads/test_custom_anchor_generator.py index b2828b150c2..484d81c1dc8 100644 --- a/tests/unit/algo/detection/heads/test_custom_anchor_generator.py +++ b/tests/unit/algo/detection/heads/test_custom_anchor_generator.py @@ -4,7 +4,6 @@ import pytest import torch - from otx.algo.detection.heads.custom_anchor_generator import SSDAnchorGeneratorClustered diff --git a/tests/unit/algo/detection/heads/test_custom_ssd_head.py b/tests/unit/algo/detection/heads/test_custom_ssd_head.py index 244d0948ea4..1d4e1f19d33 100644 --- a/tests/unit/algo/detection/heads/test_custom_ssd_head.py +++ b/tests/unit/algo/detection/heads/test_custom_ssd_head.py @@ -3,7 +3,6 @@ """Test of CustomSSDHead.""" from mmdet.models.losses.cross_entropy_loss import CrossEntropyLoss - from otx.algo.detection.heads.custom_ssd_head import CustomSSDHead diff --git a/tests/unit/algo/detection/test_ssd.py b/tests/unit/algo/detection/test_ssd.py index 1744068c45e..9a21a1a570d 100644 --- a/tests/unit/algo/detection/test_ssd.py +++ b/tests/unit/algo/detection/test_ssd.py @@ -3,7 +3,6 @@ """Test of OTX SSD architecture.""" import pytest - from otx.algo.detection.ssd import SSD diff --git a/tests/unit/algo/hooks/test_saliency_map_dumping.py b/tests/unit/algo/hooks/test_saliency_map_dumping.py index 78759454d0f..28c9d3254cf 100644 --- a/tests/unit/algo/hooks/test_saliency_map_dumping.py +++ b/tests/unit/algo/hooks/test_saliency_map_dumping.py @@ -5,7 +5,6 @@ import cv2 import numpy as np - from otx.algo.utils.xai_utils import dump_saliency_maps from otx.core.config.explain import ExplainConfig from otx.core.data.entity.base import ImageInfo diff --git a/tests/unit/algo/hooks/test_saliency_map_processing.py b/tests/unit/algo/hooks/test_saliency_map_processing.py index 273c0ccabc2..628649925b0 100644 --- a/tests/unit/algo/hooks/test_saliency_map_processing.py +++ b/tests/unit/algo/hooks/test_saliency_map_processing.py @@ -3,7 +3,6 @@ import numpy as np import pytest import torch - from otx.algo.utils.xai_utils import process_saliency_maps, process_saliency_maps_in_pred_entity from otx.core.config.explain import ExplainConfig from otx.core.data.entity.base import ImageInfo diff --git a/tests/unit/algo/hooks/test_xai_hooks.py b/tests/unit/algo/hooks/test_xai_hooks.py index 71ac3e0a8dc..65869496356 100644 --- a/tests/unit/algo/hooks/test_xai_hooks.py +++ b/tests/unit/algo/hooks/test_xai_hooks.py @@ -2,9 +2,6 @@ # SPDX-License-Identifier: Apache-2.0 import torch from datumaro import Polygon -from torch import LongTensor -from torchvision import tv_tensors - from otx.algo.hooks.recording_forward_hook import ( ActivationMapHook, DetClassProbabilityMapHook, @@ -14,6 +11,8 @@ ) from otx.core.data.entity.base import ImageInfo from otx.core.data.entity.instance_segmentation import InstanceSegBatchPredEntity +from torch import LongTensor +from torchvision import tv_tensors def test_activationmap() -> None: diff --git a/tests/unit/algo/instance_segmentation/heads/test_custom_roi_head.py b/tests/unit/algo/instance_segmentation/heads/test_custom_roi_head.py index 55f41892f28..9ed6683250a 100644 --- a/tests/unit/algo/instance_segmentation/heads/test_custom_roi_head.py +++ b/tests/unit/algo/instance_segmentation/heads/test_custom_roi_head.py @@ -10,7 +10,6 @@ import torch from mmdet.structures import DetDataSample from mmengine.structures import InstanceData - from otx.algo.instance_segmentation.heads.custom_roi_head import CustomRoIHead from otx.algo.instance_segmentation.maskrcnn import MaskRCNN diff --git a/tests/unit/algo/instance_segmentation/test_evaluation.py b/tests/unit/algo/instance_segmentation/test_evaluation.py index bb4b472d730..06ae5a4772c 100644 --- a/tests/unit/algo/instance_segmentation/test_evaluation.py +++ b/tests/unit/algo/instance_segmentation/test_evaluation.py @@ -1,8 +1,7 @@ import torch -from torchmetrics.detection.mean_ap import MeanAveragePrecision - from otx.algo.instance_segmentation.otx_instseg_evaluation import OTXMaskRLEMeanAveragePrecision from otx.core.utils.mask_util import encode_rle +from torchmetrics.detection.mean_ap import MeanAveragePrecision def test_custom_rle_map_metric(num_masks=50, h=10, w=10): diff --git a/tests/unit/algo/samplers/test_balanced_sampler.py b/tests/unit/algo/samplers/test_balanced_sampler.py index 276359cfc05..587f9d61990 100644 --- a/tests/unit/algo/samplers/test_balanced_sampler.py +++ b/tests/unit/algo/samplers/test_balanced_sampler.py @@ -7,7 +7,6 @@ from datumaro.components.annotation import Label from datumaro.components.dataset import Dataset as DmDataset from datumaro.components.dataset_base import DatasetItem - from otx.algo.samplers.balanced_sampler import BalancedSampler from otx.core.data.dataset.base import OTXDataset from otx.core.utils.utils import get_idx_list_per_classes diff --git a/tests/unit/algo/samplers/test_class_incremental_sampler.py b/tests/unit/algo/samplers/test_class_incremental_sampler.py index 54b2ad69302..2482c9c1f1d 100644 --- a/tests/unit/algo/samplers/test_class_incremental_sampler.py +++ b/tests/unit/algo/samplers/test_class_incremental_sampler.py @@ -5,7 +5,6 @@ from datumaro.components.annotation import Label from datumaro.components.dataset import Dataset as DmDataset from datumaro.components.dataset_base import DatasetItem - from otx.algo.samplers.class_incremental_sampler import ClassIncrementalSampler from otx.core.data.dataset.base import OTXDataset from otx.core.utils.utils import get_idx_list_per_classes diff --git a/tests/unit/algo/segmentation/heads/test_class_incremental_mixin.py b/tests/unit/algo/segmentation/heads/test_class_incremental_mixin.py index 6b7c25624fe..7b16a0b94f6 100644 --- a/tests/unit/algo/segmentation/heads/test_class_incremental_mixin.py +++ b/tests/unit/algo/segmentation/heads/test_class_incremental_mixin.py @@ -5,7 +5,6 @@ from typing import ClassVar import torch - from otx.algo.segmentation.litehrnet import LiteHRNet diff --git a/tests/unit/algo/utils/test_support_otx_v1.py b/tests/unit/algo/utils/test_support_otx_v1.py index c0c0ab005ae..57eeca84ea2 100644 --- a/tests/unit/algo/utils/test_support_otx_v1.py +++ b/tests/unit/algo/utils/test_support_otx_v1.py @@ -6,7 +6,6 @@ import pytest import torch - from otx.algo.utils.support_otx_v1 import OTXv1Helper diff --git a/tests/unit/algo/visual_prompting/backbones/test_tiny_vit.py b/tests/unit/algo/visual_prompting/backbones/test_tiny_vit.py index d87d31d8e4a..334ec8d3ec4 100644 --- a/tests/unit/algo/visual_prompting/backbones/test_tiny_vit.py +++ b/tests/unit/algo/visual_prompting/backbones/test_tiny_vit.py @@ -5,8 +5,6 @@ import pytest import torch -from torch import nn - from otx.algo.visual_prompting.backbones.tiny_vit import ( Attention, BasicLayer, @@ -19,6 +17,7 @@ TinyViT, TinyViTBlock, ) +from torch import nn class TestConv2d_BN: # noqa: N801 diff --git a/tests/unit/algo/visual_prompting/backbones/test_vit.py b/tests/unit/algo/visual_prompting/backbones/test_vit.py index 018b3bdfe05..92dcb8c4a3e 100644 --- a/tests/unit/algo/visual_prompting/backbones/test_vit.py +++ b/tests/unit/algo/visual_prompting/backbones/test_vit.py @@ -5,8 +5,6 @@ import pytest import torch -from torch import Tensor, nn - from otx.algo.visual_prompting.backbones.vit import ( Attention, Block, @@ -18,6 +16,7 @@ window_unpartition, ) from otx.algo.visual_prompting.utils import MLPBlock +from torch import Tensor, nn class TestViT: diff --git a/tests/unit/algo/visual_prompting/conftest.py b/tests/unit/algo/visual_prompting/conftest.py index 427c42f7edf..f9567775649 100644 --- a/tests/unit/algo/visual_prompting/conftest.py +++ b/tests/unit/algo/visual_prompting/conftest.py @@ -5,8 +5,6 @@ import pytest import torch -from torchvision import tv_tensors - from otx.core.data.entity.base import ImageInfo, Points from otx.core.data.entity.visual_prompting import ( VisualPromptingBatchDataEntity, @@ -16,6 +14,7 @@ ZeroShotVisualPromptingBatchPredEntity, ZeroShotVisualPromptingDataEntity, ) +from torchvision import tv_tensors @pytest.fixture(scope="session") diff --git a/tests/unit/algo/visual_prompting/decoders/test_sam_mask_decoder.py b/tests/unit/algo/visual_prompting/decoders/test_sam_mask_decoder.py index e3e75d4575e..2aa5a998690 100644 --- a/tests/unit/algo/visual_prompting/decoders/test_sam_mask_decoder.py +++ b/tests/unit/algo/visual_prompting/decoders/test_sam_mask_decoder.py @@ -5,8 +5,6 @@ import pytest import torch -from torch import nn - from otx.algo.visual_prompting.decoders.sam_mask_decoder import ( MLP, Attention, @@ -15,6 +13,7 @@ TwoWayTransformer, ) from otx.algo.visual_prompting.utils.mlp_block import MLPBlock +from torch import nn class TestSAMMaskDecoder: diff --git a/tests/unit/algo/visual_prompting/encoders/test_sam_image_encoder.py b/tests/unit/algo/visual_prompting/encoders/test_sam_image_encoder.py index 4d5c414e575..f1f87b81ffa 100644 --- a/tests/unit/algo/visual_prompting/encoders/test_sam_image_encoder.py +++ b/tests/unit/algo/visual_prompting/encoders/test_sam_image_encoder.py @@ -2,7 +2,6 @@ # SPDX-License-Identifier: Apache-2.0 import pytest - from otx.algo.visual_prompting.encoders.sam_image_encoder import SAMImageEncoder diff --git a/tests/unit/algo/visual_prompting/encoders/test_sam_prompt_encoder.py b/tests/unit/algo/visual_prompting/encoders/test_sam_prompt_encoder.py index cb11f25afb9..dbb57cb74ea 100644 --- a/tests/unit/algo/visual_prompting/encoders/test_sam_prompt_encoder.py +++ b/tests/unit/algo/visual_prompting/encoders/test_sam_prompt_encoder.py @@ -5,9 +5,8 @@ import pytest import torch -from torch import nn - from otx.algo.visual_prompting.encoders.sam_prompt_encoder import PositionEmbeddingRandom, SAMPromptEncoder +from torch import nn class TestSAMPromptEncoder: diff --git a/tests/unit/algo/visual_prompting/test_openvino_models.py b/tests/unit/algo/visual_prompting/test_openvino_models.py index b5849db1b59..bd821b1f60c 100644 --- a/tests/unit/algo/visual_prompting/test_openvino_models.py +++ b/tests/unit/algo/visual_prompting/test_openvino_models.py @@ -10,7 +10,6 @@ from openvino.model_api.adapters.openvino_adapter import OpenvinoAdapter from openvino.model_api.models import ImageModel, SegmentationModel from openvino.model_api.models.types import NumericalValue - from otx.algo.visual_prompting.openvino_models import VisualPromptingDecoder, VisualPromptingImageEncoder diff --git a/tests/unit/algo/visual_prompting/test_segment_anything.py b/tests/unit/algo/visual_prompting/test_segment_anything.py index c14bb57881c..329289e976a 100644 --- a/tests/unit/algo/visual_prompting/test_segment_anything.py +++ b/tests/unit/algo/visual_prompting/test_segment_anything.py @@ -5,12 +5,11 @@ import pytest import torch -from torch import Tensor -from torchvision import tv_tensors - from otx.algo.visual_prompting.segment_anything import OTXSegmentAnything, SegmentAnything from otx.core.data.entity.base import Points from otx.core.data.entity.visual_prompting import VisualPromptingBatchPredEntity +from torch import Tensor +from torchvision import tv_tensors class TestSegmentAnything: diff --git a/tests/unit/algo/visual_prompting/test_zero_shot_segment_anything.py b/tests/unit/algo/visual_prompting/test_zero_shot_segment_anything.py index 9e39a476308..d02f02195d8 100644 --- a/tests/unit/algo/visual_prompting/test_zero_shot_segment_anything.py +++ b/tests/unit/algo/visual_prompting/test_zero_shot_segment_anything.py @@ -8,9 +8,6 @@ import pytest import torch -from torch import Tensor -from torchvision import tv_tensors - from otx.algo.visual_prompting.zero_shot_segment_anything import ( OTXZeroShotSegmentAnything, PromptGetter, @@ -18,6 +15,8 @@ ) from otx.core.data.entity.base import Points from otx.core.data.entity.visual_prompting import ZeroShotVisualPromptingBatchPredEntity +from torch import Tensor +from torchvision import tv_tensors class TestPromptGetter: diff --git a/tests/unit/algo/visual_prompting/utils/test_layer_norm_2d.py b/tests/unit/algo/visual_prompting/utils/test_layer_norm_2d.py index 9ba3ef8200a..93718efc71b 100644 --- a/tests/unit/algo/visual_prompting/utils/test_layer_norm_2d.py +++ b/tests/unit/algo/visual_prompting/utils/test_layer_norm_2d.py @@ -3,7 +3,6 @@ import torch - from otx.algo.visual_prompting.utils.layer_norm_2d import LayerNorm2d diff --git a/tests/unit/cli/test_cli.py b/tests/unit/cli/test_cli.py index 1e1cedddbea..0eea9f1bc57 100644 --- a/tests/unit/cli/test_cli.py +++ b/tests/unit/cli/test_cli.py @@ -6,7 +6,6 @@ import pytest import yaml - from otx.cli import OTXCLI, main diff --git a/tests/unit/cli/test_install.py b/tests/unit/cli/test_install.py index 26f5be00851..a55c587a8a9 100644 --- a/tests/unit/cli/test_install.py +++ b/tests/unit/cli/test_install.py @@ -4,11 +4,10 @@ import pytest from _pytest.monkeypatch import MonkeyPatch from jsonargparse import ArgumentParser +from otx.cli.install import add_install_parser, otx_install from pkg_resources import Requirement from pytest_mock.plugin import MockerFixture -from otx.cli.install import add_install_parser, otx_install - class TestInstall: @pytest.fixture(autouse=True) diff --git a/tests/unit/cli/utils/test_help_formatter.py b/tests/unit/cli/utils/test_help_formatter.py index 53e4ffc06a4..61a05a6e27b 100644 --- a/tests/unit/cli/utils/test_help_formatter.py +++ b/tests/unit/cli/utils/test_help_formatter.py @@ -8,7 +8,6 @@ import pytest from jsonargparse import ArgumentParser - from otx.cli.utils.help_formatter import ( CustomHelpFormatter, get_cli_usage_docstring, diff --git a/tests/unit/cli/utils/test_installation.py b/tests/unit/cli/utils/test_installation.py index c2cfb148053..ecdc1552279 100644 --- a/tests/unit/cli/utils/test_installation.py +++ b/tests/unit/cli/utils/test_installation.py @@ -7,9 +7,6 @@ import pkg_resources import pytest -from pkg_resources import Requirement -from pytest_mock import MockerFixture - from otx.cli.utils.installation import ( add_hardware_suffix_to_torch, get_cuda_suffix, @@ -23,6 +20,8 @@ parse_requirements, update_cuda_version_with_available_torch_cuda_build, ) +from pkg_resources import Requirement +from pytest_mock import MockerFixture @pytest.fixture() diff --git a/tests/unit/cli/utils/test_jsonargparse.py b/tests/unit/cli/utils/test_jsonargparse.py index 468937b9991..2137d76526e 100644 --- a/tests/unit/cli/utils/test_jsonargparse.py +++ b/tests/unit/cli/utils/test_jsonargparse.py @@ -3,7 +3,6 @@ import pytest from jsonargparse import Namespace - from otx.cli.utils.jsonargparse import ( flatten_dict, get_configuration, diff --git a/tests/unit/core/conftest.py b/tests/unit/core/conftest.py index 84136b2bd82..5ef50e9eff9 100644 --- a/tests/unit/core/conftest.py +++ b/tests/unit/core/conftest.py @@ -9,8 +9,6 @@ from datumaro.components.annotation import AnnotationType, LabelCategories from datumaro.components.dataset import Dataset, DatasetItem from datumaro.components.media import Image -from torchvision import tv_tensors - from otx.core.config import register_configs from otx.core.data.dataset.base import LabelInfo from otx.core.data.dataset.classification import HLabelInfo @@ -23,6 +21,7 @@ ZeroShotVisualPromptingBatchPredEntity, ZeroShotVisualPromptingDataEntity, ) +from torchvision import tv_tensors @pytest.fixture(scope="session", autouse=True) diff --git a/tests/unit/core/data/conftest.py b/tests/unit/core/data/conftest.py index 522c35337a2..f9105cefb6d 100644 --- a/tests/unit/core/data/conftest.py +++ b/tests/unit/core/data/conftest.py @@ -12,7 +12,6 @@ from datumaro.components.dataset import DatasetSubset from datumaro.components.dataset_base import DatasetItem from datumaro.components.media import Image - from otx.core.data.dataset.classification import ( MulticlassClsDataEntity, OTXMulticlassClsDataset, @@ -28,10 +27,9 @@ from otx.core.data.mem_cache import MemCacheHandlerSingleton if TYPE_CHECKING: - from pytest_mock import MockerFixture - from otx.core.data.dataset.base import OTXDataset, T_OTXDataEntity from otx.core.data.mem_cache import MemCacheHandlerBase + from pytest_mock import MockerFixture @pytest.fixture() diff --git a/tests/unit/core/data/dataset/test_visual_prompting.py b/tests/unit/core/data/dataset/test_visual_prompting.py index edd32027e11..51795c0f861 100644 --- a/tests/unit/core/data/dataset/test_visual_prompting.py +++ b/tests/unit/core/data/dataset/test_visual_prompting.py @@ -7,13 +7,12 @@ import numpy as np import pytest from datumaro import Dataset as DmDataset +from otx.core.data.dataset.visual_prompting import OTXVisualPromptingDataset, OTXZeroShotVisualPromptingDataset +from otx.core.data.entity.base import ImageInfo, Points from torch import Tensor from torchvision.transforms.v2 import Identity, Transform from torchvision.tv_tensors import BoundingBoxes, Image, Mask -from otx.core.data.dataset.visual_prompting import OTXVisualPromptingDataset, OTXZeroShotVisualPromptingDataset -from otx.core.data.entity.base import ImageInfo, Points - class TestOTXVisualPromptingDataset: @pytest.fixture() diff --git a/tests/unit/core/data/entity/conftest.py b/tests/unit/core/data/entity/conftest.py index 53f0995bb1b..00e31e2cd7e 100644 --- a/tests/unit/core/data/entity/conftest.py +++ b/tests/unit/core/data/entity/conftest.py @@ -6,11 +6,10 @@ import pytest import torch from datumaro import Polygon -from torch import LongTensor -from torchvision import tv_tensors - from otx.core.data.entity.base import ImageInfo, OTXDataEntity, Points from otx.core.data.entity.visual_prompting import VisualPromptingDataEntity +from torch import LongTensor +from torchvision import tv_tensors @pytest.fixture() diff --git a/tests/unit/core/data/entity/test_base.py b/tests/unit/core/data/entity/test_base.py index 033c8c5eb87..7515327135d 100644 --- a/tests/unit/core/data/entity/test_base.py +++ b/tests/unit/core/data/entity/test_base.py @@ -7,7 +7,6 @@ import torch import torchvision.transforms.v2 as tvt import torchvision.transforms.v2.functional as F # noqa: N812 - from otx.core.data.entity.base import ImageType, OTXBatchDataEntity, OTXDataEntity, Points from otx.core.data.entity.visual_prompting import VisualPromptingDataEntity diff --git a/tests/unit/core/data/entity/test_detection.py b/tests/unit/core/data/entity/test_detection.py index 0bddfb77704..28dcfc7cdf9 100644 --- a/tests/unit/core/data/entity/test_detection.py +++ b/tests/unit/core/data/entity/test_detection.py @@ -3,12 +3,11 @@ """Unit tests of detection data entity.""" import torch -from torch import LongTensor -from torchvision import tv_tensors - from otx.core.data.entity.base import ImageInfo from otx.core.data.entity.detection import DetBatchDataEntity, DetDataEntity from otx.core.types.task import OTXTaskType +from torch import LongTensor +from torchvision import tv_tensors class TestDetDataEntity: diff --git a/tests/unit/core/data/entity/test_visual_prompting.py b/tests/unit/core/data/entity/test_visual_prompting.py index 0a2f6fb0d03..94ece5a86a6 100644 --- a/tests/unit/core/data/entity/test_visual_prompting.py +++ b/tests/unit/core/data/entity/test_visual_prompting.py @@ -5,9 +5,6 @@ import torch from datumaro import Polygon -from torch import LongTensor -from torchvision import tv_tensors - from otx.core.data.entity.base import ImageInfo, Points from otx.core.data.entity.visual_prompting import ( VisualPromptingBatchDataEntity, @@ -16,6 +13,8 @@ ZeroShotVisualPromptingDataEntity, ) from otx.core.types.task import OTXTaskType +from torch import LongTensor +from torchvision import tv_tensors class TestVisualPromptingDataEntity: diff --git a/tests/unit/core/data/test_factory.py b/tests/unit/core/data/test_factory.py index eef222fa29a..328ad03d173 100644 --- a/tests/unit/core/data/test_factory.py +++ b/tests/unit/core/data/test_factory.py @@ -4,7 +4,6 @@ """Test Factory classes for dataset and transforms.""" import pytest - from otx.core.config.data import DataModuleConfig, SubsetConfig, TileConfig, VisualPromptingConfig from otx.core.data.dataset.classification import OTXMulticlassClsDataset from otx.core.data.dataset.detection import OTXDetectionDataset diff --git a/tests/unit/core/data/test_mem_cache.py b/tests/unit/core/data/test_mem_cache.py index e4f44807d36..9172978bfe0 100644 --- a/tests/unit/core/data/test_mem_cache.py +++ b/tests/unit/core/data/test_mem_cache.py @@ -8,7 +8,6 @@ import numpy as np import psutil import pytest - from otx.core.data.mem_cache import ( MemCacheHandlerSingleton, parse_mem_cache_size_to_int, diff --git a/tests/unit/core/data/test_module.py b/tests/unit/core/data/test_module.py index c1703b83c2d..9746e79789f 100644 --- a/tests/unit/core/data/test_module.py +++ b/tests/unit/core/data/test_module.py @@ -8,7 +8,6 @@ from importlib_resources import files from lightning.pytorch.loggers import CSVLogger from omegaconf import DictConfig, OmegaConf - from otx.core.config.data import ( DataModuleConfig, SubsetConfig, diff --git a/tests/unit/core/data/test_pre_filtering.py b/tests/unit/core/data/test_pre_filtering.py index eedc26330c6..f3f9ccf2d18 100644 --- a/tests/unit/core/data/test_pre_filtering.py +++ b/tests/unit/core/data/test_pre_filtering.py @@ -5,7 +5,6 @@ from datumaro.components.annotation import Label from datumaro.components.dataset import Dataset as DmDataset from datumaro.components.dataset_base import DatasetItem - from otx.core.data.pre_filtering import pre_filtering diff --git a/tests/unit/core/data/test_transform_libs.py b/tests/unit/core/data/test_transform_libs.py index 0d63ba44ed3..0d9aac017e3 100644 --- a/tests/unit/core/data/test_transform_libs.py +++ b/tests/unit/core/data/test_transform_libs.py @@ -9,9 +9,6 @@ import torch from lightning.pytorch.cli import instantiate_class from omegaconf import OmegaConf -from torchvision import tv_tensors -from torchvision.transforms import v2 - from otx.core.config.data import SubsetConfig from otx.core.data.entity.base import Points from otx.core.data.transform_libs.torchvision import ( @@ -21,6 +18,8 @@ TorchVisionTransformLib, ) from otx.core.types.image import ImageColorChannel +from torchvision import tv_tensors +from torchvision.transforms import v2 class TestPerturbBoundingBoxes: diff --git a/tests/unit/core/data/transform_libs/test_mmcv.py b/tests/unit/core/data/transform_libs/test_mmcv.py index bad160694ae..263936fee34 100644 --- a/tests/unit/core/data/transform_libs/test_mmcv.py +++ b/tests/unit/core/data/transform_libs/test_mmcv.py @@ -4,13 +4,13 @@ import numpy as np import pytest -from mmcv.transforms.builder import TRANSFORMS - from otx.core.config.data import SubsetConfig from otx.core.data.entity.base import ImageInfo, OTXDataEntity from otx.core.data.transform_libs.mmcv import LoadImageFromFile, MMCVTransformLib from otx.core.types.transformer_libs import TransformLibType +from mmcv.transforms.builder import TRANSFORMS + class TestLoadImageFromFile: def test_transform(self) -> None: diff --git a/tests/unit/core/data/transform_libs/test_mmdet.py b/tests/unit/core/data/transform_libs/test_mmdet.py index c29bba49cd5..0815a0ef976 100644 --- a/tests/unit/core/data/transform_libs/test_mmdet.py +++ b/tests/unit/core/data/transform_libs/test_mmdet.py @@ -7,9 +7,6 @@ import numpy as np import pytest import torch -from torch import LongTensor -from torchvision import tv_tensors - from otx.core.config.data import SubsetConfig from otx.core.data.entity.base import ImageInfo from otx.core.data.entity.detection import DetDataEntity @@ -17,6 +14,8 @@ from otx.core.data.transform_libs.mmcv import LoadImageFromFile from otx.core.data.transform_libs.mmdet import LoadAnnotations, MMDetTransformLib, PackDetInputs, PerturbBoundingBoxes from otx.core.types.transformer_libs import TransformLibType +from torch import LongTensor +from torchvision import tv_tensors class TestLoadAnnotations: diff --git a/tests/unit/core/data/transform_libs/test_mmseg.py b/tests/unit/core/data/transform_libs/test_mmseg.py index 6edff99b27f..df420569fa3 100644 --- a/tests/unit/core/data/transform_libs/test_mmseg.py +++ b/tests/unit/core/data/transform_libs/test_mmseg.py @@ -5,7 +5,6 @@ from __future__ import annotations import pytest - from otx.core.data.entity.segmentation import SegDataEntity from otx.core.data.transform_libs.mmcv import LoadImageFromFile from otx.core.data.transform_libs.mmseg import LoadAnnotations, PackSegInputs diff --git a/tests/unit/core/metrics/test_accuracy.py b/tests/unit/core/metrics/test_accuracy.py index fe06af7b5a9..47c72b7f8b8 100644 --- a/tests/unit/core/metrics/test_accuracy.py +++ b/tests/unit/core/metrics/test_accuracy.py @@ -5,7 +5,6 @@ import pytest import torch - from otx.core.data.dataset.base import LabelInfo from otx.core.data.dataset.classification import HLabelInfo from otx.core.metrics.accuracy import ( diff --git a/tests/unit/core/metrics/test_fmeasure.py b/tests/unit/core/metrics/test_fmeasure.py index 7513bf57b92..0f364fa1654 100644 --- a/tests/unit/core/metrics/test_fmeasure.py +++ b/tests/unit/core/metrics/test_fmeasure.py @@ -7,7 +7,6 @@ import pytest import torch - from otx.core.metrics.fmeasure import FMeasure diff --git a/tests/unit/core/model/entity/test_base.py b/tests/unit/core/model/entity/test_base.py index 243d588ca7c..9a96a36f45a 100644 --- a/tests/unit/core/model/entity/test_base.py +++ b/tests/unit/core/model/entity/test_base.py @@ -2,7 +2,6 @@ import pytest import torch from openvino.model_api.models.utils import ClassificationResult - from otx.core.data.entity.base import OTXBatchDataEntity from otx.core.model.entity.base import OTXModel, OVModel diff --git a/tests/unit/core/model/entity/test_segmentation.py b/tests/unit/core/model/entity/test_segmentation.py index a63daba9020..288e09e4014 100644 --- a/tests/unit/core/model/entity/test_segmentation.py +++ b/tests/unit/core/model/entity/test_segmentation.py @@ -11,7 +11,6 @@ import torch from importlib_resources import files from omegaconf import OmegaConf - from otx.core.model.entity.segmentation import MMSegCompatibleModel if TYPE_CHECKING: @@ -45,7 +44,6 @@ def test_customize_inputs(self, model, fxt_seg_data_entity) -> None: def test_customize_outputs(self, model, fxt_seg_data_entity) -> None: from mmengine.structures import PixelData from mmseg.structures import SegDataSample - from otx.core.data.entity.base import OTXBatchLossEntity from otx.core.data.entity.segmentation import SegBatchPredEntity diff --git a/tests/unit/core/model/entity/test_visual_prompting.py b/tests/unit/core/model/entity/test_visual_prompting.py index e15671db4b7..7373b31fb11 100644 --- a/tests/unit/core/model/entity/test_visual_prompting.py +++ b/tests/unit/core/model/entity/test_visual_prompting.py @@ -11,8 +11,6 @@ import numpy as np import pytest import torch -from torchvision import tv_tensors - from otx.core.data.entity.visual_prompting import VisualPromptingBatchPredEntity from otx.core.exporter.visual_prompting import OTXVisualPromptingModelExporter from otx.core.model.entity.visual_prompting import ( @@ -20,6 +18,7 @@ OVVisualPromptingModel, OVZeroShotVisualPromptingModel, ) +from torchvision import tv_tensors class TestOTXVisualPromptingModel: diff --git a/tests/unit/core/model/module/test_base.py b/tests/unit/core/model/module/test_base.py index 45d0cdc34ba..9e294ddadb7 100644 --- a/tests/unit/core/model/module/test_base.py +++ b/tests/unit/core/model/module/test_base.py @@ -10,11 +10,10 @@ import pytest from lightning.pytorch.cli import ReduceLROnPlateau from lightning.pytorch.trainer import Trainer -from torch.optim import Optimizer - from otx.algo.schedulers.warmup_schedulers import LinearWarmupScheduler from otx.core.model.entity.base import OTXModel from otx.core.model.module.base import OTXLitModule +from torch.optim import Optimizer class TestOTXLitModule: diff --git a/tests/unit/core/model/module/test_detection.py b/tests/unit/core/model/module/test_detection.py index afe691a9da0..f694a2864f5 100644 --- a/tests/unit/core/model/module/test_detection.py +++ b/tests/unit/core/model/module/test_detection.py @@ -10,13 +10,12 @@ import pytest from lightning.pytorch.cli import ReduceLROnPlateau -from torch.optim import Optimizer - from otx.algo.schedulers.warmup_schedulers import LinearWarmupScheduler from otx.core.metrics.fmeasure import FMeasure from otx.core.model.entity.detection import OTXDetectionModel from otx.core.model.module.base import OTXLitModule from otx.core.model.module.detection import OTXDetectionLitModule +from torch.optim import Optimizer class TestOTXLitModule: diff --git a/tests/unit/core/model/module/test_segmentation.py b/tests/unit/core/model/module/test_segmentation.py index a1529f62aba..edb40c697a4 100644 --- a/tests/unit/core/model/module/test_segmentation.py +++ b/tests/unit/core/model/module/test_segmentation.py @@ -9,11 +9,10 @@ import pytest import torch -from torchmetrics.metric import Metric - from otx.core.data.entity.segmentation import SegBatchPredEntity from otx.core.model.entity.segmentation import MMSegCompatibleModel from otx.core.model.module.segmentation import OTXSegmentationLitModule +from torchmetrics.metric import Metric class MockMetric(torch.nn.Module): diff --git a/tests/unit/core/utils/test_mask_utils.py b/tests/unit/core/utils/test_mask_utils.py index 965485e5fec..5f32eca07a9 100644 --- a/tests/unit/core/utils/test_mask_utils.py +++ b/tests/unit/core/utils/test_mask_utils.py @@ -1,8 +1,7 @@ import numpy as np import torch -from pycocotools import mask as mask_utils - from otx.core.utils.mask_util import encode_rle +from pycocotools import mask as mask_utils def test_encode_rle(num_test_cases=30): diff --git a/tests/unit/core/utils/test_tile.py b/tests/unit/core/utils/test_tile.py index 2ba455fd2f5..a32a13cf91f 100644 --- a/tests/unit/core/utils/test_tile.py +++ b/tests/unit/core/utils/test_tile.py @@ -11,7 +11,6 @@ from datumaro.plugins.tiling.util import xywh_to_x1y1x2y2 from openvino.model_api.models import Model from openvino.model_api.tilers import Tiler - from otx.core.data.dataset.tile import OTXTileTransform diff --git a/tests/unit/core/utils/test_utils.py b/tests/unit/core/utils/test_utils.py index a7bd53cd2c4..917c2e421ed 100644 --- a/tests/unit/core/utils/test_utils.py +++ b/tests/unit/core/utils/test_utils.py @@ -1,5 +1,4 @@ import pytest - from otx.core.utils import utils as target_file from otx.core.utils.utils import get_adaptive_num_workers diff --git a/tests/unit/engine/utils/test_api.py b/tests/unit/engine/utils/test_api.py index f173c2e0c63..e136058d463 100644 --- a/tests/unit/engine/utils/test_api.py +++ b/tests/unit/engine/utils/test_api.py @@ -2,7 +2,6 @@ # SPDX-License-Identifier: Apache-2.0 import pytest - from otx.core.types.task import OTXTaskType from otx.engine.utils.api import RECIPE_PATH, list_models diff --git a/tests/unit/engine/utils/test_auto_configurator.py b/tests/unit/engine/utils/test_auto_configurator.py index 4fbbf37ea32..028ea79177d 100644 --- a/tests/unit/engine/utils/test_auto_configurator.py +++ b/tests/unit/engine/utils/test_auto_configurator.py @@ -5,7 +5,6 @@ from pathlib import Path import pytest - from otx.core.data.dataset.base import LabelInfo from otx.core.data.module import OTXDataModule from otx.core.model.entity.base import OTXModel diff --git a/tests/unit/hpo/test_hpo_base.py b/tests/unit/hpo/test_hpo_base.py index b169ecc4e81..14b574b1d93 100644 --- a/tests/unit/hpo/test_hpo_base.py +++ b/tests/unit/hpo/test_hpo_base.py @@ -2,7 +2,6 @@ from pathlib import Path import pytest - from otx.hpo.hpo_base import Trial diff --git a/tests/unit/hpo/test_hyperband.py b/tests/unit/hpo/test_hyperband.py index 63bf577c71d..00dad36d58c 100644 --- a/tests/unit/hpo/test_hyperband.py +++ b/tests/unit/hpo/test_hyperband.py @@ -12,7 +12,6 @@ from tempfile import TemporaryDirectory import pytest - from otx.hpo import hyperband from otx.hpo.hpo_base import TrialStatus from otx.hpo.hyperband import AshaTrial, Bracket, HyperBand, Rung diff --git a/tests/unit/hpo/test_resource_manager.py b/tests/unit/hpo/test_resource_manager.py index e7b35cfbfbb..f1688931750 100644 --- a/tests/unit/hpo/test_resource_manager.py +++ b/tests/unit/hpo/test_resource_manager.py @@ -1,5 +1,4 @@ import pytest - from otx.hpo.resource_manager import ( CPUResourceManager, GPUResourceManager, diff --git a/tests/unit/hpo/test_search_space.py b/tests/unit/hpo/test_search_space.py index b1e422d0471..d72b76c1eba 100644 --- a/tests/unit/hpo/test_search_space.py +++ b/tests/unit/hpo/test_search_space.py @@ -2,7 +2,6 @@ import math import pytest - from otx.hpo.search_space import SearchSpace, SingleSearchSpace ALL_TYPE = ["uniform", "loguniform", "quniform", "qloguniform", "choice"] diff --git a/tests/unit/utils/test_utils.py b/tests/unit/utils/test_utils.py index 45b04862204..10a6a939257 100644 --- a/tests/unit/utils/test_utils.py +++ b/tests/unit/utils/test_utils.py @@ -3,7 +3,6 @@ from pathlib import Path import pytest - from otx.utils.utils import ( find_file_recursively, get_decimal_point, From bbabd6ef8251041544d674bb0e62e66825a1f8bb Mon Sep 17 00:00:00 2001 From: kprokofi Date: Tue, 19 Mar 2024 07:37:58 +0900 Subject: [PATCH 19/42] fix pre-commit --- .../heads/custom_multilabel_non_linear_cls_head.py | 3 +-- src/otx/algo/detection/backbones/pytorchcv_backbones.py | 3 +-- src/otx/algo/detection/utils/mmcv_patched_ops.py | 3 +-- src/otx/algo/segmentation/backbones/litehrnet.py | 2 +- src/otx/algo/utils/segmentation.py | 3 +-- src/otx/core/data/transform_libs/mmaction.py | 2 +- src/otx/core/data/transform_libs/mmcv.py | 2 +- src/otx/core/data/transform_libs/mmdet.py | 2 +- src/otx/engine/engine.py | 4 ++-- tests/unit/core/data/transform_libs/test_mmcv.py | 3 +-- 10 files changed, 11 insertions(+), 16 deletions(-) diff --git a/src/otx/algo/classification/heads/custom_multilabel_non_linear_cls_head.py b/src/otx/algo/classification/heads/custom_multilabel_non_linear_cls_head.py index 853ebf3c7ad..dda7800a3fc 100644 --- a/src/otx/algo/classification/heads/custom_multilabel_non_linear_cls_head.py +++ b/src/otx/algo/classification/heads/custom_multilabel_non_linear_cls_head.py @@ -8,13 +8,12 @@ from typing import TYPE_CHECKING import torch +from mmcv.cnn import build_activation_layer from mmengine.model import constant_init, normal_init from mmpretrain.models.heads import MultiLabelClsHead from mmpretrain.registry import MODELS from torch import nn -from mmcv.cnn import build_activation_layer - from .custom_multilabel_linear_cls_head import AnglularLinear if TYPE_CHECKING: diff --git a/src/otx/algo/detection/backbones/pytorchcv_backbones.py b/src/otx/algo/detection/backbones/pytorchcv_backbones.py index 643b784420b..fd10250dc00 100644 --- a/src/otx/algo/detection/backbones/pytorchcv_backbones.py +++ b/src/otx/algo/detection/backbones/pytorchcv_backbones.py @@ -9,6 +9,7 @@ from typing import TYPE_CHECKING import torch +from mmcv.cnn import build_activation_layer, build_norm_layer from mmdet.registry import MODELS from mmengine.dist import get_dist_info from pytorchcv.model_provider import _models @@ -16,8 +17,6 @@ from torch import distributed, nn from torch.nn.modules.batchnorm import _BatchNorm -from mmcv.cnn import build_activation_layer, build_norm_layer - if TYPE_CHECKING: from mmdet.registry import Registry from mmengine.config import Config, ConfigDict diff --git a/src/otx/algo/detection/utils/mmcv_patched_ops.py b/src/otx/algo/detection/utils/mmcv_patched_ops.py index c43b9088c5f..4ea42163f16 100644 --- a/src/otx/algo/detection/utils/mmcv_patched_ops.py +++ b/src/otx/algo/detection/utils/mmcv_patched_ops.py @@ -8,11 +8,10 @@ from typing import TYPE_CHECKING import torch +from mmcv.utils import ext_loader from torchvision.ops import nms as tv_nms from torchvision.ops import roi_align as tv_roi_align -from mmcv.utils import ext_loader - if TYPE_CHECKING: from mmcv.ops.nms import NMSop from mmcv.ops.roi_align import RoIAlign diff --git a/src/otx/algo/segmentation/backbones/litehrnet.py b/src/otx/algo/segmentation/backbones/litehrnet.py index 05bac2aa5d0..b503f5a65c3 100644 --- a/src/otx/algo/segmentation/backbones/litehrnet.py +++ b/src/otx/algo/segmentation/backbones/litehrnet.py @@ -12,13 +12,13 @@ import torch import torch.utils.checkpoint as cp +from mmcv.cnn import ConvModule, build_conv_layer, build_norm_layer from mmengine.model import BaseModule from mmengine.utils import is_tuple_of from mmseg.registry import MODELS from torch import nn from torch.nn import functional -from mmcv.cnn import ConvModule, build_conv_layer, build_norm_layer from otx.algo.utils.segmentation import ( AsymmetricPositionAttentionModule, IterativeAggregator, diff --git a/src/otx/algo/utils/segmentation.py b/src/otx/algo/utils/segmentation.py index bb2ae2acce4..af40ce316dd 100644 --- a/src/otx/algo/utils/segmentation.py +++ b/src/otx/algo/utils/segmentation.py @@ -9,11 +9,10 @@ import torch import torch.nn.functional as f +from mmcv.cnn import ConvModule, DepthwiseSeparableConvModule from torch import nn from torch.nn import AdaptiveAvgPool2d, AdaptiveMaxPool2d -from mmcv.cnn import ConvModule, DepthwiseSeparableConvModule - def channel_shuffle(x: torch.Tensor, groups: int) -> torch.Tensor: """Channel Shuffle operation. diff --git a/src/otx/core/data/transform_libs/mmaction.py b/src/otx/core/data/transform_libs/mmaction.py index 2d61ce7c967..f1f2f6994f1 100644 --- a/src/otx/core/data/transform_libs/mmaction.py +++ b/src/otx/core/data/transform_libs/mmaction.py @@ -10,6 +10,7 @@ from pathlib import Path from typing import TYPE_CHECKING, Any, Callable +import mmcv import numpy as np from mmaction.datasets.transforms import PackActionInputs as MMPackActionInputs from mmaction.datasets.transforms import RawFrameDecode as MMRawFrameDecode @@ -17,7 +18,6 @@ from mmengine.fileio import FileClient from torchvision import tv_tensors -import mmcv from otx.core.data.entity.action_classification import ActionClsDataEntity from otx.core.data.entity.action_detection import ActionDetDataEntity from otx.core.utils.config import convert_conf_to_mmconfig_dict diff --git a/src/otx/core/data/transform_libs/mmcv.py b/src/otx/core/data/transform_libs/mmcv.py index 755a691ce92..f763aee3be4 100644 --- a/src/otx/core/data/transform_libs/mmcv.py +++ b/src/otx/core/data/transform_libs/mmcv.py @@ -8,9 +8,9 @@ from typing import TYPE_CHECKING, Callable import numpy as np - from mmcv.transforms import LoadImageFromFile as MMCVLoadImageFromFile from mmcv.transforms.builder import TRANSFORMS + from otx.core.data.entity.base import OTXDataEntity from otx.core.utils.config import convert_conf_to_mmconfig_dict diff --git a/src/otx/core/data/transform_libs/mmdet.py b/src/otx/core/data/transform_libs/mmdet.py index 93ddf24a031..68353b4c4d8 100644 --- a/src/otx/core/data/transform_libs/mmdet.py +++ b/src/otx/core/data/transform_libs/mmdet.py @@ -12,6 +12,7 @@ import numpy as np import torch from datumaro import Polygon +from mmcv.transforms import BaseTransform from mmdet.datasets.transforms import LoadAnnotations as MMDetLoadAnnotations from mmdet.datasets.transforms import PackDetInputs as MMDetPackDetInputs from mmdet.registry import TRANSFORMS as MMDET_TRANSFORMS @@ -19,7 +20,6 @@ from mmengine.registry import Registry from torchvision import tv_tensors -from mmcv.transforms import BaseTransform from otx.core.data.entity.base import ImageInfo from otx.core.data.entity.detection import DetDataEntity from otx.core.data.entity.instance_segmentation import InstanceSegDataEntity diff --git a/src/otx/engine/engine.py b/src/otx/engine/engine.py index 5e3f8720da6..096c8d2a86f 100644 --- a/src/otx/engine/engine.py +++ b/src/otx/engine/engine.py @@ -138,10 +138,10 @@ def __init__( ) if self.task in [OTXTaskType.DETECTION, OTXTaskType.INSTANCE_SEGMENTATION] and self.device.accelerator == "xpu": import numpy as np - from mmengine.structures import instance_data - from mmcv.ops.nms import NMSop from mmcv.ops.roi_align import RoIAlign + from mmengine.structures import instance_data + from otx.algo.detection.utils import monkey_patched_nms, monkey_patched_roi_align long_type_tensor = Union[torch.LongTensor, torch.xpu.LongTensor] diff --git a/tests/unit/core/data/transform_libs/test_mmcv.py b/tests/unit/core/data/transform_libs/test_mmcv.py index 263936fee34..06ab7e79724 100644 --- a/tests/unit/core/data/transform_libs/test_mmcv.py +++ b/tests/unit/core/data/transform_libs/test_mmcv.py @@ -4,13 +4,12 @@ import numpy as np import pytest +from mmcv.transforms.builder import TRANSFORMS from otx.core.config.data import SubsetConfig from otx.core.data.entity.base import ImageInfo, OTXDataEntity from otx.core.data.transform_libs.mmcv import LoadImageFromFile, MMCVTransformLib from otx.core.types.transformer_libs import TransformLibType -from mmcv.transforms.builder import TRANSFORMS - class TestLoadImageFromFile: def test_transform(self) -> None: From ea1ea19646320f452377c4a4c027fe094959e9e4 Mon Sep 17 00:00:00 2001 From: kprokofi Date: Wed, 20 Mar 2024 00:40:24 +0900 Subject: [PATCH 20/42] added additional flag for mmcv --- pyproject.toml | 5 +---- src/otx/cli/install.py | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index a88e05a94df..09003281dd9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -67,10 +67,7 @@ docs = [ "nbsphinx", ] base = [ - "torch==2.1.0a0", - "torchvision==0.16.0a0", - "torchaudio==2.1.0a0", - "intel-extension-for-pytorch==2.1.10+xpu", + "torch==2.1.1", "lightning==2.1.2", "pytorchcv", "timm", diff --git a/src/otx/cli/install.py b/src/otx/cli/install.py index 37523539b87..f1a37fd7c1e 100644 --- a/src/otx/cli/install.py +++ b/src/otx/cli/install.py @@ -64,10 +64,20 @@ def add_install_parser(subcommands_action: _ActionSubCommands) -> None: help="Do not install PyTorch. Choose this option if you already install PyTorch.", action="store_true", ) + parser.add_argument( + "--do-not-install-mmcv", + help="Do not install mmcv. Choose this option if you already install specific version of mmcv.", + action="store_true", + ) subcommands_action.add_subcommand("install", parser, help="Install OTX requirements.") -def otx_install(option: str | None = None, verbose: bool = False, do_not_install_torch: bool = False) -> int: +def otx_install( + option: str | None = None, + verbose: bool = False, + do_not_install_torch: bool = False, + do_not_install_mmcv: bool = False, +) -> int: """Install OTX requirements. Args: @@ -109,7 +119,7 @@ def otx_install(option: str | None = None, verbose: bool = False, do_not_install # Parse mmX requirements if the task requires mmX packages. mmcv_install_args = [] - if mmcv_requirements: + if mmcv_requirements and not do_not_install_mmcv: mmcv_install_args = get_mmcv_install_args(torch_requirement, mmcv_requirements) install_args += ["openmim"] From aaf5568f3d4168f05dcf1b54f0512c591b8ba00d Mon Sep 17 00:00:00 2001 From: kprokofi Date: Wed, 20 Mar 2024 07:39:46 +0900 Subject: [PATCH 21/42] added unit tests --- src/otx/engine/engine.py | 30 ++++++---- tests/unit/algo/accelerators/__init__.py | 4 ++ tests/unit/algo/accelerators/test_xpu.py | 59 +++++++++++++++++++ tests/unit/algo/plugins/__init__.py | 4 ++ tests/unit/algo/plugins/test_plugins.py | 56 ++++++++++++++++++ tests/unit/algo/strategies/__init__.py | 4 ++ tests/unit/algo/strategies/test_strategies.py | 48 +++++++++++++++ 7 files changed, 192 insertions(+), 13 deletions(-) create mode 100644 tests/unit/algo/accelerators/__init__.py create mode 100644 tests/unit/algo/accelerators/test_xpu.py create mode 100644 tests/unit/algo/plugins/__init__.py create mode 100644 tests/unit/algo/plugins/test_plugins.py create mode 100644 tests/unit/algo/strategies/__init__.py create mode 100644 tests/unit/algo/strategies/test_strategies.py diff --git a/src/otx/engine/engine.py b/src/otx/engine/engine.py index d4fcb694140..2be107aee35 100644 --- a/src/otx/engine/engine.py +++ b/src/otx/engine/engine.py @@ -136,19 +136,7 @@ def __init__( label_info=self._datamodule.label_info if self._datamodule is not None else None, ) ) - if self.task in [OTXTaskType.DETECTION, OTXTaskType.INSTANCE_SEGMENTATION] and self.device.accelerator == "xpu": - import numpy as np - from mmcv.ops.nms import NMSop - from mmcv.ops.roi_align import RoIAlign - from mmengine.structures import instance_data - - from otx.algo.detection.utils import monkey_patched_nms, monkey_patched_roi_align - - long_type_tensor = Union[torch.LongTensor, torch.xpu.LongTensor] - bool_type_tensor = Union[torch.BoolTensor, torch.xpu.BoolTensor] - instance_data.IndexType = Union[str, slice, int, list, long_type_tensor, bool_type_tensor, np.ndarray] - NMSop.forward = monkey_patched_nms - RoIAlign.forward = monkey_patched_roi_align + self._patch_packages_xpu() self.optimizer: list[OptimizerCallable] | OptimizerCallable | None = ( optimizer if optimizer is not None else self._auto_configurator.get_optimizer() @@ -927,3 +915,19 @@ def _get_anomaly_model( model.optimizer = optimizer model.scheduler = scheduler return model + + def _patch_packages_xpu(self) -> None: + """Patch packages when xpu is available.""" + if self.task in [OTXTaskType.DETECTION, OTXTaskType.INSTANCE_SEGMENTATION] and self.device.accelerator == "xpu": + import numpy as np + from mmcv.ops.nms import NMSop + from mmcv.ops.roi_align import RoIAlign + from mmengine.structures import instance_data + + from otx.algo.detection.utils import monkey_patched_nms, monkey_patched_roi_align + + long_type_tensor = Union[torch.LongTensor, torch.xpu.LongTensor] + bool_type_tensor = Union[torch.BoolTensor, torch.xpu.BoolTensor] + instance_data.IndexType = Union[str, slice, int, list, long_type_tensor, bool_type_tensor, np.ndarray] + NMSop.forward = monkey_patched_nms + RoIAlign.forward = monkey_patched_roi_align diff --git a/tests/unit/algo/accelerators/__init__.py b/tests/unit/algo/accelerators/__init__.py new file mode 100644 index 00000000000..9996ffc6523 --- /dev/null +++ b/tests/unit/algo/accelerators/__init__.py @@ -0,0 +1,4 @@ +# Copyright (C) 2024 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# +"""Unit tests of accelerators of OTX algo.""" diff --git a/tests/unit/algo/accelerators/test_xpu.py b/tests/unit/algo/accelerators/test_xpu.py new file mode 100644 index 00000000000..cd335b66284 --- /dev/null +++ b/tests/unit/algo/accelerators/test_xpu.py @@ -0,0 +1,59 @@ +# Copyright (C) 2024 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# +"""Test for otx.algo.accelerators.xpu""" + + +import pytest +import torch +from otx.algo.accelerators import XPUAccelerator +from otx.utils.utils import is_xpu_available + + +class TestXPUAccelerator: + @pytest.fixture + def accelerator(self, mocker): + mock_torch = mocker.patch("otx.algo.accelerators.xpu.torch") + return XPUAccelerator(), mock_torch + + def test_setup_device(self, accelerator): + accelerator, mock_torch = accelerator + device = torch.device("xpu") + accelerator.setup_device(device) + assert mock_torch.xpu.set_device.called + + def test_parse_devices(self, accelerator): + accelerator, _ = accelerator + devices = [1, 2, 3] + parsed_devices = accelerator.parse_devices(devices) + assert isinstance(parsed_devices, list) + assert parsed_devices == devices + + def test_get_parallel_devices(self, accelerator, mocker): + accelerator, _ = accelerator + devices = [1, 2, 3] + parallel_devices = accelerator.get_parallel_devices(devices) + assert isinstance(parallel_devices, list) + assert all([isinstance(device, mocker.MagicMock) for device in parallel_devices]) + + def test_auto_device_count(self, accelerator, mocker): + accelerator, mock_torch = accelerator + count = accelerator.auto_device_count() + assert isinstance(count, mocker.MagicMock) + assert mock_torch.xpu.device_count.called + + def test_is_available(self, accelerator): + accelerator, _ = accelerator + available = accelerator.is_available() + assert isinstance(available, bool) + assert available == is_xpu_available() + + def test_get_device_stats(self, accelerator): + accelerator, _ = accelerator + device = torch.device("xpu") + stats = accelerator.get_device_stats(device) + assert isinstance(stats, dict) + + def test_teardown(self, accelerator): + accelerator, _ = accelerator + accelerator.teardown() diff --git a/tests/unit/algo/plugins/__init__.py b/tests/unit/algo/plugins/__init__.py new file mode 100644 index 00000000000..be7fe475146 --- /dev/null +++ b/tests/unit/algo/plugins/__init__.py @@ -0,0 +1,4 @@ +# Copyright (C) 2024 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# +"""Unit tests of plugins of OTX algo.""" diff --git a/tests/unit/algo/plugins/test_plugins.py b/tests/unit/algo/plugins/test_plugins.py new file mode 100644 index 00000000000..905b07f8d5b --- /dev/null +++ b/tests/unit/algo/plugins/test_plugins.py @@ -0,0 +1,56 @@ +# Copyright (C) 2024 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# +"""Test for otx.algo.plugins.xpu_precision""" + + +import pytest +import torch +from torch.optim import Optimizer +from otx.algo.plugins.xpu_precision import MixedPrecisionXPUPlugin + + +class TestMixedPrecisionXPUPlugin: + @pytest.fixture + def plugin(self): + return MixedPrecisionXPUPlugin() + + def test_init(self, plugin): + assert plugin.scaler is None + + def test_pre_backward(self, plugin, mocker): + tensor = torch.zeros(1) + module = mocker.MagicMock() + output = plugin.pre_backward(tensor, module) + assert output == tensor + + def test_optimizer_step_no_scaler(self, plugin, mocker): + optimizer = mocker.MagicMock(Optimizer) + model = mocker.MagicMock() + closure = mocker.MagicMock() + kwargs = {} + mock_optimizer_step = mocker.patch( + "otx.algo.plugins.xpu_precision.Precision.optimizer_step" + ) + out = plugin.optimizer_step(optimizer, model, closure, **kwargs) + assert isinstance(out, mocker.MagicMock) + mock_optimizer_step.assert_called_once() + + def test_optimizer_step_with_scaler(self, plugin, mocker): + optimizer = mocker.MagicMock(Optimizer) + model = mocker.MagicMock() + closure = mocker.MagicMock() + plugin.scaler = mocker.MagicMock() + kwargs = {} + out = plugin.optimizer_step(optimizer, model, closure, **kwargs) + assert isinstance(out, mocker.MagicMock) + + def test_clip_gradients(self, plugin, mocker): + optimizer = mocker.MagicMock(Optimizer) + clip_val = 0.1 + gradient_clip_algorithm = "norm" + mock_clip_gradients = mocker.patch( + "otx.algo.plugins.xpu_precision.Precision.clip_gradients" + ) + plugin.clip_gradients(optimizer, clip_val, gradient_clip_algorithm) + mock_clip_gradients.assert_called_once() diff --git a/tests/unit/algo/strategies/__init__.py b/tests/unit/algo/strategies/__init__.py new file mode 100644 index 00000000000..8830174eb83 --- /dev/null +++ b/tests/unit/algo/strategies/__init__.py @@ -0,0 +1,4 @@ +# Copyright (C) 2024 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# +"""Unit tests of strategies of OTX algo.""" diff --git a/tests/unit/algo/strategies/test_strategies.py b/tests/unit/algo/strategies/test_strategies.py new file mode 100644 index 00000000000..43a09763add --- /dev/null +++ b/tests/unit/algo/strategies/test_strategies.py @@ -0,0 +1,48 @@ +# Copyright (C) 2024 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# +"""Tests the XPU strategy.""" + + +import pytest +import torch +import pytorch_lightning as pl +from otx.algo.strategies.xpu_single import SingleXPUStrategy +from lightning.pytorch.utilities.exceptions import MisconfigurationException + + +class TestSingleXPUStrategy: + def test_init(self, mocker): + with pytest.raises(MisconfigurationException): + strategy = SingleXPUStrategy(device="xpu:0") + mocked_is_xpu_available = mocker.patch( + "otx.algo.strategies.xpu_single.is_xpu_available", return_value=True + ) + strategy = SingleXPUStrategy(device="xpu:0") + assert mocked_is_xpu_available.call_count == 1 + assert strategy._root_device.type == "xpu" + assert strategy.accelerator is None + + @pytest.fixture + def strategy(self, mocker): + mocker.patch( + "otx.algo.strategies.xpu_single.is_xpu_available", return_value=True + ) + return SingleXPUStrategy(device="xpu:0") + + def test_is_distributed(self, strategy): + assert not strategy.is_distributed + + def test_setup_optimizers(self, strategy, mocker): + mocker.patch("otx.algo.strategies.xpu_single.torch") + mocker.patch( + "otx.algo.strategies.xpu_single.torch.xpu.optimize", + return_value=(mocker.MagicMock(), mocker.MagicMock()), + ) + trainer = pl.Trainer() + # Create mock optimizers and models for testing + model = torch.nn.Linear(10, 2) + strategy._optimizers = [torch.optim.Adam(model.parameters(), lr=0.001)] + strategy._model = model + strategy.setup_optimizers(trainer) + assert len(strategy.optimizers) == 1 From a3573c1c36a425f2e06ec873d53968faba6201b2 Mon Sep 17 00:00:00 2001 From: kprokofi Date: Wed, 20 Mar 2024 07:41:59 +0900 Subject: [PATCH 22/42] fixed unit test --- tests/unit/cli/test_install.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/cli/test_install.py b/tests/unit/cli/test_install.py index a55c587a8a9..51464e8b43d 100644 --- a/tests/unit/cli/test_install.py +++ b/tests/unit/cli/test_install.py @@ -28,7 +28,7 @@ def test_add_install_parser(self) -> None: assert parser_subcommands.choices.get("install") is not None install_parser = parser_subcommands.choices.get("install") argument_list = [action.dest for action in install_parser._actions] - expected_argument = ["help", "option", "verbose", "do_not_install_torch"] + expected_argument = ["help", "option", "verbose", "do_not_install_torch", "do_not_install_mmcv"] assert argument_list == expected_argument def test_install_extra(self, mocker: MockerFixture) -> None: From 2184b7d7b784677b3ad398cb0a74dd00772cff50 Mon Sep 17 00:00:00 2001 From: kprokofi Date: Wed, 20 Mar 2024 07:50:17 +0900 Subject: [PATCH 23/42] fix linter --- tests/unit/algo/accelerators/test_xpu.py | 5 +++-- tests/unit/algo/plugins/test_plugins.py | 8 ++++---- tests/unit/algo/strategies/test_strategies.py | 12 +++++++----- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/tests/unit/algo/accelerators/test_xpu.py b/tests/unit/algo/accelerators/test_xpu.py index cd335b66284..28bde8e5976 100644 --- a/tests/unit/algo/accelerators/test_xpu.py +++ b/tests/unit/algo/accelerators/test_xpu.py @@ -11,7 +11,7 @@ class TestXPUAccelerator: - @pytest.fixture + @pytest.fixture() def accelerator(self, mocker): mock_torch = mocker.patch("otx.algo.accelerators.xpu.torch") return XPUAccelerator(), mock_torch @@ -34,7 +34,8 @@ def test_get_parallel_devices(self, accelerator, mocker): devices = [1, 2, 3] parallel_devices = accelerator.get_parallel_devices(devices) assert isinstance(parallel_devices, list) - assert all([isinstance(device, mocker.MagicMock) for device in parallel_devices]) + for device in parallel_devices: + assert isinstance(device, mocker.MagicMock) def test_auto_device_count(self, accelerator, mocker): accelerator, mock_torch = accelerator diff --git a/tests/unit/algo/plugins/test_plugins.py b/tests/unit/algo/plugins/test_plugins.py index 905b07f8d5b..a84f4ec18d6 100644 --- a/tests/unit/algo/plugins/test_plugins.py +++ b/tests/unit/algo/plugins/test_plugins.py @@ -6,12 +6,12 @@ import pytest import torch -from torch.optim import Optimizer from otx.algo.plugins.xpu_precision import MixedPrecisionXPUPlugin +from torch.optim import Optimizer class TestMixedPrecisionXPUPlugin: - @pytest.fixture + @pytest.fixture() def plugin(self): return MixedPrecisionXPUPlugin() @@ -30,7 +30,7 @@ def test_optimizer_step_no_scaler(self, plugin, mocker): closure = mocker.MagicMock() kwargs = {} mock_optimizer_step = mocker.patch( - "otx.algo.plugins.xpu_precision.Precision.optimizer_step" + "otx.algo.plugins.xpu_precision.Precision.optimizer_step", ) out = plugin.optimizer_step(optimizer, model, closure, **kwargs) assert isinstance(out, mocker.MagicMock) @@ -50,7 +50,7 @@ def test_clip_gradients(self, plugin, mocker): clip_val = 0.1 gradient_clip_algorithm = "norm" mock_clip_gradients = mocker.patch( - "otx.algo.plugins.xpu_precision.Precision.clip_gradients" + "otx.algo.plugins.xpu_precision.Precision.clip_gradients", ) plugin.clip_gradients(optimizer, clip_val, gradient_clip_algorithm) mock_clip_gradients.assert_called_once() diff --git a/tests/unit/algo/strategies/test_strategies.py b/tests/unit/algo/strategies/test_strategies.py index 43a09763add..8d76bb7d76c 100644 --- a/tests/unit/algo/strategies/test_strategies.py +++ b/tests/unit/algo/strategies/test_strategies.py @@ -5,10 +5,10 @@ import pytest -import torch import pytorch_lightning as pl -from otx.algo.strategies.xpu_single import SingleXPUStrategy +import torch from lightning.pytorch.utilities.exceptions import MisconfigurationException +from otx.algo.strategies.xpu_single import SingleXPUStrategy class TestSingleXPUStrategy: @@ -16,17 +16,19 @@ def test_init(self, mocker): with pytest.raises(MisconfigurationException): strategy = SingleXPUStrategy(device="xpu:0") mocked_is_xpu_available = mocker.patch( - "otx.algo.strategies.xpu_single.is_xpu_available", return_value=True + "otx.algo.strategies.xpu_single.is_xpu_available", + return_value=True, ) strategy = SingleXPUStrategy(device="xpu:0") assert mocked_is_xpu_available.call_count == 1 assert strategy._root_device.type == "xpu" assert strategy.accelerator is None - @pytest.fixture + @pytest.fixture() def strategy(self, mocker): mocker.patch( - "otx.algo.strategies.xpu_single.is_xpu_available", return_value=True + "otx.algo.strategies.xpu_single.is_xpu_available", + return_value=True, ) return SingleXPUStrategy(device="xpu:0") From 7e303a1a9caedfa247c9c98d47e7956d5fee01d0 Mon Sep 17 00:00:00 2001 From: kprokofi Date: Thu, 21 Mar 2024 02:29:33 +0900 Subject: [PATCH 24/42] added unit tests and replied comments --- .../algo/detection/utils/mmcv_patched_ops.py | 1 - src/otx/engine/engine.py | 21 +---- src/otx/utils/utils.py | 21 ++++- tests/unit/algo/detection/utils/__init__.py | 4 + .../detection/utils/test_mmcv_patched_ops.py | 91 +++++++++++++++++++ 5 files changed, 118 insertions(+), 20 deletions(-) create mode 100644 tests/unit/algo/detection/utils/__init__.py create mode 100644 tests/unit/algo/detection/utils/test_mmcv_patched_ops.py diff --git a/src/otx/algo/detection/utils/mmcv_patched_ops.py b/src/otx/algo/detection/utils/mmcv_patched_ops.py index 4ea42163f16..ec3a884232d 100644 --- a/src/otx/algo/detection/utils/mmcv_patched_ops.py +++ b/src/otx/algo/detection/utils/mmcv_patched_ops.py @@ -55,7 +55,6 @@ def monkey_patched_nms( inds = inds[:max_num] if is_filtering_by_score: inds = valid_inds[inds] - print(inds) return inds diff --git a/src/otx/engine/engine.py b/src/otx/engine/engine.py index 2be107aee35..74a36f1d0e3 100644 --- a/src/otx/engine/engine.py +++ b/src/otx/engine/engine.py @@ -26,6 +26,7 @@ from otx.core.types.precision import OTXPrecisionType from otx.core.types.task import OTXTaskType from otx.core.utils.cache import TrainerArgumentsCache +from otx.utils.utils import patch_packages_xpu from .hpo import execute_hpo, update_hyper_parameter from .utils.auto_configurator import DEFAULT_CONFIG_PER_TASK, AutoConfigurator @@ -136,7 +137,7 @@ def __init__( label_info=self._datamodule.label_info if self._datamodule is not None else None, ) ) - self._patch_packages_xpu() + patch_packages_xpu(self.task.value, self.device.accelerator.value) self.optimizer: list[OptimizerCallable] | OptimizerCallable | None = ( optimizer if optimizer is not None else self._auto_configurator.get_optimizer() @@ -811,7 +812,7 @@ def _build_trainer(self, **kwargs) -> None: if self._device.accelerator == DeviceType.xpu: self._cache.update(strategy="xpu_single") # add plugin for Automatic Mixed Precision on XPU - if kwargs["precision"] == 16: + if self._cache.args["precision"] == 16: self._cache.update(plugins=[MixedPrecisionXPUPlugin()]) self._cache.args["precision"] = None @@ -915,19 +916,3 @@ def _get_anomaly_model( model.optimizer = optimizer model.scheduler = scheduler return model - - def _patch_packages_xpu(self) -> None: - """Patch packages when xpu is available.""" - if self.task in [OTXTaskType.DETECTION, OTXTaskType.INSTANCE_SEGMENTATION] and self.device.accelerator == "xpu": - import numpy as np - from mmcv.ops.nms import NMSop - from mmcv.ops.roi_align import RoIAlign - from mmengine.structures import instance_data - - from otx.algo.detection.utils import monkey_patched_nms, monkey_patched_roi_align - - long_type_tensor = Union[torch.LongTensor, torch.xpu.LongTensor] - bool_type_tensor = Union[torch.BoolTensor, torch.xpu.BoolTensor] - instance_data.IndexType = Union[str, slice, int, list, long_type_tensor, bool_type_tensor, np.ndarray] - NMSop.forward = monkey_patched_nms - RoIAlign.forward = monkey_patched_roi_align diff --git a/src/otx/utils/utils.py b/src/otx/utils/utils.py index bca60c4b5b4..42f41cc48fd 100644 --- a/src/otx/utils/utils.py +++ b/src/otx/utils/utils.py @@ -6,7 +6,8 @@ from __future__ import annotations from decimal import Decimal -from typing import TYPE_CHECKING, Any +from typing import TYPE_CHECKING, Any, Union +from otx.core.types.task import OTXTaskType import torch @@ -130,3 +131,21 @@ def is_xpu_available() -> bool: if XPU_AVAILABLE is None: XPU_AVAILABLE = hasattr(torch, "xpu") and torch.xpu.is_available() return XPU_AVAILABLE + + +def patch_packages_xpu(task: str, accelerator: str) -> None: + """Patch packages when xpu is available.""" + if accelerator == "xpu" and ("DETECTION" in task or "INSTANCE_SEGMENTATION" in task): + import numpy as np + from mmcv.ops.nms import NMSop + from mmcv.ops.roi_align import RoIAlign + from mmengine.structures import instance_data + + from otx.algo.detection.utils import monkey_patched_nms, monkey_patched_roi_align + + + long_type_tensor = Union[torch.LongTensor, torch.xpu.LongTensor] + bool_type_tensor = Union[torch.BoolTensor, torch.xpu.BoolTensor] + instance_data.IndexType = Union[str, slice, int, list, long_type_tensor, bool_type_tensor, np.ndarray] + NMSop.forward = monkey_patched_nms + RoIAlign.forward = monkey_patched_roi_align diff --git a/tests/unit/algo/detection/utils/__init__.py b/tests/unit/algo/detection/utils/__init__.py new file mode 100644 index 00000000000..a3c91b9065c --- /dev/null +++ b/tests/unit/algo/detection/utils/__init__.py @@ -0,0 +1,4 @@ +# Copyright (C) 2024 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# +"""Test of utils for OTX Detection task.""" diff --git a/tests/unit/algo/detection/utils/test_mmcv_patched_ops.py b/tests/unit/algo/detection/utils/test_mmcv_patched_ops.py new file mode 100644 index 00000000000..933989e35e1 --- /dev/null +++ b/tests/unit/algo/detection/utils/test_mmcv_patched_ops.py @@ -0,0 +1,91 @@ +# Copyright (C) 2024 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# +"""Test of mmcv_patched_ops.""" + +import pytest +import torch +from mmcv.ops import nms +from otx.algo.detection.utils.mmcv_patched_ops import monkey_patched_nms +from mmcv.ops.roi_align import RoIAlign +from otx.algo.detection.utils import monkey_patched_roi_align + + +class TestMonkeyPatchedNMS: + @pytest.fixture + def setup(self): + self.ctx = None + self.bboxes = torch.tensor([[0.324, 0.422, 0.469, 0.123], [0.324, 0.422, 0.469, 0.123], [0.314, 0.423, 0.469, 0.123]]) + self.scores = torch.tensor([0.9, 0.2, 0.3]) + self.iou_threshold = 0.5 + self.offset = 0 + self.score_threshold = 0 + self.max_num = 0 + + def test_case1(self, setup): + # Testing when is_filtering_by_score is False + result = monkey_patched_nms(self.ctx, self.bboxes, self.scores, self.iou_threshold, self.offset, self.score_threshold, self.max_num) + assert torch.equal(result, torch.tensor([0, 2, 1])) + + def test_case2(self, setup): + # Testing when is_filtering_by_score is True + self.score_threshold = 0.8 + result = monkey_patched_nms(self.ctx, self.bboxes, self.scores, self.iou_threshold, self.offset, self.score_threshold, self.max_num) + assert torch.equal(result, torch.tensor([0])) + + def test_case3(self, setup): + # Testing when bboxes and scores have torch.bfloat16 dtype + self.bboxes = torch.tensor([[0.324, 0.422, 0.469, 0.123], [0.324, 0.422, 0.469, 0.123], [0.314, 0.423, 0.469, 0.123]], dtype=torch.bfloat16) + self.scores = torch.tensor([0.9, 0.2, 0.3], dtype=torch.bfloat16) + result1 = monkey_patched_nms(self.ctx, self.bboxes, self.scores, self.iou_threshold, self.offset, self.score_threshold, self.max_num) + assert torch.equal(result1, torch.tensor([0, 2, 1])) + + def test_case4(self, setup): + # Testing when offset is not 0 + self.offset = 1 + result = monkey_patched_nms(self.ctx, self.bboxes, self.scores, self.iou_threshold, self.offset, self.score_threshold, self.max_num) + assert torch.equal(result, torch.tensor([0])) + + def test_case5(self, setup): + # Testing when max_num is greater than 0 + self.max_num = 1 + result = monkey_patched_nms(self.ctx, self.bboxes, self.scores, self.iou_threshold, self.offset, self.score_threshold, self.max_num) + assert torch.equal(result, torch.tensor([0])) + + def test_case6(self, setup): + # Testing that monkey_patched_nms equals mmcv nms + self.score_threshold = 0.7 + result1 = monkey_patched_nms(self.ctx, self.bboxes, self.scores, self.iou_threshold, self.offset, self.score_threshold, self.max_num) + result2 = nms(self.bboxes, self.scores, self.iou_threshold, score_threshold=self.score_threshold) + assert torch.equal(result1, result2[1]) + # test random bboxes and scores + bboxes = torch.rand((100, 4)) + scores = torch.rand(100) + result1 = monkey_patched_nms(self.ctx, bboxes, scores, self.iou_threshold, self.offset, self.score_threshold, self.max_num) + result2 = nms(bboxes, scores, self.iou_threshold, score_threshold=self.score_threshold) + assert torch.equal(result1, result2[1]) + # no score threshold + self.iou_threshold = 0.7 + self.score_threshold = 0.0 + result1 = monkey_patched_nms(self.ctx, bboxes, scores, self.iou_threshold, self.offset, self.score_threshold, self.max_num) + result2 = nms(bboxes, scores, self.iou_threshold) + assert torch.equal(result1, result2[1]) + + +class TestMonkeyPatchedRoIAlign: + @pytest.fixture + def roi_align(self): + return RoIAlign(output_size=(7, 7), spatial_scale=1.0, sampling_ratio=0, aligned=False, use_torchvision=True) + + @pytest.fixture + def input(self): + return torch.randn(1, 3, 32, 32) + + @pytest.fixture + def rois(self): + return torch.tensor([[0, 1, 10, 40, 50], [1, 2, 30, 70, 90]], dtype=torch.float) + + def test_monkey_patched_roi_align(self, roi_align, input, rois): + expected_output = roi_align.forward(input, rois) + output = monkey_patched_roi_align(roi_align, input, rois) + assert torch.allclose(expected_output, output) From 4dd325e7a8b06f833a2b92b473cf143b1bb63d70 Mon Sep 17 00:00:00 2001 From: kprokofi Date: Thu, 21 Mar 2024 02:31:36 +0900 Subject: [PATCH 25/42] fix pre-commit --- src/otx/engine/engine.py | 2 +- src/otx/utils/utils.py | 2 - .../detection/utils/test_mmcv_patched_ops.py | 107 ++++++++++++++---- 3 files changed, 89 insertions(+), 22 deletions(-) diff --git a/src/otx/engine/engine.py b/src/otx/engine/engine.py index 74a36f1d0e3..820816e7b3e 100644 --- a/src/otx/engine/engine.py +++ b/src/otx/engine/engine.py @@ -7,7 +7,7 @@ import inspect from pathlib import Path -from typing import TYPE_CHECKING, Any, Iterable, Literal, Union +from typing import TYPE_CHECKING, Any, Iterable, Literal from warnings import warn import torch diff --git a/src/otx/utils/utils.py b/src/otx/utils/utils.py index 42f41cc48fd..a3dc47263d9 100644 --- a/src/otx/utils/utils.py +++ b/src/otx/utils/utils.py @@ -7,7 +7,6 @@ from decimal import Decimal from typing import TYPE_CHECKING, Any, Union -from otx.core.types.task import OTXTaskType import torch @@ -143,7 +142,6 @@ def patch_packages_xpu(task: str, accelerator: str) -> None: from otx.algo.detection.utils import monkey_patched_nms, monkey_patched_roi_align - long_type_tensor = Union[torch.LongTensor, torch.xpu.LongTensor] bool_type_tensor = Union[torch.BoolTensor, torch.xpu.BoolTensor] instance_data.IndexType = Union[str, slice, int, list, long_type_tensor, bool_type_tensor, np.ndarray] diff --git a/tests/unit/algo/detection/utils/test_mmcv_patched_ops.py b/tests/unit/algo/detection/utils/test_mmcv_patched_ops.py index 933989e35e1..6dd0c120b59 100644 --- a/tests/unit/algo/detection/utils/test_mmcv_patched_ops.py +++ b/tests/unit/algo/detection/utils/test_mmcv_patched_ops.py @@ -6,16 +6,18 @@ import pytest import torch from mmcv.ops import nms -from otx.algo.detection.utils.mmcv_patched_ops import monkey_patched_nms from mmcv.ops.roi_align import RoIAlign from otx.algo.detection.utils import monkey_patched_roi_align +from otx.algo.detection.utils.mmcv_patched_ops import monkey_patched_nms class TestMonkeyPatchedNMS: - @pytest.fixture + @pytest.fixture() def setup(self): self.ctx = None - self.bboxes = torch.tensor([[0.324, 0.422, 0.469, 0.123], [0.324, 0.422, 0.469, 0.123], [0.314, 0.423, 0.469, 0.123]]) + self.bboxes = torch.tensor( + [[0.324, 0.422, 0.469, 0.123], [0.324, 0.422, 0.469, 0.123], [0.314, 0.423, 0.469, 0.123]], + ) self.scores = torch.tensor([0.9, 0.2, 0.3]) self.iou_threshold = 0.5 self.offset = 0 @@ -24,68 +26,135 @@ def setup(self): def test_case1(self, setup): # Testing when is_filtering_by_score is False - result = monkey_patched_nms(self.ctx, self.bboxes, self.scores, self.iou_threshold, self.offset, self.score_threshold, self.max_num) + result = monkey_patched_nms( + self.ctx, + self.bboxes, + self.scores, + self.iou_threshold, + self.offset, + self.score_threshold, + self.max_num, + ) assert torch.equal(result, torch.tensor([0, 2, 1])) def test_case2(self, setup): # Testing when is_filtering_by_score is True self.score_threshold = 0.8 - result = monkey_patched_nms(self.ctx, self.bboxes, self.scores, self.iou_threshold, self.offset, self.score_threshold, self.max_num) + result = monkey_patched_nms( + self.ctx, + self.bboxes, + self.scores, + self.iou_threshold, + self.offset, + self.score_threshold, + self.max_num, + ) assert torch.equal(result, torch.tensor([0])) def test_case3(self, setup): # Testing when bboxes and scores have torch.bfloat16 dtype - self.bboxes = torch.tensor([[0.324, 0.422, 0.469, 0.123], [0.324, 0.422, 0.469, 0.123], [0.314, 0.423, 0.469, 0.123]], dtype=torch.bfloat16) + self.bboxes = torch.tensor( + [[0.324, 0.422, 0.469, 0.123], [0.324, 0.422, 0.469, 0.123], [0.314, 0.423, 0.469, 0.123]], + dtype=torch.bfloat16, + ) self.scores = torch.tensor([0.9, 0.2, 0.3], dtype=torch.bfloat16) - result1 = monkey_patched_nms(self.ctx, self.bboxes, self.scores, self.iou_threshold, self.offset, self.score_threshold, self.max_num) + result1 = monkey_patched_nms( + self.ctx, + self.bboxes, + self.scores, + self.iou_threshold, + self.offset, + self.score_threshold, + self.max_num, + ) assert torch.equal(result1, torch.tensor([0, 2, 1])) def test_case4(self, setup): # Testing when offset is not 0 self.offset = 1 - result = monkey_patched_nms(self.ctx, self.bboxes, self.scores, self.iou_threshold, self.offset, self.score_threshold, self.max_num) + result = monkey_patched_nms( + self.ctx, + self.bboxes, + self.scores, + self.iou_threshold, + self.offset, + self.score_threshold, + self.max_num, + ) assert torch.equal(result, torch.tensor([0])) def test_case5(self, setup): # Testing when max_num is greater than 0 self.max_num = 1 - result = monkey_patched_nms(self.ctx, self.bboxes, self.scores, self.iou_threshold, self.offset, self.score_threshold, self.max_num) + result = monkey_patched_nms( + self.ctx, + self.bboxes, + self.scores, + self.iou_threshold, + self.offset, + self.score_threshold, + self.max_num, + ) assert torch.equal(result, torch.tensor([0])) def test_case6(self, setup): # Testing that monkey_patched_nms equals mmcv nms self.score_threshold = 0.7 - result1 = monkey_patched_nms(self.ctx, self.bboxes, self.scores, self.iou_threshold, self.offset, self.score_threshold, self.max_num) + result1 = monkey_patched_nms( + self.ctx, + self.bboxes, + self.scores, + self.iou_threshold, + self.offset, + self.score_threshold, + self.max_num, + ) result2 = nms(self.bboxes, self.scores, self.iou_threshold, score_threshold=self.score_threshold) assert torch.equal(result1, result2[1]) # test random bboxes and scores bboxes = torch.rand((100, 4)) scores = torch.rand(100) - result1 = monkey_patched_nms(self.ctx, bboxes, scores, self.iou_threshold, self.offset, self.score_threshold, self.max_num) + result1 = monkey_patched_nms( + self.ctx, + bboxes, + scores, + self.iou_threshold, + self.offset, + self.score_threshold, + self.max_num, + ) result2 = nms(bboxes, scores, self.iou_threshold, score_threshold=self.score_threshold) assert torch.equal(result1, result2[1]) # no score threshold self.iou_threshold = 0.7 self.score_threshold = 0.0 - result1 = monkey_patched_nms(self.ctx, bboxes, scores, self.iou_threshold, self.offset, self.score_threshold, self.max_num) + result1 = monkey_patched_nms( + self.ctx, + bboxes, + scores, + self.iou_threshold, + self.offset, + self.score_threshold, + self.max_num, + ) result2 = nms(bboxes, scores, self.iou_threshold) assert torch.equal(result1, result2[1]) class TestMonkeyPatchedRoIAlign: - @pytest.fixture + @pytest.fixture() def roi_align(self): return RoIAlign(output_size=(7, 7), spatial_scale=1.0, sampling_ratio=0, aligned=False, use_torchvision=True) - @pytest.fixture - def input(self): + @pytest.fixture() + def input_image(self): return torch.randn(1, 3, 32, 32) - @pytest.fixture + @pytest.fixture() def rois(self): return torch.tensor([[0, 1, 10, 40, 50], [1, 2, 30, 70, 90]], dtype=torch.float) - def test_monkey_patched_roi_align(self, roi_align, input, rois): - expected_output = roi_align.forward(input, rois) - output = monkey_patched_roi_align(roi_align, input, rois) + def test_monkey_patched_roi_align(self, roi_align, input_image, rois): + expected_output = roi_align.forward(input_image, rois) + output = monkey_patched_roi_align(roi_align, input_image, rois) assert torch.allclose(expected_output, output) From 64a41006625dde4ccb4ca7b45d924e63ec3840f5 Mon Sep 17 00:00:00 2001 From: kprokofi Date: Thu, 21 Mar 2024 05:10:25 +0900 Subject: [PATCH 26/42] minor fix --- 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 820816e7b3e..e3f6c4cae56 100644 --- a/src/otx/engine/engine.py +++ b/src/otx/engine/engine.py @@ -137,7 +137,7 @@ def __init__( label_info=self._datamodule.label_info if self._datamodule is not None else None, ) ) - patch_packages_xpu(self.task.value, self.device.accelerator.value) + patch_packages_xpu(self.task.value, self.device.accelerator) self.optimizer: list[OptimizerCallable] | OptimizerCallable | None = ( optimizer if optimizer is not None else self._auto_configurator.get_optimizer() From 967b2db4b041e0ddfd5913e67c7b0f34d1556355 Mon Sep 17 00:00:00 2001 From: kprokofi Date: Thu, 21 Mar 2024 05:53:34 +0900 Subject: [PATCH 27/42] added documentation --- .../source/guide/get_started/installation.rst | 68 ++++++++++++++++++- 1 file changed, 65 insertions(+), 3 deletions(-) diff --git a/docs/source/guide/get_started/installation.rst b/docs/source/guide/get_started/installation.rst index fd4ce0d08f6..09709394a38 100644 --- a/docs/source/guide/get_started/installation.rst +++ b/docs/source/guide/get_started/installation.rst @@ -11,9 +11,9 @@ The current version of OpenVINO™ Training Extensions was tested in the followi - Python >= 3.10 -*********************************************** -Install OpenVINO™ Training Extensions for users -*********************************************** +********************************************************** +Install OpenVINO™ Training Extensions for users (CUDA/CPU) +********************************************************** 1. Clone the training_extensions repository with the following command: @@ -65,6 +65,68 @@ virtual environment. 5. Once the package is installed in the virtual environment, you can use full OpenVINO™ Training Extensions command line functionality. +************************************************************* +Install OpenVINO™ Training Extensions for users (XPU devices) +************************************************************* + +1. Follow the first two steps from above instructions +on cloning the repository and creating a virtual environment. + +2. Install Intel Extensions For Pytorch (IPEX). +Follow the `official documentation `_ to install prerequisites such as OneAPI and proper drivers. + +.. code-block:: shell + + python -m pip install torch==2.1.0a0 torchvision==0.16.0a0 torchaudio==2.1.0a0 intel-extension-for-pytorch==2.1.10+xpu --extra-index-url https://pytorch-extension.intel.com/release-whl/stable/xpu/us/ + +3. Install MMCV. +It is required to install mmcv from source to properly build it with IPEX. + +.. code-block:: shell + + git clone https://github.com/open-mmlab/mmcv + cd mmcv + git checkout v2.1.0 + MMCV_WITH_OPS=1 pip install -e . + +4. Install OpenVINO™ Training Extensions +package from either: + +* A local source in development mode + +.. code-block:: shell + + pip install -e . + +* PyPI + +.. code-block:: shell + + pip install otx + +5. Install requirements for training +excluding Pytorch and MMCV. + +.. code-block:: shell + + otx install -v --do-not-install-torch --do-no-install-mmcv + +6. Activate OneAPI environment +and export required IPEX system variables + +.. code-block:: shell + + source /path/to/intel/oneapi/setvars.sh + export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.30 + export IPEX_FP32_MATH_MODE=TF32 + +7. Once the package is installed in the virtual environment, you can use full +OpenVINO™ Training Extensions command line functionality. + +.. code-block:: shell + + otx --help + **************************************************** Install OpenVINO™ Training Extensions for developers **************************************************** From 5411d0403895ad89188649ccf7ab4f39fd021611 Mon Sep 17 00:00:00 2001 From: kprokofi Date: Thu, 21 Mar 2024 06:00:03 +0900 Subject: [PATCH 28/42] fix unit test --- src/otx/engine/engine.py | 2 +- src/otx/utils/utils.py | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/otx/engine/engine.py b/src/otx/engine/engine.py index e3f6c4cae56..fa015c588c7 100644 --- a/src/otx/engine/engine.py +++ b/src/otx/engine/engine.py @@ -137,7 +137,7 @@ def __init__( label_info=self._datamodule.label_info if self._datamodule is not None else None, ) ) - patch_packages_xpu(self.task.value, self.device.accelerator) + patch_packages_xpu(self.task, self.device.accelerator) self.optimizer: list[OptimizerCallable] | OptimizerCallable | None = ( optimizer if optimizer is not None else self._auto_configurator.get_optimizer() diff --git a/src/otx/utils/utils.py b/src/otx/utils/utils.py index a3dc47263d9..fbee2824cc7 100644 --- a/src/otx/utils/utils.py +++ b/src/otx/utils/utils.py @@ -12,6 +12,9 @@ if TYPE_CHECKING: from pathlib import Path + from otx.core.types.task import OTXTaskType + from otx.core.types.device import DeviceType + XPU_AVAILABLE = None try: @@ -132,7 +135,7 @@ def is_xpu_available() -> bool: return XPU_AVAILABLE -def patch_packages_xpu(task: str, accelerator: str) -> None: +def patch_packages_xpu(task: str | OTXTaskType, accelerator : str | DeviceType) -> None: """Patch packages when xpu is available.""" if accelerator == "xpu" and ("DETECTION" in task or "INSTANCE_SEGMENTATION" in task): import numpy as np From 2f1e4116adfc54419d75f44d81217133f6137b4e Mon Sep 17 00:00:00 2001 From: kprokofi Date: Thu, 21 Mar 2024 06:27:55 +0900 Subject: [PATCH 29/42] add workaround for semantic segmentation --- src/otx/engine/engine.py | 4 +++- src/otx/utils/utils.py | 5 +++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/otx/engine/engine.py b/src/otx/engine/engine.py index fa015c588c7..de2845e8ea4 100644 --- a/src/otx/engine/engine.py +++ b/src/otx/engine/engine.py @@ -810,7 +810,9 @@ def _build_trainer(self, **kwargs) -> None: self._cache.update(**kwargs) # set up xpu device if self._device.accelerator == DeviceType.xpu: - self._cache.update(strategy="xpu_single") + if self.task != "SEMANTIC_SEGMENTATION": + # TODO(Kirill): remove this after fixining bug on the IPEX side #noqa: TD003 + self._cache.update(strategy="xpu_single") # add plugin for Automatic Mixed Precision on XPU if self._cache.args["precision"] == 16: self._cache.update(plugins=[MixedPrecisionXPUPlugin()]) diff --git a/src/otx/utils/utils.py b/src/otx/utils/utils.py index fbee2824cc7..8462e839dd8 100644 --- a/src/otx/utils/utils.py +++ b/src/otx/utils/utils.py @@ -12,8 +12,9 @@ if TYPE_CHECKING: from pathlib import Path - from otx.core.types.task import OTXTaskType + from otx.core.types.device import DeviceType + from otx.core.types.task import OTXTaskType XPU_AVAILABLE = None @@ -135,7 +136,7 @@ def is_xpu_available() -> bool: return XPU_AVAILABLE -def patch_packages_xpu(task: str | OTXTaskType, accelerator : str | DeviceType) -> None: +def patch_packages_xpu(task: str | OTXTaskType, accelerator: str | DeviceType) -> None: """Patch packages when xpu is available.""" if accelerator == "xpu" and ("DETECTION" in task or "INSTANCE_SEGMENTATION" in task): import numpy as np From ef4b93d04c7627dc5ff4a80072e6bafdc7c7aeb0 Mon Sep 17 00:00:00 2001 From: kprokofi Date: Thu, 21 Mar 2024 06:38:55 +0900 Subject: [PATCH 30/42] remove RoiAlignTest due to unstability --- .../detection/utils/test_mmcv_patched_ops.py | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/tests/unit/algo/detection/utils/test_mmcv_patched_ops.py b/tests/unit/algo/detection/utils/test_mmcv_patched_ops.py index 6dd0c120b59..d13da48d1aa 100644 --- a/tests/unit/algo/detection/utils/test_mmcv_patched_ops.py +++ b/tests/unit/algo/detection/utils/test_mmcv_patched_ops.py @@ -139,22 +139,3 @@ def test_case6(self, setup): ) result2 = nms(bboxes, scores, self.iou_threshold) assert torch.equal(result1, result2[1]) - - -class TestMonkeyPatchedRoIAlign: - @pytest.fixture() - def roi_align(self): - return RoIAlign(output_size=(7, 7), spatial_scale=1.0, sampling_ratio=0, aligned=False, use_torchvision=True) - - @pytest.fixture() - def input_image(self): - return torch.randn(1, 3, 32, 32) - - @pytest.fixture() - def rois(self): - return torch.tensor([[0, 1, 10, 40, 50], [1, 2, 30, 70, 90]], dtype=torch.float) - - def test_monkey_patched_roi_align(self, roi_align, input_image, rois): - expected_output = roi_align.forward(input_image, rois) - output = monkey_patched_roi_align(roi_align, input_image, rois) - assert torch.allclose(expected_output, output) From 121be65399806249665e85fa003845e15b15af48 Mon Sep 17 00:00:00 2001 From: kprokofi Date: Thu, 21 Mar 2024 06:39:28 +0900 Subject: [PATCH 31/42] minor --- tests/unit/algo/detection/utils/test_mmcv_patched_ops.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/unit/algo/detection/utils/test_mmcv_patched_ops.py b/tests/unit/algo/detection/utils/test_mmcv_patched_ops.py index d13da48d1aa..09daa1b2cab 100644 --- a/tests/unit/algo/detection/utils/test_mmcv_patched_ops.py +++ b/tests/unit/algo/detection/utils/test_mmcv_patched_ops.py @@ -6,8 +6,6 @@ import pytest import torch from mmcv.ops import nms -from mmcv.ops.roi_align import RoIAlign -from otx.algo.detection.utils import monkey_patched_roi_align from otx.algo.detection.utils.mmcv_patched_ops import monkey_patched_nms From 047b0b7c30ceb52f639afe3c9c18eb611574dc7c Mon Sep 17 00:00:00 2001 From: kprokofi Date: Thu, 21 Mar 2024 07:16:13 +0900 Subject: [PATCH 32/42] remove strategy back --- src/otx/engine/engine.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/otx/engine/engine.py b/src/otx/engine/engine.py index de2845e8ea4..fa015c588c7 100644 --- a/src/otx/engine/engine.py +++ b/src/otx/engine/engine.py @@ -810,9 +810,7 @@ def _build_trainer(self, **kwargs) -> None: self._cache.update(**kwargs) # set up xpu device if self._device.accelerator == DeviceType.xpu: - if self.task != "SEMANTIC_SEGMENTATION": - # TODO(Kirill): remove this after fixining bug on the IPEX side #noqa: TD003 - self._cache.update(strategy="xpu_single") + self._cache.update(strategy="xpu_single") # add plugin for Automatic Mixed Precision on XPU if self._cache.args["precision"] == 16: self._cache.update(plugins=[MixedPrecisionXPUPlugin()]) From 028190a5242db86ec770f0f2aaaffce86ea99caa Mon Sep 17 00:00:00 2001 From: kprokofi Date: Thu, 21 Mar 2024 18:26:54 +0900 Subject: [PATCH 33/42] try to patch SingleDeviceStrategy --- .../source/guide/get_started/installation.rst | 2 +- src/otx/algo/accelerators/xpu.py | 4 +- src/otx/algo/strategies/xpu_single.py | 74 +++++++++---------- src/otx/engine/engine.py | 3 - src/otx/utils/utils.py | 52 +++++++++---- 5 files changed, 80 insertions(+), 55 deletions(-) diff --git a/docs/source/guide/get_started/installation.rst b/docs/source/guide/get_started/installation.rst index 09709394a38..6e20264972d 100644 --- a/docs/source/guide/get_started/installation.rst +++ b/docs/source/guide/get_started/installation.rst @@ -109,7 +109,7 @@ excluding Pytorch and MMCV. .. code-block:: shell - otx install -v --do-not-install-torch --do-no-install-mmcv + otx install -v --do-not-install-torch --do-not-install-mmcv 6. Activate OneAPI environment and export required IPEX system variables diff --git a/src/otx/algo/accelerators/xpu.py b/src/otx/algo/accelerators/xpu.py index b9f861df627..b3f3faa978f 100644 --- a/src/otx/algo/accelerators/xpu.py +++ b/src/otx/algo/accelerators/xpu.py @@ -10,7 +10,7 @@ from lightning.pytorch.accelerators import AcceleratorRegistry from lightning.pytorch.accelerators.accelerator import Accelerator -from otx.utils.utils import is_xpu_available +from otx.utils.utils import is_xpu_available, patch_packages_xpu class XPUAccelerator(Accelerator): @@ -25,6 +25,8 @@ def setup_device(self, device: torch.device) -> None: raise RuntimeError(msg) torch.xpu.set_device(device) + patch_packages_xpu() + @staticmethod def parse_devices(devices: str | list | torch.device) -> list: diff --git a/src/otx/algo/strategies/xpu_single.py b/src/otx/algo/strategies/xpu_single.py index 808f7e27bf3..2ab5df6a4e6 100644 --- a/src/otx/algo/strategies/xpu_single.py +++ b/src/otx/algo/strategies/xpu_single.py @@ -22,47 +22,47 @@ from lightning_fabric.utilities.types import _DEVICE -class SingleXPUStrategy(SingleDeviceStrategy): - """Strategy for training on single XPU device.""" +# class SingleXPUStrategy(SingleDeviceStrategy): +# """Strategy for training on single XPU device.""" - strategy_name = "xpu_single" +# strategy_name = "xpu_single" - def __init__( - self, - device: _DEVICE = "xpu:0", - accelerator: pl.accelerators.Accelerator | None = None, - checkpoint_io: CheckpointIO | None = None, - precision_plugin: PrecisionPlugin | None = None, - ): - if not is_xpu_available(): - msg = "`SingleXPUStrategy` requires XPU devices to run" - raise MisconfigurationException(msg) +# def __init__( +# self, +# device: _DEVICE = "xpu:0", +# accelerator: pl.accelerators.Accelerator | None = None, +# checkpoint_io: CheckpointIO | None = None, +# precision_plugin: PrecisionPlugin | None = None, +# ): +# if not is_xpu_available(): +# msg = "`SingleXPUStrategy` requires XPU devices to run" +# raise MisconfigurationException(msg) - super().__init__( - accelerator=accelerator, - device=device, - checkpoint_io=checkpoint_io, - precision_plugin=precision_plugin, - ) +# super().__init__( +# accelerator=accelerator, +# device=device, +# checkpoint_io=checkpoint_io, +# precision_plugin=precision_plugin, +# ) - @property - def is_distributed(self) -> bool: - """Returns true if the strategy supports distributed training.""" - return False +# @property +# def is_distributed(self) -> bool: +# """Returns true if the strategy supports distributed training.""" +# return False - def setup_optimizers(self, trainer: pl.Trainer) -> None: - """Sets up optimizers.""" - super().setup_optimizers(trainer) - if len(self.optimizers) != 1: # type: ignore[has-type] - msg = "XPU strategy doesn't support multiple optimizers" - raise RuntimeError(msg) - model, optimizer = torch.xpu.optimize(trainer.model, optimizer=self.optimizers[0]) # type: ignore[has-type] - self.optimizers = [optimizer] - self.model = model +# def setup_optimizers(self, trainer: pl.Trainer) -> None: +# """Sets up optimizers.""" +# super().setup_optimizers(trainer) +# if len(self.optimizers) != 1: # type: ignore[has-type] +# msg = "XPU strategy doesn't support multiple optimizers" +# raise RuntimeError(msg) +# model, optimizer = torch.xpu.optimize(trainer.model, optimizer=self.optimizers[0]) # type: ignore[has-type] +# self.optimizers = [optimizer] +# self.model = model -StrategyRegistry.register( - SingleXPUStrategy.strategy_name, - SingleXPUStrategy, - description="Strategy that enables training on single XPU", -) +# StrategyRegistry.register( +# SingleXPUStrategy.strategy_name, +# SingleXPUStrategy, +# description="Strategy that enables training on single XPU", +# ) diff --git a/src/otx/engine/engine.py b/src/otx/engine/engine.py index fa015c588c7..0e22efabc05 100644 --- a/src/otx/engine/engine.py +++ b/src/otx/engine/engine.py @@ -26,7 +26,6 @@ from otx.core.types.precision import OTXPrecisionType from otx.core.types.task import OTXTaskType from otx.core.utils.cache import TrainerArgumentsCache -from otx.utils.utils import patch_packages_xpu from .hpo import execute_hpo, update_hyper_parameter from .utils.auto_configurator import DEFAULT_CONFIG_PER_TASK, AutoConfigurator @@ -137,7 +136,6 @@ def __init__( label_info=self._datamodule.label_info if self._datamodule is not None else None, ) ) - patch_packages_xpu(self.task, self.device.accelerator) self.optimizer: list[OptimizerCallable] | OptimizerCallable | None = ( optimizer if optimizer is not None else self._auto_configurator.get_optimizer() @@ -810,7 +808,6 @@ def _build_trainer(self, **kwargs) -> None: self._cache.update(**kwargs) # set up xpu device if self._device.accelerator == DeviceType.xpu: - self._cache.update(strategy="xpu_single") # add plugin for Automatic Mixed Precision on XPU if self._cache.args["precision"] == 16: self._cache.update(plugins=[MixedPrecisionXPUPlugin()]) diff --git a/src/otx/utils/utils.py b/src/otx/utils/utils.py index 8462e839dd8..7abff15e60e 100644 --- a/src/otx/utils/utils.py +++ b/src/otx/utils/utils.py @@ -7,6 +7,13 @@ from decimal import Decimal from typing import TYPE_CHECKING, Any, Union +import numpy as np +from mmcv.ops.nms import NMSop +from mmcv.ops.roi_align import RoIAlign +from mmengine.structures import instance_data +from lightning.pytorch.strategies.single_device import SingleDeviceStrategy + +from otx.algo.detection.utils import monkey_patched_nms, monkey_patched_roi_align import torch @@ -138,16 +145,35 @@ def is_xpu_available() -> bool: def patch_packages_xpu(task: str | OTXTaskType, accelerator: str | DeviceType) -> None: """Patch packages when xpu is available.""" - if accelerator == "xpu" and ("DETECTION" in task or "INSTANCE_SEGMENTATION" in task): - import numpy as np - from mmcv.ops.nms import NMSop - from mmcv.ops.roi_align import RoIAlign - from mmengine.structures import instance_data - - from otx.algo.detection.utils import monkey_patched_nms, monkey_patched_roi_align - - long_type_tensor = Union[torch.LongTensor, torch.xpu.LongTensor] - bool_type_tensor = Union[torch.BoolTensor, torch.xpu.BoolTensor] - instance_data.IndexType = Union[str, slice, int, list, long_type_tensor, bool_type_tensor, np.ndarray] - NMSop.forward = monkey_patched_nms - RoIAlign.forward = monkey_patched_roi_align + import lightning.pytorch as pl + + def patched_setup_optimizers(self, trainer: pl.Trainer) -> None: + """Sets up optimizers.""" + super(SingleDeviceStrategy).setup_optimizers(trainer) + if len(self.optimizers) != 1: # type: ignore[has-type] + msg = "XPU strategy doesn't support multiple optimizers" + raise RuntimeError(msg) + model, optimizer = torch.xpu.optimize(trainer.model, optimizer=self.optimizers[0]) # type: ignore[has-type] + self.optimizers = [optimizer] + self.model = model + + # patch instance_data from mmengie + long_type_tensor = Union[torch.LongTensor, torch.xpu.LongTensor] + bool_type_tensor = Union[torch.BoolTensor, torch.xpu.BoolTensor] + instance_data.IndexType = Union[str, slice, int, list, long_type_tensor, bool_type_tensor, np.ndarray] + + # patch nms, roi_align and setup_optimizers for the lightning strategy + global _nms_op_forward, _roi_align_forward, _setup_optimizers + _nms_op_forward = NMSop.forward + _roi_align_forward = RoIAlign.forward + _setup_optimizers = SingleDeviceStrategy.setup_optimizers + NMSop.forward = monkey_patched_nms + RoIAlign.forward = monkey_patched_roi_align + SingleDeviceStrategy.setup_optimizers = patched_setup_optimizers + + +def revert_packages_xpu(): + """Revert packages when xpu is available.""" + NMSop.forward = _nms_op_forward + RoIAlign.forward = _roi_align_forward + SingleDeviceStrategy.setup_optimizers = _setup_optimizers From c1deb52fc409d440b5e3a5a5640b46ffd6cc7288 Mon Sep 17 00:00:00 2001 From: kprokofi Date: Thu, 21 Mar 2024 19:58:24 +0900 Subject: [PATCH 34/42] added auto xpu configuration --- src/otx/algo/strategies/xpu_single.py | 64 +++++++++++++-------------- src/otx/engine/engine.py | 3 ++ src/otx/utils/utils.py | 4 +- 3 files changed, 38 insertions(+), 33 deletions(-) diff --git a/src/otx/algo/strategies/xpu_single.py b/src/otx/algo/strategies/xpu_single.py index 2ab5df6a4e6..d07598f12c4 100644 --- a/src/otx/algo/strategies/xpu_single.py +++ b/src/otx/algo/strategies/xpu_single.py @@ -22,43 +22,43 @@ from lightning_fabric.utilities.types import _DEVICE -# class SingleXPUStrategy(SingleDeviceStrategy): -# """Strategy for training on single XPU device.""" +class SingleXPUStrategy(SingleDeviceStrategy): + """Strategy for training on single XPU device.""" -# strategy_name = "xpu_single" + strategy_name = "xpu_single" -# def __init__( -# self, -# device: _DEVICE = "xpu:0", -# accelerator: pl.accelerators.Accelerator | None = None, -# checkpoint_io: CheckpointIO | None = None, -# precision_plugin: PrecisionPlugin | None = None, -# ): -# if not is_xpu_available(): -# msg = "`SingleXPUStrategy` requires XPU devices to run" -# raise MisconfigurationException(msg) + def __init__( + self, + device: _DEVICE = "xpu:0", + accelerator: pl.accelerators.Accelerator | None = None, + checkpoint_io: CheckpointIO | None = None, + precision_plugin: PrecisionPlugin | None = None, + ): + if not is_xpu_available(): + msg = "`SingleXPUStrategy` requires XPU devices to run" + raise MisconfigurationException(msg) -# super().__init__( -# accelerator=accelerator, -# device=device, -# checkpoint_io=checkpoint_io, -# precision_plugin=precision_plugin, -# ) + super().__init__( + accelerator=accelerator, + device=device, + checkpoint_io=checkpoint_io, + precision_plugin=precision_plugin, + ) -# @property -# def is_distributed(self) -> bool: -# """Returns true if the strategy supports distributed training.""" -# return False + @property + def is_distributed(self) -> bool: + """Returns true if the strategy supports distributed training.""" + return False -# def setup_optimizers(self, trainer: pl.Trainer) -> None: -# """Sets up optimizers.""" -# super().setup_optimizers(trainer) -# if len(self.optimizers) != 1: # type: ignore[has-type] -# msg = "XPU strategy doesn't support multiple optimizers" -# raise RuntimeError(msg) -# model, optimizer = torch.xpu.optimize(trainer.model, optimizer=self.optimizers[0]) # type: ignore[has-type] -# self.optimizers = [optimizer] -# self.model = model + def setup_optimizers(self, trainer: pl.Trainer) -> None: + """Sets up optimizers.""" + super().setup_optimizers(trainer) + if len(self.optimizers) != 1: # type: ignore[has-type] + msg = "XPU strategy doesn't support multiple optimizers" + raise RuntimeError(msg) + model, optimizer = torch.xpu.optimize(trainer.model, optimizer=self.optimizers[0]) # type: ignore[has-type] + self.optimizers = [optimizer] + self.model = model # StrategyRegistry.register( diff --git a/src/otx/engine/engine.py b/src/otx/engine/engine.py index 0e22efabc05..b175abd3a52 100644 --- a/src/otx/engine/engine.py +++ b/src/otx/engine/engine.py @@ -26,6 +26,7 @@ from otx.core.types.precision import OTXPrecisionType from otx.core.types.task import OTXTaskType from otx.core.utils.cache import TrainerArgumentsCache +from otx.utils.utils import is_xpu_available from .hpo import execute_hpo, update_hyper_parameter from .utils.auto_configurator import DEFAULT_CONFIG_PER_TASK, AutoConfigurator @@ -785,6 +786,8 @@ def device(self) -> DeviceConfig: @device.setter def device(self, device: DeviceType) -> None: + if is_xpu_available() and device == DeviceType.auto: + device = DeviceType.xpu self._device = DeviceConfig(accelerator=device) self._cache.update(accelerator=self._device.accelerator, devices=self._device.devices) diff --git a/src/otx/utils/utils.py b/src/otx/utils/utils.py index 7abff15e60e..978d93e88db 100644 --- a/src/otx/utils/utils.py +++ b/src/otx/utils/utils.py @@ -14,7 +14,6 @@ from lightning.pytorch.strategies.single_device import SingleDeviceStrategy from otx.algo.detection.utils import monkey_patched_nms, monkey_patched_roi_align - import torch if TYPE_CHECKING: @@ -173,6 +172,9 @@ def patched_setup_optimizers(self, trainer: pl.Trainer) -> None: def revert_packages_xpu(): + from mmcv.ops.nms import NMSop + from mmcv.ops.roi_align import RoIAlign + from lightning.pytorch.strategies.single_device import SingleDeviceStrategy """Revert packages when xpu is available.""" NMSop.forward = _nms_op_forward RoIAlign.forward = _roi_align_forward From 52e529a743e7987e5c117c425f002f2d51670ff2 Mon Sep 17 00:00:00 2001 From: kprokofi Date: Fri, 22 Mar 2024 00:43:55 +0900 Subject: [PATCH 35/42] patch strategy --- src/otx/algo/accelerators/xpu.py | 11 ++++++----- src/otx/utils/utils.py | 7 ++++++- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/otx/algo/accelerators/xpu.py b/src/otx/algo/accelerators/xpu.py index b3f3faa978f..185fbd3ead2 100644 --- a/src/otx/algo/accelerators/xpu.py +++ b/src/otx/algo/accelerators/xpu.py @@ -10,7 +10,7 @@ from lightning.pytorch.accelerators import AcceleratorRegistry from lightning.pytorch.accelerators.accelerator import Accelerator -from otx.utils.utils import is_xpu_available, patch_packages_xpu +from otx.utils.utils import is_xpu_available, patch_packages_xpu, revert_packages_xpu class XPUAccelerator(Accelerator): @@ -18,13 +18,13 @@ class XPUAccelerator(Accelerator): accelerator_name = "xpu" - def setup_device(self, device: torch.device) -> None: + def setup_device(self) -> None: """Sets up the specified device.""" - if device.type != "xpu": - msg = f"Device should be xpu, got {device} instead" + if not is_xpu_available(): + msg = f"XPU is not available. Please, check the environment." raise RuntimeError(msg) - torch.xpu.set_device(device) + torch.xpu.set_device("xpu:0") patch_packages_xpu() @@ -56,6 +56,7 @@ def get_device_stats(self, device: str | torch.device) -> dict[str, Any]: def teardown(self) -> None: """Cleans-up XPU-related resources.""" + revert_packages_xpu() AcceleratorRegistry.register( diff --git a/src/otx/utils/utils.py b/src/otx/utils/utils.py index 978d93e88db..2cf54b2026d 100644 --- a/src/otx/utils/utils.py +++ b/src/otx/utils/utils.py @@ -145,10 +145,15 @@ def is_xpu_available() -> bool: def patch_packages_xpu(task: str | OTXTaskType, accelerator: str | DeviceType) -> None: """Patch packages when xpu is available.""" import lightning.pytorch as pl + from lightning.pytorch.trainer.states import TrainerFn + from lightning.pytorch.core.optimizer import _init_optimizers_and_lr_schedulers def patched_setup_optimizers(self, trainer: pl.Trainer) -> None: """Sets up optimizers.""" - super(SingleDeviceStrategy).setup_optimizers(trainer) + if trainer.state.fn != TrainerFn.FITTING: + return + assert self.lightning_module is not None + self.optimizers, self.lr_scheduler_configs = _init_optimizers_and_lr_schedulers(self.lightning_module) if len(self.optimizers) != 1: # type: ignore[has-type] msg = "XPU strategy doesn't support multiple optimizers" raise RuntimeError(msg) From 8892171af02012fe11856c9d09fe2962705279ca Mon Sep 17 00:00:00 2001 From: kprokofi Date: Fri, 22 Mar 2024 00:46:59 +0900 Subject: [PATCH 36/42] small fix --- src/otx/utils/utils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/otx/utils/utils.py b/src/otx/utils/utils.py index 2cf54b2026d..064ac500537 100644 --- a/src/otx/utils/utils.py +++ b/src/otx/utils/utils.py @@ -142,7 +142,7 @@ def is_xpu_available() -> bool: return XPU_AVAILABLE -def patch_packages_xpu(task: str | OTXTaskType, accelerator: str | DeviceType) -> None: +def patch_packages_xpu() -> None: """Patch packages when xpu is available.""" import lightning.pytorch as pl from lightning.pytorch.trainer.states import TrainerFn @@ -181,6 +181,7 @@ def revert_packages_xpu(): from mmcv.ops.roi_align import RoIAlign from lightning.pytorch.strategies.single_device import SingleDeviceStrategy """Revert packages when xpu is available.""" + global _nms_op_forward, _roi_align_forward, _setup_optimizers NMSop.forward = _nms_op_forward RoIAlign.forward = _roi_align_forward SingleDeviceStrategy.setup_optimizers = _setup_optimizers From 24895815667f05eb824256230c2bf62a0c4f5581 Mon Sep 17 00:00:00 2001 From: kprokofi Date: Fri, 22 Mar 2024 00:58:36 +0900 Subject: [PATCH 37/42] reply to comments --- src/otx/algo/accelerators/xpu.py | 8 ++++---- src/otx/algo/strategies/xpu_single.py | 10 +++++----- src/otx/engine/engine.py | 1 + src/otx/utils/utils.py | 28 ++------------------------- 4 files changed, 12 insertions(+), 35 deletions(-) diff --git a/src/otx/algo/accelerators/xpu.py b/src/otx/algo/accelerators/xpu.py index 185fbd3ead2..979daed4ec1 100644 --- a/src/otx/algo/accelerators/xpu.py +++ b/src/otx/algo/accelerators/xpu.py @@ -18,13 +18,13 @@ class XPUAccelerator(Accelerator): accelerator_name = "xpu" - def setup_device(self) -> None: + def setup_device(self, device: torch.device) -> None: """Sets up the specified device.""" - if not is_xpu_available(): - msg = f"XPU is not available. Please, check the environment." + if device.type != "xpu": + msg = f"Device should be xpu, got {device} instead" raise RuntimeError(msg) - torch.xpu.set_device("xpu:0") + torch.xpu.set_device(device) patch_packages_xpu() diff --git a/src/otx/algo/strategies/xpu_single.py b/src/otx/algo/strategies/xpu_single.py index d07598f12c4..808f7e27bf3 100644 --- a/src/otx/algo/strategies/xpu_single.py +++ b/src/otx/algo/strategies/xpu_single.py @@ -61,8 +61,8 @@ def setup_optimizers(self, trainer: pl.Trainer) -> None: self.model = model -# StrategyRegistry.register( -# SingleXPUStrategy.strategy_name, -# SingleXPUStrategy, -# description="Strategy that enables training on single XPU", -# ) +StrategyRegistry.register( + SingleXPUStrategy.strategy_name, + SingleXPUStrategy, + description="Strategy that enables training on single XPU", +) diff --git a/src/otx/engine/engine.py b/src/otx/engine/engine.py index b175abd3a52..772c0f9ee4e 100644 --- a/src/otx/engine/engine.py +++ b/src/otx/engine/engine.py @@ -811,6 +811,7 @@ def _build_trainer(self, **kwargs) -> None: self._cache.update(**kwargs) # set up xpu device if self._device.accelerator == DeviceType.xpu: + self._cache.update(strategy="xpu_single") # add plugin for Automatic Mixed Precision on XPU if self._cache.args["precision"] == 16: self._cache.update(plugins=[MixedPrecisionXPUPlugin()]) diff --git a/src/otx/utils/utils.py b/src/otx/utils/utils.py index 064ac500537..129c3bdef1c 100644 --- a/src/otx/utils/utils.py +++ b/src/otx/utils/utils.py @@ -144,44 +144,20 @@ def is_xpu_available() -> bool: def patch_packages_xpu() -> None: """Patch packages when xpu is available.""" - import lightning.pytorch as pl - from lightning.pytorch.trainer.states import TrainerFn - from lightning.pytorch.core.optimizer import _init_optimizers_and_lr_schedulers - - def patched_setup_optimizers(self, trainer: pl.Trainer) -> None: - """Sets up optimizers.""" - if trainer.state.fn != TrainerFn.FITTING: - return - assert self.lightning_module is not None - self.optimizers, self.lr_scheduler_configs = _init_optimizers_and_lr_schedulers(self.lightning_module) - if len(self.optimizers) != 1: # type: ignore[has-type] - msg = "XPU strategy doesn't support multiple optimizers" - raise RuntimeError(msg) - model, optimizer = torch.xpu.optimize(trainer.model, optimizer=self.optimizers[0]) # type: ignore[has-type] - self.optimizers = [optimizer] - self.model = model - # patch instance_data from mmengie long_type_tensor = Union[torch.LongTensor, torch.xpu.LongTensor] bool_type_tensor = Union[torch.BoolTensor, torch.xpu.BoolTensor] instance_data.IndexType = Union[str, slice, int, list, long_type_tensor, bool_type_tensor, np.ndarray] - # patch nms, roi_align and setup_optimizers for the lightning strategy - global _nms_op_forward, _roi_align_forward, _setup_optimizers + # patch nms and roi_align + global _nms_op_forward, _roi_align_forward _nms_op_forward = NMSop.forward _roi_align_forward = RoIAlign.forward - _setup_optimizers = SingleDeviceStrategy.setup_optimizers NMSop.forward = monkey_patched_nms RoIAlign.forward = monkey_patched_roi_align - SingleDeviceStrategy.setup_optimizers = patched_setup_optimizers def revert_packages_xpu(): - from mmcv.ops.nms import NMSop - from mmcv.ops.roi_align import RoIAlign - from lightning.pytorch.strategies.single_device import SingleDeviceStrategy """Revert packages when xpu is available.""" - global _nms_op_forward, _roi_align_forward, _setup_optimizers NMSop.forward = _nms_op_forward RoIAlign.forward = _roi_align_forward - SingleDeviceStrategy.setup_optimizers = _setup_optimizers From 8fb52df736f8c03245d64994bbadd54debab8007 Mon Sep 17 00:00:00 2001 From: kprokofi Date: Fri, 22 Mar 2024 01:14:50 +0900 Subject: [PATCH 38/42] move patching xpu packages to accelerator --- src/otx/algo/accelerators/xpu.py | 32 +++++++++++++++++++++++++----- src/otx/utils/utils.py | 34 ++------------------------------ 2 files changed, 29 insertions(+), 37 deletions(-) diff --git a/src/otx/algo/accelerators/xpu.py b/src/otx/algo/accelerators/xpu.py index 979daed4ec1..f5969336ab4 100644 --- a/src/otx/algo/accelerators/xpu.py +++ b/src/otx/algo/accelerators/xpu.py @@ -4,13 +4,18 @@ # from __future__ import annotations -from typing import Any +from typing import Any, Union +import numpy as np import torch from lightning.pytorch.accelerators import AcceleratorRegistry from lightning.pytorch.accelerators.accelerator import Accelerator +from mmcv.ops.nms import NMSop +from mmcv.ops.roi_align import RoIAlign +from mmengine.structures import instance_data -from otx.utils.utils import is_xpu_available, patch_packages_xpu, revert_packages_xpu +from otx.algo.detection.utils import monkey_patched_nms, monkey_patched_roi_align +from otx.utils.utils import is_xpu_available class XPUAccelerator(Accelerator): @@ -25,8 +30,7 @@ def setup_device(self, device: torch.device) -> None: raise RuntimeError(msg) torch.xpu.set_device(device) - patch_packages_xpu() - + self.patch_packages_xpu() @staticmethod def parse_devices(devices: str | list | torch.device) -> list: @@ -56,7 +60,25 @@ def get_device_stats(self, device: str | torch.device) -> dict[str, Any]: def teardown(self) -> None: """Cleans-up XPU-related resources.""" - revert_packages_xpu() + self.revert_packages_xpu() + + def patch_packages_xpu(self) -> None: + """Patch packages when xpu is available.""" + # patch instance_data from mmengie + long_type_tensor = Union[torch.LongTensor, torch.xpu.LongTensor] + bool_type_tensor = Union[torch.BoolTensor, torch.xpu.BoolTensor] + instance_data.IndexType = Union[str, slice, int, list, long_type_tensor, bool_type_tensor, np.ndarray] + + # patch nms and roi_align + self._nms_op_forward = NMSop.forward + self._roi_align_forward = RoIAlign.forward + NMSop.forward = monkey_patched_nms + RoIAlign.forward = monkey_patched_roi_align + + def revert_packages_xpu(self) -> None: + """Revert packages when xpu is available.""" + NMSop.forward = self._nms_op_forward + RoIAlign.forward = self._roi_align_forward AcceleratorRegistry.register( diff --git a/src/otx/utils/utils.py b/src/otx/utils/utils.py index 129c3bdef1c..797274aa634 100644 --- a/src/otx/utils/utils.py +++ b/src/otx/utils/utils.py @@ -6,22 +6,13 @@ from __future__ import annotations from decimal import Decimal -from typing import TYPE_CHECKING, Any, Union -import numpy as np -from mmcv.ops.nms import NMSop -from mmcv.ops.roi_align import RoIAlign -from mmengine.structures import instance_data -from lightning.pytorch.strategies.single_device import SingleDeviceStrategy - -from otx.algo.detection.utils import monkey_patched_nms, monkey_patched_roi_align +from typing import TYPE_CHECKING, Any + import torch if TYPE_CHECKING: from pathlib import Path - from otx.core.types.device import DeviceType - from otx.core.types.task import OTXTaskType - XPU_AVAILABLE = None try: @@ -140,24 +131,3 @@ def is_xpu_available() -> bool: if XPU_AVAILABLE is None: XPU_AVAILABLE = hasattr(torch, "xpu") and torch.xpu.is_available() return XPU_AVAILABLE - - -def patch_packages_xpu() -> None: - """Patch packages when xpu is available.""" - # patch instance_data from mmengie - long_type_tensor = Union[torch.LongTensor, torch.xpu.LongTensor] - bool_type_tensor = Union[torch.BoolTensor, torch.xpu.BoolTensor] - instance_data.IndexType = Union[str, slice, int, list, long_type_tensor, bool_type_tensor, np.ndarray] - - # patch nms and roi_align - global _nms_op_forward, _roi_align_forward - _nms_op_forward = NMSop.forward - _roi_align_forward = RoIAlign.forward - NMSop.forward = monkey_patched_nms - RoIAlign.forward = monkey_patched_roi_align - - -def revert_packages_xpu(): - """Revert packages when xpu is available.""" - NMSop.forward = _nms_op_forward - RoIAlign.forward = _roi_align_forward From d3b9a6d357a727e0e35f7bfa1e712a8e37f28ee8 Mon Sep 17 00:00:00 2001 From: kprokofi Date: Fri, 22 Mar 2024 01:41:34 +0900 Subject: [PATCH 39/42] fix test_xpu test --- tests/unit/algo/accelerators/test_xpu.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/unit/algo/accelerators/test_xpu.py b/tests/unit/algo/accelerators/test_xpu.py index 28bde8e5976..793bbe18331 100644 --- a/tests/unit/algo/accelerators/test_xpu.py +++ b/tests/unit/algo/accelerators/test_xpu.py @@ -14,6 +14,8 @@ class TestXPUAccelerator: @pytest.fixture() def accelerator(self, mocker): mock_torch = mocker.patch("otx.algo.accelerators.xpu.torch") + mocker.patch.object(XPUAccelerator, "patch_packages_xpu") + mocker.patch.object(XPUAccelerator, "teardown") return XPUAccelerator(), mock_torch def test_setup_device(self, accelerator): From f99f022516f3c187e616b8aa081fd18d3fdedf6f Mon Sep 17 00:00:00 2001 From: kprokofi Date: Fri, 22 Mar 2024 02:11:48 +0900 Subject: [PATCH 40/42] remove do-not-install-mmcv --- docs/source/guide/get_started/installation.rst | 4 ++-- src/otx/cli/install.py | 11 +++-------- tests/unit/cli/test_install.py | 2 +- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/docs/source/guide/get_started/installation.rst b/docs/source/guide/get_started/installation.rst index 3b80cbfc0c8..bb8f6c72c61 100644 --- a/docs/source/guide/get_started/installation.rst +++ b/docs/source/guide/get_started/installation.rst @@ -97,11 +97,11 @@ package from either: pip install otx 5. Install requirements for training -excluding Pytorch and MMCV. +excluding Pytorch. .. code-block:: shell - otx install -v --do-not-install-torch --do-not-install-mmcv + otx install -v --do-not-install-torch 6. Activate OneAPI environment and export required IPEX system variables diff --git a/src/otx/cli/install.py b/src/otx/cli/install.py index f1a37fd7c1e..43dcb3df8a7 100644 --- a/src/otx/cli/install.py +++ b/src/otx/cli/install.py @@ -64,19 +64,14 @@ def add_install_parser(subcommands_action: _ActionSubCommands) -> None: help="Do not install PyTorch. Choose this option if you already install PyTorch.", action="store_true", ) - parser.add_argument( - "--do-not-install-mmcv", - help="Do not install mmcv. Choose this option if you already install specific version of mmcv.", - action="store_true", - ) + subcommands_action.add_subcommand("install", parser, help="Install OTX requirements.") def otx_install( option: str | None = None, verbose: bool = False, - do_not_install_torch: bool = False, - do_not_install_mmcv: bool = False, + do_not_install_torch: bool = False ) -> int: """Install OTX requirements. @@ -119,7 +114,7 @@ def otx_install( # Parse mmX requirements if the task requires mmX packages. mmcv_install_args = [] - if mmcv_requirements and not do_not_install_mmcv: + if mmcv_requirements: mmcv_install_args = get_mmcv_install_args(torch_requirement, mmcv_requirements) install_args += ["openmim"] diff --git a/tests/unit/cli/test_install.py b/tests/unit/cli/test_install.py index 51464e8b43d..a55c587a8a9 100644 --- a/tests/unit/cli/test_install.py +++ b/tests/unit/cli/test_install.py @@ -28,7 +28,7 @@ def test_add_install_parser(self) -> None: assert parser_subcommands.choices.get("install") is not None install_parser = parser_subcommands.choices.get("install") argument_list = [action.dest for action in install_parser._actions] - expected_argument = ["help", "option", "verbose", "do_not_install_torch", "do_not_install_mmcv"] + expected_argument = ["help", "option", "verbose", "do_not_install_torch"] assert argument_list == expected_argument def test_install_extra(self, mocker: MockerFixture) -> None: From a368e9e106f964ce3f4afcce8675f29607a55f87 Mon Sep 17 00:00:00 2001 From: kprokofi Date: Fri, 22 Mar 2024 06:29:59 +0900 Subject: [PATCH 41/42] fix pre-commit --- src/otx/cli/install.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/otx/cli/install.py b/src/otx/cli/install.py index 43dcb3df8a7..c67229d4ca5 100644 --- a/src/otx/cli/install.py +++ b/src/otx/cli/install.py @@ -71,7 +71,7 @@ def add_install_parser(subcommands_action: _ActionSubCommands) -> None: def otx_install( option: str | None = None, verbose: bool = False, - do_not_install_torch: bool = False + do_not_install_torch: bool = False, ) -> int: """Install OTX requirements. From 98e0b69e2903fa1d4ce799c1ee5480416f52b0ee Mon Sep 17 00:00:00 2001 From: kprokofi Date: Fri, 22 Mar 2024 08:11:58 +0900 Subject: [PATCH 42/42] remove torch.xpu.optimize for segmentation --- src/otx/algo/strategies/xpu_single.py | 7 ++++--- src/otx/engine/engine.py | 1 + tests/unit/algo/strategies/test_strategies.py | 1 + 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/otx/algo/strategies/xpu_single.py b/src/otx/algo/strategies/xpu_single.py index 808f7e27bf3..aa1ecf3d559 100644 --- a/src/otx/algo/strategies/xpu_single.py +++ b/src/otx/algo/strategies/xpu_single.py @@ -56,9 +56,10 @@ def setup_optimizers(self, trainer: pl.Trainer) -> None: if len(self.optimizers) != 1: # type: ignore[has-type] msg = "XPU strategy doesn't support multiple optimizers" raise RuntimeError(msg) - model, optimizer = torch.xpu.optimize(trainer.model, optimizer=self.optimizers[0]) # type: ignore[has-type] - self.optimizers = [optimizer] - self.model = model + if trainer.task != "SEMANTIC_SEGMENTATION": + model, optimizer = torch.xpu.optimize(trainer.model, optimizer=self.optimizers[0]) # type: ignore[has-type] + self.optimizers = [optimizer] + self.model = model StrategyRegistry.register( diff --git a/src/otx/engine/engine.py b/src/otx/engine/engine.py index 772c0f9ee4e..edd03472562 100644 --- a/src/otx/engine/engine.py +++ b/src/otx/engine/engine.py @@ -819,6 +819,7 @@ def _build_trainer(self, **kwargs) -> None: kwargs = self._cache.args self._trainer = Trainer(**kwargs) + self._trainer.task = self.task self.work_dir = self._trainer.default_root_dir @property diff --git a/tests/unit/algo/strategies/test_strategies.py b/tests/unit/algo/strategies/test_strategies.py index 8d76bb7d76c..1e7ddfb1809 100644 --- a/tests/unit/algo/strategies/test_strategies.py +++ b/tests/unit/algo/strategies/test_strategies.py @@ -42,6 +42,7 @@ def test_setup_optimizers(self, strategy, mocker): return_value=(mocker.MagicMock(), mocker.MagicMock()), ) trainer = pl.Trainer() + trainer.task = "CLASSIFICATION" # Create mock optimizers and models for testing model = torch.nn.Linear(10, 2) strategy._optimizers = [torch.optim.Adam(model.parameters(), lr=0.001)]