test_pisa_ssd_head.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. # Copyright (c) OpenMMLab. All rights reserved.
  2. from math import ceil
  3. from unittest import TestCase
  4. import torch
  5. from mmengine import Config
  6. from mmengine.structures import InstanceData
  7. from mmdet import * # noqa
  8. from mmdet.models.dense_heads import PISASSDHead
  9. class TestPISASSDHead(TestCase):
  10. def test_pisa_ssd_head_loss(self):
  11. """Tests pisa ssd head loss when truth is empty and non-empty."""
  12. s = 300
  13. img_metas = [{
  14. 'img_shape': (s, s, 3),
  15. 'pad_shape': (s, s, 3),
  16. 'scale_factor': 1,
  17. }]
  18. cfg = Config(
  19. dict(
  20. assigner=dict(
  21. type='MaxIoUAssigner',
  22. pos_iou_thr=0.5,
  23. neg_iou_thr=0.5,
  24. min_pos_iou=0.,
  25. ignore_iof_thr=-1,
  26. gt_max_assign_all=False),
  27. sampler=dict(type='PseudoSampler'),
  28. smoothl1_beta=1.,
  29. allowed_border=-1,
  30. pos_weight=-1,
  31. neg_pos_ratio=3,
  32. debug=False))
  33. pisa_ssd_head = PISASSDHead(
  34. num_classes=4,
  35. in_channels=(1, 1, 1, 1, 1, 1),
  36. anchor_generator=dict(
  37. type='SSDAnchorGenerator',
  38. scale_major=False,
  39. input_size=s,
  40. basesize_ratio_range=(0.15, 0.9),
  41. strides=[8, 16, 32, 64, 100, 300],
  42. ratios=[[2], [2, 3], [2, 3], [2, 3], [2], [2]]),
  43. train_cfg=cfg)
  44. # PISA SSD head expects a multiple levels of features per image
  45. feats = (
  46. torch.rand(1, 1, ceil(s / stride[0]), ceil(s / stride[0]))
  47. for stride in pisa_ssd_head.prior_generator.strides)
  48. cls_scores, bbox_preds = pisa_ssd_head.forward(feats)
  49. # test without isr and carl
  50. # Test that empty ground truth encourages the network to
  51. # predict background
  52. gt_instances = InstanceData()
  53. gt_instances.bboxes = torch.empty((0, 4))
  54. gt_instances.labels = torch.LongTensor([])
  55. empty_gt_losses = pisa_ssd_head.loss_by_feat(cls_scores, bbox_preds,
  56. [gt_instances], img_metas)
  57. # When there is no truth, cls_loss and box_loss should all be zero.
  58. empty_cls_loss = sum(empty_gt_losses['loss_cls'])
  59. empty_box_loss = sum(empty_gt_losses['loss_bbox'])
  60. self.assertEqual(
  61. empty_cls_loss.item(), 0,
  62. 'there should be no cls loss when there are no true boxes')
  63. self.assertEqual(
  64. empty_box_loss.item(), 0,
  65. 'there should be no box loss when there are no true boxes')
  66. # When truth is non-empty then both cls and box loss
  67. # should be nonzero for random inputs
  68. gt_instances = InstanceData()
  69. gt_instances.bboxes = torch.Tensor(
  70. [[23.6667, 23.8757, 238.6326, 151.8874]])
  71. gt_instances.labels = torch.LongTensor([2])
  72. one_gt_losses = pisa_ssd_head.loss_by_feat(cls_scores, bbox_preds,
  73. [gt_instances], img_metas)
  74. onegt_cls_loss = sum(one_gt_losses['loss_cls'])
  75. onegt_box_loss = sum(one_gt_losses['loss_bbox'])
  76. self.assertGreater(onegt_cls_loss.item(), 0,
  77. 'cls loss should be non-zero')
  78. self.assertGreater(onegt_box_loss.item(), 0,
  79. 'box loss should be non-zero')
  80. pisa_ssd_head.train_cfg.update(
  81. dict(isr=dict(k=2., bias=0.), carl=dict(k=1., bias=0.2)))
  82. # test with isr and carl
  83. # Test that empty ground truth encourages the network to
  84. # predict background
  85. gt_instances = InstanceData()
  86. gt_instances.bboxes = torch.empty((0, 4))
  87. gt_instances.labels = torch.LongTensor([])
  88. empty_gt_losses = pisa_ssd_head.loss_by_feat(cls_scores, bbox_preds,
  89. [gt_instances], img_metas)
  90. # When there is no truth, cls_loss and box_loss should all be zero.
  91. empty_cls_loss = sum(empty_gt_losses['loss_cls'])
  92. empty_box_loss = sum(empty_gt_losses['loss_bbox'])
  93. self.assertEqual(
  94. empty_cls_loss.item(), 0,
  95. 'there should be no cls loss when there are no true boxes')
  96. self.assertEqual(
  97. empty_box_loss.item(), 0,
  98. 'there should be no box loss when there are no true boxes')
  99. # When truth is non-empty then both cls and box loss
  100. # should be nonzero for random inputs
  101. gt_instances = InstanceData()
  102. gt_instances.bboxes = torch.Tensor(
  103. [[23.6667, 23.8757, 238.6326, 151.8874]])
  104. gt_instances.labels = torch.LongTensor([2])
  105. one_gt_losses = pisa_ssd_head.loss_by_feat(cls_scores, bbox_preds,
  106. [gt_instances], img_metas)
  107. onegt_cls_loss = sum(one_gt_losses['loss_cls'])
  108. onegt_box_loss = sum(one_gt_losses['loss_bbox'])
  109. self.assertGreater(onegt_cls_loss.item(), 0,
  110. 'cls loss should be non-zero')
  111. self.assertGreater(onegt_box_loss.item(), 0,
  112. 'box loss should be non-zero')