Train a model
Freeze reviewed labels into an export, then train an object detection (RF-DETR, YOLOX), segmentation, keypoint or classification model on a managed GPU.
On this page
A model trains on an export: a frozen copy of the dataset’s labels and splits. Review drafted labels before you export.
Export, price, train
from pictograph import Client, TrainingQuote, TrainingRun
client = Client()
client.exports.create(
dataset="road-signs",
name="road-signs-v1",
format="pictograph",
include_images=True,
wait=True,
)
quote: TrainingQuote = client.training.quote(
dataset="road-signs",
export="road-signs-v1",
pipeline_type="yolox",
gpu_type="auto",
)
print(quote.gpu_type, quote.estimate.total_micro_usd, quote.can_start, quote.blocking)
run: TrainingRun = client.training.create(
dataset="road-signs",
export="road-signs-v1",
pipeline_type="yolox",
name="road-signs-detector",
gpu_type="auto",
config={"epochs": 50, "batch_size": 16},
)
if run.model_id:
client.models.download(
model=run.model_id,
output_path="./yolox.onnx",
)
pictograph exports create road-signs --name road-signs-v1 -f pictograph --include-images
pictograph train quote road-signs road-signs-v1 --pipeline yolox --gpu auto
pictograph train start road-signs road-signs-v1 --pipeline yolox --gpu auto --name road-signs-detector
The quote prices the run and runs a start’s checks (blocking says why it can’t start).
create waits for the run; with wait=False it returns at once, and
client.training.wait_for_completion(run=run.id) waits later
(arguments).
Choose a pipeline
| Task | pipeline_type |
|---|---|
| Boxes | yolox or rfdetr_detection (which one?) |
| Instance masks | rfdetr_segmentation |
| Semantic masks | sm_pytorch |
| Pose (keypoints) | rfdetr_keypoint |
| Image labels | classification |
There’s no minimum image count; classification needs two classes, every other pipeline one.
GPU tiers and prices: Training.
Hyperparameters
config keys depend on the pipeline. Unknown keys are ignored; a key you leave out takes the
app’s default.
| Key | Type | Typical value |
|---|---|---|
epochs |
int | 30 to 100 |
batch_size |
int | 8, 16 or 32 |
learning_rate |
float | 0.001 to 0.01 |
model_size |
str | One of the pipeline’s sizes (below) |
image_width, image_height |
int | Input size in pixels |
| Pipeline | model_size values |
Default size | Default input |
|---|---|---|---|
yolox |
nano, tiny, s, m, l, x |
m |
640 px |
rfdetr_detection |
nano, small, medium, large |
medium |
576 px |
rfdetr_segmentation |
nano, small, medium, large, xlarge, 2xlarge |
medium |
432 px |
rfdetr_keypoint |
preview |
preview |
576 px |
sm_pytorch |
- | - | 512 px |
classification |
- | - | 224 px (EfficientNet B1 to B4: 240, 260, 300, 380 px) |
Instead of a size, sm_pytorch takes an architecture (default Segformer) and an encoder
(default efficientnet-b1), and classification takes a backbone (default resnet18).
How images are split
Training uses the export’s train, val and test splits. An image with no split gets one when the run starts, from the dataset’s split percentages (70 / 20 / 10 by default), drawn per cluster of its embedding map so every visual group reaches all three splits (at random without a map).
- Splits you assigned never change.
- An image that is a class’s only possible training image goes to train.
- If filling would leave validation empty, those images split at random; below three images, everything trains.
- The dataset keeps the filled splits, and the run’s
warningsincludesplits_assigned.
Classes a model cannot learn
Without classes in config, a run trains the dataset’s classes that the export holds and the
pipeline learns from, in the dataset’s order:
| Pipeline | Learns from |
|---|---|
yolox, rfdetr_detection |
Boxes and polygons (a rotated box trains as its upright box) |
rfdetr_segmentation, sm_pytorch |
Polygons |
rfdetr_keypoint |
Keypoints |
classification |
Image tags |
A class trains only if its train split holds that kind of annotation. Otherwise it is left
out, and the run’s warnings say which and why:
run = client.training.get(run=run.id)
for warning in run.warnings or []:
print(warning.code, warning.message)
# classes_not_trained 1 class left out of this model: 'pallet_bbox' has no polygons
# this model can train on. The model predicts only the classes it trained on.
reason |
Meaning |
|---|---|
no_training_data |
Nothing the pipeline learns from, anywhere in the export |
not_in_train_split |
Only in the val or test splits you assigned |
The model’s class_mapping lists only the classes it trained on. A run that can train none of
its classes is refused (400, no_trainable_classes); a keypoint run is refused
(untrainable_classes) if any selected class can’t train.
Keypoint (pose) training
rfdetr_keypoint learns one pose per object from keypoint annotations:
- Group the joints. A pose is every joint that shares an
instance_id; the editor assigns it per class as you draw. A point with noinstance_idtrains as a one-joint object. - Name left and right.
left_*andright_*joints swap when an image is flipped; a joint with no counterpart flips onto itself. - Boxes come from the joints. An object with joints still missing trains as a detection.
run = client.training.create(
dataset="gymnasts",
export="gymnasts-v1",
pipeline_type="rfdetr_keypoint",
name="gymnast-pose",
gpu_type="a10g",
config={"epochs": 30},
)
print(run.metrics["OKS"])
Predictions are keypoint annotations with an instance_id, like hand-drawn poses. Accuracy is
OKS (object keypoint similarity), which doesn’t compare with mAP.
Errors
A failed run has status="failed" and an error_message. Every error a start can raise:
Training. What a run costs:
Training.
Next
- Evaluate the model on a held-out export
- Deploy it behind a URL, or run it locally