diff --git a/paddle/fluid/API.spec b/paddle/fluid/API.spec index df3497de209e3b6ede6986e1ac5f92c4427ca9bd..8ad66eaa4d5ffb018463cef62b2b97b1cd4bd5fb 100644 --- a/paddle/fluid/API.spec +++ b/paddle/fluid/API.spec @@ -327,7 +327,7 @@ paddle.fluid.layers.generate_mask_labels (ArgSpec(args=['im_info', 'gt_classes', paddle.fluid.layers.iou_similarity (ArgSpec(args=['x', 'y', 'name'], varargs=None, keywords=None, defaults=(None,)), ('document', '587845f60c5d97ffdf2dfd21da52eca1')) paddle.fluid.layers.box_coder (ArgSpec(args=['prior_box', 'prior_box_var', 'target_box', 'code_type', 'box_normalized', 'name', 'axis'], varargs=None, keywords=None, defaults=('encode_center_size', True, None, 0)), ('document', '032d0f4b7d8f6235ee5d91e473344f0e')) paddle.fluid.layers.polygon_box_transform (ArgSpec(args=['input', 'name'], varargs=None, keywords=None, defaults=(None,)), ('document', '0e5ac2507723a0b5adec473f9556799b')) -paddle.fluid.layers.yolov3_loss (ArgSpec(args=['x', 'gtbox', 'gtlabel', 'anchors', 'anchor_mask', 'class_num', 'ignore_thresh', 'downsample_ratio', 'name'], varargs=None, keywords=None, defaults=(None,)), ('document', '991e934c3e09abf0edec7c9c978b4691')) +paddle.fluid.layers.yolov3_loss (ArgSpec(args=['x', 'gtbox', 'gtlabel', 'anchors', 'anchor_mask', 'class_num', 'ignore_thresh', 'downsample_ratio', 'name', 'gtscore', 'use_label_smooth'], varargs=None, keywords=None, defaults=(None, None, True)), ('document', '991e934c3e09abf0edec7c9c978b4691')) paddle.fluid.layers.box_clip (ArgSpec(args=['input', 'im_info', 'name'], varargs=None, keywords=None, defaults=(None,)), ('document', '397e9e02b451d99c56e20f268fa03f2e')) paddle.fluid.layers.multiclass_nms (ArgSpec(args=['bboxes', 'scores', 'score_threshold', 'nms_top_k', 'keep_top_k', 'nms_threshold', 'normalized', 'nms_eta', 'background_label', 'name'], varargs=None, keywords=None, defaults=(0.3, True, 1.0, 0, None)), ('document', 'ca7d1107b6c5d2d6d8221039a220fde0')) paddle.fluid.layers.distribute_fpn_proposals (ArgSpec(args=['fpn_rois', 'min_level', 'max_level', 'refer_level', 'refer_scale', 'name'], varargs=None, keywords=None, defaults=(None,)), ('document', '7bb011ec26bace2bc23235aa4a17647d')) diff --git a/paddle/fluid/operators/detection/yolov3_loss_op.cc b/paddle/fluid/operators/detection/yolov3_loss_op.cc index 3b1d4d2a8052ca86d76ef12b140d83f66a837623..2dbe46de0be137c006d2a7c3a997699fbd773364 100644 --- a/paddle/fluid/operators/detection/yolov3_loss_op.cc +++ b/paddle/fluid/operators/detection/yolov3_loss_op.cc @@ -128,7 +128,8 @@ class Yolov3LossOpMaker : public framework::OpProtoAndCheckerMaker { "The score of GTLabel, This is a 2-D tensor in same shape " "GTLabel, and score values should in range (0, 1). This " "input is for GTLabel score can be not 1.0 in image mixup " - "augmentation."); + "augmentation.") + .AsDispensable(); AddOutput("Loss", "The output yolov3 loss tensor, " "This is a 1-D tensor with shape of [N]"); diff --git a/paddle/fluid/operators/detection/yolov3_loss_op.h b/paddle/fluid/operators/detection/yolov3_loss_op.h index 54038b6e657b4c46b015d21cc9e0961458eacecc..df6f28d41d12c78b4a28b5789fb14216fa0d659b 100644 --- a/paddle/fluid/operators/detection/yolov3_loss_op.h +++ b/paddle/fluid/operators/detection/yolov3_loss_op.h @@ -289,7 +289,6 @@ class Yolov3LossKernel : public framework::OpKernel { const T* input_data = input->data(); const T* gt_box_data = gt_box->data(); const int* gt_label_data = gt_label->data(); - const T* gt_score_data = gt_score->data(); T* loss_data = loss->mutable_data({n}, ctx.GetPlace()); memset(loss_data, 0, loss->numel() * sizeof(T)); T* obj_mask_data = @@ -298,6 +297,19 @@ class Yolov3LossKernel : public framework::OpKernel { int* gt_match_mask_data = gt_match_mask->mutable_data({n, b}, ctx.GetPlace()); + const T* gt_score_data; + if (!gt_score) { + Tensor _gt_score; + _gt_score.mutable_data({n, b}, ctx.GetPlace()); + math::SetConstant()( + ctx.template device_context(), &_gt_score, + static_cast(1.0)); + gt_score = &_gt_score; + gt_score_data = _gt_score.data(); + } else { + gt_score_data = gt_score->data(); + } + // calc valid gt box mask, avoid calc duplicately in following code Tensor gt_valid_mask; bool* gt_valid_mask_data = @@ -432,7 +444,6 @@ class Yolov3LossGradKernel : public framework::OpKernel { const T* input_data = input->data(); const T* gt_box_data = gt_box->data(); const int* gt_label_data = gt_label->data(); - const T* gt_score_data = gt_score->data(); const T* loss_grad_data = loss_grad->data(); const T* obj_mask_data = objness_mask->data(); const int* gt_match_mask_data = gt_match_mask->data(); @@ -440,6 +451,19 @@ class Yolov3LossGradKernel : public framework::OpKernel { input_grad->mutable_data({n, c, h, w}, ctx.GetPlace()); memset(input_grad_data, 0, input_grad->numel() * sizeof(T)); + const T* gt_score_data; + if (!gt_score) { + Tensor _gt_score; + _gt_score.mutable_data({n, b}, ctx.GetPlace()); + math::SetConstant()( + ctx.template device_context(), &_gt_score, + static_cast(1.0)); + gt_score = &_gt_score; + gt_score_data = _gt_score.data(); + } else { + gt_score_data = gt_score->data(); + } + for (int i = 0; i < n; i++) { for (int t = 0; t < b; t++) { int mask_idx = gt_match_mask_data[i * b + t]; diff --git a/python/paddle/fluid/tests/unittests/test_yolov3_loss_op.py b/python/paddle/fluid/tests/unittests/test_yolov3_loss_op.py index b3d1ff8058e6a59378e9e55a91bc893b87e18f0e..e4d6edc72c0ca888e271101f079cdcc6fb4e8a70 100644 --- a/python/paddle/fluid/tests/unittests/test_yolov3_loss_op.py +++ b/python/paddle/fluid/tests/unittests/test_yolov3_loss_op.py @@ -168,7 +168,6 @@ class TestYolov3LossOp(OpTest): x = logit(np.random.uniform(0, 1, self.x_shape).astype('float32')) gtbox = np.random.random(size=self.gtbox_shape).astype('float32') gtlabel = np.random.randint(0, self.class_num, self.gtbox_shape[:2]) - gtscore = np.random.random(self.gtbox_shape[:2]).astype('float32') gtmask = np.random.randint(0, 2, self.gtbox_shape[:2]) gtbox = gtbox * gtmask[:, :, np.newaxis] gtlabel = gtlabel * gtmask @@ -186,8 +185,13 @@ class TestYolov3LossOp(OpTest): 'X': x, 'GTBox': gtbox.astype('float32'), 'GTLabel': gtlabel.astype('int32'), - 'GTScore': gtscore.astype('float32') } + + gtscore = np.ones(self.gtbox_shape[:2]).astype('float32') + if self.gtscore: + gtscore = np.random.random(self.gtbox_shape[:2]).astype('float32') + self.inputs['GTScore'] = gtscore + loss, objness, gt_matches = YOLOv3Loss(x, gtbox, gtlabel, gtscore, self.attrs) self.outputs = { @@ -202,11 +206,7 @@ class TestYolov3LossOp(OpTest): def test_check_grad_ignore_gtbox(self): place = core.CPUPlace() - self.check_grad_with_place( - place, ['X'], - 'Loss', - no_grad_set=set(["GTBox", "GTLabel", "GTScore"]), - max_relative_error=0.2) + self.check_grad_with_place(place, ['X'], 'Loss', max_relative_error=0.2) def initTestCase(self): self.anchors = [ @@ -215,17 +215,45 @@ class TestYolov3LossOp(OpTest): ] self.anchor_mask = [0, 1, 2] self.class_num = 5 - self.ignore_thresh = 0.5 + self.ignore_thresh = 0.7 self.downsample_ratio = 32 self.x_shape = (3, len(self.anchor_mask) * (5 + self.class_num), 5, 5) self.gtbox_shape = (3, 5, 4) + self.gtscore = True self.use_label_smooth = True class TestYolov3LossWithoutLabelSmooth(TestYolov3LossOp): - def set_label_smooth(self): + def initTestCase(self): + self.anchors = [ + 10, 13, 16, 30, 33, 23, 30, 61, 62, 45, 59, 119, 116, 90, 156, 198, + 373, 326 + ] + self.anchor_mask = [0, 1, 2] + self.class_num = 5 + self.ignore_thresh = 0.7 + self.downsample_ratio = 32 + self.x_shape = (3, len(self.anchor_mask) * (5 + self.class_num), 5, 5) + self.gtbox_shape = (3, 5, 4) + self.gtscore = True self.use_label_smooth = False +class TestYolov3LossNoGTScore(TestYolov3LossOp): + def initTestCase(self): + self.anchors = [ + 10, 13, 16, 30, 33, 23, 30, 61, 62, 45, 59, 119, 116, 90, 156, 198, + 373, 326 + ] + self.anchor_mask = [0, 1, 2] + self.class_num = 5 + self.ignore_thresh = 0.7 + self.downsample_ratio = 32 + self.x_shape = (3, len(self.anchor_mask) * (5 + self.class_num), 5, 5) + self.gtbox_shape = (3, 5, 4) + self.gtscore = False + self.use_label_smooth = True + + if __name__ == "__main__": unittest.main()