Prerequisites:
In this section, we will assume that you want to build you own recipe, and to train a model based on that recipe.
We will cover 2 different approaches in writing your recipe.
- SuperGradients Format - you stick to the format used in SuperGradients.
- Custom Format - you organize recipes the way you want.
This approach is most appropriate when you want to quickly get started.
Since you will be following all SuperGradients convention when building the recipe, you won't have to worry about working with hydra to instantiate your objects and to launch a training; SuperGradients already provides a script that will do it for you.
How to get started?
- We recommend that you would go through the pre-defined recipes and chose the one which seems most similar to your use case. Make sure it covers the same task as you.
- Copy it to a folder that will be exclusively meant for recipes, inside your project.
- Override the required parameters to fit your needs. Make sure to keep the same structure. Think about registering custom objects if you need.
- Copy train_from_recipe script to your project (see below), but think to override
<config-path>
with the path to your recipe folder.
# The code below is the same as the `train_from_recipe.py` script
# See: https://github.com/Deci-AI/super-gradients/blob/master/src/super_gradients/train_from_recipe.py
import hydra
from omegaconf import DictConfig
from super_gradients import Trainer, init_trainer
@hydra.main(config_path="<config-path>", version_base="1.2") # TODO: overwrite `<config-path>`
def _main(cfg: DictConfig) -> None:
Trainer.train_from_config(cfg)
def main() -> None:
init_trainer() # `init_trainer` needs to be called before `@hydra.main`
_main()
if __name__ == "__main__":
main()
With this approach, you will have much more freedom in the way you organize your recipe but this will come at the cost of writing code! This is mainly recommended for specific use-cases which are not properly covered with the previous approach.
Despite not being required with this approach, we strongly recommend for you to use the same format as in SuperGradients as it would allow you to build on top of pre-defined recipes.
What are the recipe format constraints here ?
With this approach, you will still need to follow certain conventions
training_hyperparams
should include the same required fields as with the previous approach. You can find the list here.- The config passed to
dataloaders.get
should still be compatible to dataset/dataloader you want to load.
Basically, the format constraints that you will face with this approach are the same as these that you would face when working exclusively with python.
How to launch a training ?
Similarly to the previous approach, you will need a script that will launch the training.
The difference being that here you won't be using Trainer.train_from_config
. Instead, you will to isntantiate all the required objects in your script.
Here is an example of how such a script could look like:
import hydra
from omegaconf import DictConfig
from super_gradients import Trainer, init_trainer, setup_device
from super_gradients.training import dataloaders, models
@hydra.main(config_path="<config-path>", version_base="1.2") # TODO: overwrite `<config-path>`
def _main(cfg: DictConfig) -> None:
setup_device(
device=cfg.device,
multi_gpu=cfg.multi_gpu,
num_gpus=cfg.num_gpus,
)
# INSTANTIATE ALL OBJECTS IN CFG
cfg = hydra.utils.instantiate(cfg)
trainer = Trainer(experiment_name=cfg.experiment_name, ckpt_root_dir=cfg.ckpt_root_dir)
# BUILD NETWORK
model = models.get(
model_name=cfg.architecture,
num_classes=cfg.arch_params.num_classes,
arch_params=cfg.arch_params,
strict_load=cfg.checkpoint_params.strict_load,
pretrained_weights=cfg.checkpoint_params.pretrained_weights,
checkpoint_path=cfg.checkpoint_params.checkpoint_path,
load_backbone=cfg.checkpoint_params.load_backbone,
)
# INSTANTIATE DATA LOADERS
train_dataloader = dataloaders.get(
name=cfg.train_dataloader,
dataset_params=cfg.dataset_params.train_dataset_params,
dataloader_params=cfg.dataset_params.train_dataloader_params,
)
val_dataloader = dataloaders.get(
name=cfg.val_dataloader,
dataset_params=cfg.dataset_params.val_dataset_params,
dataloader_params=cfg.dataset_params.val_dataloader_params,
)
# TRAIN
results = trainer.train(
model=model,
train_loader=train_dataloader,
valid_loader=val_dataloader,
training_params=cfg.training_hyperparams,
additional_configs_to_log={},
)
print(results)
def main() -> None:
init_trainer() # `init_trainer` needs to be called before `@hydra.main`
_main()
if __name__ == "__main__":
main()
By default, defaults
only works with recipes that are defined in the same recipe directory, but this can be extended to other directories.
In our case, this comes handy when you want to build on top of recipes that were implemented in SuperGradients.
Using default_train_params
defined in super_gradients/recipes/training_hyperparams/default_train_params.yaml
defaults:
- training_hyperparams: default_train_params
hydra:
searchpath:
- pkg://super_gradients.recipes
... # Continue with your recipe