From aa669c749ffe98c940c1ac1999565c97298db6a9 Mon Sep 17 00:00:00 2001 From: JYChen Date: Thu, 3 Nov 2022 20:44:05 +0800 Subject: [PATCH] [Fluid Clean] move fluid.layers.deformable_conv to static.nn (#47435) * move fluid.layers.deformable_conv to static.nn * modify example code * fix doc * Update common.py Co-authored-by: Ligoml <39876205+Ligoml@users.noreply.github.com> --- python/paddle/fluid/layers/nn.py | 245 ----------------- .../ir/inference/test_trt_deformable_conv.py | 3 +- .../tests/unittests/test_deform_conv2d.py | 8 +- .../unittests/test_deformable_conv_op.py | 23 +- .../unittests/test_deformable_conv_v1_op.py | 43 --- .../fluid/tests/unittests/test_layers.py | 78 ------ .../xpu/test_deformable_conv_op_xpu.py | 35 --- python/paddle/static/nn/common.py | 254 +++++++++++++++++- 8 files changed, 268 insertions(+), 421 deletions(-) diff --git a/python/paddle/fluid/layers/nn.py b/python/paddle/fluid/layers/nn.py index e775390f2a..5623413af0 100644 --- a/python/paddle/fluid/layers/nn.py +++ b/python/paddle/fluid/layers/nn.py @@ -202,7 +202,6 @@ __all__ = [ 'continuous_value_model', 'where', 'sign', - 'deformable_conv', 'unfold', 'deformable_roi_pooling', 'filter_by_instag', @@ -15607,250 +15606,6 @@ def unique_with_counts(x, dtype='int32'): return out, index, count -def deformable_conv( - input, - offset, - mask, - num_filters, - filter_size, - stride=1, - padding=0, - dilation=1, - groups=None, - deformable_groups=None, - im2col_step=None, - param_attr=None, - bias_attr=None, - modulated=True, - name=None, -): - r""" - :api_attr: Static Graph - - **Deformable Convolution op** - - Compute 2-D deformable convolution on 4-D input. - Given input image x, output feature map y, the deformable convolution operation can be expressed as follow: - - - Deformable Convolution v2: - - .. math:: - - y(p) = \sum_{k=1}^{K}{w_k * x(p + p_k + \Delta p_k) * \Delta m_k} - - Deformable Convolution v1: - - .. math:: - - y(p) = \sum_{k=1}^{K}{w_k * x(p + p_k + \Delta p_k)} - - Where :math:`\Delta p_k` and :math:`\Delta m_k` are the learnable offset and modulation scalar for the k-th location, - Which :math:`\Delta m_k` is one in deformable convolution v1. Please refer to `Deformable ConvNets v2: More Deformable, Better Results - `_ and `Deformable Convolutional Networks `_. - - Example: - - Input: - - Input shape: :math:`(N, C_{in}, H_{in}, W_{in})` - - Filter shape: :math:`(C_{out}, C_{in}, H_f, W_f)` - - Offset shape: :math:`(N, 2 * deformable\_groups * H_f * H_w, H_{in}, W_{in})` - - Mask shape: :math:`(N, deformable\_groups * H_f * H_w, H_{in}, W_{in})` - - - Output: - - Output shape: :math:`(N, C_{out}, H_{out}, W_{out})` - - Where - - .. math:: - - H_{out}&= \\frac{(H_{in} + 2 * paddings[0] - (dilations[0] * (H_f - 1) + 1))}{strides[0]} + 1 \\\\ - W_{out}&= \\frac{(W_{in} + 2 * paddings[1] - (dilations[1] * (W_f - 1) + 1))}{strides[1]} + 1 - - Args: - input (Variable): The input image with [N, C, H, W] format. A Tensor with type - float32, float64. - offset (Variable): The input coordinate offset of deformable convolution layer. - A Tensor with type float32, float64. - Mask (Variable, Optional): The input mask of deformable convolution layer. - A Tensor with type float32, float64. It should be None when you use - deformable convolution v1. - num_filters(int): The number of filter. It is as same as the output - image channel. - filter_size (int|tuple): The filter size. If filter_size is a tuple, - it must contain two integers, (filter_size_H, filter_size_W). - Otherwise, the filter will be a square. - stride (int|tuple): The stride size. If stride is a tuple, it must - contain two integers, (stride_H, stride_W). Otherwise, the - stride_H = stride_W = stride. Default: stride = 1. - padding (int|tuple): The padding size. If padding is a tuple, it must - contain two integers, (padding_H, padding_W). Otherwise, the - padding_H = padding_W = padding. Default: padding = 0. - dilation (int|tuple): The dilation size. If dilation is a tuple, it must - contain two integers, (dilation_H, dilation_W). Otherwise, the - dilation_H = dilation_W = dilation. Default: dilation = 1. - groups (int): The groups number of the deformable conv layer. According to - grouped convolution in Alex Krizhevsky's Deep CNN paper: when group=2, - the first half of the filters is only connected to the first half - of the input channels, while the second half of the filters is only - connected to the second half of the input channels. Default: groups=1. - deformable_groups (int): The number of deformable group partitions. - Default: deformable_groups = 1. - im2col_step (int): Maximum number of images per im2col computation; - The total batch size should be devisable by this value or smaller - than this value; if you face out of memory problem, you can try - to use a smaller value here. - Default: im2col_step = 64. - param_attr (ParamAttr, Optional): The parameter attribute for learnable parameters/weights - of deformable conv. If it is set to None or one attribute of ParamAttr, - deformable conv will create ParamAttr as param_attr. - If the Initializer of the param_attr is not set, the parameter is - initialized with :math:`Normal(0.0, std)`, and the - :math:`std` is :math:`(\\frac{2.0 }{filter\_elem\_num})^{0.5}`. Default: None. - bias_attr (ParamAttr|bool, Optional): The parameter attribute for the bias of - deformable conv layer. If it is set to False, no bias will be added - to the output units. If it is set to None or one attribute of ParamAttr, conv2d - will create ParamAttr as bias_attr. If the Initializer of the bias_attr - is not set, the bias is initialized zero. Default: None. - modulated (bool): Make sure which version should be used between v1 and v2, where v2 is \ - used while True. Default: True. - name(str, Optional): For details, please refer to :ref:`api_guide_Name`. - Generally, no setting is required. Default: None. - Returns: - Variable: The tensor variable storing the deformable convolution \ - result. A Tensor with type float32, float64. - Raises: - ValueError: If the shapes of input, filter_size, stride, padding and - groups mismatch. - Examples: - .. code-block:: python - - #deformable conv v2: - - import paddle.fluid as fluid - import paddle - paddle.enable_static() - - C_in, H_in, W_in = 3, 32, 32 - filter_size, deformable_groups = 3, 1 - data = fluid.data(name='data', shape=[None, C_in, H_in, W_in], dtype='float32') - offset = fluid.data(name='offset', shape=[None, 2*deformable_groups*filter_size**2, H_in, W_in], dtype='float32') - mask = fluid.data(name='mask', shape=[None, deformable_groups*filter_size**2, H_in, W_in], dtype='float32') - out = fluid.layers.deformable_conv(input=data, offset=offset, mask=mask, - num_filters=2, filter_size=filter_size, padding=1, modulated=True) - - #deformable conv v1: - - import paddle.fluid as fluid - C_in, H_in, W_in = 3, 32, 32 - filter_size, deformable_groups = 3, 1 - data = fluid.data(name='data', shape=[None, C_in, H_in, W_in], dtype='float32') - offset = fluid.data(name='offset', shape=[None, 2*deformable_groups*filter_size**2, H_in, W_in], dtype='float32') - out = fluid.layers.deformable_conv(input=data, offset=offset, mask=None, - num_filters=2, filter_size=filter_size, padding=1, modulated=False) - """ - - check_variable_and_dtype( - input, "input", ['float32', 'float64'], 'deformable_conv' - ) - check_variable_and_dtype( - offset, "offset", ['float32', 'float64'], 'deformable_conv' - ) - check_type(mask, 'mask', (Variable, type(None)), 'deformable_conv') - - num_channels = input.shape[1] - assert param_attr is not False, "param_attr should not be False here." - - helper = LayerHelper('deformable_conv', **locals()) - dtype = helper.input_dtype() - - if not isinstance(input, Variable): - raise TypeError("Input of deformable_conv must be Variable") - if not isinstance(offset, Variable): - raise TypeError("Input Offset of deformable_conv must be Variable") - - if groups is None: - num_filter_channels = num_channels - else: - if num_channels % groups != 0: - raise ValueError("num_channels must be divisible by groups.") - num_filter_channels = num_channels // groups - - filter_size = utils.convert_to_list(filter_size, 2, 'filter_size') - stride = utils.convert_to_list(stride, 2, 'stride') - padding = utils.convert_to_list(padding, 2, 'padding') - dilation = utils.convert_to_list(dilation, 2, 'dilation') - - input_shape = input.shape - filter_shape = [num_filters, int(num_filter_channels)] + filter_size - - def _get_default_param_initializer(): - filter_elem_num = filter_size[0] * filter_size[1] * num_channels - if filter_elem_num <= 0: - raise ValueError( - "Invalid filter number, excepted number is larger than 0, but" - " received {}, please check the input shape and " - "filter size.".format(filter_elem_num) - ) - std = (2.0 / filter_elem_num) ** 0.5 - return Normal(0.0, std, 0) - - filter_param = helper.create_parameter( - attr=helper.param_attr, - shape=filter_shape, - dtype=dtype, - default_initializer=_get_default_param_initializer(), - ) - - pre_bias = helper.create_variable_for_type_inference(dtype) - - if modulated: - helper.append_op( - type='deformable_conv', - inputs={ - 'Input': input, - 'Filter': filter_param, - 'Offset': offset, - 'Mask': mask, - }, - outputs={"Output": pre_bias}, - attrs={ - 'strides': stride, - 'paddings': padding, - 'dilations': dilation, - 'groups': groups, - 'deformable_groups': deformable_groups, - 'im2col_step': im2col_step, - }, - ) - - else: - helper.append_op( - type='deformable_conv_v1', - inputs={ - 'Input': input, - 'Filter': filter_param, - 'Offset': offset, - }, - outputs={"Output": pre_bias}, - attrs={ - 'strides': stride, - 'paddings': padding, - 'dilations': dilation, - 'groups': groups, - 'deformable_groups': deformable_groups, - 'im2col_step': im2col_step, - }, - ) - - output = helper.append_bias_op(pre_bias, dim_start=1, dim_end=2) - return output - - def unfold(x, kernel_sizes, strides=1, paddings=0, dilations=1, name=None): r""" diff --git a/python/paddle/fluid/tests/unittests/ir/inference/test_trt_deformable_conv.py b/python/paddle/fluid/tests/unittests/ir/inference/test_trt_deformable_conv.py index eb79b4ccd1..baf8e564df 100644 --- a/python/paddle/fluid/tests/unittests/ir/inference/test_trt_deformable_conv.py +++ b/python/paddle/fluid/tests/unittests/ir/inference/test_trt_deformable_conv.py @@ -16,6 +16,7 @@ import os import unittest import numpy as np from inference_pass_test import InferencePassTest +import paddle import paddle.fluid as fluid import paddle.fluid.core as core from paddle.fluid.core import PassVersionChecker @@ -38,7 +39,7 @@ class TRTDeformableConvTest(InferencePassTest): name='mask', shape=self.mask_size, dtype=self.dtype ) - output = fluid.layers.deformable_conv( + output = paddle.static.nn.common.deformable_conv( input, offset, mask, diff --git a/python/paddle/fluid/tests/unittests/test_deform_conv2d.py b/python/paddle/fluid/tests/unittests/test_deform_conv2d.py index 80bf06fa6d..0bca1d051a 100644 --- a/python/paddle/fluid/tests/unittests/test_deform_conv2d.py +++ b/python/paddle/fluid/tests/unittests/test_deform_conv2d.py @@ -141,7 +141,7 @@ class TestDeformConv2D(TestCase): dtype=self.dtype, ) - y_v1 = paddle.fluid.layers.deformable_conv( + y_v1 = paddle.static.nn.common.deformable_conv( input=x, offset=offset, mask=None, @@ -158,7 +158,7 @@ class TestDeformConv2D(TestCase): modulated=False, ) - y_v2 = paddle.fluid.layers.deformable_conv( + y_v2 = paddle.static.nn.common.deformable_conv( input=x, offset=offset, mask=mask, @@ -357,7 +357,7 @@ class TestDeformConv2DFunctional(TestCase): dtype=self.dtype, ) - y_v1 = paddle.fluid.layers.deformable_conv( + y_v1 = paddle.static.nn.common.deformable_conv( input=x, offset=offset, mask=None, @@ -374,7 +374,7 @@ class TestDeformConv2DFunctional(TestCase): modulated=False, ) - y_v2 = paddle.fluid.layers.deformable_conv( + y_v2 = paddle.static.nn.common.deformable_conv( input=x, offset=offset, mask=mask, diff --git a/python/paddle/fluid/tests/unittests/test_deformable_conv_op.py b/python/paddle/fluid/tests/unittests/test_deformable_conv_op.py index f89ef98e95..dec6d9d8db 100644 --- a/python/paddle/fluid/tests/unittests/test_deformable_conv_op.py +++ b/python/paddle/fluid/tests/unittests/test_deformable_conv_op.py @@ -15,7 +15,6 @@ import paddle import unittest import numpy as np -import paddle.fluid as fluid from op_test import OpTest from paddle.fluid.framework import _test_eager_guard @@ -395,13 +394,13 @@ class TestModulatedDeformableConvInvalidInput(unittest.TestCase): def test_invalid_input(): paddle.enable_static() input = [1, 3, 32, 32] - offset = fluid.data( + offset = paddle.static.data( name='offset', shape=[None, 3, 32, 32], dtype='float32' ) - mask = fluid.data( + mask = paddle.static.data( name='mask', shape=[None, 3, 32, 32], dtype='float32' ) - loss = fluid.layers.deformable_conv( + loss = paddle.static.nn.common.deformable_conv( input, offset, mask, num_filters=4, filter_size=1 ) @@ -409,16 +408,16 @@ class TestModulatedDeformableConvInvalidInput(unittest.TestCase): def test_invalid_offset(): paddle.enable_static() - input = fluid.data( + input = paddle.static.data( name='input', shape=[None, 3, 32, 32], dtype='int32' ) - offset = fluid.data( + offset = paddle.static.data( name='offset', shape=[None, 3, 32, 32], dtype='float32' ) - mask = fluid.data( + mask = paddle.static.data( name='mask', shape=[None, 3, 32, 32], dtype='float32' ) - loss = fluid.layers.deformable_conv( + loss = paddle.static.nn.common.deformable_conv( input, offset, mask, num_filters=4, filter_size=1 ) @@ -426,16 +425,16 @@ class TestModulatedDeformableConvInvalidInput(unittest.TestCase): def test_invalid_filter(): paddle.enable_static() - input = fluid.data( + input = paddle.static.data( name='input_filter', shape=[None, 3, 32, 32], dtype='float32' ) - offset = fluid.data( + offset = paddle.static.data( name='offset_filter', shape=[None, 3, 32, 32], dtype='float32' ) - mask = fluid.data( + mask = paddle.static.data( name='mask_filter', shape=[None, 3, 32, 32], dtype='float32' ) - loss = fluid.layers.deformable_conv( + loss = paddle.static.nn.common.deformable_conv( input, offset, mask, num_filters=4, filter_size=0 ) diff --git a/python/paddle/fluid/tests/unittests/test_deformable_conv_v1_op.py b/python/paddle/fluid/tests/unittests/test_deformable_conv_v1_op.py index 19a81e21a6..00556f7e5a 100644 --- a/python/paddle/fluid/tests/unittests/test_deformable_conv_v1_op.py +++ b/python/paddle/fluid/tests/unittests/test_deformable_conv_v1_op.py @@ -15,9 +15,7 @@ import paddle import unittest import numpy as np -import paddle.fluid as fluid from op_test import OpTest -from paddle.fluid.framework import _test_eager_guard def dmc_bilinear(data_im, height, width, h, w): @@ -348,46 +346,5 @@ class TestWithDouble(TestModulatedDeformableConvOp): self.dtype = np.float64 -class TestModulatedDeformableConvV1InvalidInput(unittest.TestCase): - def test_error(self): - def test_invalid_input(): - input = [1, 3, 32, 32] - offset = fluid.data( - name='offset', shape=[None, 3, 32, 32], dtype='float32' - ) - loss = fluid.layers.deformable_conv( - input, - offset, - mask=None, - num_filters=4, - filter_size=1, - modulated=False, - ) - - self.assertRaises(TypeError, test_invalid_input) - - def test_invalid_offset(): - input = fluid.data( - name='input', shape=[None, 3, 32, 32], dtype='int32' - ) - offset = fluid.data( - name='offset', shape=[None, 3, 32, 32], dtype='float32' - ) - loss = fluid.layers.deformable_conv( - input, - offset, - mask=None, - num_filters=4, - filter_size=1, - modulated=False, - ) - - self.assertRaises(TypeError, test_invalid_offset) - - def test_error_with_eager_guard(self): - with _test_eager_guard(): - self.test_error() - - if __name__ == '__main__': unittest.main() diff --git a/python/paddle/fluid/tests/unittests/test_layers.py b/python/paddle/fluid/tests/unittests/test_layers.py index 5947e1d9b3..c68b9f3681 100644 --- a/python/paddle/fluid/tests/unittests/test_layers.py +++ b/python/paddle/fluid/tests/unittests/test_layers.py @@ -4797,57 +4797,6 @@ class TestBook(LayerTest): self.assertIsNotNone(out) print(str(program)) - def test_deformable_conv(self): - with self.static_graph(): - input = layers.data( - name='input', - append_batch_size=False, - shape=[2, 3, 32, 32], - dtype="float32", - ) - offset = layers.data( - name='offset', - append_batch_size=False, - shape=[2, 18, 32, 32], - dtype="float32", - ) - mask = layers.data( - name='mask', - append_batch_size=False, - shape=[2, 9, 32, 32], - dtype="float32", - ) - out = layers.deformable_conv( - input=input, - offset=offset, - mask=mask, - num_filters=2, - filter_size=3, - padding=1, - ) - return out - - def test_deformable_conv2(self): - with self.static_graph(): - input = fluid.data( - name='input', shape=[None, 3, None, None], dtype="float32" - ) - offset = fluid.data( - name='offset', shape=[None, 18, None, None], dtype="float32" - ) - mask = fluid.data( - name='mask', shape=[None, 9, None, None], dtype="float32" - ) - out = layers.deformable_conv( - input=input, - offset=offset, - mask=mask, - num_filters=2, - filter_size=3, - padding=1, - ) - return out - def test_unfold(self): with self.static_graph(): x = layers.data(name='x', shape=[3, 20, 20], dtype='float32') @@ -4900,33 +4849,6 @@ class TestBook(LayerTest): ) return out - def test_deformable_conv_v1(self): - with program_guard( - fluid.default_main_program(), fluid.default_startup_program() - ): - input = layers.data( - name='input', - append_batch_size=False, - shape=[2, 3, 32, 32], - dtype="float32", - ) - offset = layers.data( - name='offset', - append_batch_size=False, - shape=[2, 18, 32, 32], - dtype="float32", - ) - out = layers.deformable_conv( - input=input, - offset=offset, - mask=None, - num_filters=2, - filter_size=3, - padding=1, - modulated=False, - ) - return out - def test_retinanet_target_assign(self): with program_guard( fluid.default_main_program(), fluid.default_startup_program() diff --git a/python/paddle/fluid/tests/unittests/xpu/test_deformable_conv_op_xpu.py b/python/paddle/fluid/tests/unittests/xpu/test_deformable_conv_op_xpu.py index 678afafc08..0c11942804 100644 --- a/python/paddle/fluid/tests/unittests/xpu/test_deformable_conv_op_xpu.py +++ b/python/paddle/fluid/tests/unittests/xpu/test_deformable_conv_op_xpu.py @@ -19,7 +19,6 @@ import unittest import numpy as np import paddle.fluid.core as core -import paddle.fluid as fluid from op_test_xpu import OpTest, XPUOpTest import paddle from xpu.get_test_cover_info import ( @@ -304,40 +303,6 @@ class XPUTestModulatedDeformableConvOp(XPUOpTestWrapper): self.input_size[3], ] - class TestModulatedDeformableConvInvalidInput(unittest.TestCase): - def test_error(self): - def test_invalid_input(): - paddle.enable_static() - input = [1, 3, 32, 32] - offset = fluid.data( - name='offset', shape=[None, 3, 32, 32], dtype='float32' - ) - mask = fluid.data( - name='mask', shape=[None, 3, 32, 32], dtype='float32' - ) - loss = fluid.layers.deformable_conv( - input, offset, mask, num_filters=4, filter_size=1 - ) - - self.assertRaises(TypeError, test_invalid_input) - - def test_invalid_offset(): - paddle.enable_static() - input = fluid.data( - name='input', shape=[None, 3, 32, 32], dtype='int32' - ) - offset = fluid.data( - name='offset', shape=[None, 3, 32, 32], dtype='float32' - ) - mask = fluid.data( - name='mask', shape=[None, 3, 32, 32], dtype='float32' - ) - loss = fluid.layers.deformable_conv( - input, offset, mask, num_filters=4, filter_size=1 - ) - - self.assertRaises(TypeError, test_invalid_offset) - support_types = get_xpu_op_support_types('deformable_conv') for stype in support_types: diff --git a/python/paddle/static/nn/common.py b/python/paddle/static/nn/common.py index 98c5e81a2e..9c0e1114f7 100755 --- a/python/paddle/static/nn/common.py +++ b/python/paddle/static/nn/common.py @@ -1,4 +1,4 @@ -# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved. +# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -15,6 +15,13 @@ import paddle from paddle.fluid.framework import static_only +from paddle.common_ops_import import ( + check_type, + check_variable_and_dtype, + utils, + LayerHelper, +) + __all__ = [] @@ -167,6 +174,247 @@ def fc( ) +def deformable_conv( + input, + offset, + mask, + num_filters, + filter_size, + stride=1, + padding=0, + dilation=1, + groups=None, + deformable_groups=None, + im2col_step=None, + param_attr=None, + bias_attr=None, + modulated=True, + name=None, +): + r""" + + **Deformable Convolution op** + + Compute 2-D deformable convolution on 4-D input. + Given input image x, output feature map y, the deformable convolution operation can be expressed as follow: + + + Deformable Convolution v2: + + .. math:: + + y(p) = \sum_{k=1}^{K}{w_k * x(p + p_k + \Delta p_k) * \Delta m_k} + + Deformable Convolution v1: + + .. math:: + + y(p) = \sum_{k=1}^{K}{w_k * x(p + p_k + \Delta p_k)} + + Where :math:`\Delta p_k` and :math:`\Delta m_k` are the learnable offset and modulation scalar for the k-th location, + Which :math:`\Delta m_k` is one in deformable convolution v1. Please refer to `Deformable ConvNets v2: More Deformable, Better Results + `_ and `Deformable Convolutional Networks `_. + + Example: + - Input: + + Input shape: :math:`(N, C_{in}, H_{in}, W_{in})` + + Filter shape: :math:`(C_{out}, C_{in}, H_f, W_f)` + + Offset shape: :math:`(N, 2 * deformable\_groups * H_f * H_w, H_{in}, W_{in})` + + Mask shape: :math:`(N, deformable\_groups * H_f * H_w, H_{in}, W_{in})` + + - Output: + + Output shape: :math:`(N, C_{out}, H_{out}, W_{out})` + + Where + + .. math:: + + H_{out}&= \\frac{(H_{in} + 2 * paddings[0] - (dilations[0] * (H_f - 1) + 1))}{strides[0]} + 1 \\\\ + W_{out}&= \\frac{(W_{in} + 2 * paddings[1] - (dilations[1] * (W_f - 1) + 1))}{strides[1]} + 1 + + Args: + input (Tensor): The input image with [N, C, H, W] format. A Tensor with type + float32, float64. + offset (Tensor): The input coordinate offset of deformable convolution layer. + A Tensor with type float32, float64. + Mask (Variable, Optional): The input mask of deformable convolution layer. + A Tensor with type float32, float64. It should be None when you use + deformable convolution v1. + num_filters(int): The number of filter. It is as same as the output + image channel. + filter_size (int|tuple): The filter size. If filter_size is a tuple, + it must contain two integers, (filter_size_H, filter_size_W). + Otherwise, the filter will be a square. + stride (int|tuple): The stride size. If stride is a tuple, it must + contain two integers, (stride_H, stride_W). Otherwise, the + stride_H = stride_W = stride. Default: stride = 1. + padding (int|tuple): The padding size. If padding is a tuple, it must + contain two integers, (padding_H, padding_W). Otherwise, the + padding_H = padding_W = padding. Default: padding = 0. + dilation (int|tuple): The dilation size. If dilation is a tuple, it must + contain two integers, (dilation_H, dilation_W). Otherwise, the + dilation_H = dilation_W = dilation. Default: dilation = 1. + groups (int): The groups number of the deformable conv layer. According to + grouped convolution in Alex Krizhevsky's Deep CNN paper: when group=2, + the first half of the filters is only connected to the first half + of the input channels, while the second half of the filters is only + connected to the second half of the input channels. Default: groups=1. + deformable_groups (int): The number of deformable group partitions. + Default: deformable_groups = 1. + im2col_step (int): Maximum number of images per im2col computation; + The total batch size should be devisable by this value or smaller + than this value; if you face out of memory problem, you can try + to use a smaller value here. + Default: im2col_step = 64. + param_attr (ParamAttr, Optional): The parameter attribute for learnable parameters/weights + of deformable conv. If it is set to None or one attribute of ParamAttr, + deformable conv will create ParamAttr as param_attr. + If the Initializer of the param_attr is not set, the parameter is + initialized with :math:`Normal(0.0, std)`, and the + :math:`std` is :math:`(\\frac{2.0 }{filter\_elem\_num})^{0.5}`. Default: None. + bias_attr (ParamAttr|bool, Optional): The parameter attribute for the bias of + deformable conv layer. If it is set to False, no bias will be added + to the output units. If it is set to None or one attribute of ParamAttr, conv2d + will create ParamAttr as bias_attr. If the Initializer of the bias_attr + is not set, the bias is initialized zero. Default: None. + modulated (bool): Make sure which version should be used between v1 and v2, where v2 is \ + used while True. Default: True. + name(str, Optional): For details, please refer to :ref:`api_guide_Name`. + Generally, no setting is required. Default: None. + Returns: + Tensor: The tensor variable storing the deformable convolution \ + result. A Tensor with type float32, float64. + Examples: + .. code-block:: python + + #deformable conv v2: + + import paddle + paddle.enable_static() + + C_in, H_in, W_in = 3, 32, 32 + filter_size, deformable_groups = 3, 1 + data = paddle.static.data(name='data', shape=[None, C_in, H_in, W_in], dtype='float32') + offset = paddle.static.data(name='offset', shape=[None, 2*deformable_groups*filter_size**2, H_in, W_in], dtype='float32') + mask = paddle.static.data(name='mask', shape=[None, deformable_groups*filter_size**2, H_in, W_in], dtype='float32') + out = paddle.static.layers.common.deformable_conv(input=data, offset=offset, mask=mask, + num_filters=2, filter_size=filter_size, padding=1, modulated=True) + + #deformable conv v1: + + import paddle + C_in, H_in, W_in = 3, 32, 32 + filter_size, deformable_groups = 3, 1 + data = paddle.static.data(name='data', shape=[None, C_in, H_in, W_in], dtype='float32') + offset = paddle.static.data(name='offset', shape=[None, 2*deformable_groups*filter_size**2, H_in, W_in], dtype='float32') + out = paddle.static.layers.common.deformable_conv(input=data, offset=offset, mask=None, + num_filters=2, filter_size=filter_size, padding=1, modulated=False) + """ + + check_variable_and_dtype( + input, "input", ['float32', 'float64'], 'deformable_conv' + ) + check_variable_and_dtype( + offset, "offset", ['float32', 'float64'], 'deformable_conv' + ) + check_type( + mask, 'mask', (paddle.static.Variable, type(None)), 'deformable_conv' + ) + + num_channels = input.shape[1] + assert param_attr is not False, "param_attr should not be False here." + + helper = LayerHelper('deformable_conv', **locals()) + dtype = helper.input_dtype() + + if not isinstance(input, paddle.static.Variable): + raise TypeError("Input of deformable_conv must be Variable") + if not isinstance(offset, paddle.static.Variable): + raise TypeError("Input Offset of deformable_conv must be Variable") + + if groups is None: + num_filter_channels = num_channels + else: + if num_channels % groups != 0: + raise ValueError("num_channels must be divisible by groups.") + num_filter_channels = num_channels // groups + + filter_size = utils.convert_to_list(filter_size, 2, 'filter_size') + stride = utils.convert_to_list(stride, 2, 'stride') + padding = utils.convert_to_list(padding, 2, 'padding') + dilation = utils.convert_to_list(dilation, 2, 'dilation') + + input_shape = input.shape + filter_shape = [num_filters, int(num_filter_channels)] + filter_size + + def _get_default_param_initializer(): + filter_elem_num = filter_size[0] * filter_size[1] * num_channels + if filter_elem_num <= 0: + raise ValueError( + "Invalid filter number, excepted number is larger than 0, but" + " received {}, please check the input shape and " + "filter size.".format(filter_elem_num) + ) + std = (2.0 / filter_elem_num) ** 0.5 + return paddle.nn.initializer.normal.NormalInitializer(0.0, std, 0) + + filter_param = helper.create_parameter( + attr=helper.param_attr, + shape=filter_shape, + dtype=dtype, + default_initializer=_get_default_param_initializer(), + ) + + pre_bias = helper.create_variable_for_type_inference(dtype) + + if modulated: + helper.append_op( + type='deformable_conv', + inputs={ + 'Input': input, + 'Filter': filter_param, + 'Offset': offset, + 'Mask': mask, + }, + outputs={"Output": pre_bias}, + attrs={ + 'strides': stride, + 'paddings': padding, + 'dilations': dilation, + 'groups': groups, + 'deformable_groups': deformable_groups, + 'im2col_step': im2col_step, + }, + ) + + else: + helper.append_op( + type='deformable_conv_v1', + inputs={ + 'Input': input, + 'Filter': filter_param, + 'Offset': offset, + }, + outputs={"Output": pre_bias}, + attrs={ + 'strides': stride, + 'paddings': padding, + 'dilations': dilation, + 'groups': groups, + 'deformable_groups': deformable_groups, + 'im2col_step': im2col_step, + }, + ) + + output = helper.append_bias_op(pre_bias, dim_start=1, dim_end=2) + return output + + @static_only def deform_conv2d( x, @@ -309,7 +557,7 @@ def deform_conv2d( """ if mask is None: - return paddle.fluid.layers.deformable_conv( + return deformable_conv( input=x, offset=offset, mask=mask, @@ -327,7 +575,7 @@ def deform_conv2d( name=name, ) else: - return paddle.fluid.layers.deformable_conv( + return deformable_conv( input=x, offset=offset, mask=mask, -- GitLab