From af124dcdf6891390202fffb7c30daf70aa3c8659 Mon Sep 17 00:00:00 2001 From: dengkaipeng Date: Mon, 14 Jan 2019 21:30:25 +0800 Subject: [PATCH] fix API error --- paddle/fluid/API.spec | 2 +- paddle/fluid/operators/yolov3_loss_op.h | 55 ++++++++++++------- python/paddle/fluid/layers/detection.py | 2 +- .../tests/unittests/test_yolov3_loss_op.py | 11 ++-- 4 files changed, 43 insertions(+), 27 deletions(-) diff --git a/paddle/fluid/API.spec b/paddle/fluid/API.spec index d773c2518..e71e494f9 100644 --- a/paddle/fluid/API.spec +++ b/paddle/fluid/API.spec @@ -324,7 +324,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,)) paddle.fluid.layers.box_coder ArgSpec(args=['prior_box', 'prior_box_var', 'target_box', 'code_type', 'box_normalized', 'name'], varargs=None, keywords=None, defaults=('encode_center_size', True, None)) paddle.fluid.layers.polygon_box_transform ArgSpec(args=['input', 'name'], varargs=None, keywords=None, defaults=(None,)) -paddle.fluid.layers.yolov3_loss ArgSpec(args=['x', 'gtbox', 'gtlabel', 'gtscore', 'anchors', 'anchor_mask', 'class_num', 'ignore_thresh', 'downsample', 'label_smooth', 'name'], varargs=None, keywords=None, defaults=(None,)) +paddle.fluid.layers.yolov3_loss ArgSpec(args=['x', 'gtbox', 'gtlabel', 'gtscore', 'anchors', 'anchor_mask', 'class_num', 'ignore_thresh', 'downsample', 'use_label_smooth', 'name'], varargs=None, keywords=None, defaults=(True, None,)) 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)) paddle.fluid.layers.accuracy ArgSpec(args=['input', 'label', 'k', 'correct', 'total'], varargs=None, keywords=None, defaults=(1, None, None)) paddle.fluid.layers.auc ArgSpec(args=['input', 'label', 'curve', 'num_thresholds', 'topk', 'slide_steps'], varargs=None, keywords=None, defaults=('ROC', 4095, 1, 1)) diff --git a/paddle/fluid/operators/yolov3_loss_op.h b/paddle/fluid/operators/yolov3_loss_op.h index 5cb48b7cd..de01a01a4 100644 --- a/paddle/fluid/operators/yolov3_loss_op.h +++ b/paddle/fluid/operators/yolov3_loss_op.h @@ -121,13 +121,13 @@ template static void CalcBoxLocationLoss(T* loss, const T* input, Box gt, std::vector anchors, int an_idx, int box_idx, int gi, int gj, int grid_size, - int input_size, int stride) { + int input_size, int stride, T score) { T tx = gt.x * grid_size - gi; T ty = gt.y * grid_size - gj; T tw = std::log(gt.w * input_size / anchors[2 * an_idx]); T th = std::log(gt.h * input_size / anchors[2 * an_idx + 1]); - T scale = 2.0 - gt.w * gt.h; + T scale = (2.0 - gt.w * gt.h) * score; loss[0] += SCE(input[box_idx], tx) * scale; loss[0] += SCE(input[box_idx + stride], ty) * scale; loss[0] += L1Loss(input[box_idx + 2 * stride], tw) * scale; @@ -138,13 +138,14 @@ template static void CalcBoxLocationLossGrad(T* input_grad, const T loss, const T* input, Box gt, std::vector anchors, int an_idx, int box_idx, int gi, int gj, - int grid_size, int input_size, int stride) { + int grid_size, int input_size, int stride, + T score) { T tx = gt.x * grid_size - gi; T ty = gt.y * grid_size - gj; T tw = std::log(gt.w * input_size / anchors[2 * an_idx]); T th = std::log(gt.h * input_size / anchors[2 * an_idx + 1]); - T scale = 2.0 - gt.w * gt.h; + T scale = (2.0 - gt.w * gt.h) * score; input_grad[box_idx] = SCEGrad(input[box_idx], tx) * scale * loss; input_grad[box_idx + stride] = SCEGrad(input[box_idx + stride], ty) * scale * loss; @@ -157,10 +158,11 @@ static void CalcBoxLocationLossGrad(T* input_grad, const T loss, const T* input, template static inline void CalcLabelLoss(T* loss, const T* input, const int index, const int label, const int class_num, - const int stride, const T pos, const T neg) { + const int stride, const T pos, const T neg, + T score) { for (int i = 0; i < class_num; i++) { T pred = input[index + i * stride]; - loss[0] += SCE(pred, (i == label) ? pos : neg); + loss[0] += SCE(pred, (i == label) ? pos : neg) * score; } } @@ -168,12 +170,12 @@ template static inline void CalcLabelLossGrad(T* input_grad, const T loss, const T* input, const int index, const int label, const int class_num, - const int stride, const T pos, - const T neg) { + const int stride, const T pos, const T neg, + T score) { for (int i = 0; i < class_num; i++) { T pred = input[index + i * stride]; input_grad[index + i * stride] = - SCEGrad(pred, (i == label) ? pos : neg) * loss; + SCEGrad(pred, (i == label) ? pos : neg) * score * loss; } } @@ -187,8 +189,12 @@ static inline void CalcObjnessLoss(T* loss, const T* input, const T* objness, for (int k = 0; k < h; k++) { for (int l = 0; l < w; l++) { T obj = objness[k * w + l]; - if (obj > -0.5) { - loss[i] += SCE(input[k * w + l], obj); + if (obj > 1e-5) { + // positive sample: obj = mixup score + loss[i] += SCE(input[k * w + l], 1.0) * obj; + } else if (obj > -0.5) { + // negetive sample: obj = 0 + loss[i] += SCE(input[k * w + l], 0.0); } } } @@ -209,8 +215,11 @@ static inline void CalcObjnessLossGrad(T* input_grad, const T* loss, for (int k = 0; k < h; k++) { for (int l = 0; l < w; l++) { T obj = objness[k * w + l]; - if (obj > -0.5) { - input_grad[k * w + l] = SCEGrad(input[k * w + l], obj) * loss[i]; + if (obj > 1e-5) { + input_grad[k * w + l] = + SCEGrad(input[k * w + l], 1.0) * obj * loss[i]; + } else if (obj > -0.5) { + input_grad[k * w + l] = SCEGrad(input[k * w + l], 0.0) * loss[i]; } } } @@ -315,7 +324,7 @@ class Yolov3LossKernel : public framework::OpKernel { if (best_iou > ignore_thresh) { int obj_idx = (i * mask_num + j) * stride + k * w + l; - obj_mask_data[obj_idx] = static_cast(-1.0); + obj_mask_data[obj_idx] = static_cast(-1); } // TODO(dengkaipeng): all losses should be calculated if best IoU // is bigger then truth thresh should be calculated here, but @@ -357,12 +366,12 @@ class Yolov3LossKernel : public framework::OpKernel { int mask_idx = GetMaskIndex(anchor_mask, best_n); gt_match_mask_data[i * b + t] = mask_idx; if (mask_idx >= 0) { + T score = gt_score_data[i * b + t]; int box_idx = GetEntryIndex(i, mask_idx, gj * w + gi, mask_num, an_stride, stride, 0); CalcBoxLocationLoss(loss_data + i, input_data, gt, anchors, best_n, - box_idx, gi, gj, h, input_size, stride); + box_idx, gi, gj, h, input_size, stride, score); - T score = gt_score_data[i * b + t]; int obj_idx = (i * mask_num + mask_idx) * stride + gj * w + gi; obj_mask_data[obj_idx] = score; @@ -370,7 +379,7 @@ class Yolov3LossKernel : public framework::OpKernel { int label_idx = GetEntryIndex(i, mask_idx, gj * w + gi, mask_num, an_stride, stride, 5); CalcLabelLoss(loss_data + i, input_data, label_idx, label, - class_num, stride, label_pos, label_neg); + class_num, stride, label_pos, label_neg, score); } } } @@ -387,6 +396,7 @@ class Yolov3LossGradKernel : public framework::OpKernel { auto* input = ctx.Input("X"); auto* gt_box = ctx.Input("GTBox"); auto* gt_label = ctx.Input("GTLabel"); + auto* gt_score = ctx.Input("GTScore"); auto* input_grad = ctx.Output(framework::GradVarName("X")); auto* loss_grad = ctx.Input(framework::GradVarName("Loss")); auto* objness_mask = ctx.Input("ObjectnessMask"); @@ -418,6 +428,7 @@ 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(); @@ -429,22 +440,24 @@ class Yolov3LossGradKernel : public framework::OpKernel { for (int t = 0; t < b; t++) { int mask_idx = gt_match_mask_data[i * b + t]; if (mask_idx >= 0) { + T score = gt_score_data[i * b + t]; Box gt = GetGtBox(gt_box_data, i, b, t); int gi = static_cast(gt.x * w); int gj = static_cast(gt.y * h); int box_idx = GetEntryIndex(i, mask_idx, gj * w + gi, mask_num, an_stride, stride, 0); - CalcBoxLocationLossGrad( - input_grad_data, loss_grad_data[i], input_data, gt, anchors, - anchor_mask[mask_idx], box_idx, gi, gj, h, input_size, stride); + CalcBoxLocationLossGrad(input_grad_data, loss_grad_data[i], + input_data, gt, anchors, + anchor_mask[mask_idx], box_idx, gi, gj, h, + input_size, stride, score); int label = gt_label_data[i * b + t]; int label_idx = GetEntryIndex(i, mask_idx, gj * w + gi, mask_num, an_stride, stride, 5); CalcLabelLossGrad(input_grad_data, loss_grad_data[i], input_data, label_idx, label, class_num, stride, label_pos, - label_neg); + label_neg, score); } } } diff --git a/python/paddle/fluid/layers/detection.py b/python/paddle/fluid/layers/detection.py index febfc8e12..07df60169 100644 --- a/python/paddle/fluid/layers/detection.py +++ b/python/paddle/fluid/layers/detection.py @@ -482,7 +482,7 @@ def yolov3_loss(x, raise TypeError("Attr anchor_mask of yolov3_loss must be list or tuple") if not isinstance(class_num, int): raise TypeError("Attr class_num of yolov3_loss must be an integer") - if not isinstance(use_label_smooth, int): + if not isinstance(use_label_smooth, bool): raise TypeError("Attr ues_label_smooth of yolov3 must be a bool value") if not isinstance(ignore_thresh, float): raise TypeError( 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 426a64f7a..ff76b7636 100644 --- a/python/paddle/fluid/tests/unittests/test_yolov3_loss_op.py +++ b/python/paddle/fluid/tests/unittests/test_yolov3_loss_op.py @@ -142,7 +142,7 @@ def YOLOv3Loss(x, gtbox, gtlabel, gtscore, attrs): ty = gtbox[i, j, 1] * w - gj tw = np.log(gtbox[i, j, 2] * input_size / mask_anchors[an_idx][0]) th = np.log(gtbox[i, j, 3] * input_size / mask_anchors[an_idx][1]) - scale = 2.0 - gtbox[i, j, 2] * gtbox[i, j, 3] + scale = (2.0 - gtbox[i, j, 2] * gtbox[i, j, 3]) * gtscore[i, j] loss[i] += sce(x[i, an_idx, gj, gi, 0], tx) * scale loss[i] += sce(x[i, an_idx, gj, gi, 1], ty) * scale loss[i] += l1loss(x[i, an_idx, gj, gi, 2], tw) * scale @@ -152,11 +152,14 @@ def YOLOv3Loss(x, gtbox, gtlabel, gtscore, attrs): for label_idx in range(class_num): loss[i] += sce(x[i, an_idx, gj, gi, 5 + label_idx], label_pos - if label_idx == gtlabel[i, j] else label_neg) + if label_idx == gtlabel[i, j] else + label_neg) * gtscore[i, j] for j in range(mask_num * h * w): - if objness[i, j] >= 0: - loss[i] += sce(pred_obj[i, j], objness[i, j]) + if objness[i, j] > 0: + loss[i] += sce(pred_obj[i, j], 1.0) * objness[i, j] + elif objness[i, j] == 0: + loss[i] += sce(pred_obj[i, j], 0.0) return (loss, objness.reshape((n, mask_num, h, w)).astype('float32'), \ gt_matches.astype('int32')) -- GitLab