Skip to content

Commit f608bb2

Browse files
Merge pull request #8651 from wanghaoshuang/fix_pool
Add ceil_mode option for pool2d and pool3d
2 parents 98ac929 + 0ffec51 commit f608bb2

File tree

4 files changed

+152
-29
lines changed

4 files changed

+152
-29
lines changed

paddle/fluid/operators/pool_op.cc

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,15 @@ limitations under the License. */
1717
namespace paddle {
1818
namespace operators {
1919

20-
int PoolOutputSize(int input_size, int filter_size, int padding, int stride) {
21-
int output_size = (input_size - filter_size + 2 * padding) / stride + 1;
20+
int PoolOutputSize(int input_size, int filter_size, int padding, int stride,
21+
bool ceil_mode) {
22+
int output_size;
23+
if (!ceil_mode) {
24+
output_size = (input_size - filter_size + 2 * padding) / stride + 1;
25+
} else {
26+
output_size =
27+
(input_size - filter_size + 2 * padding + stride - 1) / stride + 1;
28+
}
2229
PADDLE_ENFORCE(output_size > 0,
2330
"Due to the settings of padding(%d), filter_size(%d) and "
2431
"stride(%d), the output size is less than 0, please check "
@@ -38,6 +45,7 @@ void PoolOp::InferShape(framework::InferShapeContext *ctx) const {
3845
std::vector<int> ksize = ctx->Attrs().Get<std::vector<int>>("ksize");
3946
std::vector<int> strides = ctx->Attrs().Get<std::vector<int>>("strides");
4047
std::vector<int> paddings = ctx->Attrs().Get<std::vector<int>>("paddings");
48+
bool ceil_mode = ctx->Attrs().Get<bool>("ceil_mode");
4149

4250
PADDLE_ENFORCE(in_x_dims.size() == 4 || in_x_dims.size() == 5,
4351
"Pooling intput should be 4-D or 5-D tensor.");
@@ -59,8 +67,8 @@ void PoolOp::InferShape(framework::InferShapeContext *ctx) const {
5967

6068
std::vector<int64_t> output_shape({in_x_dims[0], in_x_dims[1]});
6169
for (size_t i = 0; i < ksize.size(); ++i) {
62-
output_shape.push_back(
63-
PoolOutputSize(in_x_dims[i + 2], ksize[i], paddings[i], strides[i]));
70+
output_shape.push_back(PoolOutputSize(in_x_dims[i + 2], ksize[i],
71+
paddings[i], strides[i], ceil_mode));
6472
}
6573
ctx->SetOutputDim("Out", framework::make_ddim(output_shape));
6674
ctx->ShareLoD("X", "Out");
@@ -167,6 +175,12 @@ Pool2dOpMaker::Pool2dOpMaker(OpProto *proto, OpAttrChecker *op_checker)
167175
"use_cudnn",
168176
"(bool, default false) Only used in cudnn kernel, need install cudnn")
169177
.SetDefault(false);
178+
AddAttr<bool>(
179+
"ceil_mode",
180+
"(bool, default false) Wether to use the ceil function to calculate "
181+
"output height and width. False is the default. If it is set to False, "
182+
"the floor function will be used.")
183+
.SetDefault(false);
170184
AddAttr<std::string>(
171185
"data_format",
172186
"(string, default NCHW) Only used in "
@@ -187,16 +201,21 @@ Parameters(ksize, strides, paddings) are two elements.
187201
These two elements represent height and width, respectively.
188202
The input(X) size and output(Out) size may be different.
189203
190-
Example:
204+
Example:
191205
Input:
192206
X shape: $(N, C, H_{in}, W_{in})$
193207
Output:
194208
Out shape: $(N, C, H_{out}, W_{out})$
195-
Where
196-
$$
209+
For ceil_mode = false:
210+
$$
197211
H_{out} = \frac{(H_{in} - ksize[0] + 2 * paddings[0])}{strides[0]} + 1 \\
198212
W_{out} = \frac{(W_{in} - ksize[1] + 2 * paddings[1])}{strides[1]} + 1
199213
$$
214+
For ceil_mode = true:
215+
$$
216+
H_{out} = \frac{(H_{in} - ksize[0] + 2 * paddings[0] + strides[0] - 1)}{strides[0]} + 1 \\
217+
W_{out} = \frac{(W_{in} - ksize[1] + 2 * paddings[1] + strides[1] - 1)}{strides[1]} + 1
218+
$$
200219
201220
)DOC");
202221
}
@@ -251,6 +270,12 @@ Pool3dOpMaker::Pool3dOpMaker(OpProto *proto, OpAttrChecker *op_checker)
251270
"use_cudnn",
252271
"(bool, default false) Only used in cudnn kernel, need install cudnn")
253272
.SetDefault(false);
273+
AddAttr<bool>(
274+
"ceil_mode",
275+
"(bool, default false) Wether to use the ceil function to calculate "
276+
"output height and width. False is the default. If it is set to False, "
277+
"the floor function will be used.")
278+
.SetDefault(false);
254279
AddAttr<std::string>(
255280
"data_format",
256281
"(string, default NCHW) Only used in "
@@ -267,21 +292,27 @@ The pooling3d operation calculates the output based on
267292
the input, pooling_type, ksize, strides, and paddings parameters.
268293
Input(X) and output(Out) are in NCDHW format, where N is batch
269294
size, C is the number of channels, and D, H and W are the depth, height and
270-
width of the feature, respectively. Parameters(ksize, strides, paddings)
271-
are three elements. These three elements represent depth, height and
295+
width of the feature, respectively. Parameters(ksize, strides, paddings)
296+
are three elements. These three elements represent depth, height and
272297
width, respectively. The input(X) size and output(Out) size may be different.
273298
274299
Example:
275300
Input:
276301
X shape: $(N, C, D_{in}, H_{in}, W_{in})$
277302
Output:
278303
Out shape: $(N, C, D_{out}, H_{out}, W_{out})$
279-
Where
304+
For ceil_mode = false:
280305
$$
281306
D_{out} = \frac{(D_{in} - ksize[0] + 2 * paddings[0])}{strides[0]} + 1 \\
282307
H_{out} = \frac{(H_{in} - ksize[1] + 2 * paddings[1])}{strides[1]} + 1 \\
283308
W_{out} = \frac{(W_{in} - ksize[2] + 2 * paddings[2])}{strides[2]} + 1
284309
$$
310+
For ceil_mode = true:
311+
$$
312+
D_{out} = \frac{(D_{in} - ksize[0] + 2 * paddings[0] + strides[0] -1)}{strides[0]} + 1 \\
313+
H_{out} = \frac{(H_{in} - ksize[1] + 2 * paddings[1] + strides[1] -1)}{strides[1]} + 1 \\
314+
W_{out} = \frac{(W_{in} - ksize[2] + 2 * paddings[2] + strides[2] -1)}{strides[2]} + 1
315+
$$
285316
286317
)DOC");
287318
}

python/paddle/fluid/layers/nn.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1438,6 +1438,7 @@ def pool2d(input,
14381438
pool_padding=0,
14391439
global_pooling=False,
14401440
use_cudnn=True,
1441+
ceil_mode=False,
14411442
name=None):
14421443
"""
14431444
This function adds the operator for pooling in 2 dimensions, using the
@@ -1474,7 +1475,8 @@ def pool2d(input,
14741475
"global_pooling": global_pooling,
14751476
"strides": pool_stride,
14761477
"paddings": pool_padding,
1477-
"use_cudnn": use_cudnn
1478+
"use_cudnn": use_cudnn,
1479+
"ceil_mode": ceil_mode
14781480
})
14791481

14801482
return pool_out

python/paddle/fluid/tests/unittests/test_pool2d_op.py

Lines changed: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,21 @@
1919
from op_test import OpTest
2020

2121

22-
def max_pool2D_forward_naive(x, ksize, strides, paddings, global_pool=0):
22+
def max_pool2D_forward_naive(x,
23+
ksize,
24+
strides,
25+
paddings,
26+
global_pool=0,
27+
ceil_mode=False):
2328
N, C, H, W = x.shape
2429
if global_pool == 1:
2530
ksize = [H, W]
26-
H_out = (H - ksize[0] + 2 * paddings[0]) / strides[0] + 1
27-
W_out = (W - ksize[1] + 2 * paddings[1]) / strides[1] + 1
31+
H_out = (H - ksize[0] + 2 * paddings[0] + strides[0] - 1
32+
) / strides[0] + 1 if ceil_mode else (H - ksize[0] + 2 *
33+
paddings[0]) / strides[0] + 1
34+
W_out = (W - ksize[1] + 2 * paddings[1] + strides[1] - 1
35+
) / strides[1] + 1 if ceil_mode else (W - ksize[1] + 2 *
36+
paddings[1]) / strides[1] + 1
2837
out = np.zeros((N, C, H_out, W_out))
2938
for i in xrange(H_out):
3039
for j in xrange(W_out):
@@ -38,12 +47,21 @@ def max_pool2D_forward_naive(x, ksize, strides, paddings, global_pool=0):
3847
return out
3948

4049

41-
def avg_pool2D_forward_naive(x, ksize, strides, paddings, global_pool=0):
50+
def avg_pool2D_forward_naive(x,
51+
ksize,
52+
strides,
53+
paddings,
54+
global_pool=0,
55+
ceil_mode=False):
4256
N, C, H, W = x.shape
4357
if global_pool == 1:
4458
ksize = [H, W]
45-
H_out = (H - ksize[0] + 2 * paddings[0]) / strides[0] + 1
46-
W_out = (W - ksize[1] + 2 * paddings[1]) / strides[1] + 1
59+
H_out = (H - ksize[0] + 2 * paddings[0] + strides[0] - 1
60+
) / strides[0] + 1 if ceil_mode else (H - ksize[0] + 2 *
61+
paddings[0]) / strides[0] + 1
62+
W_out = (W - ksize[1] + 2 * paddings[1] + strides[1] - 1
63+
) / strides[1] + 1 if ceil_mode else (W - ksize[1] + 2 *
64+
paddings[1]) / strides[1] + 1
4765
out = np.zeros((N, C, H_out, W_out))
4866
for i in xrange(H_out):
4967
for j in xrange(W_out):
@@ -65,12 +83,13 @@ def setUp(self):
6583
self.init_global_pool()
6684
self.init_op_type()
6785
self.init_pool_type()
86+
self.init_ceil_mode()
6887
if self.global_pool:
6988
self.paddings = [0 for _ in range(len(self.paddings))]
7089
input = np.random.random(self.shape).astype("float32")
7190
output = self.pool2D_forward_naive(input, self.ksize, self.strides,
72-
self.paddings,
73-
self.global_pool).astype("float32")
91+
self.paddings, self.global_pool,
92+
self.ceil_mode).astype("float32")
7493
self.inputs = {'X': input}
7594

7695
self.attrs = {
@@ -80,6 +99,7 @@ def setUp(self):
8099
'pooling_type': self.pool_type,
81100
'global_pooling': self.global_pool,
82101
'use_cudnn': self.use_cudnn,
102+
'ceil_mode': self.ceil_mode,
83103
'data_format': 'AnyLayout' # TODO(dzhwinter) : should be fix latter
84104
}
85105

@@ -116,6 +136,9 @@ def init_pool_type(self):
116136
def init_global_pool(self):
117137
self.global_pool = True
118138

139+
def init_ceil_mode(self):
140+
self.ceil_mode = False
141+
119142

120143
class TestCase1(TestPool2d_Op):
121144
def init_test_case(self):
@@ -217,5 +240,25 @@ def init_op_type(self):
217240
self.op_type = "pool2d"
218241

219242

243+
class TestCeilModeCase1(TestCUDNNCase1):
244+
def init_ceil_mode(self):
245+
self.ceil_mode = True
246+
247+
248+
class TestCeilModeCase2(TestCUDNNCase2):
249+
def init_ceil_mode(self):
250+
self.ceil_mode = True
251+
252+
253+
class TestCeilModeCase3(TestCase1):
254+
def init_ceil_mode(self):
255+
self.ceil_mode = True
256+
257+
258+
class TestCeilModeCase4(TestCase2):
259+
def init_ceil_mode(self):
260+
self.ceil_mode = True
261+
262+
220263
if __name__ == '__main__':
221264
unittest.main()

python/paddle/fluid/tests/unittests/test_pool3d_op.py

Lines changed: 57 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,24 @@
1919
from op_test import OpTest
2020

2121

22-
def max_pool3D_forward_naive(x, ksize, strides, paddings, global_pool=0):
22+
def max_pool3D_forward_naive(x,
23+
ksize,
24+
strides,
25+
paddings,
26+
global_pool=0,
27+
ceil_mode=False):
2328
N, C, D, H, W = x.shape
2429
if global_pool == 1:
2530
ksize = [D, H, W]
26-
D_out = (D - ksize[0] + 2 * paddings[0]) / strides[0] + 1
27-
H_out = (H - ksize[1] + 2 * paddings[1]) / strides[1] + 1
28-
W_out = (W - ksize[2] + 2 * paddings[2]) / strides[2] + 1
31+
D_out = (D - ksize[0] + 2 * paddings[0] + strides[0] - 1
32+
) / strides[0] + 1 if ceil_mode else (H - ksize[0] + 2 *
33+
paddings[0]) / strides[0] + 1
34+
H_out = (H - ksize[1] + 2 * paddings[1] + strides[1] - 1
35+
) / strides[1] + 1 if ceil_mode else (W - ksize[1] + 2 *
36+
paddings[1]) / strides[1] + 1
37+
W_out = (W - ksize[2] + 2 * paddings[2] + strides[2] - 1
38+
) / strides[2] + 1 if ceil_mode else (W - ksize[2] + 2 *
39+
paddings[2]) / strides[2] + 1
2940
out = np.zeros((N, C, D_out, H_out, W_out))
3041
for k in xrange(D_out):
3142
d_start = np.max((k * strides[0] - paddings[0], 0))
@@ -42,13 +53,24 @@ def max_pool3D_forward_naive(x, ksize, strides, paddings, global_pool=0):
4253
return out
4354

4455

45-
def avg_pool3D_forward_naive(x, ksize, strides, paddings, global_pool=0):
56+
def avg_pool3D_forward_naive(x,
57+
ksize,
58+
strides,
59+
paddings,
60+
global_pool=0,
61+
ceil_mode=False):
4662
N, C, D, H, W = x.shape
4763
if global_pool == 1:
4864
ksize = [D, H, W]
49-
D_out = (D - ksize[0] + 2 * paddings[0]) / strides[0] + 1
50-
H_out = (H - ksize[1] + 2 * paddings[1]) / strides[1] + 1
51-
W_out = (W - ksize[2] + 2 * paddings[2]) / strides[2] + 1
65+
D_out = (D - ksize[0] + 2 * paddings[0] + strides[0] - 1
66+
) / strides[0] + 1 if ceil_mode else (H - ksize[0] + 2 *
67+
paddings[0]) / strides[0] + 1
68+
H_out = (H - ksize[1] + 2 * paddings[1] + strides[1] - 1
69+
) / strides[1] + 1 if ceil_mode else (W - ksize[1] + 2 *
70+
paddings[1]) / strides[1] + 1
71+
W_out = (W - ksize[2] + 2 * paddings[2] + strides[2] - 1
72+
) / strides[2] + 1 if ceil_mode else (W - ksize[2] + 2 *
73+
paddings[2]) / strides[2] + 1
5274
out = np.zeros((N, C, D_out, H_out, W_out))
5375
for k in xrange(D_out):
5476
d_start = np.max((k * strides[0] - paddings[0], 0))
@@ -73,13 +95,14 @@ def setUp(self):
7395
self.init_global_pool()
7496
self.init_op_type()
7597
self.init_pool_type()
98+
self.init_ceil_mode()
7699

77100
if self.global_pool:
78101
self.paddings = [0 for _ in range(len(self.paddings))]
79102
input = np.random.random(self.shape).astype("float32")
80103
output = self.pool3D_forward_naive(input, self.ksize, self.strides,
81-
self.paddings,
82-
self.global_pool).astype("float32")
104+
self.paddings, self.global_pool,
105+
self.ceil_mode).astype("float32")
83106
self.inputs = {'X': input}
84107

85108
self.attrs = {
@@ -89,6 +112,7 @@ def setUp(self):
89112
'pooling_type': self.pool_type,
90113
'global_pooling': self.global_pool,
91114
'use_cudnn': self.use_cudnn,
115+
'ceil_mode': self.ceil_mode,
92116
'data_format': 'AnyLayout' # TODO(dzhwinter) : should be fix latter
93117
}
94118

@@ -125,6 +149,9 @@ def init_pool_type(self):
125149
def init_global_pool(self):
126150
self.global_pool = True
127151

152+
def init_ceil_mode(self):
153+
self.ceil_mode = False
154+
128155

129156
class TestCase1(TestPool3d_Op):
130157
def init_test_case(self):
@@ -227,5 +254,25 @@ def init_op_type(self):
227254
self.op_type = "pool3d"
228255

229256

257+
class TestCeilModeCase1(TestCUDNNCase1):
258+
def init_ceil_mode(self):
259+
self.ceil_mode = True
260+
261+
262+
class TestCeilModeCase2(TestCUDNNCase2):
263+
def init_ceil_mode(self):
264+
self.ceil_mode = True
265+
266+
267+
class TestCeilModeCase3(TestCase1):
268+
def init_ceil_mode(self):
269+
self.ceil_mode = True
270+
271+
272+
class TestCeilModeCase4(TestCase2):
273+
def init_ceil_mode(self):
274+
self.ceil_mode = True
275+
276+
230277
if __name__ == '__main__':
231278
unittest.main()

0 commit comments

Comments
 (0)