From e5fe96e74462bf9ed5164811bc7d0914100b3134 Mon Sep 17 00:00:00 2001 From: Yuan Gao Date: Sat, 11 Jan 2020 17:55:01 +0800 Subject: [PATCH] Add the DropBlock module to Yolo v3 (#158) * add dropblock module * move dropblock module from yolo_head to ops * fix obj365 num classes --- ...cascade_rcnn_dcnv2_se154_vd_fpn_gn_cas.yml | 2 +- ppdet/modeling/anchor_heads/yolo_head.py | 20 ++++++ ppdet/modeling/ops.py | 64 +++++++++++++++++-- 3 files changed, 81 insertions(+), 5 deletions(-) diff --git a/configs/obj365/cascade_rcnn_dcnv2_se154_vd_fpn_gn_cas.yml b/configs/obj365/cascade_rcnn_dcnv2_se154_vd_fpn_gn_cas.yml index 7b0e67a7a..4e9326e8d 100644 --- a/configs/obj365/cascade_rcnn_dcnv2_se154_vd_fpn_gn_cas.yml +++ b/configs/obj365/cascade_rcnn_dcnv2_se154_vd_fpn_gn_cas.yml @@ -8,7 +8,7 @@ save_dir: output pretrain_weights: https://paddlemodels.bj.bcebos.com/object_detection/cascade_mask_rcnn_dcnv2_se154_vd_fpn_gn_coco_pretrained.tar weights: output/cascade_rcnn_dcnv2_se154_vd_fpn_gn_cas/model_final metric: COCO -num_classes: 81 +num_classes: 501 CascadeRCNN: backbone: ResNet diff --git a/ppdet/modeling/anchor_heads/yolo_head.py b/ppdet/modeling/anchor_heads/yolo_head.py index a140f45c4..647647596 100644 --- a/ppdet/modeling/anchor_heads/yolo_head.py +++ b/ppdet/modeling/anchor_heads/yolo_head.py @@ -23,6 +23,7 @@ from paddle.fluid.regularizer import L2Decay from ppdet.modeling.ops import MultiClassNMS from ppdet.modeling.losses.yolo_loss import YOLOv3Loss from ppdet.core.workspace import register +from ppdet.modeling.ops import DropBlock __all__ = ['YOLOv3Head'] @@ -48,6 +49,9 @@ class YOLOv3Head(object): anchors=[[10, 13], [16, 30], [33, 23], [30, 61], [62, 45], [59, 119], [116, 90], [156, 198], [373, 326]], anchor_masks=[[6, 7, 8], [3, 4, 5], [0, 1, 2]], + drop_block=False, + block_size=3, + keep_prob=0.9, yolo_loss="YOLOv3Loss", nms=MultiClassNMS( score_threshold=0.01, @@ -63,6 +67,9 @@ class YOLOv3Head(object): self.yolo_loss = yolo_loss self.nms = nms self.prefix_name = weight_prefix_name + self.drop_block = drop_block + self.block_size = block_size + self.keep_prob = keep_prob if isinstance(nms, dict): self.nms = MultiClassNMS(**nms) @@ -126,6 +133,19 @@ class YOLOv3Head(object): padding=1, is_test=is_test, name='{}.{}.1'.format(name, j)) + if self.drop_block and j == 0 and channel != 512: + conv = DropBlock( + conv, + block_size=self.block_size, + keep_prob=self.keep_prob, + is_test=is_test) + + if self.drop_block and channel == 512: + conv = DropBlock( + conv, + block_size=self.block_size, + keep_prob=self.keep_prob, + is_test=is_test) route = self._conv_bn( conv, channel, diff --git a/ppdet/modeling/ops.py b/ppdet/modeling/ops.py index 357088a4f..dffa1a670 100644 --- a/ppdet/modeling/ops.py +++ b/ppdet/modeling/ops.py @@ -21,10 +21,10 @@ from paddle.fluid.regularizer import L2Decay from ppdet.core.workspace import register, serializable __all__ = [ - 'AnchorGenerator', 'RPNTargetAssign', 'GenerateProposals', 'MultiClassNMS', - 'BBoxAssigner', 'MaskAssigner', 'RoIAlign', 'RoIPool', 'MultiBoxHead', - 'SSDOutputDecoder', 'RetinaTargetAssign', 'RetinaOutputDecoder', 'ConvNorm', - 'MultiClassSoftNMS', 'MultiClassDiouNMS' + 'AnchorGenerator', 'DropBlock', 'RPNTargetAssign', 'GenerateProposals', + 'MultiClassNMS', 'BBoxAssigner', 'MaskAssigner', 'RoIAlign', 'RoIPool', + 'MultiBoxHead', 'SSDOutputDecoder', 'RetinaTargetAssign', + 'RetinaOutputDecoder', 'ConvNorm', 'MultiClassSoftNMS' ] @@ -112,6 +112,62 @@ def ConvNorm(input, return out +def DropBlock(input, block_size, keep_prob, is_test): + if is_test: + return input + + def CalculateGamma(input, block_size, keep_prob): + input_shape = fluid.layers.shape(input) + feat_shape_tmp = fluid.layers.slice(input_shape, [0], [3], [4]) + feat_shape_tmp = fluid.layers.cast(feat_shape_tmp, dtype="float32") + feat_shape_t = fluid.layers.reshape(feat_shape_tmp, [1, 1, 1, 1]) + feat_area = fluid.layers.pow(feat_shape_t, factor=2) + + block_shape_t = fluid.layers.fill_constant( + shape=[1, 1, 1, 1], value=block_size, dtype='float32') + block_area = fluid.layers.pow(block_shape_t, factor=2) + + useful_shape_t = feat_shape_t - block_shape_t + 1 + useful_area = fluid.layers.pow(useful_shape_t, factor=2) + + upper_t = feat_area * (1 - keep_prob) + bottom_t = block_area * useful_area + output = upper_t / bottom_t + return output + + gamma = CalculateGamma(input, block_size=block_size, keep_prob=keep_prob) + input_shape = fluid.layers.shape(input) + p = fluid.layers.expand_as(gamma, input) + + input_shape_tmp = fluid.layers.cast(input_shape, dtype="int64") + random_matrix = fluid.layers.uniform_random( + input_shape_tmp, dtype='float32', min=0.0, max=1.0) + one_zero_m = fluid.layers.less_than(random_matrix, p) + one_zero_m.stop_gradient = True + one_zero_m = fluid.layers.cast(one_zero_m, dtype="float32") + + mask_flag = fluid.layers.pool2d( + one_zero_m, + pool_size=block_size, + pool_type='max', + pool_stride=1, + pool_padding=block_size // 2) + mask = 1.0 - mask_flag + + elem_numel = fluid.layers.reduce_prod(input_shape) + elem_numel = fluid.layers.cast(elem_numel, dtype="float32") + elem_numel_tmp = fluid.layers.reshape(elem_numel, [1, 1, 1, 1]) + elem_numel_m = fluid.layers.expand_as(elem_numel_tmp, input) + + elem_sum = fluid.layers.reduce_sum(mask) + elem_sum_tmp = fluid.layers.cast(elem_sum, dtype="float32") + elem_sum_tmp = fluid.layers.reshape(elem_sum_tmp, [1, 1, 1, 1]) + elem_sum_m = fluid.layers.expand_as(elem_sum_tmp, input) + + output = input * mask * elem_numel_m / elem_sum_m + return output + + @register @serializable class AnchorGenerator(object): -- GitLab