Skip to content

Feature/yolov26 - #153

Merged
asgersvenning merged 28 commits into
developfrom
feature/yolov26
Jul 7, 2026
Merged

Feature/yolov26#153
asgersvenning merged 28 commits into
developfrom
feature/yolov26

Conversation

@asgersvenning

Copy link
Copy Markdown
Collaborator

Add support for YOLOv26 models by updating flatbug compatibility to ultralytics>=8.4.0,<=8.4.90 and changed the default model to flat_bug_M_v2.pt which is such a newly trained YOLOv26 Medium flatbug model with the following evaluation statistics:

overall_model_comparison stratified_subdataset_comparison

Which is marginally lower Precision (92.3 vs 92.4) but better Recall (96.4 vs 95.0) and F1 (93.7 vs 93.1) as compared to the original flat_bug_M.pt model.

Also contains some linting and package management improvements.

asgersvenning and others added 28 commits June 6, 2025 16:44
- Bump ultralytics upper bound to 8.4.49 (required for YOLOv26)
- Update postprocess() in yolo_helpers.py to handle the end2end output
  format introduced by YOLOv26 (post-NMS xyxy detections vs legacy
  pre-NMS xywh anchors); also handle the 8.4.x tuple output wrapping
  for legacy YOLO11 models
- Fix trainers.py to use load_checkpoint (ultralytics >= 8.4 renamed
  attempt_load_one_weight) and yaml_load (replaced by YAML.load)
- Add scripts/training/fb_config_yolo26n.yaml for training with yolo26n-seg

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace the internal-API hack (pred.setup_model(self=pred, ...)) with
direct access to yolo.model. The setup_model call in ultralytics 8.4
now requires args.end2end which the dict2attr stub did not provide.
For .pt models the AutoBackend wrapper is unnecessary since flat-bug
preprocesses images itself and only uses PyTorch tensors.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- fb_train.py: change default model from yolov8m-seg.pt to yolo26m-seg.pt
- fb_config_M40S.yaml: update to yolo26m-seg.pt
- fb_config_M40S_GHPC.yaml: fix yolov26m.pt (wrong name/variant) to yolo26m-seg.pt

Pretrained weights are auto-downloaded by ultralytics if not present locally.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ultralytics < 8.4 does not call attempt_download_asset inside
torch_safe_load, so yolo26m-seg.pt (and any other asset-list model)
was never downloaded on machines running 8.3.x. Add an explicit
attempt_download_asset call in setup_model before _load_checkpoint.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
YOLOv26's one2many loss uses significantly more memory during validation
than YOLOv8 did. Call torch.cuda.empty_cache() before each validation
pass to release fragmented reserved memory.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ultralytics doubles batch_size for validation (non-OBB tasks), but
YOLOv26's one2many loss makes this OOM on memory-constrained GPUs.
Clamp validation batch_size back to self.args.batch.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Default compression level 6 is slow for large batches of crops.
Level 1 is significantly faster at the cost of slightly larger files.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
YOLOv26's one2many head assigns many positive anchors per GT instance.
On dense flat-bug images (hundreds of insects per 1024×1024 crop) this
causes single_mask_loss/crop_mask to materialise a [n_pos, 256, 256]
float32 tensor of ~11.5 GB — OOM even at batch_size=1.

The validation loss is only logged and has no effect on fitness, mAP,
or early stopping. We therefore replace model.loss (on both the live
model and the EMA model) with a no-op returning zeros for the duration
of each validation pass, then restore the class method via del.

This is orthogonal to the earlier batch_size and empty_cache mitigations,
which did not address the per-image root cause.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
YOLOv26's validator initialises self.loss with 5 components; our
no-op was returning torch.zeros(4) from len(self.loss_names).
Return scalar 0 instead — adding a scalar to any tensor is always valid.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@asgersvenning asgersvenning added the enhancement New feature or request label Jul 7, 2026

@asgersvenning asgersvenning left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I've manually made and reviewed these changes.

@asgersvenning
asgersvenning merged commit 3517720 into develop Jul 7, 2026
4 checks passed
@asgersvenning asgersvenning mentioned this pull request Aug 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants