未验证 提交 5a2d15a1 编写于 作者: Z zhupengyang 提交者: GitHub

arange API: start default is 0, end default is None (#25452)

上级 630f23ce
...@@ -1322,25 +1322,35 @@ def isfinite(x): ...@@ -1322,25 +1322,35 @@ def isfinite(x):
return out return out
def range(start, end, step, dtype): def range(start, end, step, dtype, name=None):
""" """
Return evenly spaced values within a given interval. Return evenly spaced values within a given interval.
Values are generated within the half-open interval [start, stop) (in other words, Values are generated within the half-open interval [start, stop) (in other
the interval including start but excluding stop). words, the interval including start but excluding stop).
If dtype is float32 or float64, we advise adding a small epsilon to end to
avoid floating point rounding errors when comparing against end.
Parameters: Parameters:
start(float32 | float64 | int32 | int64 | Variable): Start of interval. The interval includes this value. start(float|int|Variable): Start of interval. The interval includes
when start is Variable, it is a 1-D Tensor with shape [1]. this value. If start is Variable, it is a 1-D Tensor with shape [1],
end(float32 | float64 | int32 | int64 | Variable): End of interval. The interval does not include this and it's data type should be one of int32, int64, float32, float64.
value, except in some cases where step is not an integer end(float|int|Variable): End of interval. The interval does not include
and floating point round-off affects the length of out. When end is Variable, this value. When end is Variable, it is a 1-D Tensor with shape [1],
it is a 1-D Tensor with shape [1]. and it's data type should be int32, int64, float32, float64.
step(float32 | float64 | int32 | int64 | Variable): Spacing between values. For any output out, this is the step(float|int|Variable): Spacing between values. For any out, this is
distance between two adjacent values, out[i+1] - out[i]. the istance between two adjacent values, out[i+1] - out[i].
dtype(str|core.VarDesc.VarType): the data type of the output tensor, can be float32, float64, int32, int64. When end is Variable, it is a 1-D Tensor with shape [1], and it's
data type should be one of int32, int64, float32, float64.
Returns: a 1-D Tensor which is evenly spaced values within a given interval. Its data type is set by dtype. dtype(str|np.dtype|core.VarDesc.VarType): The data type of the output
tensor, can be float32, float64, int32, int64.
name(str, optional): Normally there is no need for user to set this property.
For more information, please refer to :ref:`api_guide_Name` .
Default is None.
Returns: a 1-D Tensor which is evenly spaced values within a given interval.
Its data type is set by dtype.
Return type: Variable Return type: Variable
...@@ -1348,44 +1358,47 @@ def range(start, end, step, dtype): ...@@ -1348,44 +1358,47 @@ def range(start, end, step, dtype):
.. code-block:: python .. code-block:: python
import paddle.fluid as fluid import paddle.fluid as fluid
data = fluid.layers.range(0, 10, 2, 'int32')
""" out1 = fluid.layers.range(0, 10, 2, 'int32')
check_type(start, 'start', (float, int, Variable), 'range') # [0, 2, 4, 6, 8]
check_type(end, 'end', (float, int, Variable), 'range')
check_type(step, 'step', (float, int, Variable), 'range')
helper = LayerHelper("range", **locals())
check_dtype(dtype, 'create data type', start_var = fluid.layers.fill_constant([1], 'int64', 3)
['float32', 'float64', 'int32', 'int64'], 'range') out2 = fluid.layers.range(start_var, 7, 1, 'int64')
# [3, 4, 5, 6]
"""
if not isinstance(dtype, core.VarDesc.VarType):
dtype = convert_np_dtype_to_dtype_(dtype)
dtype = convert_dtype(dtype)
if not isinstance(start, Variable): if not isinstance(start, Variable):
start = fill_constant([1], dtype, start) start = fill_constant([1], dtype, start)
elif convert_dtype(start.dtype) != dtype: elif start.dtype != dtype:
# make sure that start, end, step has the same dtype as start = cast(start, dtype)
# `dtype`
start = cast(x=start, dtype=dtype)
if not isinstance(end, Variable): if not isinstance(end, Variable):
end = fill_constant([1], dtype, end) end = fill_constant([1], dtype, end)
elif convert_dtype(end.dtype) != dtype: elif end.dtype != dtype:
end = cast(x=end, dtype=dtype) end = cast(end, dtype)
if not isinstance(step, Variable): if not isinstance(step, Variable):
step = fill_constant([1], dtype, step) step = fill_constant([1], dtype, step)
elif convert_dtype(step.dtype) != dtype: elif step.dtype != dtype:
step = cast(x=step, dtype=dtype) step = cast(step, dtype)
out = helper.create_variable_for_type_inference(dtype=start.dtype) if in_dygraph_mode():
return core.ops.range(start, end, step)
check_dtype(dtype, 'dtype', ['float32', 'float64', 'int32', 'int64'],
'range/arange')
helper = LayerHelper('range', **locals())
out = helper.create_variable_for_type_inference(dtype)
helper.append_op( helper.append_op(
type='range', type='range',
inputs={'Start': start, inputs={'Start': start,
'End': end, 'End': end,
'Step': step}, 'Step': step},
outputs={'Out': [out]}) outputs={'Out': out})
out.stop_gradient = True out.stop_gradient = True
return out return out
......
...@@ -15,7 +15,8 @@ ...@@ -15,7 +15,8 @@
from __future__ import print_function from __future__ import print_function
import paddle import paddle
import paddle.fluid as fluid from paddle.fluid import core
from paddle import program_guard, Program
import unittest import unittest
import numpy as np import numpy as np
from op_test import OpTest from op_test import OpTest
...@@ -44,47 +45,67 @@ class TestArangeOp(OpTest): ...@@ -44,47 +45,67 @@ class TestArangeOp(OpTest):
self.check_output() self.check_output()
class TestFloatArangeOpCase0(TestArangeOp): class TestFloatArangeOp(TestArangeOp):
def init_config(self): def init_config(self):
self.dtype = np.float32 self.dtype = np.float32
self.case = (0, 5, 1) self.case = (0, 5, 1)
class TestInt32ArangeOpCase0(TestArangeOp): class TestInt32ArangeOp(TestArangeOp):
def init_config(self): def init_config(self):
self.dtype = np.int32 self.dtype = np.int32
self.case = (0, 5, 2) self.case = (0, 5, 2)
class TestInt32ArangeOpCase1(TestArangeOp): class TestFloat64ArangeOp(TestArangeOp):
def init_config(self): def init_config(self):
self.dtype = np.int32 self.dtype = np.float64
self.case = (10, 1, -2) self.case = (10, 1, -2)
class TestInt32ArangeOpCase2(TestArangeOp): class TestInt64ArangeOp(TestArangeOp):
def init_config(self): def init_config(self):
self.dtype = np.int32 self.dtype = np.int64
self.case = (-1, -10, -2) self.case = (-1, -10, -2)
class TestArangeOpError(unittest.TestCase):
def test_errors(self):
with program_guard(Program(), Program()):
self.assertRaises(TypeError, paddle.arange, 10, dtype='int8')
class TestArangeAPI(unittest.TestCase): class TestArangeAPI(unittest.TestCase):
def test_out(self): def test_out(self):
with fluid.program_guard(fluid.Program()): with program_guard(Program(), Program()):
data = paddle.arange(0, 5, 1) x1 = paddle.arange(0, 5, 1, 'float32')
place = fluid.CPUPlace()
exe = fluid.Executor(place) place = paddle.CUDAPlace(0) if core.is_compiled_with_cuda(
result, = exe.run(fetch_list=[data]) ) else paddle.CPUPlace()
expected_data = np.arange(0, 5, 1).astype(np.float32) exe = paddle.Executor(place)
self.assertEqual((result == expected_data).all(), True) out = exe.run(fetch_list=[x1])
with fluid.program_guard(fluid.Program()): expected_data = np.arange(0, 5, 1).astype(np.float32)
data = paddle.arange(0.0, 5.0, 1.0, 'int32') self.assertEqual((out == expected_data).all(), True)
place = fluid.CPUPlace()
exe = fluid.Executor(place)
result, = exe.run(fetch_list=[data]) class TestArangeImperative(unittest.TestCase):
expected_data = np.arange(0, 5, 1).astype(np.int32) def test_out(self):
self.assertEqual((result == expected_data).all(), True) place = paddle.CUDAPlace(0) if core.is_compiled_with_cuda(
) else paddle.CPUPlace()
with paddle.imperative.guard(place):
x1 = paddle.arange(0, 5, 1)
x2 = paddle.tensor.arange(5)
x3 = paddle.tensor.creation.arange(5)
start = paddle.imperative.to_variable(np.array([0], 'float32'))
end = paddle.imperative.to_variable(np.array([5], 'float32'))
step = paddle.imperative.to_variable(np.array([1], 'float32'))
x4 = paddle.arange(start, end, step, 'int64')
expected_data = np.arange(0, 5, 1).astype(np.int64)
for i in [x1, x2, x3, x4]:
self.assertEqual((i.numpy() == expected_data).all(), True)
if __name__ == "__main__": if __name__ == "__main__":
......
...@@ -21,6 +21,7 @@ from ..fluid.data_feeder import check_variable_and_dtype, check_type, check_dtyp ...@@ -21,6 +21,7 @@ from ..fluid.data_feeder import check_variable_and_dtype, check_type, check_dtyp
from ..fluid.framework import convert_np_dtype_to_dtype_, in_dygraph_mode, _varbase_creator, device_guard, OpProtoHolder from ..fluid.framework import convert_np_dtype_to_dtype_, in_dygraph_mode, _varbase_creator, device_guard, OpProtoHolder
from ..fluid.layers import fill_constant from ..fluid.layers import fill_constant
from paddle.common_ops_import import * from paddle.common_ops_import import *
import paddle
# TODO: define functions to get create a tensor # TODO: define functions to get create a tensor
from ..fluid.layers import crop_tensor #DEFINE_ALIAS from ..fluid.layers import crop_tensor #DEFINE_ALIAS
...@@ -413,76 +414,80 @@ def full(shape, fill_value, dtype=None, name=None): ...@@ -413,76 +414,80 @@ def full(shape, fill_value, dtype=None, name=None):
return fill_constant(shape=shape, dtype=dtype, value=fill_value, name=name) return fill_constant(shape=shape, dtype=dtype, value=fill_value, name=name)
def arange(start, end, step=1, dtype=None, name=None): def arange(start=0, end=None, step=1, dtype=None, name=None):
""" """
:alias_main: paddle.arange :alias_main: paddle.arange
:alias: paddle.arange,paddle.tensor.arange,paddle.tensor.creation.arange :alias: paddle.arange,paddle.tensor.arange,paddle.tensor.creation.arange
Return evenly spaced values within a given interval. Return evenly spaced values within a given interval.
Values are generated within the half-open interval [start, stop) (in other words, Values are generated into the half-open interval [start, stop) with the step.
the interval including start but excluding stop). (the interval including start but excluding stop).
If dtype is float32 or float64, we advise adding a small epsilon to end to
avoid floating point rounding errors when comparing against end.
Parameters: Parameters:
start(float32 | float64 | int32 | int64 | Variable): Start of interval. The interval includes this value. start(float|int|Variable): Start of interval. The interval includes
when start is Variable, it is a 1-D Tensor with shape [1]. this value. If end is None, the half-open interval is [0, start).
end(float32 | float64 | int32 | int64 | Variable): End of interval. The interval does not include this If start is Variable, it is a 1-D Tensor with shape [1], and it's
value, except in some cases where step is not an integer data type should be one of int32, int64, float32, float64. Default
and floating point round-off affects the length of out. When end is Variable, is 0.
it is a 1-D Tensor with shape [1]. end(float|int|Variable, optional): End of interval. The interval does
step(float32 | float64 | int32 | int64 | Variable): Spacing between values. For any output out, this is the not include this value. When end is Variable, it is a 1-D Tensor
distance between two adjacent values, out[i+1] - out[i]. with shape [1], and it's data type should be one of int32, int64,
dtype(str|core.VarDesc.VarType): the data type of the output tensor, can be float32, float64, int32, int64. float32, float64. If end is None, the half-open interval is [0, start).
Default is None.
Returns: a 1-D Tensor which is evenly spaced values within a given interval. Its data type is set by dtype. step(float|int|Variable, optional): Spacing between values. For any
out, this is the istance between two adjacent values, out[i+1] - out[i].
When end is Variable, it is a 1-D Tensor with shape [1], and it's
data type should be one of int32, int64, float32, float64. Default is 1.
dtype(str|np.dtype|core.VarDesc.VarType, optional): The data type of
the output tensor, can be float32, float64, int32, int64. If dtype
is `None` , the data type of out tensor is `int64` . Defaule is None
name(str, optional): Normally there is no need for user to set this property.
For more information, please refer to :ref:`api_guide_Name` .
Default is None.
Returns: a 1-D Tensor which is evenly spaced values within a given interval.
Its data type is set by dtype.
Return type: Variable Return type: Variable
Raises:
TypeError: If dtype is not float32, float64, int32 or int64.
examples: examples:
.. code-block:: python .. code-block:: python
import paddle import paddle
# expected out put: [0, 2, 4, 6, 8] import numpy as np
data = paddle.arange(0, 10, 2, 'int32')
#dygraph mode
import paddle
import paddle.fluid as fluid
with fluid.dygraph.guard():
x = paddle.arange(0, 6, 2)
# x: [0, 2, 4]
# x dtype: float32
"""
helper = LayerHelper("range", **locals())
if dtype is None:
dtype = 'float32'
check_dtype(dtype, 'create data type', paddle.enable_imperative()
['float32', 'float64', 'int32', 'int64'], 'range')
dtype = convert_dtype(dtype) out1 = paddle.arange(5)
if not isinstance(start, Variable): # [0, 1, 2, 3, 4]
start = fill_constant([1], dtype, start)
if not isinstance(end, Variable): out2 = paddle.arange(3, 9, 2.0)
end = fill_constant([1], dtype, end) # [3, 5, 7]
if not isinstance(step, Variable): # use 4.999 instead of 5.0 to avoid floating point rounding errors
step = fill_constant([1], dtype, step) out3 = paddle.arange(4.999, dtype='float32')
# [0., 1., 2., 3., 4.]
out = helper.create_variable_for_type_inference(dtype=start.dtype) start_var = paddle.imperative.to_variable(np.array([3]))
out4 = paddle.arange(start_var, 7)
# [3, 4, 5, 6]
"""
if dtype is None:
dtype = 'int64'
if end is None:
end = start
start = 0
helper.append_op( return paddle.fluid.layers.range(start, end, step, dtype, name)
type='range',
inputs={'Start': start,
'End': end,
'Step': step},
outputs={'Out': [out]})
out.stop_gradient = True
return out
def _tril_triu_op(helper): def _tril_triu_op(helper):
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册