Skip to content

Commit 06d155b

Browse files
author
chengduo
authored
Merge pull request #5718 from chengduoZH/Add_pad_and_stride_for_conv_transpose_op
Add padding for conv_transpose_op
2 parents 00a5155 + eb07047 commit 06d155b

File tree

6 files changed

+77
-37
lines changed

6 files changed

+77
-37
lines changed

paddle/operators/conv_transpose_op.cc

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,6 @@ void ConvTransposeOp::InferShape(framework::InferShapeContext* ctx) const {
3030
std::vector<int> strides = ctx->Attrs().Get<std::vector<int>>("strides");
3131
std::vector<int> paddings = ctx->Attrs().Get<std::vector<int>>("paddings");
3232

33-
for (size_t i = 0; i < paddings.size(); ++i) {
34-
PADDLE_ENFORCE_EQ(paddings[i], 0,
35-
"No Padding allowed in conv transpose op.");
36-
}
37-
3833
PADDLE_ENFORCE(in_dims.size() == 4 || in_dims.size() == 5,
3934
"ConvTransposeOp intput should be 4-D or 5-D tensor.");
4035
PADDLE_ENFORCE_EQ(in_dims.size(), filter_dims.size(),
@@ -52,7 +47,7 @@ void ConvTransposeOp::InferShape(framework::InferShapeContext* ctx) const {
5247

5348
std::vector<int64_t> output_shape({in_dims[0], filter_dims[1]});
5449
for (size_t i = 0; i < strides.size(); ++i) {
55-
output_shape.push_back((in_dims[i + 2] - 1) * strides[i] +
50+
output_shape.push_back((in_dims[i + 2] - 1) * strides[i] - 2 * paddings[i] +
5651
filter_dims[i + 2]);
5752
}
5853
ctx->SetOutputDim("Output", framework::make_ddim(output_shape));

paddle/operators/conv_transpose_op.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ class GemmConvTransposeKernel : public framework::OpKernel<T> {
6262
Tensor* output = context.Output<Tensor>("Output");
6363

6464
std::vector<int> strides = context.Attr<std::vector<int>>("strides");
65-
// Actually, no paddings and groups allowed in conv transpose.
6665
std::vector<int> paddings = context.Attr<std::vector<int>>("paddings");
6766
// TODO(Zhuoyuan): Paddings can be added in future.
6867
// groups will alway be disabled in conv2dtranspose.
@@ -148,8 +147,8 @@ class GemmConvTransposeKernel : public framework::OpKernel<T> {
148147
} else if (filter_shape_vec.size() == 3) {
149148
// col2vol: col_matrix -> dy
150149
// from (c * k_d * k_h * k_w, d * h * w) to (c, o_d, o_h, o_w)
151-
col2vol(context.device_context(), col, dilations, strides,
152-
std::vector<int>{0, 0, 0}, &output_batch);
150+
col2vol(context.device_context(), col, dilations, strides, paddings,
151+
&output_batch);
153152
}
154153
}
155154
}
@@ -173,7 +172,6 @@ class GemmConvTransposeGradKernel : public framework::OpKernel<T> {
173172
if ((!input_grad) && (!filter_grad)) return;
174173

175174
std::vector<int> strides = context.Attr<std::vector<int>>("strides");
176-
// Actually, no paddings and groups allowed in conv transpose.
177175
std::vector<int> paddings = context.Attr<std::vector<int>>("paddings");
178176

179177
const int batch_size = static_cast<int>(input->dims()[0]);

paddle/operators/math/im2col.cu

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,8 @@ __global__ void col2im(int n, const T* data_col, int im_height, int im_width,
119119

120120
if (index < n) {
121121
T val = 0;
122-
int w = index % im_width;
123-
int h = (index / im_width) % im_height;
122+
int w = index % im_width + padding_width;
123+
int h = (index / im_width) % im_height + padding_height;
124124
int c = index / (im_width * im_height);
125125

126126
// compute the start and end of the output

python/paddle/v2/fluid/tests/test_conv2d_op.py

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -110,13 +110,30 @@ def init_op_type(self):
110110
self.op_type = "conv2d"
111111

112112

113+
class TestWithPad(TestConv2dOp):
114+
def init_test_case(self):
115+
self.pad = [1, 1]
116+
self.stride = [1, 1]
117+
self.input_size = [2, 3, 5, 5] # NCHW
118+
assert np.mod(self.input_size[1], self.groups) == 0
119+
f_c = self.input_size[1] / self.groups
120+
self.filter_size = [6, f_c, 3, 3]
121+
122+
123+
class TestWithStride(TestConv2dOp):
124+
def init_test_case(self):
125+
self.pad = [1, 1]
126+
self.stride = [2, 2]
127+
self.input_size = [2, 3, 6, 6] # NCHW
128+
assert np.mod(self.input_size[1], self.groups) == 0
129+
f_c = self.input_size[1] / self.groups
130+
self.filter_size = [6, f_c, 3, 3]
131+
132+
113133
class TestWithGroup(TestConv2dOp):
114134
def init_group(self):
115135
self.groups = 3
116136

117-
def init_op_type(self):
118-
self.op_type = "conv2d"
119-
120137

121138
class TestWith1x1(TestConv2dOp):
122139
def init_test_case(self):
@@ -127,15 +144,9 @@ def init_test_case(self):
127144
f_c = self.input_size[1] / self.groups
128145
self.filter_size = [6, f_c, 1, 1]
129146

130-
def init_dilation(self):
131-
self.dilations = [1, 1]
132-
133147
def init_group(self):
134148
self.groups = 3
135149

136-
def init_op_type(self):
137-
self.op_type = "conv2d"
138-
139150

140151
class TestWithDilation(TestConv2dOp):
141152
def init_test_case(self):
@@ -152,14 +163,19 @@ def init_dilation(self):
152163
def init_group(self):
153164
self.groups = 3
154165

166+
167+
#----------------Conv2dCudnn----------------
168+
class TestCudnn(TestConv2dOp):
155169
def init_op_type(self):
156-
self.op_type = "conv2d"
170+
self.op_type = "conv_cudnn"
157171

158172

159-
#----------------Conv2dCudnn----------------
173+
class TestCudnnWithPad(TestWithPad):
174+
def init_op_type(self):
175+
self.op_type = "conv_cudnn"
160176

161177

162-
class TestCudnn(TestConv2dOp):
178+
class TestCudnnWithStride(TestWithStride):
163179
def init_op_type(self):
164180
self.op_type = "conv_cudnn"
165181

python/paddle/v2/fluid/tests/test_conv2d_transpose_op.py

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@
44

55

66
def conv2dtranspose_forward_naive(input_, filter_, conv2dtranspose_param):
7-
# [2, 3, 5, 5]
87
in_n, in_c, in_h, in_w = input_.shape
9-
# [3, 6, 3, 3]
108
f_c, out_c, f_h, f_w = filter_.shape
119
assert in_c == f_c
1210

@@ -29,15 +27,14 @@ def conv2dtranspose_forward_naive(input_, filter_, conv2dtranspose_param):
2927
j1, j2 = j * stride[0], j * stride[0] + f_w
3028
out[n, k, i1:i2, j1:j2] += tmp_out
3129

30+
out = out[:, :, pad[0]:out_h - pad[0], pad[1]:out_w - pad[1]]
3231
return out
3332

3433

3534
class TestConv2dTransposeOp(OpTest):
3635
def setUp(self):
3736
# init as conv transpose
3837
self.init_op_type()
39-
40-
# [2, 3, 5, 5] -> kernel [3, 6, 3, 3] -> output [2, 6, 7, 7]
4138
self.init_test_case()
4239

4340
conv2dtranspose_param = {'stride': self.stride, 'pad': self.pad}
@@ -55,7 +52,6 @@ def setUp(self):
5552
self.outputs = {'Output': output}
5653

5754
def test_check_output(self):
58-
print 'check output here for', self.op_type
5955
self.check_output()
6056

6157
def test_check_grad_no_input(self):
@@ -88,6 +84,26 @@ def init_op_type(self):
8884
self.op_type = "conv2d_transpose"
8985

9086

87+
class TestWithPad(TestConv2dTransposeOp):
88+
def init_test_case(self):
89+
self.pad = [1, 1]
90+
self.stride = [1, 1]
91+
self.dilations = [1, 1]
92+
self.input_size = [2, 3, 5, 5] # NCHW
93+
f_c = self.input_size[1]
94+
self.filter_size = [f_c, 6, 3, 3]
95+
96+
97+
class TestWithStride(TestConv2dTransposeOp):
98+
def init_test_case(self):
99+
self.pad = [1, 1]
100+
self.stride = [2, 2]
101+
self.dilations = [1, 1]
102+
self.input_size = [2, 3, 5, 5] # NCHW
103+
f_c = self.input_size[1]
104+
self.filter_size = [f_c, 6, 3, 3]
105+
106+
91107
# ------------ test_cudnn ------------
92108
class TestCudnn(TestConv2dTransposeOp):
93109
def init_op_type(self):

python/paddle/v2/fluid/tests/test_conv3d_transpose_op.py

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,14 @@
44

55

66
def conv3dtranspose_forward_naive(input_, filter_, conv3dtranspose_param):
7-
# [2, 3, 5, 5, 5]
87
in_n, in_c, in_d, in_h, in_w = input_.shape
9-
# [3, 6, 3, 3, 3]
108
f_c, out_c, f_d, f_h, f_w = filter_.shape
119
assert in_c == f_c
1210

1311
stride, pad = conv3dtranspose_param['stride'], conv3dtranspose_param['pad']
1412
out_d = (in_d - 1) * stride[0] + f_d
1513
out_h = (in_h - 1) * stride[1] + f_h
1614
out_w = (in_w - 1) * stride[2] + f_w
17-
1815
out = np.zeros((in_n, out_c, out_d, out_h, out_w))
1916

2017
for n in range(in_n):
@@ -33,23 +30,22 @@ def conv3dtranspose_forward_naive(input_, filter_, conv3dtranspose_param):
3330
j1, j2 = j * stride[2], j * stride[2] + f_w
3431
out[n, k, d1:d2, i1:i2, j1:j2] += tmp_out
3532

33+
out = out[:, :, pad[0]:out_d - pad[0], pad[1]:out_h - pad[1], pad[2]:out_w -
34+
pad[2]]
3635
return out
3736

3837

3938
class TestConv3dTransposeOp(OpTest):
4039
def setUp(self):
4140
# init as conv transpose
4241
self.init_op_type()
43-
44-
# [2, 3, 5, 5, 5] -> kernel [3, 6, 3, 3, 3] -> output [2, 6, 7, 7, 7]
4542
self.init_test_case()
4643

4744
conv3dtranspose_param = {'stride': self.stride, 'pad': self.pad}
4845
input_ = np.random.random(self.input_size).astype("float32")
4946
filter_ = np.random.random(self.filter_size).astype("float32")
5047
output = conv3dtranspose_forward_naive(
5148
input_, filter_, conv3dtranspose_param).astype("float32")
52-
# print 'deconv output py', output, output.shape
5349

5450
self.inputs = {'Input': input_, 'Filter': filter_}
5551
self.attrs = {
@@ -60,7 +56,6 @@ def setUp(self):
6056
self.outputs = {'Output': output}
6157

6258
def test_check_output(self):
63-
print 'check output here'
6459
self.check_output()
6560

6661
def test_check_grad(self):
@@ -85,13 +80,33 @@ def init_test_case(self):
8580
self.pad = [0, 0, 0]
8681
self.stride = [1, 1, 1]
8782
self.dilations = [1, 1, 1]
88-
self.input_size = [2, 3, 5, 5, 5] # NCHW
83+
self.input_size = [2, 3, 5, 5, 5] # NCDHW
8984
f_c = self.input_size[1]
9085
self.filter_size = [f_c, 6, 3, 3, 3]
9186

9287
def init_op_type(self):
9388
self.op_type = "conv3d_transpose"
9489

9590

91+
class TestWithPad(TestConv3dTransposeOp):
92+
def init_test_case(self):
93+
self.pad = [1, 1, 1]
94+
self.stride = [1, 1, 1]
95+
self.dilations = [1, 1, 1]
96+
self.input_size = [2, 3, 5, 5, 5] # NCDHW
97+
f_c = self.input_size[1]
98+
self.filter_size = [f_c, 6, 3, 3, 3]
99+
100+
101+
class TestWithStride(TestConv3dTransposeOp):
102+
def init_test_case(self):
103+
self.pad = [1, 1, 1]
104+
self.stride = [2, 2, 2]
105+
self.dilations = [1, 1, 1]
106+
self.input_size = [2, 3, 5, 5, 5] # NCDHW
107+
f_c = self.input_size[1]
108+
self.filter_size = [f_c, 6, 3, 3, 3]
109+
110+
96111
if __name__ == '__main__':
97112
unittest.main()

0 commit comments

Comments
 (0)