Browse Source

training rcnn mdoel w/ negative sample supports bs>1

will-jl944 3 years ago
parent
commit
574c36e2d3

+ 1 - 1
PaddleDetection

@@ -1 +1 @@
-Subproject commit a2f247621f52150cb036dec8054ac63bc5b2f84a
+Subproject commit 692d732994660ceba82c75034c802eb1138239cf

+ 14 - 54
paddlex/cv/models/detector.py

@@ -1352,42 +1352,22 @@ class FasterRCNN(BaseDetector):
         """
         """
         if train_dataset.pos_num < len(train_dataset.file_list):
         if train_dataset.pos_num < len(train_dataset.file_list):
             train_dataset.num_workers = 0
             train_dataset.num_workers = 0
-            if train_batch_size != 1:
-                train_batch_size = 1
-                logging.warning(
-                    "Training RCNN models with negative samples only support batch size equals to 1 "
-                    "on a single gpu/cpu card, `train_batch_size` is forcibly set to 1."
-                )
-            nranks = paddle.distributed.get_world_size()
-            local_rank = paddle.distributed.get_rank()
-            # single card training
-            if nranks < 2 or local_rank == 0:
-                super(FasterRCNN, self).train(
-                    num_epochs, train_dataset, train_batch_size, eval_dataset,
-                    optimizer, save_interval_epochs, log_interval_steps,
-                    save_dir, pretrain_weights, learning_rate, warmup_steps,
-                    warmup_start_lr, lr_decay_epochs, lr_decay_gamma, metric,
-                    use_ema, early_stop, early_stop_patience, use_vdl,
-                    resume_checkpoint)
-        else:
-            super(FasterRCNN, self).train(
-                num_epochs, train_dataset, train_batch_size, eval_dataset,
-                optimizer, save_interval_epochs, log_interval_steps, save_dir,
-                pretrain_weights, learning_rate, warmup_steps, warmup_start_lr,
-                lr_decay_epochs, lr_decay_gamma, metric, use_ema, early_stop,
-                early_stop_patience, use_vdl, resume_checkpoint)
+        super(FasterRCNN, self).train(
+            num_epochs, train_dataset, train_batch_size, eval_dataset,
+            optimizer, save_interval_epochs, log_interval_steps, save_dir,
+            pretrain_weights, learning_rate, warmup_steps, warmup_start_lr,
+            lr_decay_epochs, lr_decay_gamma, metric, use_ema, early_stop,
+            early_stop_patience, use_vdl, resume_checkpoint)
 
 
     def _compose_batch_transform(self, transforms, mode='train'):
     def _compose_batch_transform(self, transforms, mode='train'):
         if mode == 'train':
         if mode == 'train':
             default_batch_transforms = [
             default_batch_transforms = [
                 _BatchPadding(pad_to_stride=32 if self.with_fpn else -1)
                 _BatchPadding(pad_to_stride=32 if self.with_fpn else -1)
             ]
             ]
-            collate_batch = False
         else:
         else:
             default_batch_transforms = [
             default_batch_transforms = [
                 _BatchPadding(pad_to_stride=32 if self.with_fpn else -1)
                 _BatchPadding(pad_to_stride=32 if self.with_fpn else -1)
             ]
             ]
-            collate_batch = True
         custom_batch_transforms = []
         custom_batch_transforms = []
         for i, op in enumerate(transforms.transforms):
         for i, op in enumerate(transforms.transforms):
             if isinstance(op, (BatchRandomResize, BatchRandomResizeByShort)):
             if isinstance(op, (BatchRandomResize, BatchRandomResizeByShort)):
@@ -1400,7 +1380,7 @@ class FasterRCNN(BaseDetector):
 
 
         batch_transforms = BatchCompose(
         batch_transforms = BatchCompose(
             custom_batch_transforms + default_batch_transforms,
             custom_batch_transforms + default_batch_transforms,
-            collate_batch=collate_batch)
+            collate_batch=False)
 
 
         return batch_transforms
         return batch_transforms
 
 
@@ -2200,42 +2180,22 @@ class MaskRCNN(BaseDetector):
         """
         """
         if train_dataset.pos_num < len(train_dataset.file_list):
         if train_dataset.pos_num < len(train_dataset.file_list):
             train_dataset.num_workers = 0
             train_dataset.num_workers = 0
