未验证 提交 6ff19d66 编写于 作者: Z zmxdream 提交者: GitHub

[New API]add rot90 api (#37634)

* update

* update. test=develop

* fix. test=develop

* fix ut. test=develop

* fix ut. test=develop

* fix ut. test=develop

* update. test=develop

* fix ut. test=develop

* fix ut. test=develop

* fix sample code. test=develop

* fix ut. test=develop

* fix ut. test=develop

* fix ut. test=develop

* fix ut. test=develop

* fix paddle.rot90 doc. test=develop

* update ut. test=develop

* fix. test=develop

* fix .test=develop

* fix .test=develop

* fix doc. test=develop
上级 f5609de4
...@@ -115,8 +115,6 @@ TEST(HeterPipelineTrainerTest, GPU) { ...@@ -115,8 +115,6 @@ TEST(HeterPipelineTrainerTest, GPU) {
t3.add_trainers(1); t3.add_trainers(1);
t3.add_trainers(1); t3.add_trainers(1);
t3.add_trainers(1); t3.add_trainers(1);
t3.add_dump_fields("hello");
t3.add_dump_param("fc_0");
auto* heter_section_param3 = t3.mutable_heter_section_param(); auto* heter_section_param3 = t3.mutable_heter_section_param();
heter_section_param3->set_num_pipeline_stages(3); heter_section_param3->set_num_pipeline_stages(3);
heter_section_param3->set_pipeline_stage(2); heter_section_param3->set_pipeline_stage(2);
......
...@@ -150,6 +150,7 @@ from .tensor.manipulation import unsqueeze # noqa: F401 ...@@ -150,6 +150,7 @@ from .tensor.manipulation import unsqueeze # noqa: F401
from .tensor.manipulation import unsqueeze_ # noqa: F401 from .tensor.manipulation import unsqueeze_ # noqa: F401
from .tensor.manipulation import unstack # noqa: F401 from .tensor.manipulation import unstack # noqa: F401
from .tensor.manipulation import flip # noqa: F401 from .tensor.manipulation import flip # noqa: F401
from .tensor.manipulation import rot90 # noqa: F401
from .tensor.manipulation import unbind # noqa: F401 from .tensor.manipulation import unbind # noqa: F401
from .tensor.manipulation import roll # noqa: F401 from .tensor.manipulation import roll # noqa: F401
from .tensor.manipulation import chunk # noqa: F401 from .tensor.manipulation import chunk # noqa: F401
...@@ -408,6 +409,7 @@ __all__ = [ # noqa ...@@ -408,6 +409,7 @@ __all__ = [ # noqa
'bitwise_not', 'bitwise_not',
'mm', 'mm',
'flip', 'flip',
'rot90',
'bincount', 'bincount',
'histogram', 'histogram',
'multiplex', 'multiplex',
......
# Copyright (c) 2021 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.
from __future__ import print_function
import unittest
import numpy as np
import paddle
import paddle.fluid as fluid
import paddle.fluid.core as core
from paddle.fluid import Program, program_guard
class TestRot90_API(unittest.TestCase):
"""Test rot90 api."""
def test_static_graph(self):
paddle.enable_static()
startup_program = fluid.Program()
train_program = fluid.Program()
with fluid.program_guard(train_program, startup_program):
input = fluid.data(name='input', dtype='float32', shape=[2, 3])
output = paddle.rot90(input, k=1, axes=[0, 1])
output = paddle.rot90(output, k=1, axes=[0, 1])
output = output.rot90(k=1, axes=[0, 1])
place = fluid.CPUPlace()
if fluid.core.is_compiled_with_cuda():
place = fluid.CUDAPlace(0)
exe = fluid.Executor(place)
exe.run(startup_program)
img = np.array([[1, 2, 3], [4, 5, 6]]).astype(np.float32)
res = exe.run(train_program,
feed={'input': img},
fetch_list=[output])
out_np = np.array(res[0])
out_ref = np.array([[4, 1], [5, 2], [6, 3]]).astype(np.float32)
self.assertTrue(
(out_np == out_ref).all(),
msg='rot90 output is wrong, out =' + str(out_np))
def test_static_k_0(self):
paddle.enable_static()
input = fluid.data(name='input', dtype='float32', shape=[2, 3])
startup_program = fluid.Program()
train_program = fluid.Program()
with fluid.program_guard(train_program, startup_program):
input = fluid.data(name='input', dtype='float32', shape=[2, 3])
output = paddle.rot90(input, k=0, axes=[0, 1])
place = fluid.CPUPlace()
if fluid.core.is_compiled_with_cuda():
place = fluid.CUDAPlace(0)
exe = fluid.Executor(place)
exe.run(startup_program)
img = np.array([[1, 2, 3], [4, 5, 6]]).astype(np.float32)
res = exe.run(train_program,
feed={'input': img},
fetch_list=[output])
out_np = np.array(res[0])
out_ref = np.array([[1, 2, 3], [4, 5, 6]]).astype(np.float32)
self.assertTrue(
(out_np == out_ref).all(),
msg='rot90 output is wrong, out =' + str(out_np))
def test_static_k_2(self):
paddle.enable_static()
input = fluid.data(name='input', dtype='float32', shape=[2, 3])
startup_program = fluid.Program()
train_program = fluid.Program()
with fluid.program_guard(train_program, startup_program):
input = fluid.data(name='input', dtype='float32', shape=[2, 3])
output = paddle.rot90(input, k=2, axes=[0, 1])
place = fluid.CPUPlace()
if fluid.core.is_compiled_with_cuda():
place = fluid.CUDAPlace(0)
exe = fluid.Executor(place)
exe.run(startup_program)
img = np.array([[1, 2, 3], [4, 5, 6]]).astype(np.float32)
res = exe.run(train_program,
feed={'input': img},
fetch_list=[output])
out_np = np.array(res[0])
out_ref = np.array([[6, 5, 4], [3, 2, 1]]).astype(np.float32)
self.assertTrue(
(out_np == out_ref).all(),
msg='rot90 output is wrong, out =' + str(out_np))
def test_static_k_3(self):
paddle.enable_static()
input = fluid.data(name='input', dtype='float32', shape=[2, 3])
startup_program = fluid.Program()
train_program = fluid.Program()
with fluid.program_guard(train_program, startup_program):
input = fluid.data(name='input', dtype='float32', shape=[2, 3])
output = paddle.rot90(input, k=3, axes=[0, 1])
place = fluid.CPUPlace()
if fluid.core.is_compiled_with_cuda():
place = fluid.CUDAPlace(0)
exe = fluid.Executor(place)
exe.run(startup_program)
img = np.array([[1, 2, 3], [4, 5, 6]]).astype(np.float32)
res = exe.run(train_program,
feed={'input': img},
fetch_list=[output])
out_np = np.array(res[0])
out_ref = np.array([[4, 1], [5, 2], [6, 3]]).astype(np.float32)
self.assertTrue(
(out_np == out_ref).all(),
msg='rot90 output is wrong, out =' + str(out_np))
def test_static_neg_k_1(self):
paddle.enable_static()
input = fluid.data(name='input', dtype='float32', shape=[2, 3])
startup_program = fluid.Program()
train_program = fluid.Program()
with fluid.program_guard(train_program, startup_program):
input = fluid.data(name='input', dtype='float32', shape=[2, 3])
output = paddle.rot90(input, k=-1, axes=[0, 1])
place = fluid.CPUPlace()
if fluid.core.is_compiled_with_cuda():
place = fluid.CUDAPlace(0)
exe = fluid.Executor(place)
exe.run(startup_program)
img = np.array([[1, 2, 3], [4, 5, 6]]).astype(np.float32)
res = exe.run(train_program,
feed={'input': img},
fetch_list=[output])
out_np = np.array(res[0])
out_ref = np.array([[4, 1], [5, 2], [6, 3]]).astype(np.float32)
self.assertTrue(
(out_np == out_ref).all(),
msg='rot90 output is wrong, out =' + str(out_np))
def test_static_neg_k_2(self):
paddle.enable_static()
input = fluid.data(name='input', dtype='float32', shape=[2, 3])
startup_program = fluid.Program()
train_program = fluid.Program()
with fluid.program_guard(train_program, startup_program):
input = fluid.data(name='input', dtype='float32', shape=[2, 3])
output = paddle.rot90(input, k=-2, axes=[0, 1])
place = fluid.CPUPlace()
if fluid.core.is_compiled_with_cuda():
place = fluid.CUDAPlace(0)
exe = fluid.Executor(place)
exe.run(startup_program)
img = np.array([[1, 2, 3], [4, 5, 6]]).astype(np.float32)
res = exe.run(train_program,
feed={'input': img},
fetch_list=[output])
out_np = np.array(res[0])
out_ref = np.array([[6, 5, 4], [3, 2, 1]]).astype(np.float32)
self.assertTrue(
(out_np == out_ref).all(),
msg='rot90 output is wrong, out =' + str(out_np))
def test_static_neg_k_3(self):
paddle.enable_static()
input = fluid.data(name='input', dtype='float32', shape=[2, 3])
startup_program = fluid.Program()
train_program = fluid.Program()
with fluid.program_guard(train_program, startup_program):
input = fluid.data(name='input', dtype='float32', shape=[2, 3])
output = paddle.rot90(input, k=-3, axes=[0, 1])
place = fluid.CPUPlace()
if fluid.core.is_compiled_with_cuda():
place = fluid.CUDAPlace(0)
exe = fluid.Executor(place)
exe.run(startup_program)
img = np.array([[1, 2, 3], [4, 5, 6]]).astype(np.float32)
res = exe.run(train_program,
feed={'input': img},
fetch_list=[output])
out_np = np.array(res[0])
out_ref = np.array([[3, 6], [2, 5], [1, 4]]).astype(np.float32)
self.assertTrue(
(out_np == out_ref).all(),
msg='rot90 output is wrong, out =' + str(out_np))
def test_error_api(self):
paddle.enable_static()
## dims error
def run1():
input = fluid.data(name='input', dtype='float32', shape=[2, 3])
output = paddle.rot90(input, k=1, axes=[0])
self.assertRaises(ValueError, run1)
## input dims error
def run2():
input = fluid.data(name='input', dtype='float32', shape=[2])
output = paddle.rot90(input, k=1, axes=[0, 1])
self.assertRaises(ValueError, run2)
def run3():
input = fluid.data(name='input', dtype='float32', shape=[2, 3])
output = paddle.rot90(input, k=1, axes=[0, 0])
self.assertRaises(ValueError, run3)
def run4():
input = fluid.data(name='input', dtype='float32', shape=[2, 3])
output = paddle.rot90(input, k=1, axes=[3, 1])
self.assertRaises(ValueError, run4)
def run5():
input = fluid.data(name='input', dtype='float32', shape=[2, 3])
output = paddle.rot90(input, k=1, axes=[0, 3])
self.assertRaises(ValueError, run5)
def test_dygraph(self):
img = np.array([[1, 2, 3], [4, 5, 6]]).astype(np.float32)
with fluid.dygraph.guard():
inputs = fluid.dygraph.to_variable(img)
ret = paddle.rot90(inputs, k=1, axes=[0, 1])
ret = ret.rot90(1, axes=[0, 1])
ret = paddle.rot90(ret, k=1, axes=[0, 1])
out_ref = np.array([[4, 1], [5, 2], [6, 3]]).astype(np.float32)
self.assertTrue(
(ret.numpy() == out_ref).all(),
msg='rot90 output is wrong, out =' + str(ret.numpy()))
if __name__ == "__main__":
unittest.main()
...@@ -106,6 +106,7 @@ from .manipulation import unsqueeze # noqa: F401 ...@@ -106,6 +106,7 @@ from .manipulation import unsqueeze # noqa: F401
from .manipulation import unsqueeze_ # noqa: F401 from .manipulation import unsqueeze_ # noqa: F401
from .manipulation import unstack # noqa: F401 from .manipulation import unstack # noqa: F401
from .manipulation import flip # noqa: F401 from .manipulation import flip # noqa: F401
from .manipulation import rot90 # noqa: F401
from .manipulation import unbind # noqa: F401 from .manipulation import unbind # noqa: F401
from .manipulation import roll # noqa: F401 from .manipulation import roll # noqa: F401
from .manipulation import chunk # noqa: F401 from .manipulation import chunk # noqa: F401
...@@ -370,6 +371,7 @@ tensor_method_func = [ #noqa ...@@ -370,6 +371,7 @@ tensor_method_func = [ #noqa
'unsqueeze_', 'unsqueeze_',
'unstack', 'unstack',
'flip', 'flip',
'rot90',
'unbind', 'unbind',
'roll', 'roll',
'tile', 'tile',
......
...@@ -495,6 +495,92 @@ def flip(x, axis, name=None): ...@@ -495,6 +495,92 @@ def flip(x, axis, name=None):
return out return out
def rot90(x, k=1, axes=[0, 1], name=None):
"""
Rotate a n-D tensor by 90 degrees in the plane specified by dims axis. Rotation direction is from the first towards the second axis if k > 0, and from the second towards the first for k < 0.
Args:
x (Tensor): The input Tensor(or LoDTensor). The data type of the input Tensor x
should be float32, float64, int32, int64, bool.
k (int): Number of times to rotate
axes (list|tuple): Axis to rotate
name (str, optional): The default value is None. Normally there is no need for user to set this property.
For more information, please refer to :ref:`api_guide_Name` .
Returns:
Tensor: Tensor or LoDTensor calculated by rot90 layer. The data type is same with input x.
Raises:
TypeError: If the data type of ``x`` is not Variable
TypeError: If the dtype of ``x`` is not float16, float32, float64, int32, int64, bool
TypeError: If the data type of ``dims`` is not list, tuple
Examples:
.. code-block:: python
import paddle
import numpy as np
data = paddle.arange(4)
data = paddle.reshape(data, (2, 2))
print(data) ## [[0, 1],[2, 3]]
y = paddle.rot90(data, 1, [0, 1])
print(y) #[[1, 3],[0, 2]]
y= paddle.rot90(data, -1, [0, 1])
print(y) #[[2, 0],[3, 1]]
data2 = paddle.arange(8)
data2 = paddle.reshape(data2, (2,2,2))
print(data2) ###[[[0, 1],[2, 3]],[[4, 5],[6, 7]]]
y = paddle.rot90(data2, 1, [1, 2])
print(y) ### [[[1, 3],[0, 2]],[[5, 7],[4, 6]]]
"""
helper = LayerHelper("rot90", **locals())
check_type(x, 'X', (Variable), 'rot90')
dtype = helper.input_dtype('x')
check_dtype(dtype, 'X',
['float16', 'float32', 'float64', 'int32', 'int64', 'bool'],
'rot90')
check_type(axes, 'axes', (list, tuple), 'rot90')
input_total_dims = len(x.shape)
total_rot_dims = len(axes)
if total_rot_dims != 2:
raise ValueError("expected total rotation axes == 2, but got axes = {}".
format(total_rot_dims))
if input_total_dims < 2:
raise ValueError("expected total dims >= 2, but got total dims = {}".
format(input_total_dims))
if not (axes[0] != axes[1] and abs(axes[0] - axes[1]) != input_total_dims):
raise ValueError(
"expected rotation axes to be different, but got axis0 = {}, and axis1 = {}".
format(axes[0], axes[1]))
if not (axes[0] < input_total_dims and axes[0] >= -input_total_dims):
raise ValueError("Rotation axis0 out of range, axis0 = {}".format(axes[
0]))
if not (axes[1] < input_total_dims and axes[1] >= -input_total_dims):
raise ValueError("Rotation axis1 out of range, axis1 = {}".format(axes[
1]))
## k % 4
k = k % 4 if k >= 0 else 4 - (-k % 4)
if k == 0:
return x
if k == 2:
return flip(flip(x, axes[0]), axes[1])
axes_list = list(range(0, input_total_dims))
(axes_list[axes[0]], axes_list[axes[1]]) = (axes_list[axes[1]],
axes_list[axes[0]])
if k == 1:
return transpose(flip(x, axes[1]), axes_list)
else:
# k == 3
return flip(transpose(x, axes_list), axes[1])
def flatten(x, start_axis=0, stop_axis=-1, name=None): def flatten(x, start_axis=0, stop_axis=-1, name=None):
r""" r"""
**Flatten op** **Flatten op**
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册