diff --git a/configs/anchor_free/README.md b/configs/anchor_free/README.md index 184ca2a6e938cc37d3a57e684480e7c0d035beac..81e9d0843904108bfbde0c8be722e8431c26dcf4 100644 --- a/configs/anchor_free/README.md +++ b/configs/anchor_free/README.md @@ -35,6 +35,7 @@ **注意:** - 模型FPS在Tesla V100单卡环境中通过tools/eval.py进行测试 +- CornerNet-Squeeze要求使用PaddlePaddle1.8及以上版本或适当的develop版本 - CornerNet-Squeeze中使用ResNet结构的骨干网络时,加入了FPN结构,骨干网络的输出feature map采用FPN中的P3层输出。 - \*CornerNet-Squeeze-dcn-mixup-cosine是基于原版CornerNet-Squeeze优化效果最好的模型,在ResNet的骨干网络基础上增加mixup预处理和使用cosine_decay - FCOS使用GIoU loss、用location分支预测centerness、左上右下角点偏移量归一化和ground truth中心匹配策略 diff --git a/configs/yolov4/README.md b/configs/yolov4/README.md index 98a53258036519737068144a6fffa75ee63adcff..5127d88c8a8f1514e127d327806d752cd9ac8c12 100644 --- a/configs/yolov4/README.md +++ b/configs/yolov4/README.md @@ -8,7 +8,7 @@ ## 简介 -[YOLO v4](https://arxiv.org/abs/2004.10934)的Paddle实现版本 +[YOLO v4](https://arxiv.org/abs/2004.10934)的Paddle实现版本,要求使用PaddlePaddle2.0.0及以上版本或适当的develop版本 目前转换了[darknet](https://github.com/AlexeyAB/darknet)中YOLO v4的权重,可以直接对图片进行预测,在[test-dev2019](http://cocodataset.org/#detection-2019)中精度为43.5%。另外,支持VOC数据集上finetune,精度达到85.5% @@ -19,6 +19,7 @@ - SPP模块 - ciou loss - label_smooth +- grid_sensitive ## 模型库 下表中展示了当前支持的网络结构。 @@ -39,7 +40,7 @@ 1. mish激活函数优化 2. mosaic数据预处理实现 -3. scale\_x\_y为yolo_box中decode时对box的位置进行微调,该功能将在Paddle2.0版本中实现 + ## 如何贡献代码 diff --git a/ppdet/ext_op/cornerpool_lib.py b/ppdet/ext_op/cornerpool_lib.py index c56fc661ad27f89df7540f05bdbd01035e06ec67..4cae5a088c66bd945f4987a9201fe0914d54f83c 100644 --- a/ppdet/ext_op/cornerpool_lib.py +++ b/ppdet/ext_op/cornerpool_lib.py @@ -1,8 +1,16 @@ import os import paddle.fluid as fluid +use_cpp = False + file_dir = os.path.dirname(os.path.abspath(__file__)) -fluid.load_op_library(os.path.join(file_dir, 'src/cornerpool_lib.so')) +try: + fluid.load_op_library(os.path.join(file_dir, 'src/cornerpool_lib.so')) + use_cpp = True +except: + print( + 'Warning: cornerpool_lib.so not found, use python version instead which may drop the inference speed. Compile in ppdet/ext_op at first if you need cpp version.' + ) from paddle.fluid.layer_helper import LayerHelper @@ -14,6 +22,19 @@ __all__ = [ ] +def cornerpool_op(layer_type, input, name): + helper = LayerHelper(layer_type, input=input, name=name) + dtype = helper.input_dtype() + output = helper.create_variable_for_type_inference(dtype) + max_map = helper.create_variable_for_type_inference(dtype) + helper.append_op( + type=layer_type, + inputs={"X": input}, + outputs={"Output": output, + "MaxMap": max_map}) + return output + + def bottom_pool(input, is_test=False, name=None): """ This layer calculates the bottom pooling output based on the input. @@ -34,16 +55,28 @@ def bottom_pool(input, is_test=False, name=None): output = corner_pool.bottom_pool(input) """ if is_test: - helper = LayerHelper('bottom_pool', **locals()) - dtype = helper.input_dtype() - output = helper.create_variable_for_type_inference(dtype) - max_map = helper.create_variable_for_type_inference(dtype) - helper.append_op( - type="bottom_pool", - inputs={"X": input}, - outputs={"Output": output, - "MaxMap": max_map}) - return output + if use_cpp: + output = cornerpool_op("bottom_pool", input, name) + return output + + def cond(i, output): + return i < H + + def body(i, output): + cur = fluid.layers.slice(output, [2], [i], [H]) + next = fluid.layers.slice(output, [2], [0], [H - i]) + max_v = fluid.layers.elementwise_max(cur, next) + orig = fluid.layers.slice(output, [2], [0], [i]) + output = fluid.layers.concat([orig, max_v], axis=2) + i = i * 2 + return [i, output] + + H = fluid.layers.shape(input)[2] + i = fluid.layers.fill_constant(shape=[1], dtype='int32', value=1) + output = input + output = fluid.layers.while_loop(cond, body, [i, output]) + return output[-1] + H = input.shape[2] i = 1 output = input @@ -77,16 +110,27 @@ def top_pool(input, is_test=False, name=None): output = corner_pool.top_pool(input) """ if is_test: - helper = LayerHelper('top_pool', **locals()) - dtype = helper.input_dtype() - output = helper.create_variable_for_type_inference(dtype) - max_map = helper.create_variable_for_type_inference(dtype) - helper.append_op( - type="top_pool", - inputs={"X": input}, - outputs={"Output": output, - "MaxMap": max_map}) - return output + if use_cpp: + output = cornerpool_op("top_pool", input, name) + return output + + def cond(i, output): + return i < H + + def body(i, output): + cur = fluid.layers.slice(output, [2], [0], [H - i]) + next = fluid.layers.slice(output, [2], [i], [H]) + max_v = fluid.layers.elementwise_max(cur, next) + orig = fluid.layers.slice(output, [2], [H - i], [H]) + output = fluid.layers.concat([max_v, orig], axis=2) + i = i * 2 + return [i, output] + + H = fluid.layers.shape(input)[2] + i = fluid.layers.fill_constant(shape=[1], dtype='int32', value=1) + output = input + output = fluid.layers.while_loop(cond, body, [i, output]) + return output[-1] H = input.shape[2] i = 1 @@ -121,16 +165,27 @@ def right_pool(input, is_test=False, name=None): output = corner_pool.right_pool(input) """ if is_test: - helper = LayerHelper('right_pool', **locals()) - dtype = helper.input_dtype() - output = helper.create_variable_for_type_inference(dtype) - max_map = helper.create_variable_for_type_inference(dtype) - helper.append_op( - type="right_pool", - inputs={"X": input}, - outputs={"Output": output, - "MaxMap": max_map}) - return output + if use_cpp: + output = cornerpool_op("right_pool", input, name) + return output + + def cond(i, output): + return i < W + + def body(i, output): + cur = fluid.layers.slice(output, [3], [i], [W]) + next = fluid.layers.slice(output, [3], [0], [W - i]) + max_v = fluid.layers.elementwise_max(cur, next) + orig = fluid.layers.slice(output, [3], [0], [i]) + output = fluid.layers.concat([orig, max_v], axis=-1) + i = i * 2 + return [i, output] + + W = fluid.layers.shape(input)[3] + i = fluid.layers.fill_constant(shape=[1], dtype='int32', value=1) + output = input + output = fluid.layers.while_loop(cond, body, [i, output]) + return output[-1] W = input.shape[3] i = 1 @@ -165,16 +220,27 @@ def left_pool(input, is_test=False, name=None): output = corner_pool.left_pool(input) """ if is_test: - helper = LayerHelper('left_pool', **locals()) - dtype = helper.input_dtype() - output = helper.create_variable_for_type_inference(dtype) - max_map = helper.create_variable_for_type_inference(dtype) - helper.append_op( - type="left_pool", - inputs={"X": input}, - outputs={"Output": output, - "MaxMap": max_map}) - return output + if use_cpp: + output = cornerpool_op("left_pool", input, name) + return output + + def cond(i, output): + return i < W + + def body(i, output): + cur = fluid.layers.slice(output, [3], [0], [W - i]) + next = fluid.layers.slice(output, [3], [i], [W]) + max_v = fluid.layers.elementwise_max(cur, next) + orig = fluid.layers.slice(output, [3], [W - i], [W]) + output = fluid.layers.concat([max_v, orig], axis=-1) + i = i * 2 + return [i, output] + + W = fluid.layers.shape(input)[3] + i = fluid.layers.fill_constant(shape=[1], dtype='int32', value=1) + output = input + output = fluid.layers.while_loop(cond, body, [i, output]) + return output[-1] W = input.shape[3] i = 1 diff --git a/ppdet/modeling/anchor_heads/yolo_head.py b/ppdet/modeling/anchor_heads/yolo_head.py index 9540963c01afb9aacf7e52fc17f1bc4efb452ee6..a998f789de38f222a9de44f9e75bdb331099bdb4 100644 --- a/ppdet/modeling/anchor_heads/yolo_head.py +++ b/ppdet/modeling/anchor_heads/yolo_head.py @@ -29,6 +29,7 @@ try: from collections.abc import Sequence except Exception: from collections import Sequence +from ppdet.utils.check import check_version __all__ = ['YOLOv3Head', 'YOLOv4Head'] @@ -70,6 +71,7 @@ class YOLOv3Head(object): downsample=[32, 16, 8], scale_x_y=1.0, clip_bbox=True): + check_version('2.0.0') self.norm_decay = norm_decay self.num_classes = num_classes self.anchor_masks = anchor_masks diff --git a/ppdet/modeling/architectures/cornernet_squeeze.py b/ppdet/modeling/architectures/cornernet_squeeze.py index fb2ce42a11e5d30a6e0ffcfd60ea5f6b50047764..6e3a48f7c818a8d8aefdf5b95da6cb530c74a076 100644 --- a/ppdet/modeling/architectures/cornernet_squeeze.py +++ b/ppdet/modeling/architectures/cornernet_squeeze.py @@ -22,6 +22,7 @@ from paddle import fluid from ppdet.core.workspace import register import numpy as np +from ppdet.utils.check import check_version __all__ = ['CornerNetSqueeze'] @@ -48,6 +49,7 @@ class CornerNetSqueeze(object): corner_head='CornerHead', num_classes=80, fpn=None): + check_version('1.8.0') super(CornerNetSqueeze, self).__init__() self.backbone = backbone self.corner_head = corner_head diff --git a/ppdet/modeling/losses/yolo_loss.py b/ppdet/modeling/losses/yolo_loss.py index 00975b17deae8e26ec5d0499e3786c4705ca5bab..732edb39d3b1102e0fdb1abe1165f714be4c1aad 100644 --- a/ppdet/modeling/losses/yolo_loss.py +++ b/ppdet/modeling/losses/yolo_loss.py @@ -86,6 +86,7 @@ class YOLOv3Loss(object): use_label_smooth=self._label_smooth, scale_x_y=scale_x_y, name=prefix_name + "yolo_loss" + str(i)) + losses.append(fluid.layers.reduce_mean(loss)) return {'loss': sum(losses)} diff --git a/ppdet/utils/check.py b/ppdet/utils/check.py index 2b3283585c490edff5821eb7230e6d3bc756c5eb..43303f6d68e60626d55fc0f57c5d7511442da783 100644 --- a/ppdet/utils/check.py +++ b/ppdet/utils/check.py @@ -21,6 +21,8 @@ import sys import paddle.fluid as fluid import logging +import six +import paddle.version as fluid_version logger = logging.getLogger(__name__) __all__ = ['check_gpu', 'check_version', 'check_config'] @@ -45,20 +47,27 @@ def check_gpu(use_gpu): pass -def check_version(): +def check_version(version='1.7.0'): """ Log error and exit when the installed version of paddlepaddle is not satisfied. """ - err = "PaddlePaddle version 1.6 or higher is required, " \ + err = "PaddlePaddle version {} or higher is required, " \ "or a suitable develop version is satisfied as well. \n" \ - "Please make sure the version is good with your code." \ - - try: - fluid.require_version('1.7.0') - except Exception as e: - logger.error(err) - sys.exit(1) + "Please make sure the version is good with your code.".format(version) + + version_installed = [ + fluid_version.major, fluid_version.minor, fluid_version.patch, + fluid_version.rc + ] + if version_installed == ['0', '0', '0', '0']: + return + version_split = version.split('.') + + length = min(len(version_installed), len(version_split)) + for i in six.moves.range(length): + if version_installed[i] < version_split[i]: + raise Exception(err) def check_config(cfg):