1. Install and run doctor
Install the CPU runtime extra first. It gives the quickstart the native PyTorch, Lightning, COCO metric, and image-loading dependencies used by training, testing, and inference.
python -m pip install 'simpledet[cpu]'
python -m simpledet doctor --workdir ./runs/quickstart
When working from a checkout, use python -m pip install -e '.[cpu]' instead. doctor reports missing optional extras as warnings unless you add --strict, so it is useful before deciding whether you need extras such as timm, geo, or plots.
2. Create a tiny local COCO fixture
This fixture exists only to verify the wiring. It creates two small RGB PNG files and three COCO-style annotation files under data/quickstart-coco, so the commands do not depend on private machine paths or external datasets.
python - <<'PY'
import json
import struct
import zlib
from pathlib import Path
root = Path("data/quickstart-coco")
(root / "imgs").mkdir(parents=True, exist_ok=True)
(root / "Annotations").mkdir(parents=True, exist_ok=True)
def chunk(kind, payload):
return (
struct.pack(">I", len(payload))
+ kind
+ payload
+ struct.pack(">I", zlib.crc32(kind + payload) & 0xFFFFFFFF)
)
def write_png(path, width=64, height=64):
row = b"\x00" + (b"\x40\x90\xe0" * width)
raw = row * height
path.write_bytes(
b"\x89PNG\r\n\x1a\n"
+ chunk(b"IHDR", struct.pack(">IIBBBBB", width, height, 8, 2, 0, 0, 0))
+ chunk(b"IDAT", zlib.compress(raw))
+ chunk(b"IEND", b"")
)
for name in ("sample_0001.png", "sample_0002.png"):
write_png(root / "imgs" / name)
def payload(image_id, file_name):
return {
"images": [{"id": image_id, "file_name": file_name, "width": 64, "height": 64}],
"annotations": [{
"id": image_id,
"image_id": image_id,
"category_id": 1,
"bbox": [12, 10, 28, 30],
"area": 840,
"iscrowd": 0,
}],
"categories": [{"id": 1, "name": "wake"}],
}
splits = {
"train_annotations.json": payload(1, "sample_0001.png"),
"val_annotations.json": payload(2, "sample_0002.png"),
"test_annotations.json": payload(2, "sample_0002.png"),
}
for filename, split_payload in splits.items():
(root / "Annotations" / filename).write_text(json.dumps(split_payload, indent=2))
PY
3. Define a RetinaNet detector
A DetectorSpec is the high-level model description. The suite registry resolves the RetinaNet alias, the ResNet backbone, and the native head and neck wiring before training starts.
python - <<'PY'
from pprint import pprint
from simpledet.suite import build_detector, build_neck, compile_native_detector_plan
spec = build_detector(
"retinanet",
backbone="resnet18",
neck=build_neck("FPN", out_channels=128, num_outs=4),
num_classes=1,
in_channels=3,
pretrained=False,
)
plan = compile_native_detector_plan(spec)
print(spec.family)
pprint(plan.encoder)
pprint(plan.neck)
pprint(plan.head)
PY
Expected output shape:
dense
ComponentPlan(kind='encoder', type='resnet18', ...)
ComponentPlan(kind='neck', type='FPN', ...)
ComponentPlan(kind='head', type='RetinaHead', ...)
The quickstart disables pretrained weights so the first run does not download external checkpoints. For real experiments, keep the same shape and change the detector, backbone, class count, and dataset paths.
4. Write the dataset and runtime config
The config keeps the detector definition, dataset paths, runtime knobs, optimizer, checkpoint path, and export intent in one repeatable file.
cat > quickstart.toml <<'TOML'
stages = ["build", "train", "test"]
workdir = "runs/quickstart"
seed = 71
[detector]
name = "retinanet"
num_classes = 1
backbone = "resnet18"
pretrained = false
[detector.neck]
name = "FPN"
out_channels = 128
num_outs = 4
[dataset]
format = "coco"
root = "data/quickstart-coco"
train = "Annotations/train_annotations.json"
val = "Annotations/val_annotations.json"
test = "Annotations/test_annotations.json"
data_prefix = "imgs/"
classes = ["wake"]
in_channels = 3
tif_channels_to_load = [1, 2, 3]
[runtime]
resize = 128
batch_size = 1
max_epochs = 1
num_workers = 0
accelerator = "cpu"
devices = 1
[optimizer]
name = "AdamW"
learning_rate = 0.001
[scheduler]
name = "step"
step_size = 1
gamma = 0.5
[checkpoint]
path = "runs/quickstart/checkpoints/last.ckpt"
resume = false
[export]
formats = ["json"]
TOML
python -m simpledet --project-validate quickstart.toml
5. Train, test, and infer
These are the three operational commands for the quickstart. Run them in order: the test and inference stages load runs/quickstart/checkpoints/last.ckpt, which the train command writes.
python -m simpledet --project-run quickstart.toml --stages build train
python -m simpledet --project-run quickstart.toml --stages test
python -m simpledet --project-run quickstart.toml --stages infer
Expected artifacts:
runs/quickstart/checkpoints/last.ckpt
native-manifest.json
native-metrics.json
run-manifest.json
- prediction records and metric summaries printed by the CLI
6. Swap in your dataset
Use the same config shape for a real dataset. The important contract is local and explicit: SimpleDet validates the root, image directory, and train, validation, and test annotation files before it creates the workdir or enters the native runtime.
dataset_root/
imgs/
image_0001.png
image_0002.png
Annotations/
train_annotations.json
val_annotations.json
test_annotations.json
Replace data/quickstart-coco, classes, and num_classes together. Keep pretrained = false for fully offline smoke runs; choose a pretrained backbone only when the environment can download or already has the weights.