mlpack
atrous_convolution_impl.hpp
Go to the documentation of this file.
1 
13 #ifndef MLPACK_METHODS_ANN_LAYER_ATROUS_CONVOLUTION_IMPL_HPP
14 #define MLPACK_METHODS_ANN_LAYER_ATROUS_CONVOLUTION_IMPL_HPP
15 
16 // In case it hasn't yet been included.
17 #include "atrous_convolution.hpp"
18 
19 namespace mlpack {
20 namespace ann {
21 
22 template<
23  typename ForwardConvolutionRule,
24  typename BackwardConvolutionRule,
25  typename GradientConvolutionRule,
26  typename InputDataType,
27  typename OutputDataType
28 >
29 AtrousConvolution<
30  ForwardConvolutionRule,
31  BackwardConvolutionRule,
32  GradientConvolutionRule,
33  InputDataType,
34  OutputDataType
36 {
37  // Nothing to do here.
38 }
39 
40 template<
41  typename ForwardConvolutionRule,
42  typename BackwardConvolutionRule,
43  typename GradientConvolutionRule,
44  typename InputDataType,
45  typename OutputDataType
46 >
48  ForwardConvolutionRule,
49  BackwardConvolutionRule,
50  GradientConvolutionRule,
51  InputDataType,
52  OutputDataType
54  const size_t inSize,
55  const size_t outSize,
56  const size_t kernelWidth,
57  const size_t kernelHeight,
58  const size_t strideWidth,
59  const size_t strideHeight,
60  const size_t padW,
61  const size_t padH,
62  const size_t inputWidth,
63  const size_t inputHeight,
64  const size_t dilationWidth,
65  const size_t dilationHeight,
66  const std::string& paddingType) :
68  inSize,
69  outSize,
70  kernelWidth,
71  kernelHeight,
72  strideWidth,
73  strideHeight,
74  std::tuple<size_t, size_t>(padW, padW),
75  std::tuple<size_t, size_t>(padH, padH),
76  inputWidth,
77  inputHeight,
78  dilationWidth,
79  dilationHeight,
80  paddingType)
81 {
82  // Nothing to do here.
83 }
84 
85 template<
86  typename ForwardConvolutionRule,
87  typename BackwardConvolutionRule,
88  typename GradientConvolutionRule,
89  typename InputDataType,
90  typename OutputDataType
91 >
93  ForwardConvolutionRule,
94  BackwardConvolutionRule,
95  GradientConvolutionRule,
96  InputDataType,
97  OutputDataType
99  const size_t inSize,
100  const size_t outSize,
101  const size_t kernelWidth,
102  const size_t kernelHeight,
103  const size_t strideWidth,
104  const size_t strideHeight,
105  const std::tuple<size_t, size_t>& padW,
106  const std::tuple<size_t, size_t>& padH,
107  const size_t inputWidth,
108  const size_t inputHeight,
109  const size_t dilationWidth,
110  const size_t dilationHeight,
111  const std::string& paddingType) :
112  inSize(inSize),
113  outSize(outSize),
114  kernelWidth(kernelWidth),
115  kernelHeight(kernelHeight),
116  strideWidth(strideWidth),
117  strideHeight(strideHeight),
118  inputWidth(inputWidth),
119  inputHeight(inputHeight),
120  outputWidth(0),
121  outputHeight(0),
122  dilationWidth(dilationWidth),
123  dilationHeight(dilationHeight)
124 {
125  weights.set_size(WeightSize(), 1);
126 
127  // Transform paddingType to lowercase.
128  const std::string paddingTypeLow = util::ToLower(paddingType);
129 
130  size_t padWLeft = std::get<0>(padW);
131  size_t padWRight = std::get<1>(padW);
132  size_t padHTop = std::get<0>(padH);
133  size_t padHBottom = std::get<1>(padH);
134  if (paddingTypeLow == "valid")
135  {
136  padWLeft = 0;
137  padWRight = 0;
138  padHTop = 0;
139  padHBottom = 0;
140  }
141  else if (paddingTypeLow == "same")
142  {
143  InitializeSamePadding(padWLeft, padWRight, padHTop, padHBottom);
144  }
145 
146  padding = ann::Padding<>(padWLeft, padWRight, padHTop, padHBottom);
147 }
148 
149 template<
150  typename ForwardConvolutionRule,
151  typename BackwardConvolutionRule,
152  typename GradientConvolutionRule,
153  typename InputDataType,
154  typename OutputDataType
155 >
156 void AtrousConvolution<
157  ForwardConvolutionRule,
158  BackwardConvolutionRule,
159  GradientConvolutionRule,
160  InputDataType,
161  OutputDataType
162 >::Reset()
163 {
164  weight = arma::cube(weights.memptr(), kernelWidth, kernelHeight,
165  outSize * inSize, false, false);
166  bias = arma::mat(weights.memptr() + weight.n_elem,
167  outSize, 1, false, false);
168 }
169 
170 template<
171  typename ForwardConvolutionRule,
172  typename BackwardConvolutionRule,
173  typename GradientConvolutionRule,
174  typename InputDataType,
175  typename OutputDataType
176 >
177 template<typename eT>
178 void AtrousConvolution<
179  ForwardConvolutionRule,
180  BackwardConvolutionRule,
181  GradientConvolutionRule,
182  InputDataType,
183  OutputDataType
184 >::Forward(const arma::Mat<eT>& input, arma::Mat<eT>& output)
185 {
186  batchSize = input.n_cols;
187  arma::cube inputTemp(const_cast<arma::Mat<eT>&>(input).memptr(),
188  inputWidth, inputHeight, inSize * batchSize, false, false);
189 
190  if (padding.PadWLeft() != 0 || padding.PadWRight() != 0 ||
191  padding.PadHTop() != 0 || padding.PadHBottom() != 0)
192  {
193  inputPaddedTemp.set_size(
194  inputTemp.n_rows + padding.PadWLeft() + padding.PadWRight(),
195  inputTemp.n_cols + padding.PadHTop() + padding.PadHBottom(),
196  inputTemp.n_slices);
197 
198  for (size_t i = 0; i < inputTemp.n_slices; ++i)
199  {
200  padding.Forward(inputTemp.slice(i), inputPaddedTemp.slice(i));
201  }
202  }
203 
204  size_t wConv = ConvOutSize(inputWidth, kernelWidth, strideWidth,
205  padding.PadWLeft(), padding.PadWRight(), dilationWidth);
206  size_t hConv = ConvOutSize(inputHeight, kernelHeight, strideHeight,
207  padding.PadHTop(), padding.PadHBottom(), dilationHeight);
208 
209  output.set_size(wConv * hConv * outSize, batchSize);
210  outputTemp = arma::Cube<eT>(output.memptr(), wConv, hConv,
211  outSize * batchSize, false, false);
212  outputTemp.zeros();
213 
214  for (size_t outMap = 0, outMapIdx = 0, batchCount = 0; outMap <
215  outSize * batchSize; outMap++)
216  {
217  if (outMap != 0 && outMap % outSize == 0)
218  {
219  batchCount++;
220  outMapIdx = 0;
221  }
222 
223  for (size_t inMap = 0; inMap < inSize; inMap++, outMapIdx++)
224  {
225  arma::Mat<eT> convOutput;
226 
227  if (padding.PadWLeft() != 0 || padding.PadWRight() != 0 ||
228  padding.PadHTop() != 0 || padding.PadHBottom() != 0)
229  {
230  ForwardConvolutionRule::Convolution(inputPaddedTemp.slice(inMap +
231  batchCount * inSize), weight.slice(outMapIdx), convOutput,
232  strideWidth, strideHeight, dilationWidth, dilationHeight);
233  }
234  else
235  {
236  ForwardConvolutionRule::Convolution(inputTemp.slice(inMap +
237  batchCount * inSize), weight.slice(outMapIdx), convOutput,
238  strideWidth, strideHeight, dilationWidth, dilationHeight);
239  }
240 
241  outputTemp.slice(outMap) += convOutput;
242  }
243 
244  outputTemp.slice(outMap) += bias(outMap % outSize);
245  }
246 
247  outputWidth = outputTemp.n_rows;
248  outputHeight = outputTemp.n_cols;
249 }
250 
251 template<
252  typename ForwardConvolutionRule,
253  typename BackwardConvolutionRule,
254  typename GradientConvolutionRule,
255  typename InputDataType,
256  typename OutputDataType
257 >
258 template<typename eT>
259 void AtrousConvolution<
260  ForwardConvolutionRule,
261  BackwardConvolutionRule,
262  GradientConvolutionRule,
263  InputDataType,
264  OutputDataType
266  const arma::Mat<eT>& /* input */, const arma::Mat<eT>& gy, arma::Mat<eT>& g)
267 {
268  arma::cube mappedError(((arma::Mat<eT>&) gy).memptr(), outputWidth,
269  outputHeight, outSize * batchSize, false, false);
270 
271  g.set_size(inputWidth * inputHeight * inSize, batchSize);
272  gTemp = arma::Cube<eT>(g.memptr(), inputWidth, inputHeight,
273  inSize * batchSize, false, false);
274  gTemp.zeros();
275 
276  for (size_t outMap = 0, outMapIdx = 0, batchCount = 0; outMap <
277  outSize * batchSize; outMap++)
278  {
279  if (outMap != 0 && outMap % outSize == 0)
280  {
281  batchCount++;
282  outMapIdx = 0;
283  }
284 
285  for (size_t inMap = 0; inMap < inSize; inMap++, outMapIdx++)
286  {
287  arma::Mat<eT> output, rotatedFilter;
288  Rotate180(weight.slice(outMapIdx), rotatedFilter);
289 
290  BackwardConvolutionRule::Convolution(mappedError.slice(outMap),
291  rotatedFilter, output, strideWidth, strideHeight, dilationWidth,
292  dilationHeight);
293 
294  if (padding.PadWLeft() != 0 || padding.PadWRight() != 0 ||
295  padding.PadHTop() != 0 || padding.PadHBottom() != 0)
296  {
297  gTemp.slice(inMap + batchCount * inSize) +=
298  output.submat(padding.PadWLeft(), padding.PadHTop(),
299  padding.PadWLeft() + gTemp.n_rows - 1,
300  padding.PadHTop() + gTemp.n_cols - 1);
301  }
302  else
303  {
304  gTemp.slice(inMap + batchCount * inSize) += output;
305  }
306  }
307  }
308 }
309 
310 template<
311  typename ForwardConvolutionRule,
312  typename BackwardConvolutionRule,
313  typename GradientConvolutionRule,
314  typename InputDataType,
315  typename OutputDataType
316 >
317 template<typename eT>
318 void AtrousConvolution<
319  ForwardConvolutionRule,
320  BackwardConvolutionRule,
321  GradientConvolutionRule,
322  InputDataType,
323  OutputDataType
324 >::Gradient(
325  const arma::Mat<eT>& input,
326  const arma::Mat<eT>& error,
327  arma::Mat<eT>& gradient)
328 {
329  arma::cube mappedError(((arma::Mat<eT>&) error).memptr(), outputWidth,
330  outputHeight, outSize * batchSize, false, false);
331  arma::cube inputTemp(const_cast<arma::Mat<eT>&>(input).memptr(),
332  inputWidth, inputHeight, inSize * batchSize, false, false);
333 
334  gradient.set_size(weights.n_elem, 1);
335  gradientTemp = arma::Cube<eT>(gradient.memptr(), weight.n_rows,
336  weight.n_cols, weight.n_slices, false, false);
337  gradientTemp.zeros();
338 
339  for (size_t outMap = 0, outMapIdx = 0, batchCount = 0; outMap <
340  outSize * batchSize; outMap++)
341  {
342  if (outMap != 0 && outMap % outSize == 0)
343  {
344  batchCount++;
345  outMapIdx = 0;
346  }
347 
348  for (size_t inMap = 0; inMap < inSize; inMap++, outMapIdx++)
349  {
350  arma::Mat<eT> inputSlice;
351  if (padding.PadWLeft() != 0 || padding.PadWRight() != 0 ||
352  padding.PadHTop() != 0 || padding.PadHBottom() != 0)
353  {
354  inputSlice = inputPaddedTemp.slice(inMap + batchCount * inSize);
355  }
356  else
357  {
358  inputSlice = inputTemp.slice(inMap + batchCount * inSize);
359  }
360 
361  arma::Mat<eT> deltaSlice = mappedError.slice(outMap);
362 
363  arma::Mat<eT> output;
364  GradientConvolutionRule::Convolution(inputSlice, deltaSlice,
365  output, strideWidth, strideHeight, 1, 1);
366 
367  if (dilationHeight > 1)
368  {
369  for (size_t i = 1; i < output.n_cols; ++i){
370  output.shed_cols(i, i + dilationHeight - 2);
371  }
372  }
373  if (dilationWidth > 1)
374  {
375  for (size_t i = 1; i < output.n_rows; ++i){
376  output.shed_rows(i, i + dilationWidth - 2);
377  }
378  }
379 
380  if (gradientTemp.n_rows < output.n_rows ||
381  gradientTemp.n_cols < output.n_cols)
382  {
383  gradientTemp.slice(outMapIdx) += output.submat(0, 0,
384  gradientTemp.n_rows - 1, gradientTemp.n_cols - 1);
385  }
386  else if (gradientTemp.n_rows > output.n_rows ||
387  gradientTemp.n_cols > output.n_cols)
388  {
389  gradientTemp.slice(outMapIdx).submat(0, 0, output.n_rows - 1,
390  output.n_cols - 1) += output;
391  }
392  else
393  {
394  gradientTemp.slice(outMapIdx) += output;
395  }
396  }
397 
398  gradient.submat(weight.n_elem + (outMap % outSize), 0, weight.n_elem +
399  (outMap % outSize), 0) = arma::accu(mappedError.slice(outMap));
400  }
401 }
402 
403 template<
404  typename ForwardConvolutionRule,
405  typename BackwardConvolutionRule,
406  typename GradientConvolutionRule,
407  typename InputDataType,
408  typename OutputDataType
409 >
410 template<typename Archive>
411 void AtrousConvolution<
412  ForwardConvolutionRule,
413  BackwardConvolutionRule,
414  GradientConvolutionRule,
415  InputDataType,
416  OutputDataType
417 >::serialize(Archive& ar, const uint32_t /* version */)
418 {
419  ar(CEREAL_NVP(inSize));
420  ar(CEREAL_NVP(outSize));
421  ar(CEREAL_NVP(batchSize));
422  ar(CEREAL_NVP(kernelWidth));
423  ar(CEREAL_NVP(kernelHeight));
424  ar(CEREAL_NVP(strideWidth));
425  ar(CEREAL_NVP(strideHeight));
426  ar(CEREAL_NVP(inputWidth));
427  ar(CEREAL_NVP(inputHeight));
428  ar(CEREAL_NVP(outputWidth));
429  ar(CEREAL_NVP(outputHeight));
430  ar(CEREAL_NVP(dilationWidth));
431  ar(CEREAL_NVP(dilationHeight));
432  ar(CEREAL_NVP(padding));
433 
434  if (cereal::is_loading<Archive>())
435  {
436  weights.set_size((outSize * inSize * kernelWidth * kernelHeight) + outSize,
437  1);
438  }
439 }
440 
441 template<
442  typename ForwardConvolutionRule,
443  typename BackwardConvolutionRule,
444  typename GradientConvolutionRule,
445  typename InputDataType,
446  typename OutputDataType
447 >
448 void AtrousConvolution<
449  ForwardConvolutionRule,
450  BackwardConvolutionRule,
451  GradientConvolutionRule,
452  InputDataType,
453  OutputDataType
454 >::InitializeSamePadding(size_t& padWLeft,
455  size_t& padWRight,
456  size_t& padHTop,
457  size_t& padHBottom) const
458 {
459  /*
460  * Using O = (W - F + 2P) / s + 1;
461  */
462  size_t totalVerticalPadding = (strideWidth - 1) * inputWidth + kernelWidth -
463  strideWidth + (dilationWidth - 1) * (kernelWidth - 1);
464  size_t totalHorizontalPadding = (strideHeight - 1) * inputHeight +
465  kernelHeight - strideHeight + (dilationHeight - 1) * (kernelHeight - 1);
466 
467  padWLeft = totalVerticalPadding / 2;
468  padWRight = totalVerticalPadding - totalVerticalPadding / 2;
469  padHTop = totalHorizontalPadding / 2;
470  padHBottom = totalHorizontalPadding - totalHorizontalPadding / 2;
471 }
472 
473 } // namespace ann
474 } // namespace mlpack
475 
476 #endif
Linear algebra utility functions, generally performed on matrices or vectors.
Definition: cv.hpp:1
Implementation of the Padding module class.
Definition: layer_types.hpp:87
AtrousConvolution()
Create the AtrousConvolution object.
Definition: atrous_convolution_impl.hpp:35
Definition: pointer_wrapper.hpp:23
void serialize(Archive &ar, const uint32_t)
Serialize the layer.
Definition: atrous_convolution_impl.hpp:417
OutputDataType const & Gradient() const
Get the gradient.
Definition: atrous_convolution.hpp:197
size_t PadWLeft() const
Get the left padding width.
Definition: padding.hpp:89
size_t PadWRight() const
Get the right padding width.
Definition: padding.hpp:94
void Forward(const arma::Mat< eT > &input, arma::Mat< eT > &output)
Ordinary feed forward pass of a neural network, evaluating the function f(x) by propagating the activ...
Definition: atrous_convolution_impl.hpp:184
void Forward(const arma::Mat< eT > &input, arma::Mat< eT > &output)
Ordinary feed forward pass of a neural network, evaluating the function f(x) by propagating the activ...
Definition: padding_impl.hpp:44
size_t PadHTop() const
Get the top padding width.
Definition: padding.hpp:99
void Backward(const arma::Mat< eT > &, const arma::Mat< eT > &gy, arma::Mat< eT > &g)
Ordinary feed backward pass of a neural network, calculating the function f(x) by propagating x backw...
Definition: atrous_convolution_impl.hpp:265
size_t PadHBottom() const
Get the bottom padding width.
Definition: padding.hpp:104
size_t WeightSize() const
Get size of the weight matrix.
Definition: atrous_convolution.hpp:263
Implementation of the Atrous Convolution class.
Definition: atrous_convolution.hpp:52