.ipynb
Train Yolo-NAS model with 3LC Metrics Collection¶
This notebook shows how to train a Yolo-NAS detection model with 3LC Metrics Collection on an Object Detection 3LC Table.
We recommend to use Python 3.10, and ensure super-gradients is installed. Note that installing super-gradients will downgrade the versions of several dependencies of 3lc. We therefore install termcolor==3.1.0 afterwards.
Install dependencies¶
[ ]:
%pip install 3lc
%pip install super-gradients
%pip install termcolor==3.1.0
Imports¶
[ ]:
import tlc
from super_gradients.common.object_names import Models
from super_gradients.training import Trainer, models
from super_gradients.training.losses import PPYoloELoss
from super_gradients.training.metrics import DetectionMetrics_050
from super_gradients.training.models.detection_models.pp_yolo_e import PPYoloEPostPredictionCallback
from super_gradients.training.transforms.transforms import (
DetectionHorizontalFlip,
DetectionHSV,
DetectionPaddedRescale,
DetectionRandomAffine,
DetectionStandardize,
DetectionTargetsFormatTransform,
)
from super_gradients.training.utils.collate_fn.detection_collate_fn import DetectionCollateFN
from tlc.integration.super_gradients import (
DetectionDataset,
DetectionMetricsCollectionCallback,
PipelineParams,
)
from torch.utils.data import DataLoader
Project Setup¶
[ ]:
PROJECT_NAME = "3LC Tutorials"
DATASET_NAME = "COCO128"
We reuse the COCO128 tables created in create-table-from-coco-detection.ipynb, so make sure to run this notebook first.
[ ]:
train_table = tlc.Table.from_names("initial", DATASET_NAME, PROJECT_NAME)
val_table = tlc.Table.from_names("initial", DATASET_NAME, PROJECT_NAME)
[ ]:
simple_value_map = train_table.get_simple_value_map("bbs.bb_list.label")
class_names = list(simple_value_map.values())
num_classes = len(class_names)
class_names
Pass the training and validation tables to a DetectionDataset, which loads images and annotations from the Table and retains image and label preprocessing functionality available in the parent SuperGradients DetectionDataset.
[ ]:
train_dataset = DetectionDataset(
train_table,
input_dim=(640, 640),
transforms=[
DetectionRandomAffine(
degrees=0.0,
scales=(0.5, 1.5),
shear=0.0,
target_size=(640, 640),
filter_box_candidates=False,
border_value=128,
),
DetectionHSV(prob=1.0, hgain=5, vgain=30, sgain=30),
DetectionHorizontalFlip(prob=0.5),
DetectionPaddedRescale(input_dim=(640, 640)),
DetectionStandardize(max_value=255),
DetectionTargetsFormatTransform(input_dim=(640, 640), output_format="LABEL_CXCYWH"),
],
)
val_dataset = DetectionDataset(
val_table,
input_dim=(640, 640),
transforms=[
DetectionPaddedRescale(input_dim=(640, 640), max_targets=300),
DetectionStandardize(max_value=255),
DetectionTargetsFormatTransform(input_dim=(640, 640), output_format="LABEL_CXCYWH"),
],
)
train_dataloader: DataLoader = DataLoader(train_dataset, batch_size=4, shuffle=True, collate_fn=DetectionCollateFN())
val_dataloader: DataLoader = DataLoader(val_dataset, batch_size=4, shuffle=False, collate_fn=DetectionCollateFN())
model = models.get(Models.YOLO_NAS_S, num_classes=num_classes, pretrained_weights="coco")
trainer = Trainer(
experiment_name="fine-tune-yolo-nas-detect-3lc",
ckpt_root_dir="checkpoints",
)
Use PipelineParams to customize the SuperGradients Pipeline used for inference when collecting metrics, and a DetectionMetricsCollectionCallback to invoke 3LC Metrics Collection, Hyperparameter and Run logging. Make sure to pass the callback to the phase_callbacks in the training parameters passed to the SuperGradients Trainer.
[ ]:
pipeline_params = PipelineParams(
iou=0.5, # IoU threshold for NMS matching
conf=0.3, # Confidence threshold for predictions to keep
max_predictions=10, # Max number of predictions for each image
class_agnostic_nms=True,
)
callback = DetectionMetricsCollectionCallback(
project_name=PROJECT_NAME,
run_description="Fine-tune Yolo-NAS detection model",
collect_val_only=True,
pipeline_params=pipeline_params,
)
train_params = {
"warmup_initial_lr": 5e-5,
"initial_lr": 5e-5,
"lr_mode": "cosine",
"cosine_final_lr_ratio": 0.5,
"optimizer": "AdamW",
"zero_weight_decay_on_bias_and_bn": True,
"lr_warmup_epochs": 1,
"warmup_mode": "LinearEpochLRWarmup",
"optimizer_params": {"weight_decay": 0.0001},
"ema": False,
"average_best_models": False,
"ema_params": {"beta": 25, "decay_type": "exp"},
"max_epochs": 5,
"mixed_precision": True,
"loss": PPYoloELoss(use_static_assigner=False, num_classes=num_classes, reg_max=16),
"valid_metrics_list": [
DetectionMetrics_050(
score_thres=0.1,
top_k_predictions=300,
num_cls=num_classes,
normalize_targets=True,
include_classwise_ap=True,
class_names=class_names,
post_prediction_callback=PPYoloEPostPredictionCallback(
score_threshold=0.01, nms_top_k=1000, max_predictions=300, nms_threshold=0.7
),
)
],
"metric_to_watch": "mAP@0.50",
"phase_callbacks": [callback],
}
run = tlc.init(project_name=PROJECT_NAME)
trainer.train(
model=model,
training_params=train_params,
train_loader=train_dataloader,
valid_loader=val_dataloader,
)