Skip to content

Commit dd903bc

Browse files
committed
add training code
1 parent 3fc7fee commit dd903bc

19 files changed

Lines changed: 1840 additions & 0 deletions

File tree

src/lightly_train/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
from lightly_train._commands.predict_task import predict_semantic_segmentation
4242
from lightly_train._commands.train import pretrain, train
4343
from lightly_train._commands.train_task import (
44+
train_depth_estimation,
4445
train_image_classification,
4546
train_image_classification_multihead,
4647
train_instance_segmentation,
@@ -74,6 +75,7 @@
7475
"ModelPart",
7576
"predict_semantic_segmentation",
7677
"pretrain",
78+
"train_depth_estimation",
7779
"train_image_classification",
7880
"train_image_classification_multihead",
7981
"train_instance_segmentation",

src/lightly_train/_commands/train_task.py

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@
3535
from lightly_train._data.coco_object_detection_dataset import (
3636
COCOObjectDetectionDataArgs,
3737
)
38+
from lightly_train._data.depth_estimation_dataset import (
39+
DepthEstimationDataArgs,
40+
)
3841
from lightly_train._data.image_classification_dataset import (
3942
ImageClassificationMulticlassDataArgs,
4043
ImageClassificationMultilabelDataArgs,
@@ -70,6 +73,170 @@
7073
logger = logging.getLogger(__name__)
7174

7275

76+
def train_depth_estimation(
77+
*,
78+
out: PathLike,
79+
data: dict[str, Any] | str,
80+
model: str,
81+
steps: int | Literal["auto"] = "auto",
82+
batch_size: int | Literal["auto"] = "auto",
83+
num_workers: int | Literal["auto"] = "auto",
84+
devices: int | str | list[int] = "auto",
85+
num_nodes: int = 1,
86+
resume_interrupted: bool = False,
87+
checkpoint: PathLike | None = None,
88+
overwrite: bool = False,
89+
accelerator: str = "auto",
90+
strategy: str = "auto",
91+
precision: _PRECISION_INPUT = "bf16-mixed",
92+
float32_matmul_precision: Literal["auto", "highest", "high", "medium"] = "auto",
93+
seed: int = 0,
94+
logger_args: dict[str, Any] | None = None,
95+
model_args: dict[str, Any] | None = None,
96+
transform_args: dict[str, Any] | None = None,
97+
metric_args: dict[str, Any] | None = None,
98+
loader_args: dict[str, Any] | None = None,
99+
save_checkpoint_args: dict[str, Any] | None = None,
100+
torch_compile_args: dict[str, Any] | None = None,
101+
gradient_accumulation_steps: int | Literal["auto"] = "auto",
102+
) -> None:
103+
"""Train a depth estimation model.
104+
105+
Fine-tunes a Depth Anything V3 model by distilling depth and sky pseudo-labels
106+
(e.g. generated with the V3 ViT-L teacher) into a smaller backbone.
107+
108+
The training process can be monitored with TensorBoard:
109+
110+
.. code-block:: bash
111+
112+
tensorboard --logdir out
113+
114+
After training, the last model checkpoint is saved in the out directory to:
115+
``out/checkpoints/last.ckpt`` and also exported to
116+
``out/exported_models/exported_last.pt``.
117+
118+
Args:
119+
out:
120+
The output directory where the model checkpoints and logs are saved.
121+
data:
122+
The dataset configuration or path to a YAML file with the configuration.
123+
Each split points to a directory of RGB images and directories of depth and
124+
sky pseudo-labels (``.npy`` files matched to each image by filename stem)::
125+
126+
data={
127+
"train": {"images": ".../train/images",
128+
"depth": ".../train/depth",
129+
"sky": ".../train/sky"},
130+
"val": {"images": ".../val/images",
131+
"depth": ".../val/depth",
132+
"sky": ".../val/sky"},
133+
}
134+
135+
Depth pixels with value ``<= 0`` are treated as invalid and ignored by the
136+
loss and metrics.
137+
model:
138+
The model to train. For example, "dinov2/dav3-relative-small", or a path to
139+
a local model checkpoint.
140+
141+
If you want to resume training from an interrupted or crashed run, use the
142+
``resume_interrupted`` parameter.
143+
steps:
144+
The number of training steps.
145+
batch_size:
146+
Global batch size. The batch size per device/GPU is inferred from this value
147+
and the number of devices and nodes.
148+
num_workers:
149+
Number of workers for the dataloader per device/GPU. 'auto' automatically
150+
sets the number of workers based on the available CPU cores.
151+
devices:
152+
Number of devices/GPUs for training. 'auto' automatically selects all
153+
available devices. The device type is determined by the ``accelerator``
154+
parameter.
155+
num_nodes:
156+
Number of nodes for distributed training.
157+
checkpoint:
158+
Use this parameter to further fine-tune a model from a previous fine-tuned
159+
checkpoint. The checkpoint must be a path to a checkpoint file, for example
160+
"checkpoints/model.ckpt". This will only load the model weights from the
161+
previous run. All other training state (e.g. optimizer state, epochs) from
162+
the previous run are not loaded.
163+
164+
This option is equivalent to setting ``model="<path_to_checkpoint>"``.
165+
166+
If you want to resume training from an interrupted or crashed run, use the
167+
``resume_interrupted`` parameter instead.
168+
resume_interrupted:
169+
Set this to True if you want to resume training from an **interrupted or
170+
crashed** training run. This will pick up exactly where the training left
171+
off, including the optimizer state and the current step.
172+
173+
- You must use the same ``out`` directory as the interrupted run.
174+
- You must **NOT** change any training parameters (e.g., learning rate, batch size, data, etc.).
175+
- This is intended for continuing the same run without modification.
176+
overwrite:
177+
Overwrite the output directory if it already exists. Warning, this might
178+
overwrite existing files in the directory!
179+
accelerator:
180+
Hardware accelerator. Can be one of ['cpu', 'gpu', 'mps', 'auto'].
181+
'auto' will automatically select the best accelerator available.
182+
strategy:
183+
Training strategy. For example 'ddp' or 'auto'. 'auto' automatically
184+
selects the best strategy available.
185+
precision:
186+
Training precision. Select '16-mixed' for mixed 16-bit precision, '32-true'
187+
for full 32-bit precision, or 'bf16-mixed' for mixed bfloat16 precision.
188+
float32_matmul_precision:
189+
Precision for float32 matrix multiplication. Can be one of ['auto',
190+
'highest', 'high', 'medium']. See https://docs.pytorch.org/docs/stable/generated/torch.set_float32_matmul_precision.html#torch.set_float32_matmul_precision
191+
for more information.
192+
seed:
193+
Random seed for reproducibility.
194+
logger_args:
195+
Logger arguments. Either None or a dictionary of logger names to either
196+
None or a dictionary of logger arguments. None uses the default loggers.
197+
To disable a logger, set it to None: ``logger_args={"tensorboard": None}``.
198+
model_args:
199+
Model training arguments. Either None or a dictionary of model arguments.
200+
transform_args:
201+
Transform arguments. Either None or a dictionary of transform arguments.
202+
The image size and normalization parameters can be set with
203+
``transform_args={"image_size": (height, width), "normalize": {"mean": (r, g, b), "std": (r, g, b)}}``
204+
metric_args:
205+
Metric arguments. Either None or a dictionary of metric arguments.
206+
Set ``metric_args={"train": True}`` to also compute depth metrics on the
207+
training data. Set ``metric_args={"watch_metric": "val_metric/rmse"}`` to
208+
configure the metric used to select the best checkpoint.
209+
loader_args:
210+
Arguments for the PyTorch DataLoader. Should only be used in special cases
211+
as default values are automatically set. Prefer to use the `batch_size` and
212+
`num_workers` arguments instead. For details, see:
213+
https://pytorch.org/docs/stable/data.html#torch.utils.data.DataLoader
214+
save_checkpoint_args:
215+
Arguments to configure the saving of checkpoints. The checkpoint frequency
216+
can be set with ``save_checkpoint_args={"save_every_num_steps": 100}``.
217+
torch_compile_args:
218+
Arguments to configure model compilation with torch.compile. The arguments
219+
are directly passed to torch.compile. Set
220+
``torch_compile_args={"disable": True}`` to disable it if you encounter any
221+
issues.
222+
gradient_accumulation_steps:
223+
Number of gradient accumulation steps. 'auto' automatically enables
224+
gradient accumulation when batch_size is smaller than the model's default
225+
batch size, using ``max(1, default_batch_size // batch_size)`` steps to
226+
keep the effective batch size and learning rate close to the model defaults.
227+
Set to 1 to explicitly disable gradient accumulation.
228+
"""
229+
tracker.track_training_started(
230+
task_type="depth_estimation",
231+
model=model,
232+
method="depth_anything",
233+
batch_size=batch_size,
234+
devices=devices,
235+
steps=steps,
236+
)
237+
return _train_task(config_cls=DepthEstimationTrainTaskConfig, **locals())
238+
239+
73240
def train_image_classification(
74241
*,
75242
out: PathLike,
@@ -1847,6 +2014,7 @@ class TrainTaskConfig(PydanticConfig):
18472014
data: TaskDataArgs
18482015
model: str
18492016
task: Literal[
2017+
"depth_estimation",
18502018
"image_classification",
18512019
"image_classification_multihead",
18522020
"instance_segmentation",
@@ -1889,6 +2057,11 @@ def _load_yaml_if_path(cls, v: Any) -> Any:
18892057
)
18902058

18912059

2060+
class DepthEstimationTrainTaskConfig(TrainTaskConfig):
2061+
data: DepthEstimationDataArgs
2062+
task: Literal["depth_estimation"] = "depth_estimation"
2063+
2064+
18922065
class ImageClassificationMulticlassTrainTaskConfig(TrainTaskConfig):
18932066
data: ImageClassificationMulticlassDataArgs
18942067
task: Literal["image_classification"] = "image_classification"

src/lightly_train/_commands/train_task_helpers.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@
4949
)
5050
from lightly_train._task_checkpoint import TaskSaveCheckpointArgs
5151
from lightly_train._task_models import task_model_helpers
52+
from lightly_train._task_models.depth_estimation.train_model import (
53+
DepthEstimationTrain,
54+
)
5255
from lightly_train._task_models.dinov2_eomt_instance_segmentation.train_model import (
5356
DINOv2EoMTInstanceSegmentationTrain,
5457
)
@@ -119,6 +122,7 @@
119122

120123

121124
TASK_TRAIN_MODEL_CLASSES: list[type[TrainModel]] = [
125+
DepthEstimationTrain,
122126
ImageClassificationTrain,
123127
ImageClassificationMultiheadTrain,
124128
DINOv2EoMTInstanceSegmentationTrain,
@@ -137,6 +141,11 @@
137141

138142
# TODO(Thomas, 10/25): Create a type for the metrics.
139143
TASK_TO_METRICS: dict[str, dict[str, str]] = {
144+
"depth_estimation": {
145+
"val_metric/rmse": "Val RMSE",
146+
"val_metric/abs_rel": "Val AbsRel",
147+
"val_metric/delta1": "Val delta<1.25",
148+
},
140149
"instance_segmentation": {
141150
"val_metric/map": "Val mAP@0.5:0.95",
142151
"val_metric/map_50": "Val mAP@0.5",

0 commit comments

Comments
 (0)