Training API
Trainer(cfg)
¶
Main class for training models in deepvisiontools. Everything configurable can be done through the TrainerConfig class.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cfg
|
deepvisiontools.train.trainconfig.TrainerConfig
|
Trainer configuration. |
required |
Usage
from deepvisiontools.config import current, set_current
from deepvisiontools.models import ModelFactory
from deepvisiontools.datasets import DeepVisionDataset, DeepVisionLoader
from deepvisiontools.train import Trainer, launch, TrainerConfig
from deepvisiontools.metrics.factories import (
DetectionSuiteFactory,
InstanceSegSuiteFactory,
SemanticSegSuiteFactory,
)
from torch.optim import Adam
from torchvision.transforms.v2 import (
RandomHorizontalFlip,
RandomVerticalFlip,
RandomGrayscale,
ColorJitter,
)
# For a 1 class detection dataset, otherwise need to modify current() as explained in DVConfig class
# ── Datsets Paths ───────────────────────
TRAIN_DIR = "datasets_demo/instance_nc=1/train" # e.g. /data/coco/train2017
VAL_DIR = "datasets_demo/instance_nc=1/valid" # e.g. /data/coco/val2017
set_current(current().update_device("cuda"))
augs = [
RandomVerticalFlip(),
RandomVerticalFlip(),
ColorJitter(hue=0.15, brightness=0.15, contrast=0.15, saturation=0.15),
RandomGrayscale(0.05),
]
trainset = DeepVisionDataset(
TRAIN_DIR,
"coco",
data_type_reader="instance_mask",
augmentation=augs,
)
valset = DeepVisionDataset(
VAL_DIR, "coco", data_type_reader="instance_mask"
)
trainloader = DeepVisionLoader(trainset, batch_size=4)
validloader = DeepVisionLoader(valset, batch_size=4)
# Best way to use deepvisiontools : build config from registered ones, then modify them if needed
Config = TrainerConfig.build_registered_config(
model="detector-seg",
config="detector_convnextv2-base_cascade_maskrcnn",
train_loader=trainloader,
valid_loader=validloader,
)
# exemple of modification but everything is configurable (optimizer, scheduler, models directly from ModelFactory etc.)
# Note : you can build TrainerConfig from scratch as well, but there are a bunch of parameters you may want to default to
Config.epochs = 120
# Start Training
def main():
Trainer(Config).fit(resume=None)
launch(main, devices="auto") # Can Use DDP wrapper if multiple gpu detected
# If you want to restart from a checkpoint :
Trainer.fit(resume="my/checkpoint/path") # in main
Source code in src/deepvisiontools/train/trainer.py
783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 | |
fit(resume=None)
¶
Complete training program.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
resume
|
Optional[Union[str, Path]], **optional**
|
Resume training from checkpoint. Defaults to None. |
None
|
Source code in src/deepvisiontools/train/trainer.py
1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 | |
validate()
¶
Epoch-end validation.
DDP policy: - only rank0 runs the full validation pass - other ranks wait at barrier
Safety: - preserves the model's previous train/eval mode - restores BN runtime freeze policy when returning to train mode - stays symmetric with validate_sync()
Source code in src/deepvisiontools/train/trainer.py
1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 | |
export_model(path, *, builder, model_kwargs, include_optimizer=False, include_scaler=False, include_ema=True)
¶
Write a portable model artifact (weights + builder/kwargs + pred params).
Source code in src/deepvisiontools/train/trainer.py
1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 | |
validate_sync()
¶
Synchronized cross-rank in-epoch validation.
Design: - all ranks participate - validation data is sharded across ranks - uses a temporary fresh valid meter from MetricsHook - final metrics are synchronized through suite.finalize_distributed() - rank0 updates the monitor + logger - restores previous train/eval mode afterwards
Source code in src/deepvisiontools/train/trainer.py
2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 | |
launch(main_fn, *, devices='auto', nproc=None, main_args=None, main_kwargs=None)
¶
Launch a training entrypoint, optionally through torch.distributed.run.
launch is a convenience wrapper around torchrun --standalone. If the
current process is already inside a torchrun context (LOCAL_RANK is set),
it directly calls main_fn(*main_args, **main_kwargs). Otherwise, it infers
the number of processes from devices or nproc.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
main_fn
|
`Callable[..., Any]`
|
User training function to execute. |
required |
devices
|
`str | int | Sequence[int]`
|
Device/process selection.
Accepted values include:
- |
'auto'
|
nproc
|
`int | None`
|
Optional explicit process count override. If set,
it takes precedence over the process count inferred from |
None
|
main_args
|
`Sequence[Any] | None`
|
Positional arguments forwarded to
|
None
|
main_kwargs
|
`Mapping[str, Any] | None`
|
Keyword arguments forwarded to
|
None
|
DDP behavior
nproc == 1and no GPU remapping:main_fnruns in-process.nproc == 1with GPU remapping, for exampledevices="cuda:2": a child process is spawned so PyTorch sees the intendedCUDA_VISIBLE_DEVICES.nproc > 1: the current Python script is re-executed withpython -m torch.distributed.run --standalone --nproc_per_node=<nproc>.
Usage
from deepvisiontools.train import Trainer, launch
def main():
Trainer(cfg).fit()
# Auto: one process per visible GPU, or CPU/single-process if no GPU.
launch(main, devices="auto")
# Force CPU / single process.
launch(main, devices="cpu")
# Use 2 processes. This is a process count, not GPU id 2.
launch(main, devices=2)
# Use exactly physical GPUs 0 and 1.
launch(main, devices=[0, 1])
# Same as above with string syntax.
launch(main, devices="cuda:0,1")
# Use only physical GPU 2.
launch(main, devices="cuda:2")
# Forward arguments to the main function.
def train_with_name(run_name, *, resume=None):
cfg.logging.mlflow_run_name = run_name
Trainer(cfg).fit(resume=resume)
launch(
train_with_name,
devices="auto",
main_args=("experiment_001",),
main_kwargs={"resume": None},
)
Source code in src/deepvisiontools/train/trainer.py
2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 | |
TrainerConfig(model=None, train_loader=None, valid_loader=None, model_spec=None, epochs=100, output_dir=None, devices=DevicesConfig(), optim=OptimConfig(), sched=SchedConfig(), precision=PrecisionConfig(), ema=EMAConfig(), freezing=FreezingConfig(), normalization=NormalizationConfig(), checkpoint=CheckpointConfig(), logging=LoggingConfig(), eval=EvalConfig(), find_unused_parameters=False, optuna=None)
dataclass
¶
Main configuration object consumed by Trainer.
TrainerConfig gathers runtime objects such as loaders, portable model
reconstruction information, training duration, device/DDP policy,
optimization, scheduler/warmup, precision, EMA, freezing, normalization,
checkpointing, logging, evaluation, and optional Optuna configuration.
Typical usage is to start from a registered preset, then override only what is specific to the experiment.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
`Any | None`
|
Optional runtime model object. If provided, it is
wrapped into |
None
|
train_loader
|
`Any`
|
Training dataloader. A |
None
|
valid_loader
|
`Any`
|
Validation dataloader. A |
None
|
model_spec
|
`ModelSpec | None`
|
Portable model reconstruction information. It stores the model builder key and kwargs and can also hold the runtime model object. |
None
|
epochs
|
`int`
|
Number of training epochs. Defaults to 100. |
100
|
output_dir
|
`str | None`
|
Optional run output directory. If None, deepvisiontools uses its default output/logging setup. |
None
|
devices
|
`DevicesConfig`
|
Device, strategy, |
deepvisiontools.train.trainconfig.DevicesConfig()
|
optim
|
`OptimConfig`
|
Optimizer class/spec, optimizer kwargs, weight decay, and parameter-group strategy. |
deepvisiontools.train.trainconfig.OptimConfig()
|
sched
|
`SchedConfig`
|
Scheduler class/spec, scheduler kwargs, step policy, and optional warmup. |
deepvisiontools.train.trainconfig.SchedConfig()
|
precision
|
`PrecisionConfig`
|
AMP, AMP dtype, gradient clipping, and gradient accumulation. |
deepvisiontools.train.trainconfig.PrecisionConfig()
|
ema
|
`EMAConfig`
|
Exponential moving average configuration. |
deepvisiontools.train.trainconfig.EMAConfig()
|
freezing
|
`FreezingConfig`
|
Optional temporary backbone freezing. |
deepvisiontools.train.trainconfig.FreezingConfig()
|
normalization
|
`NormalizationConfig`
|
BatchNorm / SyncBatchNorm policy. |
deepvisiontools.train.trainconfig.NormalizationConfig()
|
checkpoint
|
`CheckpointConfig`
|
Training checkpoint and portable model artifact export configuration. |
deepvisiontools.train.trainconfig.CheckpointConfig()
|
logging
|
`LoggingConfig`
|
Logging backend configuration, including MLflow and TensorBoard settings. |
deepvisiontools.train.trainconfig.LoggingConfig()
|
eval
|
`EvalConfig`
|
Validation frequency, evaluated split(s), and metric suite configuration. |
deepvisiontools.train.trainconfig.EvalConfig()
|
find_unused_parameters
|
`bool`
|
DDP option forwarded to
|
False
|
optuna
|
`Any | None`
|
Optional Optuna configuration. In normal training
it can stay None. For HPO, set it to an |
None
|
Recommended usage from a registered preset
from deepvisiontools.train import TrainerConfig
cfg = TrainerConfig.build_registered_config(
model="detector-seg",
config="detector_convnextv2-base_cascade_maskrcnn",
train_loader=trainloader,
valid_loader=validloader,
)
cfg.epochs = 50
cfg.devices.device = "cuda"
cfg.devices.strategy = "auto"
cfg.devices.num_workers = 4
cfg.devices.pin_memory = True
cfg.precision.amp = True
cfg.precision.amp_dtype = "bf16"
cfg.precision.grad_clip = 5.0
cfg.precision.accumulate_steps = 2
cfg.ema.enabled = True
cfg.ema.decay = 0.995
cfg.ema.update_every = 1
cfg.ema.warmup_steps = 100
cfg.ema.eval_with_ema = True
cfg.checkpoint.enable_checkpointing = True
cfg.checkpoint.monitor = ("valid/loss", "loss")
cfg.checkpoint.mode = "min"
cfg.checkpoint.filename = "checkpoint"
cfg.checkpoint.save_every_n_epochs = 1
cfg.checkpoint.keep_last_n = 3
cfg.checkpoint.export_model_artifact = False
cfg.checkpoint.export_when = "best"
cfg.logging.backends = ["mlflow"]
cfg.logging.mlflow_experiment_name = "deepvisiontools_experiments"
cfg.logging.mlflow_run_name = "detector_seg_baseline"
cfg.logging.log_every_n_steps = 0
cfg.eval.eval_every_n_steps = 0
cfg.eval.eval_on = "valid"
Optimizer, scheduler, warmup and LLRD
import torch
from deepvisiontools.train import TrainerConfig
from deepvisiontools.train.trainconfig import WarmupConfig
cfg = TrainerConfig.build_registered_config(
model="detector",
config="detector_convnextv2-base_vfnet",
train_loader=trainloader,
valid_loader=validloader,
)
cfg.optim.optimizer = torch.optim.AdamW
cfg.optim.optim_args = {
"lr": 2.5e-4,
"betas": (0.9, 0.999),
}
cfg.optim.weight_decay = 0.05
# Available built-in modes are "flat", "llrd", and "layer_aware_llrd".
cfg.optim.param_groups = "layer_aware_llrd"
cfg.optim.layer_decay = 0.85
cfg.sched.scheduler = torch.optim.lr_scheduler.CosineAnnealingLR
cfg.sched.scheduler_args = {"T_max": "auto", "eta_min": 1e-6}
cfg.sched.step_on = "step"
cfg.sched.warmup = WarmupConfig(
steps=500,
steps_unit="step",
ratio=1.0,
start_factor=0.001,
)
Evaluation metrics
from deepvisiontools.train.trainconfig import EvalConfig, MetricsSpec
# Detection metrics.
cfg.eval = EvalConfig(
eval_every_n_steps=0,
eval_on="valid",
metrics=MetricsSpec(
kind="bbox",
num_classes=3,
),
)
# Instance segmentation metrics.
cfg.eval.metrics = MetricsSpec(
kind="instance_mask",
num_classes=3,
)
# Semantic segmentation metrics.
cfg.eval.metrics = MetricsSpec(
kind="semantic_mask",
num_classes=3,
kwargs={"keep_per_image": True},
)
Portable custom model with ModelSpec
# my_project/custom_models.py
#
# The custom builder must be imported before loading/building the config,
# so that it is registered in MODEL_REGISTRY.
#
# IMPORTANT:
# - the builder must return a DeepVisionModel;
# - all kwargs stored in ModelSpec must be YAML-safe;
# - avoid storing runtime objects such as instantiated torch modules,
# datasets, losses or lambdas in model_spec.kwargs.
import torch
from deepvisiontools.models.base.basemodel import (
MODEL_REGISTRY,
DeepVisionModel,
)
@MODEL_REGISTRY.register("my_custom_smp")
def build_my_custom_smp(
*,
arch: str = "Unet",
encoder_name: str = "resnet18",
encoder_weights: str | None = "imagenet",
in_channels: int = 3,
num_classes: int = 1,
device: str | torch.device | None = None,
use_amp: bool | None = None,
) -> DeepVisionModel:
from deepvisiontools.models import ModelFactory
model = ModelFactory(
name="smp",
arch=arch,
encoder_name=encoder_name,
encoder_weights=encoder_weights,
in_channels=in_channels,
num_classes=num_classes,
device=device,
use_amp=use_amp,
)
# Ensure exported artifacts and TrainerConfig YAML can rebuild this
# exact model through the registered custom builder.
model.set_export_spec(
"my_custom_smp",
{
"arch": arch,
"encoder_name": encoder_name,
# Usually set to None for artifact reload because weights
# will be loaded from the saved state_dict.
"encoder_weights": None,
"in_channels": in_channels,
"num_classes": num_classes,
"device": device,
"use_amp": use_amp,
},
)
return model
# train.py
# Import the module once so @MODEL_REGISTRY.register(...) is executed.
import my_project.custom_models # noqa: F401
import torch
from deepvisiontools.train import Trainer, TrainerConfig
from deepvisiontools.train.trainconfig import (
ModelSpec,
OptimConfig,
SchedConfig,
)
cfg = TrainerConfig(
train_loader=trainloader,
valid_loader=validloader,
model_spec=ModelSpec(
builder="my_custom_smp",
kwargs={
"arch": "Unet",
"encoder_name": "resnet18",
"encoder_weights": "imagenet",
"in_channels": 3,
"num_classes": 1,
"device": "cuda",
"use_amp": True,
},
),
epochs=30,
)
cfg.optim = OptimConfig(
optimizer=torch.optim.AdamW,
optim_args={"lr": 1e-4},
weight_decay=1e-4,
)
cfg.sched = SchedConfig(
scheduler=None,
scheduler_args={},
step_on="epoch",
)
Trainer(cfg).fit()
The exported YAML will contain a portable model block similar to:
trainer:
model_spec:
builder: my_custom_smp
kwargs:
arch: Unet
encoder_name: resnet18
encoder_weights: imagenet
in_channels: 3
num_classes: 1
device: cuda
use_amp: true
To reload this YAML later, import the custom builder module before
calling TrainerConfig.from_yaml(...):
import my_project.custom_models # noqa: F401
from deepvisiontools.train import TrainerConfig
cfg = TrainerConfig.from_yaml(
"my_training_config.yaml",
train_loader=trainloader,
valid_loader=validloader,
)
Normalization, freezing and DDP
# Device strategy:
# - "auto": single process unless launched with torchrun/launch(...).
# - "single": force single-device training.
# - "ddp": require distributed context.
cfg.devices.device = "cuda"
cfg.devices.strategy = "auto"
# Required by some DDP models with conditional branches.
cfg.find_unused_parameters = False
# BatchNorm policy.
cfg.normalization.policy = "auto"
cfg.normalization.freeze_affine = True
cfg.normalization.freeze_running_stats = True
cfg.normalization.verbose = True
# Temporarily freeze backbone optimizer param groups.
cfg.freezing.freeze_epochs = 2
cfg.freezing.backbone_group_name = "backbone"
Optuna HPO entrypoint
from deepvisiontools.train.optuna_wrapper import (
OptunaConfig,
SearchSpaceSpec,
run_optuna,
)
cfg.optuna = OptunaConfig(
enabled=True,
study_name="my_study",
storage="my_study.db",
n_trials=20,
search_space=[
SearchSpaceSpec(
name="lr",
kind="float",
path="optim.optim_args.lr",
low=1e-5,
high=1e-3,
log=True,
),
SearchSpaceSpec(
name="accumulate_steps",
kind="categorical",
path="precision.accumulate_steps",
choices=[1, 2, 4],
),
],
)
study = run_optuna(cfg)
ensure_model_spec_from_model()
¶
If a DeepVisionModel exists in model_spec and has export_spec(), populate model_spec/checkpoint hints.
Source code in src/deepvisiontools/train/trainconfig.py
1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 | |
freeze_initial_snapshot()
¶
Freeze a stable snapshot for reproducible export.
Source code in src/deepvisiontools/train/trainconfig.py
1648 1649 1650 1651 1652 1653 1654 1655 1656 | |
from_yaml(path, *, train_loader, valid_loader=None, model=None)
classmethod
¶
Load portable YAML and rebuild a TrainerConfig.
You MUST pass loaders. You MAY pass model to override; otherwise if model_spec exists in YAML we rebuild from it.
Source code in src/deepvisiontools/train/trainconfig.py
1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 | |
available_configs()
classmethod
¶
List all registered default TrainerConfig presets.
Layout matches ModelFactory configs
dtype: model: - "name": description
Source code in src/deepvisiontools/train/trainconfig.py
1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 | |
build_registered_config(*, model, config, train_loader, valid_loader=None, dtype=None, model_override=None)
classmethod
¶
Build a TrainerConfig from a registered preset.
???+ example "Usage":
# example usage
Config = TrainerConfig.build_registered_config(
model="detector-seg",
config="detector_convnextv2-base_cascade_maskrcnn",
train_loader=trainloader,
valid_loader=validloader,
)
Source code in src/deepvisiontools/train/trainconfig.py
1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 | |
ModelSpec(builder=None, kwargs=None, model=None)
dataclass
¶
Portable model reconstruction information + optional cached runtime model.
Note
- builder/kwargs are the portable representation (what goes to YAML)
- model is a runtime-only object (never exported in portable=True)
- model is a property so that setting it auto-refreshes builder/kwargs from DeepVisionModel.export_spec() when possible.
- If model is None at init: build from builder/kwargs (must be set).
- If model is provided at init and it's DeepVisionModel: override builder/kwargs from model.export_spec() when available.
Source code in src/deepvisiontools/train/trainconfig.py
307 308 309 310 311 312 313 314 315 316 317 318 319 320 | |
model_obj
property
¶
Internal getter with a clear name.
ImportSpec(target, kwargs=dict())
dataclass
¶
Main class to make config exportable/readable from yaml.
DevicesConfig(device=None, strategy='auto', num_workers=None, pin_memory=None, ddp_timeout_seconds=None)
dataclass
¶
Device / dataloader runtime hints.
Note
- device=None + strategy="auto": choose "cuda" if available, else "cpu" with warning.
- strategy="auto" matches trainer logic (DDP if >1 GPU).
- ddp_timeout_seconds controls the distributed process-group timeout for
DDP collectives. If None, DDPStrategy reads DVT_DDP_TIMEOUT_SECONDS
when present, otherwise it uses its internal default.
OptimConfig(optimizer=None, optim_args=dict(), param_groups='flat', weight_decay=None, layer_decay=None)
dataclass
¶
Optimizer configuration. This configuration allows to generate torch.optim objects from yaml and/or export them to yaml. Handles LLRD strategies.
???+ note "Note":
Allowed values for optimizer:
- ImportSpec (portable)
- torch optimizer class/type (portable if importable, e.g. torch.optim.AdamW)
Disallowed:
- optimizer instances (runtime-only, NOT portable)
- lambdas / closures / non-importable callables (NOT portable)
LLRD :
- learning rate layer decay is an excellent optimization strategy when dealing with large backbones. It assigns decreasing learning rate to all blocks in the model.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
optimizer
|
`Optional[Any]`
|
use optim type (python obj like torch.optim.Adamw) or |
None
|
optim_args
|
`Dict[str, Any]`
|
all kwargs style dict you want to feed the optimizer with. |
dict()
|
param_groups
|
`str | Callable`
|
"flat" or "llrd" or user provided callable that build param groups from model. llrd will call deepvisiontools internal llrd strategy to compute param groups. |
'flat'
|
weight_decay
|
`Optional[float]`
|
optional weight decay (regularization) for optimizer |
None
|
layer_decay
|
Optional[float]
|
parameter used in llrd strategy for internal llrd strategy. |
None
|
get_optimizer_spec()
¶
Return an ImportSpec (portable), coercing from a class/type when needed. Raises if optimizer is missing or not portable.
Source code in src/deepvisiontools/train/trainconfig.py
671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 | |
SchedConfig(scheduler=None, scheduler_args=dict(), step_on='epoch', warmup=None)
dataclass
¶
Optim scheduler configuration
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scheduler
|
`Optional[ImportSpec]`
|
siùmilar to optimizer, needs to be an importable object. Defaults to None (lr won't change). |
None
|
scheduler_args
|
`Optional[Dict[str, Any]]`
|
args used in scheduler. Defaults to None. |
dict()
|
step_on
|
`Literal["epoch", "step", "batch"]`
|
when lr is updated by scheduler. Defaults to epoch |
'epoch'
|
warmup
|
`Optional[WarmupConfig]`
|
if warmup is required. Defaults to None. |
None
|
get_scheduler_spec()
¶
Return an ImportSpec (portable), coercing from a class/type when needed.
Raises if the scheduler is not portable or was assigned to the wrong field.
Source code in src/deepvisiontools/train/trainconfig.py
812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 | |
build_scheduler(optimizer)
¶
Validate/coerce the scheduler and instantiate it.
Calling get_scheduler_spec() first ensures:
- class/type inputs are converted to ImportSpec for stable export
- invalid assignments fail early with a helpful message
Source code in src/deepvisiontools/train/trainconfig.py
914 915 916 917 918 919 920 921 922 923 924 925 926 927 | |
WarmupConfig(kind='linear', steps=None, epochs=None, steps_unit='step', ratio=1.0, start_factor=0.001)
dataclass
¶
Warmup configuration.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
`Literal["linear", "constant"]`
|
Default to "linear". |
'linear'
|
steps
|
`Optional[int]`
|
Default to None |
None
|
epochs
|
`Optional[float]`
|
Default to None |
None
|
steps_unit
|
`Literal["step", "epoch"]`
|
Default to"step" |
'step'
|
ratio
|
`float`
|
linear warmup starts from |
1.0
|
start_factor
|
`float`
|
Defaults to 0.001 |
0.001
|
???+ note Note:
Supports 2 ways to specify duration:
- steps: number of optimizer steps (batch-based warmup)
- epochs: number of epochs (converted to steps by Trainer using len(train_loader))
A "switch" is provided via steps_unit:
- steps_unit="step" -> interpret steps as optimizer steps (default)
- steps_unit="epoch" -> interpret steps as epochs (converted into epochs)
so WarmupConfig(steps=1, steps_unit="epoch") == WarmupConfig(epochs=1)
- Trainer will compute warmup_steps as:
- if steps is not None: warmup_steps = steps
- elif epochs is not None: warmup_steps = epochs * len(train_loader)
- So do NOT set both steps and epochs (we normalize to one).
PrecisionConfig(amp=None, amp_dtype='bf16', grad_clip=None, accumulate_steps=1)
dataclass
¶
Torch AMP and gradient precision configuration.
Automatic mixed precision is strongly recommended when supported: it is usually faster, uses less CUDA memory, and often has no accuracy trade-off. This config also controls gradient clipping and gradient accumulation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
amp
|
`bool | None`
|
Enable or disable AMP. If None, the Trainer falls
back to the global |
None
|
amp_dtype
|
`Literal["fp16", "bf16", "fp32"]`
|
Precision dtype used by AMP.
Defaults to |
'bf16'
|
grad_clip
|
`float | None`
|
Optional gradient clipping value. Typical values are in the 1-10 range for very large models. Defaults to None. |
None
|
accumulate_steps
|
`int`
|
Number of batches to accumulate before optimizer update, scheduler step, and EMA update. Useful to emulate a larger effective batch size when limited by hardware memory. Defaults to 1. |
1
|
EMAConfig(enabled=True, decay=0.995, update_every=1, warmup_steps=0, eval_with_ema=True)
dataclass
¶
Exponential moving average configuration.
EMA keeps a smoothed copy of model weights during training. After each optimizer step, the EMA state is updated from the current model weights. EMA weights are often more stable for validation and deployment, especially for noisy training setups such as detection and instance segmentation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
enabled
|
`bool`
|
Whether to enable EMA tracking. Defaults to True. |
True
|
decay
|
`float`
|
EMA decay factor. Typical values range from 0.99 for short trainings to 0.9998 for long trainings. Defaults to 0.995. |
0.995
|
update_every
|
`int`
|
Update EMA every N optimizer steps. Defaults to 1. |
1
|
warmup_steps
|
`int`
|
Number of optimizer steps used to ramp EMA decay at the beginning of training. Defaults to 0. |
0
|
eval_with_ema
|
`bool`
|
Whether to temporarily swap EMA weights during validation/evaluation. Defaults to True. |
True
|
FreezingConfig(freeze_epochs=0, backbone_group_name='backbone', freeze_backbone=False, freeze_bn=False)
dataclass
¶
If you need to freeze backbone at begining of training
NormalizationConfig(policy='auto', freeze_affine=True, freeze_running_stats=True, verbose=True)
dataclass
¶
BatchNorm / SyncBatchNorm policy. Used in DDP and small batches to freeze batch norm layers / sync BN.
Policies¶
-
"auto": Safe default.
- if no BN is present -> do nothing
- if BN is present and local micro-batch <= 1 -> freeze BN
- otherwise -> do nothing This intentionally does NOT auto-convert to SyncBN.
-
"none": Never touch normalization layers.
-
"freeze_bn": Freeze BatchNorm / SyncBatchNorm affine params (optional) and keep running stats frozen during train epochs.
-
"sync_bn": Convert BatchNorm{1,2,3}d to SyncBatchNorm, but only when DDP is active on CUDA. Otherwise the request is ignored with a logged summary.
-
"sync_or_freeze_bn": If DDP+CUDA is active -> convert to SyncBN. Otherwise -> freeze BN.
Notes¶
- LayerNorm / GroupNorm / InstanceNorm are never modified by this policy.
- "freeze BN" is implemented by:
- setting affine params requires_grad=False (if freeze_affine=True)
- forcing BN modules to eval() whenever the trainer enters train mode (if freeze_running_stats=True)
CheckpointConfig(output_dir=None, enable_checkpointing=True, monitor=('valid/loss', 'loss'), mode='min', filename='checkpoint', save_every_n_epochs=1, keep_last_n=3, export_model_artifact=False, export_when='best', model_builder=None, model_kwargs=None)
dataclass
¶
Handles checkpointing and optional model artifact export.
Checkpointing is used to save restartable training states and to keep track of the best model according to a monitored metric.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
output_dir
|
`str | None`
|
Optional checkpoint output directory. If None, the Trainer uses the default deepvisiontools output setup. |
None
|
enable_checkpointing
|
`bool`
|
Master switch for checkpointing and model artifact export. If False, training and logging still run normally, but checkpoint/model export phases are skipped. |
True
|
monitor
|
`tuple[str, str]`
|
Metric to monitor as
|
('valid/loss', 'loss')
|
mode
|
`Literal["min", "max"]`
|
Direction used to decide whether a model
is better. Use |
'min'
|
filename
|
`str`
|
Prefix used for checkpoint filenames. Defaults to
|
'checkpoint'
|
save_every_n_epochs
|
`int`
|
Periodic checkpoint interval in epochs. If 0, no periodic checkpoint is written. Defaults to 1. |
1
|
keep_last_n
|
`int`
|
Number of most recent periodic checkpoints to keep. Older periodic checkpoints are removed. Defaults to 3. |
3
|
export_model_artifact
|
`bool`
|
Whether to export a portable model artifact in addition to training checkpoints. Defaults to False. |
False
|
export_when
|
`Literal["best", "all"]`
|
Controls when model artifacts are exported: only for the best model or at every export opportunity. |
'best'
|
model_builder
|
`str | None`
|
Optional model builder key saved as a restore
hint. Usually inferred automatically from |
None
|
model_kwargs
|
`dict[str, Any] | None`
|
Optional model builder kwargs saved
as restore hints. Usually inferred automatically from |
None
|
Note
enable_checkpointing=Falseis the master switch. When disabled, the training loop still runs normally and MLflow/TensorBoard logging still works, but checkpoint/model export phases are skipped.- This is especially useful for large Optuna studies where you only want metrics/losses/logging without writing restart artifacts.
LoggingConfig(backends='mlflow', tensorboard=dict(), mlflow=dict(), log_every_n_steps=0, mlflow_experiment_name=None, mlflow_run_name=None, wandb_project=None, wandb_run_name=None)
dataclass
¶
Monitoring configuration.
MLflow can already consume arbitrary keys from mlflow, but exposing the most
common ones explicitly makes the Trainer config much cleaner and safer.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
backends
|
str | collections.abc.Sequence[str]
|
Logging backend(s), e.g. "mlflow", "tensorboard", or both. |
'mlflow'
|
tensorboard
|
dict[str, typing.Any]
|
Extra kwargs forwarded to TensorBoard logger. |
dict()
|
mlflow
|
dict[str, typing.Any]
|
Extra kwargs forwarded to MLflowLogger. |
dict()
|
log_every_n_steps
|
int
|
Logging period hint used by hooks. |
0
|
mlflow_experiment_name
|
str | None
|
Optional explicit MLflow experiment name. |
None
|
mlflow_run_name
|
str | None
|
Optional explicit MLflow run name. |
None
|
wandb_project
|
str | None
|
Reserved/legacy field. |
None
|
wandb_run_name
|
str | None
|
Reserved/legacy field. |
None
|
EvalConfig(eval_every_n_steps=0, eval_on='valid', metrics=None)
dataclass
¶
Evaluation configuration.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
eval_every_n_steps
|
`int`
|
Optional step-based evaluation period. If 0, evaluation is performed once per epoch. Defaults to 0. |
0
|
eval_on
|
`Literal["valid", "train", "valid_and_train"]`
|
Dataset split(s)
used for evaluation. Evaluating on train during training is possible
but slower. If |
'valid'
|
metrics
|
`MetricsSpec | None`
|
Portable metric suite configuration. If None, no metrics factory is built. Defaults to None. |
None
|
MetricsSpec(kind=None, num_classes=None, target=None, kwargs=dict())
dataclass
¶
Main metric setup config class used in EvalConfig. Two modes: 1) kind-based: kind in {"bbox","instance_mask","semantic_mask"} + num_classes 2) target-based: import target "module:qualname" + kwargs (if having special callables). Note that this second mode had not been widely tested yet.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
`Optional[str]`
|
str val from "detection", "semantic", "instance". Setup standard metric suites in deepvisiontools |
None
|
num_classes
|
`Optional[int]`
|
if you want to override, but dvt computes class from current() when needed. Defaults to None |
None
|
target
|
Optional[str]
|
for specifi metrics callables. |
None
|
kwargs
|
Optional[Dict[str, typing.Any]]
|
args for your specific metric |
dict()
|
build_factory()
¶
Return a zero-arg factory that builds the metric suite object.
Rules: - If target is set: import + kwargs - Else: kind-based factory, with num_classes taken from: - self.num_classes if provided - else current().data_* defaults depending on kind
Source code in src/deepvisiontools/train/trainconfig.py
1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 | |