diff --git a/paddle/fluid/operators/pool_op.cc b/paddle/fluid/operators/pool_op.cc index a87a3511ee46dd657c27da26feb43ba43a08f25d..0edbbfc1744f96afa06cf42b2dc03ebc022cdd36 100644 --- a/paddle/fluid/operators/pool_op.cc +++ b/paddle/fluid/operators/pool_op.cc @@ -17,8 +17,15 @@ limitations under the License. */ namespace paddle { namespace operators { -int PoolOutputSize(int input_size, int filter_size, int padding, int stride) { - int output_size = (input_size - filter_size + 2 * padding) / stride + 1; +int PoolOutputSize(int input_size, int filter_size, int padding, int stride, + bool ceil_mode) { + int output_size; + if (!ceil_mode) { + output_size = (input_size - filter_size + 2 * padding) / stride + 1; + } else { + output_size = + (input_size - filter_size + 2 * padding + stride - 1) / stride + 1; + } PADDLE_ENFORCE(output_size > 0, "Due to the settings of padding(%d), filter_size(%d) and " "stride(%d), the output size is less than 0, please check " @@ -38,6 +45,7 @@ void PoolOp::InferShape(framework::InferShapeContext *ctx) const { std::vector ksize = ctx->Attrs().Get>("ksize"); std::vector strides = ctx->Attrs().Get>("strides"); std::vector paddings = ctx->Attrs().Get>("paddings"); + bool ceil_mode = ctx->Attrs().Get("ceil_mode"); PADDLE_ENFORCE(in_x_dims.size() == 4 || in_x_dims.size() == 5, "Pooling intput should be 4-D or 5-D tensor."); @@ -59,8 +67,8 @@ void PoolOp::InferShape(framework::InferShapeContext *ctx) const { std::vector output_shape({in_x_dims[0], in_x_dims[1]}); for (size_t i = 0; i < ksize.size(); ++i) { - output_shape.push_back( - PoolOutputSize(in_x_dims[i + 2], ksize[i], paddings[i], strides[i])); + output_shape.push_back(PoolOutputSize(in_x_dims[i + 2], ksize[i], + paddings[i], strides[i], ceil_mode)); } ctx->SetOutputDim("Out", framework::make_ddim(output_shape)); ctx->ShareLoD("X", "Out"); @@ -167,6 +175,13 @@ Pool2dOpMaker::Pool2dOpMaker(OpProto *proto, OpAttrChecker *op_checker) "use_cudnn", "(bool, default false) Only used in cudnn kernel, need install cudnn") .SetDefault(false); + AddAttr( + "ceil_mode", + "(bool, default false) Wether to use the ceil function to calculate " + "output height and width." + "True is the default. If it is set to False, the floor function will" + "be used") + .SetDefault(false); AddAttr( "data_format", "(string, default NCHW) Only used in " @@ -187,16 +202,21 @@ Parameters(ksize, strides, paddings) are two elements. These two elements represent height and width, respectively. The input(X) size and output(Out) size may be different. -Example: +Example: Input: X shape: $(N, C, H_{in}, W_{in})$ Output: Out shape: $(N, C, H_{out}, W_{out})$ - Where - $$ + For ceil_mode = false: + $$ H_{out} = \frac{(H_{in} - ksize[0] + 2 * paddings[0])}{strides[0]} + 1 \\ W_{out} = \frac{(W_{in} - ksize[1] + 2 * paddings[1])}{strides[1]} + 1 $$ + For ceil_mode = true: + $$ + H_{out} = \frac{(H_{in} - ksize[0] + 2 * paddings[0] + strides[0] - 1)}{strides[0]} + 1 \\ + W_{out} = \frac{(W_{in} - ksize[1] + 2 * paddings[1] + strides[1] - 1)}{strides[1]} + 1 + $$ )DOC"); } @@ -251,6 +271,13 @@ Pool3dOpMaker::Pool3dOpMaker(OpProto *proto, OpAttrChecker *op_checker) "use_cudnn", "(bool, default false) Only used in cudnn kernel, need install cudnn") .SetDefault(false); + AddAttr( + "ceil_mode", + "(bool, default false) Wether to use the ceil function to calculate " + "output height and width." + "True is the default. If it is set to False, the floor function will" + "be used") + .SetDefault(false); AddAttr( "data_format", "(string, default NCHW) Only used in " @@ -267,8 +294,8 @@ The pooling3d operation calculates the output based on the input, pooling_type, ksize, strides, and paddings parameters. Input(X) and output(Out) are in NCDHW format, where N is batch size, C is the number of channels, and D, H and W are the depth, height and -width of the feature, respectively. Parameters(ksize, strides, paddings) -are three elements. These three elements represent depth, height and +width of the feature, respectively. Parameters(ksize, strides, paddings) +are three elements. These three elements represent depth, height and width, respectively. The input(X) size and output(Out) size may be different. Example: @@ -276,12 +303,18 @@ Example: X shape: $(N, C, D_{in}, H_{in}, W_{in})$ Output: Out shape: $(N, C, D_{out}, H_{out}, W_{out})$ - Where + For ceil_mode = false: $$ D_{out} = \frac{(D_{in} - ksize[0] + 2 * paddings[0])}{strides[0]} + 1 \\ H_{out} = \frac{(H_{in} - ksize[1] + 2 * paddings[1])}{strides[1]} + 1 \\ W_{out} = \frac{(W_{in} - ksize[2] + 2 * paddings[2])}{strides[2]} + 1 $$ + For ceil_mode = true: + $$ + D_{out} = \frac{(D_{in} - ksize[0] + 2 * paddings[0] + strides[0] -1)}{strides[0]} + 1 \\ + H_{out} = \frac{(H_{in} - ksize[1] + 2 * paddings[1] + strides[1] -1)}{strides[1]} + 1 \\ + W_{out} = \frac{(W_{in} - ksize[2] + 2 * paddings[2] + strides[2] -1)}{strides[2]} + 1 + $$ )DOC"); } diff --git a/python/paddle/fluid/layers/nn.py b/python/paddle/fluid/layers/nn.py index ead7041b7b20c7036bbea3da544f3b422c9f31fa..c30e7d84eeefa76a7588ecfa0e9c21bc4179062a 100644 --- a/python/paddle/fluid/layers/nn.py +++ b/python/paddle/fluid/layers/nn.py @@ -1437,6 +1437,7 @@ def pool2d(input, pool_padding=0, global_pooling=False, use_cudnn=True, + ceil_mode=False, name=None): """ This function adds the operator for pooling in 2 dimensions, using the @@ -1473,7 +1474,8 @@ def pool2d(input, "global_pooling": global_pooling, "strides": pool_stride, "paddings": pool_padding, - "use_cudnn": use_cudnn + "use_cudnn": use_cudnn, + "ceil_mode": ceil_mode }) return pool_out diff --git a/python/paddle/fluid/tests/unittests/test_pool2d_op.py b/python/paddle/fluid/tests/unittests/test_pool2d_op.py index 12899ecca36dd1a49f536e657c1840803c3405e2..d2107fb4796a588b87d09f3d67e08566c12ffefb 100644 --- a/python/paddle/fluid/tests/unittests/test_pool2d_op.py +++ b/python/paddle/fluid/tests/unittests/test_pool2d_op.py @@ -19,12 +19,21 @@ import paddle.fluid.core as core from op_test import OpTest -def max_pool2D_forward_naive(x, ksize, strides, paddings, global_pool=0): +def max_pool2D_forward_naive(x, + ksize, + strides, + paddings, + global_pool=0, + ceil_mode=False): N, C, H, W = x.shape if global_pool == 1: ksize = [H, W] - H_out = (H - ksize[0] + 2 * paddings[0]) / strides[0] + 1 - W_out = (W - ksize[1] + 2 * paddings[1]) / strides[1] + 1 + H_out = (H - ksize[0] + 2 * paddings[0] + strides[0] - 1 + ) / strides[0] + 1 if ceil_mode else (H - ksize[0] + 2 * + paddings[0]) / strides[0] + 1 + W_out = (W - ksize[1] + 2 * paddings[1] + strides[1] - 1 + ) / strides[1] + 1 if ceil_mode else (W - ksize[1] + 2 * + paddings[1]) / strides[1] + 1 out = np.zeros((N, C, H_out, W_out)) for i in xrange(H_out): for j in xrange(W_out): @@ -38,12 +47,21 @@ def max_pool2D_forward_naive(x, ksize, strides, paddings, global_pool=0): return out -def avg_pool2D_forward_naive(x, ksize, strides, paddings, global_pool=0): +def avg_pool2D_forward_naive(x, + ksize, + strides, + paddings, + global_pool=0, + ceil_mode=False): N, C, H, W = x.shape if global_pool == 1: ksize = [H, W] - H_out = (H - ksize[0] + 2 * paddings[0]) / strides[0] + 1 - W_out = (W - ksize[1] + 2 * paddings[1]) / strides[1] + 1 + H_out = (H - ksize[0] + 2 * paddings[0] + strides[0] - 1 + ) / strides[0] + 1 if ceil_mode else (H - ksize[0] + 2 * + paddings[0]) / strides[0] + 1 + W_out = (W - ksize[1] + 2 * paddings[1] + strides[1] - 1 + ) / strides[1] + 1 if ceil_mode else (W - ksize[1] + 2 * + paddings[1]) / strides[1] + 1 out = np.zeros((N, C, H_out, W_out)) for i in xrange(H_out): for j in xrange(W_out): @@ -65,12 +83,13 @@ class TestPool2d_Op(OpTest): self.init_global_pool() self.init_op_type() self.init_pool_type() + self.init_ceil_mode() if self.global_pool: self.paddings = [0 for _ in range(len(self.paddings))] input = np.random.random(self.shape).astype("float32") output = self.pool2D_forward_naive(input, self.ksize, self.strides, - self.paddings, - self.global_pool).astype("float32") + self.paddings, self.global_pool, + self.ceil_mode).astype("float32") self.inputs = {'X': input} self.attrs = { @@ -80,6 +99,7 @@ class TestPool2d_Op(OpTest): 'pooling_type': self.pool_type, 'global_pooling': self.global_pool, 'use_cudnn': self.use_cudnn, + 'ceil_mode': self.ceil_mode, 'data_format': 'AnyLayout' # TODO(dzhwinter) : should be fix latter } @@ -116,6 +136,9 @@ class TestPool2d_Op(OpTest): def init_global_pool(self): self.global_pool = True + def init_ceil_mode(self): + self.ceil_mode = False + class TestCase1(TestPool2d_Op): def init_test_case(self): @@ -217,5 +240,25 @@ class TestCUDNNCase6(TestCase5): self.op_type = "pool2d" +class TestCeilModeCase1(TestCUDNNCase1): + def init_ceil_mode(self): + self.ceil_mode = True + + +class TestCeilModeCase2(TestCUDNNCase2): + def init_ceil_mode(self): + self.ceil_mode = True + + +class TestCeilModeCase3(TestCase1): + def init_ceil_mode(self): + self.ceil_mode = True + + +class TestCeilModeCase4(TestCase2): + def init_ceil_mode(self): + self.ceil_mode = True + + if __name__ == '__main__': unittest.main() diff --git a/python/paddle/fluid/tests/unittests/test_pool3d_op.py b/python/paddle/fluid/tests/unittests/test_pool3d_op.py index 321b5f39ffff129384c2a809ba8f7d154dcf5036..15a8ac5e2029eec204d061d1832df3df90339697 100644 --- a/python/paddle/fluid/tests/unittests/test_pool3d_op.py +++ b/python/paddle/fluid/tests/unittests/test_pool3d_op.py @@ -19,13 +19,24 @@ import paddle.fluid.core as core from op_test import OpTest -def max_pool3D_forward_naive(x, ksize, strides, paddings, global_pool=0): +def max_pool3D_forward_naive(x, + ksize, + strides, + paddings, + global_pool=0, + ceil_mode=False): N, C, D, H, W = x.shape if global_pool == 1: ksize = [D, H, W] - D_out = (D - ksize[0] + 2 * paddings[0]) / strides[0] + 1 - H_out = (H - ksize[1] + 2 * paddings[1]) / strides[1] + 1 - W_out = (W - ksize[2] + 2 * paddings[2]) / strides[2] + 1 + D_out = (D - ksize[0] + 2 * paddings[0] + strides[0] - 1 + ) / strides[0] + 1 if ceil_mode else (H - ksize[0] + 2 * + paddings[0]) / strides[0] + 1 + H_out = (H - ksize[1] + 2 * paddings[1] + strides[1] - 1 + ) / strides[1] + 1 if ceil_mode else (W - ksize[1] + 2 * + paddings[1]) / strides[1] + 1 + W_out = (W - ksize[2] + 2 * paddings[2] + strides[2] - 1 + ) / strides[2] + 1 if ceil_mode else (W - ksize[2] + 2 * + paddings[2]) / strides[2] + 1 out = np.zeros((N, C, D_out, H_out, W_out)) for k in xrange(D_out): 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): return out -def avg_pool3D_forward_naive(x, ksize, strides, paddings, global_pool=0): +def avg_pool3D_forward_naive(x, + ksize, + strides, + paddings, + global_pool=0, + ceil_mode=False): N, C, D, H, W = x.shape if global_pool == 1: ksize = [D, H, W] - D_out = (D - ksize[0] + 2 * paddings[0]) / strides[0] + 1 - H_out = (H - ksize[1] + 2 * paddings[1]) / strides[1] + 1 - W_out = (W - ksize[2] + 2 * paddings[2]) / strides[2] + 1 + D_out = (D - ksize[0] + 2 * paddings[0] + strides[0] - 1 + ) / strides[0] + 1 if ceil_mode else (H - ksize[0] + 2 * + paddings[0]) / strides[0] + 1 + H_out = (H - ksize[1] + 2 * paddings[1] + strides[1] - 1 + ) / strides[1] + 1 if ceil_mode else (W - ksize[1] + 2 * + paddings[1]) / strides[1] + 1 + W_out = (W - ksize[2] + 2 * paddings[2] + strides[2] - 1 + ) / strides[2] + 1 if ceil_mode else (W - ksize[2] + 2 * + paddings[2]) / strides[2] + 1 out = np.zeros((N, C, D_out, H_out, W_out)) for k in xrange(D_out): d_start = np.max((k * strides[0] - paddings[0], 0)) @@ -73,13 +95,14 @@ class TestPool3d_Op(OpTest): self.init_global_pool() self.init_op_type() self.init_pool_type() + self.init_ceil_mode() if self.global_pool: self.paddings = [0 for _ in range(len(self.paddings))] input = np.random.random(self.shape).astype("float32") output = self.pool3D_forward_naive(input, self.ksize, self.strides, - self.paddings, - self.global_pool).astype("float32") + self.paddings, self.global_pool, + self.ceil_mode).astype("float32") self.inputs = {'X': input} self.attrs = { @@ -89,6 +112,7 @@ class TestPool3d_Op(OpTest): 'pooling_type': self.pool_type, 'global_pooling': self.global_pool, 'use_cudnn': self.use_cudnn, + 'ceil_mode': self.ceil_mode, 'data_format': 'AnyLayout' # TODO(dzhwinter) : should be fix latter } @@ -125,6 +149,9 @@ class TestPool3d_Op(OpTest): def init_global_pool(self): self.global_pool = True + def init_ceil_mode(self): + self.ceil_mode = False + class TestCase1(TestPool3d_Op): def init_test_case(self): @@ -227,5 +254,25 @@ class TestCUDNNCase6(TestCase5): self.op_type = "pool3d" +class TestCeilModeCase1(TestCUDNNCase1): + def init_ceil_mode(self): + self.ceil_mode = True + + +class TestCeilModeCase2(TestCUDNNCase2): + def init_ceil_mode(self): + self.ceil_mode = True + + +class TestCeilModeCase3(TestCase1): + def init_ceil_mode(self): + self.ceil_mode = True + + +class TestCeilModeCase4(TestCase2): + def init_ceil_mode(self): + self.ceil_mode = True + + if __name__ == '__main__': unittest.main()