Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Omegaconfig PR1: basic functionality #97

Open
wants to merge 29 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
6f8ab55
new config file and training_job file
gqcpm Sep 27, 2024
72b9d7b
created config folder w subfiles
gqcpm Sep 27, 2024
80e5915
created all classes, still need to edit last two
gqcpm Oct 1, 2024
186be74
add validators
gqcpm Oct 4, 2024
796788d
add docstrings
gqcpm Oct 4, 2024
34548b8
updated to implement attrs
gqcpm Oct 9, 2024
7ea94b6
finished parameters and docstring for dataconfig class
gqcpm Oct 9, 2024
192399d
black linted
gqcpm Oct 9, 2024
184d5ea
add first 3 parameters. NEED TO look at how to change parameters in b…
gqcpm Oct 15, 2024
c79ea42
add first 3 parameters. NEED TO look at how to change parameters in b…
gqcpm Oct 15, 2024
d866e36
added backbone_config manuel initialization and pretrainedweights va…
gqcpm Oct 18, 2024
d572730
add clarifying comments to backbone_config initialization process
gqcpm Oct 18, 2024
35b29c4
head_config singleinstance
gqcpm Oct 21, 2024
5a5dc7b
added config for centroid and centered instance
gqcpm Oct 21, 2024
3b0f48a
added bottomup headconfig
gqcpm Oct 21, 2024
a074821
rename and setup for trainerconfig
gqcpm Oct 21, 2024
470a2f3
delete training_job, create data loaders
gqcpm Oct 21, 2024
4d5f169
modelckpt and individual params in trainer config
gqcpm Oct 21, 2024
cfd87d4
added wandb, optimizer, lrscheduler, earlystopping
gqcpm Oct 21, 2024
c73e546
change to oneof headconfig
gqcpm Oct 25, 2024
d191bf1
*not finished - check backbone* doctrings and lint
gqcpm Oct 25, 2024
d7ba20c
finished trainer_config docstrings and lint
gqcpm Oct 25, 2024
19f5256
instantiate backboneconfig with oneof decorator
gqcpm Oct 29, 2024
16c8f26
add proportion validator, change random crop
gqcpm Nov 1, 2024
43c777b
add data loaders
gqcpm Nov 8, 2024
5286eb7
formatted
gqcpm Nov 8, 2024
7b71a8b
trainerconfig docstrings
gqcpm Nov 8, 2024
46df99a
remove json and dict loaders. keep only yaml
gqcpm Nov 15, 2024
110ca64
default values test
gqcpm Nov 22, 2024
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
152 changes: 152 additions & 0 deletions sleap_nn/config/data_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
import attrs
from omegaconf import MISSING
from typing import Optional, Tuple, List, Dict


"""Serializable configuration classes for specifying all data configuration parameters.

These configuration classes are intended to specify all
the parameters required to initialize the data config.
"""
Comment on lines +1 to +10
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Optimize imports

The imports need the following adjustments:

  • Remove unused imports: List and Dict
  • Add missing import: Union from typing

Apply this diff to fix the imports:

 import attrs
 from omegaconf import MISSING
-from typing import Optional, Tuple, List, Dict
+from typing import Optional, Tuple, Union
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import attrs
from omegaconf import MISSING
from typing import Optional, Tuple, List, Dict
"""Serializable configuration classes for specifying all data configuration parameters.
These configuration classes are intended to specify all
the parameters required to initialize the data config.
"""
import attrs
from omegaconf import MISSING
from typing import Optional, Tuple, Union
"""Serializable configuration classes for specifying all data configuration parameters.
These configuration classes are intended to specify all
the parameters required to initialize the data config.
"""
🧰 Tools
🪛 Ruff

3-3: typing.List imported but unused

Remove unused import

(F401)


3-3: typing.Dict imported but unused

Remove unused import

(F401)



@attrs.define
class DataConfig:
"""Data configuration.

provider: (str) Provider class to read the input sleap files. Only "LabelsReader" supported for the training pipeline.
train_labels_path: (str) Path to training data (.slp file)
val_labels_path: (str) Path to validation data (.slp file)
user_instances_only: (bool) True if only user labeled instances should be used for training. If False, both user labeled and predicted instances would be used. Default: True.
chunk_size: (int) Size of each chunk (in MB). Default: "100". #TODO: change in inference ckpts
preprocessing: Configuration options related to data preprocessing.
use_augmentations_train: (bool) True if the data augmentation should be applied to the training data, else False.
augmentation_config: Configurations related to augmentation
instance_cropping: Configuration options related to instance cropping for centroid
and topdown models.
"""

