Errors with P2 segmentation model due to hardcoded scaling factor:
```
Traceba…ck (most recent call last):
File "/opt/conda/bin/yolo", line 8, in <module>
sys.exit(entrypoint())
^^^^^^^^^^^^
File "/ultralytics/ultralytics/cfg/__init__.py", line 987, in entrypoint
getattr(model, mode)(**overrides) # default args from model
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/ultralytics/ultralytics/engine/model.py", line 774, in train
self.trainer.train()
File "/ultralytics/ultralytics/engine/trainer.py", line 243, in train
self._do_train()
File "/ultralytics/ultralytics/engine/trainer.py", line 478, in _do_train
self.metrics, self.fitness = self.validate()
^^^^^^^^^^^^^^^
File "/ultralytics/ultralytics/engine/trainer.py", line 708, in validate
metrics = self.validator(self)
^^^^^^^^^^^^^^^^^^^^
File "/opt/conda/lib/python3.11/site-packages/torch/utils/_contextlib.py", line 120, in decorate_context
return func(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^
File "/ultralytics/ultralytics/engine/validator.py", line 223, in __call__
self.update_metrics(preds, batch)
File "/ultralytics/ultralytics/models/yolo/detect/val.py", line 184, in update_metrics
**self._process_batch(predn, pbatch),
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/ultralytics/ultralytics/models/yolo/segment/val.py", line 168, in _process_batch
iou = mask_iou(batch["masks"].flatten(1), preds["masks"].flatten(1).float()) # float, uint8
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/ultralytics/ultralytics/utils/metrics.py", line 162, in mask_iou
intersection = torch.matmul(mask1, mask2.T).clamp_(0)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
RuntimeError: mat1 and mat2 shapes cannot be multiplied (8x21504 and 86016x12)
```
**MRE**
`yolo11-seg-p2.yaml`
```yaml
# Model
nc: 80
strides: [4, 8, 16, 32]
scales:
n: [0.50, 0.25, 1024]
s: [0.50, 0.50, 1024]
m: [0.50, 1.00, 512]
l: [1.00, 1.00, 512]
x: [1.00, 1.50, 512]
backbone:
# Stem
- [-1, 1, Conv, [64, 3, 2]] # (1, 64, 320, 320) - 0
# P2 Backbone
- [-1, 1, Conv, [128, 3, 2]] # (1, 128, 160, 160) - 1
- [-1, 2, C3k2, [256, False, 0.25]] # (1, 256, 160, 160) - 2
# P3 Backbone
- [-1, 1, Conv, [256, 3, 2]] # (1, 256, 80, 80) - 3
- [-1, 2, C3k2, [512, False, 0.25]] # (1, 512, 80, 80) - 4
# P4 Backbone
- [-1, 1, Conv, [512, 3, 2]] # (1, 512, 40, 40) - 5
- [-1, 2, C3k2, [512, True]] # (1, 512, 40, 40) - 6
# P5 Backbone
- [-1, 1, Conv, [1024, 3, 2]] # (1, 512, 20, 20) - 7
- [-1, 2, C3k2, [1024, True]] # (1, 512, 20, 20) - 8
- [-1, 1, SPPF, [1024, 5]] # (1, 512, 20, 20) - 9
- [-1, 2, C2PSA, [1024]] # (1, 512, 20, 20) - 10
head:
# Top-Down Path (Feature Pyramid)
# P4 Head
- [-1, 1, nn.Upsample, [None, 2, nearest]] # (1, 512, 40, 40) - 11
- [[-1, 6], 1, Concat, [1]] # (1, 1024, 40, 40) - 12
- [-1, 2, C3k2, [512, False]] # (1, 512, 40, 40) - 13
# P3 Head
- [-1, 1, nn.Upsample, [None, 2, nearest]] # (1, 512, 80, 80) - 14
- [[-1, 4], 1, Concat, [1]] # (1, 1024, 80, 80) - 15
- [-1, 2, C3k2, [256, False]] # (1, 256, 80, 80) - 16
# P2 Head
- [-1, 1, nn.Upsample, [None, 2, nearest]] # (1, 256, 160, 160) - 17
- [[-1, 2], 1, Concat, [1]] # (1, 512, 160, 160) - 18
- [-1, 2, C3k2, [128, False]] # (1, 128, 160, 160) - 19
# Bottom-Up Path (PAN-FPN)
# P3
- [-1, 1, Conv, [128, 3, 2]] # (1, 128, 80, 80) - 20
- [[-1, 16], 1, Concat, [1]] # (1, 384, 80, 80) - 21
- [-1, 2, C3k2, [256, False]] # (1, 256, 80, 80) - 22
# P4
- [-1, 1, Conv, [256, 3, 2]] # (1, 256, 40, 40) - 23
- [[-1, 13], 1, Concat, [1]] # (1, 768, 40, 40) - 24
- [-1, 2, C3k2, [512, False]] # (1, 512, 40, 40) - 25
# P5
- [-1, 1, Conv, [512, 3, 2]] # (1, 512, 20, 20) - 26
- [[-1, 10], 1, Concat, [1]] # (1, 1024, 20, 20) - 27
- [-1, 2, C3k2, [1024, True]] # (1, 512, 20, 20) - 28
# Segmentation Head (P2, P3, P4, P5)
- [[19, 22, 25, 28], 1, Segment, [nc, 32, 256]] # 29
```
```
yolo train model=yolo11n-seg-p2.yaml data=coco128-seg.yaml epochs=30 batch=2
```
## 🛠️ PR Summary
<sub>Made with ❤️ by [Ultralytics Actions](https://www.ultralytics.com/actions)</sub>
### 🌟 Summary
Fixes segmentation validation mask scaling by deriving the mask/image scaling factor from the model stride (instead of a hardcoded value) 🧩
### 📊 Key Changes
- Updates `Validator` to set `self.stride = model.stride` after model warmup to ensure stride is available and accurate during validation.
- In segmentation validation, replaces hardcoded proto-to-image scaling (`4 * x`) with a stride-based scaling factor derived from `self.stride`.
- Adjusts ground-truth mask resizing logic to compute expected mask size using stride, improving consistency across different model/export configurations.
### 🎯 Purpose & Impact
- Improves correctness of mask resizing/scaling during validation for segmentation models, especially when stride differs from the previously assumed factor.
- Reduces the chance of mismatched mask shapes and associated metric inaccuracies when validating across model variants/exports.
- Makes validation behavior more robust and model-aware, helping users get more reliable segmentation metrics 📈