未验证 提交 74803f51 编写于 作者: myq406450149's avatar myq406450149 提交者: GitHub

add unbind python api (#24141)

* add unbind pyhon api. test=develp
上级 3e2bc871
...@@ -186,6 +186,7 @@ __all__ = [ ...@@ -186,6 +186,7 @@ __all__ = [
'hard_swish', 'hard_swish',
'gather_tree', 'gather_tree',
'uniform_random', 'uniform_random',
'unbind',
] ]
...@@ -14344,3 +14345,57 @@ def uniform_random(shape, dtype='float32', min=-1.0, max=1.0, seed=0): ...@@ -14344,3 +14345,57 @@ def uniform_random(shape, dtype='float32', min=-1.0, max=1.0, seed=0):
outputs={"Out": out}) outputs={"Out": out})
return helper.append_activation(out) return helper.append_activation(out)
def unbind(input, axis=0):
"""
Removes a tensor dimension, then split the input tensor into multiple sub-Tensors.
Args:
input (Variable): The input variable which is an N-D Tensor, data type being float32, float64, int32 or int64.
axis (int32|int64, optional): A scalar with type ``int32|int64`` shape [1]. The dimension along which to unbind. If :math:`axis < 0`, the
dimension to unbind along is :math:`rank(input) + axis`. Default is 0.
Returns:
list(Variable): The list of segmented Tensor variables.
Example:
.. code-block:: python
import paddle
# input is a variable which shape is [3, 4, 5]
input = paddle.fluid.data(
name="input", shape=[3, 4, 5], dtype="float32")
[x0, x1, x2] = paddle.tensor.unbind(input, axis=0)
# x0.shape [4, 5]
# x1.shape [4, 5]
# x2.shape [4, 5]
[x0, x1, x2, x3] = paddle.tensor.unbind(input, axis=1)
# x0.shape [3, 5]
# x1.shape [3, 5]
# x2.shape [3, 5]
# x3.shape [3, 5]
"""
helper = LayerHelper("unbind", **locals())
check_type(input, 'input', (Variable), 'unbind')
dtype = helper.input_dtype()
check_dtype(dtype, 'unbind', ['float32', 'float64', 'int32', 'int64'],
'unbind')
if not isinstance(axis, (int)):
raise TypeError("The type of 'axis' must be int, but received %s." %
(type(axis)))
if isinstance(axis, np.generic):
axis = np.asscalar(axis)
input_shape = input.shape
axis_ = axis if axis >= 0 else len(input_shape) + axis
num = input_shape[axis_]
outs = [
helper.create_variable_for_type_inference(dtype=helper.input_dtype())
for i in range(num)
]
helper.append_op(
type="unbind",
inputs={"X": input},
outputs={"Out": outs},
attrs={"axis": axis})
return outs
...@@ -18,9 +18,46 @@ import unittest ...@@ -18,9 +18,46 @@ import unittest
import numpy as np import numpy as np
from op_test import OpTest from op_test import OpTest
import paddle.fluid as fluid import paddle.fluid as fluid
import paddle.tensor as tensor
from paddle.fluid import compiler, Program, program_guard, core from paddle.fluid import compiler, Program, program_guard, core
class TestUnbind(unittest.TestCase):
def test_unbind(self):
x_1 = fluid.data(shape=[2, 3], dtype='float32', name='x_1')
[out_0, out_1] = tensor.unbind(input=x_1, axis=0)
input_1 = np.random.random([2, 3]).astype("float32")
axis = fluid.data(shape=[1], dtype='int32', name='axis')
exe = fluid.Executor(place=fluid.CPUPlace())
[res_1, res_2] = exe.run(fluid.default_main_program(),
feed={"x_1": input_1,
"axis": 0},
fetch_list=[out_0, out_1])
assert np.array_equal(res_1, input_1[0, 0:100])
assert np.array_equal(res_2, input_1[1, 0:100])
class TestLayersUnbind(unittest.TestCase):
def test_layers_unbind(self):
x_1 = fluid.data(shape=[2, 3], dtype='float32', name='x_1')
[out_0, out_1] = fluid.layers.unbind(input=x_1, axis=0)
input_1 = np.random.random([2, 3]).astype("float32")
axis = fluid.data(shape=[1], dtype='int32', name='axis')
exe = fluid.Executor(place=fluid.CPUPlace())
[res_1, res_2] = exe.run(fluid.default_main_program(),
feed={"x_1": input_1,
"axis": 0},
fetch_list=[out_0, out_1])
assert np.array_equal(res_1, input_1[0, 0:100])
assert np.array_equal(res_2, input_1[1, 0:100])
class TestUnbindOp(OpTest): class TestUnbindOp(OpTest):
def initParameters(self): def initParameters(self):
pass pass
...@@ -37,7 +74,6 @@ class TestUnbindOp(OpTest): ...@@ -37,7 +74,6 @@ class TestUnbindOp(OpTest):
self.axis = 0 self.axis = 0
self.num = 3 self.num = 3
self.initParameters() self.initParameters()
#x = np.random.random((3, 2, 2)).astype(self.dtype)
x = np.arange(12).reshape(3, 2, 2).astype(self.dtype) x = np.arange(12).reshape(3, 2, 2).astype(self.dtype)
self.out = np.split(x, self.num, self.axis) self.out = np.split(x, self.num, self.axis)
self.outReshape() self.outReshape()
...@@ -118,5 +154,16 @@ class TestUnbindOp4(TestUnbindOp): ...@@ -118,5 +154,16 @@ class TestUnbindOp4(TestUnbindOp):
self.out[1] = self.out[1].reshape((3, 2)) self.out[1] = self.out[1].reshape((3, 2))
class TestUnbindAxisError(unittest.TestCase):
def test_errors(self):
with program_guard(Program(), Program()):
x = fluid.data(shape=[2, 3], dtype='float32', name='x')
def test_table_Variable():
tensor.unbind(input=x, axis=2.0)
self.assertRaises(TypeError, test_table_Variable)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()
...@@ -151,6 +151,7 @@ from .math import erf #DEFINE_ALIAS ...@@ -151,6 +151,7 @@ from .math import erf #DEFINE_ALIAS
from .math import addcmul #DEFINE_ALIAS from .math import addcmul #DEFINE_ALIAS
from .math import addmm #DEFINE_ALIAS from .math import addmm #DEFINE_ALIAS
from .math import clamp #DEFINE_ALIAS from .math import clamp #DEFINE_ALIAS
from .manipulation import unbind #DEFINE_ALIAS
from .math import trace #DEFINE_ALIAS from .math import trace #DEFINE_ALIAS
from .math import kron #DEFINE_ALIAS from .math import kron #DEFINE_ALIAS
# from .random import gaussin #DEFINE_ALIAS # from .random import gaussin #DEFINE_ALIAS
......
...@@ -20,6 +20,7 @@ from ..fluid.framework import Variable, OpProtoHolder, in_dygraph_mode, convert_ ...@@ -20,6 +20,7 @@ from ..fluid.framework import Variable, OpProtoHolder, in_dygraph_mode, convert_
from ..fluid.data_feeder import convert_dtype, check_variable_and_dtype, check_type, check_dtype from ..fluid.data_feeder import convert_dtype, check_variable_and_dtype, check_type, check_dtype
from ..fluid.layers.tensor import fill_constant from ..fluid.layers.tensor import fill_constant
from ..fluid.layers import utils from ..fluid.layers import utils
import numpy as np
# TODO: define functions to manipulate a tensor # TODO: define functions to manipulate a tensor
from ..fluid.layers import cast #DEFINE_ALIAS from ..fluid.layers import cast #DEFINE_ALIAS
from ..fluid.layers import concat #DEFINE_ALIAS from ..fluid.layers import concat #DEFINE_ALIAS
...@@ -60,7 +61,7 @@ __all__ = [ ...@@ -60,7 +61,7 @@ __all__ = [
'unsqueeze', 'unsqueeze',
'unstack', 'unstack',
'flip', 'flip',
# 'unbind', 'unbind',
'roll' 'roll'
] ]
...@@ -657,3 +658,57 @@ def gather(input, index, overwrite=True): ...@@ -657,3 +658,57 @@ def gather(input, index, overwrite=True):
outputs={"Out": out}, outputs={"Out": out},
attrs={'overwrite': overwrite}) attrs={'overwrite': overwrite})
return out return out
def unbind(input, axis=0):
"""
Removes a tensor dimension, then split the input tensor into multiple sub-Tensors.
Args:
input (Variable): The input variable which is an N-D Tensor, data type being float32, float64, int32 or int64.
axis (int32|int64, optional): A scalar with type ``int32|int64`` shape [1]. The dimension along which to unbind. If :math:`axis < 0`, the
dimension to unbind along is :math:`rank(input) + axis`. Default is 0.
Returns:
list(Variable): The list of segmented Tensor variables.
Example:
.. code-block:: python
import paddle
# input is a variable which shape is [3, 4, 5]
input = paddle.fluid.data(
name="input", shape=[3, 4, 5], dtype="float32")
[x0, x1, x2] = paddle.tensor.unbind(input, axis=0)
# x0.shape [4, 5]
# x1.shape [4, 5]
# x2.shape [4, 5]
[x0, x1, x2, x3] = paddle.tensor.unbind(input, axis=1)
# x0.shape [3, 5]
# x1.shape [3, 5]
# x2.shape [3, 5]
# x3.shape [3, 5]
"""
helper = LayerHelper("unbind", **locals())
check_type(input, 'input', (Variable), 'unbind')
dtype = helper.input_dtype()
check_dtype(dtype, 'unbind', ['float32', 'float64', 'int32', 'int64'],
'unbind')
if not isinstance(axis, (int)):
raise TypeError("The type of 'axis' must be int, but received %s." %
(type(axis)))
if isinstance(axis, np.generic):
axis = np.asscalar(axis)
input_shape = input.shape
axis_ = axis if axis >= 0 else len(input_shape) + axis
num = input_shape[axis_]
outs = [
helper.create_variable_for_type_inference(dtype=helper.input_dtype())
for i in range(num)
]
helper.append_op(
type="unbind",
inputs={"X": input},
outputs={"Out": outs},
attrs={"axis": axis})
return outs
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册