Posts mmdetection
Post
Cancel

mmdetection

官方文档

1
2
3
4
5
# Train
python tools/train.py configs/yolox/yolox_tiny_8x8_300e_coco.py

# Test
python tools/test.py configs/yolox/yolox_tiny_8x8_300e_coco.py xxx.pth --eval mAP

Train

Traceback

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
File "./tools/train.py", line 189 in <module>
	main()
File "./tools/train.py", line 178 in main
	train_detector()
File "mmdet/apis/train.py", line 177 in train_detector
	runner.run(data_loaders, cfg.workflow)
File "/home/zuo/code/mmcv/mmcv/runner/epoch_based_runner.py", line 177 in run
	epoch_runner(data_loaders[i], **kwargs)
File "/home/zuo/code/mmcv/mmcv/runner/epoch_based_runner.py", line 50 in train
	self.run_iter(data_batch, train_mode=True, **kwargs)
File "/home/zuo/code/mmcv/mmcv/runner/epoch_based_runner.py", line 29 in run_iter
	self.model.train_step(data_batch, self.optimizer, **kwargs)
File "/home/zuo/code/mmcv/mmcv/parallel/distributed.py", line 177 in train_step
	self.module.train_step(*inputs[0], **kwargs[0])
File "mmdet/models/detectors/base.py", line 238 in train_step
	losses = self(**data)
File "lib/python3.7/site-packages/torch/nn/modules/module.py", line 727  in _call_impl
	result = self.forward(*input, **kwargs)
File "/home/zuo/code/mmcv/mmcv/runner/fp16_utils.py", line 98 in new_func
	return old_func(*args, **kwargs)
File "mmdet/models/detectors/base.py", line 172  in forward
	return self.forward_train(img, img_metas, **kwargs)
File "mmdet/models/detectors/single_stage.py", line 82~83 in forward_train
	x = self.extract_feat(img), line 82  in forward_train
		extract_feat()                   "mmdet/models/detectors/single_stage.py:41", extract_feat(), 提取特征
	losses = self.bbox_head.forward_train(x, img_metas, gt_bboxes, gt_labels, gt_bboxes_ignore)	
		outs = self(x)                   "mmdet/models/dense_heads/yolox_head.py:196", forward(), 计算输出
		losses = self.loss(*loss_inputs) "mmdet/models/dense_heads/yolox_head.py:324", loss(), 计算loss

Test

Traceback

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
_do_evaluate                             "mmdet/core/evaluation/eval_hooks.py:12"
  results = single_gpu_test(runner.model, self.dataloader, show=False)
    result = model(return_loss=False, rescale=True, **data)  "mmdet/apis/test.py:28"
      forward_test(self, imgs, img_metas, **kwargs)  "mmdet/models/detectors/base.py:112~154"
        simple_test()  "mmdet/models/detectors/single_stage.py"
          feat = self.extract_feat(img)  "mmdet/models/detectors/single_stage.py:41~46"
          self.bbox_head.simple_test(feat,..)
            simple_test() "mmdet/models/dense_heads/base_dense_head.py:334"
              simple_test_bboxes() "mmdet/models/dense_heads/dense_test_mixins.py:17~39"
                outs = self.forward(feats)
                  multi_apply() "mmdet/models/dense_heads/yolox_head.py:207"
        		results_list = self.get_bboxes()
        		  get_bboxes()  "mmdet/models/dense_heads/yolox_head.py:214~295"
          bbox2result(det_bboxes,..)     "mmdet/core/bbox/transforms.py:100~117"
  key_score = self.evaluate(runner, results)
    self.dataloader.dataset.evaluate()   "/home/zuo/code/mmcv/mmcv/runner/hooks/evaluation.py:359"
      evaluate()                         "mmdet/datasets/voc.py:28~105"
      	eval_map()                       "mmdet/core/evaluation/mean_ap.py:297~441"

YOLOX迁移遇到的问题

主要是Dynamic Shape类问题

dataset

由于数据集每张图片中object数量不固定,所以所模型输入tensor gt_bboxesgt_labelsshape是不固定的。这就涉及到dynamic shape输入。彼时MindSporedynamic shape的支持还不完善,因此通过设置一个合理的最大objects数,将gt_bboxesgt_labels padding到最大shape来规避dynamic shape问题。

另外增加有效object的标识作为输入tensor来表示哪些索引位置的object是真实的,哪些索引处的是padding的,以方便将padding对后续计算loss的影响降到最低。

loss

loss计算流程中get_in_gt_and_in_center_info函数里最后一个步骤:

1
2
3
4
5
# both in boxes and centers. shape:[num_fg, num_gt]
is_in_boxes_and_centers = (
	is_in_gts[is_in_gts_or_centers, :] &
    is_in_cts[is_in_gts_or_centers, :]
	)

is_in_boxes_and_centers的shape会随is_in_gts_or_centers的值不同而不同,也就产生了dynamic shape问题,为了规避这个问题,做了如下修改:

1
2
3
is_in_boxes_and_centers = in_gts * in_cts
zeros = mnp.full_like(is_in_boxes_and_centers, 0)
is_in_boxes_and_centers = P.Select()(is_in_gts_or_centers_repeat, is_in_gts_and_centers, zeros)

通过Select算子,将is_in_gts_or_centers_repeatTrue对应的元素赋值给is_in_gts_and_centersis_in_gts_or_centers_repeatFalse对应的位置padding成非法值(这里就是0)。

上面的例子是loss计算流程中dynamic shape的引入点,后续流程还有涉及到dynamic shape的地方,均按照同样的思想进行修改,同样要保证不影响loss的计算结果。

This post is licensed under CC BY 4.0 by the author.