mlpack  master
naive_convolution.hpp
Go to the documentation of this file.
1 
13 #ifndef MLPACK_METHODS_ANN_CONVOLUTION_RULES_NAIVE_CONVOLUTION_HPP
14 #define MLPACK_METHODS_ANN_CONVOLUTION_RULES_NAIVE_CONVOLUTION_HPP
15 
16 #include <mlpack/prereqs.hpp>
17 #include "border_modes.hpp"
18 
19 namespace mlpack {
20 namespace ann {
21 
34 template<typename BorderMode = FullConvolution>
36 {
37  public:
38  /*
39  * Perform a convolution (valid mode).
40  *
41  * @param input Input used to perform the convolution.
42  * @param filter Filter used to perform the conolution.
43  * @param output Output data that contains the results of the convolution.
44  * @param dW Stride of filter application in the x direction.
45  * @param dH Stride of filter application in the y direction.
46  */
47  template<typename eT, typename Border = BorderMode>
48  static typename std::enable_if<
49  std::is_same<Border, ValidConvolution>::value, void>::type
50  Convolution(const arma::Mat<eT>& input,
51  const arma::Mat<eT>& filter,
52  arma::Mat<eT>& output,
53  const size_t dW = 1,
54  const size_t dH = 1)
55  {
56  output = arma::zeros<arma::Mat<eT> >((input.n_rows - filter.n_rows + 1) /
57  dW, (input.n_cols - filter.n_cols + 1) / dH);
58 
59  // It seems to be about 3.5 times faster to use pointers instead of
60  // filter(ki, kj) * input(leftInput + ki, topInput + kj) and output(i, j).
61  eT* outputPtr = output.memptr();
62 
63  for (size_t j = 0; j < output.n_cols; ++j)
64  {
65  for (size_t i = 0; i < output.n_rows; ++i, outputPtr++)
66  {
67  const eT* kernelPtr = filter.memptr();
68  for (size_t kj = 0; kj < filter.n_cols; ++kj)
69  {
70  const eT* inputPtr = input.colptr(kj + j * dW) + i * dH;
71  for (size_t ki = 0; ki < filter.n_rows; ++ki, ++kernelPtr, ++inputPtr)
72  *outputPtr += *kernelPtr * (*inputPtr);
73  }
74  }
75  }
76  }
77 
78  /*
79  * Perform a convolution (full mode).
80  *
81  * @param input Input used to perform the convolution.
82  * @param filter Filter used to perform the conolution.
83  * @param output Output data that contains the results of the convolution.
84  * @param dW Stride of filter application in the x direction.
85  * @param dH Stride of filter application in the y direction.
86  */
87  template<typename eT, typename Border = BorderMode>
88  static typename std::enable_if<
89  std::is_same<Border, FullConvolution>::value, void>::type
90  Convolution(const arma::Mat<eT>& input,
91  const arma::Mat<eT>& filter,
92  arma::Mat<eT>& output,
93  const size_t dW = 1,
94  const size_t dH = 1)
95  {
96  const size_t outputRows = (input.n_rows + 2 * (filter.n_rows - 1)) * dW;
97  const size_t outputCols = (input.n_cols + 2 * (filter.n_cols - 1)) * dH;
98 
99  // Pad filter and input to the working output shape.
100  arma::Mat<eT> inputPadded = arma::zeros<arma::Mat<eT> >(outputRows,
101  outputCols);
102  inputPadded.submat(filter.n_rows - 1, filter.n_cols - 1,
103  filter.n_rows - 1 + input.n_rows - 1,
104  filter.n_cols - 1 + input.n_cols - 1) = input;
105 
107  output, 1, 1);
108  }
109 
110  /*
111  * Perform a convolution using 3rd order tensors.
112  *
113  * @param input Input used to perform the convolution.
114  * @param filter Filter used to perform the conolution.
115  * @param output Output data that contains the results of the convolution.
116  * @param dW Stride of filter application in the x direction.
117  * @param dH Stride of filter application in the y direction.
118  */
119  template<typename eT>
120  static void Convolution(const arma::Cube<eT>& input,
121  const arma::Cube<eT>& filter,
122  arma::Cube<eT>& output,
123  const size_t dW = 1,
124  const size_t dH = 1)
125  {
126  arma::Mat<eT> convOutput;
127  NaiveConvolution<BorderMode>::Convolution(input.slice(0), filter.slice(0),
128  convOutput, dW, dH);
129 
130  output = arma::Cube<eT>(convOutput.n_rows, convOutput.n_cols,
131  input.n_slices);
132  output.slice(0) = convOutput;
133 
134  for (size_t i = 1; i < input.n_slices; i++)
135  {
136  NaiveConvolution<BorderMode>::Convolution(input.slice(i), filter.slice(i),
137  output.slice(i), dW, dH);
138  }
139  }
140 
141  /*
142  * Perform a convolution using dense matrix as input and a 3rd order tensors
143  * as filter and output.
144  *
145  * @param input Input used to perform the convolution.
146  * @param filter Filter used to perform the conolution.
147  * @param output Output data that contains the results of the convolution.
148  * @param dW Stride of filter application in the x direction.
149  * @param dH Stride of filter application in the y direction.
150  */
151  template<typename eT>
152  static void Convolution(const arma::Mat<eT>& input,
153  const arma::Cube<eT>& filter,
154  arma::Cube<eT>& output,
155  const size_t dW = 1,
156  const size_t dH = 1)
157  {
158  arma::Mat<eT> convOutput;
159  NaiveConvolution<BorderMode>::Convolution(input, filter.slice(0),
160  convOutput, dW, dH);
161 
162  output = arma::Cube<eT>(convOutput.n_rows, convOutput.n_cols,
163  filter.n_slices);
164  output.slice(0) = convOutput;
165 
166  for (size_t i = 1; i < filter.n_slices; i++)
167  {
168  NaiveConvolution<BorderMode>::Convolution(input, filter.slice(i),
169  output.slice(i), dW, dH);
170  }
171  }
172 
173  /*
174  * Perform a convolution using a 3rd order tensors as input and output and a
175  * dense matrix as filter.
176  *
177  * @param input Input used to perform the convolution.
178  * @param filter Filter used to perform the conolution.
179  * @param output Output data that contains the results of the convolution.
180  * @param dW Stride of filter application in the x direction.
181  * @param dH Stride of filter application in the y direction.
182  */
183  template<typename eT>
184  static void Convolution(const arma::Cube<eT>& input,
185  const arma::Mat<eT>& filter,
186  arma::Cube<eT>& output,
187  const size_t dW = 1,
188  const size_t dH = 1)
189  {
190  arma::Mat<eT> convOutput;
191  NaiveConvolution<BorderMode>::Convolution(input.slice(0), filter,
192  convOutput, dW, dH);
193 
194  output = arma::Cube<eT>(convOutput.n_rows, convOutput.n_cols,
195  input.n_slices);
196  output.slice(0) = convOutput;
197 
198  for (size_t i = 1; i < input.n_slices; i++)
199  {
200  NaiveConvolution<BorderMode>::Convolution(input.slice(i), filter,
201  output.slice(i), dW, dH);
202  }
203  }
204 
205 }; // class NaiveConvolution
206 
207 } // namespace ann
208 } // namespace mlpack
209 
210 #endif
static std::enable_if< std::is_same< Border, FullConvolution >::value, void >::type Convolution(const arma::Mat< eT > &input, const arma::Mat< eT > &filter, arma::Mat< eT > &output, const size_t dW=1, const size_t dH=1)
Linear algebra utility functions, generally performed on matrices or vectors.
Definition: binarize.hpp:18
The core includes that mlpack expects; standard C++ includes and Armadillo.
static void Convolution(const arma::Cube< eT > &input, const arma::Cube< eT > &filter, arma::Cube< eT > &output, const size_t dW=1, const size_t dH=1)
static void Convolution(const arma::Mat< eT > &input, const arma::Cube< eT > &filter, arma::Cube< eT > &output, const size_t dW=1, const size_t dH=1)
static void Convolution(const arma::Cube< eT > &input, const arma::Mat< eT > &filter, arma::Cube< eT > &output, const size_t dW=1, const size_t dH=1)
Computes the two-dimensional convolution.
static std::enable_if< std::is_same< Border, ValidConvolution >::value, void >::type Convolution(const arma::Mat< eT > &input, const arma::Mat< eT > &filter, arma::Mat< eT > &output, const size_t dW=1, const size_t dH=1)