Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
机器未来
Paddle
提交
595a7197
P
Paddle
项目概览
机器未来
/
Paddle
与 Fork 源项目一致
Fork自
PaddlePaddle / Paddle
通知
1
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
1
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
P
Paddle
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
1
Issue
1
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
未验证
提交
595a7197
编写于
7月 30, 2020
作者:
W
wawltor
提交者:
GitHub
7月 30, 2020
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Update the api for the compare_ops
Update the code for the compare_ops, update the api and doc
上级
fc6fed32
变更
11
隐藏空白更改
内联
并排
Showing
11 changed file
with
358 addition
and
201 deletion
+358
-201
cmake/operators.cmake
cmake/operators.cmake
+1
-1
paddle/fluid/operators/controlflow/CMakeLists.txt
paddle/fluid/operators/controlflow/CMakeLists.txt
+1
-1
paddle/fluid/operators/controlflow/compare_all_op.cc
paddle/fluid/operators/controlflow/compare_all_op.cc
+34
-33
paddle/fluid/operators/controlflow/compare_all_op.cu
paddle/fluid/operators/controlflow/compare_all_op.cu
+34
-23
paddle/fluid/operators/controlflow/compare_all_op.h
paddle/fluid/operators/controlflow/compare_all_op.h
+0
-0
python/paddle/__init__.py
python/paddle/__init__.py
+1
-1
python/paddle/fluid/layers/control_flow.py
python/paddle/fluid/layers/control_flow.py
+18
-6
python/paddle/fluid/tests/unittests/test_compare_op.py
python/paddle/fluid/tests/unittests/test_compare_op.py
+46
-2
python/paddle/fluid/tests/unittests/test_compare_reduce_op.py
...on/paddle/fluid/tests/unittests/test_compare_reduce_op.py
+13
-57
python/paddle/tensor/__init__.py
python/paddle/tensor/__init__.py
+1
-1
python/paddle/tensor/logic.py
python/paddle/tensor/logic.py
+209
-76
未找到文件。
cmake/operators.cmake
浏览文件 @
595a7197
...
...
@@ -114,7 +114,7 @@ function(op_library TARGET)
endif
()
# Define operators that don't need pybind here.
foreach
(
manual_pybind_op
"compare_
reduce
_op"
"compare_op"
"logical_op"
"nccl_op"
foreach
(
manual_pybind_op
"compare_
all
_op"
"compare_op"
"logical_op"
"nccl_op"
"tensor_array_read_write_op"
"tensorrt_engine_op"
"conv_fusion_op"
"fusion_transpose_flatten_concat_op"
"fusion_conv_inception_op"
"sync_batch_norm_op"
"dgc_op"
"fused_fc_elementwise_layernorm_op"
...
...
paddle/fluid/operators/controlflow/CMakeLists.txt
浏览文件 @
595a7197
...
...
@@ -9,4 +9,4 @@ cc_test(conditional_block_op_test SRCS conditional_block_op_test.cc DEPS conditi
target_link_libraries
(
conditional_block_infer_op conditional_block_op
)
file
(
APPEND
${
pybind_file
}
"USE_OP(less_than);
\n
USE_OP(equal_
reduce
);
\n
USE_OP(logical_and);
\n
USE_NO_KERNEL_OP(read_from_array);
\n
"
)
file
(
APPEND
${
pybind_file
}
"USE_OP(less_than);
\n
USE_OP(equal_
all
);
\n
USE_OP(logical_and);
\n
USE_NO_KERNEL_OP(read_from_array);
\n
"
)
paddle/fluid/operators/controlflow/compare_
reduce
_op.cc
→
paddle/fluid/operators/controlflow/compare_
all
_op.cc
浏览文件 @
595a7197
...
...
@@ -12,7 +12,7 @@ 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. */
#include "paddle/fluid/operators/controlflow/compare_
reduce
_op.h"
#include "paddle/fluid/operators/controlflow/compare_
all
_op.h"
#include <string>
#include "paddle/fluid/framework/op_registry.h"
...
...
@@ -30,38 +30,44 @@ class CompareReduceOpKernel
auto
*
x
=
context
.
Input
<
Tensor
>
(
"X"
);
auto
*
y
=
context
.
Input
<
Tensor
>
(
"Y"
);
auto
*
z
=
context
.
Output
<
Tensor
>
(
"Out"
);
int
axis
=
context
.
Attr
<
int
>
(
"axis"
)
;
bool
shape_same
=
true
;
Tensor
tmp
;
framework
::
DDim
x_dims
=
x
->
dims
();
framework
::
DDim
y_dims
=
y
->
dims
();
int
max_dim
=
std
::
max
(
x_dims
.
size
(),
y_dims
.
size
());
axis
=
(
axis
==
-
1
?
std
::
abs
(
x_dims
.
size
()
-
y_dims
.
size
())
:
axis
);
std
::
vector
<
int
>
x_dims_array
(
max_dim
);
std
::
vector
<
int
>
y_dims_array
(
max_dim
);
std
::
vector
<
int
>
tmp_dims_array
(
max_dim
);
GetBroadcastDimsArrays
(
x_dims
,
y_dims
,
x_dims_array
.
data
(),
y_dims_array
.
data
(),
tmp_dims_array
.
data
(),
max_dim
,
axis
);
tmp
.
mutable_data
<
bool
>
(
framework
::
make_ddim
(
tmp_dims_array
),
context
.
GetPlace
());
if
(
x
->
numel
()
==
1
&&
y
->
numel
()
==
1
)
{
bool
*
z_data
=
tmp
.
mutable_data
<
bool
>
(
context
.
GetPlace
());
z_data
[
0
]
=
Functor
()(
x
->
data
<
T
>
()[
0
],
y
->
data
<
T
>
()[
0
]);
// judge the two inputs shape is same, if not same, just return false
if
(
x_dims
.
size
()
!=
y_dims
.
size
())
{
shape_same
=
false
;
}
else
{
ElementwiseComputeEx
<
Functor
,
platform
::
CPUDeviceContext
,
T
,
bool
>
(
context
,
x
,
y
,
axis
,
Functor
(),
&
tmp
);
for
(
auto
i
=
0
;
i
<
x_dims
.
size
();
i
++
)
{
if
(
x_dims
[
i
]
!=
y_dims
[
i
])
{
shape_same
=
false
;
break
;
}
}
}
// Reduce by 'logical and' operator
z
->
mutable_data
<
bool
>
(
context
.
GetPlace
());
auto
ipt
=
framework
::
EigenVector
<
bool
>::
Flatten
(
tmp
);
auto
out
=
framework
::
EigenScalar
<
bool
>::
From
(
*
z
);
auto
&
place
=
*
context
.
template
device_context
<
platform
::
CPUDeviceContext
>()
.
eigen_device
();
auto
reduce_dim
=
Eigen
::
array
<
int
,
1
>
({{
0
}});
out
.
device
(
place
)
=
ipt
.
all
(
reduce_dim
);
bool
*
z_data
=
z
->
mutable_data
<
bool
>
(
context
.
GetPlace
());
if
(
!
shape_same
)
{
z_data
[
0
]
=
false
;
}
else
{
tmp
.
mutable_data
<
bool
>
(
x_dims
,
context
.
GetPlace
());
if
(
x
->
numel
()
==
1
&&
y
->
numel
()
==
1
)
{
bool
*
z_data
=
tmp
.
mutable_data
<
bool
>
(
context
.
GetPlace
());
z_data
[
0
]
=
Functor
()(
x
->
data
<
T
>
()[
0
],
y
->
data
<
T
>
()[
0
]);
}
else
{
ElementwiseComputeEx
<
Functor
,
platform
::
CPUDeviceContext
,
T
,
bool
>
(
context
,
x
,
y
,
0
,
Functor
(),
&
tmp
);
}
auto
ipt
=
framework
::
EigenVector
<
bool
>::
Flatten
(
tmp
);
auto
out
=
framework
::
EigenScalar
<
bool
>::
From
(
*
z
);
auto
&
place
=
*
context
.
template
device_context
<
platform
::
CPUDeviceContext
>()
.
eigen_device
();
auto
reduce_dim
=
Eigen
::
array
<
int
,
1
>
({{
0
}});
out
.
device
(
place
)
=
ipt
.
all
(
reduce_dim
);
}
}
};
...
...
@@ -74,11 +80,6 @@ class CompareReduceOpProtoMaker : public framework::OpProtoAndCheckerMaker {
comment
.
type
));
AddInput
(
"Y"
,
string
::
Sprintf
(
"the right hand operand of %s operator"
,
comment
.
type
));
AddAttr
<
int
>
(
"axis"
,
"The start dimension index for broadcasting Y onto X. [default -1]"
)
.
SetDefault
(
-
1
)
.
EqualGreaterThan
(
-
1
);
AddOutput
(
"Out"
,
string
::
Sprintf
(
"tensor with a bool element. If all "
"element %s, the Out tensor is [True], else [False]"
,
...
...
@@ -144,7 +145,7 @@ class CompareReduceOp : public framework::OperatorWithKernel {
::paddle::platform::CPUDeviceContext, functor<float>>, \
::paddle::operators::CompareReduceOpKernel< \
::paddle::platform::CPUDeviceContext, functor<double>>);
REGISTER_COMPARE_REDUCE_OP
(
equal_
reduce
,
"X == Y"
);
REGISTER_COMPARE_REDUCE_OP
(
equal_
all
,
"X == Y"
);
REGISTER_COMPARE_REDUCE_CPU_KERNEL
(
equal_
reduce
,
REGISTER_COMPARE_REDUCE_CPU_KERNEL
(
equal_
all
,
paddle
::
operators
::
EqualReduceFunctor
);
paddle/fluid/operators/controlflow/compare_
reduce
_op.cu
→
paddle/fluid/operators/controlflow/compare_
all
_op.cu
浏览文件 @
595a7197
...
...
@@ -12,7 +12,8 @@ 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. */
#include "paddle/fluid/operators/controlflow/compare_reduce_op.h"
#include <thrust/fill.h>
#include "paddle/fluid/operators/controlflow/compare_all_op.h"
#include "paddle/fluid/operators/reduce_ops/cub_reduce.h"
namespace
paddle
{
namespace
operators
{
...
...
@@ -43,31 +44,41 @@ class CompareReduceOpKernel
auto
*
x
=
context
.
Input
<
Tensor
>
(
"X"
);
auto
*
y
=
context
.
Input
<
Tensor
>
(
"Y"
);
auto
*
z
=
context
.
Output
<
Tensor
>
(
"Out"
);
int
axis
=
context
.
Attr
<
int
>
(
"axis"
)
;
bool
shape_same
=
true
;
Tensor
tmp
;
framework
::
DDim
x_dims
=
x
->
dims
();
framework
::
DDim
y_dims
=
y
->
dims
();
int
max_dim
=
std
::
max
(
x_dims
.
size
(),
y_dims
.
size
());
axis
=
(
axis
==
-
1
?
std
::
abs
(
x_dims
.
size
()
-
y_dims
.
size
())
:
axis
);
std
::
vector
<
int
>
x_dims_array
(
max_dim
);
std
::
vector
<
int
>
y_dims_array
(
max_dim
);
std
::
vector
<
int
>
tmp_dims_array
(
max_dim
);
GetBroadcastDimsArrays
(
x_dims
,
y_dims
,
x_dims_array
.
data
(),
y_dims_array
.
data
(),
tmp_dims_array
.
data
(),
max_dim
,
axis
);
tmp
.
mutable_data
<
bool
>
(
framework
::
make_ddim
(
tmp_dims_array
),
context
.
GetPlace
());
ElementwiseComputeEx
<
Functor
,
DeviceContext
,
T
,
bool
>
(
context
,
x
,
y
,
axis
,
Functor
(),
&
tmp
);
// Reduce by 'bitwise and' operator
std
::
vector
<
int
>
reduce_dims
;
reduce_dims
.
resize
(
tmp
.
dims
().
size
());
for
(
int
i
=
0
;
i
<
reduce_dims
.
size
();
++
i
)
reduce_dims
[
i
]
=
i
;
auto
stream
=
context
.
cuda_device_context
().
stream
();
TensorReduce
<
bool
,
bool
,
BitwiseAdd
,
IdentityFunctor
<
bool
>>
(
tmp
,
z
,
reduce_dims
,
true
,
BitwiseAdd
(),
IdentityFunctor
<
bool
>
(),
stream
);
if
(
x_dims
.
size
()
!=
y_dims
.
size
())
{
shape_same
=
false
;
}
else
{
for
(
auto
i
=
0
;
i
<
x_dims
.
size
();
i
++
)
{
if
(
x_dims
[
i
]
!=
y_dims
[
i
])
{
shape_same
=
false
;
break
;
}
}
}
bool
*
z_data
=
z
->
mutable_data
<
bool
>
(
context
.
GetPlace
());
if
(
!
shape_same
)
{
thrust
::
device_ptr
<
bool
>
z_dev_ptr
(
z_data
);
thrust
::
fill
(
z_dev_ptr
,
z_dev_ptr
+
1
,
false
);
return
;
}
else
{
tmp
.
mutable_data
<
bool
>
(
x_dims
,
context
.
GetPlace
());
ElementwiseComputeEx
<
Functor
,
DeviceContext
,
T
,
bool
>
(
context
,
x
,
y
,
0
,
Functor
(),
&
tmp
);
// Reduce by 'bitwise and' operator
std
::
vector
<
int
>
reduce_dims
;
reduce_dims
.
resize
(
tmp
.
dims
().
size
());
for
(
int
i
=
0
;
i
<
reduce_dims
.
size
();
++
i
)
reduce_dims
[
i
]
=
i
;
auto
stream
=
context
.
cuda_device_context
().
stream
();
TensorReduce
<
bool
,
bool
,
BitwiseAdd
,
IdentityFunctor
<
bool
>>
(
tmp
,
z
,
reduce_dims
,
true
,
BitwiseAdd
(),
IdentityFunctor
<
bool
>
(),
stream
);
}
}
};
...
...
@@ -84,5 +95,5 @@ class CompareReduceOpKernel
paddle::platform::CUDADeviceContext, functor<float>>, \
paddle::operators::CompareReduceOpKernel< \
paddle::platform::CUDADeviceContext, functor<double>>);
REGISTER_COMPARE_REDUCE_CUDA_KERNEL
(
equal_
reduce
,
REGISTER_COMPARE_REDUCE_CUDA_KERNEL
(
equal_
all
,
paddle
::
operators
::
EqualReduceFunctor
);
paddle/fluid/operators/controlflow/compare_
reduce
_op.h
→
paddle/fluid/operators/controlflow/compare_
all
_op.h
浏览文件 @
595a7197
文件已移动
python/paddle/__init__.py
浏览文件 @
595a7197
...
...
@@ -98,7 +98,7 @@ from .tensor.logic import not_equal #DEFINE_ALIAS
from
.tensor.logic
import
reduce_all
#DEFINE_ALIAS
from
.tensor.logic
import
reduce_any
#DEFINE_ALIAS
from
.tensor.logic
import
allclose
#DEFINE_ALIAS
from
.tensor.logic
import
e
lementwise_equa
l
#DEFINE_ALIAS
from
.tensor.logic
import
e
qual_al
l
#DEFINE_ALIAS
# from .tensor.logic import isnan #DEFINE_ALIAS
from
.tensor.manipulation
import
cast
#DEFINE_ALIAS
from
.tensor.manipulation
import
concat
#DEFINE_ALIAS
...
...
python/paddle/fluid/layers/control_flow.py
浏览文件 @
595a7197
...
...
@@ -1580,7 +1580,7 @@ def create_array(dtype):
@
templatedoc
()
def
less_than
(
x
,
y
,
force_cpu
=
None
,
cond
=
None
):
def
less_than
(
x
,
y
,
force_cpu
=
None
,
cond
=
None
,
name
=
None
):
"""
:alias_main: paddle.less_than
:alias: paddle.less_than,paddle.tensor.less_than,paddle.tensor.logic.less_than
...
...
@@ -1595,6 +1595,8 @@ def less_than(x, y, force_cpu=None, cond=None):
cond(Variable, optional): Optional output which can be any created Variable
that meets the requirements to store the result of *less_than*.
if cond is None, a new Varibale will be created to store the result.
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:
${out_comment}.
...
...
@@ -1649,7 +1651,7 @@ def less_than(x, y, force_cpu=None, cond=None):
@
templatedoc
()
def
less_equal
(
x
,
y
,
cond
=
None
):
def
less_equal
(
x
,
y
,
cond
=
None
,
name
=
None
):
"""
:alias_main: paddle.less_equal
:alias: paddle.less_equal,paddle.tensor.less_equal,paddle.tensor.logic.less_equal
...
...
@@ -1662,6 +1664,8 @@ def less_equal(x, y, cond=None):
y(Variable): Second input to compare which is N-D tensor. The input data type should be float32, float64, int32, int64.
cond(Variable, optional): Optional output which can be any created Variable that meets the requirements to store the result of *less_equal*.
if cond is None, a new Varibale will be created to store the result.
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:
Variable, the output data type is bool: The tensor variable storing the output, the output shape is same as input :attr:`x`.
...
...
@@ -1701,7 +1705,7 @@ def less_equal(x, y, cond=None):
@
templatedoc
()
def
greater_than
(
x
,
y
,
cond
=
None
):
def
greater_than
(
x
,
y
,
cond
=
None
,
name
=
None
):
"""
:alias_main: paddle.greater_than
:alias: paddle.greater_than,paddle.tensor.greater_than,paddle.tensor.logic.greater_than
...
...
@@ -1714,6 +1718,8 @@ def greater_than(x, y, cond=None):
y(Variable): Second input to compare which is N-D tensor. The input data type should be float32, float64, int32, int64.
cond(Variable, optional): Optional output which can be any created Variable that meets the requirements to store the result of *greater_than*.
if cond is None, a new Varibale will be created to store the result.
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:
Variable, the output data type is bool: The tensor variable storing the output, the output shape is same as input :attr:`x` .
...
...
@@ -1752,7 +1758,7 @@ def greater_than(x, y, cond=None):
@
templatedoc
()
def
greater_equal
(
x
,
y
,
cond
=
None
):
def
greater_equal
(
x
,
y
,
cond
=
None
,
name
=
None
):
"""
:alias_main: paddle.greater_equal
:alias: paddle.greater_equal,paddle.tensor.greater_equal,paddle.tensor.logic.greater_equal
...
...
@@ -1765,6 +1771,8 @@ def greater_equal(x, y, cond=None):
y(Variable): Second input to compare which is N-D tensor. The input data type should be float32, float64, int32, int64.
cond(Variable, optional): Optional output which can be any created Variable that meets the requirements to store the result of *greater_equal*.
if cond is None, a new Varibale will be created to store the result.
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:
Variable, the output data type is bool: The tensor variable storing the output, the output shape is same as input :attr:`x`.
...
...
@@ -1804,7 +1812,7 @@ def greater_equal(x, y, cond=None):
return
cond
def
equal
(
x
,
y
,
cond
=
None
):
def
equal
(
x
,
y
,
cond
=
None
,
name
=
None
):
"""
This layer returns the truth value of :math:`x == y` elementwise.
...
...
@@ -1814,6 +1822,8 @@ def equal(x, y, cond=None):
cond(Variable, optional): Optional output which can be any created
Variable that meets the requirements to store the result of *equal*.
if cond is None, a new Varibale will be created to store the result.
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:
Variable: output Tensor, it's shape is the same as the input's Tensor,
...
...
@@ -1849,7 +1859,7 @@ def equal(x, y, cond=None):
return
cond
def
not_equal
(
x
,
y
,
cond
=
None
):
def
not_equal
(
x
,
y
,
cond
=
None
,
name
=
None
):
"""
:alias_main: paddle.not_equal
:alias: paddle.not_equal,paddle.tensor.not_equal,paddle.tensor.logic.not_equal
...
...
@@ -1862,6 +1872,8 @@ def not_equal(x, y, cond=None):
y(Variable): Second input to compare which is N-D tensor. The input data type should be float32, float64, int32, int64.
cond(Variable, optional): Optional output which can be any created Variable that meets the requirements to store the result of *not_equal*.
if cond is None, a new Varibale will be created to store the result.
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:
Variable, the output data type is bool: The tensor variable storing the output, the output shape is same as input :attr:`x`.
...
...
python/paddle/fluid/tests/unittests/test_compare_op.py
浏览文件 @
595a7197
...
...
@@ -20,6 +20,7 @@ import numpy
import
numpy
as
np
import
paddle
import
paddle.fluid
as
fluid
import
paddle.fluid.core
as
core
from
paddle.fluid
import
Program
,
program_guard
...
...
@@ -67,6 +68,49 @@ for _type_name in {'float32', 'float64', 'int32', 'int64'}:
create_test_class
(
'not_equal'
,
_type_name
,
lambda
_a
,
_b
:
_a
!=
_b
)
def
create_paddle_case
(
op_type
,
callback
):
class
PaddleCls
(
unittest
.
TestCase
):
def
setUp
(
self
):
self
.
op_type
=
op_type
self
.
input_x
=
np
.
array
([
1
,
2
,
3
,
4
])
self
.
input_y
=
np
.
array
([
1
,
3
,
2
,
4
])
self
.
real_result
=
callback
(
self
.
input_x
,
self
.
input_y
)
def
test_api
(
self
):
with
program_guard
(
Program
(),
Program
()):
x
=
fluid
.
layers
.
data
(
name
=
'x'
,
shape
=
[
4
],
dtype
=
'int64'
)
y
=
fluid
.
layers
.
data
(
name
=
'y'
,
shape
=
[
4
],
dtype
=
'int64'
)
op
=
eval
(
"paddle.%s"
%
(
self
.
op_type
))
out
=
op
(
x
,
y
)
place
=
fluid
.
CPUPlace
()
if
core
.
is_compiled_with_cuda
():
place
=
paddle
.
CUDAPlace
(
0
)
exe
=
fluid
.
Executor
(
place
)
res
,
=
exe
.
run
(
feed
=
{
"x"
:
self
.
input_x
,
"y"
:
self
.
input_y
},
fetch_list
=
[
out
])
self
.
assertEqual
((
res
==
self
.
real_result
).
all
(),
True
)
def
test_attr_name
(
self
):
with
program_guard
(
Program
(),
Program
()):
x
=
fluid
.
layers
.
data
(
name
=
'x'
,
shape
=
[
4
],
dtype
=
'int32'
)
y
=
fluid
.
layers
.
data
(
name
=
'y'
,
shape
=
[
4
],
dtype
=
'int32'
)
op
=
eval
(
"paddle.%s"
%
(
self
.
op_type
))
out
=
op
(
x
=
x
,
y
=
y
,
name
=
"name_%s"
%
(
self
.
op_type
))
self
.
assertEqual
(
"name_%s"
%
(
self
.
op_type
)
in
out
.
name
,
True
)
cls_name
=
"TestCase_{}"
.
format
(
op_type
)
PaddleCls
.
__name__
=
cls_name
globals
()[
cls_name
]
=
PaddleCls
create_paddle_case
(
'less_equal'
,
lambda
_a
,
_b
:
_a
<=
_b
)
create_paddle_case
(
'greater_than'
,
lambda
_a
,
_b
:
_a
>
_b
)
create_paddle_case
(
'greater_equal'
,
lambda
_a
,
_b
:
_a
>=
_b
)
create_paddle_case
(
'equal'
,
lambda
_a
,
_b
:
_a
==
_b
)
create_paddle_case
(
'not_equal'
,
lambda
_a
,
_b
:
_a
!=
_b
)
class
TestCompareOpError
(
unittest
.
TestCase
):
def
test_errors
(
self
):
with
program_guard
(
Program
(),
Program
()):
...
...
@@ -82,7 +126,7 @@ class API_TestElementwise_Equal(unittest.TestCase):
with
fluid
.
program_guard
(
fluid
.
Program
(),
fluid
.
Program
()):
label
=
fluid
.
layers
.
assign
(
np
.
array
([
3
,
3
],
dtype
=
"int32"
))
limit
=
fluid
.
layers
.
assign
(
np
.
array
([
3
,
2
],
dtype
=
"int32"
))
out
=
paddle
.
e
lementwise_e
qual
(
x
=
label
,
y
=
limit
)
out
=
paddle
.
equal
(
x
=
label
,
y
=
limit
)
place
=
fluid
.
CPUPlace
()
exe
=
fluid
.
Executor
(
place
)
res
,
=
exe
.
run
(
fetch_list
=
[
out
])
...
...
@@ -91,7 +135,7 @@ class API_TestElementwise_Equal(unittest.TestCase):
with
fluid
.
program_guard
(
fluid
.
Program
(),
fluid
.
Program
()):
label
=
fluid
.
layers
.
assign
(
np
.
array
([
3
,
3
],
dtype
=
"int32"
))
limit
=
fluid
.
layers
.
assign
(
np
.
array
([
3
,
3
],
dtype
=
"int32"
))
out
=
paddle
.
e
lementwise_e
qual
(
x
=
label
,
y
=
limit
)
out
=
paddle
.
equal
(
x
=
label
,
y
=
limit
)
place
=
fluid
.
CPUPlace
()
exe
=
fluid
.
Executor
(
place
)
res
,
=
exe
.
run
(
fetch_list
=
[
out
])
...
...
python/paddle/fluid/tests/unittests/test_compare_reduce_op.py
浏览文件 @
595a7197
...
...
@@ -22,30 +22,29 @@ import paddle.fluid as fluid
from
paddle.fluid
import
Program
,
program_guard
def
create_test_
broadcast_class
(
op_type
,
args
,
callback
):
def
create_test_
not_equal_class
(
op_type
,
typename
,
callback
):
class
Cls
(
op_test
.
OpTest
):
def
setUp
(
self
):
x
=
np
.
random
.
random
(
size
=
args
[
'x_size'
]).
astype
(
'int32'
)
y
=
np
.
random
.
random
(
size
=
args
[
'y_size'
]).
astype
(
'int32'
)
x
=
np
.
random
.
random
(
size
=
(
10
,
7
)).
astype
(
typename
)
y
=
np
.
random
.
random
(
size
=
(
10
,
7
)).
astype
(
typename
)
z
=
callback
(
x
,
y
)
self
.
inputs
=
{
'X'
:
x
,
'Y'
:
y
}
self
.
outputs
=
{
'Out'
:
z
}
self
.
op_type
=
op_type
self
.
axis
=
args
[
'axis'
]
def
test_output
(
self
):
self
.
check_output
()
cls_name
=
"{0}_{1}
"
.
format
(
op_type
,
'broadcast
'
)
cls_name
=
"{0}_{1}
_{2}"
.
format
(
op_type
,
typename
,
'not_equal_all
'
)
Cls
.
__name__
=
cls_name
globals
()[
cls_name
]
=
Cls
def
create_test_not_equal_class
(
op_type
,
typename
,
callback
):
def
create_test_not_
shape_
equal_class
(
op_type
,
typename
,
callback
):
class
Cls
(
op_test
.
OpTest
):
def
setUp
(
self
):
x
=
np
.
random
.
random
(
size
=
(
10
,
7
)).
astype
(
typename
)
y
=
np
.
random
.
random
(
size
=
(
10
,
7
)).
astype
(
typename
)
y
=
np
.
random
.
random
(
size
=
(
10
)).
astype
(
typename
)
z
=
callback
(
x
,
y
)
self
.
inputs
=
{
'X'
:
x
,
'Y'
:
y
}
self
.
outputs
=
{
'Out'
:
z
}
...
...
@@ -54,7 +53,7 @@ def create_test_not_equal_class(op_type, typename, callback):
def
test_output
(
self
):
self
.
check_output
()
cls_name
=
"{0}_{1}_{2}"
.
format
(
op_type
,
typename
,
'not_
equa
l'
)
cls_name
=
"{0}_{1}_{2}"
.
format
(
op_type
,
typename
,
'not_
shape_equal_al
l'
)
Cls
.
__name__
=
cls_name
globals
()[
cls_name
]
=
Cls
...
...
@@ -71,7 +70,7 @@ def create_test_equal_class(op_type, typename, callback):
def
test_output
(
self
):
self
.
check_output
()
cls_name
=
"{0}_{1}_{2}"
.
format
(
op_type
,
typename
,
'equal'
)
cls_name
=
"{0}_{1}_{2}"
.
format
(
op_type
,
typename
,
'equal
_all
'
)
Cls
.
__name__
=
cls_name
globals
()[
cls_name
]
=
Cls
...
...
@@ -88,7 +87,7 @@ def create_test_dim1_class(op_type, typename, callback):
def
test_output
(
self
):
self
.
check_output
()
cls_name
=
"{0}_{1}_{2}"
.
format
(
op_type
,
typename
,
'equal'
)
cls_name
=
"{0}_{1}_{2}"
.
format
(
op_type
,
typename
,
'equal
_all
'
)
Cls
.
__name__
=
cls_name
globals
()[
cls_name
]
=
Cls
...
...
@@ -96,59 +95,16 @@ def create_test_dim1_class(op_type, typename, callback):
np_equal
=
lambda
_x
,
_y
:
np
.
array
(
np
.
array_equal
(
_x
,
_y
))
for
_type_name
in
{
'float32'
,
'float64'
,
'int32'
,
'int64'
}:
create_test_not_equal_class
(
'equal_reduce'
,
_type_name
,
np_equal
)
create_test_equal_class
(
'equal_reduce'
,
_type_name
,
np_equal
)
create_test_dim1_class
(
'equal_reduce'
,
_type_name
,
np_equal
)
broadcast_args
=
[{
'x_size'
:
(
100
,
2
,
3
),
'y_size'
:
(
100
),
'axis'
:
0
},
{
'x_size'
:
(
2
,
100
,
3
),
'y_size'
:
(
100
),
'axis'
:
1
},
{
'x_size'
:
(
2
,
3
,
100
),
'y_size'
:
(
1
,
1
),
'axis'
:
-
1
},
{
'x_size'
:
(
2
,
10
,
12
,
3
),
'y_size'
:
(
10
,
12
),
'axis'
:
1
},
{
'x_size'
:
(
100
,
2
,
3
,
4
),
'y_size'
:
(
100
,
1
),
'axis'
:
0
},
{
'x_size'
:
(
10
,
3
,
12
),
'y_size'
:
(
10
,
1
,
12
),
'axis'
:
-
1
},
{
'x_size'
:
(
2
,
12
,
3
,
5
),
'y_size'
:
(
2
,
12
,
1
,
5
),
'axis'
:
-
1
},
{
'x_size'
:
(
2
,
12
,
3
,
5
),
'y_size'
:
(
3
,
5
),
'axis'
:
2
}]
def
np_broadcast_equal
(
_x
,
_y
):
res
=
np
.
all
(
np
.
equal
(
_x
,
_y
))
return
np
.
array
(
res
)
for
args
in
broadcast_args
:
create_test_broadcast_class
(
'equal_reduce'
,
args
,
np_broadcast_equal
)
create_test_not_equal_class
(
'equal_all'
,
_type_name
,
np_equal
)
create_test_equal_class
(
'equal_all'
,
_type_name
,
np_equal
)
create_test_dim1_class
(
'equal_all'
,
_type_name
,
np_equal
)
class
TestEqualReduceAPI
(
unittest
.
TestCase
):
def
test_name
(
self
):
x
=
fluid
.
layers
.
assign
(
np
.
array
([
3
,
4
],
dtype
=
"int32"
))
y
=
fluid
.
layers
.
assign
(
np
.
array
([
3
,
4
],
dtype
=
"int32"
))
out
=
paddle
.
equal
(
x
,
y
,
name
=
'equal_res'
)
out
=
paddle
.
equal
_all
(
x
,
y
,
name
=
'equal_res'
)
assert
'equal_res'
in
out
.
name
...
...
python/paddle/tensor/__init__.py
浏览文件 @
595a7197
...
...
@@ -71,7 +71,7 @@ from .logic import not_equal #DEFINE_ALIAS
from
.logic
import
reduce_all
#DEFINE_ALIAS
from
.logic
import
reduce_any
#DEFINE_ALIAS
from
.logic
import
allclose
#DEFINE_ALIAS
from
.logic
import
e
lementwise_equa
l
#DEFINE_ALIAS
from
.logic
import
e
qual_al
l
#DEFINE_ALIAS
# from .logic import isnan #DEFINE_ALIAS
from
.manipulation
import
cast
#DEFINE_ALIAS
from
.manipulation
import
concat
#DEFINE_ALIAS
...
...
python/paddle/tensor/logic.py
浏览文件 @
595a7197
...
...
@@ -15,24 +15,21 @@
from
..fluid.layer_helper
import
LayerHelper
from
..fluid.data_feeder
import
check_type
from
..fluid.layers.layer_function_generator
import
templatedoc
from
..
import
fluid
# TODO: define logic functions of a tensor
from
..fluid.layers
import
greater_equal
#DEFINE_ALIAS
from
..fluid.layers
import
greater_than
#DEFINE_ALIAS
from
..fluid.layers
import
is_empty
#DEFINE_ALIAS
from
..fluid.layers
import
isfinite
#DEFINE_ALIAS
from
..fluid.layers
import
less_equal
#DEFINE_ALIAS
from
..fluid.layers
import
less_than
#DEFINE_ALIAS
from
..fluid.layers
import
logical_and
#DEFINE_ALIAS
from
..fluid.layers
import
logical_not
#DEFINE_ALIAS
from
..fluid.layers
import
logical_or
#DEFINE_ALIAS
from
..fluid.layers
import
logical_xor
#DEFINE_ALIAS
from
..fluid.layers
import
not_equal
#DEFINE_ALIAS
from
..fluid.layers
import
reduce_all
#DEFINE_ALIAS
from
..fluid.layers
import
reduce_any
#DEFINE_ALIAS
__all__
=
[
'equal'
,
'equal_all'
,
'greater_equal'
,
'greater_than'
,
'is_empty'
,
...
...
@@ -47,78 +44,50 @@ __all__ = [
'reduce_all'
,
'reduce_any'
,
'allclose'
,
'elementwise_equal'
,
# 'isnan'
]
def
equal
(
x
,
y
,
axis
=-
1
,
name
=
None
):
def
equal
_all
(
x
,
y
,
name
=
None
):
"""
:alias_main: paddle.equal
:alias: paddle.equal
,paddle.tensor.equal,paddle.tensor.logic.equa
l
:alias_main: paddle.equal
_all
:alias: paddle.equal
_all,paddle.tensor.equal_all,paddle.tensor.logic.equal_al
l
This OP returns the truth value of :math:`x == y`. True if two inputs have the same elements, False otherwise.
**NOTICE**: The output of this OP has no gradient
, and this OP supports broadcasting by :attr:`axis`
.
**NOTICE**: The output of this OP has no gradient.
Args:
x(Variable): Tensor, data type is float32, float64, int32, int64.
y(Variable): Tensor, data type is float32, float64, int32, int64.
axis(int32, optional): If X.dimension != Y.dimension, Y.dimension
must be a subsequence of x.dimension. And axis is the start
dimension index for broadcasting Y onto X. For more detail,
please refer to OP:`elementwise_add`.
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: None.
x(Tensor): Tensor, data type is float32, float64, int32, int64.
y(Tensor): Tensor, data type is float32, float64, int32, int64.
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:
Variable
: output Tensor, data type is bool, value is [False] or [True].
Tensor
: output Tensor, data type is bool, value is [False] or [True].
Examples:
.. code-block:: python
import paddle.fluid as fluid
import paddle
import numpy as np
label = fluid.layers.assign(np.array([3, 4], dtype="int32"))
label_1 = fluid.layers.assign(np.array([1, 2], dtype="int32"))
limit = fluid.layers.assign(np.array([3, 4], dtype="int32"))
out1 = paddle.equal(x=label, y=limit) #out1=[True]
out2 = paddle.equal(x=label_1, y=limit) #out2=[False]
.. code-block:: python
import paddle.fluid as fluid
import paddle
import numpy as np
def gen_data():
return {
"x": np.ones((2, 3, 4, 5)).astype('float32'),
"y": np.zeros((3, 4)).astype('float32')
}
x = fluid.data(name="x", shape=[2,3,4,5], dtype='float32')
y = fluid.data(name="y", shape=[3,4], dtype='float32')
out = paddle.equal(x, y, axis=1)
place = fluid.CPUPlace()
exe = fluid.Executor(place)
res = exe.run(feed=gen_data(),
fetch_list=[out])
print(res[0]) #[False]
import paddle.imperative as imperative
paddle.enable_imperative()
x = imperative.to_variable(np.array([1, 2, 3]))
y = imperative.to_variable(np.array([1, 2, 3]))
z = imperative.to_variable(np.array([1, 4, 3]))
result1 = paddle.equal_all(x, y)
print(result1.numpy()) # result1 = [True ]
result2 = paddle.equal_all(x, z)
print(result2.numpy()) # result2 = [False ]
"""
helper
=
LayerHelper
(
"equal_reduce"
,
**
locals
())
helper
=
LayerHelper
(
"equal_all"
,
**
locals
())
out
=
helper
.
create_variable_for_type_inference
(
dtype
=
'bool'
)
attrs
=
{}
attrs
[
'axis'
]
=
axis
helper
.
append_op
(
type
=
'equal_reduce'
,
inputs
=
{
'X'
:
[
x
],
'Y'
:
[
y
]},
attrs
=
attrs
,
outputs
=
{
'Out'
:
[
out
]})
type
=
'equal_all'
,
inputs
=
{
'X'
:
[
x
],
'Y'
:
[
y
]},
outputs
=
{
'Out'
:
[
out
]})
return
out
...
...
@@ -208,41 +177,205 @@ def allclose(input, other, rtol=1e-05, atol=1e-08, equal_nan=False, name=None):
return
out
def
elementwise_equal
(
x
,
y
,
name
=
None
):
@
templatedoc
()
def
equal
(
x
,
y
,
name
=
None
):
"""
:alias_main: paddle.e
lementwise_e
qual
:alias: paddle.e
lementwise_equal,paddle.tensor.elementwise_equal,paddle.tensor.logic.elementwise_
equal
:alias_main: paddle.equal
:alias: paddle.e
qual,paddle.tensor.equal,paddle.tensor.logic.
equal
This layer returns the truth value of :math:`x == y` elementwise.
**NOTICE**: The output of this OP has no gradient.
Args:
x(
Variable
): Tensor, data type is float32, float64, int32, int64.
y(
Variable
): Tensor, data type is float32, float64, int32, int64.
x(
Tensor
): Tensor, data type is float32, float64, int32, int64.
y(
Tensor
): Tensor, data type is float32, float64, int32, int64.
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:
Variable
: output Tensor, it's shape is the same as the input's Tensor,
Tensor
: output Tensor, it's shape is the same as the input's Tensor,
and the data type is bool. The result of this op is stop_gradient.
Examples:
.. code-block:: python
import paddle
import paddle.fluid as fluid
import numpy as np
label = fluid.layers.assign(np.array([3, 3], dtype="int32"))
limit = fluid.layers.assign(np.array([3, 2], dtype="int32"))
out1 = paddle.elementwise_equal(x=label, y=limit) #out1=[True, False]
import paddle
import paddle.imperative as imperative
paddle.enable_imperative()
x = imperative.to_variable(np.array([1, 2, 3]))
y = imperative.to_variable(np.array([1, 3, 2]))
result1 = paddle.equal(x, y)
print(result1.numpy()) # result1 = [True False False]
"""
helper
=
LayerHelper
(
"elementwise_equal"
,
**
locals
())
out
=
helper
.
create_variable_for_type_inference
(
dtype
=
'bool'
)
out
.
stop_gradient
=
True
out
=
fluid
.
layers
.
equal
(
x
,
y
,
name
=
name
,
cond
=
None
)
return
out
helper
.
append_op
(
type
=
'equal'
,
inputs
=
{
'X'
:
[
x
],
'Y'
:
[
y
]},
outputs
=
{
'Out'
:
[
out
]},
attrs
=
{
'force_cpu'
:
False
})
@
templatedoc
()
def
greater_equal
(
x
,
y
,
name
=
None
):
"""
:alias_main: paddle.greater_equal
:alias: paddle.greater_equal,paddle.tensor.greater_equal,paddle.tensor.logic.greater_equal
This OP returns the truth value of :math:`x >= y` elementwise, which is equivalent function to the overloaded operator `>=`.
**NOTICE**: The output of this OP has no gradient.
Args:
x(Tensor): First input to compare which is N-D tensor. The input data type should be float32, float64, int32, int64.
y(Tensor): Second input to compare which is N-D tensor. The input data type should be float32, float64, int32, int64.
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, the output data type is bool: The tensor storing the output, the output shape is same as input :attr:`x`.
Examples:
.. code-block:: python
import numpy as np
import paddle
import paddle.imperative as imperative
paddle.enable_imperative()
x = imperative.to_variable(np.array([1, 2, 3]))
y = imperative.to_variable(np.array([1, 3, 2]))
result1 = paddle.greater_equal(x, y)
print(result1.numpy()) # result1 = [True False True]
"""
out
=
fluid
.
layers
.
greater_equal
(
x
,
y
,
name
=
name
,
cond
=
None
)
return
out
@
templatedoc
()
def
greater_than
(
x
,
y
,
name
=
None
):
"""
:alias_main: paddle.greater_than
:alias: paddle.greater_than,paddle.tensor.greater_than,paddle.tensor.logic.greater_than
This OP returns the truth value of :math:`x > y` elementwise, which is equivalent function to the overloaded operator `>`.
**NOTICE**: The output of this OP has no gradient.
Args:
x(Tensor): First input to compare which is N-D tensor. The input data type should be float32, float64, int32, int64.
y(Tensor): Second input to compare which is N-D tensor. The input data type should be float32, float64, int32, int64.
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, the output data type is bool: The tensor storing the output, the output shape is same as input :attr:`x` .
Examples:
.. code-block:: python
import numpy as np
import paddle
import paddle.imperative as imperative
paddle.enable_imperative()
x = imperative.to_variable(np.array([1, 2, 3]))
y = imperative.to_variable(np.array([1, 3, 2]))
result1 = paddle.greater_than(x, y)
print(result1.numpy()) # result1 = [False False True]
"""
out
=
fluid
.
layers
.
greater_than
(
x
,
y
,
name
=
name
,
cond
=
None
)
return
out
@
templatedoc
()
def
less_equal
(
x
,
y
,
name
=
None
):
"""
:alias_main: paddle.less_equal
:alias: paddle.less_equal,paddle.tensor.less_equal,paddle.tensor.logic.less_equal
This OP returns the truth value of :math:`x <= y` elementwise, which is equivalent function to the overloaded operator `<=`.
**NOTICE**: The output of this OP has no gradient.
Args:
x(Tensor): First input to compare which is N-D tensor. The input data type should be float32, float64, int32, int64.
y(Tensor): Second input to compare which is N-D tensor. The input data type should be float32, float64, int32, int64.
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, the output data type is bool: The tensor storing the output, the output shape is same as input :attr:`x`.
Examples:
.. code-block:: python
import numpy as np
import paddle
import paddle.imperative as imperative
paddle.enable_imperative()
x = imperative.to_variable(np.array([1, 2, 3]))
y = imperative.to_variable(np.array([1, 3, 2]))
result1 = paddle.less_equal(x, y)
print(result1.numpy()) # result1 = [True True False]
"""
out
=
fluid
.
layers
.
less_equal
(
x
,
y
,
name
=
name
,
cond
=
None
)
return
out
@
templatedoc
()
def
less_than
(
x
,
y
,
name
=
None
):
"""
:alias_main: paddle.less_than
:alias: paddle.less_than,paddle.tensor.less_than,paddle.tensor.logic.less_than
This OP returns the truth value of :math:`x < y` elementwise, which is equivalent function to the overloaded operator `<`.
**NOTICE**: The output of this OP has no gradient.
Args:
x(Tensor): First input to compare which is N-D tensor. The input data type should be float32, float64, int32, int64.
y(Tensor): Second input to compare which is N-D tensor. The input data type should be float32, float64, int32, int64.
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, the output data type is bool: The tensor storing the output, the output shape is same as input :attr:`x`.
Examples:
.. code-block:: python
import numpy as np
import paddle
import paddle.imperative as imperative
paddle.enable_imperative()
x = imperative.to_variable(np.array([1, 2, 3]))
y = imperative.to_variable(np.array([1, 3, 2]))
result1 = paddle.less_than(x, y)
print(result1.numpy()) # result1 = [False True False]
"""
out
=
fluid
.
layers
.
less_than
(
x
,
y
,
force_cpu
=
False
,
name
=
name
,
cond
=
None
)
return
out
@
templatedoc
()
def
not_equal
(
x
,
y
,
name
=
None
):
"""
:alias_main: paddle.not_equal
:alias: paddle.not_equal,paddle.tensor.not_equal,paddle.tensor.logic.not_equal
This OP returns the truth value of :math:`x != y` elementwise, which is equivalent function to the overloaded operator `!=`.
**NOTICE**: The output of this OP has no gradient.
Args:
x(Tensor): First input to compare which is N-D tensor. The input data type should be float32, float64, int32, int64.
y(Tensor): Second input to compare which is N-D tensor. The input data type should be float32, float64, int32, int64.
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, the output data type is bool: The tensor storing the output, the output shape is same as input :attr:`x`.
Examples:
.. code-block:: python
import numpy as np
import paddle
import paddle.imperative as imperative
paddle.enable_imperative()
x = imperative.to_variable(np.array([1, 2, 3]))
y = imperative.to_variable(np.array([1, 3, 2]))
result1 = paddle.not_equal(x, y)
print(result1.numpy()) # result1 = [False True True]
"""
out
=
fluid
.
layers
.
not_equal
(
x
,
y
,
name
=
name
,
cond
=
None
)
return
out
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录