Skip to content

V0.6.0 dev - #37

Open
hugobaudchon wants to merge 63 commits into
mainfrom
v0.6.0-dev
Open

hugobaudchon wants to merge 63 commits into
mainfrom
v0.6.0-dev

Conversation

@hugobaudchon

Copy link
Copy Markdown
Owner

No description provided.

Replace the duplicated literal {CLASSIFIER_SCORE, CLASSIFIER_CLASS,
CLASSIFIER_SCORES} in the ComponentResult with the already-declared
self.produces_columns attribute, so the produced columns have a single
source of truth (BASE_PRODUCES_COLUMNS).
Eliminate duplicated checkpoint-loading logic across model wrappers:

- Add two shared loaders to models/utils.py:
  - load_state_dict_with_key_repair: resolve HF URL, load state dict,
    retry with 'model.'/'module.' prefix repair on key mismatch
    (detector/classifier; replaces the verbatim-duplicated HF block and
    try_rename_state_dict_keys_with_model that lived in both bases).
  - load_finetuned_checkpoint: resolve HF URL (revision-aware), unwrap a
    'model_state_dict' training-checkpoint wrapper, load with a given
    strict flag (SAM2/SAM3).
- detector_base and classifier_base now delegate to the shared loader;
  removed their local try_rename copies and the HF blocks.
- sam2/sam3 delegate to load_finetuned_checkpoint (sam2 strict=True,
  sam3 strict=False); removed sam3's local _download_from_huggingface.
- A requested checkpoint that cannot be resolved/downloaded now RAISES
  instead of silently falling back to base pretrained weights.
WarmupStepLR was defined but never referenced anywhere; remove it and
its now-dead StepLR import.
Add a timm-based ViT classifier wrapper that fits the existing classifier
interface (registered as 'vit_timm', subclasses ClassifierWrapperBase):

- vit_timm_classifier.py: ViTTimmClassifier nn.Module (timm backbone +
  multi-layer CLS-token head) plus the ClassifierWrapperBase wrapper that
  builds it from config and emits the standard scores/labels output.
- ClassifierConfig.n_cls_layers: number of final transformer blocks whose
  CLS tokens are concatenated for the head (must match training).
- Example config: DINOv3 ViT-S @ 512px for the Quebec trees dataset.
Loosen exact pins (==) to minimum-version constraints (>=) for
rasterio and shapely to ease dependency resolution.
Add the ability to resume a crashed/interrupted inference run and to
initialize a new-config pipeline from a previous run's outputs.

- A run records resumable state under {output}/_state/ (status.jsonl +
  state.json), managed by a single RunState class (persistence.py).
- DataState fields declare a "persist" role via field metadata; one
  apply_snapshot method restores the input slice (initialize) or the
  input slice + output registries (resume).
- The gdf is recovered by reusing the gpkg each component already
  writes (latest gpkg across components), decoding list columns that
  gpkg stringifies; no extra heavy files.
- infer.py gains --resume_from (same config; in-place or cross-folder)
  and --initialize_from (new config, inputs seeded from a prior run).
- Config-hash drift in the resumed prefix is refused; async COCO
  generation is tracked per-component so resume never skips a component
  whose side outputs were still in flight.

Split preset_test_classif into part1/part2 to exercise initialize_from.
geodataset v0.6.6 makes decode_coco_segmentation require image_height/image_width
(COCO stores size on the image, not the annotation) and adds
decode_coco_rle_segmentation for self-describing RLE.

- Pass tile height/width to decode_coco_segmentation in the SAM training dataset.
- Use decode_coco_rle_segmentation in the (RLE-only) segmentation dataset prep.
Add classifier_score as a first-class aggregator score weight (default 0.0, so
existing detector/segmenter pipelines are unaffected). The config parses
scores_weights['classifier_score'], the component requires the classifier_score
column when weighted and includes it in the scores passed to the aggregator.

Enables running an aggregator on classifier outputs (NMS/ranking by classifier
confidence).
Add a classifier_class_name column mapping the predicted class index to a
human-readable name from config.class_names. The mapping is done in the
component (the model stays index-only); the column is only produced when
class_names is configured, with an out-of-range guard.
Replace the v1 DataState/gdf-merge pipeline with the v3 relational engine: typed
Sources/Tiles/Objects tables threaded by type, with declarative Need/produces
contracts validated before and after each component.

- Promote engine/v3/* to engine/*; delete v1 (pipeline, components, data_state,
  persistence, resume, pipeline_visualizer, constants) and v2.
- Pipeline: generalized seeding (sources/tiles/objects), run-level AOI, resume
  (same/cross-folder) and initialize_from. Persist seed tables under _seed/ so a
  from_dir reload is self-contained (relinks produced Objects' FKs to seeds).
- Rewire callers to the v3 API: infer.py; the detector/segmenter benchmarker
  (export()/from_dir instead of DataState.get_output_file); train_sam COCO eval.
- Port classifier preprocessing off DataState (folder scan); stub the
  not-yet-ported classifier benchmarker (Phase C4 TODO).
- Tests: migrate to v3 (contracts, data model, persistence, export, pipeline
  integration, component contracts); scope pytest to tests/ and register markers.
Run NMS once per (raster, nms_iou) at the min score threshold, then derive every
higher score threshold by masking survivors (exact for greedy NMS). Split the
evaluator into build_raster_eval_context + evaluate_raster_from_context so the
score axis costs only cheap matching; old entry point kept as a wrapper.
Parallel task unit is now (raster, nms_iou). Same grid, same results.
Port the docs off the removed v1 API (DataState / InferIOConfig / *Component /
run_standalone). Rewrite the pipeline and components guides around the typed
Sources/Tiles/Objects tables and requires/produces contracts; replace the
standalone-usage guide with the one-step-pipeline pattern; replace the DataState
API page with a data-model page (and fix the nav + index links); refresh the
quickstart output section and the 'adding a component' contributor steps.
Drop the internal 'v3' version labels from docstrings, comments, strings, the
component-registry name, and test names (kept purely as refactor shorthand), and
delete the internal MIGRATION_PLAN.md. No behavior change.
- Imagery is one self-referential table (kind=source|tile, parent_id): pixels
  load from the nearest on-disk ancestor, so tiles and crops need no files.
- Need gains kind= and modalities=; all checks run on Schema snapshots; each
  component receives the newest table satisfying its declared needs.
- Run record replaces the manifest (run.json); seed tables persisted for reload.
- Vectorized aggregator georeferencing; engine README; docs and tests updated.
InferTimer reports where each model stage's wall time went on one line:
data_wait | prep | gpu | post | other, as shares of the stage. Every key is
main-process time and they sum to the whole loop, so a nonzero `other` means
a missing mark. Marks sync CUDA so async kernels are billed to the stage that
launched them. Wired into the detector, segmenter and classifier infer loops.

Loader workers become a pipeline config key (`num_workers`), replacing the
hardcoded Component.NUM_WORKERS = 4. The default counts the CPUs actually
allocated to the process (sched_getaffinity, not cpu_count, which reports the
whole node on a cluster) less one, capped at 10.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants