glimpse.hpp
Go to the documentation of this file.
1 // Temporarily drop.
28 #ifndef MLPACK_METHODS_ANN_LAYER_GLIMPSE_HPP
29 #define MLPACK_METHODS_ANN_LAYER_GLIMPSE_HPP
30 
31 #include <mlpack/prereqs.hpp>
32 
33 #include "layer_types.hpp"
34 #include <algorithm>
35 
36 namespace mlpack {
37 namespace ann {
38 
39 
40 /*
41  * The mean pooling rule for convolution neural networks. Average all values
42  * within the receptive block.
43  */
45 {
46  public:
47  /*
48  * Return the average value within the receptive block.
49  *
50  * @param input Input used to perform the pooling operation.
51  */
52  template<typename MatType>
53  double Pooling(const MatType& input)
54  {
55  return arma::mean(arma::mean(input));
56  }
57 
58  /*
59  * Set the average value within the receptive block.
60  *
61  * @param input Input used to perform the pooling operation.
62  * @param value The unpooled value.
63  * @param output The unpooled output data.
64  */
65  template<typename MatType>
66  void Unpooling(const MatType& input, const double value, MatType& output)
67  {
68  output = arma::zeros<MatType>(input.n_rows, input.n_cols);
69  const double mean = arma::mean(arma::mean(input));
70 
71  output.elem(arma::find(mean == input, 1)).fill(value);
72  }
73 };
74 
85 template <
86  typename InputType = arma::mat,
87  typename OutputType = arma::mat
88 >
89 class GlimpseType : public Layer<InputType, OutputType>
90 {
91  public:
104  GlimpseType(const size_t inSize = 0,
105  const size_t size = 0,
106  const size_t depth = 3,
107  const size_t scale = 2,
108  const size_t inputWidth = 0,
109  const size_t inputHeight = 0);
110 
117  void Forward(const InputType& input, OutputType& output);
118 
126  void Backward(const InputType& /* input */,
127  const OutputType& gy,
128  OutputType& g);
129 
132  void Location(const arma::mat& location) { this->location = location; }
133 
135  size_t const& InputWidth() const { return inputWidth; }
137  size_t& InputWidth() { return inputWidth; }
138 
140  size_t const& InputHeight() const { return inputHeight; }
142  size_t& InputHeight() { return inputHeight; }
143 
145  size_t const& OutputWidth() const { return outputWidth; }
147  size_t& OutputWidth() { return outputWidth; }
148 
150  size_t const& OutputHeight() const { return outputHeight; }
152  size_t& OutputHeight() { return outputHeight; }
153 
155  size_t const& Depth() const { return depth; }
156 
158  size_t const& Scale() const { return scale; }
159 
161  size_t InSize() const { return inSize; }
162 
164  size_t GlimpseSize() const { return size;}
165 
166  const std::vector<size_t> OutputDimensions() const
167  {
168  std::vector<size_t> result(inputDimensions.size(), 0);
169  result[0] = outputWidth;
170  result[1] = outputHeight;
171  for (size_t i = 2; i < inputDimensions.size(); ++i)
172  result[i] = inputDimensions[i];
173  return result;
174  }
175 
179  template<typename Archive>
180  void serialize(Archive& ar, const uint32_t /* version */);
181 
182  private:
188  void Transform(arma::mat& w)
189  {
190  arma::mat t = w;
191 
192  for (size_t i = 0, k = 0; i < w.n_elem; ++k)
193  {
194  for (size_t j = 0; j < w.n_cols; ++j, ++i)
195  {
196  w(k, j) = t(i);
197  }
198  }
199  }
200 
201  /*
202  * Transform the given input by changing rows to columns.
203  *
204  * @param w The input matrix used to perform the transformation.
205  */
206  void Transform(arma::cube& w)
207  {
208  for (size_t i = 0; i < w.n_slices; ++i)
209  {
210  arma::mat t = w.slice(i);
211  Transform(t);
212  w.slice(i) = t;
213  }
214  }
215 
223  void Pooling(const size_t kSize,
224  const InputType& input,
225  OutputType& output)
226  {
227  const size_t rStep = kSize;
228  const size_t cStep = kSize;
229 
230  for (size_t j = 0; j < input.n_cols; j += cStep)
231  {
232  for (size_t i = 0; i < input.n_rows; i += rStep)
233  {
234  output(i / rStep, j / cStep) += pooling.Pooling(
235  input(arma::span(i, i + rStep - 1), arma::span(j, j + cStep - 1)));
236  }
237  }
238  }
239 
247  void Unpooling(const InputType& input,
248  const OutputType& error,
249  OutputType& output)
250  {
251  const size_t rStep = input.n_rows / error.n_rows;
252  const size_t cStep = input.n_cols / error.n_cols;
253 
254  OutputType unpooledError;
255  for (size_t j = 0; j < input.n_cols; j += cStep)
256  {
257  for (size_t i = 0; i < input.n_rows; i += rStep)
258  {
259  const InputType& inputArea = input(arma::span(i, i + rStep - 1),
260  arma::span(j, j + cStep - 1));
261 
262  pooling.Unpooling(inputArea, error(i / rStep, j / cStep),
263  unpooledError);
264 
265  output(arma::span(i, i + rStep - 1),
266  arma::span(j, j + cStep - 1)) += unpooledError;
267  }
268  }
269  }
270 
278  void ReSampling(const InputType& input, OutputType& output)
279  {
280  double wRatio = (double) (input.n_rows - 1) / (size - 1);
281  double hRatio = (double) (input.n_cols - 1) / (size - 1);
282 
283  double iWidth = input.n_rows - 1;
284  double iHeight = input.n_cols - 1;
285 
286  for (size_t y = 0; y < size; y++)
287  {
288  for (size_t x = 0; x < size; x++)
289  {
290  double ix = wRatio * x;
291  double iy = hRatio * y;
292 
293  // Get the 4 nearest neighbors.
294  double ixNw = std::floor(ix);
295  double iyNw = std::floor(iy);
296  double ixNe = ixNw + 1;
297  double iySw = iyNw + 1;
298 
299  // Get surfaces to each neighbor.
300  double se = (ix - ixNw) * (iy - iyNw);
301  double sw = (ixNe - ix) * (iy - iyNw);
302  double ne = (ix - ixNw) * (iySw - iy);
303  double nw = (ixNe - ix) * (iySw - iy);
304 
305  // Calculate the weighted sum.
306  output(y, x) = input(iyNw, ixNw) * nw +
307  input(iyNw, std::min(ixNe, iWidth)) * ne +
308  input(std::min(iySw, iHeight), ixNw) * sw +
309  input(std::min(iySw, iHeight), std::min(ixNe, iWidth)) * se;
310  }
311  }
312  }
313 
322  void DownwardReSampling(const InputType& input,
323  const OutputType& error,
324  OutputType& output)
325  {
326  double iWidth = input.n_rows - 1;
327  double iHeight = input.n_cols - 1;
328 
329  double wRatio = iWidth / (size - 1);
330  double hRatio = iHeight / (size - 1);
331 
332  for (size_t y = 0; y < size; y++)
333  {
334  for (size_t x = 0; x < size; x++)
335  {
336  double ix = wRatio * x;
337  double iy = hRatio * y;
338 
339  // Get the 4 nearest neighbors.
340  double ixNw = std::floor(ix);
341  double iyNw = std::floor(iy);
342  double ixNe = ixNw + 1;
343  double iySw = iyNw + 1;
344 
345  // Get surfaces to each neighbor.
346  double se = (ix - ixNw) * (iy - iyNw);
347  double sw = (ixNe - ix) * (iy - iyNw);
348  double ne = (ix - ixNw) * (iySw - iy);
349  double nw = (ixNe - ix) * (iySw - iy);
350 
351  double ograd = error(y, x);
352 
353  output(iyNw, ixNw) = output(iyNw, ixNw) + nw * ograd;
354  output(iyNw, std::min(ixNe, iWidth)) = output(iyNw,
355  std::min(ixNe, iWidth)) + ne * ograd;
356  output(std::min(iySw, iHeight), ixNw) = output(std::min(iySw, iHeight),
357  ixNw) + sw * ograd;
358  output(std::min(iySw, iHeight), std::min(ixNe, iWidth)) = output(
359  std::min(iySw, iHeight), std::min(ixNe, iWidth)) + se * ograd;
360  }
361  }
362  }
363 
365  size_t inSize;
366 
368  size_t size;
369 
371  size_t depth;
372 
374  size_t scale;
375 
377  size_t inputWidth;
378 
380  size_t inputHeight;
381 
383  size_t outputWidth;
384 
386  size_t outputHeight;
387 
389  size_t inputDepth;
390 
392  arma::Cube<typename InputType::elem_type> inputTemp;
393 
395  arma::Cube<typename OutputType::elem_type> outputTemp;
396 
398  OutputType location;
399 
401  MeanPoolingRule pooling;
402 
404  std::vector<OutputType> locationParameter;
405 
407  arma::Cube<typename OutputType::elem_type> gTemp;
408 }; // class GlimpseType
409 
410 // Standard Glimpse layer.
412 
413 } // namespace ann
414 } // namespace mlpack
415 
416 // Include implementation.
417 #include "glimpse_impl.hpp"
418 
419 #endif
constexpr auto size(Container const &container) noexcept -> decltype(container.size())
Definition: iterator.hpp:29
Linear algebra utility functions, generally performed on matrices or vectors.
size_t & OutputWidth()
Modify the output width.
Definition: glimpse.hpp:147
size_t & InputHeight()
Modify the input height.
Definition: glimpse.hpp:142
double Pooling(const MatType &input)
Definition: glimpse.hpp:53
size_t & InputWidth()
Modify input the width.
Definition: glimpse.hpp:137
size_t GlimpseSize() const
Get the used glimpse size (height = width).
Definition: glimpse.hpp:164
The glimpse layer returns a retina-like representation (down-scaled cropped images) of increasing sca...
Definition: glimpse.hpp:89
size_t const & OutputWidth() const
Get the output width.
Definition: glimpse.hpp:145
The core includes that mlpack expects; standard C++ includes and Armadillo.
const std::vector< size_t > OutputDimensions() const
Definition: glimpse.hpp:166
size_t const & OutputHeight() const
Get the output height.
Definition: glimpse.hpp:150
size_t const & InputWidth() const
Get the input width.
Definition: glimpse.hpp:135
typename impl::find< T, U >::type find
Definition: meta.hpp:238
size_t const & Scale() const
Get the scale fraction.
Definition: glimpse.hpp:158
size_t const & InputHeight() const
Get the input height.
Definition: glimpse.hpp:140
void Unpooling(const MatType &input, const double value, MatType &output)
Definition: glimpse.hpp:66
size_t & OutputHeight()
Modify the output height.
Definition: glimpse.hpp:152
void Location(const arma::mat &location)
Set the locationthe x and y coordinate of the center of the output glimpse.
Definition: glimpse.hpp:132
GlimpseType< arma::mat, arma::mat > Glimpse
Definition: glimpse.hpp:411
size_t const & Depth() const
Get the number of patches to crop per glimpse.
Definition: glimpse.hpp:155
A layer is an abstract class implementing common neural networks operations, such as convolution...
Definition: layer.hpp:52
constexpr T const & min(T const &lhs, T const &rhs)
Definition: algorithm.hpp:69
size_t InSize() const
Get the size of the input units.
Definition: glimpse.hpp:161