Skip to content

Commit

Permalink
Merge branch 'releases/1.6.0' into ashwin/anomaly_geti_task_migration…
Browse files Browse the repository at this point in the history
…_1_6
  • Loading branch information
ashwinvaidya17 committed Aug 28, 2024
2 parents 489a0b7 + ae994cb commit 2e4f592
Show file tree
Hide file tree
Showing 19 changed files with 83 additions and 30 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,21 @@

All notable changes to this project will be documented in this file.

## \[v1.6.5\]

### Bug fixes

- Fix labels names in hierarchical config (<https://github.com/openvinotoolkit/training_extensions/pull/3879>)
- Fix Learning Rate and Loss Handling in Tile Classifier MaskRCNN EfficientNet (<https://github.com/openvinotoolkit/training_extensions/pull/3873>)
- Disable Tile Classifier in Rotated Detection (<https://github.com/openvinotoolkit/training_extensions/pull/3894>)
- Enhance Memeory Cache Handler with Complex Unique Keys (<https://github.com/openvinotoolkit/training_extensions/pull/3897>)

## \[v1.6.4\]

### Bug fixes

- Pad input image to square when tiling is enabled (<https://github.com/openvinotoolkit/training_extensions/pull/3844>)
- Fix confusion matrix calculation (<https://github.com/openvinotoolkit/training_extensions/pull/3857>)

## \[v1.6.3\]

Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,11 @@ You can find more details with examples in the [CLI command intro](https://openv

## Updates

### v1.6.3 (3Q24)
### v1.6.5 (3Q24)

- Improve Vitens Kiemgetal OTX 1.6.x
- Fix rotated detection data pipeline
- Update dependencies to omit vulnerabilities
- Fix labels names in hierarchical config
- Fix Learning Rate and Loss Handling in Tile Classifier MaskRCNN EfficientNet
- Enhance Memeory Cache Handler with Complex Unique Keys

### Release History

Expand Down
13 changes: 13 additions & 0 deletions docs/source/guide/release_notes/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,19 @@ Releases
.. toctree::
:maxdepth: 1

v1.6.5 (3Q24)
-------------

- Fix labels names in hierarchical config
- Fix Learning Rate and Loss Handling in Tile Classifier MaskRCNN EfficientNet
- Enhance Memeory Cache Handler with Complex Unique Keys

v1.6.4 (3Q24)
-------------

- Pad input image to square when tiling is enabled
- Fix confusion matrix calculation

v1.6.3 (3Q24)
-------------

Expand Down
2 changes: 1 addition & 1 deletion src/otx/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
# Copyright (C) 2021-2023 Intel Corporation
# SPDX-License-Identifier: Apache-2.0

__version__ = "1.6.4rc0"
__version__ = "1.6.5"
# NOTE: Sync w/ src/otx/api/usecases/exportable_code/demo/requirements.txt on release
4 changes: 4 additions & 0 deletions src/otx/algorithms/classification/adapters/openvino/task.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ def _async_callback(self, request: Any, callback_args: tuple) -> None:
result_handler(id, annotation, aux_data)

except Exception as e:
logger.exception(e)
self.callback_exceptions.append(e)

def predict(self, image: np.ndarray) -> Tuple[ClassificationResult, AnnotationSceneEntity]:
Expand Down Expand Up @@ -280,6 +281,9 @@ def add_prediction(id: int, predicted_scene: AnnotationSceneEntity, aux_data: tu

self.inferencer.await_all()

if self.inferencer.callback_exceptions:
raise RuntimeError("Inference failed, check the exceptions log.")

self._avg_time_per_image = total_time / len(dataset)
logger.info(f"Avg time per image: {self._avg_time_per_image} secs")
logger.info(f"Total time: {total_time} secs")
Expand Down
22 changes: 15 additions & 7 deletions src/otx/algorithms/classification/utils/cls_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,20 @@
from otx.api.entities.label import LabelEntity
from otx.api.entities.label_schema import LabelSchemaEntity
from otx.api.serialization.label_mapper import LabelSchemaMapper
from otx.api.utils.labels_utils import get_normalized_label_name


def get_multihead_class_info(label_schema: LabelSchemaEntity): # pylint: disable=too-many-locals
def get_multihead_class_info(
label_schema: LabelSchemaEntity, normalize_labels: bool = False
): # pylint: disable=too-many-locals
"""Get multihead info by label schema."""
all_groups = label_schema.get_groups(include_empty=False)
all_groups_str = []
for g in all_groups:
group_labels_str = [lbl.name for lbl in g.labels]
if normalize_labels:
group_labels_str = [get_normalized_label_name(lbl) for lbl in g.labels]
else:
group_labels_str = [lbl.name for lbl in g.labels]
all_groups_str.append(group_labels_str)

single_label_groups = [g for g in all_groups_str if len(g) == 1]
Expand Down Expand Up @@ -76,7 +82,7 @@ def get_cls_inferencer_configuration(label_schema: LabelSchemaEntity):
hierarchical = not multilabel and len(label_schema.get_groups(False)) > 1
multihead_class_info = {}
if hierarchical:
multihead_class_info = get_multihead_class_info(label_schema)
multihead_class_info = get_multihead_class_info(label_schema, normalize_labels=True)
return {
"multilabel": multilabel,
"hierarchical": hierarchical,
Expand Down Expand Up @@ -112,17 +118,19 @@ def get_cls_model_api_configuration(label_schema: LabelSchemaEntity, inference_c
all_labels = ""
all_label_ids = ""
for lbl in label_entities:
all_labels += lbl.name.replace(" ", "_") + " "
all_labels += get_normalized_label_name(lbl) + " "
all_label_ids += f"{lbl.id_} "

mapi_config[("model_info", "labels")] = all_labels.strip()
mapi_config[("model_info", "label_ids")] = all_label_ids.strip()

hierarchical_config = {}
hierarchical_config["cls_heads_info"] = get_multihead_class_info(label_schema)
hierarchical_config["cls_heads_info"] = get_multihead_class_info(label_schema, normalize_labels=True)
hierarchical_config["label_tree_edges"] = []
for edge in label_schema.label_tree.edges: # (child, parent)
hierarchical_config["label_tree_edges"].append((edge[0].name, edge[1].name))
hierarchical_config["label_tree_edges"].append(
(get_normalized_label_name(edge[0]), get_normalized_label_name(edge[1]))
)

mapi_config[("model_info", "hierarchical_config")] = json.dumps(hierarchical_config)
return mapi_config
Expand All @@ -137,7 +145,7 @@ def get_hierarchical_label_list(hierarchical_cls_heads_info: Dict, labels: List)
hierarchical_labels = []
for label_str, _ in label_to_idx.items():
for label_entity in labels:
if label_entity.name == label_str:
if get_normalized_label_name(label_entity) == label_str:
hierarchical_labels.append(label_entity)
break
return hierarchical_labels
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,12 @@ def _get_unique_key(results: Dict[str, Any]) -> Tuple:
if "cache_key" in results:
return results["cache_key"]
d_item = results["dataset_item"]
results["cache_key"] = d_item.media.path, d_item.roi.id
if d_item.media.path: # when video extracted frames come, media.path is None
results["cache_key"] = d_item.media.path, d_item.roi.id
elif len(d_item.annotation_scene.annotations) > 0:
results["cache_key"] = d_item.roi.id, d_item.annotation_scene.annotations[0].id
else:
results["cache_key"] = d_item.roi.id
return results["cache_key"]

def _get_memcache_handler(self):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ def forward_train(
img, img_metas, gt_bboxes, gt_labels, gt_bboxes_ignore, gt_masks, proposals, **kwargs
)
losses.update(rcnn_loss)
if "acc" in losses:
losses.pop("acc")
return losses

@staticmethod
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,11 +122,8 @@ def patch_tiling(config, hparams, dataset=None):

if config.model.backbone.type == "efficientnet_b2b":
learning_rate = 0.002
logger.info(
f"Patched {config.model.backbone.type} LR: "
f"{hparams.learning_parameters.learning_rate} -> {learning_rate}"
)
hparams.learning_parameters.learning_rate = learning_rate
logger.info(f"Patched {config.model.backbone.type} LR: " f"{config.optimizer.lr} -> {learning_rate}")
config.optimizer.lr = learning_rate

config.data.train.filter_empty_gt = False

Expand Down
4 changes: 4 additions & 0 deletions src/otx/algorithms/detection/adapters/openvino/task.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ def _async_callback(self, request: Any, callback_args: tuple) -> None:
result_handler(id, processed_prediciton, features)

except Exception as e:
logger.exception(e)
self.callback_exceptions.append(e)

def enqueue_prediction(self, image: np.ndarray, id: int, result_handler: Any) -> None:
Expand Down Expand Up @@ -557,6 +558,9 @@ def add_prediction(id: int, predicted_scene: AnnotationSceneEntity, aux_data: tu

self.inferencer.await_all()

if self.inferencer.callback_exceptions:
raise RuntimeError("Inference failed, check the exceptions log.")

self._avg_time_per_image = total_time / len(dataset)
logger.info(f"Avg time per image: {self._avg_time_per_image} secs")
logger.info(f"Total time: {total_time} secs")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
dict(type="Resize", img_scale=img_size, keep_ratio=True),
dict(type="RandomFlip", flip_ratio=0.5),
dict(type="Normalize", **img_norm_cfg),
dict(type="Pad", pad_to_square=True),
dict(type="Pad", size=img_size),
dict(type="DefaultFormatBundle"),
dict(
type="Collect",
Expand Down Expand Up @@ -45,7 +45,7 @@
dict(type="Resize", keep_ratio=True),
dict(type="RandomFlip"),
dict(type="Normalize", **img_norm_cfg),
dict(type="Pad", pad_to_square=True),
dict(type="Pad", size=img_size),
dict(type="ImageToTensor", keys=["img"]),
dict(type="Collect", keys=["img"]),
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
dict(type="Resize", img_scale=img_size, keep_ratio=True),
dict(type="RandomFlip", flip_ratio=0.5),
dict(type="Normalize", **img_norm_cfg),
dict(type="Pad", pad_to_square=True),
dict(type="Pad", size=img_size),
dict(type="DefaultFormatBundle"),
dict(
type="Collect",
Expand Down Expand Up @@ -45,7 +45,7 @@
dict(type="Resize", keep_ratio=True),
dict(type="RandomFlip"),
dict(type="Normalize", **img_norm_cfg),
dict(type="Pad", pad_to_square=True),
dict(type="Pad", size=img_size),
dict(type="ImageToTensor", keys=["img"]),
dict(type="Collect", keys=["img"]),
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -565,16 +565,16 @@ tiling_parameters:
header: Enable tile classifier
description: Enabling tile classifier enhances the speed of tiling inference by incorporating a tile classifier into the instance segmentation model. This feature prevents the detector from making predictions on tiles that do not contain any objects, thus optimizing its speed performance.
default_value: false
editable: true
editable: false
affects_outcome_of: TRAINING
type: BOOLEAN
ui_rules:
action: DISABLE_EDITING
operator: AND
rules: []
type: UI_RULES
value: true
visible_in_ui: true
value: false
visible_in_ui: false
warning: The tile classifier prioritizes inference speed over training speed, it requires more training in order to achieve its optimized performance.

enable_adaptive_params:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
dict(type="Resize", img_scale=img_size, keep_ratio=False),
dict(type="RandomFlip", flip_ratio=0.5),
dict(type="Normalize", **img_norm_cfg),
dict(type="Pad", pad_to_square=True),
dict(type="Pad", size=img_size),
dict(type="DefaultFormatBundle"),
dict(
type="Collect",
Expand Down Expand Up @@ -45,7 +45,7 @@
dict(type="Resize", keep_ratio=False),
dict(type="RandomFlip"),
dict(type="Normalize", **img_norm_cfg),
dict(type="Pad", pad_to_square=True),
dict(type="Pad", size=img_size),
dict(type="ImageToTensor", keys=["img"]),
dict(type="Collect", keys=["img"]),
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
dict(type="Resize", img_scale=img_size, keep_ratio=True),
dict(type="RandomFlip", flip_ratio=0.5),
dict(type="Normalize", **img_norm_cfg),
dict(type="Pad", pad_to_square=True),
dict(type="Pad", size=img_size),
dict(type="DefaultFormatBundle"),
dict(
type="Collect",
Expand Down Expand Up @@ -45,7 +45,7 @@
dict(type="Resize", keep_ratio=True),
dict(type="RandomFlip"),
dict(type="Normalize", **img_norm_cfg),
dict(type="Pad", pad_to_square=True),
dict(type="Pad", size=img_size),
dict(type="ImageToTensor", keys=["img"]),
dict(type="Collect", keys=["img"]),
],
Expand Down
4 changes: 4 additions & 0 deletions src/otx/algorithms/segmentation/adapters/openvino/task.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ def _async_callback(self, request: Any, callback_args: tuple) -> None:
result_handler(id, annotation, processed_prediciton.feature_vector, processed_prediciton.saliency_map)

except Exception as e:
logger.exception(e)
self.callback_exceptions.append(e)


Expand Down Expand Up @@ -254,6 +255,9 @@ def add_prediction(

self.inferencer.await_all()

if self.inferencer.callback_exceptions:
raise RuntimeError("Inference failed, check the exceptions log.")

self._avg_time_per_image = total_time / len(dataset)
logger.info(f"Avg time per image: {self._avg_time_per_image} secs")
logger.info(f"Total time: {total_time} secs")
Expand Down
2 changes: 1 addition & 1 deletion src/otx/api/usecases/exportable_code/demo/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
openvino==2023.3.0
openvino-model-api==0.1.9.1
otx==1.6.3
otx==1.6.5
numpy>=1.21.0,<=1.23.5 # np.bool was removed in 1.24.0 which was used in openvino runtime
5 changes: 5 additions & 0 deletions src/otx/api/utils/labels_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,8 @@ def get_empty_label(label_schema: LabelSchemaEntity) -> Optional[LabelEntity]:
if empty_candidates:
return empty_candidates[0]
return None


def get_normalized_label_name(label: LabelEntity) -> str:
"""Gets a nomalized label name"""
return label.name.replace(" ", "_")
Original file line number Diff line number Diff line change
Expand Up @@ -211,3 +211,4 @@ def test_patch_tiling_func(self):
hyper_parameters.tiling_parameters.enable_tiling = True
hyper_parameters.tiling_parameters.enable_tile_classifier = True
patch_tiling(cfg, hyper_parameters, self.dataset)
assert cfg.optimizer.lr == 0.002, "Learning rate should be 0.002 when MRCNN EfficientNet is used"

0 comments on commit 2e4f592

Please sign in to comment.