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

Generate NN archive from training configs #17

Merged
merged 29 commits into from
Mar 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
90e615c
add archiver CLI
jkbmrz Mar 10, 2024
9dc3328
add archiver callback
jkbmrz Mar 10, 2024
a3ab7d7
add max_det parameter to EfficientBBoxHead
jkbmrz Mar 10, 2024
01255ed
add enum to categorize tasks for the implemented heads
jkbmrz Mar 10, 2024
654de83
add archiver tests
jkbmrz Mar 10, 2024
65acca2
adjust Archiver to new nn archive format
jkbmrz Mar 13, 2024
7302204
pre-comit formatting
jkbmrz Mar 13, 2024
f2536f6
add LDF creation and adjust to new nn archive format
jkbmrz Mar 13, 2024
6e5d17f
update requirements.txt
jkbmrz Mar 13, 2024
0e3b4de
add opencv-python to requirements.txt
jkbmrz Mar 14, 2024
3c0ddc3
add support for ImplicitKeypointBBoxHead
jkbmrz Mar 14, 2024
87bd9b2
remove support for ObjectDetectionSSD
jkbmrz Mar 14, 2024
0932b20
Update requirements.txt
kozlov721 Mar 14, 2024
ecf905f
Added mlflow and removed opencv
kozlov721 Mar 14, 2024
6aea106
[Automated] Updated coverage badge
actions-user Mar 14, 2024
04bc590
add support for SegmentationHead and BiSeNetHead
jkbmrz Mar 14, 2024
5e59c3a
base archiver tests on model from luxonis-train instead of torchvision
jkbmrz Mar 14, 2024
55c74e9
adjust head parameters to changes in NN Archive
jkbmrz Mar 14, 2024
b39dafd
adjust keypoint detection head parameters to changes in NN Archive
jkbmrz Mar 15, 2024
18d4946
bugfix - make sure self.max_det is used in nms
jkbmrz Mar 15, 2024
85f174b
add max_det parameter to ImplicitKeypointBBoxHead
jkbmrz Mar 15, 2024
1009354
adjust task categorization for ImplicitKeypointBBoxHead
jkbmrz Mar 15, 2024
5ee6649
fixing Windows PermissionError occuring on file deletion
jkbmrz Mar 15, 2024
331eae7
fixing Windows PermissionError occuring on file deletion due to unrel…
jkbmrz Mar 18, 2024
adf5f65
add method to remove file handlers keeping the log file open
jkbmrz Mar 18, 2024
305192d
add a logging statement at the end of archiving
jkbmrz Mar 18, 2024
ac7cafb
add optuna_integration to requirements.txt
jkbmrz Mar 18, 2024
4362cff
add hard-coded solution to determining is_softmax parameter
jkbmrz Mar 18, 2024
e4ca5bf
added help
kozlov721 Mar 19, 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
14 changes: 14 additions & 0 deletions luxonis_train/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,20 @@ def inspect(
exit()


@app.command()
def archive(
executable: Annotated[
Optional[Path], typer.Option(help="Path to the model file.", show_default=False)
],
config: ConfigType = None,
opts: OptsType = None,
):
"""Generate NN archive."""
from luxonis_train.core import Archiver

Archiver(str(config), opts).archive(executable)


def version_callback(value: bool):
if value:
typer.echo(f"LuxonisTrain Version: {version(__package__)}")
Expand Down
2 changes: 2 additions & 0 deletions luxonis_train/callbacks/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

from luxonis_train.utils.registry import CALLBACKS

from .archive_on_train_end import ArchiveOnTrainEnd
from .export_on_train_end import ExportOnTrainEnd
from .luxonis_progress_bar import LuxonisProgressBar
from .metadata_logger import MetadataLogger
Expand All @@ -23,6 +24,7 @@


__all__ = [
"ArchiveOnTrainEnd",
"ExportOnTrainEnd",
"LuxonisProgressBar",
"MetadataLogger",
Expand Down
72 changes: 72 additions & 0 deletions luxonis_train/callbacks/archive_on_train_end.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import logging
import os
from pathlib import Path
from typing import cast

import lightning.pytorch as pl

from luxonis_train.utils.config import Config
from luxonis_train.utils.registry import CALLBACKS
from luxonis_train.utils.tracker import LuxonisTrackerPL


@CALLBACKS.register_module()
class ArchiveOnTrainEnd(pl.Callback):
def __init__(self, upload_to_mlflow: bool = False):
"""Callback that performs archiving of onnx or exported model at the end of
training/export. TODO: description.

@type upload_to_mlflow: bool
@param upload_to_mlflow: If set to True, overrides the upload url in Archiver
with currently active MLFlow run (if present).
"""
super().__init__()
self.upload_to_mlflow = upload_to_mlflow

def on_train_end(self, trainer: pl.Trainer, pl_module: pl.LightningModule) -> None:
"""Archives the model on train end.

@type trainer: L{pl.Trainer}
@param trainer: Pytorch Lightning trainer.
@type pl_module: L{pl.LightningModule}
@param pl_module: Pytorch Lightning module.
@raises RuntimeError: If no best model path is found.
"""
from luxonis_train.core.archiver import Archiver

model_checkpoint_callbacks = [
c
for c in trainer.callbacks # type: ignore
if isinstance(c, pl.callbacks.ModelCheckpoint) # type: ignore
]

# NOTE: assume that first checkpoint callback is based on val loss
best_model_path = model_checkpoint_callbacks[0].best_model_path
if not best_model_path:
raise RuntimeError(
"No best model path found. "
"Please make sure that ModelCheckpoint callback is present "
"and at least one validation epoch has been performed."
)
cfg: Config = pl_module.cfg
cfg.model.weights = best_model_path
if self.upload_to_mlflow:
if cfg.tracker.is_mlflow:
tracker = cast(LuxonisTrackerPL, trainer.logger)
new_upload_url = f"mlflow://{tracker.project_id}/{tracker.run_id}"
cfg.archiver.upload_url = new_upload_url
else:
logging.getLogger(__name__).warning(
"`upload_to_mlflow` is set to True, "
"but there is no MLFlow active run, skipping."
)

onnx_path = str(Path(best_model_path).parent.with_suffix(".onnx"))
if not os.path.exists(onnx_path):
raise FileNotFoundError(
"Model executable not found. Make sure to run exporter callback before archiver callback"
)

archiver = Archiver(cfg=cfg)

archiver.archive(onnx_path)
3 changes: 2 additions & 1 deletion luxonis_train/core/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from .archiver import Archiver
from .exporter import Exporter
from .inferer import Inferer
from .trainer import Trainer
from .tuner import Tuner

__all__ = ["Exporter", "Trainer", "Tuner", "Inferer"]
__all__ = ["Exporter", "Trainer", "Tuner", "Inferer", "Archiver"]
Loading
Loading