provider: str = "LabelsReader"
train_labels_path: str = MISSING
val_labels_path: str = MISSING
user_instances_only: bool = True
chunk_size: int = 100
preprocessing: PreprocessingConfig = attrs.field(factory=PreprocessingConfig)
use_augmentations_train: bool = False
augmentation_config: Optional[AugmentationConfig] = None
Comment on lines +34 to +36
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Use forward references for configuration classes

To avoid circular imports and undefined names, use string literals for type hints of configuration classes.

Apply this diff:

-    preprocessing: PreprocessingConfig = attrs.field(factory=PreprocessingConfig)
-    augmentation_config: Optional[AugmentationConfig] = None
+    preprocessing: 'PreprocessingConfig' = attrs.field(
+        factory=lambda: PreprocessingConfig()
+    )
+    augmentation_config: Optional['AugmentationConfig'] = None
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
preprocessing: PreprocessingConfig = attrs.field(factory=PreprocessingConfig)
use_augmentations_train: bool = False
augmentation_config: Optional[AugmentationConfig] = None
preprocessing: 'PreprocessingConfig' = attrs.field(
factory=lambda: PreprocessingConfig()
)
use_augmentations_train: bool = False
augmentation_config: Optional['AugmentationConfig'] = None
🧰 Tools
🪛 Ruff

34-34: Undefined name PreprocessingConfig

(F821)


34-34: Undefined name PreprocessingConfig

(F821)


36-36: Undefined name AugmentationConfig

(F821)



def validate_proportion(instance, attribute, value):
if not (0.0 <= value <= 1.0):
raise ValueError(f"{attribute.name} must be between 0.0 and 1.0, got {value}")


@attrs.define
class PreprocessingConfig:
"""Configuration of Preprocessing.

Attributes:
is_rgb: (bool) True if the image has 3 channels (RGB image). If input has only one channel when this is set to True, then the images from single-channel is replicated along the channel axis. If input has three channels and this is set to False, then we convert the image to grayscale (single-channel) image.
max_height: (int) Maximum height the image should be padded to. If not provided, the original image size will be retained. Default: None.
max_width: (int) Maximum width the image should be padded to. If not provided, the original image size will be retained. Default: None.
scale: (float or List[float]) Factor to resize the image dimensions by, specified as either a float scalar or as a 2-tuple of [scale_x, scale_y]. If a scalar is provided, both dimensions are resized by the same factor.
crop_hw: (Tuple[int]) Crop height and width of each instance (h, w) for centered-instance model. If None, this would be automatically computed based on the largest instance in the sio.Labels file.
min_crop_size: (int) Minimum crop size to be used if crop_hw is None.
"""

is_rgb: bool = True
max_height: Optional[int] = None
max_width: Optional[int] = None
scale: Union[float, Tuple[float, float]] = 1.0
crop_hw: Optional[Tuple[int, int]] = None
min_crop_size: int = 32 # to help app work incase of error
Comment on lines +44 to +62
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Approve PreprocessingConfig class and add missing import

The PreprocessingConfig class is well-structured with appropriate attributes and documentation. However, there's a missing import for the Union type.

Add the following import at the top of the file:

from typing import Union

This will resolve the undefined name issue for the Union type used in the scale attribute.

🧰 Tools
🪛 Ruff

55-55: Undefined name Union

(F821)



@attrs.define
class AugmentationConfig:
"""Configuration of Augmentation

Attributes:
intensity: (Optional)
geometric: (Optional)
"""

intensity: Optional[IntensityConfig] = attrs.field(default=None)
geometric: Optional[GeometricConfig] = attrs.field(default=None)


@attrs.define
class IntensityConfig:
"""Configuration of Intensity (Optional):

Attributes:
uniform_noise_min: (float) Minimum value for uniform noise (uniform_noise_min >=0).
uniform_noise_max: (float) Maximum value for uniform noise (uniform_noise_max <>=1).
uniform_noise_p: (float) Probability of applying random uniform noise. Default=0.0
gaussian_noise_mean: (float) The mean of the gaussian noise distribution.
gaussian_noise_std: (float) The standard deviation of the gaussian noise distribution.
gaussian_noise_p: (float) Probability of applying random gaussian noise. Default=0.0
contrast_min: (float) Minimum contrast factor to apply. Default: 0.5.
contrast_max: (float) Maximum contrast factor to apply. Default: 2.0.
contrast_p: (float) Probability of applying random contrast. Default=0.0
brightness: (float) The brightness factor to apply. Default: (1.0, 1.0).
brightness_p: (float) Probability of applying random brightness. Default=0.0
"""

