Skip to content
Open
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,14 @@ class TransformsUpdater:
"max_shear_degree": "shear",
}

# Augmentations that cannot be combined with the tiling pipeline. Mosaic and
# MixUp stitch/blend multiple full images together, which is fundamentally
# incompatible with splitting an image into tiles, so they must never be added
# to a tiling recipe (see the tile recipe NOTE about the AugmentationScheduler).
TILING_INCOMPATIBLE_AUGMENTATIONS: ClassVar[set[str]] = {"mosaic", "mixup"}

@classmethod
def update(cls, augmentation_params: dict, config: dict) -> None: # noqa: C901
def update(cls, augmentation_params: dict, config: dict) -> None: # noqa: C901, PLR0912
"""Update augmentations in the config based on Geti model template.

For each augmentation in augmentation_params:
Expand Down Expand Up @@ -186,6 +192,9 @@ def update(cls, augmentation_params: dict, config: dict) -> None: # noqa: C901
is_ultralytics = config.get("backend") == "ultralytics"

for aug_name, aug_value in augmentation_params.items():
if tiling and aug_name in cls.TILING_INCOMPATIBLE_AUGMENTATIONS:
logger.info("Augmentation '%s' is incompatible with the Tiling pipeline and will be skipped", aug_name)
Comment thread
A-Artemis marked this conversation as resolved.
Outdated
continue
if aug_name not in cls.AUGMENTATION_REGISTRY:
if tiling:
logger.info("Augmentation '%s' is not applicable in Tiling pipeline", aug_name)
Comment thread
A-Artemis marked this conversation as resolved.
Outdated
Expand Down Expand Up @@ -1047,16 +1056,22 @@ def _update_params(config: dict, param_dict: dict) -> None:
deim_framework = augmentation_params.pop("deim_framework", None)
training_parameters = param_dict.get("training", {})

# Update tiling (always applied regardless of DEIM state)
# Update tiling first so downstream augmentation handling can react to it.
TransformsUpdater.update_tiling(tiling, config)

# When DEIM is enabled, the AugmentationSchedulerCallback owns the pipeline;
# user augmentation overrides must be ignored.
deim_enabled = deim_framework is True
tile_enabled = bool(config["data"].get("tile_config", {}).get("enable_tiler", False))

# The DEIM adaptive augmentation scheduling framework (mosaic/mixup based)
# is incompatible with tiling. The tile recipe intentionally omits the
# AugmentationSchedulerCallback and ships a static tiling-friendly pipeline,
# so DEIM must be treated as disabled whenever tiling is enabled, regardless
# of the requested value. Otherwise the converter would silently ignore the
# user's augmentations (deim=True) or add incompatible ones for a tiling run.
deim_enabled = deim_framework is True and not tile_enabled
if not deim_enabled:
TransformsUpdater.update(augmentation_params, config)
if deim_framework is False:
# User explicitly disabled DEIM -> remove the scheduler callback
if deim_framework is False or tile_enabled:
# DEIM disabled by the user, or forced off because tiling is on ->
# remove the scheduler callback and fall back to the static pipeline.
GetiConfigConverter._disable_deim_framework(config)

# Update training hyperparameters
Expand Down
36 changes: 33 additions & 3 deletions application/backend/app/execution/training/getitune_trainer.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

if TYPE_CHECKING:
from getitune import TaskType
from getitune.config.data import SubsetConfig
from getitune.config.data import SubsetConfig, TileConfig
from getitune.data.dataset.base import VisionDataset
from getitune.engine.engine import Engine

Expand Down Expand Up @@ -90,6 +90,7 @@ class DatasetInfo:
getitune_validation_subset_config: SubsetConfig
getitune_testing_subset_config: SubsetConfig
revision_id: UUID
tile_config: TileConfig


@dataclass(frozen=True)
Expand Down Expand Up @@ -243,7 +244,7 @@ def prepare_training_configuration(
return training_config, getitune_training_config

@step("Prepare Training Dataset", 10)
def prepare_training_dataset(
def prepare_training_dataset( # noqa: PLR0915
self,
project_id: UUID,
task: Task,
Expand All @@ -258,7 +259,9 @@ def prepare_training_dataset(
Otherwise, it creates a new dataset from the current items in the database with user-verified annotations.
"""

from getitune.config.data import SamplerConfig, SubsetConfig
from getitune import TaskType
from getitune.config.data import SamplerConfig, SubsetConfig, TileConfig
from getitune.data.dataset.tile import TileDatasetFactory
from getitune.data.entity.utils import detect_storage_dtype
Comment thread
A-Artemis marked this conversation as resolved.
from getitune.data.factory import TransformLibFactory

