From 6b91c0aeab041cc84817ec37019bdad12b4e0bcf Mon Sep 17 00:00:00 2001 From: Sergio Date: Sun, 13 Apr 2014 19:49:02 -0700 Subject: [PATCH] Added max_idx to Pooling layer CPU --- include/caffe/vision_layers.hpp | 1 + src/caffe/layers/pooling_layer.cpp | 35 +++++++++++++++++++---------------- src/caffe/test/test_pooling_layer.cpp | 27 +++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 16 deletions(-) diff --git a/include/caffe/vision_layers.hpp b/include/caffe/vision_layers.hpp index 07ab577..c0bbd37 100644 --- a/include/caffe/vision_layers.hpp +++ b/include/caffe/vision_layers.hpp @@ -350,6 +350,7 @@ class PoolingLayer : public Layer { int pooled_height_; int pooled_width_; Blob rand_idx_; + shared_ptr max_idx_; }; /* SoftmaxLayer diff --git a/src/caffe/layers/pooling_layer.cpp b/src/caffe/layers/pooling_layer.cpp index 7e880a2..63ea12d 100644 --- a/src/caffe/layers/pooling_layer.cpp +++ b/src/caffe/layers/pooling_layer.cpp @@ -4,8 +4,10 @@ #include #include +#include "caffe/common.hpp" #include "caffe/layer.hpp" #include "caffe/vision_layers.hpp" +#include "caffe/syncedmem.hpp" #include "caffe/util/math_functions.hpp" using std::max; @@ -35,6 +37,10 @@ void PoolingLayer::SetUp(const vector*>& bottom, width_ + 2 * pad_ - kernel_size_) / stride_)) + 1; (*top)[0]->Reshape(bottom[0]->num(), channels_, pooled_height_, pooled_width_); + // If max pooling, we will initialize the vector index part. + if (this->layer_param_.pool() == LayerParameter_PoolMethod_MAX) { + max_idx_.reset(new SyncedMemory((*top)[0]->count() * sizeof(int))); + } // If stochastic pooling, we will initialize the random index part. if (this->layer_param_.pooling_param().pool() == PoolingParameter_PoolMethod_STOCHASTIC) { @@ -53,11 +59,14 @@ Dtype PoolingLayer::Forward_cpu(const vector*>& bottom, // Different pooling methods. We explicitly do the switch outside the for // loop to save time, although this results in more codes. int top_count = (*top)[0]->count(); + int* mask; switch (this->layer_param_.pooling_param().pool()) { case PoolingParameter_PoolMethod_MAX: - // Initialize + // Initialize + mask = (int*)max_idx_->mutable_cpu_data(); for (int i = 0; i < top_count; ++i) { top_data[i] = -FLT_MAX; + mask[i] = 0; } // The main loop for (int n = 0; n < bottom[0]->num(); ++n) { @@ -70,9 +79,10 @@ Dtype PoolingLayer::Forward_cpu(const vector*>& bottom, int wend = min(wstart + kernel_size_, width_); for (int h = hstart; h < hend; ++h) { for (int w = wstart; w < wend; ++w) { - top_data[ph * pooled_width_ + pw] = - max(top_data[ph * pooled_width_ + pw], - bottom_data[h * width_ + w]); + if (bottom_data[h * width_ + w] > top_data[ph * pooled_width_ + pw]) { + top_data[ph * pooled_width_ + pw] = bottom_data[h * width_ + w]; + mask[ph * pooled_width_ + pw] = h * width_ + w; + } } } } @@ -80,6 +90,7 @@ Dtype PoolingLayer::Forward_cpu(const vector*>& bottom, // compute offset bottom_data += bottom[0]->offset(0, 1); top_data += (*top)[0]->offset(0, 1); + mask += (*top)[0]->offset(0, 1); } } break; @@ -138,25 +149,16 @@ void PoolingLayer::Backward_cpu(const vector*>& top, // Different pooling methods. We explicitly do the switch outside the for // loop to save time, although this results in more codes. memset(bottom_diff, 0, (*bottom)[0]->count() * sizeof(Dtype)); + int* mask; switch (this->layer_param_.pooling_param().pool()) { case PoolingParameter_PoolMethod_MAX: // The main loop + mask = (int*)max_idx_->cpu_data(); for (int n = 0; n < top[0]->num(); ++n) { for (int c = 0; c < channels_; ++c) { for (int ph = 0; ph < pooled_height_; ++ph) { for (int pw = 0; pw < pooled_width_; ++pw) { - int hstart = ph * stride_; - int wstart = pw * stride_; - int hend = min(hstart + kernel_size_, height_); - int wend = min(wstart + kernel_size_, width_); - for (int h = hstart; h < hend; ++h) { - for (int w = wstart; w < wend; ++w) { - bottom_diff[h * width_ + w] += - top_diff[ph * pooled_width_ + pw] * - (bottom_data[h * width_ + w] == - top_data[ph * pooled_width_ + pw]); - } - } + bottom_diff[mask[ph * pooled_width_ + pw]]+=top_diff[ph * pooled_width_ + pw]; } } // offset @@ -164,6 +166,7 @@ void PoolingLayer::Backward_cpu(const vector*>& top, top_data += top[0]->offset(0, 1); bottom_diff += (*bottom)[0]->offset(0, 1); top_diff += top[0]->offset(0, 1); + mask += top[0]->offset(0, 1); } } break; diff --git a/src/caffe/test/test_pooling_layer.cpp b/src/caffe/test/test_pooling_layer.cpp index 41d4841..11bbd14 100644 --- a/src/caffe/test/test_pooling_layer.cpp +++ b/src/caffe/test/test_pooling_layer.cpp @@ -99,6 +99,33 @@ TYPED_TEST(PoolingLayerTest, PrintGPUBackward) { } */ +/* +TYPED_TEST(PoolingLayerTest, PrintCPUBackward) { + LayerParameter layer_param; + layer_param.set_kernelsize(3); + layer_param.set_stride(2); + layer_param.set_pool(LayerParameter_PoolMethod_MAX); + Caffe::set_mode(Caffe::CPU); + PoolingLayer layer(layer_param); + layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + for (int i = 0; i < this->blob_bottom_->count(); ++i) { + cout << "bottom data " << i << " " << this->blob_bottom_->cpu_data()[i] << endl; + } + for (int i = 0; i < this->blob_top_->count(); ++i) { + cout << "top data " << i << " " << this->blob_top_->cpu_data()[i] << endl; + } + + for (int i = 0; i < this->blob_top_->count(); ++i) { + this->blob_top_->mutable_cpu_diff()[i] = i; + } + layer.Backward(this->blob_top_vec_, true, &(this->blob_bottom_vec_)); + for (int i = 0; i < this->blob_bottom_->count(); ++i) { + cout << "bottom diff " << i << " " << this->blob_bottom_->cpu_diff()[i] << endl; + } +} +*/ + TYPED_TEST(PoolingLayerTest, TestCPUGradientMax) { LayerParameter layer_param; PoolingParameter* pooling_param = layer_param.mutable_pooling_param(); -- 2.7.4