提交 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 "
...@@ -187,16 +202,21 @@ Parameters(ksize, strides, paddings) are two elements. ...@@ -187,16 +202,21 @@ Parameters(ksize, strides, paddings) are two elements.
These two elements represent height and width, respectively. These two elements represent height and width, respectively.
The input(X) size and output(Out) size may be different. The input(X) size and output(Out) size may be different.
Example: Example:
Input: Input:
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 "
...@@ -267,8 +294,8 @@ The pooling3d operation calculates the output based on ...@@ -267,8 +294,8 @@ The pooling3d operation calculates the output based on
the input, pooling_type, ksize, strides, and paddings parameters. the input, pooling_type, ksize, strides, and paddings parameters.
Input(X) and output(Out) are in NCDHW format, where N is batch 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 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) width of the feature, respectively. Parameters(ksize, strides, paddings)
are three elements. These three elements represent depth, height and are three elements. These three elements represent depth, height and
width, respectively. The input(X) size and output(Out) size may be different. width, respectively. The input(X) size and output(Out) size may be different.
Example: Example:
...@@ -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.
先完成此消息的编辑!
想要评论请 注册