Browse Source

rewrite pooling pad scheme, global pooling return continous blob

tags/20180314
nihui 8 years ago
parent
commit
d1ea2a34b4
3 changed files with 110 additions and 95 deletions
  1. +34
    -35
      src/layer/arm/pooling_arm.cpp
  2. +72
    -58
      src/layer/pooling.cpp
  3. +4
    -2
      src/layer/pooling.h

+ 34
- 35
src/layer/arm/pooling_arm.cpp View File

@@ -49,9 +49,40 @@ int Pooling_arm::forward(const Mat& bottom_blob, Mat& top_blob) const
int channels = bottom_blob.c;

Mat bottom_blob_bordered = bottom_blob;
if (pad_w > 0 || pad_h > 0)

float pad_value = 0.f;
if (pooling_type == PoolMethod_MAX)
{
pad_value = -FLT_MAX;
}
else if (pooling_type == PoolMethod_AVE)
{
pad_value = 0.f;
}

int wtailpad = 0;
int htailpad = 0;

if (pad_mode == 0) // full padding
{
int wtail = (w + pad_left + pad_right - kernel_w) % stride_w;
int htail = (h + pad_top + pad_bottom - kernel_h) % stride_h;

if (wtail != 0)
wtailpad = kernel_w - wtail;
if (htail != 0)
htailpad = kernel_h - htail;

copy_make_border(bottom_blob, bottom_blob_bordered, pad_top, pad_bottom + htailpad, pad_left, pad_right + wtailpad, BORDER_CONSTANT, pad_value);
if (bottom_blob_bordered.empty())
return -100;

w = bottom_blob_bordered.w;
h = bottom_blob_bordered.h;
}
else if (pad_mode == 1) // valid padding
{
copy_make_border(bottom_blob, bottom_blob_bordered, pad_h, pad_h, pad_w, pad_w, BORDER_CONSTANT, 0.f);
copy_make_border(bottom_blob, bottom_blob_bordered, pad_top, pad_bottom, pad_left, pad_right, BORDER_CONSTANT, pad_value);
if (bottom_blob_bordered.empty())
return -100;

@@ -64,7 +95,7 @@ int Pooling_arm::forward(const Mat& bottom_blob, Mat& top_blob) const
int hpad = kernel_h + (h - 1) / stride_h * stride_h - h;
if (wpad > 0 || hpad > 0)
{
copy_make_border(bottom_blob, bottom_blob_bordered, hpad / 2, hpad - hpad / 2, wpad / 2, wpad - wpad / 2, BORDER_CONSTANT, 0.f);
copy_make_border(bottom_blob, bottom_blob_bordered, hpad / 2, hpad - hpad / 2, wpad / 2, wpad - wpad / 2, BORDER_CONSTANT, pad_value);
if (bottom_blob_bordered.empty())
return -100;
}
@@ -76,38 +107,6 @@ int Pooling_arm::forward(const Mat& bottom_blob, Mat& top_blob) const
int outw = (w - kernel_w) / stride_w + 1;
int outh = (h - kernel_h) / stride_h + 1;

int wtail = 0;
int htail = 0;
if (pad_mode == 0) // full padding
{
wtail = (w - kernel_w) % stride_w;
htail = (h - kernel_h) % stride_h;
}
if (wtail != 0 || htail != 0)
{
int wtailpad = 0;
int htailpad = 0;
if (wtail != 0)
wtailpad = kernel_w - wtail;
if (htail != 0)
htailpad = kernel_h - htail;

Mat bottom_blob_bordered2;
copy_make_border(bottom_blob_bordered, bottom_blob_bordered2, 0, htailpad, 0, wtailpad, BORDER_REPLICATE, 0.f);
if (bottom_blob_bordered2.empty())
return -100;

bottom_blob_bordered = bottom_blob_bordered2;

w = bottom_blob_bordered.w;
h = bottom_blob_bordered.h;

if (wtail != 0)
outw += 1;
if (htail != 0)
outh += 1;
}

top_blob.create(outw, outh, channels);
if (top_blob.empty())
return -100;


+ 72
- 58
src/layer/pooling.cpp View File

@@ -13,6 +13,7 @@
// specific language governing permissions and limitations under the License.

#include "pooling.h"
#include <float.h>
#include <algorithm>

namespace ncnn {
@@ -32,8 +33,10 @@ int Pooling::load_param(const ParamDict& pd)
kernel_h = pd.get(11, kernel_w);
stride_w = pd.get(2, 1);
stride_h = pd.get(12, stride_w);
pad_w = pd.get(3, 0);
pad_h = pd.get(13, pad_w);
pad_left = pd.get(3, 0);
pad_right = pd.get(14, pad_left);
pad_top = pd.get(13, pad_left);
pad_bottom = pd.get(15, pad_top);
global_pooling = pd.get(4, 0);
pad_mode = pd.get(5, 0);

@@ -52,7 +55,7 @@ int Pooling::forward(const Mat& bottom_blob, Mat& top_blob) const
// fprintf(stderr, "Pooling input %d x %d pad = %d %d ksize=%d %d stride=%d %d\n", w, h, pad_w, pad_h, kernel_w, kernel_h, stride_w, stride_h);
if (global_pooling)
{
top_blob.create(1, 1, channels);
top_blob.create(channels);
if (top_blob.empty())
return -100;

@@ -64,7 +67,6 @@ int Pooling::forward(const Mat& bottom_blob, Mat& top_blob) const
for (int q=0; q<channels; q++)
{
const float* ptr = bottom_blob.channel(q);
float* outptr = top_blob.channel(q);

float max = ptr[0];
for (int i=0; i<size; i++)
@@ -72,7 +74,7 @@ int Pooling::forward(const Mat& bottom_blob, Mat& top_blob) const
max = std::max(max, ptr[i]);
}

outptr[0] = max;
top_blob[q] = max;
}
}
else if (pooling_type == PoolMethod_AVE)
@@ -81,7 +83,6 @@ int Pooling::forward(const Mat& bottom_blob, Mat& top_blob) const
for (int q=0; q<channels; q++)
{
const float* ptr = bottom_blob.channel(q);
float* outptr = top_blob.channel(q);

float sum = 0.f;
for (int i=0; i<size; i++)
@@ -89,7 +90,7 @@ int Pooling::forward(const Mat& bottom_blob, Mat& top_blob) const
sum += ptr[i];
}

outptr[0] = sum / size;
top_blob[q] = sum / size;
}
}

