提交 1eac2763 编写于 作者: S sweetsky0901

add spp avg

上级 ea093283
...@@ -30,6 +30,11 @@ class SppOpMaker : public framework::OpProtoAndCheckerMaker { ...@@ -30,6 +30,11 @@ class SppOpMaker : public framework::OpProtoAndCheckerMaker {
"N * M." "N * M."
"M = C * H * W"); "M = C * H * W");
AddAttr<int>("pyramid_height", "(int), multi level pooling"); AddAttr<int>("pyramid_height", "(int), multi level pooling");
AddAttr<std::string>(
"pooling_type",
"(string), pooling type, can be \"max\" for max-pooling "
"and \"avg\" for average-pooling.")
.InEnum({"max", "avg"});
AddComment(R"DOC( AddComment(R"DOC(
"With spatial pyramid pooling, the input image can "With spatial pyramid pooling, the input image can
be of any sizes. This not only allows arbitrary aspect be of any sizes. This not only allows arbitrary aspect
......
...@@ -27,6 +27,8 @@ class SppKernel : public framework::OpKernel<T> { ...@@ -27,6 +27,8 @@ class SppKernel : public framework::OpKernel<T> {
const framework::Tensor* in_x = context.Input<framework::Tensor>("X"); const framework::Tensor* in_x = context.Input<framework::Tensor>("X");
auto* out = context.Output<framework::Tensor>("Out"); auto* out = context.Output<framework::Tensor>("Out");
int pyramid_height = context.template Attr<int>("pyramid_height"); int pyramid_height = context.template Attr<int>("pyramid_height");
std::string pooling_type =
context.template Attr<std::string>("pooling_type");
out->mutable_data<T>(context.GetPlace()); out->mutable_data<T>(context.GetPlace());
auto out_stride = framework::stride(out->dims()); auto out_stride = framework::stride(out->dims());
int input_h = in_x->dims()[2]; int input_h = in_x->dims()[2];
...@@ -48,10 +50,17 @@ class SppKernel : public framework::OpKernel<T> { ...@@ -48,10 +50,17 @@ class SppKernel : public framework::OpKernel<T> {
framework::DDim output_shape(framework::make_ddim(output_shape_vec)); framework::DDim output_shape(framework::make_ddim(output_shape_vec));
out_level.mutable_data<T>(output_shape, context.GetPlace()); out_level.mutable_data<T>(output_shape, context.GetPlace());
// pooling // pooling
math::Pool2dFunctor<DeviceContext, math::MaxPool<T>, T> pool_forward; if (pooling_type == "max") {
math::MaxPool<T> max_process; math::Pool2dFunctor<DeviceContext, math::MaxPool<T>, T> pool_forward;
pool_forward(context.template device_context<DeviceContext>(), *in_x, math::MaxPool<T> max_process;
kernel_size, strides, paddings, max_process, &out_level); pool_forward(context.template device_context<DeviceContext>(), *in_x,
kernel_size, strides, paddings, max_process, &out_level);
} else if (pooling_type == "avg") {
math::Pool2dFunctor<DeviceContext, math::AvgPool<T>, T> pool_forward;
math::AvgPool<T> avg_process;
pool_forward(context.template device_context<DeviceContext>(), *in_x,
kernel_size, strides, paddings, avg_process, &out_level);
}
// flatten pooling output shape // flatten pooling output shape
int output_flatten_w = in_x->dims()[1] * bins * bins; int output_flatten_w = in_x->dims()[1] * bins * bins;
std::vector<int64_t> output_flatten_shape_vec( std::vector<int64_t> output_flatten_shape_vec(
...@@ -79,6 +88,8 @@ class SppGradKernel : public framework::OpKernel<T> { ...@@ -79,6 +88,8 @@ class SppGradKernel : public framework::OpKernel<T> {
framework::Tensor* in_x_grad = framework::Tensor* in_x_grad =
context.Output<framework::Tensor>(framework::GradVarName("X")); context.Output<framework::Tensor>(framework::GradVarName("X"));
int pyramid_height = context.template Attr<int>("pyramid_height"); int pyramid_height = context.template Attr<int>("pyramid_height");
std::string pooling_type =
context.template Attr<std::string>("pooling_type");
auto& device_ctx = context.template device_context<DeviceContext>(); auto& device_ctx = context.template device_context<DeviceContext>();
math::SetConstant<DeviceContext, T> zero; math::SetConstant<DeviceContext, T> zero;
in_x_grad->mutable_data<T>(context.GetPlace()); in_x_grad->mutable_data<T>(context.GetPlace());
...@@ -130,10 +141,19 @@ class SppGradKernel : public framework::OpKernel<T> { ...@@ -130,10 +141,19 @@ class SppGradKernel : public framework::OpKernel<T> {
outgrad_level.ShareDataWith(outgrad_level); outgrad_level.ShareDataWith(outgrad_level);
outgrad_level.Resize(out_shape); outgrad_level.Resize(out_shape);
// pooling backward // pooling backward
math::MaxPool2dGradFunctor<DeviceContext, T> pool2d_backward; if (pooling_type == "max") {
pool2d_backward(context.template device_context<DeviceContext>(), *in_x, math::MaxPool2dGradFunctor<DeviceContext, T> pool2d_backward;
pool2d_backward(context.template device_context<DeviceContext>(), *in_x,
*&out_level, *&outgrad_level, kernel_size, strides,
paddings, in_x_grad);
} else if (pooling_type == "avg") {
math::Pool2dGradFunctor<DeviceContext, math::AvgPoolGrad<T>, T>
pool_backward;
math::AvgPoolGrad<T> avg_process;
pool_backward(context.template device_context<DeviceContext>(), *in_x,
*&out_level, *&outgrad_level, kernel_size, strides, *&out_level, *&outgrad_level, kernel_size, strides,
paddings, in_x_grad); paddings, avg_process, in_x_grad);
}
} }
} }
}; };
......
...@@ -2,6 +2,7 @@ import unittest ...@@ -2,6 +2,7 @@ import unittest
import numpy as np import numpy as np
from op_test import OpTest from op_test import OpTest
from test_pool2d_op import max_pool2D_forward_naive from test_pool2d_op import max_pool2D_forward_naive
from test_pool2d_op import avg_pool2D_forward_naive
class TestSppOp(OpTest): class TestSppOp(OpTest):
...@@ -24,8 +25,8 @@ class TestSppOp(OpTest): ...@@ -24,8 +25,8 @@ class TestSppOp(OpTest):
bins.astype("double")).astype("int32") bins.astype("double")).astype("int32")
padding[1] = ( padding[1] = (
(kernel_size[1] * bins - wsize + 1) / 2).astype("int32") (kernel_size[1] * bins - wsize + 1) / 2).astype("int32")
out_level = max_pool2D_forward_naive(input, kernel_size, out_level = self.pool2D_forward_naive(input, kernel_size,
kernel_size, padding) kernel_size, padding)
out_level_flatten.append( out_level_flatten.append(
out_level.reshape(nsize, bins * bins * csize)) out_level.reshape(nsize, bins * bins * csize))
if i == 0: if i == 0:
...@@ -34,7 +35,10 @@ class TestSppOp(OpTest): ...@@ -34,7 +35,10 @@ class TestSppOp(OpTest):
output = np.concatenate((output, out_level_flatten[i]), 1) output = np.concatenate((output, out_level_flatten[i]), 1)
# output = np.concatenate(out_level_flatten.tolist(), 0); # output = np.concatenate(out_level_flatten.tolist(), 0);
self.inputs = {'X': input.astype('float32'), } self.inputs = {'X': input.astype('float32'), }
self.attrs = {'pyramid_height': self.pyramid_height} self.attrs = {
'pyramid_height': self.pyramid_height,
'pooling_type': self.pool_type
}
self.outputs = {'Out': output.astype('float32')} self.outputs = {'Out': output.astype('float32')}
...@@ -42,11 +46,22 @@ class TestSppOp(OpTest): ...@@ -42,11 +46,22 @@ class TestSppOp(OpTest):
self.check_output() self.check_output()
def test_check_grad(self): def test_check_grad(self):
self.check_grad(['X'], 'Out', max_relative_error=0.05) if self.pool_type != "avg":
self.check_grad(['X'], 'Out', max_relative_error=0.05)
def init_test_case(self): def init_test_case(self):
self.shape = [3, 2, 4, 4] self.shape = [3, 2, 4, 4]
self.pyramid_height = 3 self.pyramid_height = 3
self.pool2D_forward_naive = max_pool2D_forward_naive
self.pool_type = "max"
class TestCase2(TestSppOp):
def init_test_case(self):
self.shape = [3, 2, 4, 4]
self.pyramid_height = 3
self.pool2D_forward_naive = avg_pool2D_forward_naive
self.pool_type = "avg"
if __name__ == '__main__': if __name__ == '__main__':
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册