facebookresearch / facebookresearch/detectron2

Training works but AssertionError for MODEL.ROI_HEADS.NUM_CLASSES only when COCOEvaluator is used

Open
#4,922 5 comments 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
34.7k
Forks
7.9k
PR merge metrics
No merged PRs in 30d

Description

Based on the suggestions mentioned in [this discussion](https://github.com/facebookresearch/detectron2/issues/810), I am trying to compute validation loss during the training of Mask R-CNN model. Please note that my dataset has only 1 class, say toys, which are small items (maximum 10 cm long).

## Instructions To Reproduce the Issue:

1. [Using code from this discussion](https://github.com/facebookresearch/detectron2/issues/810)
2. Specially, please see the `ValLossHook` below:
```
class ValLossHook(HookBase):
def __init__(self, cfg, validation_set_key):
super().__init__()
self.cfg = cfg.clone()
self._loader = iter(build_detection_test_loader(self.cfg, validation_set_key,
mapper=DatasetMapper(self.cfg, is_train=True)))

def after_step(self):
data = next(self._loader)
with torch.no_grad():
loss_dict = self.trainer.model(data)

losses = sum(loss_dict.values())
assert torch.isfinite(losses).all(), loss_dict

loss_dict_reduced = {"val_" + k: v.item() for k, v in comm.reduce_dict(loss_dict).items()}
losses_reduced = sum(loss for loss in loss_dict_reduced.values())
if comm.is_main_process():
self.trainer.storage.put_scalars(val_total_loss=losses_reduced,
**loss_dict_reduced)
```

## Observations:

While training together with computing validation loss, I noticed the following behaviors:

1. With default `cfg`, the training works but the `COCOEvaluator` throws `AssertionError` as shown below:
```
Traceback (most recent call last):
File "train.py", line 123, in
main()
File "train.py", line 119, in main
trainer.train()
File "/home/ravi/.local/lib/python3.6/site-packages/detectron2/engine/defaults.py", line 484, in train
super().train(self.start_iter, self.max_iter)
File "/home/ravi/.local/lib/python3.6/site-packages/detectron2/engine/train_loop.py", line 150, in train
self.after_step()
File "/home/ravi/.local/lib/python3.6/site-packages/detectron2/engine/train_loop.py", line 180, in after_step
h.after_step()
File "/home/ravi/.local/lib/python3.6/site-packages/detectron2/engine/hooks.py", line 552, in after_step
self._do_eval()
File "/home/ravi/.local/lib/python3.6/site-packages/detectron2/engine/hooks.py", line 525, in _do_eval
results = self._func()
File "/home/ravi/.local/lib/python3.6/site-packages/detectron2/engine/defaults.py", line 453, in test_and_save_results
self._last_eval_results = self.test(self.cfg, self.model)
File "/home/ravi/.local/lib/python3.6/site-packages/detectron2/engine/defaults.py", line 608, in test
results_i = inference_on_dataset(model, data_loader, evaluator)
File "/home/ravi/.local/lib/python3.6/site-packages/detectron2/evaluation/evaluator.py", line 204, in inference_on_dataset
results = evaluator.evaluate()
File "/home/ravi/.local/lib/python3.6/site-packages/detectron2/evaluation/coco_evaluation.py", line 194, in evaluate
self._eval_predictions(predictions, img_ids=img_ids)
File "/home/ravi/.local/lib/python3.6/site-packages/detectron2/evaluation/coco_evaluation.py", line 229, in _eval_predictions
f"A prediction has class={category_id}, "
AssertionError: A prediction has class=77, but the dataset only has 1 classes and predicted class id should be in [0, 0].
```
The solution is to set `cfg.MODEL.ROI_HEADS.NUM_CLASSES = 1`. However, after adding this configuration, detectron2 is showing the following warning:
```
[04/20 18:56:34 d2.data.dataset_mapper]: [DatasetMapper] Augmentations used in training: [ResizeShortestEdge(short_edge_length=(640, 672, 704, 736, 768, 800), max_size=1333, sample_style='choice'), RandomFlip()]
[04/20 18:56:34 d2.data.build]: Using training sampler TrainingSampler
[04/20 18:56:34 d2.data.common]: Serializing 5 elements to byte tensors and concatenating them all ...
[04/20 18:56:34 d2.data.common]: Serialized dataset takes 0.25 MiB
Skip loading parameter 'roi_heads.box_predictor.cls_score.weight' to the model due to incompatible shapes: (81, 1024) in the checkpoint but (2, 1024) in the model! You might want to double check if this is expected.
Skip loading parameter 'roi_heads.box_predictor.cls_score.bias' to the model due to incompatible shapes: (81,) in the checkpoint but (2,) in the model! You might want to double check if this is expected.
Skip loading parameter 'roi_heads.box_predictor.bbox_pred.weight' to the model due to incompatible shapes: (320, 1024) in the checkpoint but (4, 1024) in the model! You might want to double check if this is expected.
Skip loading parameter 'roi_heads.box_predictor.bbox_pred.bias' to the model due to incompatible shapes: (320,) in the checkpoint but (4,) in the model! You might want to double check if this is expected.
Skip loading parameter 'roi_heads.mask_head.predictor.weight' to the model due to incompatible shapes: (80, 256, 1, 1) in the checkpoint but (1, 256, 1, 1) in the model! You might want to double check if this is expected.
Skip loading parameter 'roi_heads.mask_head.predictor.bias' to the model due to incompatible shapes: (80,) in the checkpoint but (1,) in the model! You might want to double check if this is expected.
Some model parameters or buffers are not found in the checkpoint:
roi_heads.box_predictor.bbox_pred.{bias, weight}
roi_heads.box_predictor.cls_score.{bias, weight}
roi_heads.mask_head.predictor.{bias, weight}
[04/20 18:56:34 d2.engine.train_loop]: Starting training from iteration 0
```
2. My dataset contains small items (maximum 10 cm long). However, the `COCOEvaluator` is showing `nan` for APs. See below, please:
```
[04/20 18:56:45 d2.evaluation.fast_eval_api]: Evaluate annotation type *segm*
[04/20 18:56:45 d2.evaluation.fast_eval_api]: COCOeval_opt.evaluate() finished in 0.02 seconds.
[04/20 18:56:45 d2.evaluation.fast_eval_api]: Accumulating evaluation results...
[04/20 18:56:45 d2.evaluation.fast_eval_api]: COCOeval_opt.accumulate() finished in 0.00 seconds.
Average Precision (AP) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.432
Average Precision (AP) @[ IoU=0.50 | area= all | maxDets=100 ] = 0.709
Average Precision (AP) @[ IoU=0.75 | area= all | maxDets=100 ] = 0.466
Average Precision (AP) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = -1.000
Average Precision (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.401
Average Precision (AP) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.437
Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 1 ] = 0.016
Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets= 10 ] = 0.190
Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.667
Average Recall (AR) @[ IoU=0.50:0.95 | area= small | maxDets=100 ] = -1.000
Average Recall (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=100 ] = 0.750
Average Recall (AR) @[ IoU=0.50:0.95 | area= large | maxDets=100 ] = 0.662
[04/20 18:56:45 d2.evaluation.coco_evaluation]: Evaluation results for segm:
| AP | AP50 | AP75 | APs | APm | APl |
|:------:|:------:|:------:|:-----:|:------:|:------:|
| 43.207 | 70.906 | 46.571 | nan | 40.081 | 43.697 |
[04/20 18:56:45 d2.evaluation.coco_evaluation]: Some metrics cannot be computed and is shown as NaN.
[04/20 18:56:45 d2.engine.defaults]: Evaluation results for toys_test in csv format:
[04/20 18:56:45 d2.evaluation.testing]: copypaste: Task: bbox
[04/20 18:56:45 d2.evaluation.testing]: copypaste: AP,AP50,AP75,APs,APm,APl
[04/20 18:56:45 d2.evaluation.testing]: copypaste: 35.4201,68.1637,32.0485,nan,61.3645,35.2860
[04/20 18:56:45 d2.evaluation.testing]: copypaste: Task: segm
[04/20 18:56:45 d2.evaluation.testing]: copypaste: AP,AP50,AP75,APs,APm,APl
[04/20 18:56:45 d2.evaluation.testing]: copypaste: 43.2066,70.9056,46.5707,nan,40.0806,43.6967
```

## Environment:

| Name | Info./Version |
|:------------------------|:-------------------------------------------------------------------------|
| sys.platform | linux |
| OS | Ubuntu 18.04.6 LTS |
| OS Kernel | 5.4.0-120-generic |
| Python | 3.6.9 (default, Mar 10 2023, 16:46:00) [GCC 8.4.0] |
| numpy | 1.19.5 |
| detectron2 | 0.6 @/home/ravi/.local/lib/python3.6/site-packages/detectron2 |
| Compiler | GCC 7.5 |
| CUDA compiler | CUDA 11.6 |
| detectron2 arch flags | 7.0 |
| DETECTRON2_ENV_MODULE | \ |
| PyTorch | 1.9.0+cu111 @/home/ravi/.local/lib/python3.6/site-packages/torch |
| PyTorch debug build | False |
| GPU available | Yes |
| GPU 0,1 | NVIDIA GeForce RTX 3090 (arch=8.6) |
| Driver version | 515.48.07 |
| CUDA_HOME | /usr/local/cuda |
| Pillow | 8.4.0 |
| torchvision | 0.10.0+cu111 @/home/ravi/.local/lib/python3.6/site-packages/torchvision |
| torchvision arch flags | 3.5, 5.0, 6.0, 7.0, 7.5, 8.0, 8.6 |
| fvcore | 0.1.5.post20221221 |
| iopath | 0.1.9 |
| cv2 | 4.7.0 |

## Questions:

1. Is it necessary to set `NUM_CLASSES` for `roi_heads`? Surprisingly, the training works even without setting it. Nevertheless, after setting it, detectron2 shows an incompatible message mentioned above. Does it mean that weights for `roi_heads` are not loaded? Furthermore. does setting `NUM_CLASSES` to 1 hurt model learning/performance?
2. Why does the `COCOEvaluator` show nan for APs in my dataset having only small objects?

Thank you very much.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.