Skip to content

fix(datasets): normalize YOLO class IDs across class-name entry points - #1571

Merged
Borda merged 7 commits into
roboflow:developfrom
INo-xious:fix/yolo-class-id-normalization
Sep 30, 2026
Merged

Borda merged 7 commits into
roboflow:developfrom
INo-xious:fix/yolo-class-id-normalization

Conversation

@INo-xious

Copy link
Copy Markdown
Contributor

Summary

YOLO names such as {'0': 'cat', '1': 'dog'} pass numeric-ID validation but raise
KeyError during detection/pose loading. The facade separately sorts quoted IDs
lexicographically and raises TypeError for mixed integer/string keys. Normalize
keys once and use the same parser for facade class discovery.

Changes

  • Read names from their normalized numeric IDs and reject duplicate normalized
    IDs while preserving the contiguous zero-based requirement.
  • Reuse existing class parsing in the facade, preserving its dataset-path gate.
  • Test detection, pose, and facade ordering/validation with temporary datasets;
    document quoted numeric keys.

Verification

  • Added regression tests first: 16 failed/14 passed on develop, then all passed.
  • Focused YOLO, keypoint-schema, and COCO suites (uv run --no-sync pytest tests/datasets/test_yolo.py tests/datasets/test_keypoint_schema.py tests/datasets/test_coco.py -n 1 --timeout=120 --color=no -q): 268 passed.
  • Full macOS CPU suite: 6560 passed, 114 skipped, 736 warnings (11m18s).
  • pre-commit run --all-files: passed, including mypy (UV_NO_SYNC=1).
  • uv run --no-sync mkdocs build --verbose: passed with docs/plus installed.
  • GPU/TPU and hosted CI were not run; no training accuracy claim.

Related issues

No issue claimed. Follow-up to the shared YOLO detection/pose parser in merged
#1156; independent of the dataset-entry-point
candidate. No direct active duplicate found during the overlap review.

@Borda
Borda requested a balanced review from Copilot September 30, 2026 10:44
@Borda Borda added the bug Something isn't working label Sep 30, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Identical keys in a YAML names mapping can still silently overwrite a class name before duplicate-ID validation runs.

Review effort: Balanced
Findings: 1 High severity

Open (1)
What changed in this PR

This PR aligns YOLO class-name parsing across detection, pose, and the RFDETR facade, following the shared pose parser introduced in #1156.

Changes:

  • Normalize numeric class IDs and reject collisions that remain visible after YAML loading.
  • Reuse the parser in the facade and add entry-point tests.
  • Document quoted numeric keys.
File Description
tests/​datasets/​test_yolo.py Tests class ordering and invalid IDs across entry points.
src/​rfdetr/​detr.py Uses the shared YOLO class parser.
src/​rfdetr/​datasets/​_keypoint_schema.py Normalizes IDs and checks for collisions.
docs/​learn/​train/​dataset-formats.md Documents numeric-key behavior.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/rfdetr/datasets/_keypoint_schema.py Outdated
unique_sorted_keys = sorted(set(numeric_keys))
if not unique_sorted_keys or unique_sorted_keys != list(range(len(unique_sorted_keys))) or non_numeric_keys:
sorted_ids = sorted(names_by_id)
if not sorted_ids or sorted_ids != list(range(len(sorted_ids))) or len(names_by_id) != len(names):
@codecov

codecov Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.87234% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 90%. Comparing base (fd889c6) to head (fd7abe0).

Additional details and impacted files
@@           Coverage Diff           @@
##           develop   #1571   +/-   ##
=======================================
  Coverage       90%     90%           
=======================================
  Files          137     138    +1     
  Lines        18254   18264   +10     
=======================================
+ Hits         16421   16436   +15     
+ Misses        1833    1828    -5     
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Borda and others added 5 commits October 1, 2026 00:04
…_keypoint_schema.py into a new _yolo_yaml.py module, since they parse generic YOLO data.yaml fields unrelated to keypoint schemas. yolo.py now imports both helpers from _yolo_yaml instead of _keypoint_schema; _keypoint_schema.py imports them back for its own infer_yolo_keypoint_schema use.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
…emoize YAML load

Reword the ambiguous duplicate-key error message so it no longer implies the length
check catches every duplicate-key case. Add an _ascii_digit_key helper (now in the
relocated _yolo_yaml.py module) so non-ASCII digit YAML keys fall through to the
existing length-mismatch error instead of raising a bare int() ValueError, and reuse
it for the kpt_names key-0 lookup. Memoize _load_yaml_mapping by (resolved path,
mtime_ns, size) so repeated data.yaml parses within one RFDETR.train() call reuse one
parsed mapping; each caller gets a deep copy so mutation can never corrupt the cache.

[resolve group] PR roboflow#1571 — items 1 3 5 8

---
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
…are data-file lookup

Embed the original inference exception text in both YOLO pose data-file wrapper
messages so the real cause is visible directly in the raised ValueError, not only in
__cause__. Add 12 parametrized edge-case class-ID keys (empty, non-integer, whitespace,
negative, non-numeric, bool, non-ASCII digit variants) across all three entry points,
and split the two branching test methods into six focused ones with no runtime
if/else. Add a shared _yolo_data_file(dataset_dir) helper in yolo.py and route
is_valid_yolo_dataset, RFDETR._yolo_data_file_path, and the build_roboflow_from_yolo
fallback through it, keeping the divergent root/"data.yaml" fallback explicit.

[resolve group] PR roboflow#1571 — items 2 6 7 11

---
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Note that three-or-more-digit zero-padded keys in the dictionary names format collide
under YAML 1.1 octal parsing (e.g. 010 and 008 both resolve to class 8); two-digit
padding is unaffected.

[resolve group] PR roboflow#1571 — items 9

---
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
…normalization

# Conflicts:
#	src/rfdetr/datasets/yolo.py
#	src/rfdetr/detr.py
@Borda
Borda merged commit 8913f7b into roboflow:develop Sep 30, 2026
52 checks passed
Borda added a commit that referenced this pull request Oct 3, 2026
#1571)

* fix(datasets): normalize YOLO class IDs across entry points
* Move _load_yaml_mapping and _extract_yolo_class_names_from_data from _keypoint_schema.py into a new _yolo_yaml.py module, since they parse generic YOLO data.yaml fields unrelated to keypoint schemas. yolo.py now imports both helpers from _yolo_yaml instead of _keypoint_schema; _keypoint_schema.py imports them back for its own infer_yolo_keypoint_schema use.
* keypoint-schema: normalize YOLO class-ID key parsing, reword error, memoize YAML load
* entry-points: surface real pose errors, cover edge-case class IDs, share data-file lookup
* docs: document the YAML octal-key collision for zero-padded class IDs

---------

Co-authored-by: jirka <[email protected]>
Co-authored-by: Claude Sonnet 5 <[email protected]>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants