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 {
...
@@ -45,7 +45,19 @@ class GreaterThanChecker {
public:
public:
explicit
GreaterThanChecker
(
T
lower_bound
)
:
lower_bound_
(
lower_bound
)
{}
explicit
GreaterThanChecker
(
T
lower_bound
)
:
lower_bound_
(
lower_bound
)
{}
void
operator
()(
T
&
value
)
const
{
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:
private:
...
@@ -115,6 +127,11 @@ class TypedAttrChecker {
...
@@ -115,6 +127,11 @@ class TypedAttrChecker {
return
*
this
;
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()...
// we can add more common limits, like LessThan(), Between()...
TypedAttrChecker
&
SetDefault
(
const
T
&
default_value
)
{
TypedAttrChecker
&
SetDefault
(
const
T
&
default_value
)
{
...
...
paddle/framework/ddim.cc
浏览文件 @
544458e0
...
@@ -283,5 +283,14 @@ std::ostream& operator<<(std::ostream& os, const DDim& ddim) {
...
@@ -283,5 +283,14 @@ std::ostream& operator<<(std::ostream& os, const DDim& ddim) {
DDim
::
DDim
(
std
::
initializer_list
<
int64_t
>
init_list
)
{
DDim
::
DDim
(
std
::
initializer_list
<
int64_t
>
init_list
)
{
*
this
=
make_ddim
(
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 framework
}
// namespace paddle
}
// namespace paddle
paddle/framework/ddim.h
浏览文件 @
544458e0
...
@@ -115,6 +115,12 @@ int arity(const DDim& ddim);
...
@@ -115,6 +115,12 @@ int arity(const DDim& ddim);
std
::
ostream
&
operator
<<
(
std
::
ostream
&
,
const
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 framework
}
// namespace paddle
}
// namespace paddle
...
...
paddle/framework/eigen.h
浏览文件 @
544458e0
...
@@ -63,20 +63,35 @@ struct EigenTensor {
...
@@ -63,20 +63,35 @@ struct EigenTensor {
template
<
typename
T
,
int
MajorType
=
Eigen
::
RowMajor
,
template
<
typename
T
,
int
MajorType
=
Eigen
::
RowMajor
,
typename
IndexType
=
Eigen
::
DenseIndex
>
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
,
template
<
typename
T
,
int
MajorType
=
Eigen
::
RowMajor
,
typename
IndexType
=
Eigen
::
DenseIndex
>
typename
IndexType
=
Eigen
::
DenseIndex
>
struct
EigenVector
:
public
EigenTensor
<
T
,
1
,
MajorType
,
IndexType
>
{
struct
EigenVector
:
public
EigenTensor
<
T
,
1
,
MajorType
,
IndexType
>
{
// Flatten reshapes a Tensor into an EigenVector.
// Flatten reshapes a Tensor into an EigenVector.
static
typename
EigenVector
::
Type
Flatten
(
Tensor
&
tensor
)
{
static
typename
EigenVector
::
Type
Flatten
(
Tensor
&
tensor
)
{
return
EigenVector
::
From
(
return
EigenVector
::
From
(
tensor
,
{
product
(
tensor
.
dims_
)});
tensor
,
make_ddim
({
static_cast
<
int
>
(
product
(
tensor
.
dims_
))}));
}
}
static
typename
EigenVector
::
ConstType
Flatten
(
const
Tensor
&
tensor
)
{
static
typename
EigenVector
::
ConstType
Flatten
(
const
Tensor
&
tensor
)
{
return
EigenVector
::
From
(
return
EigenVector
::
From
(
tensor
,
{
product
(
tensor
.
dims_
)});
tensor
,
make_ddim
({
static_cast
<
int
>
(
product
(
tensor
.
dims_
))}));
}
}
};
};
...
...
paddle/framework/eigen_test.cc
浏览文件 @
544458e0
...
@@ -108,5 +108,24 @@ TEST(Eigen, Matrix) {
...
@@ -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 framework
}
// namespace paddle
}
// namespace paddle
paddle/framework/tensor.h
浏览文件 @
544458e0
...
@@ -43,6 +43,9 @@ class Tensor {
...
@@ -43,6 +43,9 @@ class Tensor {
template
<
typename
T
,
size_t
D
,
int
MajorType
,
typename
IndexType
>
template
<
typename
T
,
size_t
D
,
int
MajorType
,
typename
IndexType
>
friend
struct
EigenTensor
;
friend
struct
EigenTensor
;
template
<
typename
T
,
int
MajorType
,
typename
IndexType
>
friend
struct
EigenMatrix
;
template
<
typename
T
,
int
MajorType
,
typename
IndexType
>
template
<
typename
T
,
int
MajorType
,
typename
IndexType
>
friend
struct
EigenVector
;
friend
struct
EigenVector
;
...
...
paddle/framework/tensor_impl.h
浏览文件 @
544458e0
...
@@ -148,5 +148,13 @@ inline Tensor& Tensor::Resize(const DDim& dims) {
...
@@ -148,5 +148,13 @@ inline Tensor& Tensor::Resize(const DDim& dims) {
inline
const
DDim
&
Tensor
::
dims
()
const
{
return
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 framework
}
// namespace paddle
}
// namespace paddle
paddle/framework/tensor_test.cc
浏览文件 @
544458e0
...
@@ -262,3 +262,16 @@ TEST(Tensor, CopyFrom) {
...
@@ -262,3 +262,16 @@ TEST(Tensor, CopyFrom) {
}
}
#endif
#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 {
...
@@ -25,18 +25,27 @@ class MulOp : public framework::OperatorWithKernel {
protected:
protected:
void
InferShape
(
const
framework
::
InferShapeContext
&
ctx
)
const
override
{
void
InferShape
(
const
framework
::
InferShapeContext
&
ctx
)
const
override
{
auto
dim0
=
ctx
.
Input
<
Tensor
>
(
"X"
)
->
dims
();
auto
x_dims
=
ctx
.
Input
<
Tensor
>
(
"X"
)
->
dims
();
auto
dim1
=
ctx
.
Input
<
Tensor
>
(
"Y"
)
->
dims
();
auto
y_dims
=
ctx
.
Input
<
Tensor
>
(
"Y"
)
->
dims
();
PADDLE_ENFORCE_EQ
(
dim0
.
size
(),
2
,
int
x_num_col_dims
=
Attr
<
int
>
(
"x_num_col_dims"
);
"input X(%s) should be a tensor with 2 dims, a matrix"
,
int
y_num_col_dims
=
Attr
<
int
>
(
"y_num_col_dims"
);
ctx
.
op
().
Input
(
"X"
));
PADDLE_ENFORCE_EQ
(
dim1
.
size
(),
2
,
PADDLE_ENFORCE
(
x_dims
.
size
()
>
x_num_col_dims
,
"input Y(%s) should be a tensor with 2 dims, a matrix"
,
"The rank of input tensor X(%s) should be larger than "
ctx
.
op
().
Input
(
"Y"
));
"`mul_op`'s `x_num_col_dims`."
,
ctx
.
op
().
Input
(
"X"
));
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
(
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."
);
"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 {
...
@@ -47,6 +56,23 @@ class MulOpMaker : public framework::OpProtoAndCheckerMaker {
AddInput
(
"X"
,
"The first input of mul op"
);
AddInput
(
"X"
,
"The first input of mul op"
);
AddInput
(
"Y"
,
"The second input of mul op"
);
AddInput
(
"Y"
,
"The second input of mul op"
);
AddOutput
(
"Out"
,
"The output 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(
AddComment
(
R"DOC(
Two Element Mul Operator.
Two Element Mul Operator.
...
@@ -70,10 +96,20 @@ class MulOpGrad : public framework::OperatorWithKernel {
...
@@ -70,10 +96,20 @@ class MulOpGrad : public framework::OperatorWithKernel {
auto
out_dims
=
ctx
.
Input
<
Tensor
>
(
framework
::
GradVarName
(
"Out"
))
->
dims
();
auto
out_dims
=
ctx
.
Input
<
Tensor
>
(
framework
::
GradVarName
(
"Out"
))
->
dims
();
auto
*
x_grad
=
ctx
.
Output
<
Tensor
>
(
framework
::
GradVarName
(
"X"
));
auto
*
x_grad
=
ctx
.
Output
<
Tensor
>
(
framework
::
GradVarName
(
"X"
));
auto
*
y_grad
=
ctx
.
Output
<
Tensor
>
(
framework
::
GradVarName
(
"Y"
));
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 "
);
auto
x_mat_dims
=
PADDLE_ENFORCE
(
y_dims
[
1
]
==
out_dims
[
1
],
framework
::
flatten_to_2d
(
x_dims
,
Attr
<
int
>
(
"x_num_col_dims"
));
"Out@GRAD M X N must equal to Y dims 1, N "
);
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
(
x_grad
)
x_grad
->
Resize
(
x_dims
);
if
(
y_grad
)
y_grad
->
Resize
(
y_dims
);
if
(
y_grad
)
y_grad
->
Resize
(
y_dims
);
...
...
paddle/operators/mul_op.h
浏览文件 @
544458e0
/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.
/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.
Licensed under the Apache License, Version 2.0 (the "License");
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
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
http://www.apache.org/licenses/LICENSE-2.0
...
@@ -31,13 +31,25 @@ template <typename Place, typename T>
...
@@ -31,13 +31,25 @@ template <typename Place, typename T>
class
MulKernel
:
public
framework
::
OpKernel
{
class
MulKernel
:
public
framework
::
OpKernel
{
public:
public:
void
Compute
(
const
framework
::
ExecutionContext
&
context
)
const
override
{
void
Compute
(
const
framework
::
ExecutionContext
&
context
)
const
override
{
auto
*
x
=
context
.
Input
<
Tensor
>
(
"X"
);
const
Tensor
*
x
=
context
.
Input
<
Tensor
>
(
"X"
);
auto
*
y
=
context
.
Input
<
Tensor
>
(
"Y"
);
const
Tensor
*
y
=
context
.
Input
<
Tensor
>
(
"Y"
);
auto
*
z
=
context
.
Output
<
Tensor
>
(
"Out"
);
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
());
z
->
mutable_data
<
T
>
(
context
.
GetPlace
());
auto
*
device_context
=
auto
*
device_context
=
const_cast
<
platform
::
DeviceContext
*>
(
context
.
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>
...
@@ -45,23 +57,39 @@ template <typename Place, typename T>
class
MulGradKernel
:
public
framework
::
OpKernel
{
class
MulGradKernel
:
public
framework
::
OpKernel
{
public:
public:
void
Compute
(
const
framework
::
ExecutionContext
&
ctx
)
const
override
{
void
Compute
(
const
framework
::
ExecutionContext
&
ctx
)
const
override
{
auto
*
x
=
ctx
.
Input
<
Tensor
>
(
"X"
);
int
x_num_col_dims
=
ctx
.
template
Attr
<
int
>(
"x_num_col_dims"
);
auto
*
y
=
ctx
.
Input
<
Tensor
>
(
"Y"
);
int
y_num_col_dims
=
ctx
.
template
Attr
<
int
>(
"y_num_col_dims"
);
auto
*
dout
=
ctx
.
Input
<
Tensor
>
(
framework
::
GradVarName
(
"Out"
));
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"
));
Tensor
*
dx
=
ctx
.
Output
<
Tensor
>
(
framework
::
GradVarName
(
"X"
));
auto
*
dy
=
ctx
.
Output
<
Tensor
>
(
framework
::
GradVarName
(
"Y"
));
Tensor
*
dy
=
ctx
.
Output
<
Tensor
>
(
framework
::
GradVarName
(
"Y"
));
auto
*
device_context
=
auto
*
device_context
=
const_cast
<
platform
::
DeviceContext
*>
(
ctx
.
device_context_
);
const_cast
<
platform
::
DeviceContext
*>
(
ctx
.
device_context_
);
if
(
dx
)
{
if
(
dx
)
{
dx
->
mutable_data
<
T
>
(
ctx
.
GetPlace
());
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
// 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
)
{
if
(
dy
)
{
dy
->
mutable_data
<
T
>
(
ctx
.
GetPlace
());
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
// 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 {
...
@@ -25,14 +25,19 @@ class RowwiseAddOp : public framework::OperatorWithKernel {
protected:
protected:
void
InferShape
(
const
framework
::
InferShapeContext
&
ctx
)
const
override
{
void
InferShape
(
const
framework
::
InferShapeContext
&
ctx
)
const
override
{
auto
dim0
=
ctx
.
Input
<
Tensor
>
(
"X"
)
->
dims
();
auto
x_dims
=
ctx
.
Input
<
Tensor
>
(
"X"
)
->
dims
();
auto
dim1
=
ctx
.
Input
<
Tensor
>
(
"b"
)
->
dims
();
auto
b_dims
=
ctx
.
Input
<
Tensor
>
(
"b"
)
->
dims
();
PADDLE_ENFORCE_GT
(
PADDLE_ENFORCE
(
dim0
.
size
()
==
2
,
"Input 0 must be matrix"
);
x_dims
.
size
(),
b_dims
.
size
(),
PADDLE_ENFORCE
(
dim1
.
size
()
==
1
,
"The second input must be vector"
);
"The rank of input `X` must be larger than the one of input `b`."
);
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"
);
int
num_col_dims
=
x_dims
.
size
()
-
b_dims
.
size
();
ctx
.
Output
<
Tensor
>
(
"Out"
)
->
Resize
(
ctx
.
Input
<
Tensor
>
(
"X"
)
->
dims
());
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 {
...
@@ -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
(
"b"
),
"b should not be null"
);
PADDLE_ENFORCE_NOT_NULL
(
ctx
.
InputVar
(
framework
::
GradVarName
(
"Out"
)),
PADDLE_ENFORCE_NOT_NULL
(
ctx
.
InputVar
(
framework
::
GradVarName
(
"Out"
)),
"Input(Out@GRAD) should not be null"
);
"Input(Out@GRAD) should not be null"
);
auto
dims0
=
ctx
.
Input
<
Tensor
>
(
"X"
)
->
dims
();
auto
x_dims
=
ctx
.
Input
<
Tensor
>
(
"X"
)
->
dims
();
auto
dims1
=
ctx
.
Input
<
Tensor
>
(
"b"
)
->
dims
();
auto
b_dims
=
ctx
.
Input
<
Tensor
>
(
"b"
)
->
dims
();
PADDLE_ENFORCE_EQ
(
1
,
dims1
.
size
(),
"b dims should be 1"
)
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
*
dx
=
ctx
.
Output
<
Tensor
>
(
framework
::
GradVarName
(
"X"
));
auto
*
db
=
ctx
.
Output
<
Tensor
>
(
framework
::
GradVarName
(
"b"
));
auto
*
db
=
ctx
.
Output
<
Tensor
>
(
framework
::
GradVarName
(
"b"
));
if
(
dx
)
dx
->
Resize
(
dims0
);
if
(
dx
)
dx
->
Resize
(
x_dims
);
if
(
db
)
db
->
Resize
(
dims1
);
if
(
db
)
db
->
Resize
(
b_dims
);
}
}
};
};
...
...
paddle/operators/rowwise_add_op.h
浏览文件 @
544458e0
...
@@ -33,10 +33,12 @@ class RowwiseAddKernel : public framework::OpKernel {
...
@@ -33,10 +33,12 @@ class RowwiseAddKernel : public framework::OpKernel {
void
Compute
(
const
framework
::
ExecutionContext
&
context
)
const
override
{
void
Compute
(
const
framework
::
ExecutionContext
&
context
)
const
override
{
auto
out
=
context
.
Output
<
Tensor
>
(
"Out"
);
auto
out
=
context
.
Output
<
Tensor
>
(
"Out"
);
out
->
mutable_data
<
T
>
(
context
.
GetPlace
());
out
->
mutable_data
<
T
>
(
context
.
GetPlace
());
int
num_col_dims
=
context
.
Input
<
Tensor
>
(
"X"
)
->
dims
().
size
()
-
auto
input
=
EigenMatrix
<
T
>::
From
(
*
context
.
Input
<
Tensor
>
(
"X"
));
context
.
Input
<
Tensor
>
(
"b"
)
->
dims
().
size
();
auto
bias
=
EigenVector
<
T
>::
From
(
*
context
.
Input
<
Tensor
>
(
"b"
));
auto
input
=
auto
output
=
EigenMatrix
<
T
>::
From
(
*
out
);
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
bias_size
=
bias
.
dimension
(
0
);
const
int
rest_size
=
input
.
size
()
/
bias_size
;
const
int
rest_size
=
input
.
size
()
/
bias_size
;
...
@@ -54,12 +56,15 @@ class RowwiseAddGradKernel : public framework::OpKernel {
...
@@ -54,12 +56,15 @@ class RowwiseAddGradKernel : public framework::OpKernel {
auto
*
dout
=
context
.
Input
<
Tensor
>
(
framework
::
GradVarName
(
"Out"
));
auto
*
dout
=
context
.
Input
<
Tensor
>
(
framework
::
GradVarName
(
"Out"
));
auto
*
dx
=
context
.
Output
<
Tensor
>
(
framework
::
GradVarName
(
"X"
));
auto
*
dx
=
context
.
Output
<
Tensor
>
(
framework
::
GradVarName
(
"X"
));
auto
*
db
=
context
.
Output
<
Tensor
>
(
framework
::
GradVarName
(
"b"
));
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
>
();
auto
place
=
context
.
GetEigenDevice
<
Place
>
();
if
(
dx
)
{
if
(
dx
)
{
dx
->
mutable_data
<
T
>
(
context
.
GetPlace
());
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
)
{
if
(
db
)
{
...
...
python/paddle/v2/framework/tests/test_mul_op.py
浏览文件 @
544458e0
...
@@ -2,6 +2,7 @@ import unittest
...
@@ -2,6 +2,7 @@ import unittest
import
numpy
as
np
import
numpy
as
np
from
gradient_checker
import
GradientChecker
,
create_op
from
gradient_checker
import
GradientChecker
,
create_op
from
op_test_util
import
OpTestMeta
from
op_test_util
import
OpTestMeta
from
paddle.v2.framework.op
import
Operator
class
TestMulOp
(
unittest
.
TestCase
):
class
TestMulOp
(
unittest
.
TestCase
):
...
@@ -16,6 +17,22 @@ class TestMulOp(unittest.TestCase):
...
@@ -16,6 +17,22 @@ class TestMulOp(unittest.TestCase):
self
.
outputs
=
{
'Out'
:
np
.
dot
(
self
.
inputs
[
'X'
],
self
.
inputs
[
'Y'
])}
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
):
class
TestMulGradOp
(
GradientChecker
):
def
setUp
(
self
):
def
setUp
(
self
):
self
.
op
=
create_op
(
"mul"
)
self
.
op
=
create_op
(
"mul"
)
...
@@ -49,7 +66,38 @@ class TestMulGradOp(GradientChecker):
...
@@ -49,7 +66,38 @@ class TestMulGradOp(GradientChecker):
no_grad_set
=
{
"Y"
})
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__'
:
if
__name__
==
'__main__'
:
unittest
.
main
()
unittest
.
main
()
python/paddle/v2/framework/tests/test_rowwise_add_op.py
浏览文件 @
544458e0
...
@@ -16,6 +16,18 @@ class TestRowwiseAddOp(unittest.TestCase):
...
@@ -16,6 +16,18 @@ class TestRowwiseAddOp(unittest.TestCase):
self
.
outputs
=
{
'Out'
:
np
.
add
(
self
.
inputs
[
'X'
],
self
.
inputs
[
'b'
])}
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
):
class
TestRowwiseAddGradOp
(
GradientChecker
):
def
setUp
(
self
):
def
setUp
(
self
):
self
.
op
=
create_op
(
"rowwise_add"
)
self
.
op
=
create_op
(
"rowwise_add"
)
...
@@ -34,5 +46,23 @@ class TestRowwiseAddGradOp(GradientChecker):
...
@@ -34,5 +46,23 @@ class TestRowwiseAddGradOp(GradientChecker):
self
.
check_grad
(
self
.
op
,
self
.
inputs
,
[
"b"
],
"Out"
,
no_grad_set
=
{
"X"
})
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__'
:
if
__name__
==
'__main__'
:
unittest
.
main
()
unittest
.
main
()
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录