提交 f1ca3f7e 编写于 作者: G gongweibao

add block forward

上级 d2fda532
...@@ -24,18 +24,43 @@ class BlockExpandOp : public framework::OperatorWithKernel { ...@@ -24,18 +24,43 @@ class BlockExpandOp : public framework::OperatorWithKernel {
protected: protected:
void InferShape(framework::InferShapeContext* ctx) const override { void InferShape(framework::InferShapeContext* ctx) const override {
using namespace framework; using namespace framework;
PADDLE_ENFORCE(ctx->HasInput("input"), PADDLE_ENFORCE(ctx->HasInput("X"),
"Input of BlockExpandOp should not be null."); "Input of BlockExpandOp should not be null.");
PADDLE_ENFORCE(ctx->HasOutput("Out"), PADDLE_ENFORCE(ctx->HasOutput("Out"),
"Output(Out) of BlockExpandOp op should not be null."); "Output of BlockExpandOp op should not be null.");
auto in_dim = ctx->GetInputDim("input"); auto in_dim = ctx->GetInputDim("X");
PADDLE_ENFORCE_EQ(in_dim.size(), 4, "Input format must be NCHW."); PADDLE_ENFORCE_EQ(in_dim.size(), 4, "Input format must be NCHW.");
PADDLE_ENFORCE_GE(in_dim[0], 1, "Input batchsize must >= 1."); PADDLE_ENFORCE_GE(in_dim[0], 1, "Input batchsize must >= 1.");
ctx->ShareLoD("X", /*->*/ "Out"); int blockHeight = ctx->Attrs().Get<int>("blockHeight");
int blockWidth = ctx->Attrs().Get<int>("blockWidth");
// ctx->SetOutputDim("Out", {1}); int strideHeight = ctx->Attrs().Get<int>("strideHeight");
int strideWidth = ctx->Attrs().Get<int>("strideWidth");
int paddingHeight = ctx->Attrs().Get<int>("paddingHeight");
int paddingWidth = ctx->Attrs().Get<int>("paddingWidth");
int N = in_dim[0];
int C = in_dim[1];
int imgHeight = in_dim[3];
int imgWidth = in_dim[4];
int outputHeight = 0;
int outputWidth = 0;
get_blockexpand_output_shape(imgHeight, imgWidth, blockHeight, blockWidth,
strideHeight, strideWidth, paddingHeight,
paddingWidth, outputHeight, outputWidth);
// The result of im2col is [outputHeight, outputWidth,
// inputChannels, filterHeight, filterWidth], and it is easy to
// reshape into [seqLength, stepSize], where seqLength is equal
// outputHeight * outputWidth, stepSize is equal
// input_channels * blockHeight * blockWidth
ctx->SetOutputDim(
"Out", {N, outputHeight, outputWidth, C, blockHeight, blockWidth});
// ctx->ShareLoD("X", /*->*/ "Out");
} }
}; };
...@@ -44,41 +69,36 @@ class BlockExpandOpMaker : public framework::OpProtoAndCheckerMaker { ...@@ -44,41 +69,36 @@ class BlockExpandOpMaker : public framework::OpProtoAndCheckerMaker {
BlockExpandOpMaker(framework::OpProto* proto, BlockExpandOpMaker(framework::OpProto* proto,
framework::OpAttrChecker* op_checker) framework::OpAttrChecker* op_checker)
: OpProtoAndCheckerMaker(proto, op_checker) { : OpProtoAndCheckerMaker(proto, op_checker) {
AddInput("input", "The input of block_expand op"); AddInput("X", R"DOC(
AddOutput("out", "The output of block_expand op"); (Tensor)The input tensor has NCHW format.
AddAttr<int>("block_height", N: batch size
R"DOC( C: channels
)DOC"); H: height
AddAttr<int>("block_width", W: width
R"DOC( )DOC");
)DOC"); AddOutput("Out", "(LodTensor)The output data of block_expand op,");
AddAttr<int>("stride_height", AddAttr<int>("blockHeight", "(int)height of block.");
R"DOC( AddAttr<int>("blockWidth", "(int)width of block.");
)DOC"); AddAttr<int>("strideHeight", "(int)height of stride.");
AddAttr<int>("stride_width", AddAttr<int>("strideWidth", "(int)width of stride.");
R"DOC( AddAttr<int>("paddingHeight", "(int)height of padding.");
)DOC"); AddAttr<int>("paddingWidth", "(int)width of padding.");
AddAttr<int>("padding_height",
R"DOC(
)DOC");
AddAttr<int>("padding_width",
R"DOC(
)DOC");
AddComment(R"DOC( AddComment(R"DOC(
Expand feature map to minibatch matrix. Expand feature map to minibatch matrix.
- matrix width is: blockH_ * blockW_ * channels_ - matirx height is: outputHeight * outputWidth
- matirx height is: outputH_ * outputW_ - matrix width is: blockHeight * blockWidth * channels
outputH\_ = 1 + (2paddingH\_ + imgSizeH\_ - blockH\_ + strideH\_ - 1) / outputHeight =
strideH\_ \\ 1 + (2 * paddingHeight + imgHeight - blockHeight + strideHeight - 1) /
outputW\_ = 1 + (2paddingW\_ + imgSizeW\_ - blockW\_ + strideW\_ - 1) / strideHeight;
strideW\_ outputWidth =
1 + (2 * paddingWidth + imgWidth - blockWidth + strideWidth - 1) /
strideWidth;
The expand method is the same with ExpandConvLayer, but saved the transposed The expand method is the same with ExpandConvLayer, but saved the transposed
value. After expanding, output_.sequenceStartPositions will store timeline. value. After expanding, The number of time steps are outputHeight * outputWidth
The number of time steps are outputH_outputW_ and the dimension of each and the dimension of each time step is blockHeight * blockWidth * channels.
time step is blockH_ * blockW_ * channels_. This layer can be used after This layer can be used after convolution neural network, and before recurrent neural network.
convolution neural network, and before recurrent neural network.
)DOC"); )DOC");
} }
}; };
...@@ -98,7 +118,7 @@ namespace ops = paddle::operators; ...@@ -98,7 +118,7 @@ namespace ops = paddle::operators;
REGISTER_OP(block_expand, ops::BlockExpandOp, ops::BlockExpandOpMaker, REGISTER_OP(block_expand, ops::BlockExpandOp, ops::BlockExpandOpMaker,
block_expand_grad, ops::BlockExpandOpGrad); block_expand_grad, ops::BlockExpandOpGrad);
REGISTER_OP_CPU_KERNEL( REGISTER_OP_CPU_KERNEL(
block_expand, ops::BlockExpanddKernel<paddle::platform::CPUPlace, float>); block_expand, ops::BlockExpandKernel<paddle::platform::CPUPlace, float>);
REGISTER_OP_CPU_KERNEL( REGISTER_OP_CPU_KERNEL(
block_expand_grad, block_expand_grad,
ops::BlockExpandGradKernel<paddle::platform::CPUPlace, float>); ops::BlockExpandGradKernel<paddle::platform::CPUPlace, float>);
...@@ -18,10 +18,26 @@ ...@@ -18,10 +18,26 @@
#include "paddle/framework/eigen.h" #include "paddle/framework/eigen.h"
#include "paddle/framework/op_registry.h" #include "paddle/framework/op_registry.h"
#include "paddle/operators/math/img2col.h"
namespace paddle { namespace paddle {
namespace operators { namespace operators {
inline void get_blockexpand_output_shape(int imgHeight, int imgWidth,
int blockHeight, int blockWidth,
int strideHeight, int strideWidth,
int paddingHeight, int paddingWidth,
int& outputHeight, int& outputWidth) {
outputHeight =
1 +
(imgHeight + 2 * paddingHeight - blockHeight + strideHeight - 1) /
strideHeight;
outputWidth = 1 +
(imgWidth + 2 * paddingWidth - blockWidth + strideWidth - 1) /
strideWidth;
}
template <typename Place, typename T> template <typename Place, typename T>
class BlockExpandKernel : public framework::OpKernel<T> { class BlockExpandKernel : public framework::OpKernel<T> {
public: public:
...@@ -34,39 +50,30 @@ class BlockExpandKernel : public framework::OpKernel<T> { ...@@ -34,39 +50,30 @@ class BlockExpandKernel : public framework::OpKernel<T> {
auto in_dim = in->dims(); auto in_dim = in->dims();
int N = in_dim[0]; int N = in_dim[0];
int C = in_dim[1]; int C = in_dim[1];
int imgHeight = in_dim[2];
int in_height = in_dim[2]; int imgWidth = in_dim[3];
int in_width = in_dim[3];
int blockHeight = ctx.Attr<int>("blockHeight");
int block_height = ctx.Attr<int>("block_height"); int blockWidth = ctx.Attr<int>("blockWidth");
int block_width = ctx.Attr<int>("block_width"); int strideHeight = ctx.Attr<int>("strideHeight");
int stride_height = ctx.Attr<int>("stride_height"); int strideWidth = ctx.Attr<int>("strideWidth");
int stride_width = ctx.Attr<int>("stride_width"); int paddingHeight = ctx.Attr<int>("paddingHeight");
int padding_height = ctx.Attr<int>("padding_height"); int paddingWidth = ctx.Attr<int>("paddingWidth");
int padding_width = ctx.Attr<int>("padding_width");
int outputHeight = 0;
int output_height = int outputWidth = 0;
1 +
(in_height + 2 * padding_height - block_height + stride_height - 1) / get_blockexpand_output_shape(imgHeight, imgWidth, blockHeight, blockWidth,
stride_height; strideHeight, strideWidth, paddingHeight,
paddingWidth, outputHeight, outputWidth);
int output_width =
1 + for (int i = 0; i < N; i++) {
(in_width + 2 * padding_width - block_width + stride_width - 1) / Tensor src = in->Slice<T>(i, i + 1).Resize(C, imgHeight, imgWidth);
stride_width; Tensor dst = out->Slice<T>(i, i + 1).Resize(outputHeight, outputWidth, C,
blockHeight, blockWidth);
Tensor col; math::Im2ColFunctor<kOCF, ctx->GetPlace(), T>(ctx, src, dst, strideHeight,
if (clo_format = KCFO) { strideWidth, paddingHeight,
col.Resize( paddingWidth);
{N, C, filter_height, filter_width, output_height, output_width});
} else {
col.Resize(
{N, output_height, output_width, C, filter_height, filter_width});
}
for (size_t i = 0; i < N; i++) {
Im2ColFunctor<col_format, place, T>(ctx, one_img, col, stride[0],
stride[1], padding[0], padding[1]);
} }
} }
}; };
...@@ -75,13 +82,7 @@ template <typename Place, typename T> ...@@ -75,13 +82,7 @@ template <typename Place, typename T>
class BlockExpandGradKernel : public framework::OpKernel<T> { class BlockExpandGradKernel : public framework::OpKernel<T> {
public: public:
void Compute(const framework::ExecutionContext& ctx) const override { void Compute(const framework::ExecutionContext& ctx) const override {
using Tensor = framework::Tensor; using namespace framework;
/*
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");
*/
} }
}; };
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册