mlpack
glimpse_impl.hpp
Go to the documentation of this file.
1 
14 #ifndef MLPACK_METHODS_ANN_LAYER_GLIMPSE_IMPL_HPP
15 #define MLPACK_METHODS_ANN_LAYER_GLIMPSE_IMPL_HPP
16 
17 // In case it hasn't yet been included.
18 #include "glimpse.hpp"
19 
20 namespace mlpack {
21 namespace ann {
22 
23 template <typename InputDataType, typename OutputDataType>
25  const size_t inSize,
26  const size_t size,
27  const size_t depth,
28  const size_t scale,
29  const size_t inputWidth,
30  const size_t inputHeight) :
31  inSize(inSize),
32  size(size),
33  depth(depth),
34  scale(scale),
35  inputWidth(inputWidth),
36  inputHeight(inputHeight),
37  outputWidth(size),
38  outputHeight(size),
39  inputDepth(0),
40  deterministic(true)
41 {
42  // Nothing to do here.
43 }
44 
45 template<typename InputDataType, typename OutputDataType>
46 template<typename eT>
48  const arma::Mat<eT>& input, arma::Mat<eT>& output)
49 {
50  inputTemp = arma::cube(input.colptr(0), inputWidth, inputHeight, inSize);
51  outputTemp = arma::Cube<eT>(size, size, depth * inputTemp.n_slices);
52 
53  location = input.submat(0, 1, 1, 1);
54 
55  if (!deterministic)
56  {
57  locationParameter.push_back(location);
58  }
59 
60  inputDepth = inputTemp.n_slices / inSize;
61 
62  for (size_t inputIdx = 0; inputIdx < inSize; inputIdx++)
63  {
64  for (size_t depthIdx = 0, glimpseSize = size;
65  depthIdx < depth; depthIdx++, glimpseSize *= scale)
66  {
67  size_t padSize = std::floor((glimpseSize - 1) / 2);
68 
69  arma::Cube<eT> inputPadded = arma::zeros<arma::Cube<eT> >(
70  inputTemp.n_rows + padSize * 2, inputTemp.n_cols + padSize * 2,
71  inputTemp.n_slices / inSize);
72 
73  inputPadded.tube(padSize, padSize, padSize + inputTemp.n_rows - 1,
74  padSize + inputTemp.n_cols - 1) = inputTemp.subcube(0, 0,
75  inputIdx * inputDepth, inputTemp.n_rows - 1, inputTemp.n_cols - 1,
76  (inputIdx + 1) * inputDepth - 1);
77 
78  size_t h = inputPadded.n_rows - glimpseSize;
79  size_t w = inputPadded.n_cols - glimpseSize;
80 
81  size_t x = std::min(h, (size_t) std::max(0.0,
82  (location(0, inputIdx) + 1) / 2.0 * h));
83  size_t y = std::min(w, (size_t) std::max(0.0,
84  (location(1, inputIdx) + 1) / 2.0 * w));
85 
86  if (depthIdx == 0)
87  {
88  for (size_t j = (inputIdx + depthIdx), paddedSlice = 0;
89  j < outputTemp.n_slices; j += (inSize * depth), paddedSlice++)
90  {
91  outputTemp.slice(j) = inputPadded.subcube(x, y,
92  paddedSlice, x + glimpseSize - 1, y + glimpseSize - 1,
93  paddedSlice);
94  }
95  }
96  else
97  {
98  for (size_t j = (inputIdx + depthIdx * (depth - 1)), paddedSlice = 0;
99  j < outputTemp.n_slices; j += (inSize * depth), paddedSlice++)
100  {
101  arma::Mat<eT> poolingInput = inputPadded.subcube(x, y,
102  paddedSlice, x + glimpseSize - 1, y + glimpseSize - 1,
103  paddedSlice);
104 
105  if (scale == 2)
106  {
107  Pooling(glimpseSize / size, poolingInput, outputTemp.slice(j));
108  }
109  else
110  {
111  ReSampling(poolingInput, outputTemp.slice(j));
112  }
113  }
114  }
115  }
116  }
117 
118  for (size_t i = 0; i < outputTemp.n_slices; ++i)
119  {
120  outputTemp.slice(i) = arma::trans(outputTemp.slice(i));
121  }
122 
123  output = arma::Mat<eT>(outputTemp.memptr(), outputTemp.n_elem, 1);
124 
125  outputWidth = outputTemp.n_rows;
126  outputHeight = outputTemp.n_cols;
127 }
128 
129 template<typename InputDataType, typename OutputDataType>
130 template<typename eT>
132  const arma::Mat<eT>& /* input */, const arma::Mat<eT>& gy, arma::Mat<eT>& g)
133 {
134  // Generate a cube using the backpropagated error matrix.
135  arma::Cube<eT> mappedError = arma::zeros<arma::cube>(outputWidth,
136  outputHeight, 1);
137 
138  location = locationParameter.back();
139  locationParameter.pop_back();
140 
141  for (size_t s = 0, j = 0; s < mappedError.n_slices; s+= gy.n_cols, ++j)
142  {
143  for (size_t i = 0; i < gy.n_cols; ++i)
144  {
145  mappedError.slice(s + i) = arma::Mat<eT>(gy.memptr(),
146  outputWidth, outputHeight);
147  }
148  }
149 
150  gTemp = arma::zeros<arma::cube>(inputTemp.n_rows, inputTemp.n_cols,
151  inputTemp.n_slices);
152 
153  for (size_t inputIdx = 0; inputIdx < inSize; inputIdx++)
154  {
155  for (size_t depthIdx = 0, glimpseSize = size;
156  depthIdx < depth; depthIdx++, glimpseSize *= scale)
157  {
158  size_t padSize = std::floor((glimpseSize - 1) / 2);
159 
160  arma::Cube<eT> inputPadded = arma::zeros<arma::Cube<eT> >(
161  inputTemp.n_rows + padSize * 2, inputTemp.n_cols +
162  padSize * 2, inputTemp.n_slices / inSize);
163 
164  size_t h = inputPadded.n_rows - glimpseSize;
165  size_t w = inputPadded.n_cols - glimpseSize;
166 
167  size_t x = std::min(h, (size_t) std::max(0.0,
168  (location(0, inputIdx) + 1) / 2.0 * h));
169  size_t y = std::min(w, (size_t) std::max(0.0,
170  (location(1, inputIdx) + 1) / 2.0 * w));
171 
172  if (depthIdx == 0)
173  {
174  for (size_t j = (inputIdx + depthIdx), paddedSlice = 0;
175  j < mappedError.n_slices; j += (inSize * depth), paddedSlice++)
176  {
177  inputPadded.subcube(x, y,
178  paddedSlice, x + glimpseSize - 1, y + glimpseSize - 1,
179  paddedSlice) = mappedError.slice(j);
180  }
181  }
182  else
183  {
184  for (size_t j = (inputIdx + depthIdx * (depth - 1)), paddedSlice = 0;
185  j < mappedError.n_slices; j += (inSize * depth), paddedSlice++)
186  {
187  arma::Mat<eT> poolingOutput = inputPadded.subcube(x, y,
188  paddedSlice, x + glimpseSize - 1, y + glimpseSize - 1,
189  paddedSlice);
190 
191  if (scale == 2)
192  {
193  Unpooling(inputTemp.slice(paddedSlice), mappedError.slice(j),
194  poolingOutput);
195  }
196  else
197  {
198  DownwardReSampling(inputTemp.slice(paddedSlice),
199  mappedError.slice(j), poolingOutput);
200  }
201 
202  inputPadded.subcube(x, y,
203  paddedSlice, x + glimpseSize - 1, y + glimpseSize - 1,
204  paddedSlice) = poolingOutput;
205  }
206  }
207 
208  gTemp += inputPadded.tube(padSize, padSize, padSize +
209  inputTemp.n_rows - 1, padSize + inputTemp.n_cols - 1);
210  }
211  }
212 
213  Transform(gTemp);
214  g = arma::mat(gTemp.memptr(), gTemp.n_elem, 1);
215 }
216 
217 template<typename InputDataType, typename OutputDataType>
218 template<typename Archive>
220  Archive& ar, const uint32_t /* version */)
221 {
222  ar(CEREAL_NVP(inSize));
223  ar(CEREAL_NVP(size));
224  ar(CEREAL_NVP(depth));
225  ar(CEREAL_NVP(scale));
226  ar(CEREAL_NVP(inputWidth));
227  ar(CEREAL_NVP(inputHeight));
228  ar(CEREAL_NVP(outputWidth));
229  ar(CEREAL_NVP(outputHeight));
230  ar(CEREAL_NVP(location));
231 }
232 
233 } // namespace ann
234 } // namespace mlpack
235 
236 #endif
Linear algebra utility functions, generally performed on matrices or vectors.
Definition: cv.hpp:1
void Backward(const arma::Mat< eT > &, const arma::Mat< eT > &gy, arma::Mat< eT > &g)
Ordinary feed backward pass of the glimpse layer.
Definition: glimpse_impl.hpp:131
void serialize(Archive &ar, const uint32_t)
Serialize the layer.
Definition: glimpse_impl.hpp:219
Glimpse(const size_t inSize=0, const size_t size=0, const size_t depth=3, const size_t scale=2, const size_t inputWidth=0, const size_t inputHeight=0)
Create the GlimpseLayer object using the specified ratio and rescale parameter.
Definition: glimpse_impl.hpp:24
void Forward(const arma::Mat< eT > &input, arma::Mat< eT > &output)
Ordinary feed forward pass of the glimpse layer.
Definition: glimpse_impl.hpp:47