From 5ed1209d5fe504de55646e7ad816eb9fceb6d234 Mon Sep 17 00:00:00 2001 From: bapijun Date: Fri, 29 Sep 2023 01:40:15 +0800 Subject: [PATCH 1/3] add api for diagonal scatter --- python/paddle/__init__.py | 2 + python/paddle/tensor/__init__.py | 66 ++------------------ python/paddle/tensor/manipulation.py | 25 +++++++- test/legacy_test/test_diagonal_scatter.py | 73 +++++++++++++++++++++++ 4 files changed, 101 insertions(+), 65 deletions(-) create mode 100644 test/legacy_test/test_diagonal_scatter.py diff --git a/python/paddle/__init__.py b/python/paddle/__init__.py index e73b9ae0cc309d..412c24e14d3673 100644 --- a/python/paddle/__init__.py +++ b/python/paddle/__init__.py @@ -211,6 +211,7 @@ scatter_, scatter_nd_add, scatter_nd, + diagonal_scatter, shard_index, slice, crop, @@ -563,6 +564,7 @@ 'diagflat', 'isnan', 'scatter_nd_add', + 'diagonal_scatter', 'unstack', 'get_default_dtype', 'save', diff --git a/python/paddle/tensor/__init__.py b/python/paddle/tensor/__init__.py index c61bd9a361cdc2..0dfa0ebac4132c 100644 --- a/python/paddle/tensor/__init__.py +++ b/python/paddle/tensor/__init__.py @@ -130,6 +130,7 @@ from .manipulation import scatter_ # noqa: F401 from .manipulation import scatter_nd_add # noqa: F401 from .manipulation import scatter_nd # noqa: F401 +from .manipulation import diagonal_scatter # noqa: F401 from .manipulation import shard_index # noqa: F401 from .manipulation import slice # noqa: F401 from .manipulation import split # noqa: F401 @@ -327,8 +328,6 @@ from .math import i1e # noqa: F401 from .math import polygamma # noqa: F401 from .math import polygamma_ # noqa: F401 -from .math import renorm # noqa: F401 -from .math import renorm_ # noqa: F401 from .random import multinomial # noqa: F401 from .random import standard_normal # noqa: F401 @@ -377,9 +376,6 @@ from .einsum import einsum # noqa: F401 -from ..signal import istft # noqa: F401 -from ..signal import stft # noqa: F401 - # this list used in math_op_patch.py for _binary_creator_ tensor_method_func = [ # noqa 'create_parameter', @@ -413,7 +409,6 @@ 'all', 'any', 'asin', - 'asin_', 'atan', 'ceil', 'ceil_', @@ -497,6 +492,8 @@ 'add_', 'subtract', 'subtract_', + 'atan', + 'logsumexp', 'inverse', 'log1p', 'log1p_', @@ -558,6 +555,7 @@ 'scatter', 'scatter_', 'scatter_nd_add', + 'diagonal_scatter', 'scatter_nd', 'shard_index', 'slice', @@ -634,7 +632,6 @@ 'triangular_solve', 'asinh', 'atanh', - 'atanh_', 'acosh', 'lu', 'lu_unpack', @@ -690,61 +687,6 @@ 'i1e', 'polygamma', 'polygamma_', - 'atan2', - 'diagflat', - 'multinomial', - 'pinv', - 'renorm', - 'renorm_', - 'tan', - 'tan_', - 'tril', - 'tril_', - 'triu', - 'triu_', - 'stft', - 'istft', - 'abs_', - 'acos_', - 'atan_', - 'cos_', - 'cosh_', - 'sin_', - 'sinh_', - 'acosh_', - 'asinh_', - 'diag', - 'eye', - 'linspace', - 'fill_constant', - 'ones', - 'ones_like', - 'zeros', - 'zeros_like', - 'arange', - 'full', - 'full_like', - 'meshgrid', - 'empty', - 'empty_like', - 'complex', - 'eigh', - 'standard_normal', - 'normal', - 'uniform', - 'randn', - 'rand', - 'randint', - 'randint_like', - 'randperm', - 'poisson', - 'searchsorted', - 'set_printoptions', - 'array_length', - 'array_read', - 'array_write', - 'create_array', - 'einsum', 'normal_', ] diff --git a/python/paddle/tensor/manipulation.py b/python/paddle/tensor/manipulation.py index aa1f1898b0186c..3b3b870aac4783 100644 --- a/python/paddle/tensor/manipulation.py +++ b/python/paddle/tensor/manipulation.py @@ -1984,10 +1984,8 @@ def split(x, num_or_sections, axis=0, name=None): dim = (len(input.shape) + dim) if dim < 0 else dim if isinstance(num_or_sections, int): - dim = dim if dim >= 0 else dim + len(input.shape) return _C_ops.split_with_num(input, num_or_sections, dim) else: - dim = dim if dim >= 0 else dim + len(input.shape) return _C_ops.split(input, num_or_sections, dim) else: @@ -3170,7 +3168,7 @@ def tile(x, repeat_times, name=None): # Tensor(shape=[1, 6], dtype=int32, place=Place(gpu:0), stop_gradient=True, # [[1, 2, 3, 1, 2, 3]]) """ - if in_dynamic_or_pir_mode(): + if in_dynamic_mode(): if isinstance(repeat_times, core.eager.Tensor): assert ( repeat_times.ndim == 1 @@ -5154,6 +5152,27 @@ def unfold(x, axis, size, step, name=None): """ return _C_ops.tensor_unfold(x, axis, size, step) +def _check_diagonal_scatter_shape(diag_shape, src_shape): + if diag_shape != src_shape: + raise ValueError(f"For diagonal_scatter, the shape of src should equal to the shape of input diagonal," + f"but got src.shape {src_shape} and diagonal shape {diag_shape}.") + +def diagonal_scatter(x, src, offset=0, dim1=0, dim2=1): + op_type = 'diagonal_scatter' + # input_dtype = ['int32', 'int64', 'float32', 'float64'] + + # check_variable_and_dtype(x, 'x', input_dtype, op_type) + # check_variable_and_dtype(src, 'src', input_dtype, op_type) + check_type(offset, 'offset', (int), op_type) + check_type(dim1, 'dim1', (int), op_type) + check_type(dim2, 'dim2', (int), op_type) + input_diag = paddle.diagonal(x, offset, dim1, dim2) + _check_diagonal_scatter_shape(input_diag.shape, src.shape) + embed = paddle.ones_like(src) + embed = paddle.nn.functional.diag_embed(embed, offset, dim1, dim2) + embed = x * embed + src = paddle.nn.functional.diag_embed(src, offset, dim1, dim2) + return x + src - embed # TODO(dev): We need avoid implementing it by this way. __METHODS = { diff --git a/test/legacy_test/test_diagonal_scatter.py b/test/legacy_test/test_diagonal_scatter.py new file mode 100644 index 00000000000000..03ab528f1e95fe --- /dev/null +++ b/test/legacy_test/test_diagonal_scatter.py @@ -0,0 +1,73 @@ +# Copyright (c) 2023 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. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest +import numpy as np +import paddle + +class TestDiagnalScatterAPI(unittest.TestCase): + def setUp(self): + + self.x_dtype = 'float32' + self.x_shape = [3, 3] + self.x = np.zeros([3, 3]).astype('float32') + self.src_dtype = 'float32' + self.src_shape = [3] + self.src = np.ones(3).astype('float32') + self.offset = 0 + self.init_input() + self.place = ( + paddle.CUDAPlace(0) + if paddle.is_compiled_with_cuda() + else paddle.CPUPlace() + ) + + def init_input(self): + pass + + def test_static_api(self): + paddle.enable_static() + with paddle.static.program_guard(paddle.static.Program()): + x = paddle.static.data('x', self.x_shape, dtype=self.x_dtype) + src = paddle.static.data('src', self.src_shape, dtype=self.x_dtype) + out = paddle.diagonal_scatter(x, src, self.offset) + exe = paddle.static.Executor(self.place) + res = exe.run( + feed={ + 'x': self.x, + 'src': self.src, + }, + fetch_list=[out], + ) + expect_output = [[1.0,0.0,0.0], + [0.0,1.0,0.0], + [0.0,0.0,1.0]] + np.testing.assert_allclose(expect_output, res[0], atol=1e-07) + + def test_dygraph_api(self): + paddle.disable_static(self.place) + x = paddle.to_tensor(self.x) + src = paddle.to_tensor(self.src) + res = paddle.diagonal_scatter(x, src, self.offset) + + expect_output = np.array([[1.0,0.0,0.0], + [0.0,1.0,0.0], + [0.0,0.0,1.0]]) + np.testing.assert_allclose(expect_output, res, atol=1e-07) + paddle.enable_static() + + +if __name__ == '__main__': + paddle.enable_static() + unittest.main() \ No newline at end of file From 72f8c308b4ef067f56a0c49b3266cde98ca27b3d Mon Sep 17 00:00:00 2001 From: bapijun Date: Tue, 10 Oct 2023 20:50:24 +0800 Subject: [PATCH 2/3] fix the bug --- python/paddle/tensor/__init__.py | 64 +++++++++++++++++++++++++++- python/paddle/tensor/manipulation.py | 4 +- 2 files changed, 65 insertions(+), 3 deletions(-) diff --git a/python/paddle/tensor/__init__.py b/python/paddle/tensor/__init__.py index 0dfa0ebac4132c..8a450ebf1da417 100644 --- a/python/paddle/tensor/__init__.py +++ b/python/paddle/tensor/__init__.py @@ -328,6 +328,8 @@ from .math import i1e # noqa: F401 from .math import polygamma # noqa: F401 from .math import polygamma_ # noqa: F401 +from .math import renorm # noqa: F401 +from .math import renorm_ # noqa: F401 from .random import multinomial # noqa: F401 from .random import standard_normal # noqa: F401 @@ -376,6 +378,9 @@ from .einsum import einsum # noqa: F401 +from ..signal import istft # noqa: F401 +from ..signal import stft # noqa: F401 + # this list used in math_op_patch.py for _binary_creator_ tensor_method_func = [ # noqa 'create_parameter', @@ -409,6 +414,7 @@ 'all', 'any', 'asin', + 'asin_', 'atan', 'ceil', 'ceil_', @@ -492,8 +498,6 @@ 'add_', 'subtract', 'subtract_', - 'atan', - 'logsumexp', 'inverse', 'log1p', 'log1p_', @@ -632,6 +636,7 @@ 'triangular_solve', 'asinh', 'atanh', + 'atanh_', 'acosh', 'lu', 'lu_unpack', @@ -687,6 +692,61 @@ 'i1e', 'polygamma', 'polygamma_', + 'atan2', + 'diagflat', + 'multinomial', + 'pinv', + 'renorm', + 'renorm_', + 'tan', + 'tan_', + 'tril', + 'tril_', + 'triu', + 'triu_', + 'stft', + 'istft', + 'abs_', + 'acos_', + 'atan_', + 'cos_', + 'cosh_', + 'sin_', + 'sinh_', + 'acosh_', + 'asinh_', + 'diag', + 'eye', + 'linspace', + 'fill_constant', + 'ones', + 'ones_like', + 'zeros', + 'zeros_like', + 'arange', + 'full', + 'full_like', + 'meshgrid', + 'empty', + 'empty_like', + 'complex', + 'eigh', + 'standard_normal', + 'normal', + 'uniform', + 'randn', + 'rand', + 'randint', + 'randint_like', + 'randperm', + 'poisson', + 'searchsorted', + 'set_printoptions', + 'array_length', + 'array_read', + 'array_write', + 'create_array', + 'einsum', 'normal_', ] diff --git a/python/paddle/tensor/manipulation.py b/python/paddle/tensor/manipulation.py index 3b3b870aac4783..5da8c594412cb4 100644 --- a/python/paddle/tensor/manipulation.py +++ b/python/paddle/tensor/manipulation.py @@ -1984,8 +1984,10 @@ def split(x, num_or_sections, axis=0, name=None): dim = (len(input.shape) + dim) if dim < 0 else dim if isinstance(num_or_sections, int): + dim = dim if dim >= 0 else dim + len(input.shape) return _C_ops.split_with_num(input, num_or_sections, dim) else: + dim = dim if dim >= 0 else dim + len(input.shape) return _C_ops.split(input, num_or_sections, dim) else: @@ -3168,7 +3170,7 @@ def tile(x, repeat_times, name=None): # Tensor(shape=[1, 6], dtype=int32, place=Place(gpu:0), stop_gradient=True, # [[1, 2, 3, 1, 2, 3]]) """ - if in_dynamic_mode(): + if in_dynamic_or_pir_mode(): if isinstance(repeat_times, core.eager.Tensor): assert ( repeat_times.ndim == 1 From 5cefe4b480217b733adc4eebcb1b2ede88ae861f Mon Sep 17 00:00:00 2001 From: bapijun Date: Fri, 20 Oct 2023 16:34:09 +0800 Subject: [PATCH 3/3] give up for merging --- python/paddle/tensor/__init__.py | 9 +++++++++ python/paddle/tensor/manipulation.py | 2 ++ 2 files changed, 11 insertions(+) diff --git a/python/paddle/tensor/__init__.py b/python/paddle/tensor/__init__.py index 8a450ebf1da417..e1add04103656c 100644 --- a/python/paddle/tensor/__init__.py +++ b/python/paddle/tensor/__init__.py @@ -381,6 +381,15 @@ from ..signal import istft # noqa: F401 from ..signal import stft # noqa: F401 +from ..signal import istft # noqa: F401 +from ..signal import stft # noqa: F401 + +from ..signal import istft # noqa: F401 +from ..signal import stft # noqa: F401 + +from ..signal import istft # noqa: F401 +from ..signal import stft # noqa: F401 + # this list used in math_op_patch.py for _binary_creator_ tensor_method_func = [ # noqa 'create_parameter', diff --git a/python/paddle/tensor/manipulation.py b/python/paddle/tensor/manipulation.py index 5da8c594412cb4..70e8099c093667 100644 --- a/python/paddle/tensor/manipulation.py +++ b/python/paddle/tensor/manipulation.py @@ -1975,8 +1975,10 @@ def split(x, num_or_sections, axis=0, name=None): ) if isinstance(num_or_sections, int): + dim = dim if dim >= 0 else dim + len(input.shape) return _C_ops.split_with_num(input, num_or_sections, dim) else: + dim = dim if dim >= 0 else dim + len(input.shape) return _C_ops.split(input, num_or_sections, dim) elif in_pir_mode(): if isinstance(dim, int):