@@ -97,9 +98,40 @@ int Pooling::forward(const Mat& bottom_blob, Mat& top_blob) const
}

Mat bottom_blob_bordered = bottom_blob;
if (pad_w > 0 || pad_h > 0)

float pad_value = 0.f;
if (pooling_type == PoolMethod_MAX)
{
pad_value = -FLT_MAX;
}
else if (pooling_type == PoolMethod_AVE)
{
pad_value = 0.f;
}

int wtailpad = 0;
int htailpad = 0;

if (pad_mode == 0) // full padding
{
int wtail = (w + pad_left + pad_right - kernel_w) % stride_w;
int htail = (h + pad_top + pad_bottom - kernel_h) % stride_h;

if (wtail != 0)
wtailpad = kernel_w - wtail;
if (htail != 0)
htailpad = kernel_h - htail;

copy_make_border(bottom_blob, bottom_blob_bordered, pad_top, pad_bottom + htailpad, pad_left, pad_right + wtailpad, BORDER_CONSTANT, pad_value);
if (bottom_blob_bordered.empty())
return -100;

w = bottom_blob_bordered.w;
h = bottom_blob_bordered.h;
}
else if (pad_mode == 1) // valid padding
{
copy_make_border(bottom_blob, bottom_blob_bordered, pad_h, pad_h, pad_w, pad_w, BORDER_CONSTANT, 0.f);
copy_make_border(bottom_blob, bottom_blob_bordered, pad_top, pad_bottom, pad_left, pad_right, BORDER_CONSTANT, pad_value);
if (bottom_blob_bordered.empty())
return -100;

@@ -112,7 +144,7 @@ int Pooling::forward(const Mat& bottom_blob, Mat& top_blob) const
int hpad = kernel_h + (h - 1) / stride_h * stride_h - h;
if (wpad > 0 || hpad > 0)
{
copy_make_border(bottom_blob, bottom_blob_bordered, hpad / 2, hpad - hpad / 2, wpad / 2, wpad - wpad / 2, BORDER_CONSTANT, 0.f);
copy_make_border(bottom_blob, bottom_blob_bordered, hpad / 2, hpad - hpad / 2, wpad / 2, wpad - wpad / 2, BORDER_CONSTANT, pad_value);
if (bottom_blob_bordered.empty())
return -100;
}
@@ -124,45 +156,6 @@ int Pooling::forward(const Mat& bottom_blob, Mat& top_blob) const
int outw = (w - kernel_w) / stride_w + 1;
int outh = (h - kernel_h) / stride_h + 1;

int wtail = 0;
int htail = 0;
if (pad_mode == 0) // full padding
{
wtail = (w - kernel_w) % stride_w;
htail = (h - kernel_h) % stride_h;
}
if (wtail != 0 || htail != 0)
{
int wtailpad = 0;
int htailpad = 0;
if (wtail != 0)
wtailpad = kernel_w - wtail;
if (htail != 0)
htailpad = kernel_h - htail;

Mat bottom_blob_bordered2;
if (pooling_type == PoolMethod_MAX)
{
copy_make_border(bottom_blob_bordered, bottom_blob_bordered2, 0, htailpad, 0, wtailpad, BORDER_REPLICATE, 0.f);
}
else if (pooling_type == PoolMethod_AVE)
{
copy_make_border(bottom_blob_bordered, bottom_blob_bordered2, 0, htailpad, 0, wtailpad, BORDER_CONSTANT, 0.f);
}
if (bottom_blob_bordered2.empty())
return -100;

bottom_blob_bordered = bottom_blob_bordered2;

w = bottom_blob_bordered.w;
h = bottom_blob_bordered.h;

if (wtail != 0)
outw += 1;
if (htail != 0)
outh += 1;
}

top_blob.create(outw, outh, channels);
if (top_blob.empty())
return -100;
@@ -245,27 +238,48 @@ int Pooling::forward(const Mat& bottom_blob, Mat& top_blob) const
outptr += outw;
}