Expand Down Expand Up @@ -349,6 +352,30 @@ def build_subset_config(subset_name: str) -> SubsetConfig:
transforms=test_subset_config.transforms, # pyrefly: ignore[missing-attribute,bad-argument-type]
)

# Build a TileConfig, and wrap each subset dataset with the tiling factory (if tiling is enabled).
tile_cfg_data = getitune_training_config["data"].get("tile_config", {})
tile_config = TileConfig(**tile_cfg_data)
logger.info("Tiling is set to {}", tile_config.enable_tiler)
if tile_config.enable_tiler and getitune_task_type in (TaskType.DETECTION, TaskType.INSTANCE_SEGMENTATION):
logger.info("TileConfig for training: {}", tile_config)
logger.info("Wrapping subset datasets with TileDatasetFactory")
getitune_training_dataset = TileDatasetFactory.create(
dataset=getitune_training_dataset, tile_config=tile_config
)
getitune_validation_dataset = TileDatasetFactory.create(
dataset=getitune_validation_dataset, tile_config=tile_config
)
getitune_testing_dataset = TileDatasetFactory.create(
dataset=getitune_testing_dataset, tile_config=tile_config
)
Comment thread
A-Artemis marked this conversation as resolved.

logger.info(
"Training dataset size: {}, Validation dataset size: {}, Testing dataset size: {}",
len(getitune_training_dataset),
len(getitune_validation_dataset),
len(getitune_testing_dataset),
)
logger.info("Augmentations applied {}", getitune_training_config["data"])
return DatasetInfo(
getitune_training_dataset=getitune_training_dataset,
getitune_validation_dataset=getitune_validation_dataset,
Expand All @@ -357,6 +384,7 @@ def build_subset_config(subset_name: str) -> SubsetConfig:
getitune_validation_subset_config=val_subset_config,
getitune_testing_subset_config=test_subset_config,
revision_id=dataset_revision_id,
tile_config=tile_config,
)

@step("Prepare Model")
Expand Down Expand Up @@ -416,6 +444,8 @@ def train_model(
val_subset=dataset_info.getitune_validation_subset_config,
test_subset=dataset_info.getitune_testing_subset_config,
)
# Ensure the datamodule (and downstream model) uses the resolved tiling configuration.
datamodule.tile_config = dataset_info.tile_config

