Files
parking_solution/apps/trainer/README.md
T
julian f7a262ac9a
Build & push images / images (push) Successful in 6m31s
feat(trainer): phase-B body-type classifier — trainer job on the collector host + the classifier stage on the booth
apps/trainer (parking-trainer): inspect / train / evaluate / publish. Reads the wash
collector's SQLite + crops read-only off its volume; time split (validation = newest
slice); thin classes dropped; damped class weights; `features` mode (frozen ImageNet
backbone, on-disk feature cache, seconds to retrain) and `finetune` mode (light
augmentation). CPU-only torch from PyTorch's wheel index. ONNX export checked against
the torch model; NO model file below the validation floor (exit 3, report still written);
exit 2 = not enough labels. `evaluate` scores a shipped model on labels reviewed after
training + the unlabelled pile; `publish` PUTs a version folder to a Gitea generic package.
Light core deps; the `train` extra is heavy — CI syncs without it, torch tests skip.

apps/vision: BodyTypeClassifier (bodytype.onnx + sidecar = the preprocessing contract:
crop margin, input size, RGB 0-255, normalisation inside the graph) and
RefinedVehicleDetector over YOLOX — refines only `car` or a class the classifier trained
on, min-confidence, `detector_class` on the result; path set but no file = phase B off
without an error; a broken file is a health detail. models/bodytype.version (tracked,
empty) pins the published version the Dockerfile fetches at build (BuildKit secret;
a pin that cannot be fetched fails the build). Verified: a trainer model gives identical
probabilities inside the vision service; both images built and smoke-tested.

Delivery: parking-trainer image in build-images.yml, the `trainer` compose profile on the
collector stack (CPU, read-only data, TRAINER_OUT), commented TRAINER_OUT/PUBLISH_TOKEN in
the wash-collector stack, .dockerignore for both Python contexts, trainer deps synced in CI.

Wiki: bodytype-classifier-training rewritten as built (+ one fleet model not per site,
secrets/access, where the crops live), opencv-anpr-service §Phase B, vision-review-outbox,
vision-service-packaging, fleet-deployment-komodo, index, log.

Claude-Session: https://claude.ai/code/session_01FWncR69HgGPuei1dLrW3cU
2026-09-07 11:14:50 +02:00

37 lines
1.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# parking-trainer
The phase-B **body-type classifier** job. Reads the wash collector's volume
(`collector.sqlite` + `crops/`), trains a classifier on the reviewer's labels, and writes a
versioned model folder the vision image bakes in — or refuses when validation is below the
floor. Design and decisions: `wiki/decisions/bodytype-classifier-training.md`.
```
parking-trainer inspect --data /data # what a run would train on
parking-trainer train --data /data --out /out # features mode (minutes)
parking-trainer train --mode finetune --epochs 12 ... # full fine-tune (about an hour on 4 cores)
parking-trainer evaluate --model /out/<version>/bodytype.onnx --data /data
parking-trainer publish /out/<version> --url https://git.infra.msai.al/api/packages/mca/generic/parking-bodytype
```
Exit codes: `0` model written · `2` not enough labels · `3` below the floor (report written,
no model) · `1` other.
A passing run writes `<out>/<version>/`:
| file | what |
| --- | --- |
| `bodytype.onnx` | the classifier; input `image` = RGB float32 0–255 `[N,3,S,S]`, output `logits` `[N,K]`; normalisation is inside the graph |
| `bodytype.json` | sidecar: version, class list (in vocabulary order), input size, crop margin, backbone, mode, label counts, validation metrics |
| `report.md` | the human report: accuracy, per-class recall/precision, confusion matrix, dropped classes, loss weights |
| `metrics.json` | the same numbers, machine-readable |
On the reviewer's host (the `wash-collector` stack):
```
docker compose -f docker-compose.collector.yml --profile train run --rm trainer inspect
docker compose -f docker-compose.collector.yml --profile train run --rm trainer train --min-accuracy 0.85
```
Local dev: `uv sync --extra train` (CPU torch, ~200 MB), `uv run pytest -q`. The test suite
runs without the extra (torch tests skip), matching CI.