提交 500e29a4 编写于 作者: W wanghaoshuang

1. Reduce attributes

2. Rename 'get_output_size' to 'OutputSize'
3. Remove redundant whitespace char.
上级 fe45f211
...@@ -30,28 +30,24 @@ class Im2SequenceOp : public framework::OperatorWithKernel { ...@@ -30,28 +30,24 @@ class Im2SequenceOp : public framework::OperatorWithKernel {
auto in_dim = ctx->GetInputDim("X"); auto in_dim = ctx->GetInputDim("X");
PADDLE_ENFORCE_EQ(in_dim.size(), 4, PADDLE_ENFORCE_EQ(in_dim.size(), 4,
"Input(X) format must be 4D tensor, eg., NCHW."); "Input(X) format must be 4D tensor, eg., NCHW.");
int block_height = ctx->Attrs().Get<int>("block_height"); auto kernels = ctx->Attrs().Get<std::vector<int>>("kernels");
int block_width = ctx->Attrs().Get<int>("block_width"); auto strides = ctx->Attrs().Get<std::vector<int>>("strides");
int stride_height = ctx->Attrs().Get<int>("stride_height"); auto paddings = ctx->Attrs().Get<std::vector<int>>("paddings");
int stride_width = ctx->Attrs().Get<int>("stride_width");
int padding_height = ctx->Attrs().Get<int>("padding_height");
int padding_width = ctx->Attrs().Get<int>("padding_width");
int batch_size = in_dim[0]; int batch_size = in_dim[0];
int img_channels = in_dim[1]; int img_channels = in_dim[1];
int img_height = in_dim[2]; int img_height = in_dim[2];
int img_width = in_dim[3]; int img_width = in_dim[3];
int output_height = get_output_size(img_height, block_height, stride_height, int output_height = OutputSize(img_height, kernels[0], paddings[0],
padding_height); paddings[2], strides[0]);
int output_width = int output_width =
get_output_size(img_width, block_width, stride_width, padding_width); OutputSize(img_width, kernels[1], paddings[1], paddings[3], strides[1]);
ctx->SetOutputDim("Out", {batch_size * output_height * output_width, ctx->SetOutputDim("Out", {batch_size * output_height * output_width,
img_channels * block_height * block_width}); img_channels * kernels[0] * kernels[1]});
// TODO(wanghaoshuang): cal lod in complie time
} }
}; };
...@@ -66,26 +62,30 @@ class Im2SequenceOpMaker : public framework::OpProtoAndCheckerMaker { ...@@ -66,26 +62,30 @@ class Im2SequenceOpMaker : public framework::OpProtoAndCheckerMaker {
"H: height" "H: height"
"W: width"); "W: width");
AddOutput("Out", "(LodTensor)The output data of im2sequence op,"); AddOutput("Out", "(LodTensor)The output data of im2sequence op,");
AddAttr<int>("block_height", "(int)height of block."); AddAttr<std::vector<int>>("kernels",
AddAttr<int>("block_width", "(int)width of block."); "(vector<int>), the "
AddAttr<int>("stride_height", "(int)height of stride."); "kernels(kernel_height, kernel_width)")
AddAttr<int>("stride_width", "(int)width of stride."); AddAttr<std::vector<int>>("strides",
AddAttr<int>("padding_height", "(int)height of padding."); "(vector<int> default:{1, 1}), the "
AddAttr<int>("padding_width", "(int)width of padding."); "strides(h_stride, w_stride)")
.SetDefault({1, 1});
AddAttr<std::vector<int>>("paddings",
"(vector<int> default:{0, 0, 0, 0}), the "
"paddings(up_pad, left_pad, down_pad, right_pad)")
.SetDefault({0, 0, 0, 0});
AddComment(R"DOC( AddComment(R"DOC(
Convert feature map to minibatch matrix. This op uses kernels to scan images and converts these images to sequences.
- matirx height is: output_height * output_width After expanding, The number of time steps are output_height * output_width
- matrix width is: block_height * block_width * channels and the dimension of each time step is kernel_height * kernel_width * channels,
in which:
output_height = output_height =
1 + (2 * padding_height + img_height - block_height + stride_height - 1) / 1 + (padding_height + padding_down + img_height - kernel_height + stride_height - 1) /
stride_height; stride_height;
output_width = output_width =
1 + (2 * padding_width + img_width - block_width + stride_width - 1) / 1 + (padding_left + padding+right + img_width - kernel_width + stride_width - 1) /
stride_width; stride_width;
After expanding, The number of time steps are output_height * output_width
and the dimension of each time step is block_height * block_width * channels.
This op can be used after convolution neural network, and before recurrent neural network. This op can be used after convolution neural network, and before recurrent neural network.
Given: Given:
...@@ -109,12 +109,9 @@ x.dims = {2, 2, 3, 3} ...@@ -109,12 +109,9 @@ x.dims = {2, 2, 3, 3}
And: And:
block_height = 2 kernels = [2, 2]
block_width = 2 strides = [1, 1]
stride_height = 1 paddings = [0, 0, 0, 0]
stride_width = 1
padding_height = 0
padding_width = 0
Then: Then:
......
...@@ -26,9 +26,11 @@ namespace operators { ...@@ -26,9 +26,11 @@ namespace operators {
using Tensor = framework::Tensor; using Tensor = framework::Tensor;
using LoDTensor = framework::LoDTensor; using LoDTensor = framework::LoDTensor;
inline int get_output_size(int img_size, int block_size, int stride, inline int OutputSize(int input_size, int filter_size, int padding_0,
int padding) { int padding_1, int stride) {
return (1 + (img_size + 2 * padding - block_size + stride - 1) / stride); const int output_size =
(input_size + padding_0 + padding_1 - filter_size) / stride + 1;
return output_size;
} }
template <typename DeviceContext, typename T> template <typename DeviceContext, typename T>
...@@ -47,32 +49,24 @@ class Im2SequenceKernel : public framework::OpKernel<T> { ...@@ -47,32 +49,24 @@ class Im2SequenceKernel : public framework::OpKernel<T> {
int img_channels = in_dim[1]; int img_channels = in_dim[1];
int img_height = in_dim[2]; int img_height = in_dim[2];
int img_width = in_dim[3]; int img_width = in_dim[3];
int block_height = ctx.Attr<int>("block_height");
int block_width = ctx.Attr<int>("block_width"); auto kernels = ctx->Attrs().Get<std::vector<int>>("kernels");
int stride_height = ctx.Attr<int>("stride_height"); auto strides = ctx->Attrs().Get<std::vector<int>>("strides");
int stride_width = ctx.Attr<int>("stride_width"); auto paddings = ctx->Attrs().Get<std::vector<int>>("paddings");
int padding_height = ctx.Attr<int>("padding_height"); int output_height =
int padding_width = ctx.Attr<int>("padding_width"); OutputSize(img_height, kernels[0], paddings[0], paddings[2] strides[0]);
int output_height = get_output_size(img_height, block_height, stride_height,
padding_height);
int output_width = int output_width =
get_output_size(img_width, block_width, stride_width, padding_width); OutputSize(img_width, kernels[1], paddings[1], paddings[3], strides[1]);
const std::vector<int> dilations({1, 1}); const std::vector<int> dilations({1, 1});
const std::vector<int> strides(
{stride_height, stride_width, stride_height, stride_width});
const std::vector<int> paddings(
{padding_height, padding_width, padding_height, padding_width});
auto out_dims = out->dims(); auto out_dims = out->dims();
out->Resize({batch_size, out->numel() / batch_size}); out->Resize({batch_size, out->numel() / batch_size});
for (int i = 0; i < batch_size; i++) { for (int i = 0; i < batch_size; i++) {
const Tensor src = const Tensor src =
in->Slice(i, i + 1).Resize({img_channels, img_height, img_width}); in->Slice(i, i + 1).Resize({img_channels, img_height, img_width});
Tensor dst = out->Slice(i, i + 1).Resize({output_height, output_width, Tensor dst = out->Slice(i, i + 1).Resize(
img_channels, block_height, {output_height, output_width, img_channels, kernels[0], kernels[1]});
block_width});
math::Im2ColFunctor<math::ColFormat::kOCF, DeviceContext, T> f; math::Im2ColFunctor<math::ColFormat::kOCF, DeviceContext, T> f;
auto& dev_ctx = ctx.template device_context<DeviceContext>(); auto& dev_ctx = ctx.template device_context<DeviceContext>();
...@@ -112,22 +106,15 @@ class Im2SequenceGradKernel : public framework::OpKernel<T> { ...@@ -112,22 +106,15 @@ class Im2SequenceGradKernel : public framework::OpKernel<T> {
int img_height = in_dim[2]; int img_height = in_dim[2];
int img_width = in_dim[3]; int img_width = in_dim[3];
int block_height = ctx.Attr<int>("block_height"); auto kernels = ctx->Attrs().Get<std::vector<int>>("kernels");
int block_width = ctx.Attr<int>("block_width"); auto strides = ctx->Attrs().Get<std::vector<int>>("strides");
int stride_height = ctx.Attr<int>("stride_height"); auto paddings = ctx->Attrs().Get<std::vector<int>>("paddings");
int stride_width = ctx.Attr<int>("stride_width"); int output_height = OutputSize(img_height, kernels[0], paddings[0],
int padding_height = ctx.Attr<int>("padding_height"); paddings[2], strides[0]);
int padding_width = ctx.Attr<int>("padding_width");
int output_height = get_output_size(img_height, block_height, stride_height,
padding_height);
int output_width = int output_width =
get_output_size(img_width, block_width, stride_width, padding_width); OutputSize(img_width, kernels[1], paddings[1], paddings[3], strides[1]);
const std::vector<int> dilations({1, 1}); const std::vector<int> dilations({1, 1});
const std::vector<int> strides(
{stride_height, stride_width, stride_height, stride_width});
const std::vector<int> paddings(
{padding_height, padding_width, padding_height, padding_width});
auto d_out_dims = d_out->dims(); auto d_out_dims = d_out->dims();
d_out->Resize({batch_size, d_out->numel() / batch_size}); d_out->Resize({batch_size, d_out->numel() / batch_size});
...@@ -135,8 +122,7 @@ class Im2SequenceGradKernel : public framework::OpKernel<T> { ...@@ -135,8 +122,7 @@ class Im2SequenceGradKernel : public framework::OpKernel<T> {
Tensor dst = Tensor dst =
d_x->Slice(i, i + 1).Resize({img_channels, img_height, img_width}); d_x->Slice(i, i + 1).Resize({img_channels, img_height, img_width});
const Tensor src = d_out->Slice(i, i + 1).Resize( const Tensor src = d_out->Slice(i, i + 1).Resize(
{output_height, output_width, img_channels, block_height, {output_height, output_width, img_channels, kernels[0], kernels[1]});
block_width});
math::Col2ImFunctor<math::ColFormat::kOCF, DeviceContext, T> f; math::Col2ImFunctor<math::ColFormat::kOCF, DeviceContext, T> f;
auto& dev_ctx = ctx.template device_context<DeviceContext>(); auto& dev_ctx = ctx.template device_context<DeviceContext>();
f(dev_ctx, src, dilations, strides, paddings, &dst); f(dev_ctx, src, dilations, strides, paddings, &dst);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册