// fix tail pad
if (wtail != 0)
// fix pad
if (pad_top != 0)
{
const float scale = (float)kernel_h / (kernel_h - pad_top);

outptr = top_blob.channel(q).row(0);
for (int i = 0; i < outw; i++)
{
outptr[i] *= scale;
}
}
if (pad_bottom + htailpad != 0)
{
const float scale = (float)kernel_h / (kernel_h - pad_bottom - htailpad);

outptr = top_blob.channel(q).row(outh - 1);
for (int i = 0; i < outw; i++)
{
outptr[i] *= scale;
}
}
if (pad_left != 0)
{
const float scale = (float)kernel_w / (kernel_w - wtail);
const float scale = (float)kernel_w / (kernel_w - pad_left);

outptr = top_blob.channel(q);
outptr += outw - 1;
for (int i = 0; i < outh; i++)
{
*outptr *= scale;
outptr += outw;
}
}
if (htail != 0)
if (pad_right + wtailpad != 0)
{
const float scale = (float)kernel_h / (kernel_h - htail);
const float scale = (float)kernel_w / (kernel_w - pad_right - wtailpad);

outptr = top_blob.channel(q).row(outh - 1);
for (int i = 0; i < outw; i++)
outptr = top_blob.channel(q);
outptr += outw - 1;
for (int i = 0; i < outh; i++)
{
outptr[i] *= scale;
*outptr *= scale;
outptr += outw;
}
}
}


+ 4
- 2
src/layer/pooling.h View File

@@ -37,8 +37,10 @@ public:
int kernel_h;
int stride_w;
int stride_h;
int pad_w;
int pad_h;
int pad_left;
int pad_right;
int pad_top;
int pad_bottom;
int global_pooling;
int pad_mode;// 0=full 1=valid 2=SAME
};


Loading…
Cancel
Save