提交 1e510d99 编写于 作者: W wanghaoshuang

Add ceil_mode option for pool2d and pool3d

上级 69643b5e
...@@ -17,8 +17,15 @@ limitations under the License. */ ...@@ -17,8 +17,15 @@ limitations under the License. */
namespace paddle { namespace paddle {
namespace operators { namespace operators {
int PoolOutputSize(int input_size, int filter_size, int padding, int stride) { int PoolOutputSize(int input_size, int filter_size, int padding, int stride,
int output_size = (input_size - filter_size + 2 * padding) / stride + 1; 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, PADDLE_ENFORCE(output_size > 0,
"Due to the settings of padding(%d), filter_size(%d) and " "Due to the settings of padding(%d), filter_size(%d) and "
"stride(%d), the output size is less than 0, please check " "stride(%d), the output size is less than 0, please check "
...@@ -38,6 +45,7 @@ void PoolOp::InferShape(framework::InferShapeContext *ctx) const { ...@@ -38,6 +45,7 @@ void PoolOp::InferShape(framework::InferShapeContext *ctx) const {
std::vector<int> ksize = ctx->Attrs().Get<std::vector<int>>("ksize"); std::vector<int> ksize = ctx->Attrs().Get<std::vector<int>>("ksize");
std::vector<int> strides = ctx->Attrs().Get<std::vector<int>>("strides"); std::vector<int> strides = ctx->Attrs().Get<std::vector<int>>("strides");
std::vector<int> paddings = ctx->Attrs().Get<std::vector<int>>("paddings"); std::vector<int> paddings = ctx->Attrs().Get<std::vector<int>>("paddings");
bool ceil_mode = ctx->Attrs().Get<bool>("ceil_mode");
PADDLE_ENFORCE(in_x_dims.size() == 4 || in_x_dims.size() == 5, PADDLE_ENFORCE(in_x_dims.size() == 4 || in_x_dims.size() == 5,
"Pooling intput should be 4-D or 5-D tensor."); "Pooling intput should be 4-D or 5-D tensor.");
...@@ -59,8 +67,8 @@ void PoolOp::InferShape(framework::InferShapeContext *ctx) const { ...@@ -59,8 +67,8 @@ void PoolOp::InferShape(framework::InferShapeContext *ctx) const {
std::vector<int64_t> output_shape({in_x_dims[0], in_x_dims[1]}); std::vector<int64_t> output_shape({in_x_dims[0], in_x_dims[1]});
for (size_t i = 0; i < ksize.size(); ++i) { for (size_t i = 0; i < ksize.size(); ++i) {
output_shape.push_back( output_shape.push_back(PoolOutputSize(in_x_dims[i + 2], ksize[i],
PoolOutputSize(in_x_dims[i + 2], ksize[i], paddings[i], strides[i])); paddings[i], strides[i], ceil_mode));
} }
ctx->SetOutputDim("Out", framework::make_ddim(output_shape)); ctx->SetOutputDim("Out", framework::make_ddim(output_shape));
ctx->ShareLoD("X", "Out"); ctx->ShareLoD("X", "Out");
...@@ -167,6 +175,13 @@ Pool2dOpMaker::Pool2dOpMaker(OpProto *proto, OpAttrChecker *op_checker) ...@@ -167,6 +175,13 @@ Pool2dOpMaker::Pool2dOpMaker(OpProto *proto, OpAttrChecker *op_checker)
"use_cudnn", "use_cudnn",
"(bool, default false) Only used in cudnn kernel, need install cudnn") "(bool, default false) Only used in cudnn kernel, need install cudnn")
.SetDefault(false); .SetDefault(false);
AddAttr<bool>(
"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<std::string>( AddAttr<std::string>(
"data_format", "data_format",
"(string, default NCHW) Only used in " "(string, default NCHW) Only used in "
...@@ -192,11 +207,16 @@ Example: ...@@ -192,11 +207,16 @@ Example:
X shape: $(N, C, H_{in}, W_{in})$ X shape: $(N, C, H_{in}, W_{in})$
Output: Output:
Out shape: $(N, C, H_{out}, W_{out})$ 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 \\ 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 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"); )DOC");
} }
...@@ -251,6 +271,13 @@ Pool3dOpMaker::Pool3dOpMaker(OpProto *proto, OpAttrChecker *op_checker) ...@@ -251,6 +271,13 @@ Pool3dOpMaker::Pool3dOpMaker(OpProto *proto, OpAttrChecker *op_checker)
"use_cudnn", "use_cudnn",
"(bool, default false) Only used in cudnn kernel, need install cudnn") "(bool, default false) Only used in cudnn kernel, need install cudnn")
.SetDefault(false); .SetDefault(false);
AddAttr<bool>(
"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<std::string>( AddAttr<std::string>(
"data_format", "data_format",
"(string, default NCHW) Only used in " "(string, default NCHW) Only used in "
...@@ -276,12 +303,18 @@ Example: ...@@ -276,12 +303,18 @@ Example:
X shape: $(N, C, D_{in}, H_{in}, W_{in})$ X shape: $(N, C, D_{in}, H_{in}, W_{in})$
Output: Output:
Out shape: $(N, C, D_{out}, H_{out}, W_{out})$ 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 \\ 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 \\ 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 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"); )DOC");
} }
......
...@@ -1437,6 +1437,7 @@ def pool2d(input, ...@@ -1437,6 +1437,7 @@ def pool2d(input,
pool_padding=0, pool_padding=0,
global_pooling=False, global_pooling=False,
use_cudnn=True, use_cudnn=True,
ceil_mode=False,
name=None): name=None):
""" """
This function adds the operator for pooling in 2 dimensions, using the This function adds the operator for pooling in 2 dimensions, using the
...@@ -1473,7 +1474,8 @@ def pool2d(input, ...@@ -1473,7 +1474,8 @@ def pool2d(input,
"global_pooling": global_pooling, "global_pooling": global_pooling,
"strides": pool_stride, "strides": pool_stride,
"paddings": pool_padding, "paddings": pool_padding,
"use_cudnn": use_cudnn "use_cudnn": use_cudnn,
"ceil_mode": ceil_mode
}) })
return pool_out return pool_out
......
...@@ -19,12 +19,21 @@ import paddle.fluid.core as core ...@@ -19,12 +19,21 @@ import paddle.fluid.core as core
from op_test import OpTest 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 N, C, H, W = x.shape
if global_pool == 1: if global_pool == 1:
ksize = [H, W] ksize = [H, W]
H_out = (H - ksize[0] + 2 * paddings[0]) / strides[0] + 1 H_out = (H - ksize[0] + 2 * paddings[0] + strides[0] - 1
W_out = (W - ksize[1] + 2 * paddings[1]) / strides[1] + 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)) out = np.zeros((N, C, H_out, W_out))
for i in xrange(H_out): for i in xrange(H_out):
for j in xrange(W_out): for j in xrange(W_out):
...@@ -38,12 +47,21 @@ def max_pool2D_forward_naive(x, ksize, strides, paddings, global_pool=0): ...@@ -38,12 +47,21 @@ def max_pool2D_forward_naive(x, ksize, strides, paddings, global_pool=0):
return out 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 N, C, H, W = x.shape
if global_pool == 1: if global_pool == 1:
ksize = [H, W] ksize = [H, W]
H_out = (H - ksize[0] + 2 * paddings[0]) / strides[0] + 1 H_out = (H - ksize[0] + 2 * paddings[0] + strides[0] - 1
W_out = (W - ksize[1] + 2 * paddings[1]) / strides[1] + 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)) out = np.zeros((N, C, H_out, W_out))
for i in xrange(H_out): for i in xrange(H_out):
for j in xrange(W_out): for j in xrange(W_out):
...@@ -65,12 +83,13 @@ class TestPool2d_Op(OpTest): ...@@ -65,12 +83,13 @@ class TestPool2d_Op(OpTest):
self.init_global_pool() self.init_global_pool()
self.init_op_type() self.init_op_type()
self.init_pool_type() self.init_pool_type()
self.init_ceil_mode()
if self.global_pool: if self.global_pool:
self.paddings = [0 for _ in range(len(self.paddings))] self.paddings = [0 for _ in range(len(self.paddings))]
input = np.random.random(self.shape).astype("float32") input = np.random.random(self.shape).astype("float32")
output = self.pool2D_forward_naive(input, self.ksize, self.strides, output = self.pool2D_forward_naive(input, self.ksize, self.strides,
self.paddings, self.paddings, self.global_pool,
self.global_pool).astype("float32") self.ceil_mode).astype("float32")
self.inputs = {'X': input} self.inputs = {'X': input}
self.attrs = { self.attrs = {
...@@ -80,6 +99,7 @@ class TestPool2d_Op(OpTest): ...@@ -80,6 +99,7 @@ class TestPool2d_Op(OpTest):
'pooling_type': self.pool_type, 'pooling_type': self.pool_type,
'global_pooling': self.global_pool, 'global_pooling': self.global_pool,
'use_cudnn': self.use_cudnn, 'use_cudnn': self.use_cudnn,
'ceil_mode': self.ceil_mode,
'data_format': 'AnyLayout' # TODO(dzhwinter) : should be fix latter 'data_format': 'AnyLayout' # TODO(dzhwinter) : should be fix latter
} }
...@@ -116,6 +136,9 @@ class TestPool2d_Op(OpTest): ...@@ -116,6 +136,9 @@ class TestPool2d_Op(OpTest):
def init_global_pool(self): def init_global_pool(self):
self.global_pool = True self.global_pool = True
def init_ceil_mode(self):
self.ceil_mode = False
class TestCase1(TestPool2d_Op): class TestCase1(TestPool2d_Op):
def init_test_case(self): def init_test_case(self):
...@@ -217,5 +240,25 @@ class TestCUDNNCase6(TestCase5): ...@@ -217,5 +240,25 @@ class TestCUDNNCase6(TestCase5):
self.op_type = "pool2d" 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__': if __name__ == '__main__':
unittest.main() unittest.main()
...@@ -19,13 +19,24 @@ import paddle.fluid.core as core ...@@ -19,13 +19,24 @@ import paddle.fluid.core as core
from op_test import OpTest 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 N, C, D, H, W = x.shape
if global_pool == 1: if global_pool == 1:
ksize = [D, H, W] ksize = [D, H, W]
D_out = (D - ksize[0] + 2 * paddings[0]) / strides[0] + 1 D_out = (D - ksize[0] + 2 * paddings[0] + strides[0] - 1
H_out = (H - ksize[1] + 2 * paddings[1]) / strides[1] + 1 ) / strides[0] + 1 if ceil_mode else (H - ksize[0] + 2 *
W_out = (W - ksize[2] + 2 * paddings[2]) / strides[2] + 1 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)) out = np.zeros((N, C, D_out, H_out, W_out))
for k in xrange(D_out): for k in xrange(D_out):
d_start = np.max((k * strides[0] - paddings[0], 0)) 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): ...@@ -42,13 +53,24 @@ def max_pool3D_forward_naive(x, ksize, strides, paddings, global_pool=0):
return out 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 N, C, D, H, W = x.shape
if global_pool == 1: if global_pool == 1:
ksize = [D, H, W] ksize = [D, H, W]
D_out = (D - ksize[0] + 2 * paddings[0]) / strides[0] + 1 D_out = (D - ksize[0] + 2 * paddings[0] + strides[0] - 1
H_out = (H - ksize[1] + 2 * paddings[1]) / strides[1] + 1 ) / strides[0] + 1 if ceil_mode else (H - ksize[0] + 2 *
W_out = (W - ksize[2] + 2 * paddings[2]) / strides[2] + 1 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)) out = np.zeros((N, C, D_out, H_out, W_out))
for k in xrange(D_out): for k in xrange(D_out):
d_start = np.max((k * strides[0] - paddings[0], 0)) d_start = np.max((k * strides[0] - paddings[0], 0))
...@@ -73,13 +95,14 @@ class TestPool3d_Op(OpTest): ...@@ -73,13 +95,14 @@ class TestPool3d_Op(OpTest):
self.init_global_pool() self.init_global_pool()
self.init_op_type() self.init_op_type()
self.init_pool_type() self.init_pool_type()
self.init_ceil_mode()
if self.global_pool: if self.global_pool:
self.paddings = [0 for _ in range(len(self.paddings))] self.paddings = [0 for _ in range(len(self.paddings))]
input = np.random.random(self.shape).astype("float32") input = np.random.random(self.shape).astype("float32")
output = self.pool3D_forward_naive(input, self.ksize, self.strides, output = self.pool3D_forward_naive(input, self.ksize, self.strides,
self.paddings, self.paddings, self.global_pool,
self.global_pool).astype("float32") self.ceil_mode).astype("float32")
self.inputs = {'X': input} self.inputs = {'X': input}
self.attrs = { self.attrs = {
...@@ -89,6 +112,7 @@ class TestPool3d_Op(OpTest): ...@@ -89,6 +112,7 @@ class TestPool3d_Op(OpTest):
'pooling_type': self.pool_type, 'pooling_type': self.pool_type,
'global_pooling': self.global_pool, 'global_pooling': self.global_pool,
'use_cudnn': self.use_cudnn, 'use_cudnn': self.use_cudnn,
'ceil_mode': self.ceil_mode,
'data_format': 'AnyLayout' # TODO(dzhwinter) : should be fix latter 'data_format': 'AnyLayout' # TODO(dzhwinter) : should be fix latter
} }
...@@ -125,6 +149,9 @@ class TestPool3d_Op(OpTest): ...@@ -125,6 +149,9 @@ class TestPool3d_Op(OpTest):
def init_global_pool(self): def init_global_pool(self):
self.global_pool = True self.global_pool = True
def init_ceil_mode(self):
self.ceil_mode = False
class TestCase1(TestPool3d_Op): class TestCase1(TestPool3d_Op):
def init_test_case(self): def init_test_case(self):
...@@ -227,5 +254,25 @@ class TestCUDNNCase6(TestCase5): ...@@ -227,5 +254,25 @@ class TestCUDNNCase6(TestCase5):
self.op_type = "pool3d" 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__': if __name__ == '__main__':
unittest.main() unittest.main()
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册