Skip to content

Commit 7027132

Browse files
sovrasovnikita-savelyevvjaegukhyun
authored
Update OV / NNCF/ ModelAPI / Datumaro (#2090)
* Update ov to a pre-release version * Update OV to 2023 release * dummy fix for unit tests * Update * Apply a workaround for OV 23 bug * Fix getting rt info * Tmp update of NNCF * Changes for supporting NNCF 2.5 (WIP) * Add new model api to reqs * Integration for classification * Update model contaner * Fix OTX segm wrapper * Fix linter * Update detection inference * Fix MRCNN inference * Fix tiling inference * Fix cls unit tests * Fix detection unit tests * Fix semantic segmentation UT * Fix datumaro tests * Ugrade mapi in action and anomaly * Update exp code commit ver * Add raw scores to cls config * Revert changes in graph parsing test * Fix model creation in modelAdapter * Fix metadata shape in ModelAdapter * Fix tile classifier config * Update exportable code reqs * Fix model container * Del unused import * Update NNCF to release version * Xfail movinet inference * Updatemapi * Update exportable code commit * Fix act test xfail * Fix tiling inference Fix tiling inference * Fix imports * Fix exports in unit tests * Fix tiling test * Swithc classification to PTQ * Extract quantization check * Move transform to dataset * Switch to ptq in segmentation * Fix mypy * Fix ptq naming * Switch to PTQ in action task * Fix cls optimize test * Fix segmentation ptq test * Fix action tests * PTQ for detection task * Use ignored_scope in segm pqt * Extract OV data loader to a standalone class * PTQ for anomaly * Shuffler for action PTQ dataset * Fix det unit tests * Del unused import * Update exportable code deps * Fix exportable code tiling * Update exportable code reqs * Fix tiling in exportable code * Use py configs for PTQ segmentation * Add py style PTQ configs * Del outdated pot segm configs * Update ptq configs for anomaly * Fix cls explain inference * Fix activation cls wrapper * PArtially fix OMZ plugin * Fix opset version collisions * Partially fix nncf ckpt * Fix MRCNN wrapper * Fix softmax opset ver * Update changelog * Update exportable code reqs * Update ov related imports * Update fq num refs for semantic segmentation * Update fq refs for classification * Add update mode for FQ refs * Update fq refs for detection * Xfaail e2e for movinet * Update sses fqs pt2 * Upgrade nncf anomalib integration * Upgrade nncf weights loading workaround in anomaly task * Update FQ refs for anomaly * Bypass PTQ for tile classifier * Update IS FQ refs * Update detection FQ refs * Fix tiling classifier PTQ bypass * Minor updates in tests * Fix ruff * Fix tile classifier PTQ bypass condition * Fix a typo * Update det ut * Update fq refs for tiling iseg * Fix tiling inference configuration * Fix readme * Update datumaro commit * Update datumaro commit * Update masks postprocessing in OV wrapper * Update mrcnn unit tests * Fix yolox inference config * Update docs for NNCF state dict hooks * Fix comments formatting * Skip action det ov e2e tests * Update IS tests skips * Skip some of SS PTQ tests * Fix a type in skip comment * Fix data pipeline for tiling yolox * Revert ss PTQ->POT * Re-enable POT tests for sseg * Fix ptq config managing * Fix black * Update refs to PTQ configs in docs * Update FQs refs for anomaly * Update FQ refs for SS models --------- Co-authored-by: Nikita Savelyev <[email protected]> Co-authored-by: Jaeguk Hyun <[email protected]>
1 parent bad2081 commit 7027132

File tree

115 files changed

+1166
-1210
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

115 files changed

+1166
-1210
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ All notable changes to this project will be documented in this file.
2121
- Set persistent_workers and pin_memory as True in detection task (<https://github.com/openvinotoolkit/training_extensions/pull/2224>)
2222
- New algorithm for Semi-SL semantic segmentation based on metric lerning via class prototypes (https://github.com/openvinotoolkit/training_extensions/pull/2156)
2323
- Self-SL for classification now can recieve just folder with any images to start contrastive pretraining (https://github.com/openvinotoolkit/training_extensions/pull/2219)
24+
- Update OpenVINO version to 2023.0, and NNCF verion to 2.5 (<https://github.com/openvinotoolkit/training_extensions/pull/2090>)
2425
- Improve XAI saliency map generation for tiling detection and tiling instance segmentation (https://github.com/openvinotoolkit/training_extensions/pull/2240)
2526

2627
### Bug fixes
@@ -30,7 +31,7 @@ All notable changes to this project will be documented in this file.
3031

3132
### Known issues
3233

33-
- OpenVINO(==2022.3) IR inference is not working well on 2-stage models (e.g. Mask-RCNN) exported from torch==1.13.1
34+
- OpenVINO(==2023.0) IR inference is not working well on 2-stage models (e.g. Mask-RCNN) exported from torch==1.13.1
3435

3536
## \[v1.3.1\]
3637

docs/source/guide/explanation/additional_features/models_optimization.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ Models Optimization
44
OpenVINO™ Training Extensions provides two types of optimization algorithms: `Post-training Optimization Tool (POT) <https://docs.openvino.ai/latest/pot_introduction.html#doxid-pot-introduction>`_ and `Neural Network Compression Framework (NNCF) <https://github.com/openvinotoolkit/nncf>`_.
55

66
*******************************
7-
Post-training Optimization Tool
7+
Post-training Optimization Tool
88
*******************************
99

1010
POT is designed to optimize the inference of models by applying post-training methods that do not require model retraining or fine-tuning. If you want to know more details about how POT works and to be more familiar with model optimization methods, please refer to `documentation <https://docs.openvino.ai/latest/pot_introduction.html#doxid-pot-introduction>`_.
1111

1212
To run Post-training optimization it is required to convert the model to OpenVINO™ intermediate representation (IR) first. To perform fast and accurate quantization we use ``DefaultQuantization Algorithm`` for each task. Please, see the `DefaultQuantization Parameters <https://docs.openvino.ai/latest/pot_compression_algorithms_quantization_default_README.html#doxid-pot-compression-algorithms-quantization-default-r-e-a-d-m-e>`_ for further information about configuring the optimization.
1313

14-
POT parameters can be found and configured in ``template.yaml`` and ``configuration.yaml`` for each task. For Anomaly and Semantic Segmentation tasks, we have separate configuration files for POT, that can be found in the same directory with ``template.yaml``, for example for `PaDiM <https://github.com/openvinotoolkit/training_extensions/blob/develop/src/otx/algorithms/anomaly/configs/classification/padim/pot_optimization_config.json>`_, `OCR-Lite-HRNe-18-mod2 <https://github.com/openvinotoolkit/training_extensions/blob/develop/src/otx/algorithms/segmentation/configs/ocr_lite_hrnet_18_mod2/pot_optimization_config.json>`_ model.
14+
POT parameters can be found and configured in ``template.yaml`` and ``configuration.yaml`` for each task. For Anomaly and Semantic Segmentation tasks, we have separate configuration files for POT, that can be found in the same directory with ``template.yaml``, for example for `PaDiM <https://github.com/openvinotoolkit/training_extensions/blob/develop/src/otx/algorithms/anomaly/configs/classification/padim/ptq_optimization_config.py>`_, `OCR-Lite-HRNe-18-mod2 <https://github.com/openvinotoolkit/training_extensions/blob/develop/src/otx/algorithms/segmentation/configs/ocr_lite_hrnet_18_mod2/ptq_optimization_config.py>`_ model.
1515

1616
************************************
1717
Neural Network Compression Framework
@@ -23,8 +23,8 @@ The process of optimization is controlled by the NNCF configuration file. A JSON
2323
You can refer to configuration files for default templates for each task accordingly: `Classification <https://github.com/openvinotoolkit/training_extensions/blob/develop/src/otx/algorithms/classification/configs/efficientnet_b0_cls_incr/compression_config.json>`_, `Object Detection <https://github.com/openvinotoolkit/training_extensions/blob/develop/src/otx/algorithms/detection/configs/detection/mobilenetv2_atss/compression_config.json>`_, `Semantic segmentation <https://github.com/openvinotoolkit/training_extensions/blob/develop/src/otx/algorithms/segmentation/configs/ocr_lite_hrnet_18_mod2/compression_config.json>`_, `Instance segmentation <https://github.com/openvinotoolkit/training_extensions/blob/develop/src/otx/algorithms/detection/configs/instance_segmentation/efficientnetb2b_maskrcnn/compression_config.json>`_, `Anomaly classification <https://github.com/openvinotoolkit/training_extensions/blob/develop/src/otx/algorithms/anomaly/configs/classification/padim/compression_config.json>`_, `Anomaly Detection <https://github.com/openvinotoolkit/training_extensions/blob/develop/src/otx/algorithms/anomaly/configs/detection/padim/compression_config.json>`_, `Anomaly segmentation <https://github.com/openvinotoolkit/training_extensions/blob/develop/src/otx/algorithms/anomaly/configs/segmentation/padim/compression_config.json>`_. Configs for other templates can be found in the same directory.
2424

2525

26-
NNCF tends to provide better quality in terms of preserving accuracy as it uses training compression approaches.
27-
Compression results achievable with the NNCF can be found `here <https://github.com/openvinotoolkit/nncf#nncf-compressed-model-zoo>`_ .
26+
NNCF tends to provide better quality in terms of preserving accuracy as it uses training compression approaches.
27+
Compression results achievable with the NNCF can be found `here <https://github.com/openvinotoolkit/nncf#nncf-compressed-model-zoo>`_ .
2828
Meanwhile, the POT is faster but can degrade accuracy more than the training-enabled approach.
2929

3030
.. note::

requirements/base.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ natsort>=6.0.0
44
prettytable
55
protobuf>=3.20.0
66
pyyaml
7-
datumaro==1.3.2
7+
datumaro@ git+https://github.com/openvinotoolkit/datumaro@3e77b3138d063db68a4efba3c03a6bac7df086b1#egg=datumaro
88
psutil
99
scipy>=1.8
1010
bayesian-optimization>=1.2.0

requirements/openvino.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
22
# OpenVINO Requirements. #
3-
nncf==2.4.0
3+
nncf==2.5.0
44
onnx==1.13.0
5-
openmodelzoo-modelapi==2022.3.0
6-
openvino==2022.3.0
7-
openvino-dev==2022.3.0
5+
openvino-model-api==0.1.2
6+
openvino==2023.0
7+
openvino-dev==2023.0
88
openvino-telemetry>=2022.1.0

src/otx/algorithms/action/adapters/openvino/dataloader.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,12 @@
1818
from typing import Dict, List
1919

2020
import numpy as np
21-
from compression.api import DataLoader
2221

2322
from otx.api.entities.annotation import AnnotationSceneEntity
2423
from otx.api.entities.datasets import DatasetEntity, DatasetItemEntity
2524

2625

27-
def get_ovdataloader(dataset: DatasetEntity, task_type: str, clip_len: int, width: int, height: int) -> DataLoader:
26+
def get_ovdataloader(dataset: DatasetEntity, task_type: str, clip_len: int, width: int, height: int):
2827
"""Find proper dataloader for dataset and task type.
2928
3029
If dataset has only a single video, this returns DataLoader for online demo
@@ -49,7 +48,7 @@ def _is_multi_video(dataset: DatasetEntity) -> bool:
4948
return False
5049

5150

52-
class ActionOVDemoDataLoader(DataLoader):
51+
class ActionOVDemoDataLoader:
5352
"""DataLoader for online demo purpose.
5453
5554
Since it is for online demo purpose it selects background frames from neighbor of key frame
@@ -91,7 +90,7 @@ def add_prediction(self, data: List[DatasetItemEntity], prediction: AnnotationSc
9190
dataset_item.append_annotations(prediction.annotations)
9291

9392

94-
class ActionOVClsDataLoader(DataLoader):
93+
class ActionOVClsDataLoader:
9594
"""DataLoader for evaluation of action classification models.
9695
9796
It iterates through clustered video, and it samples frames from given video
@@ -151,7 +150,7 @@ def add_prediction(self, dataset: DatasetEntity, data: List[DatasetItemEntity],
151150
dataset_item.append_labels(prediction.annotations[0].get_labels())
152151

153152

154-
class ActionOVDetDataLoader(DataLoader):
153+
class ActionOVDetDataLoader:
155154
"""DataLoader for evaluation of spatio-temporal action detection models.
156155
157156
It iterates through DatasetEntity, which only contains non-empty frame(frame with actor annotation)

src/otx/algorithms/action/adapters/openvino/model_wrappers/openvino_models.py

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,22 +19,16 @@
1919
from typing import Any, Dict, List
2020

2121
import numpy as np
22+
from openvino.model_api.adapters import OpenvinoAdapter
23+
from openvino.model_api.models.model import Model
24+
from openvino.model_api.models.utils import (
25+
RESIZE_TYPES,
26+
Detection,
27+
InputTransform,
28+
)
2229

2330
from otx.api.entities.datasets import DatasetItemEntity
2431

25-
try:
26-
from openvino.model_zoo.model_api.adapters import OpenvinoAdapter
27-
from openvino.model_zoo.model_api.models.model import Model
28-
from openvino.model_zoo.model_api.models.utils import (
29-
RESIZE_TYPES,
30-
Detection,
31-
InputTransform,
32-
)
33-
except ImportError as e:
34-
import warnings
35-
36-
warnings.warn(f"{e}, ModelAPI was not found.")
37-
3832

3933
def softmax_numpy(x: np.ndarray):
4034
"""Softmax numpy."""

src/otx/algorithms/action/adapters/openvino/task.py

Lines changed: 36 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -18,25 +18,26 @@
1818
import json
1919
import logging
2020
import os
21+
import random
2122
import tempfile
2223
from typing import Any, Dict, List, Optional, Tuple, Union
2324
from zipfile import ZipFile
2425

26+
import nncf
2527
import numpy as np
26-
from addict import Dict as ADDict
27-
from compression.api import DataLoader
28-
from compression.engines.ie_engine import IEEngine
29-
from compression.graph import load_model, save_model
30-
from compression.graph.model_utils import compress_model_weights, get_nodes_by_type
31-
from compression.pipeline.initializer import create_pipeline
28+
import openvino.runtime as ov
3229
from mmcv.utils import ProgressBar
30+
from nncf.common.quantization.structs import QuantizationPreset
31+
from openvino.model_api.adapters import OpenvinoAdapter, create_core
32+
from openvino.model_api.models import Model
3333

3434
from otx.algorithms.action.adapters.openvino import (
3535
ActionOVClsDataLoader,
3636
get_ovdataloader,
3737
model_wrappers,
3838
)
3939
from otx.algorithms.action.configs.base import ActionConfig
40+
from otx.algorithms.common.utils.ir import check_if_quantized
4041
from otx.api.entities.annotation import AnnotationSceneEntity
4142
from otx.api.entities.datasets import DatasetEntity, DatasetItemEntity
4243
from otx.api.entities.inference_parameters import (
@@ -53,6 +54,7 @@
5354
)
5455
from otx.api.entities.optimization_parameters import OptimizationParameters
5556
from otx.api.entities.resultset import ResultSetEntity
57+
from otx.api.entities.subset import Subset
5658
from otx.api.entities.task_environment import TaskEnvironment
5759
from otx.api.serialization.label_mapper import LabelSchemaMapper, label_schema_to_bytes
5860
from otx.api.usecases.evaluation.metrics_helper import MetricsHelper
@@ -71,14 +73,6 @@
7173
OptimizationType,
7274
)
7375

74-
try:
75-
from openvino.model_zoo.model_api.adapters import OpenvinoAdapter, create_core
76-
from openvino.model_zoo.model_api.models import Model
77-
except ImportError:
78-
import warnings
79-
80-
warnings.warn("ModelAPI was not found.")
81-
8276
logger = logging.getLogger(__name__)
8377

8478

@@ -115,7 +109,7 @@ def __init__(
115109
create_core(), model_file, weight_file, device=device, max_num_requests=num_requests
116110
)
117111
self.configuration: Dict[Any, Any] = {}
118-
self.model = Model.create_model(self.task_type, model_adapter, self.configuration, preload=True)
112+
self.model = Model.create_model(model_adapter, self.task_type, self.configuration, preload=True)
119113
self.converter: IPredictionToAnnotationConverter
120114
if self.task_type == "ACTION_CLASSIFICATION":
121115
self.converter = ClassificationToAnnotationConverter(self.label_schema)
@@ -147,20 +141,26 @@ def forward(self, image: Dict[str, np.ndarray]) -> Dict[str, np.ndarray]:
147141
return self.model.infer_sync(image)
148142

149143

150-
class DataLoaderWrapper(DataLoader):
144+
class DataLoaderWrapper:
151145
"""DataLoader implementation for ActionOpenVINOTask."""
152146

153-
def __init__(self, dataloader: DataLoader, inferencer: BaseInferencer):
154-
super().__init__(config=None)
147+
def __init__(self, dataloader: Any, inferencer: BaseInferencer, shuffle: bool = True):
155148
self.dataloader = dataloader
156149
self.inferencer = inferencer
150+
self.shuffler = None
151+
if shuffle:
152+
self.shuffler = list(range(len(dataloader)))
153+
random.shuffle(self.shuffler)
157154

158155
def __getitem__(self, index: int):
159156
"""Get item from dataset."""
157+
if self.shuffler is not None:
158+
index = self.shuffler[index]
159+
160160
item = self.dataloader[index]
161161
annotation = item[len(item) // 2].annotation_scene
162-
inputs, metadata = self.inferencer.pre_process(item)
163-
return (index, annotation), inputs, metadata
162+
inputs, _ = self.inferencer.pre_process(item)
163+
return inputs, annotation
164164

165165
def __len__(self):
166166
"""Get length of dataset."""
@@ -272,13 +272,15 @@ def optimize(
272272
"""Optimize function of OpenVINOTask."""
273273

274274
if optimization_type is not OptimizationType.POT:
275-
raise ValueError("POT is the only supported optimization type for OpenVino models")
275+
raise ValueError("PTQ is the only supported optimization type for OpenVino models")
276276

277277
clip_len = self.inferencer.model.t
278278
width = self.inferencer.model.w
279279
height = self.inferencer.model.h
280+
dataset = dataset.get_subset(Subset.TRAINING)
280281
data_loader = get_ovdataloader(dataset, self.task_type, clip_len, width, height)
281282
data_loader = DataLoaderWrapper(data_loader, self.inferencer)
283+
quantization_dataset = nncf.Dataset(data_loader, lambda data: data[0])
282284

283285
if self.model is None:
284286
raise RuntimeError("optimize failed, model is None")
@@ -291,47 +293,30 @@ def optimize(
291293
with open(bin_path, "wb") as f:
292294
f.write(self.model.get_data("openvino.bin"))
293295

294-
model_config = ADDict({"model_name": "openvino_model", "model": xml_path, "weights": bin_path})
295-
296-
model = load_model(model_config)
297-
298-
if get_nodes_by_type(model, ["FakeQuantize"]):
299-
raise RuntimeError("Model is already optimized by POT")
296+
ov_model = ov.Core().read_model(xml_path)
297+
if check_if_quantized(ov_model):
298+
raise RuntimeError("Model is already optimized by PTQ")
300299

301300
if optimization_parameters is not None:
302301
optimization_parameters.update_progress(10, None)
303302

304-
engine_config = ADDict({"device": "CPU"})
305-
306303
stat_subset_size = self.hparams.pot_parameters.stat_subset_size
307-
preset = self.hparams.pot_parameters.preset.name.lower()
304+
preset = QuantizationPreset(self.hparams.pot_parameters.preset.name.lower())
308305

309-
algorithms = [
310-
{
311-
"name": "DefaultQuantization",
312-
"params": {
313-
"target_device": "ANY",
314-
"preset": preset,
315-
"stat_subset_size": min(stat_subset_size, len(data_loader)),
316-
"shuffle_data": True,
317-
},
318-
}
319-
]
320-
321-
engine = IEEngine(config=engine_config, data_loader=data_loader, metric=None)
322-
323-
pipeline = create_pipeline(algorithms, engine)
324-
325-
compressed_model = pipeline.run(model)
326-
327-
compress_model_weights(compressed_model)
306+
compressed_model = nncf.quantize(
307+
ov_model,
308+
quantization_dataset,
309+
subset_size=min(stat_subset_size, len(data_loader)),
310+
preset=preset,
311+
)
328312

329313
if optimization_parameters is not None:
330314
optimization_parameters.update_progress(90, None)
331315

332316
with tempfile.TemporaryDirectory() as tempdir:
333-
save_model(compressed_model, tempdir, model_name="model")
334-
with open(os.path.join(tempdir, "model.xml"), "rb") as f:
317+
xml_path = os.path.join(tempdir, "model.xml")
318+
ov.serialize(compressed_model, xml_path)
319+
with open(xml_path, "rb") as f:
335320
output_model.set_data("openvino.xml", f.read())
336321
with open(os.path.join(tempdir, "model.bin"), "rb") as f:
337322
output_model.set_data("openvino.bin", f.read())

src/otx/algorithms/anomaly/adapters/anomalib/exportable_code/base.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
from typing import Union
88

99
import numpy as np
10-
from openvino.model_zoo.model_api.models import SegmentationModel
11-
from openvino.model_zoo.model_api.models.types import DictValue, NumericalValue
10+
from openvino.model_api.models import SegmentationModel
11+
from openvino.model_api.models.types import DictValue, NumericalValue
1212

1313

1414
class AnomalyBase(SegmentationModel):

src/otx/algorithms/anomaly/configs/classification/padim/pot_optimization_config.json

Lines changed: 0 additions & 18 deletions
This file was deleted.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
"""PTQ config file."""
2+
from nncf import IgnoredScope
3+
from nncf.common.quantization.structs import QuantizationPreset
4+
from nncf.quantization.advanced_parameters import AdvancedQuantizationParameters
5+
from nncf.quantization.range_estimator import (
6+
AggregatorType,
7+
RangeEstimatorParameters,
8+
StatisticsCollectorParameters,
9+
StatisticsType,
10+
)
11+
12+
advanced_parameters = AdvancedQuantizationParameters(
13+
activations_range_estimator_params=RangeEstimatorParameters(
14+
min=StatisticsCollectorParameters(
15+
statistics_type=StatisticsType.QUANTILE, aggregator_type=AggregatorType.MIN, quantile_outlier_prob=1e-4
16+
),
17+
max=StatisticsCollectorParameters(
18+
statistics_type=StatisticsType.QUANTILE, aggregator_type=AggregatorType.MAX, quantile_outlier_prob=1e-4
19+
),
20+
)
21+
)
22+
23+
preset = QuantizationPreset.MIXED
24+
25+
ignored_scope = IgnoredScope(names=["/anomaly_map_generator/Mul", "/anomaly_map_generator/Sqrt"])

0 commit comments

Comments
 (0)