-            if train_batch_size != 1:
-                train_batch_size = 1
-                logging.warning(
-                    "Training RCNN models with negative samples only support batch size equals to 1 "
-                    "on a single gpu/cpu card, `train_batch_size` is forcibly set to 1."
-                )
-            nranks = paddle.distributed.get_world_size()
-            local_rank = paddle.distributed.get_rank()
-            # single card training
-            if nranks < 2 or local_rank == 0:
-                super(MaskRCNN, self).train(
-                    num_epochs, train_dataset, train_batch_size, eval_dataset,
-                    optimizer, save_interval_epochs, log_interval_steps,
-                    save_dir, pretrain_weights, learning_rate, warmup_steps,
-                    warmup_start_lr, lr_decay_epochs, lr_decay_gamma, metric,
-                    use_ema, early_stop, early_stop_patience, use_vdl,
-                    resume_checkpoint)
-        else:
-            super(MaskRCNN, self).train(
-                num_epochs, train_dataset, train_batch_size, eval_dataset,
-                optimizer, save_interval_epochs, log_interval_steps, save_dir,
-                pretrain_weights, learning_rate, warmup_steps, warmup_start_lr,
-                lr_decay_epochs, lr_decay_gamma, metric, use_ema, early_stop,
-                early_stop_patience, use_vdl, resume_checkpoint)
+        super(MaskRCNN, self).train(
+            num_epochs, train_dataset, train_batch_size, eval_dataset,
+            optimizer, save_interval_epochs, log_interval_steps, save_dir,
+            pretrain_weights, learning_rate, warmup_steps, warmup_start_lr,
+            lr_decay_epochs, lr_decay_gamma, metric, use_ema, early_stop,
+            early_stop_patience, use_vdl, resume_checkpoint)
 
 
     def _compose_batch_transform(self, transforms, mode='train'):
     def _compose_batch_transform(self, transforms, mode='train'):
         if mode == 'train':
         if mode == 'train':
             default_batch_transforms = [
             default_batch_transforms = [
                 _BatchPadding(pad_to_stride=32 if self.with_fpn else -1)
                 _BatchPadding(pad_to_stride=32 if self.with_fpn else -1)
             ]
             ]
-            collate_batch = False
         else:
         else:
             default_batch_transforms = [
             default_batch_transforms = [
                 _BatchPadding(pad_to_stride=32 if self.with_fpn else -1)
                 _BatchPadding(pad_to_stride=32 if self.with_fpn else -1)
             ]
             ]
-            collate_batch = True
         custom_batch_transforms = []
         custom_batch_transforms = []
         for i, op in enumerate(transforms.transforms):
         for i, op in enumerate(transforms.transforms):
             if isinstance(op, (BatchRandomResize, BatchRandomResizeByShort)):
             if isinstance(op, (BatchRandomResize, BatchRandomResizeByShort)):
@@ -2248,7 +2208,7 @@ class MaskRCNN(BaseDetector):
 
 
         batch_transforms = BatchCompose(
         batch_transforms = BatchCompose(
             custom_batch_transforms + default_batch_transforms,
             custom_batch_transforms + default_batch_transforms,
-            collate_batch=collate_batch)
+            collate_batch=False)
 
 
         return batch_transforms
         return batch_transforms
 
 

+ 5 - 4
paddlex/ppdet/engine/trainer.py

@@ -33,6 +33,7 @@ from paddle.static import InputSpec
 from paddlex.ppdet.optimizer import ModelEMA
 from paddlex.ppdet.optimizer import ModelEMA
 
 
 from paddlex.ppdet.core.workspace import create
 from paddlex.ppdet.core.workspace import create
+from paddlex.ppdet.modeling.architectures.meta_arch import BaseArch
 from paddlex.ppdet.utils.checkpoint import load_weight, load_pretrain_weight
 from paddlex.ppdet.utils.checkpoint import load_weight, load_pretrain_weight
 from paddlex.ppdet.utils.visualizer import visualize_results, save_result
 from paddlex.ppdet.utils.visualizer import visualize_results, save_result
 from paddlex.ppdet.metrics import Metric, COCOMetric, VOCMetric, WiderFaceMetric, get_infer_results, KeyPointTopDownCOCOEval, KeyPointTopDownMPIIEval
 from paddlex.ppdet.metrics import Metric, COCOMetric, VOCMetric, WiderFaceMetric, get_infer_results, KeyPointTopDownCOCOEval, KeyPointTopDownMPIIEval
@@ -340,11 +341,11 @@ class Trainer(object):
         assert self.mode == 'train', "Model not in 'train' mode"
         assert self.mode == 'train', "Model not in 'train' mode"
         Init_mark = False
         Init_mark = False
 
 
-        sync_bn = (getattr(self.cfg, 'norm_type', None) == 'sync_bn' and
-                   self.cfg.use_gpu and self._nranks > 1)
+        sync_bn = (
+            getattr(self.cfg, 'norm_type', None) in [None, 'sync_bn'] and
+            self.cfg.use_gpu and self._nranks > 1)
         if sync_bn:
         if sync_bn:
-            self.model = paddle.nn.SyncBatchNorm.convert_sync_batchnorm(
-                self.model)
+            self.model = BaseArch.convert_sync_batchnorm(self.model)
 
 
         model = self.model
         model = self.model
         if self.cfg.get('fleet', False):
         if self.cfg.get('fleet', False):

+ 13 - 0
paddlex/ppdet/modeling/architectures/meta_arch.py

@@ -126,3 +126,16 @@ class BaseArch(nn.Layer):
 
 
     def get_pred(self, ):
     def get_pred(self, ):
         raise NotImplementedError("Should implement get_pred method!")
         raise NotImplementedError("Should implement get_pred method!")
+
+    @classmethod
+    def convert_sync_batchnorm(cls, layer):
+        layer_output = layer
+        if getattr(layer, 'norm_type', None) == 'sync_bn':
+            layer_output = nn.SyncBatchNorm.convert_sync_batchnorm(layer)
+        else:
+            for name, sublayer in layer.named_children():
+                layer_output.add_sublayer(name,
+                                          cls.convert_sync_batchnorm(sublayer))
+
+        del layer
+        return layer_output

+ 1 - 1
paddlex/ppdet/modeling/backbones/esnet.py

@@ -20,7 +20,7 @@ import paddle
 import paddle.nn as nn
 import paddle.nn as nn
 import paddle.nn.functional as F
 import paddle.nn.functional as F
 from paddle import ParamAttr
 from paddle import ParamAttr
-from paddle.nn import Conv2D, MaxPool2D, AdaptiveAvgPool2D, BatchNorm
+from paddle.nn import Conv2D, MaxPool2D, AdaptiveAvgPool2D
 from paddle.nn.initializer import KaimingNormal
 from paddle.nn.initializer import KaimingNormal
 from paddle.regularizer import L2Decay
 from paddle.regularizer import L2Decay
 
 

+ 6 - 1
paddlex/ppdet/modeling/backbones/swin_transformer.py

@@ -493,8 +493,13 @@ class BasicLayer(nn.Layer):
         cnt = 0
         cnt = 0
         for h in h_slices:
         for h in h_slices:
             for w in w_slices:
             for w in w_slices:
-                img_mask[:, h, w, :] = cnt
+                try:
+                    img_mask[:, h, w, :] = cnt
+                except:
+                    pass
+
                 cnt += 1
                 cnt += 1
+
         mask_windows = window_partition(
         mask_windows = window_partition(
             img_mask, self.window_size)  # nW, window_size, window_size, 1
             img_mask, self.window_size)  # nW, window_size, window_size, 1
         mask_windows = mask_windows.reshape(
         mask_windows = mask_windows.reshape(

+ 2 - 2
paddlex/ppdet/modeling/proposal_generator/target.py

@@ -52,8 +52,8 @@ def rpn_anchor_target(anchors,
             labels = paddle.scatter(labels, fg_inds, paddle.ones_like(fg_inds))
             labels = paddle.scatter(labels, fg_inds, paddle.ones_like(fg_inds))
         # Step3: make output
         # Step3: make output
         if gt_bbox.shape[0] == 0:
         if gt_bbox.shape[0] == 0:
-            matched_gt_boxes = paddle.zeros([0, 4])
-            tgt_delta = paddle.zeros([0, 4])
+            matched_gt_boxes = paddle.zeros([matches.shape[0], 4])
+            tgt_delta = paddle.zeros([matches.shape[0], 4])
         else:
         else:
             matched_gt_boxes = paddle.gather(gt_bbox, matches)
             matched_gt_boxes = paddle.gather(gt_bbox, matches)
             tgt_delta = bbox2delta(anchors, matched_gt_boxes, weights)
             tgt_delta = bbox2delta(anchors, matched_gt_boxes, weights)