diff --git a/configs/ppyolo/README.md b/configs/ppyolo/README.md
index ee80a5ee22eeddc4acf9f7d0fa1c1dae475a3e3c..f9786a086bdb2f6906471e7f0e54295e54c380c3 100644
--- a/configs/ppyolo/README.md
+++ b/configs/ppyolo/README.md
@@ -72,10 +72,18 @@ PP-YOLO improved performance and speed of YOLOv3 with following methods:
| PP-YOLO_MobileNetV3_large | 4 | 32 | 18MB | 320 | 22.0 | 14.1 | [model](https://paddlemodels.bj.bcebos.com/object_detection/ppyolo_mobilenet_v3_large.pdparams) | [config](https://github.com/PaddlePaddle/PaddleDetection/tree/master/configs/ppyolo/ppyolo_mobilenet_v3_large.yml) |
| PP-YOLO_MobileNetV3_small | 4 | 32 | 11MB | 320 | 16.8 | 21.5 | [model](https://paddlemodels.bj.bcebos.com/object_detection/ppyolo_mobilenet_v3_small.pdparams) | [config](https://github.com/PaddlePaddle/PaddleDetection/tree/master/configs/ppyolo/ppyolo_mobilenet_v3_small.yml) |
+**Notes:**
+
- PP-YOLO_MobileNetV3 is trained on COCO train2017 datast and evaluated on val2017 dataset,Box APval is evaluation results of `mAP(IoU=0.5:0.95)`.
- PP-YOLO_MobileNetV3 used 4 GPUs for training and mini-batch size as 32 on each GPU, if GPU number and mini-batch size is changed, learning rate and iteration times should be adjusted according [FAQ](../../docs/FAQ.md).
- PP-YOLO_MobileNetV3 inference speed is tested on Kirin 990 with 1 thread.
+### Slim PP-YOLO
+
+| Model | GPU number | images/GPU | Prune Ratio | Teacher Model | Model Size | input shape | Box APval | Kirin 990(FPS) | download | config |
+|:----------------------------:|:----------:|:----------:| :---------: | :-----------------------: | :--------: | :----------:| :------------------: | :------------: | :------: | :-----: |
+| PP-YOLO_MobileNetV3_small | 4 | 32 | 75% | PP-YOLO_MobileNetV3_large | 4.1MB | 320 | 14.4 | 21.5 | [model](https://paddlemodels.bj.bcebos.com/object_detection/ppyolo_mobilenet_v3_small.pdparams) | [config](https://github.com/PaddlePaddle/PaddleDetection/tree/master/configs/ppyolo/ppyolo_mobilenet_v3_small.yml) |
+
## Getting Start
### 1. Training
diff --git a/slim/extensions/distill_pruned_model/distill_pruned_model.py b/slim/extensions/distill_pruned_model/distill_pruned_model.py
index a2adc6cf7652026fb493e7b141e295454bd450e4..386429f9a46aad004a77253f0c00a985ebdc6e7e 100644
--- a/slim/extensions/distill_pruned_model/distill_pruned_model.py
+++ b/slim/extensions/distill_pruned_model/distill_pruned_model.py
@@ -44,7 +44,7 @@ logging.basicConfig(level=logging.INFO, format=FORMAT)
logger = logging.getLogger(__name__)
-def split_distill(split_output_names, weight):
+def split_distill(split_output_names, weight, target_number):
"""
Add fine grained distillation losses.
Each loss is composed by distill_reg_loss, distill_cls_loss and
@@ -54,16 +54,27 @@ def split_distill(split_output_names, weight):
for name in split_output_names:
student_var.append(fluid.default_main_program().global_block().var(
name))
- s_x0, s_y0, s_w0, s_h0, s_obj0, s_cls0 = student_var[0:6]
- s_x1, s_y1, s_w1, s_h1, s_obj1, s_cls1 = student_var[6:12]
- s_x2, s_y2, s_w2, s_h2, s_obj2, s_cls2 = student_var[12:18]
+ s_x, s_y, s_w, s_h, s_obj, s_cls = [], [], [], [], [], []
+ for i in range(target_number):
+ s_x.append(student_var[i * 6])
+ s_y.append(student_var[i * 6 + 1])
+ s_w.append(student_var[i * 6 + 2])
+ s_h.append(student_var[i * 6 + 3])
+ s_obj.append(student_var[i * 6 + 4])
+ s_cls.append(student_var[i * 6 + 5])
+
teacher_var = []
for name in split_output_names:
teacher_var.append(fluid.default_main_program().global_block().var(
'teacher_' + name))
- t_x0, t_y0, t_w0, t_h0, t_obj0, t_cls0 = teacher_var[0:6]
- t_x1, t_y1, t_w1, t_h1, t_obj1, t_cls1 = teacher_var[6:12]
- t_x2, t_y2, t_w2, t_h2, t_obj2, t_cls2 = teacher_var[12:18]
+ t_x, t_y, t_w, t_h, t_obj, t_cls = [], [], [], [], [], []
+ for i in range(target_number):
+ t_x.append(teacher_var[i * 6])
+ t_y.append(teacher_var[i * 6 + 1])
+ t_w.append(teacher_var[i * 6 + 2])
+ t_h.append(teacher_var[i * 6 + 3])
+ t_obj.append(teacher_var[i * 6 + 4])
+ t_cls.append(teacher_var[i * 6 + 5])
def obj_weighted_reg(sx, sy, sw, sh, tx, ty, tw, th, tobj):
loss_x = fluid.layers.sigmoid_cross_entropy_with_logits(
@@ -92,26 +103,21 @@ def split_distill(split_output_names, weight):
fluid.layers.sigmoid_cross_entropy_with_logits(sobj, obj_mask))
return loss
- distill_reg_loss0 = obj_weighted_reg(s_x0, s_y0, s_w0, s_h0, t_x0, t_y0,
- t_w0, t_h0, t_obj0)
- distill_reg_loss1 = obj_weighted_reg(s_x1, s_y1, s_w1, s_h1, t_x1, t_y1,
- t_w1, t_h1, t_obj1)
- distill_reg_loss2 = obj_weighted_reg(s_x2, s_y2, s_w2, s_h2, t_x2, t_y2,
- t_w2, t_h2, t_obj2)
- distill_reg_loss = fluid.layers.sum(
- [distill_reg_loss0, distill_reg_loss1, distill_reg_loss2])
-
- distill_cls_loss0 = obj_weighted_cls(s_cls0, t_cls0, t_obj0)
- distill_cls_loss1 = obj_weighted_cls(s_cls1, t_cls1, t_obj1)
- distill_cls_loss2 = obj_weighted_cls(s_cls2, t_cls2, t_obj2)
- distill_cls_loss = fluid.layers.sum(
- [distill_cls_loss0, distill_cls_loss1, distill_cls_loss2])
-
- distill_obj_loss0 = obj_loss(s_obj0, t_obj0)
- distill_obj_loss1 = obj_loss(s_obj1, t_obj1)
- distill_obj_loss2 = obj_loss(s_obj2, t_obj2)
- distill_obj_loss = fluid.layers.sum(
- [distill_obj_loss0, distill_obj_loss1, distill_obj_loss2])
+ distill_reg_losses = []
+ for i in range(target_number):
+ distill_reg_losses.append(obj_weighted_reg(s_x[i], s_y[i], s_w[i], s_h[i], t_x[i], t_y[i], t_w[i], t_h[i], t_obj[i]))
+ distill_reg_loss = fluid.layers.sum(distill_reg_losses)
+
+ distill_cls_losses = []
+ for i in range(target_number):
+ distill_cls_losses.append(obj_weighted_cls(s_cls[i], t_cls[i], t_obj[i]))
+ distill_cls_loss = fluid.layers.sum(distill_cls_losses)
+
+ distill_obj_losses = []
+ for i in range(target_number):
+ distill_obj_losses.append(obj_loss(s_obj[i], t_obj[i]))
+ distill_obj_loss = fluid.layers.sum(distill_obj_losses)
+
loss = (distill_reg_loss + distill_cls_loss + distill_obj_loss) * weight
return loss
@@ -185,31 +191,35 @@ def main():
checkpoint.load_params(exe, teacher_program, FLAGS.teacher_pretrained)
teacher_program = teacher_program.clone(for_test=True)
+ target_number = len(model.yolo_head.anchor_masks)
+
data_name_map = {
- 'target0': 'target0',
- 'target1': 'target1',
- 'target2': 'target2',
'image': 'image',
'gt_bbox': 'gt_bbox',
'gt_class': 'gt_class',
'gt_score': 'gt_score'
}
+ for i in range(target_number):
+ data_name_map['target{}'.format(i)] = 'target{}'.format(i)
+
merge(teacher_program, fluid.default_main_program(), data_name_map, place)
- yolo_output_names = [
- 'strided_slice_0.tmp_0', 'strided_slice_1.tmp_0',
- 'strided_slice_2.tmp_0', 'strided_slice_3.tmp_0',
- 'strided_slice_4.tmp_0', 'transpose_0.tmp_0', 'strided_slice_5.tmp_0',
- 'strided_slice_6.tmp_0', 'strided_slice_7.tmp_0',
- 'strided_slice_8.tmp_0', 'strided_slice_9.tmp_0', 'transpose_2.tmp_0',
- 'strided_slice_10.tmp_0', 'strided_slice_11.tmp_0',
- 'strided_slice_12.tmp_0', 'strided_slice_13.tmp_0',
- 'strided_slice_14.tmp_0', 'transpose_4.tmp_0'
+ output_names = [
+ ['strided_slice_0.tmp_0', 'strided_slice_1.tmp_0', 'strided_slice_2.tmp_0',
+ 'strided_slice_3.tmp_0', 'strided_slice_4.tmp_0', 'transpose_0.tmp_0'],
+ ['strided_slice_5.tmp_0', 'strided_slice_6.tmp_0', 'strided_slice_7.tmp_0',
+ 'strided_slice_8.tmp_0', 'strided_slice_9.tmp_0', 'transpose_2.tmp_0'],
+ ['strided_slice_10.tmp_0', 'strided_slice_11.tmp_0', 'strided_slice_12.tmp_0',
+ 'strided_slice_13.tmp_0', 'strided_slice_14.tmp_0', 'transpose_4.tmp_0'],
]
+ yolo_output_names = []
+ for i in range(target_number):
+ yolo_output_names.extend(output_names[i])
+
assert cfg.use_fine_grained_loss, \
"Only support use_fine_grained_loss=True, Please set it in config file or '-o use_fine_grained_loss=true'"
- distill_loss = split_distill(yolo_output_names, 1000)
+ distill_loss = split_distill(yolo_output_names, 1000, target_number)
loss = distill_loss + loss
lr_builder = create('LearningRate')
optim_builder = create('OptimizerBuilder')