DetectorSpec
Use a detector spec when you want to express intent instead of wiring every component field manually.
It is the recommended surface for new experiments.
from simpledet.suite import build_detector, build_neck
spec = build_detector(
"fcos",
encoder="convnext_tiny.in12k_ft_in1k",
neck=build_neck(name="FPN", out_channels=192, num_outs=4),
num_classes=5,
in_channels=3,
)
In this example, architecture and num_classes describe the task,
encoder describes the backbone source, neck adapts features across scales,
and the head is selected automatically from the detector family.
Compile to a native build plan
from simpledet.suite import compile_native_detector_plan
native_plan = compile_native_detector_plan(spec)
The planner fills runtime-facing sections such as encoder, neck, head, and architecture family metadata.
Compile when you need to inspect what the native runtime will assemble.
For most user workflows, treat this plan as a read-only artifact after compilation.
Custom backbones
from simpledet.suite import EncoderSpec
custom_encoder = EncoderSpec(
source="config",
name="custom-backbone",
backbone_cfg={"type": "MyBackbone", "depth": 18},
feature_channels=(64, 128, 256, 512),
)
Use this path when the backbone is not coming from timm.
Runtime config
ProjectConfig and the direct runtime helpers own dataset paths, workdir layout, resize, batch size, optimizer settings, checkpoints, logging, and stage selection. The native runtime consumes the detector spec and compiled build plan directly.
Put it in the detector spec
Architecture, backbone, neck, head, decoder, feature interfaces, class count.
Put it in the runtime config
Dataset paths, image size, batch size, optimizer settings, checkpoints, logging, evaluators.
Use raw overrides sparingly
Only when the public builders do not yet expose a field you genuinely need to change.