Config System — detrex documentation (original) (raw)
Given that the traditional yacs-based config system or python argparse command-line options suffer from providing enough flexibility for the development of new project, we adopted the alternative and non-intrusive config system called lazy config from detectron2.
Please refer to detectron2 lazy-config tutorials for more details about the syntax and basic usage of lazy config.
Default Configs in detrex
Our detrex
has defined a standard set of config namespaces for later usage. Users can modify these configs according to their own needs.
In summary, the pre-defined namespaces are model, train, dataloader, optimizer, lr_multiplier
model
This is configuration for model definition. We define all model configs under projects/
, You can refer to projects/dab_detr/configs/models for more examples.
Here is the example of dab-detr-r50
model config:
dab_detr_r50.py
import torch.nn as nn
from detrex.modeling.matcher import HungarianMatcher from detrex.modeling.criterion import SetCriterion from detrex.layers import PositionEmbeddingSine from detrex.modeling.backbone import ResNet, BasicStem
from detectron2.config import LazyCall as L
from projects.dab_detr.modeling import ( DABDETR, DabDetrTransformer, DabDetrTransformerDecoder, DabDetrTransformerEncoder, )
model = L(DABDETR)( backbone=L(ResNet)( stem=L(BasicStem)(in_channels=3, out_channels=64, norm="FrozenBN"), stages=L(ResNet.make_default_stages)( depth=50, stride_in_1x1=False, norm="FrozenBN", ), out_features=["res2", "res3", "res4", "res5"], freeze_at=1, ), in_features=["res5"], # only use last level feature in DAB-DETR in_channels=2048, position_embedding=L(PositionEmbeddingSine)( num_pos_feats=128, temperature=20, normalize=True, ), transformer=L(DabDetrTransformer)( encoder=L(DabDetrTransformerEncoder)( embed_dim=256, num_heads=8, attn_dropout=0.0, feedforward_dim=2048, ffn_dropout=0.0, activation=L(nn.PReLU)(), num_layers=6, ), decoder=L(DabDetrTransformerDecoder)( embed_dim=256, num_heads=8, attn_dropout=0.0, feedforward_dim=2048, ffn_dropout=0.0, activation=L(nn.PReLU)(), num_layers=6, modulate_hw_attn=True, ), ), embed_dim=256, num_classes=80, num_queries=300, criterion=L(SetCriterion)( num_classes=80, matcher=L(HungarianMatcher)( cost_class=2.0, cost_bbox=5.0, cost_giou=2.0, cost_class_type="focal_loss_cost", alpha=0.25, gamma=2.0, ), weight_dict={ "loss_class": 1, "loss_bbox": 5.0, "loss_giou": 2.0, }, loss_class_type="focal_loss", alpha=0.25, gamma=2.0, ), aux_loss=True, pixel_mean=[123.675, 116.280, 103.530], pixel_std=[58.395, 57.120, 57.375], freeze_anchor_box_centers=True, select_box_nums_for_evaluation=300, device="cuda", )
which can be loaded like:
user's own config.py
from dab_detr_r50 import model
check the loaded model config
assert model.embed_dim == 256
modify model config according to your own needs
model.embed_dim = 512
After defining model configs in python files. Please import
it in the global scope of the final config file as model
.
You can access and change all keys in the model config according to your own needs.
train
This is the configuration for training and evalution. The default training config can be found in configs/common/train.py
.
The default training config is as follows:
train = dict(
# Directory where output files are written to
output_dir="./output",
# The initialize checkpoint to be loaded
init_checkpoint="",
# The total training iterations
max_iter=90000,
# options for Automatic Mixed Precision
amp=dict(enabled=False),
# options for DistributedDataParallel
ddp=dict(
broadcast_buffers=False,
find_unused_parameters=False,
fp16_compression=False,
),
# options for Gradient Clipping during training
clip_grad=dict(
enabled=False,
params=dict(
max_norm=0.1,
norm_type=2,
),
),
# # options for Fast Debugging
fast_dev_run=dict(enabled=False),
# options for PeriodicCheckpointer, which saves a model checkpoint
# after every `checkpointer.period` iterations,
# and only `checkpointer.max_to_keep` number of checkpoint will be kept.
checkpointer=dict(period=5000, max_to_keep=100),
# Run evaluation after every `eval_period` number of iterations
eval_period=5000,
# Output log to console every `log_period` number of iterations.
log_period=20,
device="cuda"
# ...
)
dataloader
This is the configuration for dataset and dataloader. We use the built-in dataset in detectron2 for simplicity. Please see configs/common/data
for more examples.
Here we take the coco_detr.py
for detr-like model as an example:
from omegaconf import OmegaConf
import detectron2.data.transforms as T from detectron2.config import LazyCall as L from detectron2.data import ( build_detection_test_loader, build_detection_train_loader, get_detection_dataset_dicts, ) from detectron2.evaluation import COCOEvaluator
from detrex.data import DetrDatasetMapper
dataloader = OmegaConf.create()
the defined train loader
dataloader.train = L(build_detection_train_loader)( dataset=L(get_detection_dataset_dicts)(names="coco_2017_train"), mapper=L(DetrDatasetMapper)( # the defined two augmentations which will be random-selected during training. augmentation=[ L(T.RandomFlip)(), L(T.ResizeShortestEdge)( short_edge_length=(480, 512, 544, 576, 608, 640, 672, 704, 736, 768, 800), max_size=1333, sample_style="choice", ), ], augmentation_with_crop=[ L(T.RandomFlip)(), L(T.ResizeShortestEdge)( short_edge_length=(400, 500, 600), sample_style="choice", ), L(T.RandomCrop)( crop_type="absolute_range", crop_size=(384, 600), ), L(T.ResizeShortestEdge)( short_edge_length=(480, 512, 544, 576, 608, 640, 672, 704, 736, 768, 800), max_size=1333, sample_style="choice", ), ], is_train=True, mask_on=False, # with instance mask or not img_format="RGB", # input image format ), total_batch_size=16, # training batch size num_workers=4, )
the defined test loader
dataloader.test = L(build_detection_test_loader)( dataset=L(get_detection_dataset_dicts)(names="coco_2017_val", filter_empty=False), mapper=L(DetrDatasetMapper)( # use no augmentation in testing augmentation=[ L(T.ResizeShortestEdge)( short_edge_length=800, max_size=1333, ), ], augmentation_with_crop=None, is_train=False, mask_on=False, img_format="RGB", ), num_workers=4, )
the defined evaluator for evaluation
dataloader.evaluator = L(COCOEvaluator)( dataset_name="${..test.dataset.names}", )
We adopted the built-in coco datasets
and detection dataloader
usage from detectron2, please refer to the following tutorials if you want to use custom datasets:
optimizer
This is the configuration for optimizer. The default configuration can be found in configs/common/optim.py
.
detrex uilizes detectron2.solver.build.get_default_optimizer_params
which needs the nn.Module
as argument and returns the parameter groups.
configs/common/optim.py
import torch
from detectron2.config import LazyCall as L from detectron2.solver.build import get_default_optimizer_params
AdamW = L(torch.optim.AdamW)( params=L(get_default_optimizer_params)( # params.model is meant to be set to the model object, before instantiating # the optimizer. base_lr="${..lr}", weight_decay_norm=0.0, ), lr=1e-4, betas=(0.9, 0.999), weight_decay=0.1, )
if you want to use torch.optim.SGD
in training, you can modify your config as follows:
import torch from configs.commom.optim import AdamW as optim
optim.target = torch.optim.SGD
Remove the incompatible arguments
del optim.betas
Add the needed arguments
optim.momentum = 0.9
lr_multiplier
This is the configuration for lr_multiplier
which is combined with detectron2.engine.hooks.LRScheduler
and performs learning scheduler function during training.
The default lr_multiplier
config can be found in configs/common/coco_schedule.py
, we defined the commonly 50 epochs scheduler referred to in the papers as follows:
from fvcore.common.param_scheduler import MultiStepParamScheduler
from detectron2.config import LazyCall as L from detectron2.solver import WarmupParamScheduler
def default_coco_scheduler(epochs=50, decay_epochs=40, warmup_epochs=0): """ Returns the config for a default multi-step LR scheduler such as "50epochs", commonly referred to in papers, where every 1x has the total length of 1440k training images (~12 COCO epochs). LR is decayed once at the end of training.
Args:
epochs (int): total training epochs.
decay_epochs (int): lr decay steps.
warmup_epochs (int): warmup epochs.
Returns:
DictConfig: configs that define the multiplier for LR during training
"""
# total number of iterations assuming 16 batch size, using 1440000/16=90000
total_steps_16bs = epochs * 7500
decay_steps = decay_epochs * 7500
warmup_steps = warmup_epochs * 7500
scheduler = L(MultiStepParamScheduler)(
values=[1.0, 0.1],
milestones=[decay_steps, total_steps_16bs],
)
return L(WarmupParamScheduler)(
scheduler=scheduler,
warmup_length=warmup_steps / total_steps_16bs,
warmup_method="linear",
warmup_factor=0.001,
)
Please refer to fvcore.common.param_scheduler.ParamScheduler for more details about the ParamScheduler
usage in detectron2.
Get the Default Config
Users don’t have to rewrite all contents in config every time. You can use the default built-in detrex configs using detrex.config.get_config
.
After building detrex
from source, you can use get_config
to get the default configs as follows:
from detrex.config import get_config
get the default config
dataloader = get_config("common/data/coco_detr.py").dataloader optimizer = get_config("common/optim.py").AdamW lr_multiplier = get_config("common/coco_schedule.py").lr_multiplier_50ep train = get_config("common/train.py").train
modify the config
train.max_iter = 375000 train.output_dir = "path/to/your/own/dir"
LazyConfig Best Practices
- Treat the configs you write as actual “code”: Avoid copying them or duplicating them. Import the common parts between configs.
- Keep the configs you write as simple as possible: Do not include keys that do not affect the experimental setting.