Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
BaiXuePrincess
Paddle
提交
d3c29e9d
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看板
提交
d3c29e9d
编写于
8月 21, 2017
作者:
Z
zchen0211
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'develop' of
https://github.com/PaddlePaddle/Paddle
into develop
上级
78553768
b7a6cc9c
变更
24
显示空白变更内容
内联
并排
Showing
24 changed file
with
602 addition
and
134 deletion
+602
-134
CMakeLists.txt
CMakeLists.txt
+1
-0
cmake/configure.cmake
cmake/configure.cmake
+4
-0
cmake/cudnn.cmake
cmake/cudnn.cmake
+1
-1
doc/api/v2/config/layer.rst
doc/api/v2/config/layer.rst
+5
-0
paddle/function/CMakeLists.txt
paddle/function/CMakeLists.txt
+4
-0
paddle/function/DepthwiseConvOp.cpp
paddle/function/DepthwiseConvOp.cpp
+0
-1
paddle/function/DepthwiseConvOpGpu.cu
paddle/function/DepthwiseConvOpGpu.cu
+0
-1
paddle/function/EigenGemm.cpp
paddle/function/EigenGemm.cpp
+91
-0
paddle/function/GemmConvOp.cpp
paddle/function/GemmConvOp.cpp
+39
-43
paddle/function/GemmFunctor.cpp
paddle/function/GemmFunctor.cpp
+90
-0
paddle/function/GemmFunctor.h
paddle/function/GemmFunctor.h
+34
-65
paddle/gserver/layers/ScaleShiftLayer.cpp
paddle/gserver/layers/ScaleShiftLayer.cpp
+107
-0
paddle/gserver/tests/test_LayerGrad.cpp
paddle/gserver/tests/test_LayerGrad.cpp
+15
-0
paddle/gserver/tests/test_NetworkCompare.cpp
paddle/gserver/tests/test_NetworkCompare.cpp
+2
-1
paddle/operators/math/math_function.cc
paddle/operators/math/math_function.cc
+4
-4
paddle/operators/mul_op.cc
paddle/operators/mul_op.cc
+21
-4
paddle/operators/mul_op.cu
paddle/operators/mul_op.cu
+2
-0
paddle/operators/mul_op.h
paddle/operators/mul_op.h
+28
-12
python/paddle/trainer/config_parser.py
python/paddle/trainer/config_parser.py
+14
-0
python/paddle/trainer_config_helpers/layers.py
python/paddle/trainer_config_helpers/layers.py
+42
-0
python/paddle/trainer_config_helpers/tests/configs/file_list.sh
.../paddle/trainer_config_helpers/tests/configs/file_list.sh
+1
-1
python/paddle/trainer_config_helpers/tests/configs/protostr/test_scale_shift_layer.protostr
...rs/tests/configs/protostr/test_scale_shift_layer.protostr
+72
-0
python/paddle/trainer_config_helpers/tests/configs/test_scale_shift_layer.py
...er_config_helpers/tests/configs/test_scale_shift_layer.py
+9
-0
python/paddle/v2/framework/tests/test_mul_op.py
python/paddle/v2/framework/tests/test_mul_op.py
+16
-1
未找到文件。
CMakeLists.txt
浏览文件 @
d3c29e9d
...
@@ -55,6 +55,7 @@ option(WITH_C_API "Compile PaddlePaddle with C-API(Prediction)" OFF)
...
@@ -55,6 +55,7 @@ option(WITH_C_API "Compile PaddlePaddle with C-API(Prediction)" OFF)
option
(
WITH_GOLANG
"Compile PaddlePaddle with GOLANG"
OFF
)
option
(
WITH_GOLANG
"Compile PaddlePaddle with GOLANG"
OFF
)
option
(
GLIDE_INSTALL
"Download and install go dependencies "
ON
)
option
(
GLIDE_INSTALL
"Download and install go dependencies "
ON
)
option
(
USE_NNPACK
"Compile PaddlePaddle with NNPACK library"
OFF
)
option
(
USE_NNPACK
"Compile PaddlePaddle with NNPACK library"
OFF
)
option
(
USE_EIGEN_FOR_BLAS
"Use matrix multiplication in Eigen"
OFF
)
# CMAKE_BUILD_TYPE
# CMAKE_BUILD_TYPE
if
(
NOT CMAKE_BUILD_TYPE
)
if
(
NOT CMAKE_BUILD_TYPE
)
...
...
cmake/configure.cmake
浏览文件 @
d3c29e9d
...
@@ -28,6 +28,10 @@ if(NOT WITH_TIMER)
...
@@ -28,6 +28,10 @@ if(NOT WITH_TIMER)
add_definitions
(
-DPADDLE_DISABLE_TIMER
)
add_definitions
(
-DPADDLE_DISABLE_TIMER
)
endif
(
NOT WITH_TIMER
)
endif
(
NOT WITH_TIMER
)
if
(
USE_EIGEN_FOR_BLAS
)
add_definitions
(
-DPADDLE_USE_EIGEN_FOR_BLAS
)
endif
(
USE_EIGEN_FOR_BLAS
)
if
(
NOT WITH_PROFILER
)
if
(
NOT WITH_PROFILER
)
add_definitions
(
-DPADDLE_DISABLE_PROFILER
)
add_definitions
(
-DPADDLE_DISABLE_PROFILER
)
endif
(
NOT WITH_PROFILER
)
endif
(
NOT WITH_PROFILER
)
...
...
cmake/cudnn.cmake
浏览文件 @
d3c29e9d
...
@@ -2,7 +2,7 @@ if(NOT WITH_GPU)
...
@@ -2,7 +2,7 @@ if(NOT WITH_GPU)
return
()
return
()
endif
()
endif
()
set
(
CUDNN_ROOT
""
CACHE PATH
"CUDNN ROOT"
)
set
(
CUDNN_ROOT
"
/usr
"
CACHE PATH
"CUDNN ROOT"
)
find_path
(
CUDNN_INCLUDE_DIR cudnn.h
find_path
(
CUDNN_INCLUDE_DIR cudnn.h
PATHS
${
CUDNN_ROOT
}
${
CUDNN_ROOT
}
/include
PATHS
${
CUDNN_ROOT
}
${
CUDNN_ROOT
}
/include
$ENV{CUDNN_ROOT} $ENV{CUDNN_ROOT}/include
${
CUDA_TOOLKIT_INCLUDE
}
$ENV{CUDNN_ROOT} $ENV{CUDNN_ROOT}/include
${
CUDA_TOOLKIT_INCLUDE
}
...
...
doc/api/v2/config/layer.rst
浏览文件 @
d3c29e9d
...
@@ -362,6 +362,11 @@ trans
...
@@ -362,6 +362,11 @@ trans
.. autoclass:: paddle.v2.layer.trans
.. autoclass:: paddle.v2.layer.trans
:noindex:
:noindex:
scale_shift
-----------
.. autoclass:: paddle.v2.layer.scale_shift
:noindex:
Sampling Layers
Sampling Layers
===============
===============
...
...
paddle/function/CMakeLists.txt
浏览文件 @
d3c29e9d
...
@@ -4,6 +4,10 @@ file(GLOB cpp_files . *Op.cpp)
...
@@ -4,6 +4,10 @@ file(GLOB cpp_files . *Op.cpp)
list
(
APPEND h_files Function.h
)
list
(
APPEND h_files Function.h
)
list
(
APPEND cpp_files Function.cpp
)
list
(
APPEND cpp_files Function.cpp
)
list
(
APPEND cpp_files BufferArg.cpp
)
list
(
APPEND cpp_files BufferArg.cpp
)
list
(
APPEND cpp_files GemmFunctor.cpp
)
if
(
USE_EIGEN_FOR_BLAS
)
list
(
APPEND cpp_files EigenGemm.cpp
)
endif
(
USE_EIGEN_FOR_BLAS
)
if
(
WITH_GPU
)
if
(
WITH_GPU
)
file
(
GLOB cu_files . *OpGpu.cu
)
file
(
GLOB cu_files . *OpGpu.cu
)
...
...
paddle/function/DepthwiseConvOp.cpp
浏览文件 @
d3c29e9d
...
@@ -14,7 +14,6 @@ limitations under the License. */
...
@@ -14,7 +14,6 @@ limitations under the License. */
#include "DepthwiseConvOp.h"
#include "DepthwiseConvOp.h"
#include "ConvOp.h"
#include "ConvOp.h"
#include "GemmFunctor.h"
namespace
paddle
{
namespace
paddle
{
...
...
paddle/function/DepthwiseConvOpGpu.cu
浏览文件 @
d3c29e9d
...
@@ -13,7 +13,6 @@ See the License for the specific language governing permissions and
...
@@ -13,7 +13,6 @@ See the License for the specific language governing permissions and
limitations under the License. */
limitations under the License. */
#include "DepthwiseConvOp.h"
#include "DepthwiseConvOp.h"
#include "GemmFunctor.h"
#include "paddle/math/BaseMatrix.h"
#include "paddle/math/BaseMatrix.h"
namespace
paddle
{
namespace
paddle
{
...
...
paddle/function/EigenGemm.cpp
0 → 100644
浏览文件 @
d3c29e9d
/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.
Licensed under the Apache License, Version 2.0 (the "License");
you 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
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
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 <glog/logging.h>
#include "unsupported/Eigen/CXX11/Tensor"
namespace
paddle
{
template
<
class
T
>
struct
EigenBlasGemm
{
typedef
Eigen
::
TensorMap
<
Eigen
::
Tensor
<
T
,
2
,
Eigen
::
RowMajor
,
int
>
,
Eigen
::
Aligned
>
Matrix
;
static
void
compute
(
const
bool
transA
,
const
bool
transB
,
const
int
M
,
const
int
N
,
const
int
K
,
const
T
alpha
,
const
T
*
A
,
const
int
lda
,
const
T
*
B
,
const
int
ldb
,
const
T
beta
,
T
*
C
,
const
int
ldc
)
{
Eigen
::
array
<
int
,
2
>
sizeA
;
if
(
transA
)
{
sizeA
[
0
]
=
K
;
sizeA
[
1
]
=
M
;
CHECK_EQ
(
M
,
lda
);
}
else
{
sizeA
[
0
]
=
M
;
sizeA
[
1
]
=
K
;
CHECK_EQ
(
K
,
lda
);
}
Eigen
::
array
<
int
,
2
>
sizeB
;
if
(
transB
)
{
sizeB
[
0
]
=
N
;
sizeB
[
1
]
=
K
;
CHECK_EQ
(
K
,
ldb
);
}
else
{
sizeB
[
0
]
=
K
;
sizeB
[
1
]
=
N
;
CHECK_EQ
(
N
,
ldb
);
}
Eigen
::
array
<
int
,
2
>
sizeC
;
sizeC
[
0
]
=
M
;
sizeC
[
1
]
=
N
;
CHECK_EQ
(
N
,
ldc
);
const
Matrix
a
(
const_cast
<
T
*>
(
A
),
sizeA
);
const
Matrix
b
(
const_cast
<
T
*>
(
B
),
sizeB
);
Matrix
c
(
C
,
sizeC
);
typedef
typename
Eigen
::
Tensor
<
T
,
2
>::
DimensionPair
DimPair
;
Eigen
::
array
<
DimPair
,
1
>
dims
;
dims
[
0
]
=
DimPair
(
1
,
0
);
dims
[
0
].
first
=
transA
?
0
:
1
;
dims
[
0
].
second
=
transB
?
1
:
0
;
Eigen
::
DefaultDevice
device
;
if
(
alpha
==
T
(
1
)
&&
beta
==
T
(
0
))
{
c
.
device
(
device
)
=
a
.
contract
(
b
,
dims
);
}
else
if
(
alpha
==
T
(
1
)
&&
beta
==
T
(
1
))
{
c
.
device
(
device
)
+=
a
.
contract
(
b
,
dims
);
}
else
{
c
.
device
(
device
)
=
alpha
*
a
.
contract
(
b
,
dims
)
+
beta
*
c
;
}
}
};
#ifdef PADDLE_TYPE_DOUBLE
template
class
EigenBlasGemm
<
double
>;
#else
template
class
EigenBlasGemm
<
float
>;
#endif
}
// namespace paddle
paddle/function/GemmConvOp.cpp
浏览文件 @
d3c29e9d
...
@@ -85,7 +85,6 @@ public:
...
@@ -85,7 +85,6 @@ public:
}
}
Im2ColFunctor
<
kCFO
,
Device
,
real
>
im2col
;
Im2ColFunctor
<
kCFO
,
Device
,
real
>
im2col
;
GemmFunctor
<
Device
,
real
>
gemm
;
size_t
inputOffset
=
imShape
.
getElements
();
size_t
inputOffset
=
imShape
.
getElements
();
size_t
outputOffset
=
size_t
outputOffset
=
(
outputChannels
/
groups_
)
*
outputHeight
*
outputWidth
;
(
outputChannels
/
groups_
)
*
outputHeight
*
outputWidth
;
...
@@ -108,8 +107,8 @@ public:
...
@@ -108,8 +107,8 @@ public:
int
M
=
outputChannels
/
groups_
;
int
M
=
outputChannels
/
groups_
;
int
N
=
outputHeight
*
outputWidth
;
int
N
=
outputHeight
*
outputWidth
;
int
K
=
inputChannels
/
groups_
*
filterHeight
*
filterWidth
;
int
K
=
inputChannels
/
groups_
*
filterHeight
*
filterWidth
;
gemm
(
CblasNoTrans
,
BlasGemm
<
Device
,
real
>::
compute
(
false
,
CblasNoTrans
,
false
,
M
,
M
,
N
,
N
,
K
,
K
,
...
@@ -188,8 +187,6 @@ public:
...
@@ -188,8 +187,6 @@ public:
}
}
Col2ImFunctor
<
kCFO
,
Device
,
real
>
col2im
;
Col2ImFunctor
<
kCFO
,
Device
,
real
>
col2im
;
GemmFunctor
<
Device
,
real
>
gemm
;
size_t
inputOffset
=
imShape
.
getElements
();
size_t
inputOffset
=
imShape
.
getElements
();
size_t
outputOffset
=
size_t
outputOffset
=
(
outputChannels
/
groups_
)
*
outputHeight
*
outputWidth
;
(
outputChannels
/
groups_
)
*
outputHeight
*
outputWidth
;
...
@@ -205,8 +202,8 @@ public:
...
@@ -205,8 +202,8 @@ public:
colData
=
inputGrad
+
g
*
inputOffset
;
colData
=
inputGrad
+
g
*
inputOffset
;
scale
=
1.0
f
;
scale
=
1.0
f
;
}
}
gemm
(
CblasTrans
,
BlasGemm
<
Device
,
real
>::
compute
(
true
,
CblasNoTrans
,
false
,
M
,
M
,
N
,
N
,
K
,
K
,
...
@@ -299,7 +296,6 @@ public:
...
@@ -299,7 +296,6 @@ public:
}
}
Im2ColFunctor
<
kCFO
,
Device
,
real
>
im2col
;
Im2ColFunctor
<
kCFO
,
Device
,
real
>
im2col
;
GemmFunctor
<
Device
,
real
>
gemm
;
size_t
inputOffset
=
imShape
.
getElements
();
size_t
inputOffset
=
imShape
.
getElements
();
size_t
outputOffset
=
size_t
outputOffset
=
(
outputChannels
/
groups_
)
*
outputHeight
*
outputWidth
;
(
outputChannels
/
groups_
)
*
outputHeight
*
outputWidth
;
...
@@ -321,8 +317,8 @@ public:
...
@@ -321,8 +317,8 @@ public:
int
M
=
outputChannels
/
groups_
;
int
M
=
outputChannels
/
groups_
;
int
K
=
outputHeight
*
outputWidth
;
int
K
=
outputHeight
*
outputWidth
;
int
N
=
inputChannels
/
groups_
*
filterHeight
*
filterWidth
;
int
N
=
inputChannels
/
groups_
*
filterHeight
*
filterWidth
;
gemm
(
CblasNoTrans
,
BlasGemm
<
Device
,
real
>::
compute
(
false
,
CblasTrans
,
true
,
M
,
M
,
N
,
N
,
K
,
K
,
...
...
paddle/function/GemmFunctor.cpp
0 → 100644
浏览文件 @
d3c29e9d
/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.
Licensed under the Apache License, Version 2.0 (the "License");
you 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
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
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 "GemmFunctor.h"
#include "paddle/math/MathFunctions.h"
namespace
paddle
{
template
<
class
T
>
struct
BlasGemm
<
DEVICE_TYPE_CPU
,
T
>
{
static
void
compute
(
const
bool
transA
,
const
bool
transB
,
const
int
M
,
const
int
N
,
const
int
K
,
const
T
alpha
,
const
T
*
A
,
const
int
lda
,
const
T
*
B
,
const
int
ldb
,
const
T
beta
,
T
*
C
,
const
int
ldc
)
{
#ifdef PADDLE_USE_EIGEN_FOR_BLAS
EigenBlasGemm
<
T
>::
compute
(
transA
,
transB
,
M
,
N
,
K
,
alpha
,
A
,
lda
,
B
,
ldb
,
beta
,
C
,
ldc
);
#else
gemm
<
T
>
(
transA
==
false
?
CblasNoTrans
:
CblasTrans
,
transB
==
false
?
CblasNoTrans
:
CblasTrans
,
M
,
N
,
K
,
alpha
,
A
,
lda
,
B
,
ldb
,
beta
,
C
,
ldc
);
#endif
}
};
template
<
class
T
>
struct
BlasGemm
<
DEVICE_TYPE_GPU
,
T
>
{
static
void
compute
(
const
bool
transA
,
const
bool
transB
,
const
int
M
,
const
int
N
,
const
int
K
,
const
T
alpha
,
const
T
*
A
,
const
int
lda
,
const
T
*
B
,
const
int
ldb
,
const
T
beta
,
T
*
C
,
const
int
ldc
)
{
hl_matrix_mul
((
T
*
)
A
,
transA
==
false
?
HPPL_OP_N
:
HPPL_OP_T
,
(
T
*
)
B
,
transB
==
false
?
HPPL_OP_N
:
HPPL_OP_T
,
C
,
M
,
N
,
K
,
alpha
,
beta
,
lda
,
ldb
,
ldc
);
}
};
template
struct
BlasGemm
<
DEVICE_TYPE_CPU
,
real
>;
template
struct
BlasGemm
<
DEVICE_TYPE_GPU
,
real
>;
}
// namespace paddle
paddle/function/GemmFunctor.h
浏览文件 @
d3c29e9d
...
@@ -14,7 +14,7 @@ limitations under the License. */
...
@@ -14,7 +14,7 @@ limitations under the License. */
#pragma once
#pragma once
#include "
paddle/math/MathFunctions
.h"
#include "
TensorType
.h"
namespace
paddle
{
namespace
paddle
{
...
@@ -24,10 +24,9 @@ namespace paddle {
...
@@ -24,10 +24,9 @@ namespace paddle {
// of MatMulFunction, we need to consider the reconstruction of hl_matrix_mul
// of MatMulFunction, we need to consider the reconstruction of hl_matrix_mul
// interface.
// interface.
template
<
DeviceType
Device
,
class
T
>
template
<
DeviceType
Device
,
class
T
>
class
GemmFunctor
{
struct
BlasGemm
{
public:
static
void
compute
(
const
bool
transA
,
void
operator
()(
const
CBLAS_TRANSPOSE
transA
,
const
bool
transB
,
const
CBLAS_TRANSPOSE
TransB
,
const
int
M
,
const
int
M
,
const
int
N
,
const
int
N
,
const
int
K
,
const
int
K
,
...
@@ -41,11 +40,15 @@ public:
...
@@ -41,11 +40,15 @@ public:
const
int
ldc
);
const
int
ldc
);
};
};
// TODO(hedaoyuan): Since the definition of the real type in the Paddle
// conflicts with the Eigen library, so compile the Eigen code can not
// include the Paddle header file. And need an EigenBlasGemm template class
// that does not contain the DeviceType parameter.
// I will fix this problem and merge BlasGemm and EigenBlasGemm into one.
template
<
class
T
>
template
<
class
T
>
class
GemmFunctor
<
DEVICE_TYPE_CPU
,
T
>
{
struct
EigenBlasGemm
{
public:
static
void
compute
(
const
bool
transA
,
void
operator
()(
const
CBLAS_TRANSPOSE
transA
,
const
bool
transB
,
const
CBLAS_TRANSPOSE
TransB
,
const
int
M
,
const
int
M
,
const
int
N
,
const
int
N
,
const
int
K
,
const
int
K
,
...
@@ -56,41 +59,7 @@ public:
...
@@ -56,41 +59,7 @@ public:
const
int
ldb
,
const
int
ldb
,
const
T
beta
,
const
T
beta
,
T
*
C
,
T
*
C
,
const
int
ldc
)
{
const
int
ldc
);
gemm
<
T
>
(
transA
,
TransB
,
M
,
N
,
K
,
alpha
,
A
,
lda
,
B
,
ldb
,
beta
,
C
,
ldc
);
}
};
template
<
class
T
>
class
GemmFunctor
<
DEVICE_TYPE_GPU
,
T
>
{
public:
void
operator
()(
const
CBLAS_TRANSPOSE
transA
,
const
CBLAS_TRANSPOSE
TransB
,
const
int
M
,
const
int
N
,
const
int
K
,
const
T
alpha
,
const
T
*
A
,
const
int
lda
,
const
T
*
B
,
const
int
ldb
,
const
T
beta
,
T
*
C
,
const
int
ldc
)
{
hl_matrix_mul
((
T
*
)
A
,
transA
==
CblasNoTrans
?
HPPL_OP_N
:
HPPL_OP_T
,
(
T
*
)
B
,
TransB
==
CblasNoTrans
?
HPPL_OP_N
:
HPPL_OP_T
,
C
,
M
,
N
,
K
,
alpha
,
beta
,
lda
,
ldb
,
ldc
);
}
};
};
}
// namespace paddle
}
// namespace paddle
paddle/gserver/layers/ScaleShiftLayer.cpp
0 → 100644
浏览文件 @
d3c29e9d
/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.
Licensed under the Apache License, Version 2.0 (the "License");
you 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
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
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 "Layer.h"
namespace
paddle
{
/**
* A layer applies a linear transformation to each element in each row of
* the input matrix. For each element, the layer first re-scale it and then
* adds a bias to it.
*
* \f[
* y = wx + b
* \f]
*
* Here, w is the scale and b is the bias. Both w and b are trainable scalars.
*
*/
class
ScaleShiftLayer
:
public
Layer
{
protected:
std
::
unique_ptr
<
Weight
>
scale_
;
std
::
unique_ptr
<
Weight
>
offset_
;
public:
explicit
ScaleShiftLayer
(
const
LayerConfig
&
config
)
:
Layer
(
config
)
{}
bool
init
(
const
LayerMap
&
layerMap
,
const
ParameterMap
&
parameterMap
)
override
;
void
forward
(
PassType
passType
)
override
;
void
backward
(
const
UpdateCallback
&
callback
=
nullptr
)
override
;
};
REGISTER_LAYER
(
scale_shift
,
ScaleShiftLayer
);
bool
ScaleShiftLayer
::
init
(
const
LayerMap
&
layerMap
,
const
ParameterMap
&
parameterMap
)
{
Layer
::
init
(
layerMap
,
parameterMap
);
CHECK_EQ
(
inputLayers_
.
size
(),
1U
);
scale_
.
reset
(
new
Weight
(
1
,
1
,
parameters_
[
0
]));
if
(
biasParameter_
.
get
()
!=
NULL
)
{
offset_
=
std
::
unique_ptr
<
Weight
>
(
new
Weight
(
1
,
1
,
biasParameter_
));
}
return
true
;
}
void
ScaleShiftLayer
::
forward
(
PassType
passType
)
{
Layer
::
forward
(
passType
);
MatrixPtr
inV
=
getInputValue
(
0
);
resetOutput
(
inV
->
getHeight
(),
inV
->
getWidth
());
MatrixPtr
outV
=
getOutputValue
();
real
scaleValue
=
scale_
->
getW
()
->
getElement
(
0
,
0
);
outV
->
mulScalar
(
*
inV
,
scaleValue
);
if
(
offset_
)
{
real
offsetValue
=
offset_
->
getW
()
->
getElement
(
0
,
0
);
outV
->
add
(
offsetValue
);
}
}
void
ScaleShiftLayer
::
backward
(
const
UpdateCallback
&
callback
)
{
MatrixPtr
inV
=
getInputValue
(
0
);
MatrixPtr
inG
=
getInputGrad
(
0
);
MatrixPtr
outV
=
getOutputValue
();
MatrixPtr
outG
=
getOutputGrad
();
/* Calculate the parameter gradient for the current layer */
if
(
scale_
->
getWGrad
())
{
MatrixPtr
rowSumMtx
;
Matrix
::
resizeOrCreate
(
rowSumMtx
,
outG
->
getHeight
(),
1
,
false
,
useGpu_
);
// this_i = scaleDest * this_i + scaleSum * \sum_j b_{ij} * c_{ij}
rowSumMtx
->
sumOfProducts
(
/* b= */
*
inV
,
/* c= */
*
outG
,
/* scaleSum= */
1
,
/* scaleDest= */
0.
);
// this_i = scaleDest * this_i + scaleSum * \sum_j b_{ji}
scale_
->
getWGrad
()
->
sumCols
(
/* b= */
*
rowSumMtx
,
/* scaleSum= */
1.
,
/* scaleDest= */
1.
);
scale_
->
getParameterPtr
()
->
incUpdate
(
callback
);
}
if
(
offset_
&&
offset_
->
getWGrad
())
{
MatrixPtr
rowSumMtx
;
Matrix
::
resizeOrCreate
(
rowSumMtx
,
outG
->
getHeight
(),
1
,
false
,
useGpu_
);
rowSumMtx
->
sumRows
(
*
outG
,
1.
,
0.
);
offset_
->
getWGrad
()
->
sumCols
(
*
rowSumMtx
,
1.
,
1.
);
offset_
->
getParameterPtr
()
->
incUpdate
(
callback
);
}
/* Calculate the input layers error */
if
(
inG
)
{
real
scaleValue
=
scale_
->
getW
()
->
getElement
(
0
,
0
);
inG
->
add
(
*
outG
,
scaleValue
);
}
}
}
// namespace paddle
paddle/gserver/tests/test_LayerGrad.cpp
浏览文件 @
d3c29e9d
...
@@ -2007,6 +2007,21 @@ TEST(Layer, RowL2NormLayer) {
...
@@ -2007,6 +2007,21 @@ TEST(Layer, RowL2NormLayer) {
}
}
}
}
TEST
(
Layer
,
ScaleShiftLayer
)
{
const
size_t
batchSize
=
16
;
const
size_t
size
=
32
;
TestConfig
config
;
config
.
layerConfig
.
set_type
(
"scale_shift"
);
config
.
layerConfig
.
set_size
(
size
);
config
.
biasSize
=
1
;
config
.
inputDefs
.
push_back
(
{
INPUT_DATA
,
"input"
,
/* dim= */
size
,
/* paraSize= */
1
});
config
.
layerConfig
.
add_inputs
();
for
(
auto
useGpu
:
{
false
,
true
})
{
testLayerGrad
(
config
,
"scale_shift"
,
batchSize
,
false
,
useGpu
,
false
);
}
}
int
main
(
int
argc
,
char
**
argv
)
{
int
main
(
int
argc
,
char
**
argv
)
{
testing
::
InitGoogleTest
(
&
argc
,
argv
);
testing
::
InitGoogleTest
(
&
argc
,
argv
);
initMain
(
argc
,
argv
);
initMain
(
argc
,
argv
);
...
...
paddle/gserver/tests/test_NetworkCompare.cpp
浏览文件 @
d3c29e9d
...
@@ -269,7 +269,8 @@ TEST(Compare, img_conv2) {
...
@@ -269,7 +269,8 @@ TEST(Compare, img_conv2) {
bool
useGpu
=
FLAGS_use_gpu
;
bool
useGpu
=
FLAGS_use_gpu
;
double
eps
=
FLAGS_checkgrad_eps
;
double
eps
=
FLAGS_checkgrad_eps
;
FLAGS_use_gpu
=
true
;
FLAGS_use_gpu
=
true
;
FLAGS_checkgrad_eps
=
1e-2
;
// Sometimes, this unit test will fail with 1e-2
FLAGS_checkgrad_eps
=
4e-2
;
compareNetwork
(
config_file_a
,
config_file_b
);
compareNetwork
(
config_file_a
,
config_file_b
);
FLAGS_use_gpu
=
useGpu
;
FLAGS_use_gpu
=
useGpu
;
FLAGS_checkgrad_eps
=
eps
;
FLAGS_checkgrad_eps
=
eps
;
...
...
paddle/operators/math/math_function.cc
浏览文件 @
d3c29e9d
...
@@ -25,8 +25,8 @@ void gemm<platform::CPUPlace, float>(const CBLAS_TRANSPOSE transA,
...
@@ -25,8 +25,8 @@ void gemm<platform::CPUPlace, float>(const CBLAS_TRANSPOSE transA,
const
float
alpha
,
const
float
*
A
,
const
float
alpha
,
const
float
*
A
,
const
float
*
B
,
const
float
beta
,
float
*
C
,
const
float
*
B
,
const
float
beta
,
float
*
C
,
platform
::
DeviceContext
*
context
)
{
platform
::
DeviceContext
*
context
)
{
int
lda
=
K
;
int
lda
=
(
transA
==
CblasNoTrans
)
?
K
:
M
;
int
ldb
=
N
;
int
ldb
=
(
transB
==
CblasNoTrans
)
?
N
:
K
;
int
ldc
=
N
;
int
ldc
=
N
;
cblas_sgemm
(
CblasRowMajor
,
transA
,
transB
,
M
,
N
,
K
,
alpha
,
A
,
lda
,
B
,
ldb
,
cblas_sgemm
(
CblasRowMajor
,
transA
,
transB
,
M
,
N
,
K
,
alpha
,
A
,
lda
,
B
,
ldb
,
beta
,
C
,
ldc
);
beta
,
C
,
ldc
);
...
@@ -40,8 +40,8 @@ void gemm<platform::CPUPlace, double>(const CBLAS_TRANSPOSE transA,
...
@@ -40,8 +40,8 @@ void gemm<platform::CPUPlace, double>(const CBLAS_TRANSPOSE transA,
const
double
*
B
,
const
double
beta
,
const
double
*
B
,
const
double
beta
,
double
*
C
,
double
*
C
,
platform
::
DeviceContext
*
context
)
{
platform
::
DeviceContext
*
context
)
{
int
lda
=
K
;
int
lda
=
(
transA
==
CblasNoTrans
)
?
K
:
M
;
int
ldb
=
N
;
int
ldb
=
(
transB
==
CblasNoTrans
)
?
N
:
K
;
int
ldc
=
N
;
int
ldc
=
N
;
cblas_dgemm
(
CblasRowMajor
,
transA
,
transB
,
M
,
N
,
K
,
alpha
,
A
,
lda
,
B
,
ldb
,
cblas_dgemm
(
CblasRowMajor
,
transA
,
transB
,
M
,
N
,
K
,
alpha
,
A
,
lda
,
B
,
ldb
,
beta
,
C
,
ldc
);
beta
,
C
,
ldc
);
...
...
paddle/operators/mul_op.cc
浏览文件 @
d3c29e9d
...
@@ -18,6 +18,8 @@
...
@@ -18,6 +18,8 @@
namespace
paddle
{
namespace
paddle
{
namespace
operators
{
namespace
operators
{
using
framework
::
Tensor
;
class
MulOp
:
public
framework
::
OperatorWithKernel
{
class
MulOp
:
public
framework
::
OperatorWithKernel
{
public:
public:
using
framework
::
OperatorWithKernel
::
OperatorWithKernel
;
using
framework
::
OperatorWithKernel
::
OperatorWithKernel
;
...
@@ -59,10 +61,23 @@ class MulOpGrad : public framework::OperatorWithKernel {
...
@@ -59,10 +61,23 @@ class MulOpGrad : public framework::OperatorWithKernel {
using
framework
::
OperatorWithKernel
::
OperatorWithKernel
;
using
framework
::
OperatorWithKernel
::
OperatorWithKernel
;
protected:
protected:
void
InferShape
(
const
framework
::
InferShapeContext
&
ctx
)
const
override
{}
void
InferShape
(
const
framework
::
InferShapeContext
&
ctx
)
const
override
{
std
::
string
DebugString
()
const
override
{
PADDLE_ENFORCE_NOT_NULL
(
ctx
.
InputVar
(
"X"
),
"Input(X) should not be null"
);
LOG
(
INFO
)
<<
"MulGrad"
;
PADDLE_ENFORCE_NOT_NULL
(
ctx
.
InputVar
(
"Y"
),
"Input(Y) should not be null"
);
return
""
;
PADDLE_ENFORCE_NOT_NULL
(
ctx
.
InputVar
(
framework
::
GradVarName
(
"Out"
)),
"Input(Out@GRAD) should not be null"
);
auto
x_dims
=
ctx
.
Input
<
Tensor
>
(
"X"
)
->
dims
();
auto
y_dims
=
ctx
.
Input
<
Tensor
>
(
"Y"
)
->
dims
();
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 "
);
x_grad
->
Resize
(
x_dims
);
y_grad
->
Resize
(
y_dims
);
}
}
};
};
...
@@ -72,3 +87,5 @@ class MulOpGrad : public framework::OperatorWithKernel {
...
@@ -72,3 +87,5 @@ class MulOpGrad : public framework::OperatorWithKernel {
namespace
ops
=
paddle
::
operators
;
namespace
ops
=
paddle
::
operators
;
REGISTER_OP
(
mul
,
ops
::
MulOp
,
ops
::
MulOpMaker
,
mul_grad
,
ops
::
MulOpGrad
);
REGISTER_OP
(
mul
,
ops
::
MulOp
,
ops
::
MulOpMaker
,
mul_grad
,
ops
::
MulOpGrad
);
REGISTER_OP_CPU_KERNEL
(
mul
,
ops
::
MulKernel
<
paddle
::
platform
::
CPUPlace
,
float
>
);
REGISTER_OP_CPU_KERNEL
(
mul
,
ops
::
MulKernel
<
paddle
::
platform
::
CPUPlace
,
float
>
);
REGISTER_OP_CPU_KERNEL
(
mul_grad
,
ops
::
MulGradKernel
<
paddle
::
platform
::
CPUPlace
,
float
>
);
paddle/operators/mul_op.cu
浏览文件 @
d3c29e9d
...
@@ -17,3 +17,5 @@
...
@@ -17,3 +17,5 @@
namespace
ops
=
paddle
::
operators
;
namespace
ops
=
paddle
::
operators
;
REGISTER_OP_GPU_KERNEL
(
mul
,
ops
::
MulKernel
<
paddle
::
platform
::
GPUPlace
,
float
>
);
REGISTER_OP_GPU_KERNEL
(
mul
,
ops
::
MulKernel
<
paddle
::
platform
::
GPUPlace
,
float
>
);
REGISTER_OP_GPU_KERNEL
(
mul_grad
,
ops
::
MulGradKernel
<
paddle
::
platform
::
GPUPlace
,
float
>
);
paddle/operators/mul_op.h
浏览文件 @
d3c29e9d
...
@@ -31,18 +31,34 @@ template <typename Place, typename T>
...
@@ -31,18 +31,34 @@ 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
{
Eigen
::
array
<
Eigen
::
IndexPair
<
Eigen
::
DenseIndex
>
,
1
>
dim_pair
=
{
auto
*
X
=
context
.
Input
<
Tensor
>
(
"X"
);
{
Eigen
::
IndexPair
<
Eigen
::
DenseIndex
>
(
1
,
0
)}};
auto
*
Y
=
context
.
Input
<
Tensor
>
(
"Y"
);
auto
*
input0
=
context
.
Input
<
Tensor
>
(
"X"
);
auto
*
Z
=
context
.
Output
<
Tensor
>
(
"Out"
);
auto
*
input1
=
context
.
Input
<
Tensor
>
(
"Y"
);
Z
->
mutable_data
<
T
>
(
context
.
GetPlace
());
auto
*
output
=
context
.
Output
<
Tensor
>
(
"Out"
);
auto
*
device_context
=
output
->
mutable_data
<
T
>
(
context
.
GetPlace
());
const_cast
<
platform
::
DeviceContext
*>
(
context
.
device_context_
);
auto
X
=
EigenMatrix
<
T
>::
From
(
*
input0
);
math
::
matmul
<
Place
,
T
>
(
*
X
,
false
,
*
Y
,
false
,
1
,
Z
,
0
,
device_context
);
auto
Y
=
EigenMatrix
<
T
>::
From
(
*
input1
);
}
auto
Z
=
EigenMatrix
<
T
>::
From
(
*
output
);
};
auto
&
place
=
context
.
GetEigenDevice
<
Place
>
();
template
<
typename
Place
,
typename
T
>
Z
.
device
(
place
)
=
X
.
contract
(
Y
,
dim_pair
);
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"
));
auto
*
dX
=
ctx
.
Output
<
Tensor
>
(
framework
::
GradVarName
(
"X"
));
auto
*
dY
=
ctx
.
Output
<
Tensor
>
(
framework
::
GradVarName
(
"Y"
));
dX
->
mutable_data
<
T
>
(
ctx
.
GetPlace
());
dY
->
mutable_data
<
T
>
(
ctx
.
GetPlace
());
auto
*
device_context
=
const_cast
<
platform
::
DeviceContext
*>
(
ctx
.
device_context_
);
// 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
);
// 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
);
}
}
};
};
...
...
python/paddle/trainer/config_parser.py
浏览文件 @
d3c29e9d
...
@@ -2232,6 +2232,20 @@ class ClipLayer(LayerBase):
...
@@ -2232,6 +2232,20 @@ class ClipLayer(LayerBase):
self
.
config
.
inputs
[
0
].
clip_conf
.
max
=
max
self
.
config
.
inputs
[
0
].
clip_conf
.
max
=
max
@
config_layer
(
'scale_shift'
)
class
ScaleShiftLayer
(
LayerBase
):
def
__init__
(
self
,
name
,
inputs
,
bias
=
True
,
**
xargs
):
super
(
ScaleShiftLayer
,
self
).
__init__
(
name
,
'scale_shift'
,
0
,
inputs
=
inputs
,
**
xargs
)
config_assert
(
len
(
self
.
inputs
)
==
1
,
'ScaleShiftLayer must have one and only one input.'
)
input_layer
=
self
.
get_input_layer
(
0
)
self
.
set_layer_size
(
input_layer
.
size
)
self
.
create_input_parameter
(
0
,
1
,
[
1
,
1
])
self
.
create_bias_parameter
(
bias
,
1
)
# key: cost type
# key: cost type
# value: cost class
# value: cost class
g_cost_map
=
{}
g_cost_map
=
{}
...
...
python/paddle/trainer_config_helpers/layers.py
浏览文件 @
d3c29e9d
...
@@ -133,6 +133,7 @@ __all__ = [
...
@@ -133,6 +133,7 @@ __all__ = [
'clip_layer'
,
'clip_layer'
,
'slice_projection'
,
'slice_projection'
,
'kmax_sequence_score_layer'
,
'kmax_sequence_score_layer'
,
'scale_shift_layer'
,
]
]
...
@@ -230,6 +231,7 @@ class LayerType(object):
...
@@ -230,6 +231,7 @@ class LayerType(object):
CLIP_LAYER
=
'clip'
CLIP_LAYER
=
'clip'
KMAX_SEQ_SCORE
=
'kmax_seq_score'
KMAX_SEQ_SCORE
=
'kmax_seq_score'
SCALE_SHIFT_LAYER
=
'scale_shift'
@
staticmethod
@
staticmethod
def
is_layer_type
(
type_name
):
def
is_layer_type
(
type_name
):
...
@@ -6210,3 +6212,43 @@ def kmax_sequence_score_layer(input, name=None, beam_size=1):
...
@@ -6210,3 +6212,43 @@ def kmax_sequence_score_layer(input, name=None, beam_size=1):
return
LayerOutput
(
return
LayerOutput
(
name
,
LayerType
.
KMAX_SEQ_SCORE
,
parents
=
[
input
],
size
=
input
.
size
)
name
,
LayerType
.
KMAX_SEQ_SCORE
,
parents
=
[
input
],
size
=
input
.
size
)
@
wrap_name_default
(
"scale_shift"
)
@
wrap_param_attr_default
()
@
wrap_bias_attr_default
()
def
scale_shift_layer
(
input
,
name
=
None
,
param_attr
=
None
,
bias_attr
=
None
):
"""
A layer applies a linear transformation to each element in each row of
the input matrix. For each element, the layer first re-scale it and then
adds a bias to it.
This layer is very like the SlopeInterceptLayer, except the scale and
bias are trainable.
.. math::
y = w * x + b
.. code-block:: python
scale_shift = scale_shift_layer(input=input_layer, bias_attr=False)
:param name: The Layer Name.
:type name: basestring
:param input: The input layer.
:type input: LayerOutput.
:param param_attr: The parameter attribute of scaling.
:type param_attr: ParameterAttribute
:param bias_attr: The parameter attribute of shifting.
:type bias_attr: ParameterAttribute
:return: LayerOutput object.
:rtype: LayerOutput
"""
Layer
(
name
=
name
,
type
=
LayerType
.
SCALE_SHIFT_LAYER
,
inputs
=
Input
(
input
.
name
,
**
param_attr
.
attr
),
bias
=
ParamAttr
.
to_bias
(
bias_attr
))
return
LayerOutput
(
name
,
LayerType
.
SCALE_SHIFT_LAYER
,
parents
=
[
input
],
size
=
input
.
size
)
python/paddle/trainer_config_helpers/tests/configs/file_list.sh
浏览文件 @
d3c29e9d
...
@@ -8,6 +8,6 @@ test_spp_layer test_bilinear_interp test_maxout test_bi_grumemory math_ops
...
@@ -8,6 +8,6 @@ test_spp_layer test_bilinear_interp test_maxout test_bi_grumemory math_ops
test_seq_concat_reshape test_pad test_smooth_l1 test_multiplex_layer
test_seq_concat_reshape test_pad test_smooth_l1 test_multiplex_layer
test_prelu_layer test_row_conv test_detection_output_layer test_multibox_loss_layer
test_prelu_layer test_row_conv test_detection_output_layer test_multibox_loss_layer
test_recursive_topology test_gated_unit_layer test_clip_layer test_row_l2_norm_layer
test_recursive_topology test_gated_unit_layer test_clip_layer test_row_l2_norm_layer
test_kmax_seq_socre_layer test_seq_select_layers
)
test_kmax_seq_socre_layer test_seq_select_layers
test_scale_shift_layer
)
export
whole_configs
=(
test_split_datasource
)
export
whole_configs
=(
test_split_datasource
)
python/paddle/trainer_config_helpers/tests/configs/protostr/test_scale_shift_layer.protostr
0 → 100644
浏览文件 @
d3c29e9d
type: "nn"
layers {
name: "data"
type: "data"
size: 100
active_type: ""
}
layers {
name: "__scale_shift_0__"
type: "scale_shift"
size: 100
active_type: ""
inputs {
input_layer_name: "data"
input_parameter_name: "___scale_shift_0__.w0"
}
}
layers {
name: "__scale_shift_1__"
type: "scale_shift"
size: 100
active_type: ""
inputs {
input_layer_name: "data"
input_parameter_name: "___scale_shift_1__.w0"
}
bias_parameter_name: "___scale_shift_1__.wbias"
}
parameters {
name: "___scale_shift_0__.w0"
size: 1
initial_mean: 0.0
initial_std: 1.0
dims: 1
dims: 1
initial_strategy: 0
initial_smart: true
}
parameters {
name: "___scale_shift_1__.w0"
size: 1
initial_mean: 0.0
initial_std: 1.0
dims: 1
dims: 1
initial_strategy: 0
initial_smart: true
}
parameters {
name: "___scale_shift_1__.wbias"
size: 1
initial_mean: 0.0
initial_std: 0.0
dims: 1
dims: 1
initial_strategy: 0
initial_smart: false
}
input_layer_names: "data"
output_layer_names: "__scale_shift_0__"
output_layer_names: "__scale_shift_1__"
sub_models {
name: "root"
layer_names: "data"
layer_names: "__scale_shift_0__"
layer_names: "__scale_shift_1__"
input_layer_names: "data"
output_layer_names: "__scale_shift_0__"
output_layer_names: "__scale_shift_1__"
is_recurrent_layer_group: false
}
python/paddle/trainer_config_helpers/tests/configs/test_scale_shift_layer.py
0 → 100644
浏览文件 @
d3c29e9d
from
paddle.trainer_config_helpers
import
*
data
=
data_layer
(
name
=
'data'
,
size
=
100
)
scale
=
scale_shift_layer
(
input
=
data
,
bias_attr
=
False
)
scale_shift
=
scale_shift_layer
(
input
=
data
)
outputs
(
scale
,
scale_shift
)
python/paddle/v2/framework/tests/test_mul_op.py
浏览文件 @
d3c29e9d
import
unittest
import
unittest
from
op_test_util
import
OpTestMeta
import
numpy
as
np
import
numpy
as
np
from
gradient_checker
import
GradientChecker
,
create_op
from
op_test_util
import
OpTestMeta
class
TestMulOp
(
unittest
.
TestCase
):
class
TestMulOp
(
unittest
.
TestCase
):
...
@@ -15,5 +16,19 @@ class TestMulOp(unittest.TestCase):
...
@@ -15,5 +16,19 @@ 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
MulGradOpTest
(
GradientChecker
):
def
test_mul
(
self
):
op
=
create_op
(
"mul"
)
inputs
=
{
'X'
:
np
.
random
.
random
((
32
,
84
)).
astype
(
"float32"
),
'Y'
:
np
.
random
.
random
((
84
,
100
)).
astype
(
"float32"
)
}
# mul op will enlarge the relative error
self
.
check_grad
(
op
,
inputs
,
set
([
"X"
,
"Y"
]),
"Out"
,
max_relative_error
=
0.5
)
# TODO(dzh,qijun) : mulgrad test case need transpose feature of blas library
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.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录