logger.info("Instantiating model for training (model_id={})", model_id)
model_cfg = training_config["model"]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,9 @@ class AugmentationParameters(BaseModel):
"training time. When disabled, a simpler static augmentation pipeline "
"is used instead, allowing direct control over individual augmentations. "
"WARNING: when the DEIM framework is enabled, all other augmentation "
"parameters below are ignored and will have no effect on training."
"parameters below are ignored and will have no effect on training. "
"Note: the DEIM framework is not supported when Tiling algorithm is "
"enabled and will be automatically disabled in that case."
),
)
random_zoom_out: RandomZoomOut | None = Field(
Expand All @@ -588,7 +590,10 @@ class AugmentationParameters(BaseModel):
mosaic: Mosaic | None = Field(
default=None,
title="Mosaic",
description="Combines 4 images into one mosaic for augmentation. Applied before resize.",
description=(
"Combines 4 images into one mosaic for augmentation. Applied before resize. "
"Note: this augmentation is not supported when Tiling algorithm is enabled."
),
json_schema_extra={"depends_on": {"deim_framework": [False, None]}},
)
random_resize_crop: RandomResizeCrop | None = Field(
Expand All @@ -613,7 +618,10 @@ class AugmentationParameters(BaseModel):
mixup: Mixup | None = Field(
default=None,
title="Mixup",
description="Blends two images and their labels for augmentation. Applied before resize.",
description=(
"Blends two images and their labels for augmentation. Applied before resize. "
"Note: this augmentation is not supported when Tiling algorithm is enabled."
),
json_schema_extra={"depends_on": {"deim_framework": [False, None]}},
)
random_horizontal_flip: RandomHorizontalFlip | None = Field(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@ stats:
coco_map_50_95: 54.7
coco_map_50: 72.4

capabilities:
tiling: false

hyperparameters:
training:
learning_rate: 0.0005
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@ stats:
benchmark_metrics:
coco_map_50_95: 52.7

capabilities:
tiling: false

hyperparameters:
training:
learning_rate: 0.0004
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@ stats:
coco_map_50_95: 56.5
coco_map_50: 74.0

capabilities:
tiling: false

hyperparameters:
training:
learning_rate: 0.0005
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@ stats:
benchmark_metrics:
coco_map_50_95: 56.0

capabilities:
tiling: false

hyperparameters:
training:
learning_rate: 0.0005
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@ stats:
benchmark_metrics:
coco_map_50_95: 53.0

capabilities:
tiling: false

hyperparameters:
training:
learning_rate: 0.0004
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@ stats:
benchmark_metrics:
coco_map_50_95: 50.9

capabilities:
tiling: false

hyperparameters:
training:
learning_rate: 0.0004
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@ stats:
coco_map_50_95: 56.5
coco_map_50: 75.1

capabilities:
tiling: false

hyperparameters:
training:
learning_rate: 0.0001
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@ stats:
coco_map_50_95: 54.7
coco_map_50: 73.6

capabilities:
tiling: false

hyperparameters:
training:
learning_rate: 0.00021
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@ stats:
coco_map_50_95: 48.4
coco_map_50: 67.6

capabilities:
tiling: false

hyperparameters:
training:
learning_rate: 0.00021
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@ stats:
coco_map_50_95: 53.0
coco_map_50: 72.1

capabilities:
tiling: false

hyperparameters:
training:
learning_rate: 0.00021
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@ stats:
coco_map_50_95: 49.9
coco_map_50: 73.1

capabilities:
tiling: false

hyperparameters:
training:
learning_rate: 0.0001
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@ stats:
coco_map_50_95: 47.1
coco_map_50: 70.5

capabilities:
tiling: false

hyperparameters:
training:
learning_rate: 0.0001
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@ stats:
coco_map_50_95: 45.3
coco_map_50: 68.4

capabilities:
tiling: false

hyperparameters:
training:
learning_rate: 0.0001
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@ stats:
coco_map_50_95: 40.3
coco_map_50: 63.0

capabilities:
tiling: false

hyperparameters:
training:
learning_rate: 0.0001
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@ stats:
coco_map_50_95: 43.1
coco_map_50: 66.2

capabilities:
tiling: false

hyperparameters:
training:
learning_rate: 0.0001
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@ stats:
coco_map_50_95: 48.8
coco_map_50: 72.2

capabilities:
tiling: false

hyperparameters:
training:
learning_rate: 0.0001
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,9 @@ def test_get_default_by_model_architecture_strips_tiling_when_unsupported(
"""Tiling parameters should be removed from the default config when the architecture doesn't support tiling."""
TrainingConfigurationService.get_default_by_model_architecture.cache_clear()

# D-FINE-M does not support tiling (capabilities.tiling: false in its manifest)
# YOLO11-N does not support tiling (capabilities.tiling: false in its manifest)
result = TrainingConfigurationService.get_default_by_model_architecture(
model_architecture_id="object-detection-dfine-m",
model_architecture_id="object-detection-yolo11-n",
)

assert result.algo_level_parameters.dataset_preparation.augmentation.tiling is None
Expand Down Expand Up @@ -183,15 +183,15 @@ def test_get_by_model_architecture_strips_tiling_when_unsupported(
algo_level_config = TrainingConfigurationDB(
id=str(uuid4()),
project_id=fxt_project.id,
model_architecture_id="object-detection-dfine-m",
model_architecture_id="object-detection-yolo11-n",
configuration_data=algo_level_data,
)
db_session.add(algo_level_config)
db_session.flush()

result = fxt_training_configuration_service.get_by_model_architecture(
project_id=UUID(fxt_project.id),
model_architecture_id="object-detection-dfine-m",
model_architecture_id="object-detection-yolo11-n",
)

assert result.algo_level_parameters.dataset_preparation.augmentation.tiling is None
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -702,7 +702,8 @@ def fxt_training_configuration_view_json() -> dict:
"key": "mosaic",
"name": "Mosaic",
"description": (
"Combines 4 images into one mosaic for augmentation. Applied before resize."
"Combines 4 images into one mosaic for augmentation. Applied before resize. "
"Note: this augmentation is not supported when Tiling algorithm is enabled."
),
"depends_on": {"deim_framework": [False, None]},
"parameters": [
Expand Down Expand Up @@ -882,7 +883,8 @@ def fxt_training_configuration_view_json() -> dict:
"key": "mixup",
"name": "Mixup",
"description": (
"Blends two images and their labels for augmentation. Applied before resize."
"Blends two images and their labels for augmentation. Applied before resize. "
"Note: this augmentation is not supported when Tiling algorithm is enabled."
),
"depends_on": {"deim_framework": [False, None]},
"parameters": [
Expand Down
Loading
Loading