uniform_noise_min: float = attrs.field(
default=0.0, validator=attrs.validators.ge(0)
)
uniform_noise_max: float = attrs.field(
default=1.0, validator=attrs.validators.le(1)
)
uniform_noise_p: float = attrs.field(default=0.0, validator=validate_proportion)
gaussian_noise_mean: float = 0.0
gaussian_noise_std: float = 1.0
gaussian_noise_p: float = attrs.field(default=0.0, validator=validate_proportion)
contrast_min: float = attrs.field(default=0.5, validator=attrs.validators.ge(0))
contrast_max: float = attrs.field(default=2.0, validator=attrs.validators.ge(0))
contrast_p: float = attrs.field(default=0.0, validator=validate_proportion)
brightness: Tuple[float, float] = (1.0, 1.0)
brightness_p: float = attrs.field(default=0.0, validator=validate_proportion)


@attrs.define
class GeometricConfig:
"""
Configuration of Geometric (Optional)

Attributes:
rotation: (float) Angles in degrees as a scalar float of the amount of rotation. A random angle in (-rotation, rotation) will be sampled and applied to both images and keypoints. Set to 0 to disable rotation augmentation.
scale: (float) scaling factor interval. If (a, b) represents isotropic scaling, the scale is randomly sampled from the range a <= scale <= b. If (a, b, c, d), the scale is randomly sampled from the range a <= scale_x <= b, c <= scale_y <= d Default: None.
translate_width: (float) Maximum absolute fraction for horizontal translation. For example, if translate_width=a, then horizontal shift is randomly sampled in the range -img_width * a < dx < img_width * a. Will not translate by default.
translate_height: (float) Maximum absolute fraction for vertical translation. For example, if translate_height=a, then vertical shift is randomly sampled in the range -img_height * a < dy < img_height * a. Will not translate by default.
affine_p: (float) Probability of applying random affine transformations. Default=0.0
erase_scale_min: (float) Minimum value of range of proportion of erased area against input image. Default: 0.0001.
erase_scale_max: (float) Maximum value of range of proportion of erased area against input image. Default: 0.01.
erase_ration_min: (float) Minimum value of range of aspect ratio of erased area. Default: 1.
erase_ratio_max: (float) Maximum value of range of aspect ratio of erased area. Default: 1.
erase_p: (float) Probability of applying random erase. Default=0.0
mixup_lambda: (float) min-max value of mixup strength. Default is 0-1. Default: None.
mixup_p: (float) Probability of applying random mixup v2. Default=0.0
input_key: (str) Can be image or instance. The input_key instance expects the KorniaAugmenter to follow the InstanceCropper else image otherwise for default.
random_crop_p: (float) Probability of applying random crop.
random_crop_height: (int) Desired output height of the random crop.
random_crop_width: (int) Desired output height of the random crop.
"""

rotation: float = 0.0
scale: Optional[Tuple[float, float, float, float]] = None
translate_width: float = 0.0
translate_height: float = 0.0
affine_p: float = attrs.field(default=0.0, validator=validate_proportion)
erase_scale_min: float = 0.0001
erase_scale_max: float = 0.01
erase_ratio_min: float = 1.0
erase_ratio_max: float = 1.0
erase_p: float = attrs.field(default=0.0, validator=validate_proportion)
mixup_lambda: Optional[float] = None
mixup_p: float = attrs.field(default=0.0, validator=validate_proportion)
input_key: str = "image"
random_crop_p: Optional[float] = None
random_crop_height: Optional[int] = None
random_crop_width: Optional[int] = None
Comment on lines +113 to +152
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix documentation and attribute name issues

There are two issues in the GeometricConfig class:

  1. Typo in attribute documentation: "erase_ration_min" should be "erase_ratio_min"
  2. Documentation error: random_crop_width's description says "output height" instead of "output width"

Apply this diff to fix the documentation:

