Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
BaiXuePrincess
Paddle
提交
a1c0b241
P
Paddle
项目概览
BaiXuePrincess
/
Paddle
与 Fork 源项目一致
Fork自
PaddlePaddle / Paddle
通知
1
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
P
Paddle
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
未验证
提交
a1c0b241
编写于
3月 04, 2020
作者:
F
FlyingQianMM
提交者:
GitHub
3月 04, 2020
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Correct CPU gradients of the argsort op. [cherry-pick #22739] test=release/1.7 (#22843)
上级
cfa34dfc
变更
2
显示空白变更内容
内联
并排
Showing
2 changed file
with
222 addition
and
64 deletion
+222
-64
paddle/fluid/operators/argsort_op.h
paddle/fluid/operators/argsort_op.h
+2
-2
python/paddle/fluid/tests/unittests/test_argsort_op.py
python/paddle/fluid/tests/unittests/test_argsort_op.py
+220
-62
未找到文件。
paddle/fluid/operators/argsort_op.h
浏览文件 @
a1c0b241
...
...
@@ -81,13 +81,13 @@ static void FullAssign(Type input_height, Type input_width, int input_dim,
auto
e_input
=
EigenVector
<
T
>::
Flatten
(
*
input
);
auto
e_indices
=
EigenVector
<
Type
>::
Flatten
(
*
indices
);
for
(
Type
j
=
0
;
j
<
input_width
;
++
j
)
{
t_out
[
i
*
input_width
+
e_indices
(
j
)]
=
e_input
(
e_indices
(
j
)
);
t_out
[
i
*
input_width
+
e_indices
(
j
)]
=
e_input
(
j
);
}
}
else
{
auto
e_input
=
EigenMatrix
<
T
>::
Reshape
(
*
input
,
input_dim
-
1
);
auto
e_indices
=
EigenMatrix
<
Type
>::
Reshape
(
*
indices
,
input_dim
-
1
);
for
(
Type
j
=
0
;
j
<
input_width
;
++
j
)
{
t_out
[
i
*
input_width
+
e_indices
(
i
,
j
)]
=
e_input
(
i
,
e_indices
(
i
,
j
)
);
t_out
[
i
*
input_width
+
e_indices
(
i
,
j
)]
=
e_input
(
i
,
j
);
}
}
}
...
...
python/paddle/fluid/tests/unittests/test_argsort_op.py
浏览文件 @
a1c0b241
# Copyright (c) 20
18
PaddlePaddle Authors. All Rights Reserved.
# Copyright (c) 20
20
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.
...
...
@@ -15,34 +15,176 @@
from
__future__
import
print_function
import
unittest
import
paddle.fluid
as
fluid
import
paddle.fluid.layers
as
layers
import
numpy
as
np
from
op_test
import
OpTest
import
six
import
paddle.fluid.core
as
core
from
paddle.fluid
import
ParamAttr
from
paddle.fluid.framework
import
Program
,
grad_var_name
from
paddle.fluid.executor
import
Executor
from
paddle.fluid.backward
import
append_backward
class
TestArgsortOp
(
OpTest
):
def
setUp
(
self
):
self
.
init_axis
()
self
.
init_datatype
()
self
.
init_direction
()
x
=
np
.
random
.
random
((
2
,
3
,
4
,
5
,
10
)).
astype
(
self
.
dtype
)
self
.
attrs
=
{
'axis'
:
self
.
axis
,
'descending'
:
self
.
descending
}
if
self
.
axis
<
0
:
self
.
axis
=
self
.
axis
+
len
(
x
.
shape
)
np
.
random
.
seed
(
123
)
class
PyArgsort
(
object
):
def
__init__
(
self
,
input_shape
,
axis
,
descending
,
dtype
):
self
.
x
=
np
.
random
.
random
(
input_shape
).
astype
(
dtype
)
self
.
label
=
np
.
random
.
random
(
input_shape
).
astype
(
dtype
)
if
axis
<
0
:
self
.
axis
=
axis
+
len
(
self
.
x
.
shape
)
else
:
self
.
axis
=
axis
self
.
descending
=
descending
def
forward
(
self
):
if
self
.
descending
:
self
.
indices
=
np
.
flip
(
np
.
argsort
(
x
,
kind
=
'quicksort'
,
axis
=
self
.
axis
),
self
.
axis
)
self
.
out
=
np
.
flip
(
self
.
x
,
kind
=
'quicksort'
,
axis
=
self
.
axis
),
self
.
axis
)
self
.
sorted_x
=
np
.
flip
(
np
.
sort
(
x
,
kind
=
'quicksort'
,
axis
=
self
.
axis
),
self
.
axis
)
self
.
x
,
kind
=
'quicksort'
,
axis
=
self
.
axis
),
self
.
axis
)
else
:
self
.
indices
=
np
.
argsort
(
x
,
kind
=
'quicksort'
,
axis
=
self
.
axis
)
self
.
out
=
np
.
sort
(
x
,
kind
=
'quicksort'
,
axis
=
self
.
axis
)
self
.
indices
=
np
.
argsort
(
self
.
x
,
kind
=
'quicksort'
,
axis
=
self
.
axis
)
self
.
sorted_x
=
np
.
sort
(
self
.
x
,
kind
=
'quicksort'
,
axis
=
self
.
axis
)
self
.
loss
=
self
.
sorted_x
*
self
.
label
self
.
loss
=
np
.
sum
(
self
.
loss
)
out
=
(
np
.
array
(
self
.
indices
,
dtype
=
self
.
indices
.
dtype
),
np
.
array
(
self
.
sorted_x
,
dtype
=
self
.
sorted_x
.
dtype
),
np
.
array
(
[
self
.
loss
],
dtype
=
self
.
loss
.
dtype
))
return
out
self
.
op_type
=
"argsort"
self
.
inputs
=
{
'X'
:
x
}
self
.
outputs
=
{
'Indices'
:
self
.
indices
,
'Out'
:
self
.
out
}
def
create_tensor
(
np_data
,
place
):
tensor
=
core
.
LoDTensor
()
tensor
.
set
(
np_data
,
place
)
return
tensor
class
TestArgsortOpCPU
(
unittest
.
TestCase
):
def
setup_program
(
self
):
self
.
main_program
=
Program
()
self
.
startup_program
=
Program
()
self
.
init_place
()
def
setUp
(
self
):
self
.
init_axis
()
self
.
init_datatype
()
self
.
init_direction
()
self
.
init_inputshape
()
self
.
setup_program
()
self
.
feed_data_field
=
{
"x"
,
"label"
}
self
.
grad_data_field
=
{
"x"
}
self
.
py_argsort
=
PyArgsort
(
self
.
input_shape
,
self
.
axis
,
self
.
descending
,
self
.
dtype
)
with
fluid
.
program_guard
(
self
.
main_program
,
self
.
startup_program
):
x
=
fluid
.
layers
.
data
(
name
=
"x"
,
shape
=
self
.
input_shape
,
dtype
=
self
.
dtype
)
x
.
stop_gradient
=
False
label
=
fluid
.
layers
.
data
(
name
=
"label"
,
shape
=
self
.
input_shape
,
dtype
=
self
.
dtype
)
self
.
sorted_x
,
self
.
index
=
fluid
.
layers
.
argsort
(
input
=
x
,
axis
=
self
.
axis
,
descending
=
self
.
descending
)
self
.
sorted_x
.
stop_gradient
=
False
loss
=
fluid
.
layers
.
elementwise_mul
(
self
.
sorted_x
,
label
)
self
.
loss
=
fluid
.
layers
.
reduce_sum
(
loss
)
def
forward
(
self
):
self
.
feed_map
=
{
x
:
create_tensor
(
getattr
(
self
.
py_argsort
,
x
),
self
.
place
)
for
x
in
self
.
feed_data_field
}
exe
=
Executor
(
self
.
place
)
out
=
exe
.
run
(
self
.
main_program
,
feed
=
self
.
feed_map
,
fetch_list
=
[
self
.
index
,
self
.
sorted_x
,
self
.
loss
])
return
out
def
backward
(
self
):
self
.
feed_map
=
{
x
:
create_tensor
(
getattr
(
self
.
py_argsort
,
x
),
self
.
place
)
for
x
in
self
.
feed_data_field
}
fetch_list
=
[
self
.
main_program
.
global_block
().
var
(
grad_var_name
(
x
))
for
x
in
self
.
grad_data_field
]
exe
=
Executor
(
self
.
place
)
out
=
exe
.
run
(
self
.
main_program
,
feed
=
self
.
feed_map
,
fetch_list
=
fetch_list
,
return_numpy
=
False
)
return
out
def
test_backward
(
self
,
numeric_grad_delta
=
1e-5
,
max_relative_error
=
1e-7
):
self
.
check_forward
()
with
fluid
.
program_guard
(
self
.
main_program
,
self
.
startup_program
):
append_backward
(
self
.
loss
)
ana_grad
=
[
np
.
array
(
x
)
for
x
in
self
.
backward
()]
num_grad
=
self
.
get_numerical_gradient
(
delta
=
numeric_grad_delta
)
self
.
assert_is_close
(
num_grad
,
ana_grad
,
'x'
,
max_relative_error
=
max_relative_error
,
msg_prefix
=
"Gradient Check On %s"
%
str
(
self
.
place
))
def
check_forward
(
self
):
pd_outputs
=
self
.
forward
()
py_outputs
=
self
.
py_argsort
.
forward
()
for
pd_output
,
py_output
in
zip
(
pd_outputs
,
py_outputs
):
self
.
assertEqual
(
pd_output
.
shape
,
py_output
.
shape
)
self
.
assertTrue
(
np
.
allclose
(
pd_output
,
py_output
,
atol
=
0
,
equal_nan
=
False
))
def
get_numerical_gradient
(
self
,
delta
=
1e-7
):
if
self
.
dtype
==
'float16'
:
delta
=
np
.
array
(
delta
).
astype
(
np
.
float16
)
feed_list
=
[
getattr
(
self
.
py_argsort
,
x
)
for
x
in
self
.
grad_data_field
]
grad_list
=
[
np
.
zeros_like
(
x
)
for
x
in
feed_list
]
for
feed
,
grad
in
zip
(
feed_list
,
grad_list
):
for
f
,
g
in
np
.
nditer
([
feed
,
grad
],
op_flags
=
[
'readwrite'
]):
o
=
float
(
f
)
f
[...]
=
o
+
delta
y_pos
=
self
.
forward
()[
2
]
f
[...]
=
o
-
delta
y_neg
=
self
.
forward
()[
2
]
f
[...]
=
o
dout_dfeed
=
(
y_pos
-
y_neg
)
/
(
delta
*
2
)
g
[...]
=
dout_dfeed
[
0
]
return
grad_list
def
assert_is_close
(
self
,
numeric_grads
,
analytic_grads
,
names
,
max_relative_error
,
msg_prefix
):
for
a
,
b
,
name
in
six
.
moves
.
zip
(
numeric_grads
,
analytic_grads
,
names
):
abs_a
=
np
.
abs
(
a
)
abs_a
[
abs_a
<
1e-3
]
=
1
diff_mat
=
np
.
abs
(
a
-
b
)
/
abs_a
max_diff
=
np
.
max
(
diff_mat
)
def
err_msg
():
offset
=
np
.
argmax
(
diff_mat
>
max_relative_error
)
return
(
"%s error, %s variable %s max gradient diff %f over limit %f, "
"the first error element is %d, expected %f, but got %f."
)
\
%
(
'argsort'
,
msg_prefix
,
name
,
max_diff
,
max_relative_error
,
offset
,
a
.
flatten
()[
offset
],
b
.
flatten
()[
offset
])
self
.
assertLessEqual
(
max_diff
,
max_relative_error
,
err_msg
())
def
init_axis
(
self
):
self
.
axis
=
-
1
...
...
@@ -53,111 +195,127 @@ class TestArgsortOp(OpTest):
def
init_direction
(
self
):
self
.
descending
=
False
def
test_check_output
(
self
):
self
.
check_output
()
def
init_inputshape
(
self
):
self
.
input_shape
=
(
2
,
2
,
2
,
2
,
3
)
def
init_place
(
self
):
self
.
place
=
core
.
CPUPlace
()
def
test_check_grad
(
self
):
self
.
check_grad
([
'X'
],
'Out'
)
class
TestArgsortOpGPU
(
TestArgsortOpCPU
):
def
init_place
(
self
):
if
core
.
is_compiled_with_cuda
():
self
.
place
=
core
.
CUDAPlace
(
0
)
else
:
self
.
place
=
core
.
CPUPlace
()
class
TestArgsortOpAxis0
(
TestArgsortOp
):
class
TestArgsortOpAxis0CPU
(
TestArgsortOpCPU
):
def
init_axis
(
self
):
self
.
axis
=
0
class
TestArgsortOpAxis
1
(
TestArgsortOp
):
class
TestArgsortOpAxis
0GPU
(
TestArgsortOpGPU
):
def
init_axis
(
self
):
self
.
axis
=
1
self
.
axis
=
0
class
TestArgsortOpAxis
2
(
TestArgsortOp
):
class
TestArgsortOpAxis
1CPU
(
TestArgsortOpCPU
):
def
init_axis
(
self
):
self
.
axis
=
2
self
.
axis
=
1
class
TestArgsortOpAxis
Neg1
(
TestArgsortOp
):
class
TestArgsortOpAxis
1GPU
(
TestArgsortOpGPU
):
def
init_axis
(
self
):
self
.
axis
=
-
1
self
.
axis
=
1
class
TestArgsortOpAxis
Neg2
(
TestArgsortOp
):
class
TestArgsortOpAxis
2CPU
(
TestArgsortOpCPU
):
def
init_axis
(
self
):
self
.
axis
=
-
2
self
.
axis
=
2
class
TestArgsortOpFP16
(
TestArgsortOp
):
def
init_datatype
(
self
):
if
core
.
is_compiled_with_cuda
():
self
.
dtype
=
'float16'
class
TestArgsortOpAxis2GPU
(
TestArgsortOpGPU
):
def
init_axis
(
self
):
self
.
axis
=
2
def
test_check_output
(
self
):
pass
def
test_check_output_with_place
(
self
):
if
core
.
is_compiled_with_cuda
():
place
=
core
.
CUDAPlace
(
0
)
self
.
check_output_with_place
(
place
,
atol
=
1e-5
)
class
TestArgsortOpAxisNeg1CPU
(
TestArgsortOpCPU
):
def
init_axis
(
self
):
self
.
axis
=
-
1
class
TestArgsortOp
FP16Axis0
(
TestArgsortOpFP16
):
class
TestArgsortOp
AxisNeg1GPU
(
TestArgsortOpGPU
):
def
init_axis
(
self
):
self
.
axis
=
0
self
.
axis
=
-
1
class
TestArgsortOp
FP16Axis2
(
TestArgsortOpFP16
):
class
TestArgsortOp
AxisNeg2CPU
(
TestArgsortOpCPU
):
def
init_axis
(
self
):
self
.
axis
=
2
self
.
axis
=
-
2
class
TestArgsortOp
FP16AxisNeg2
(
TestArgsortOpFP16
):
class
TestArgsortOp
AxisNeg2GPU
(
TestArgsortOpGPU
):
def
init_axis
(
self
):
self
.
axis
=
-
2
class
TestArgsortOp
FP16Axis4Neg4
(
TestArgsortOpFP16
):
def
init_
axis
(
self
):
self
.
axis
=
-
4
class
TestArgsortOp
DescendingAxisCPU
(
TestArgsortOpCPU
):
def
init_
direction
(
self
):
self
.
descending
=
True
class
TestArgsortOpDescendingAxis
(
TestArgsortOp
):
class
TestArgsortOpDescendingAxis
GPU
(
TestArgsortOpGPU
):
def
init_direction
(
self
):
self
.
descending
=
True
class
TestArgsortOpDescendingAxis0
(
TestArgsortOpAxis0
):
class
TestArgsortOpDescendingAxis0
CPU
(
TestArgsortOpAxis0CPU
):
def
init_direction
(
self
):
self
.
descending
=
True
class
TestArgsortOpDescendingAxis
1
(
TestArgsortOpAxis1
):
class
TestArgsortOpDescendingAxis
0GPU
(
TestArgsortOpAxis0GPU
):
def
init_direction
(
self
):
self
.
descending
=
True
class
TestArgsortOpDescendingAxis
2
(
TestArgsortOpAxis2
):
class
TestArgsortOpDescendingAxis
1CPU
(
TestArgsortOpAxis1CPU
):
def
init_direction
(
self
):
self
.
descending
=
True
class
TestArgsortOpDescendingAxis
Neg1
(
TestArgsortOpAxisNeg1
):
class
TestArgsortOpDescendingAxis
1GPU
(
TestArgsortOpAxis1GPU
):
def
init_direction
(
self
):
self
.
descending
=
True
class
TestArgsortOpDescendingAxis
Neg2
(
TestArgsortOpAxisNeg2
):
class
TestArgsortOpDescendingAxis
2CPU
(
TestArgsortOpAxis2CPU
):
def
init_direction
(
self
):
self
.
descending
=
True
class
TestArgsortOp
FP32Axis
(
TestArgsortOp
):
def
init_d
atatype
(
self
):
self
.
d
type
=
"float32"
class
TestArgsortOp
DescendingAxis2GPU
(
TestArgsortOpAxis2GPU
):
def
init_d
irection
(
self
):
self
.
d
escending
=
True
class
TestArgsortOpFP32DescendingAxis
(
TestArgsortOp
):
def
init_datatype
(
self
):
self
.
dtype
=
"float32"
class
TestArgsortOpDescendingAxisNeg1CPU
(
TestArgsortOpAxisNeg1CPU
):
def
init_direction
(
self
):
self
.
descending
=
True
class
TestArgsortOpDescendingAxisNeg1GPU
(
TestArgsortOpAxisNeg1GPU
):
def
init_direction
(
self
):
self
.
descending
=
True
class
TestArgsortOpDescendingAxisNeg2CPU
(
TestArgsortOpAxisNeg2CPU
):
def
init_direction
(
self
):
self
.
descending
=
True
class
TestArgsortOpDescendingAxisNeg2GPU
(
TestArgsortOpAxisNeg2GPU
):
def
init_direction
(
self
):
self
.
descending
=
True
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录