Caffe
base_conv_layer.hpp
1 #ifndef CAFFE_BASE_CONVOLUTION_LAYER_HPP_
2 #define CAFFE_BASE_CONVOLUTION_LAYER_HPP_
3 
4 #include <vector>
5 
6 #include "caffe/blob.hpp"
7 #include "caffe/layer.hpp"
8 #include "caffe/proto/caffe.pb.h"
9 #include "caffe/util/im2col.hpp"
10 
11 namespace caffe {
12 
17 template <typename Dtype>
18 class BaseConvolutionLayer : public Layer<Dtype> {
19  public:
20  explicit BaseConvolutionLayer(const LayerParameter& param)
21  : Layer<Dtype>(param) {}
22  virtual void LayerSetUp(const vector<Blob<Dtype>*>& bottom,
23  const vector<Blob<Dtype>*>& top);
24  virtual void Reshape(const vector<Blob<Dtype>*>& bottom,
25  const vector<Blob<Dtype>*>& top);
26 
27  virtual inline int MinBottomBlobs() const { return 1; }
28  virtual inline int MinTopBlobs() const { return 1; }
29  virtual inline bool EqualNumBottomTopBlobs() const { return true; }
30 
31  protected:
32  // Helper functions that abstract away the column buffer and gemm arguments.
33  // The last argument in forward_cpu_gemm is so that we can skip the im2col if
34  // we just called weight_cpu_gemm with the same input.
35  void forward_cpu_gemm(const Dtype* input, const Dtype* weights,
36  Dtype* output, bool skip_im2col = false);
37  void forward_cpu_bias(Dtype* output, const Dtype* bias);
38  void backward_cpu_gemm(const Dtype* input, const Dtype* weights,
39  Dtype* output);
40  void weight_cpu_gemm(const Dtype* input, const Dtype* output, Dtype*
41  weights);
42  void backward_cpu_bias(Dtype* bias, const Dtype* input);
43 
44 #ifndef CPU_ONLY
45  void forward_gpu_gemm(const Dtype* col_input, const Dtype* weights,
46  Dtype* output, bool skip_im2col = false);
47  void forward_gpu_bias(Dtype* output, const Dtype* bias);
48  void backward_gpu_gemm(const Dtype* input, const Dtype* weights,
49  Dtype* col_output);
50  void weight_gpu_gemm(const Dtype* col_input, const Dtype* output, Dtype*
51  weights);
52  void backward_gpu_bias(Dtype* bias, const Dtype* input);
53 #endif
54 
56  inline int input_shape(int i) {
57  return (*bottom_shape_)[channel_axis_ + i];
58  }
59  // reverse_dimensions should return true iff we are implementing deconv, so
60  // that conv helpers know which dimensions are which.
61  virtual bool reverse_dimensions() = 0;
62  // Compute height_out_ and width_out_ from other parameters.
63  virtual void compute_output_shape() = 0;
64 
76  vector<int> col_buffer_shape_;
78  vector<int> output_shape_;
79  const vector<int>* bottom_shape_;
80 
81  int num_spatial_axes_;
82  int bottom_dim_;
83  int top_dim_;
84 
85  int channel_axis_;
86  int num_;
87  int channels_;
88  int group_;
89  int out_spatial_dim_;
90  int weight_offset_;
91  int num_output_;
92  bool bias_term_;
93  bool is_1x1_;
94  bool force_nd_im2col_;
95 
96  private:
97  // wrap im2col/col2im so we don't have to remember the (long) argument lists
98  inline void conv_im2col_cpu(const Dtype* data, Dtype* col_buff) {
99  if (!force_nd_im2col_ && num_spatial_axes_ == 2) {
100  im2col_cpu(data, conv_in_channels_,
101  conv_input_shape_.cpu_data()[1], conv_input_shape_.cpu_data()[2],
102  kernel_shape_.cpu_data()[0], kernel_shape_.cpu_data()[1],
103  pad_.cpu_data()[0], pad_.cpu_data()[1],
104  stride_.cpu_data()[0], stride_.cpu_data()[1],
105  dilation_.cpu_data()[0], dilation_.cpu_data()[1], col_buff);
106  } else {
107  im2col_nd_cpu(data, num_spatial_axes_, conv_input_shape_.cpu_data(),
108  col_buffer_shape_.data(), kernel_shape_.cpu_data(),
109  pad_.cpu_data(), stride_.cpu_data(), dilation_.cpu_data(), col_buff);
110  }
111  }
112  inline void conv_col2im_cpu(const Dtype* col_buff, Dtype* data) {
113  if (!force_nd_im2col_ && num_spatial_axes_ == 2) {
114  col2im_cpu(col_buff, conv_in_channels_,
115  conv_input_shape_.cpu_data()[1], conv_input_shape_.cpu_data()[2],
116  kernel_shape_.cpu_data()[0], kernel_shape_.cpu_data()[1],
117  pad_.cpu_data()[0], pad_.cpu_data()[1],
118  stride_.cpu_data()[0], stride_.cpu_data()[1],
119  dilation_.cpu_data()[0], dilation_.cpu_data()[1], data);
120  } else {
121  col2im_nd_cpu(col_buff, num_spatial_axes_, conv_input_shape_.cpu_data(),
122  col_buffer_shape_.data(), kernel_shape_.cpu_data(),
123  pad_.cpu_data(), stride_.cpu_data(), dilation_.cpu_data(), data);
124  }
125  }
126 #ifndef CPU_ONLY
127  inline void conv_im2col_gpu(const Dtype* data, Dtype* col_buff) {
128  if (!force_nd_im2col_ && num_spatial_axes_ == 2) {
129  im2col_gpu(data, conv_in_channels_,
130  conv_input_shape_.cpu_data()[1], conv_input_shape_.cpu_data()[2],
131  kernel_shape_.cpu_data()[0], kernel_shape_.cpu_data()[1],
132  pad_.cpu_data()[0], pad_.cpu_data()[1],
133  stride_.cpu_data()[0], stride_.cpu_data()[1],
134  dilation_.cpu_data()[0], dilation_.cpu_data()[1], col_buff);
135  } else {
136  im2col_nd_gpu(data, num_spatial_axes_, num_kernels_im2col_,
137  conv_input_shape_.gpu_data(), col_buffer_.gpu_shape(),
138  kernel_shape_.gpu_data(), pad_.gpu_data(),
139  stride_.gpu_data(), dilation_.gpu_data(), col_buff);
140  }
141  }
142  inline void conv_col2im_gpu(const Dtype* col_buff, Dtype* data) {
143  if (!force_nd_im2col_ && num_spatial_axes_ == 2) {
144  col2im_gpu(col_buff, conv_in_channels_,
145  conv_input_shape_.cpu_data()[1], conv_input_shape_.cpu_data()[2],
146  kernel_shape_.cpu_data()[0], kernel_shape_.cpu_data()[1],
147  pad_.cpu_data()[0], pad_.cpu_data()[1],
148  stride_.cpu_data()[0], stride_.cpu_data()[1],
149  dilation_.cpu_data()[0], dilation_.cpu_data()[1], data);
150  } else {
151  col2im_nd_gpu(col_buff, num_spatial_axes_, num_kernels_col2im_,
152  conv_input_shape_.gpu_data(), col_buffer_.gpu_shape(),
153  kernel_shape_.gpu_data(), pad_.gpu_data(), stride_.gpu_data(),
154  dilation_.gpu_data(), data);
155  }
156  }
157 #endif
158 
159  int num_kernels_im2col_;
160  int num_kernels_col2im_;
161  int conv_out_channels_;
162  int conv_in_channels_;
163  int conv_out_spatial_dim_;
164  int kernel_dim_;
165  int col_offset_;
166  int output_offset_;
167 
168  Blob<Dtype> col_buffer_;
169  Blob<Dtype> bias_multiplier_;
170 };
171 
172 } // namespace caffe
173 
174 #endif // CAFFE_BASE_CONVOLUTION_LAYER_HPP_
Blob< int > kernel_shape_
The spatial dimensions of a filter kernel.
Definition: base_conv_layer.hpp:66
An interface for the units of computation which can be composed into a Net.
Definition: layer.hpp:33
A layer factory that allows one to register layers. During runtime, registered layers can be called b...
Definition: blob.hpp:14
int input_shape(int i)
The spatial dimensions of the input.
Definition: base_conv_layer.hpp:56
virtual void LayerSetUp(const vector< Blob< Dtype > *> &bottom, const vector< Blob< Dtype > *> &top)
Does layer-specific setup: your layer should implement this function as well as Reshape.
Definition: base_conv_layer.cpp:12
Abstract base class that factors out the BLAS code common to ConvolutionLayer and DeconvolutionLayer...
Definition: base_conv_layer.hpp:18
virtual bool EqualNumBottomTopBlobs() const
Returns true if the layer requires an equal number of bottom and top blobs.
Definition: base_conv_layer.hpp:29
virtual int MinBottomBlobs() const
Returns the minimum number of bottom blobs required by the layer, or -1 if no minimum number is requi...
Definition: base_conv_layer.hpp:27
Blob< int > pad_
The spatial dimensions of the padding.
Definition: base_conv_layer.hpp:70
virtual int MinTopBlobs() const
Returns the minimum number of top blobs required by the layer, or -1 if no minimum number is required...
Definition: base_conv_layer.hpp:28
vector< int > col_buffer_shape_
The spatial dimensions of the col_buffer.
Definition: base_conv_layer.hpp:76
vector< int > output_shape_
The spatial dimensions of the output.
Definition: base_conv_layer.hpp:78
virtual void Reshape(const vector< Blob< Dtype > *> &bottom, const vector< Blob< Dtype > *> &top)
Adjust the shapes of top blobs and internal buffers to accommodate the shapes of the bottom blobs...
Definition: base_conv_layer.cpp:185
Blob< int > conv_input_shape_
The spatial dimensions of the convolution input.
Definition: base_conv_layer.hpp:74
Blob< int > stride_
The spatial dimensions of the stride.
Definition: base_conv_layer.hpp:68
A wrapper around SyncedMemory holders serving as the basic computational unit through which Layers...
Definition: blob.hpp:24
Blob< int > dilation_
The spatial dimensions of the dilation.
Definition: base_conv_layer.hpp:72