Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

deconv op implementing ... #4739

Merged
merged 21 commits into from
Oct 24, 2017
Merged

deconv op implementing ... #4739

merged 21 commits into from
Oct 24, 2017

Conversation

zchen0211
Copy link
Contributor

No description provided.


for (int i = 0; i < paddings.size(); ++i) {
PADDLE_ENFORCE_EQ(paddings[i], 0, "No Padding allowed in deconv op.");
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check should be placed in "Deconv2DOpMaker", the current attribute checker doesn't support 'vector' type. @Canpio

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For vector is not supported by AttrChecker right now, we can only do check jobs in the infer shape.


PADDLE_ENFORCE_EQ(in_dims.size(), 4, "Deconv2DOp input should be 4-D.");
PADDLE_ENFORCE_EQ(filter_dims.size(), 4, "Deconv2DOp filter should be 4-D.");
PADDLE_ENFORCE_EQ(in_dims[1], filter_dims[0],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Deconv2DOp filter should be 4-D." -> "Deconv2DOp filter should be 4-D tensor."

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

"The input tensor of deconvolution operator. "
"The format of input tensor is NMHW. Where N is batch size, M is the "
"number of input channels, H and W is the height and width of image.");
AddInput("Filter",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be better to change 'NMHW' to 'NCHW'?
Both conv and pooling use NCHW

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Deconv case is a little different from Conv case. Like in Caffe2, Conv2d use NCHW for input and MCHW for filter and produces a tensor of shape NMHW; Caffe2 Deconv applies NCHW for input, CMHW for filter and produces output tensor with shape NMHW. I will make it clear in my codes.

"The format of output tensor is also NCHW.");
AddAttr<std::vector<int>>("strides", "strides of deconvolution operator.")
.SetDefault({1, 1});
AddAttr<std::vector<int>>("paddings", "paddings of deconvolution operator.")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Attribute checker should be placed here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As @Canpio said, for current version to pass, we temporarily put our check here.

public:
void Compute(const framework::ExecutionContext& context) const override {
const Tensor* input = context.Input<Tensor>("Input");
// filter will be reshaped, so we do not use constant pointer here
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of "The filter will be reshaped in the calculations, so it should not be constant pointer." ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

context.Input<Tensor>(framework::GradVarName("Output"));

// For filter, we do not use const pointer b/c we will do reshape
// but we should avoid modifying its value
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add period.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

context.Output<Tensor>(framework::GradVarName("Filter"));

std::vector<int> strides = context.Attr<std::vector<int>>("strides");
// Actually, no paddings and groups allowed in deconv
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add period.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


int C = output_grad->dims()[1]; // output channels
int O_H = output_grad->dims()[2];
int O_W = output_grad->dims()[3];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

"number of input channels, H and W is the height and width of image.");
AddInput("Filter",
"The filter tensor of deconvolution operator."
"The format of the filter tensor is MCHW, where M is the number of "
Copy link
Contributor

@chengduoZH chengduoZH Oct 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"MCHW" - >"NCHW"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

"input image channels, C is the number of output image channels, "
"H and W is height and width of filter. "
"We enforce groups number == 1 and padding == 0 in our "
"deconvolution Scenario.");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We enforce groups number == 1 and padding == 0 in our deconvolution Scenario.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

namespace paddle {
namespace operators {

void Deconv2DOp::InferShape(framework::InferShapeContext* ctx) const {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the comments: tensorflow/tensorflow#256 (comment)

How about rename Conv2DTranspose?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great suggestion!

"Input",
"The input tensor of deconvolution operator. "
"The format of input tensor is NMHW. Where N is batch size, M is the "
"number of input channels, H and W is the height and width of image.");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"(Tensor) The input tensor of transposed 2D convolution operator. "

The () is used to denote the type, same as the following annotations.

NMHW -> NCHW

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


#pragma once

#include "glog/logging.h"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove glog.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


for (int i = 0; i < N; i++) {
// batch with size (M, H * W)
Tensor input_batch = input->Slice<T>(i, i + 1).Resize(input_matrix_shape);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update code, since the Slice removed the template T.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


std::vector<int> strides = context.Attr<std::vector<int>>("strides");

// no paddings and groups allowed in deconv
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If to do in next PR, add TODO comments.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@jacquesqiao jacquesqiao self-requested a review October 20, 2017 18:11
Copy link
Contributor

@mkliegl mkliegl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. As we discussed separately, it may be worth trying to speed up GPU performance by using CUDNN convolution kernels in a future PR.

// but will be reshaped into a two-dimensional matrix shape
// to call the matrix multiplication interface.
Tensor col_matrix = col;
col_matrix.Resize(col_matrix_shape);
Copy link
Contributor

@mkliegl mkliegl Oct 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That copy assign works as intended, but it looks a little unnatural to me at first glance, since for e.g. std::vector, copy assign copies the data. However, copy assignment does share data in this case because the data is stored inside a std::shared_ptr inside the Tensor class. Nevertheless, I would suggest the more explicit:

Tensor col_matrix;
col_matrix.ShareDataWith(col);

(I realize this is carried over from conv2d_op.h - maybe you could change it there, too?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great thanks!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

// input need to compute gradient
if (input_grad) {
Tensor col_matrix = col;
DDim col_matrix_shape = {C * K_H * K_W, H * W};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above comment. I would prefer the more explicit:

Tensor col_matrix;
col_matrix.ShareDataWith(col);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@zchen0211 zchen0211 merged commit 8fdc315 into PaddlePaddle:develop Oct 24, 2017
PADDLE_ENFORCE_EQ(filter_dims.size(), 4,
"Conv2DTransposeOp filter should be 4-D tensor.");
PADDLE_ENFORCE_EQ(in_dims[1], filter_dims[0],
"input and kernel input dimension should be equal.");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

->"In Conv2DTransposeOp, The input channel should be the same as the number of filters."

The convolution transpose operation calculates the output based on the input, filter
and strides, paddings, groups parameters. The size of each dimension of the
parameters is checked in the infer-shape.
)DOC");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better to give how to calculate the output height/width according to the input height/with, padding and stride size.

The doc of Pytorch is good.

http://pytorch.org/docs/master/nn.html#convtranspose2d

std::vector<int> strides = context.Attr<std::vector<int>>("strides");

// TODO(Zhuoyuan): Paddings can be added in future.
// groups will alway be disabled in conv2dtranspose.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The attribution of group should be available in conv2dtranspose. Reference Pytorch

for (int i = 0; i < batch_size; i++) {
// batch with size (M, h * w)
Tensor input_batch = input->Slice(i, i + 1).Resize(input_matrix_shape);
// filter size: (M, c * k_h * k_w)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can delete this comment or write in line 119.

// batch with size (c, o_h * o_w)
Tensor output_grad_batch =
output_grad->Slice(i, i + 1).Resize(output_shape);
// filter of size (m, c * k_h * k_w)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above.

self.dilations = [1, 1]
self.input_size = [2, 3, 5, 5] # NCHW
f_c = self.input_size[1]
self.filter_size = [f_c, 6, 3, 3]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the calculation is not very time-consuming, you can write several border test examples.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants