From 43fb9ca393cb67f23572eb88f4f19d8b8de505f7 Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Wed, 24 Dec 2014 14:48:40 -0800 Subject: [PATCH 1/3] add util/coords.hpp for coordinate mapping functions This will be useful for keeping track of the coordinate transformations induced by, e.g., convolution and pooling layers. --- include/caffe/util/coords.hpp | 50 +++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 include/caffe/util/coords.hpp diff --git a/include/caffe/util/coords.hpp b/include/caffe/util/coords.hpp new file mode 100644 index 00000000000..8fbadc36a29 --- /dev/null +++ b/include/caffe/util/coords.hpp @@ -0,0 +1,50 @@ +#ifndef CAFFE_UTIL_COORDS_H_ +#define CAFFE_UTIL_COORDS_H_ + +#include +#include +#include + +namespace caffe { + +template +class DiagonalAffineMap { + public: + explicit DiagonalAffineMap(const vector > coefs) + : coefs_(coefs) { } + static DiagonalAffineMap identity(const int nd) { + return DiagonalAffineMap(vector >(nd, make_pair(1, 0))); + } + + inline DiagonalAffineMap compose(const DiagonalAffineMap& other) const { + CHECK_EQ(coefs_.size(), other.coefs_.size()) + << "Attempt to compose DiagonalAffineMaps of different dimensions"; + DiagonalAffineMap out; + transform(coefs_.begin(), coefs_.end(), other.coefs_.begin(), + std::back_inserter(out.coefs_), &compose_coefs); + return out; + } + inline DiagonalAffineMap inv() const { + DiagonalAffineMap out; + transform(coefs_.begin(), coefs_.end(), std::back_inserter(out.coefs_), + &inv_coefs); + return out; + } + inline vector > coefs() { return coefs_; } + + private: + DiagonalAffineMap() { } + static inline pair compose_coefs(pair left, + pair right) { + return make_pair(left.first * right.first, + left.first * right.second + left.second); + } + static inline pair inv_coefs(pair coefs) { + return make_pair(1 / coefs.first, - coefs.second / coefs.first); + } + vector > coefs_; +}; + +} // namespace caffe + +#endif // CAFFE_UTIL_COORDS_H_ From 60389112bc7748886d7f4b2ea9a93b1a7f170f00 Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Thu, 25 Dec 2014 14:31:07 -0800 Subject: [PATCH 2/3] add FilterMap for the coord mapping used by (de)conv and pooling layers --- include/caffe/util/coords.hpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/include/caffe/util/coords.hpp b/include/caffe/util/coords.hpp index 8fbadc36a29..5032fc60abd 100644 --- a/include/caffe/util/coords.hpp +++ b/include/caffe/util/coords.hpp @@ -45,6 +45,17 @@ class DiagonalAffineMap { vector > coefs_; }; +template +DiagonalAffineMap FilterMap(const int kernel_h, const int kernel_w, + const int stride_h, const int stride_w, const int pad_h, const int pad_w) { + vector > coefs; + coefs.push_back(make_pair(stride_h, + static_cast(kernel_h - 1) / 2 - pad_h)); + coefs.push_back(make_pair(stride_w, + static_cast(kernel_w - 1) / 2 - pad_w)); + return DiagonalAffineMap(coefs); +} + } // namespace caffe #endif // CAFFE_UTIL_COORDS_H_ From 918ac729c5f513e6bb477db74e64d0eb6ecc7f12 Mon Sep 17 00:00:00 2001 From: Jonathan L Long Date: Thu, 25 Dec 2014 14:34:54 -0800 Subject: [PATCH 3/3] implement coord_map for all applicable layers --- include/caffe/common_layers.hpp | 18 ++++++++++++++++++ include/caffe/layer.hpp | 8 ++++++++ include/caffe/neuron_layers.hpp | 3 +++ include/caffe/vision_layers.hpp | 16 +++++++++++++++- 4 files changed, 44 insertions(+), 1 deletion(-) diff --git a/include/caffe/common_layers.hpp b/include/caffe/common_layers.hpp index c67822c3738..07966e84bbd 100644 --- a/include/caffe/common_layers.hpp +++ b/include/caffe/common_layers.hpp @@ -87,6 +87,9 @@ class ConcatLayer : public Layer { virtual inline const char* type() const { return "Concat"; } virtual inline int MinBottomBlobs() const { return 2; } virtual inline int ExactNumTopBlobs() const { return 1; } + virtual inline DiagonalAffineMap coord_map() { + return DiagonalAffineMap::identity(2); + } protected: /** @@ -165,6 +168,9 @@ class EltwiseLayer : public Layer { virtual inline const char* type() const { return "Eltwise"; } virtual inline int MinBottomBlobs() const { return 2; } virtual inline int ExactNumTopBlobs() const { return 1; } + virtual inline DiagonalAffineMap coord_map() { + return DiagonalAffineMap::identity(2); + } protected: virtual void Forward_cpu(const vector*>& bottom, @@ -289,6 +295,9 @@ class MVNLayer : public Layer { virtual inline const char* type() const { return "MVN"; } virtual inline int ExactNumBottomBlobs() const { return 1; } virtual inline int ExactNumTopBlobs() const { return 1; } + virtual inline DiagonalAffineMap coord_map() { + return DiagonalAffineMap::identity(2); + } protected: virtual void Forward_cpu(const vector*>& bottom, @@ -351,6 +360,9 @@ class SoftmaxLayer : public Layer { virtual inline const char* type() const { return "Softmax"; } virtual inline int ExactNumBottomBlobs() const { return 1; } virtual inline int ExactNumTopBlobs() const { return 1; } + virtual inline DiagonalAffineMap coord_map() { + return DiagonalAffineMap::identity(2); + } protected: virtual void Forward_cpu(const vector*>& bottom, @@ -414,6 +426,9 @@ class SplitLayer : public Layer { virtual inline const char* type() const { return "Split"; } virtual inline int ExactNumBottomBlobs() const { return 1; } virtual inline int MinTopBlobs() const { return 1; } + virtual inline DiagonalAffineMap coord_map() { + return DiagonalAffineMap::identity(2); + } protected: virtual void Forward_cpu(const vector*>& bottom, @@ -447,6 +462,9 @@ class SliceLayer : public Layer { virtual inline const char* type() const { return "Slice"; } virtual inline int ExactNumBottomBlobs() const { return 1; } virtual inline int MinTopBlobs() const { return 2; } + virtual inline DiagonalAffineMap coord_map() { + return DiagonalAffineMap::identity(2); + } protected: virtual void Forward_cpu(const vector*>& bottom, diff --git a/include/caffe/layer.hpp b/include/caffe/layer.hpp index 34e00d72c05..6122e0139a3 100644 --- a/include/caffe/layer.hpp +++ b/include/caffe/layer.hpp @@ -3,12 +3,14 @@ #include #include +#include #include #include "caffe/blob.hpp" #include "caffe/common.hpp" #include "caffe/layer_factory.hpp" #include "caffe/proto/caffe.pb.h" +#include "caffe/util/coords.hpp" #include "caffe/util/device_alternate.hpp" namespace caffe { @@ -285,6 +287,12 @@ class Layer { param_propagate_down_[param_id] = value; } + virtual DiagonalAffineMap coord_map() { + NOT_IMPLEMENTED; + // suppress warnings + return DiagonalAffineMap(vector >()); + } + protected: /** The protobuf that stores the layer parameters */ diff --git a/include/caffe/neuron_layers.hpp b/include/caffe/neuron_layers.hpp index 0c306fb41bf..1feebf4c119 100644 --- a/include/caffe/neuron_layers.hpp +++ b/include/caffe/neuron_layers.hpp @@ -32,6 +32,9 @@ class NeuronLayer : public Layer { virtual inline int ExactNumBottomBlobs() const { return 1; } virtual inline int ExactNumTopBlobs() const { return 1; } + virtual inline DiagonalAffineMap coord_map() { + return DiagonalAffineMap::identity(2); + } }; /** diff --git a/include/caffe/vision_layers.hpp b/include/caffe/vision_layers.hpp index 6cb507a5780..f454c458c77 100644 --- a/include/caffe/vision_layers.hpp +++ b/include/caffe/vision_layers.hpp @@ -162,6 +162,10 @@ class ConvolutionLayer : public BaseConvolutionLayer { : BaseConvolutionLayer(param) {} virtual inline const char* type() const { return "Convolution"; } + virtual inline DiagonalAffineMap coord_map() { + return FilterMap(this->kernel_h_, this->kernel_w_, this->stride_h_, + this->stride_w_, this->pad_h_, this->pad_w_).inv(); + } protected: virtual void Forward_cpu(const vector*>& bottom, @@ -195,8 +199,11 @@ class DeconvolutionLayer : public BaseConvolutionLayer { public: explicit DeconvolutionLayer(const LayerParameter& param) : BaseConvolutionLayer(param) {} - virtual inline const char* type() const { return "Deconvolution"; } + virtual inline DiagonalAffineMap coord_map() { + return FilterMap(this->kernel_h_, this->kernel_w_, this->stride_h_, + this->stride_w_, this->pad_h_, this->pad_w_); + } protected: virtual void Forward_cpu(const vector*>& bottom, @@ -314,6 +321,9 @@ class LRNLayer : public Layer { virtual inline const char* type() const { return "LRN"; } virtual inline int ExactNumBottomBlobs() const { return 1; } virtual inline int ExactNumTopBlobs() const { return 1; } + virtual inline DiagonalAffineMap coord_map() { + return DiagonalAffineMap::identity(2); + } protected: virtual void Forward_cpu(const vector*>& bottom, @@ -396,6 +406,10 @@ class PoolingLayer : public Layer { return (this->layer_param_.pooling_param().pool() == PoolingParameter_PoolMethod_MAX) ? 2 : 1; } + virtual inline DiagonalAffineMap coord_map() { + return FilterMap(kernel_h_, kernel_w_, stride_h_, stride_w_, + pad_h_, pad_w_).inv(); + } protected: virtual void Forward_cpu(const vector*>& bottom,