SimpleDet Docs

Configuration guide

The most important configuration idea in this repo is responsibility: model structure belongs in the detector spec, runtime behavior belongs in the project/runtime config, and native planning fills the low-level component wiring.

Use this page to understand what belongs in a detector spec, what belongs in the runtime config, and what should stay out of both.

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.

Native backbone aliases

from simpledet.suite import build_backbone, build_detector

backbone = build_backbone("resnet50", out_indices=(1, 2, 3, 4))
spec = build_detector(name="retinanet", backbone="resnet50", num_classes=5)
module = build_detector(name="retinanet", backbone=backbone, num_classes=5, build=True)

Alias-backed backbones carry stage-channel metadata into the native build plan. build_detector(...) returns a spec by default; use build=True only when you want the native module immediately. Native assembly uses that metadata to adapt downstream channel settings for concise names such as resnet50, ConvNeXt, Swin Transformer, and ViT without manual channel tables.

timm_backbone = build_backbone(
    "timm:resnet18",
    pretrained=False,
    out_indices=(1, 2, 3, 4),
)

Prefix a TIMM model name with timm: when you want runtime feature metadata discovered from simpledet[timm].

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 owns dataset paths, workdir layout, resize, batch size, optimizer settings, scheduler settings, checkpoints, export metadata, logging, seed, and stage selection for project runs. The direct runtime helpers expose the same dataset, workdir, optimizer, scheduler, checkpoint, and seed knobs for single training or inference calls. The native runtime consumes the detector spec and compiled build plan directly.

stages = ["build", "train", "test"]
workdir = "/tmp/simpledet-runs"
seed = 71

[detector]
name = "retinanet"
num_classes = 1
backbone = "resnet18"

[dataset]
root = "/data/project"
classes = ["wake"]

[runtime]
batch_size = 2
max_epochs = 12

[optimizer]
name = "AdamW"
learning_rate = 0.001

[scheduler]
name = "step"
step_size = 2
gamma = 0.5

[checkpoint]
resume = false

[export]
formats = ["json"]

detector_spec and optimization remain accepted aliases for older project files, but new files should prefer detector, optimizer, and scheduler. Relative annotation paths under [dataset] resolve from root. A missing dataset root, image directory, or annotation file fails validation before the runner creates the workdir or writes run-manifest.json.

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.