stochastic pooling test
[jacinto-ai/caffe-jacinto.git] / src / caffe / test / test_stochastic_pooing.cpp
1 // Copyright 2013 Yangqing Jia
3 #include <cstring>
4 #include <cuda_runtime.h>
6 #include "gtest/gtest.h"
7 #include "caffe/blob.hpp"
8 #include "caffe/common.hpp"
9 #include "caffe/filler.hpp"
10 #include "caffe/vision_layers.hpp"
11 #include "caffe/test/test_gradient_check_util.hpp"
13 #include "caffe/test/test_caffe_main.hpp"
15 namespace caffe {
17 extern cudaDeviceProp CAFFE_TEST_CUDA_PROP;
19 template <typename Dtype>
20 class StochasticPoolingLayerTest : public ::testing::Test {
21  protected:
22   StochasticPoolingLayerTest()
23       : blob_bottom_(new Blob<Dtype>()),
24         blob_top_(new Blob<Dtype>()) {};
25   virtual void SetUp() {
26     Caffe::set_random_seed(1701);
27     blob_bottom_->Reshape(2, 3, 6, 5);
28     // fill the values
29     FillerParameter filler_param;
30     filler_param.set_min(0.1);
31     filler_param.set_max(1.);
32     UniformFiller<Dtype> filler(filler_param);
33     filler.Fill(this->blob_bottom_);
34     blob_bottom_vec_.push_back(blob_bottom_);
35     blob_top_vec_.push_back(blob_top_);
36   };
38   virtual ~StochasticPoolingLayerTest() {
39     delete blob_bottom_; delete blob_top_;
40   }
42   Blob<Dtype>* const blob_bottom_;
43   Blob<Dtype>* const blob_top_;
44   vector<Blob<Dtype>*> blob_bottom_vec_;
45   vector<Blob<Dtype>*> blob_top_vec_;
46 };
48 typedef ::testing::Types<float, double> Dtypes;
49 TYPED_TEST_CASE(StochasticPoolingLayerTest, Dtypes);
51 TYPED_TEST(StochasticPoolingLayerTest, TestSetup) {
52   LayerParameter layer_param;
53   layer_param.set_kernelsize(3);
54   layer_param.set_stride(2);
55   PoolingLayer<TypeParam> layer(layer_param);
56   layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_));
57   EXPECT_EQ(this->blob_top_->num(), this->blob_bottom_->num());
58   EXPECT_EQ(this->blob_top_->channels(), this->blob_bottom_->channels());
59   EXPECT_EQ(this->blob_top_->height(), 3);
60   EXPECT_EQ(this->blob_top_->width(), 2);
61 }
63 TYPED_TEST(StochasticPoolingLayerTest, TestStochasticGPU) {
64   Caffe::set_mode(Caffe::GPU);
65   Caffe::set_phase(Caffe::TRAIN);
66   LayerParameter layer_param;
67   layer_param.set_kernelsize(3);
68   layer_param.set_stride(2);
70   layer_param.set_pool(LayerParameter_PoolMethod_STOCHASTIC);
71   PoolingLayer<TypeParam> layer(layer_param);
72   layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_));
73   layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_));
75   // Check if the output is correct - it should do random sampling
76   const TypeParam* bottom_data = this->blob_bottom_->cpu_data();
77   const TypeParam* top_data = this->blob_top_->cpu_data();
78   TypeParam total = 0;
79   for (int n = 0; n < this->blob_top_->num(); ++n) {
80     for (int c = 0; c < this->blob_top_->channels(); ++c) {
81       for (int ph = 0; ph < this->blob_top_->height(); ++ph) {
82         for (int pw = 0; pw < this->blob_top_->width(); ++pw) {
83           TypeParam pooled = top_data[this->blob_top_->offset(n, c, ph, pw)];
84           total += pooled;
85           int hstart = ph * 2;
86           int hend = min(hstart + 3, this->blob_bottom_->height());
87           int wstart = pw * 2;
88           int wend = min(wstart + 3, this->blob_bottom_->width());
89           bool has_equal = false;
90           for (int h = hstart; h < hend; ++h) {
91             for (int w = wstart; w < wend; ++w) {
92               has_equal |= (pooled == bottom_data[this->blob_bottom_->offset(n, c, h, w)]);
93             }
94           }
95           EXPECT_TRUE(has_equal);
96         }
97       }
98     }
99   }
100   // When we are doing stochastic pooling, the average we get should be higher
101   // than the simple data average since we are weighting more on higher-valued
102   // ones.
103   EXPECT_GE(total / this->blob_top_->count(), 0.55);
106 TYPED_TEST(StochasticPoolingLayerTest, TestStochasticGPUTestPhase) {
107   Caffe::set_mode(Caffe::GPU);
108   Caffe::set_phase(Caffe::TEST);
109   LayerParameter layer_param;
110   layer_param.set_kernelsize(3);
111   layer_param.set_stride(2);
113   layer_param.set_pool(LayerParameter_PoolMethod_STOCHASTIC);
114   PoolingLayer<TypeParam> layer(layer_param);
115   layer.SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_));
116   layer.Forward(this->blob_bottom_vec_, &(this->blob_top_vec_));
118   // Check if the output is correct - it should do random sampling
119   const TypeParam* bottom_data = this->blob_bottom_->cpu_data();
120   const TypeParam* top_data = this->blob_top_->cpu_data();
121   for (int n = 0; n < this->blob_top_->num(); ++n) {
122     for (int c = 0; c < this->blob_top_->channels(); ++c) {
123       for (int ph = 0; ph < this->blob_top_->height(); ++ph) {
124         for (int pw = 0; pw < this->blob_top_->width(); ++pw) {
125           TypeParam pooled = top_data[this->blob_top_->offset(n, c, ph, pw)];
126           int hstart = ph * 2;
127           int hend = min(hstart + 3, this->blob_bottom_->height());
128           int wstart = pw * 2;
129           int wend = min(wstart + 3, this->blob_bottom_->width());
130           bool smaller_than_max = false;
131           for (int h = hstart; h < hend; ++h) {
132             for (int w = wstart; w < wend; ++w) {
133               smaller_than_max |= (pooled <= bottom_data[this->blob_bottom_->offset(n, c, h, w)]);
134             }
135           }
136           EXPECT_TRUE(smaller_than_max);
137         }
138       }
139     }
140   }
145 TYPED_TEST(StochasticPoolingLayerTest, TestGradientGPU) {
146   Caffe::set_mode(Caffe::GPU);
147   Caffe::set_phase(Caffe::TRAIN);
148   LayerParameter layer_param;
149   layer_param.set_kernelsize(3);
150   layer_param.set_stride(2);
152   layer_param.set_pool(LayerParameter_PoolMethod_STOCHASTIC);
153   PoolingLayer<TypeParam> layer(layer_param);
154   GradientChecker<TypeParam> checker(1e-2, 1e-3);
155   // it is too expensive to call curand multiple times, so we don't do an
156   // exhaustive gradient check.
157   checker.CheckGradient(layer, this->blob_bottom_vec_, this->blob_top_vec_);