Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
PaddlePaddle
Paddle
提交
544458e0
P
Paddle
项目概览
PaddlePaddle
/
Paddle
大约 1 年 前同步成功
通知
2299
Star
20931
Fork
5422
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
1423
列表
看板
标记
里程碑
合并请求
543
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
P
Paddle
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
1,423
Issue
1,423
列表
看板
标记
里程碑
合并请求
543
合并请求
543
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
544458e0
编写于
9月 07, 2017
作者:
F
fengjiayi
提交者:
GitHub
9月 07, 2017
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #3888 from Canpio/dev_add_axis
Add axis for `mul_op` and `rowwise_add_op`
上级
d7079cea
856611cc
变更
14
显示空白变更内容
内联
并排
Showing
14 changed file
with
301 addition
and
52 deletion
+301
-52
paddle/framework/attribute.h
paddle/framework/attribute.h
+18
-1
paddle/framework/ddim.cc
paddle/framework/ddim.cc
+9
-0
paddle/framework/ddim.h
paddle/framework/ddim.h
+6
-0
paddle/framework/eigen.h
paddle/framework/eigen.h
+20
-5
paddle/framework/eigen_test.cc
paddle/framework/eigen_test.cc
+19
-0
paddle/framework/tensor.h
paddle/framework/tensor.h
+3
-0
paddle/framework/tensor_impl.h
paddle/framework/tensor_impl.h
+8
-0
paddle/framework/tensor_test.cc
paddle/framework/tensor_test.cc
+13
-0
paddle/operators/mul_op.cc
paddle/operators/mul_op.cc
+50
-14
paddle/operators/mul_op.h
paddle/operators/mul_op.h
+40
-12
paddle/operators/rowwise_add_op.cc
paddle/operators/rowwise_add_op.cc
+25
-13
paddle/operators/rowwise_add_op.h
paddle/operators/rowwise_add_op.h
+11
-6
python/paddle/v2/framework/tests/test_mul_op.py
python/paddle/v2/framework/tests/test_mul_op.py
+49
-1
python/paddle/v2/framework/tests/test_rowwise_add_op.py
python/paddle/v2/framework/tests/test_rowwise_add_op.py
+30
-0
未找到文件。
paddle/framework/attribute.h
浏览文件 @
544458e0
...
...
@@ -45,7 +45,19 @@ class GreaterThanChecker {
public:
explicit
GreaterThanChecker
(
T
lower_bound
)
:
lower_bound_
(
lower_bound
)
{}
void
operator
()(
T
&
value
)
const
{
PADDLE_ENFORCE
(
value
>
lower_bound_
,
"larger_than check fail"
);
PADDLE_ENFORCE
(
value
>
lower_bound_
,
"larger_than check fails."
);
}
private:
T
lower_bound_
;
};
template
<
typename
T
>
class
EqualGreaterThanChecker
{
public:
explicit
EqualGreaterThanChecker
(
T
lower_bound
)
:
lower_bound_
(
lower_bound
)
{}
void
operator
()(
T
&
value
)
const
{
PADDLE_ENFORCE_GE
(
value
,
lower_bound_
,
"equal_larger_than check fails."
);
}
private:
...
...
@@ -115,6 +127,11 @@ class TypedAttrChecker {
return
*
this
;
}
TypedAttrChecker
&
EqualGreaterThan
(
const
T
&
lower_bound
)
{
value_checkers_
.
push_back
(
EqualGreaterThanChecker
<
T
>
(
lower_bound
));
return
*
this
;
}
// we can add more common limits, like LessThan(), Between()...
TypedAttrChecker
&
SetDefault
(
const
T
&
default_value
)
{
...
...
paddle/framework/ddim.cc
浏览文件 @
544458e0
...
...
@@ -283,5 +283,14 @@ std::ostream& operator<<(std::ostream& os, const DDim& ddim) {
DDim
::
DDim
(
std
::
initializer_list
<
int64_t
>
init_list
)
{
*
this
=
make_ddim
(
init_list
);
}
DDim
flatten_to_2d
(
const
DDim
&
src
,
int
num_col_dims
)
{
int
rank
=
src
.
size
();
return
make_ddim
({
product
(
slice_ddim
(
src
,
0
,
num_col_dims
)),
product
(
slice_ddim
(
src
,
num_col_dims
,
rank
))});
}
DDim
flatten_to_1d
(
const
DDim
&
src
)
{
return
make_ddim
({
product
(
src
)});
}
}
// namespace framework
}
// namespace paddle
paddle/framework/ddim.h
浏览文件 @
544458e0
...
...
@@ -115,6 +115,12 @@ int arity(const DDim& ddim);
std
::
ostream
&
operator
<<
(
std
::
ostream
&
,
const
DDim
&
);
// Reshape a tensor to a matrix. The matrix's first dimension(column length)
// will be the product of tensor's first `num_col_dims` dimensions.
DDim
flatten_to_2d
(
const
DDim
&
src
,
int
num_col_dims
);
DDim
flatten_to_1d
(
const
DDim
&
src
);
}
// namespace framework
}
// namespace paddle
...
...
paddle/framework/eigen.h
浏览文件 @
544458e0
...
...
@@ -63,20 +63,35 @@ struct EigenTensor {
template
<
typename
T
,
int
MajorType
=
Eigen
::
RowMajor
,
typename
IndexType
=
Eigen
::
DenseIndex
>
struct
EigenMatrix
:
public
EigenTensor
<
T
,
2
,
MajorType
,
IndexType
>
{};
struct
EigenMatrix
:
public
EigenTensor
<
T
,
2
,
MajorType
,
IndexType
>
{
static
typename
EigenMatrix
::
Type
Reshape
(
Tensor
&
tensor
,
int
num_col_dims
)
{
int
rank
=
tensor
.
dims_
.
size
();
PADDLE_ENFORCE
(
num_col_dims
>
0
&&
num_col_dims
<
rank
,
"`num_col_dims` must be between (0, rank_of_tensor)."
);
return
EigenMatrix
::
From
(
tensor
,
flatten_to_2d
(
tensor
.
dims
(),
num_col_dims
));
}
static
typename
EigenMatrix
::
ConstType
Reshape
(
const
Tensor
&
tensor
,
int
num_col_dims
)
{
int
rank
=
tensor
.
dims_
.
size
();
PADDLE_ENFORCE
(
num_col_dims
>
0
&&
num_col_dims
<
rank
,
"`num_col_dims` must be between (0, rank_of_tensor)."
);
return
EigenMatrix
::
From
(
tensor
,
flatten_to_2d
(
tensor
.
dims
(),
num_col_dims
));
}
};
template
<
typename
T
,
int
MajorType
=
Eigen
::
RowMajor
,
typename
IndexType
=
Eigen
::
DenseIndex
>
struct
EigenVector
:
public
EigenTensor
<
T
,
1
,
MajorType
,
IndexType
>
{
// Flatten reshapes a Tensor into an EigenVector.
static
typename
EigenVector
::
Type
Flatten
(
Tensor
&
tensor
)
{
return
EigenVector
::
From
(
tensor
,
make_ddim
({
static_cast
<
int
>
(
product
(
tensor
.
dims_
))}));
return
EigenVector
::
From
(
tensor
,
{
product
(
tensor
.
dims_
)});
}
static
typename
EigenVector
::
ConstType
Flatten
(
const
Tensor
&
tensor
)
{
return
EigenVector
::
From
(
tensor
,
make_ddim
({
static_cast
<
int
>
(
product
(
tensor
.
dims_
))}));
return
EigenVector
::
From
(
tensor
,
{
product
(
tensor
.
dims_
)});
}
};
...
...
paddle/framework/eigen_test.cc
浏览文件 @
544458e0
...
...
@@ -108,5 +108,24 @@ TEST(Eigen, Matrix) {
}
}
TEST
(
Eigen
,
MatrixReshape
)
{
Tensor
t
;
float
*
p
=
t
.
mutable_data
<
float
>
({
2
,
3
,
6
,
4
},
platform
::
CPUPlace
());
for
(
int
i
=
0
;
i
<
2
*
3
*
6
*
4
;
++
i
)
{
p
[
i
]
=
static_cast
<
float
>
(
i
);
}
EigenMatrix
<
float
>::
Type
em
=
EigenMatrix
<
float
>::
Reshape
(
t
,
2
);
ASSERT_EQ
(
2
*
3
,
em
.
dimension
(
0
));
ASSERT_EQ
(
6
*
4
,
em
.
dimension
(
1
));
for
(
int
i
=
0
;
i
<
2
*
3
;
i
++
)
{
for
(
int
j
=
0
;
j
<
6
*
4
;
j
++
)
{
ASSERT_NEAR
(
i
*
6
*
4
+
j
,
em
(
i
,
j
),
1e-6
f
);
}
}
}
}
// namespace framework
}
// namespace paddle
paddle/framework/tensor.h
浏览文件 @
544458e0
...
...
@@ -43,6 +43,9 @@ class Tensor {
template
<
typename
T
,
size_t
D
,
int
MajorType
,
typename
IndexType
>
friend
struct
EigenTensor
;
template
<
typename
T
,
int
MajorType
,
typename
IndexType
>
friend
struct
EigenMatrix
;
template
<
typename
T
,
int
MajorType
,
typename
IndexType
>
friend
struct
EigenVector
;
...
...
paddle/framework/tensor_impl.h
浏览文件 @
544458e0
...
...
@@ -148,5 +148,13 @@ inline Tensor& Tensor::Resize(const DDim& dims) {
inline
const
DDim
&
Tensor
::
dims
()
const
{
return
dims_
;
}
template
<
typename
T
>
inline
Tensor
ReshapeToMatrix
(
const
Tensor
&
src
,
int
num_col_dims
)
{
Tensor
res
;
res
.
ShareDataWith
<
T
>
(
src
);
res
.
Resize
(
flatten_to_2d
(
src
.
dims
(),
num_col_dims
));
return
res
;
}
}
// namespace framework
}
// namespace paddle
paddle/framework/tensor_test.cc
浏览文件 @
544458e0
...
...
@@ -262,3 +262,16 @@ TEST(Tensor, CopyFrom) {
}
#endif
}
TEST
(
Tensor
,
ReshapeToMatrix
)
{
using
namespace
paddle
::
framework
;
using
namespace
paddle
::
platform
;
Tensor
src
;
int
*
src_ptr
=
src
.
mutable_data
<
int
>
({
2
,
3
,
4
,
9
},
CPUPlace
());
for
(
int
i
=
0
;
i
<
2
*
3
*
4
*
9
;
++
i
)
{
src_ptr
[
i
]
=
i
;
}
Tensor
res
=
ReshapeToMatrix
<
int
>
(
src
,
2
);
ASSERT_EQ
(
res
.
dims
()[
0
],
2
*
3
);
ASSERT_EQ
(
res
.
dims
()[
1
],
4
*
9
);
}
\ No newline at end of file
paddle/operators/mul_op.cc
浏览文件 @
544458e0
...
...
@@ -25,18 +25,27 @@ class MulOp : public framework::OperatorWithKernel {
protected:
void
InferShape
(
const
framework
::
InferShapeContext
&
ctx
)
const
override
{
auto
dim0
=
ctx
.
Input
<
Tensor
>
(
"X"
)
->
dims
();
auto
dim1
=
ctx
.
Input
<
Tensor
>
(
"Y"
)
->
dims
();
PADDLE_ENFORCE_EQ
(
dim0
.
size
(),
2
,
"input X(%s) should be a tensor with 2 dims, a matrix"
,
auto
x_dims
=
ctx
.
Input
<
Tensor
>
(
"X"
)
->
dims
();
auto
y_dims
=
ctx
.
Input
<
Tensor
>
(
"Y"
)
->
dims
();
int
x_num_col_dims
=
Attr
<
int
>
(
"x_num_col_dims"
);
int
y_num_col_dims
=
Attr
<
int
>
(
"y_num_col_dims"
);
PADDLE_ENFORCE
(
x_dims
.
size
()
>
x_num_col_dims
,
"The rank of input tensor X(%s) should be larger than "
"`mul_op`'s `x_num_col_dims`."
,
ctx
.
op
().
Input
(
"X"
));
PADDLE_ENFORCE_EQ
(
dim1
.
size
(),
2
,
"input Y(%s) should be a tensor with 2 dims, a matrix"
,
PADDLE_ENFORCE
(
y_dims
.
size
()
>
y_num_col_dims
,
"The rank of input tensor Y(%s) should be larger than "
"`mul_op`'s `y_num_col_dims`."
,
ctx
.
op
().
Input
(
"Y"
));
auto
x_mat_dims
=
framework
::
flatten_to_2d
(
x_dims
,
x_num_col_dims
);
auto
y_mat_dims
=
framework
::
flatten_to_2d
(
y_dims
,
y_num_col_dims
);
PADDLE_ENFORCE_EQ
(
dim0
[
1
],
dim1
[
0
],
x_mat_dims
[
1
],
y_mat_dims
[
0
],
"First matrix's width must be equal with second matrix's height."
);
ctx
.
Output
<
Tensor
>
(
"Out"
)
->
Resize
({
dim0
[
0
],
dim1
[
1
]});
ctx
.
Output
<
Tensor
>
(
"Out"
)
->
Resize
({
x_mat_dims
[
0
],
y_mat_dims
[
1
]});
}
};
...
...
@@ -47,6 +56,23 @@ class MulOpMaker : public framework::OpProtoAndCheckerMaker {
AddInput
(
"X"
,
"The first input of mul op"
);
AddInput
(
"Y"
,
"The second input of mul op"
);
AddOutput
(
"Out"
,
"The output of mul op"
);
AddAttr
<
int
>
(
"x_num_col_dims"
,
R"DOC(mul_op can take tensors with more than two dimensions as input `X`,
in that case, tensors will be reshaped to a matrix. The matrix's first
dimension(column length) will be the product of tensor's last
`num_col_dims` dimensions, and the matrix's second dimension(row length)
will be the product of tensor's first `rank - num_col_dims` dimensions.
)DOC"
)
.
SetDefault
(
1
)
.
EqualGreaterThan
(
1
);
AddAttr
<
int
>
(
"y_num_col_dims"
,
R"DOC(mul_op can take tensors with more than two dimensions as input `Y`,
in that case, tensors will be reshaped to a matrix. Just like input `X`.
)DOC"
)
.
SetDefault
(
1
)
.
EqualGreaterThan
(
1
);
AddComment
(
R"DOC(
Two Element Mul Operator.
...
...
@@ -70,10 +96,20 @@ class MulOpGrad : public framework::OperatorWithKernel {
auto
out_dims
=
ctx
.
Input
<
Tensor
>
(
framework
::
GradVarName
(
"Out"
))
->
dims
();
auto
*
x_grad
=
ctx
.
Output
<
Tensor
>
(
framework
::
GradVarName
(
"X"
));
auto
*
y_grad
=
ctx
.
Output
<
Tensor
>
(
framework
::
GradVarName
(
"Y"
));
PADDLE_ENFORCE
(
x_dims
[
0
]
==
out_dims
[
0
],
"Out@GRAD M X N must equal to X dims 0, M "
);
PADDLE_ENFORCE
(
y_dims
[
1
]
==
out_dims
[
1
],
"Out@GRAD M X N must equal to Y dims 1, N "
);
auto
x_mat_dims
=
framework
::
flatten_to_2d
(
x_dims
,
Attr
<
int
>
(
"x_num_col_dims"
));
auto
y_mat_dims
=
framework
::
flatten_to_2d
(
y_dims
,
Attr
<
int
>
(
"y_num_col_dims"
));
PADDLE_ENFORCE_EQ
(
x_mat_dims
[
0
],
out_dims
[
0
],
"The first dimension of Out@GRAD must equal to the first dimension of "
"the first operand."
);
PADDLE_ENFORCE_EQ
(
y_mat_dims
[
1
],
out_dims
[
1
],
"The second dimension of Out@GRAD must equal to the second "
"dimension of the second operand."
);
if
(
x_grad
)
x_grad
->
Resize
(
x_dims
);
if
(
y_grad
)
y_grad
->
Resize
(
y_dims
);
...
...
paddle/operators/mul_op.h
浏览文件 @
544458e0
/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.
Licensed under the Apache License, Version 2.0 (the "License");
y
ou may not use this file except in compliance with the License.
Y
ou 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
...
...
@@ -31,13 +31,25 @@ template <typename Place, typename T>
class
MulKernel
:
public
framework
::
OpKernel
{
public:
void
Compute
(
const
framework
::
ExecutionContext
&
context
)
const
override
{
auto
*
x
=
context
.
Input
<
Tensor
>
(
"X"
);
auto
*
y
=
context
.
Input
<
Tensor
>
(
"Y"
);
auto
*
z
=
context
.
Output
<
Tensor
>
(
"Out"
);
const
Tensor
*
x
=
context
.
Input
<
Tensor
>
(
"X"
);
const
Tensor
*
y
=
context
.
Input
<
Tensor
>
(
"Y"
);
Tensor
*
z
=
context
.
Output
<
Tensor
>
(
"Out"
);
const
Tensor
x_matrix
=
x
->
dims
().
size
()
>
2
?
framework
::
ReshapeToMatrix
<
T
>
(
*
x
,
context
.
template
Attr
<
int
>(
"x_num_col_dims"
))
:
*
x
;
const
Tensor
y_matrix
=
y
->
dims
().
size
()
>
2
?
framework
::
ReshapeToMatrix
<
T
>
(
*
y
,
context
.
template
Attr
<
int
>(
"y_num_col_dims"
))
:
*
y
;
z
->
mutable_data
<
T
>
(
context
.
GetPlace
());
auto
*
device_context
=
const_cast
<
platform
::
DeviceContext
*>
(
context
.
device_context_
);
math
::
matmul
<
Place
,
T
>
(
*
x
,
false
,
*
y
,
false
,
1
,
z
,
0
,
device_context
);
math
::
matmul
<
Place
,
T
>
(
x_matrix
,
false
,
y_matrix
,
false
,
1
,
z
,
0
,
device_context
);
}
};
...
...
@@ -45,23 +57,39 @@ template <typename Place, typename T>
class
MulGradKernel
:
public
framework
::
OpKernel
{
public:
void
Compute
(
const
framework
::
ExecutionContext
&
ctx
)
const
override
{
auto
*
x
=
ctx
.
Input
<
Tensor
>
(
"X"
);
auto
*
y
=
ctx
.
Input
<
Tensor
>
(
"Y"
);
auto
*
dout
=
ctx
.
Input
<
Tensor
>
(
framework
::
GradVarName
(
"Out"
));
int
x_num_col_dims
=
ctx
.
template
Attr
<
int
>(
"x_num_col_dims"
);
int
y_num_col_dims
=
ctx
.
template
Attr
<
int
>(
"y_num_col_dims"
);
const
Tensor
*
x
=
ctx
.
Input
<
Tensor
>
(
"X"
);
const
Tensor
*
y
=
ctx
.
Input
<
Tensor
>
(
"Y"
);
const
Tensor
x_matrix
=
x
->
dims
().
size
()
>
2
?
framework
::
ReshapeToMatrix
<
T
>
(
*
x
,
x_num_col_dims
)
:
*
x
;
const
Tensor
y_matrix
=
y
->
dims
().
size
()
>
2
?
framework
::
ReshapeToMatrix
<
T
>
(
*
y
,
y_num_col_dims
)
:
*
y
;
const
Tensor
*
dout
=
ctx
.
Input
<
Tensor
>
(
framework
::
GradVarName
(
"Out"
));
auto
*
dx
=
ctx
.
Output
<
Tensor
>
(
framework
::
GradVarName
(
"X"
));
auto
*
dy
=
ctx
.
Output
<
Tensor
>
(
framework
::
GradVarName
(
"Y"
));
Tensor
*
dx
=
ctx
.
Output
<
Tensor
>
(
framework
::
GradVarName
(
"X"
));
Tensor
*
dy
=
ctx
.
Output
<
Tensor
>
(
framework
::
GradVarName
(
"Y"
));
auto
*
device_context
=
const_cast
<
platform
::
DeviceContext
*>
(
ctx
.
device_context_
);
if
(
dx
)
{
dx
->
mutable_data
<
T
>
(
ctx
.
GetPlace
());
Tensor
dx_matrix
=
dx
->
dims
().
size
()
>
2
?
framework
::
ReshapeToMatrix
<
T
>
(
*
dx
,
x_num_col_dims
)
:
*
dx
;
// dx = dout * y'. dx: M x K, dout : M x N, y : K x N
math
::
matmul
<
Place
,
T
>
(
*
dout
,
false
,
*
y
,
true
,
1
,
dx
,
0
,
device_context
);
math
::
matmul
<
Place
,
T
>
(
*
dout
,
false
,
y_matrix
,
true
,
1
,
&
dx_matrix
,
0
,
device_context
);
}
if
(
dy
)
{
dy
->
mutable_data
<
T
>
(
ctx
.
GetPlace
());
Tensor
dy_matrix
=
dy
->
dims
().
size
()
>
2
?
framework
::
ReshapeToMatrix
<
T
>
(
*
dy
,
y_num_col_dims
)
:
*
dy
;
// dy = x' * dout. dy K x N, dout : M x N, x : M x K
math
::
matmul
<
Place
,
T
>
(
*
x
,
true
,
*
dout
,
false
,
1
,
dy
,
0
,
device_context
);
math
::
matmul
<
Place
,
T
>
(
x_matrix
,
true
,
*
dout
,
false
,
1
,
&
dy_matrix
,
0
,
device_context
);
}
}
};
...
...
paddle/operators/rowwise_add_op.cc
浏览文件 @
544458e0
...
...
@@ -25,14 +25,19 @@ class RowwiseAddOp : public framework::OperatorWithKernel {
protected:
void
InferShape
(
const
framework
::
InferShapeContext
&
ctx
)
const
override
{
auto
dim0
=
ctx
.
Input
<
Tensor
>
(
"X"
)
->
dims
();
auto
dim1
=
ctx
.
Input
<
Tensor
>
(
"b"
)
->
dims
();
PADDLE_ENFORCE
(
dim0
.
size
()
==
2
,
"Input 0 must be matrix"
);
PADDLE_ENFORCE
(
dim1
.
size
()
==
1
,
"The second input must be vector"
);
PADDLE_ENFORCE
(
dim0
[
1
]
==
dim1
[
0
],
"The width of two input must be same"
);
PADDLE_ENFORCE
(
ctx
.
OutputSize
(
"Out"
)
==
1
,
"The output size must be 1"
);
ctx
.
Output
<
Tensor
>
(
"Out"
)
->
Resize
(
ctx
.
Input
<
Tensor
>
(
"X"
)
->
dims
());
auto
x_dims
=
ctx
.
Input
<
Tensor
>
(
"X"
)
->
dims
();
auto
b_dims
=
ctx
.
Input
<
Tensor
>
(
"b"
)
->
dims
();
PADDLE_ENFORCE_GT
(
x_dims
.
size
(),
b_dims
.
size
(),
"The rank of input `X` must be larger than the one of input `b`."
);
int
num_col_dims
=
x_dims
.
size
()
-
b_dims
.
size
();
PADDLE_ENFORCE_EQ
(
framework
::
slice_ddim
(
x_dims
,
num_col_dims
,
x_dims
.
size
()),
b_dims
,
"The width of two operands must be same"
);
PADDLE_ENFORCE_EQ
(
ctx
.
OutputSize
(
"Out"
),
1
,
"The output size must be 1"
);
ctx
.
Output
<
Tensor
>
(
"Out"
)
->
Resize
(
x_dims
);
}
};
...
...
@@ -61,13 +66,20 @@ class RowwiseAddGradOp : public framework::OperatorWithKernel {
PADDLE_ENFORCE_NOT_NULL
(
ctx
.
InputVar
(
"b"
),
"b should not be null"
);
PADDLE_ENFORCE_NOT_NULL
(
ctx
.
InputVar
(
framework
::
GradVarName
(
"Out"
)),
"Input(Out@GRAD) should not be null"
);
auto
dims0
=
ctx
.
Input
<
Tensor
>
(
"X"
)
->
dims
();
auto
dims1
=
ctx
.
Input
<
Tensor
>
(
"b"
)
->
dims
();
PADDLE_ENFORCE_EQ
(
1
,
dims1
.
size
(),
"b dims should be 1"
)
auto
x_dims
=
ctx
.
Input
<
Tensor
>
(
"X"
)
->
dims
();
auto
b_dims
=
ctx
.
Input
<
Tensor
>
(
"b"
)
->
dims
();
PADDLE_ENFORCE_GT
(
x_dims
.
size
(),
b_dims
.
size
(),
"The rank of input `X` must be larger than the one of input `b`."
);
int
num_col_dims
=
x_dims
.
size
()
-
b_dims
.
size
();
PADDLE_ENFORCE_EQ
(
framework
::
slice_ddim
(
x_dims
,
num_col_dims
,
x_dims
.
size
()),
b_dims
,
"The width of two operands must be same"
);
auto
*
dx
=
ctx
.
Output
<
Tensor
>
(
framework
::
GradVarName
(
"X"
));
auto
*
db
=
ctx
.
Output
<
Tensor
>
(
framework
::
GradVarName
(
"b"
));
if
(
dx
)
dx
->
Resize
(
dims0
);
if
(
db
)
db
->
Resize
(
dims1
);
if
(
dx
)
dx
->
Resize
(
x_dims
);
if
(
db
)
db
->
Resize
(
b_dims
);
}
};
...
...
paddle/operators/rowwise_add_op.h
浏览文件 @
544458e0
...
...
@@ -33,10 +33,12 @@ class RowwiseAddKernel : public framework::OpKernel {
void
Compute
(
const
framework
::
ExecutionContext
&
context
)
const
override
{
auto
out
=
context
.
Output
<
Tensor
>
(
"Out"
);
out
->
mutable_data
<
T
>
(
context
.
GetPlace
());
auto
input
=
EigenMatrix
<
T
>::
From
(
*
context
.
Input
<
Tensor
>
(
"X"
));
auto
bias
=
EigenVector
<
T
>::
From
(
*
context
.
Input
<
Tensor
>
(
"b"
));
auto
output
=
EigenMatrix
<
T
>::
From
(
*
out
);
int
num_col_dims
=
context
.
Input
<
Tensor
>
(
"X"
)
->
dims
().
size
()
-
context
.
Input
<
Tensor
>
(
"b"
)
->
dims
().
size
();
auto
input
=
EigenMatrix
<
T
>::
Reshape
(
*
context
.
Input
<
Tensor
>
(
"X"
),
num_col_dims
);
auto
bias
=
EigenVector
<
T
>::
Flatten
(
*
context
.
Input
<
Tensor
>
(
"b"
));
auto
output
=
EigenMatrix
<
T
>::
Reshape
(
*
out
,
num_col_dims
);
const
int
bias_size
=
bias
.
dimension
(
0
);
const
int
rest_size
=
input
.
size
()
/
bias_size
;
...
...
@@ -54,12 +56,15 @@ class RowwiseAddGradKernel : public framework::OpKernel {
auto
*
dout
=
context
.
Input
<
Tensor
>
(
framework
::
GradVarName
(
"Out"
));
auto
*
dx
=
context
.
Output
<
Tensor
>
(
framework
::
GradVarName
(
"X"
));
auto
*
db
=
context
.
Output
<
Tensor
>
(
framework
::
GradVarName
(
"b"
));
int
num_col_dims
=
context
.
Input
<
Tensor
>
(
"X"
)
->
dims
().
size
()
-
context
.
Input
<
Tensor
>
(
"b"
)
->
dims
().
size
();
auto
out_grad
=
EigenMatrix
<
T
>::
From
(
*
dout
);
auto
out_grad
=
EigenMatrix
<
T
>::
Reshape
(
*
dout
,
num_col_dims
);
auto
place
=
context
.
GetEigenDevice
<
Place
>
();
if
(
dx
)
{
dx
->
mutable_data
<
T
>
(
context
.
GetPlace
());
EigenMatrix
<
T
>::
From
(
*
dx
).
device
(
place
)
=
out_grad
;
EigenMatrix
<
T
>::
Reshape
(
*
dx
,
num_col_dims
).
device
(
place
)
=
out_grad
;
}
if
(
db
)
{
...
...
python/paddle/v2/framework/tests/test_mul_op.py
浏览文件 @
544458e0
...
...
@@ -2,6 +2,7 @@ import unittest
import
numpy
as
np
from
gradient_checker
import
GradientChecker
,
create_op
from
op_test_util
import
OpTestMeta
from
paddle.v2.framework.op
import
Operator
class
TestMulOp
(
unittest
.
TestCase
):
...
...
@@ -16,6 +17,22 @@ class TestMulOp(unittest.TestCase):
self
.
outputs
=
{
'Out'
:
np
.
dot
(
self
.
inputs
[
'X'
],
self
.
inputs
[
'Y'
])}
class
TestMulOp2
(
unittest
.
TestCase
):
__metaclass__
=
OpTestMeta
def
setUp
(
self
):
self
.
type
=
"mul"
self
.
inputs
=
{
'X'
:
np
.
random
.
random
((
15
,
4
,
12
,
10
)).
astype
(
"float32"
),
'Y'
:
np
.
random
.
random
((
4
,
30
,
8
,
2
,
9
)).
astype
(
"float32"
)
}
self
.
attrs
=
{
'x_num_col_dims'
:
2
,
'y_num_col_dims'
:
2
}
self
.
outputs
=
{
'Out'
:
np
.
dot
(
self
.
inputs
[
'X'
].
reshape
(
15
*
4
,
12
*
10
),
self
.
inputs
[
'Y'
].
reshape
(
4
*
30
,
8
*
2
*
9
))
}
class
TestMulGradOp
(
GradientChecker
):
def
setUp
(
self
):
self
.
op
=
create_op
(
"mul"
)
...
...
@@ -49,7 +66,38 @@ class TestMulGradOp(GradientChecker):
no_grad_set
=
{
"Y"
})
# TODO(dzh,qijun) : mulgrad test case need transpose feature of blas library
class
TestMulGradTest2
(
GradientChecker
):
def
setUp
(
self
):
self
.
op
=
Operator
(
"mul"
,
X
=
"X"
,
Y
=
"Y"
,
Out
=
"Out"
,
x_num_col_dims
=
2
,
y_num_col_dims
=
2
)
self
.
inputs
=
{
"X"
:
np
.
random
.
random
((
15
,
4
,
12
,
10
)).
astype
(
"float32"
),
"Y"
:
np
.
random
.
random
((
4
,
30
,
8
,
2
,
9
)).
astype
(
"float32"
)
}
def
test_cpu_gpu_compare
(
self
):
self
.
compare_grad
(
self
.
op
,
self
.
inputs
)
def
test_normal
(
self
):
self
.
check_grad
(
self
.
op
,
self
.
inputs
,
[
"X"
,
"Y"
],
"Out"
,
max_relative_error
=
0.5
)
def
test_ignore_x
(
self
):
self
.
check_grad
(
self
.
op
,
self
.
inputs
,
[
"Y"
],
"Out"
,
max_relative_error
=
0.5
,
no_grad_set
=
{
"X"
})
def
test_ignore_y
(
self
):
self
.
check_grad
(
self
.
op
,
self
.
inputs
,
[
"X"
],
"Out"
,
max_relative_error
=
0.5
,
no_grad_set
=
{
"Y"
})
if
__name__
==
'__main__'
:
unittest
.
main
()
python/paddle/v2/framework/tests/test_rowwise_add_op.py
浏览文件 @
544458e0
...
...
@@ -16,6 +16,18 @@ class TestRowwiseAddOp(unittest.TestCase):
self
.
outputs
=
{
'Out'
:
np
.
add
(
self
.
inputs
[
'X'
],
self
.
inputs
[
'b'
])}
class
TestRowwiseAddOp2
(
unittest
.
TestCase
):
__metaclass__
=
OpTestMeta
def
setUp
(
self
):
self
.
type
=
"rowwise_add"
self
.
inputs
=
{
'X'
:
np
.
random
.
random
((
13
,
6
,
7
,
8
)).
astype
(
"float32"
),
'b'
:
np
.
random
.
random
((
7
,
8
)).
astype
(
"float32"
)
}
self
.
outputs
=
{
'Out'
:
np
.
add
(
self
.
inputs
[
'X'
],
self
.
inputs
[
'b'
])}
class
TestRowwiseAddGradOp
(
GradientChecker
):
def
setUp
(
self
):
self
.
op
=
create_op
(
"rowwise_add"
)
...
...
@@ -34,5 +46,23 @@ class TestRowwiseAddGradOp(GradientChecker):
self
.
check_grad
(
self
.
op
,
self
.
inputs
,
[
"b"
],
"Out"
,
no_grad_set
=
{
"X"
})
class
TestRowwiseAddGradOp2
(
GradientChecker
):
def
setUp
(
self
):
self
.
op
=
create_op
(
"rowwise_add"
)
self
.
inputs
=
{
"X"
:
np
.
random
.
uniform
(
0.1
,
1
,
[
2
,
3
,
2
,
5
]).
astype
(
"float32"
),
"b"
:
np
.
random
.
uniform
(
0.1
,
1
,
[
2
,
5
]).
astype
(
"float32"
)
}
def
test_normal
(
self
):
self
.
check_grad
(
self
.
op
,
self
.
inputs
,
[
"X"
,
"b"
],
"Out"
)
def
test_ignore_b
(
self
):
self
.
check_grad
(
self
.
op
,
self
.
inputs
,
[
"X"
],
"Out"
,
no_grad_set
=
{
"b"
})
def
test_ignore_x
(
self
):
self
.
check_grad
(
self
.
op
,
self
.
inputs
,
[
"b"
],
"Out"
,
no_grad_set
=
{
"X"
})
if
__name__
==
'__main__'
:
unittest
.
main
()
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录