mixed_dataset: let the shuffle reach training instead of being discarded - #6
Open
egeboy35 wants to merge 1 commit into
Open
mixed_dataset: let the shuffle reach training instead of being discarded#6egeboy35 wants to merge 1 commit into
egeboy35 wants to merge 1 commit into
Conversation
egeboy35
force-pushed
the
fix/mixed-dataset-shuffle-reaches-training
branch
from
September 1, 2026 12:28
67f8a74 to
7afebfa
Compare
build_mixed shuffles the train image list, with the reason stated in the
comment above it:
# Shuffle the train order so that taking the first --max-images during
# training yields a balanced (cross-source) subset -- needed for clean
# data-size studies.
The order does not survive. img_id is assigned inside the per-source loop,
so each source owns one contiguous block, and the consumer re-sorts:
torchvision's CocoDetection does
self.ids = list(sorted(self.coco.imgs.keys()))
after which datasets.py takes the first --max-images in id order. Sorting
therefore front-loads whichever source was written first.
Measured by running build_mixed with three sources x 400 train images and
reading the result back through CocoDetection:
shuffle achieved, in the JSON list : waymo 148, kitti 124, nuimages 128
ids as assigned : kitti 0..399, waymo 550..949,
nuimages 1100..1499
what --max-images 200 loads : kitti 200
what --max-images 400 loads : kitti 400
what --max-images 800 loads : kitti 400, waymo 400
train.py's default is max_images = 400, so `--dataset mixed` with nothing
else set trains on one source.
The held-out block has the same shape. It is written as val.json and
labelled "held-out mixed", and run_eval defaults to --mixed-split val with
--max-images 200, which read 150 KITTI + 50 Waymo and never reached
nuImages.
Both lists are now shuffled (with separate seeds) and the image ids are
renumbered to follow that order, with annotations remapped. Train takes
0..T-1 and the held-out block the range above it, so the two stay disjoint
by construction the way this function's docstring promises.
After the change, same build:
train --max-images 200 : waymo 81, kitti 57, nuimages 62
train --max-images 400 : waymo 148, kitti 124, nuimages 128
val --max-images 200 : waymo 72, kitti 65, nuimages 63
and the invariants hold: train/val id intersection 0, every annotation
still resolves inside its own split, and test_<source>.json is unchanged at
150 images of one source each -- those filter on "source", not on id.
One thing I could not settle and am not asserting: TUTORIAL.md 18.3 runs
--dataset mixed at the 400 default and reports a fine-tune result whose
shape (kitti up, waymo and nuimages down) is what training on KITTI alone
would look like, while 18.4 passes --max-images 99999 and recovers the
other two. Whether that section is measuring catastrophic forgetting or
this bug is a question for you, not a claim from me.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
egeboy35
force-pushed
the
fix/mixed-dataset-shuffle-reaches-training
branch
from
September 1, 2026 12:43
7afebfa to
df1a5b9
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
build_mixedshuffles the train image list, and the comment above it states why:That order does not survive to the trainer.
img_idis assigned inside the per-source loop, so each source owns one contiguous id block, and the consumer re-sorts. torchvision'sCocoDetection.__init__does:which discards the JSON list order, after which
datasets.pytakes the first--max-imagesin id order. Sorting therefore front-loads whichever source happened to be written first.Measured
Ran the repository's own
build_mixedwith three sources x 400 train / 150 test images, then read the result back throughCocoDetection:train.py:63defaults tomax_images = 400, so--dataset mixedwith nothing else set trains on a single source.The held-out block has the same shape. It is written as
val.jsonand labelled "held-out mixed", andrun_eval.pydefaults to--mixed-split val --max-images 200-- which read 150 KITTI + 50 Waymo and never reached nuImages.Change
Both lists are shuffled (with separate seeds) and the image ids are renumbered to follow that order, with
annotations[].image_idremapped to match. Train takes0..T-1and the held-out block the range above it, so the two stay disjoint by construction the way this function's docstring promises.Same build, after:
Invariants re-checked on the produced files:
test_<source>.jsonunchanged at 150 images of one source each -- those filter on"source", not on idOne file, +23 lines.
What I could not run, and what I substituted
I have no KITTI/Waymo/nuImages data and no GPU here, so two things were stubbed. Neither is under test:
_source_dataset-- replaced with a stub honouring the contract the loop uses (len(ds),ds[i] -> s.image(PIL),s.gt_boxes,s.gt_labels), so no download is needed.torchvision.datasets.CocoDetection-- torchvision is not installed in my environment, so the class was reconstructed keeping the one line that matters verbatim from torchvision 0.28.0's owndatasets/coco.py, read out of the wheel:self.ids = list(sorted(self.coco.imgs.keys())).pycocotoolsis the real package, and the id-selection logic under test is this repository's own code. If your torchvision pin orders ids differently, the premise changes and this PR should be closed -- worth a 10-second check on your side.A question, not a claim
TUTORIAL.md18.3 runs--dataset mixedat the 400 default and reports a fine-tune result whose shape (kitti up, waymo and nuimages down) is what training on KITTI alone would look like, while 18.4 passes--max-images 99999and recovers the other two. Whether that section is measuring catastrophic forgetting or this bug is a question for you -- I have no way to tell from outside, and I am not asserting either reading.