-        erase_ration_min: (float) Minimum value of range of aspect ratio of erased area. Default: 1.
+        erase_ratio_min: (float) Minimum value of range of aspect ratio of erased area. Default: 1.
-        random_crop_width: (int) Desired output height of the random crop.
+        random_crop_width: (int) Desired output width of the random crop.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@attrs.define
class GeometricConfig:
"""
Configuration of Geometric (Optional)
Attributes:
rotation: (float) Angles in degrees as a scalar float of the amount of rotation. A random angle in (-rotation, rotation) will be sampled and applied to both images and keypoints. Set to 0 to disable rotation augmentation.
scale: (float) scaling factor interval. If (a, b) represents isotropic scaling, the scale is randomly sampled from the range a <= scale <= b. If (a, b, c, d), the scale is randomly sampled from the range a <= scale_x <= b, c <= scale_y <= d Default: None.
translate_width: (float) Maximum absolute fraction for horizontal translation. For example, if translate_width=a, then horizontal shift is randomly sampled in the range -img_width * a < dx < img_width * a. Will not translate by default.
translate_height: (float) Maximum absolute fraction for vertical translation. For example, if translate_height=a, then vertical shift is randomly sampled in the range -img_height * a < dy < img_height * a. Will not translate by default.
affine_p: (float) Probability of applying random affine transformations. Default=0.0
erase_scale_min: (float) Minimum value of range of proportion of erased area against input image. Default: 0.0001.
erase_scale_max: (float) Maximum value of range of proportion of erased area against input image. Default: 0.01.
erase_ration_min: (float) Minimum value of range of aspect ratio of erased area. Default: 1.
erase_ratio_max: (float) Maximum value of range of aspect ratio of erased area. Default: 1.
erase_p: (float) Probability of applying random erase. Default=0.0
mixup_lambda: (float) min-max value of mixup strength. Default is 0-1. Default: None.
mixup_p: (float) Probability of applying random mixup v2. Default=0.0
input_key: (str) Can be image or instance. The input_key instance expects the KorniaAugmenter to follow the InstanceCropper else image otherwise for default.
random_crop_p: (float) Probability of applying random crop.
random_crop_height: (int) Desired output height of the random crop.
random_crop_width: (int) Desired output height of the random crop.
"""
rotation: float = 0.0
scale: Optional[Tuple[float, float, float, float]] = None
translate_width: float = 0.0
translate_height: float = 0.0
affine_p: float = attrs.field(default=0.0, validator=validate_proportion)
erase_scale_min: float = 0.0001
erase_scale_max: float = 0.01
erase_ratio_min: float = 1.0
erase_ratio_max: float = 1.0
erase_p: float = attrs.field(default=0.0, validator=validate_proportion)
mixup_lambda: Optional[float] = None
mixup_p: float = attrs.field(default=0.0, validator=validate_proportion)
input_key: str = "image"
random_crop_p: Optional[float] = None
random_crop_height: Optional[int] = None
random_crop_width: Optional[int] = None
@attrs.define
class GeometricConfig:
"""
Configuration of Geometric (Optional)
Attributes:
rotation: (float) Angles in degrees as a scalar float of the amount of rotation. A random angle in (-rotation, rotation) will be sampled and applied to both images and keypoints. Set to 0 to disable rotation augmentation.
scale: (float) scaling factor interval. If (a, b) represents isotropic scaling, the scale is randomly sampled from the range a <= scale <= b. If (a, b, c, d), the scale is randomly sampled from the range a <= scale_x <= b, c <= scale_y <= d Default: None.
translate_width: (float) Maximum absolute fraction for horizontal translation. For example, if translate_width=a, then horizontal shift is randomly sampled in the range -img_width * a < dx < img_width * a. Will not translate by default.
translate_height: (float) Maximum absolute fraction for vertical translation. For example, if translate_height=a, then vertical shift is randomly sampled in the range -img_height * a < dy < img_height * a. Will not translate by default.
affine_p: (float) Probability of applying random affine transformations. Default=0.0
erase_scale_min: (float) Minimum value of range of proportion of erased area against input image. Default: 0.0001.
erase_scale_max: (float) Maximum value of range of proportion of erased area against input image. Default: 0.01.
erase_ratio_min: (float) Minimum value of range of aspect ratio of erased area. Default: 1.
erase_ratio_max: (float) Maximum value of range of aspect ratio of erased area. Default: 1.
erase_p: (float) Probability of applying random erase. Default=0.0
mixup_lambda: (float) min-max value of mixup strength. Default is 0-1. Default: None.
mixup_p: (float) Probability of applying random mixup v2. Default=0.0
input_key: (str) Can be image or instance. The input_key instance expects the KorniaAugmenter to follow the InstanceCropper else image otherwise for default.
random_crop_p: (float) Probability of applying random crop.
random_crop_height: (int) Desired output height of the random crop.
random_crop_width: (int) Desired output width of the random crop.
"""
rotation: float = 0.0
scale: Optional[Tuple[float, float, float, float]] = None
translate_width: float = 0.0
translate_height: float = 0.0
affine_p: float = attrs.field(default=0.0, validator=validate_proportion)
erase_scale_min: float = 0.0001
erase_scale_max: float = 0.01
erase_ratio_min: float = 1.0
erase_ratio_max: float = 1.0
erase_p: float = attrs.field(default=0.0, validator=validate_proportion)
mixup_lambda: Optional[float] = None
mixup_p: float = attrs.field(default=0.0, validator=validate_proportion)
input_key: str = "image"
random_crop_p: Optional[float] = None
random_crop_height: Optional[int] = None
random_crop_width: Optional[int] = None

Loading
Loading