From 6150fade61ef0f51fd449ae2c64738a9d12f1542 Mon Sep 17 00:00:00 2001 From: HongyuJia Date: Thu, 18 Aug 2022 16:31:23 +0800 Subject: [PATCH] [phi] Transfer fluid trilinear_interp_v2 to phi trilinear_interp (add yaml) (#45145) * transfer trilinear op to phi, change name from trilinear_interp_v2 to trilinear_interp * reserve linear_interp param * change testcase scale if-branch * testcase test_imperative_case * fix trilinear testcase * import paddle in test_trilinear_interp_v2 --- paddle/phi/api/yaml/legacy_api.yaml | 11 ++ paddle/phi/api/yaml/legacy_backward.yaml | 12 ++ paddle/phi/core/compat/op_utils.h | 2 + .../kernels/cpu/interpolate_grad_kernel.cc | 2 +- paddle/phi/kernels/cpu/interpolate_kernel.cc | 2 +- .../kernels/gpu/interpolate_grad_kernel.cu | 2 +- paddle/phi/kernels/gpu/interpolate_kernel.cu | 2 +- paddle/phi/ops/compat/interpolate_sig.cc | 6 +- .../unittests/test_trilinear_interp_v2_op.py | 125 +++++++++++++----- python/paddle/nn/functional/common.py | 12 +- 10 files changed, 133 insertions(+), 43 deletions(-) diff --git a/paddle/phi/api/yaml/legacy_api.yaml b/paddle/phi/api/yaml/legacy_api.yaml index 8f9cc3c4118..e37706a126b 100755 --- a/paddle/phi/api/yaml/legacy_api.yaml +++ b/paddle/phi/api/yaml/legacy_api.yaml @@ -2736,6 +2736,17 @@ func : tril_triu backward : tril_triu_grad +- api : trilinear_interp + args : (Tensor x, Tensor out_size, Tensor[] size_tensor, Tensor scale_tensor, str data_layout, int out_d, int out_h, int out_w, float[] scale, str interp_method, bool align_corners, int align_mode) + output : Tensor(output) + infer_meta : + func : InterpolateInferMeta + optional: out_size, size_tensor, scale_tensor + kernel : + func : trilinear_interp + data_type : x + backward : trilinear_interp_grad + # python API: paddle.nn.initializer.TruncatedNormal - api : truncated_gaussian_random args : (int[] shape, float mean, float std, int seed, DataType dtype=DataType::FLOAT32, Place place={}) diff --git a/paddle/phi/api/yaml/legacy_backward.yaml b/paddle/phi/api/yaml/legacy_backward.yaml index bb2ee9448d9..6dfbdba0c4f 100755 --- a/paddle/phi/api/yaml/legacy_backward.yaml +++ b/paddle/phi/api/yaml/legacy_backward.yaml @@ -2628,6 +2628,18 @@ kernel : func : tril_triu_grad +- backward_api : trilinear_interp_grad + forward : trilinear_interp (Tensor x, Tensor out_size, Tensor[] size_tensor, Tensor scale_tensor, str data_layout, int out_d, int out_h, int out_w, float[] scale, str interp_method, bool align_corners, int align_mode) -> Tensor(output) + args : (Tensor x, Tensor out_size, Tensor[] size_tensor, Tensor scale_tensor, Tensor output_grad, str data_layout, int out_d, int out_h, int out_w, float[] scale, str interp_method, bool align_corners, int align_mode) + output : Tensor(x_grad) + infer_meta : + func : UnchangedInferMeta + param: [x] + optional: out_size, size_tensor, scale_tensor + kernel : + func : trilinear_interp_grad + data_type : output_grad + - backward_api : unbind_grad forward : unbind (Tensor input, int axis) -> Tensor[](out) args : (Tensor[] out_grad, int axis) diff --git a/paddle/phi/core/compat/op_utils.h b/paddle/phi/core/compat/op_utils.h index a08a4593b69..8a34da1fbe6 100644 --- a/paddle/phi/core/compat/op_utils.h +++ b/paddle/phi/core/compat/op_utils.h @@ -76,6 +76,8 @@ const std::unordered_set deprecated_op_names( "linear_interp_grad", "bilinear_interp", "bilinear_interp_grad", + "trilinear_interp", + "trilinear_interp_grad", "nearest_interp", "nearest_interp_grad", "bicubic_interp", diff --git a/paddle/phi/kernels/cpu/interpolate_grad_kernel.cc b/paddle/phi/kernels/cpu/interpolate_grad_kernel.cc index 3004ff62291..4abea61f344 100644 --- a/paddle/phi/kernels/cpu/interpolate_grad_kernel.cc +++ b/paddle/phi/kernels/cpu/interpolate_grad_kernel.cc @@ -1054,7 +1054,7 @@ PD_REGISTER_KERNEL(nearest_interp_grad, kernel->InputAt(2).SetBackend(phi::Backend::ALL_BACKEND); kernel->InputAt(3).SetBackend(phi::Backend::ALL_BACKEND); } -PD_REGISTER_KERNEL(trilinear_interp_v2_grad, +PD_REGISTER_KERNEL(trilinear_interp_grad, CPU, ALL_LAYOUT, phi::TrilinearInterpGradKernel, diff --git a/paddle/phi/kernels/cpu/interpolate_kernel.cc b/paddle/phi/kernels/cpu/interpolate_kernel.cc index 98f21172d4e..90a86a26219 100644 --- a/paddle/phi/kernels/cpu/interpolate_kernel.cc +++ b/paddle/phi/kernels/cpu/interpolate_kernel.cc @@ -1209,7 +1209,7 @@ PD_REGISTER_KERNEL(nearest_interp, kernel->InputAt(2).SetBackend(phi::Backend::ALL_BACKEND); kernel->InputAt(3).SetBackend(phi::Backend::ALL_BACKEND); } -PD_REGISTER_KERNEL(trilinear_interp_v2, +PD_REGISTER_KERNEL(trilinear_interp, CPU, ALL_LAYOUT, phi::TrilinearInterpKernel, diff --git a/paddle/phi/kernels/gpu/interpolate_grad_kernel.cu b/paddle/phi/kernels/gpu/interpolate_grad_kernel.cu index 906f5d7ec0a..8e2f46b5412 100644 --- a/paddle/phi/kernels/gpu/interpolate_grad_kernel.cu +++ b/paddle/phi/kernels/gpu/interpolate_grad_kernel.cu @@ -1587,7 +1587,7 @@ PD_REGISTER_KERNEL(nearest_interp_grad, kernel->InputAt(2).SetBackend(phi::Backend::ALL_BACKEND); kernel->InputAt(3).SetBackend(phi::Backend::ALL_BACKEND); } -PD_REGISTER_KERNEL(trilinear_interp_v2_grad, +PD_REGISTER_KERNEL(trilinear_interp_grad, GPU, ALL_LAYOUT, phi::TrilinearInterpGradKernel, diff --git a/paddle/phi/kernels/gpu/interpolate_kernel.cu b/paddle/phi/kernels/gpu/interpolate_kernel.cu index 60540ebfb55..ada2f41f8e7 100644 --- a/paddle/phi/kernels/gpu/interpolate_kernel.cu +++ b/paddle/phi/kernels/gpu/interpolate_kernel.cu @@ -1461,7 +1461,7 @@ PD_REGISTER_KERNEL(nearest_interp, kernel->InputAt(2).SetBackend(phi::Backend::ALL_BACKEND); kernel->InputAt(3).SetBackend(phi::Backend::ALL_BACKEND); } -PD_REGISTER_KERNEL(trilinear_interp_v2, +PD_REGISTER_KERNEL(trilinear_interp, GPU, ALL_LAYOUT, phi::TrilinearInterpKernel, diff --git a/paddle/phi/ops/compat/interpolate_sig.cc b/paddle/phi/ops/compat/interpolate_sig.cc index c68a6b782ff..1a1a1cbb667 100644 --- a/paddle/phi/ops/compat/interpolate_sig.cc +++ b/paddle/phi/ops/compat/interpolate_sig.cc @@ -47,7 +47,7 @@ KernelSignature NearestInterpOpArgumentMapping( } KernelSignature TrilinearInterpOpArgumentMapping( const ArgumentMappingContext& ctx) { - return KernelSignature("trilinear_interp_v2", + return KernelSignature("trilinear_interp", {"X", "OutSize", "SizeTensor", "Scale"}, {"data_layout", "out_d", @@ -121,7 +121,7 @@ KernelSignature NearestInterpGradOpArgumentMapping( } KernelSignature TrilinearInterpGradOpArgumentMapping( const ArgumentMappingContext& ctx) { - return KernelSignature("trilinear_interp_v2_grad", + return KernelSignature("trilinear_interp_grad", {"X", "OutSize", "SizeTensor", "Scale", "Out@GRAD"}, {"data_layout", "out_d", @@ -168,11 +168,13 @@ KernelSignature BicubicInterpGradOpArgumentMapping( PD_REGISTER_BASE_KERNEL_NAME(linear_interp_v2, linear_interp); PD_REGISTER_BASE_KERNEL_NAME(bilinear_interp_v2, bilinear_interp); +PD_REGISTER_BASE_KERNEL_NAME(trilinear_interp_v2, trilinear_interp); PD_REGISTER_BASE_KERNEL_NAME(nearest_interp_v2, nearest_interp); PD_REGISTER_BASE_KERNEL_NAME(bicubic_interp_v2, bicubic_interp); PD_REGISTER_BASE_KERNEL_NAME(linear_interp_v2_grad, linear_interp_grad); PD_REGISTER_BASE_KERNEL_NAME(bilinear_interp_v2_grad, bilinear_interp_grad); +PD_REGISTER_BASE_KERNEL_NAME(trilinear_interp_v2_grad, trilinear_interp_grad); PD_REGISTER_BASE_KERNEL_NAME(nearest_interp_v2_grad, nearest_interp_grad); PD_REGISTER_BASE_KERNEL_NAME(bicubic_interp_v2_grad, bicubic_interp_grad); diff --git a/python/paddle/fluid/tests/unittests/test_trilinear_interp_v2_op.py b/python/paddle/fluid/tests/unittests/test_trilinear_interp_v2_op.py index 4c799a826b2..b0bb25319fd 100755 --- a/python/paddle/fluid/tests/unittests/test_trilinear_interp_v2_op.py +++ b/python/paddle/fluid/tests/unittests/test_trilinear_interp_v2_op.py @@ -19,11 +19,43 @@ import numpy as np from op_test import OpTest import paddle.fluid.core as core import paddle.fluid as fluid +from paddle.fluid.framework import _test_eager_guard from paddle.nn.functional import interpolate +import paddle np.random.seed(123) +def trilinear_interp_test(x, + OutSize=None, + SizeTensor=None, + Scale=None, + data_layout='NCHW', + out_d=-1, + out_h=-1, + out_w=-1, + scale=[], + interp_method='linear', + align_corners=False, + align_mode=1): + if isinstance(scale, float) or isinstance(scale, int): + scale_list = [] + for _ in range(len(x.shape) - 2): + scale_list.append(scale) + scale = list(map(float, scale_list)) + elif isinstance(scale, list) or isinstance(scale, tuple): + scale = list(map(float, scale)) + if SizeTensor is not None: + if not isinstance(SizeTensor, list) and not isinstance( + SizeTensor, tuple): + SizeTensor = [SizeTensor] + return paddle._C_ops.final_state_trilinear_interp(x, OutSize, SizeTensor, + Scale, data_layout, out_d, + out_h, out_w, scale, + interp_method, + align_corners, align_mode) + + def trilinear_interp_np(input, out_d, out_h, @@ -141,6 +173,7 @@ def trilinear_interp_np(input, class TestTrilinearInterpOp(OpTest): def setUp(self): + self.python_api = trilinear_interp_test self.out_size = None self.actual_shape = None self.data_layout = 'NCDHW' @@ -148,8 +181,7 @@ class TestTrilinearInterpOp(OpTest): self.op_type = "trilinear_interp_v2" # NOTE(dev): some AsDispensible input is not used under imperative mode. # Skip check_eager while found them in Inputs. - # TODO(dev): add self.python_api - self.check_eager = False + self.check_eager = True input_np = np.random.random(self.input_shape).astype("float32") scale_w = 0 @@ -164,9 +196,10 @@ class TestTrilinearInterpOp(OpTest): in_h = self.input_shape[2] in_w = self.input_shape[3] - if self.scale > 0: + if self.scale: if isinstance(self.scale, float) or isinstance(self.scale, int): - scale_d = scale_h = scale_w = float(self.scale) + if self.scale > 0: + scale_d = scale_h = scale_w = float(self.scale) if isinstance(self.scale, list) and len(self.scale) == 1: scale_d = scale_w = scale_h = self.scale[0] elif isinstance(self.scale, list) and len(self.scale) > 1: @@ -206,9 +239,10 @@ class TestTrilinearInterpOp(OpTest): 'align_mode': self.align_mode, 'data_layout': data_layout } - if self.scale > 0: + if self.scale: if isinstance(self.scale, float) or isinstance(self.scale, int): - self.scale = [self.scale] + if self.scale > 0: + self.scale = [self.scale] if isinstance(self.scale, list) and len(self.scale) == 1: self.scale = [self.scale[0], self.scale[0], self.scale[0]] self.attrs['scale'] = self.scale @@ -229,7 +263,7 @@ class TestTrilinearInterpOp(OpTest): self.out_d = 2 self.out_h = 2 self.out_w = 2 - self.scale = 0. + self.scale = [] self.out_size = np.array([3, 3, 3]).astype("int32") self.align_corners = True self.align_mode = 1 @@ -243,7 +277,7 @@ class TestTrilinearInterpCase1(TestTrilinearInterpOp): self.out_d = 1 self.out_h = 1 self.out_w = 1 - self.scale = 0. + self.scale = [] self.align_corners = True self.align_mode = 1 @@ -256,7 +290,7 @@ class TestTrilinearInterpCase2(TestTrilinearInterpOp): self.out_d = 12 self.out_h = 12 self.out_w = 12 - self.scale = 0. + self.scale = [] self.align_corners = True self.align_mode = 1 @@ -269,7 +303,7 @@ class TestTrilinearInterpCase3(TestTrilinearInterpOp): self.out_d = 32 self.out_h = 16 self.out_w = 8 - self.scale = 0. + self.scale = [] self.align_corners = True self.align_mode = 1 @@ -282,7 +316,7 @@ class TestTrilinearInterpCase4(TestTrilinearInterpOp): self.out_d = 1 self.out_h = 1 self.out_w = 1 - self.scale = 0. + self.scale = [] self.out_size = np.array([2, 2, 2]).astype("int32") self.align_corners = True self.align_mode = 1 @@ -296,7 +330,7 @@ class TestTrilinearInterpCase5(TestTrilinearInterpOp): self.out_d = 12 self.out_h = 12 self.out_w = 12 - self.scale = 0. + self.scale = [] self.out_size = np.array([11, 11, 11]).astype("int32") self.align_corners = True self.align_mode = 1 @@ -310,7 +344,7 @@ class TestTrilinearInterpCase6(TestTrilinearInterpOp): self.out_d = 8 self.out_h = 32 self.out_w = 16 - self.scale = 0. + self.scale = [] self.out_size = np.array([17, 9, 5]).astype("int32") self.align_corners = True self.align_mode = 1 @@ -324,7 +358,7 @@ class TestTrilinearInterpSame(TestTrilinearInterpOp): self.out_d = 16 self.out_h = 8 self.out_w = 4 - self.scale = 0. + self.scale = [] self.align_corners = True self.align_mode = 1 @@ -337,7 +371,7 @@ class TestTrilinearInterpSameHW(TestTrilinearInterpOp): self.out_d = 8 self.out_h = 8 self.out_w = 4 - self.scale = 0. + self.scale = [] self.align_corners = True self.align_mode = 1 @@ -350,7 +384,7 @@ class TestTrilinearInterpActualShape(TestTrilinearInterpOp): self.out_d = 64 self.out_h = 32 self.out_w = 16 - self.scale = 0. + self.scale = [] self.out_size = np.array([33, 19, 7]).astype("int32") self.align_corners = True self.align_mode = 1 @@ -364,7 +398,7 @@ class TestTrilinearInterpDatalayout(TestTrilinearInterpOp): self.out_d = 2 self.out_h = 2 self.out_w = 2 - self.scale = 0. + self.scale = [] self.out_size = np.array([3, 3, 3]).astype("int32") self.align_corners = True self.align_mode = 1 @@ -374,18 +408,19 @@ class TestTrilinearInterpDatalayout(TestTrilinearInterpOp): class TestTrilinearInterpOpUint8(OpTest): def setUp(self): + self.python_api = trilinear_interp_test self.out_size = None self.actual_shape = None self.init_test_case() self.op_type = "trilinear_interp_v2" - # TODO(dev): add self.python_api - self.check_eager = False + self.check_eager = True input_np = np.random.randint(low=0, high=256, size=self.input_shape).astype("uint8") - if self.scale > 0: + if self.scale: if isinstance(self.scale, float) or isinstance(self.scale, int): - scale_d = scale_h = scale_w = float(self.scale) + if self.scale > 0: + scale_d = scale_h = scale_w = float(self.scale) if isinstance(self.scale, list) and len(self.scale) == 1: scale_d = scale_w = scale_h = self.scale[0] elif isinstance(self.scale, list) and len(self.scale) > 1: @@ -416,9 +451,10 @@ class TestTrilinearInterpOpUint8(OpTest): 'align_corners': self.align_corners, 'align_mode': self.align_mode } - if self.scale > 0: + if self.scale: if isinstance(self.scale, float) or isinstance(self.scale, int): - self.scale = [self.scale] + if self.scale > 0: + self.scale = [self.scale] if isinstance(self.scale, list) and len(self.scale) == 1: self.scale = [self.scale[0], self.scale[0], self.scale[0]] self.attrs['scale'] = self.scale @@ -435,7 +471,7 @@ class TestTrilinearInterpOpUint8(OpTest): self.out_d = 13 self.out_h = 10 self.out_w = 9 - self.scale = 0. + self.scale = [] self.align_corners = True self.align_mode = 1 @@ -448,7 +484,7 @@ class TestTrilinearInterpCase1Uint8(TestTrilinearInterpOpUint8): self.out_d = 13 self.out_h = 7 self.out_w = 2 - self.scale = 0. + self.scale = [] self.align_corners = True self.align_mode = 1 @@ -461,7 +497,7 @@ class TestTrilinearInterpCase2Uint8(TestTrilinearInterpOpUint8): self.out_d = 3 self.out_h = 5 self.out_w = 13 - self.scale = 0. + self.scale = [] self.out_size = np.array([6, 15, 21]).astype("int32") self.align_corners = True self.align_mode = 1 @@ -535,7 +571,7 @@ class TestTrilinearInterpZero(TestTrilinearInterpOp): self.out_d = 30 self.out_h = 20 self.out_w = 25 - self.scale = 0.0 + self.scale = [] self.align_corners = False self.align_mode = 0 @@ -543,12 +579,12 @@ class TestTrilinearInterpZero(TestTrilinearInterpOp): class TestTrilinearInterpOp_attr_tensor(OpTest): def setUp(self): + self.python_api = trilinear_interp_test self.out_size = None self.actual_shape = None self.init_test_case() self.op_type = "trilinear_interp_v2" - # TODO(dev): add self.python_api - self.check_eager = False + self.check_eager = True self.shape_by_1Dtensor = False self.scale_by_1Dtensor = False self.attrs = { @@ -562,9 +598,10 @@ class TestTrilinearInterpOp_attr_tensor(OpTest): if self.scale_by_1Dtensor: self.inputs['Scale'] = np.array([self.scale]).astype("float32") - elif self.scale > 0: + elif self.scale: if isinstance(self.scale, float) or isinstance(self.scale, int): - scale_d = scale_h = scale_w = float(self.scale) + if self.scale > 0: + scale_d = scale_h = scale_w = float(self.scale) if isinstance(self.scale, list) and len(self.scale) == 1: scale_d = scale_w = scale_h = self.scale[0] elif isinstance(self.scale, list) and len(self.scale) > 1: @@ -593,9 +630,10 @@ class TestTrilinearInterpOp_attr_tensor(OpTest): self.attrs['out_d'] = self.out_d self.attrs['out_h'] = self.out_h self.attrs['out_w'] = self.out_w - if self.scale > 0: + if self.scale: if isinstance(self.scale, float) or isinstance(self.scale, int): - self.scale = [self.scale] + if self.scale > 0: + self.scale = [self.scale] if isinstance(self.scale, list) and len(self.scale) == 1: self.scale = [self.scale[0], self.scale[0], self.scale[0]] self.attrs['scale'] = self.scale @@ -619,7 +657,7 @@ class TestTrilinearInterpOp_attr_tensor(OpTest): self.out_d = 2 self.out_h = 3 self.out_w = 3 - self.scale = 0. + self.scale = [] self.out_size = [2, 3, 3] self.align_corners = True self.align_mode = 1 @@ -649,7 +687,7 @@ class TestTrilinearInterp_attr_tensor_Case2(TestTrilinearInterpOp_attr_tensor): self.out_d = 16 self.out_h = 12 self.out_w = 4 - self.scale = 0. + self.scale = [] self.out_size = [16, 4, 10] self.align_corners = True self.align_mode = 1 @@ -674,7 +712,12 @@ class TestTrilinearInterp_attr_tensor_Case3(TestTrilinearInterpOp_attr_tensor): class TestTrilinearInterpAPI(unittest.TestCase): - def test_case(self): + def test_imperative_case(self): + with _test_eager_guard(): + self.func_case() + self.func_case() + + def func_case(self): x = fluid.data(name="x", shape=[2, 3, 6, 9, 4], dtype="float32") y = fluid.data(name="y", shape=[2, 6, 9, 4, 3], dtype="float32") @@ -742,6 +785,16 @@ class TestTrilinearInterpAPI(unittest.TestCase): for i in range(len(results) - 1): np.testing.assert_allclose(results[i + 1], expect_res, rtol=1e-05) + # Follow the calculation of preceding out6, out7, out8. + # To pass CI-coverage, calculate out9 without verifying accuracy. + # Preceding PR link: https://github.com/PaddlePaddle/Paddle/pull/26520/files#diff-ee0c2b73d08659e90a8f3ac48451a6588d35e1613742f864f9aad4394e12c290 + with fluid.dygraph.guard(): + x = fluid.dygraph.to_variable(x_data) + out9 = interpolate(x, + size=[12, 18, 8], + mode='trilinear', + data_format="NCDHW") + class TestTrilinearInterpOpException(unittest.TestCase): diff --git a/python/paddle/nn/functional/common.py b/python/paddle/nn/functional/common.py index c6b4f835ba7..54da3f28cf3 100644 --- a/python/paddle/nn/functional/common.py +++ b/python/paddle/nn/functional/common.py @@ -615,7 +615,17 @@ def interpolate(x, else: out = _C_ops.bilinear_interp_v2(x, *dy_attr) elif resample_type == "trilinear": - out = _C_ops.trilinear_interp_v2(x, *dy_attr) + if in_dygraph_mode(): + out = _C_ops.final_state_trilinear_interp( + x, inputs['OutSize'] if 'OutSize' in inputs else None, + inputs['SizeTensor'] if 'SizeTensor' in inputs else None, + inputs['Scale'] if 'Scale' in inputs else None, + attrs['data_layout'], attrs['out_d'], attrs['out_h'], + attrs['out_w'], attrs['scale'] if 'scale' in attrs else [], + attrs['interp_method'], attrs['align_corners'], + attrs['align_mode']) + else: + out = _C_ops.trilinear_interp_v2(x, *dy_attr) elif resample_type == "nearest": if in_dygraph_mode(): out = _C_ops.final_state_nearest_interp( -- GitLab