13 #ifndef MLPACK_METHODS_ANN_LAYER_TRANSPOSED_CONVOLUTION_IMPL_HPP 14 #define MLPACK_METHODS_ANN_LAYER_TRANSPOSED_CONVOLUTION_IMPL_HPP 23 typename ForwardConvolutionRule,
24 typename BackwardConvolutionRule,
25 typename GradientConvolutionRule,
26 typename InputDataType,
27 typename OutputDataType
29 TransposedConvolution<
30 ForwardConvolutionRule,
31 BackwardConvolutionRule,
32 GradientConvolutionRule,
41 typename ForwardConvolutionRule,
42 typename BackwardConvolutionRule,
43 typename GradientConvolutionRule,
44 typename InputDataType,
45 typename OutputDataType
48 ForwardConvolutionRule,
49 BackwardConvolutionRule,
50 GradientConvolutionRule,
56 const size_t kernelWidth,
57 const size_t kernelHeight,
58 const size_t strideWidth,
59 const size_t strideHeight,
62 const size_t inputWidth,
63 const size_t inputHeight,
64 const size_t outputWidth,
65 const size_t outputHeight,
66 const std::string& paddingType) :
74 std::tuple<size_t, size_t>(padW, padW),
75 std::tuple<size_t, size_t>(padH, padH),
86 typename ForwardConvolutionRule,
87 typename BackwardConvolutionRule,
88 typename GradientConvolutionRule,
89 typename InputDataType,
90 typename OutputDataType
93 ForwardConvolutionRule,
94 BackwardConvolutionRule,
95 GradientConvolutionRule,
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 outputWidth,
110 const size_t outputHeight,
111 const std::string& paddingType) :
114 kernelWidth(kernelWidth),
115 kernelHeight(kernelHeight),
116 strideWidth(strideWidth),
117 strideHeight(strideHeight),
118 padWLeft(
std::get<0>(padW)),
119 padWRight(
std::get<1>(padW)),
120 padHBottom(
std::get<1>(padH)),
121 padHTop(
std::get<0>(padH)),
122 inputWidth(inputWidth),
123 inputHeight(inputHeight),
124 outputWidth(outputWidth),
125 outputHeight(outputHeight)
129 const std::string paddingTypeLow = util::ToLower(paddingType);
131 if (paddingTypeLow ==
"valid")
139 else if (paddingTypeLow ==
"same")
141 InitializeSamePadding();
144 const size_t totalPadWidth = padWLeft + padWRight;
145 const size_t totalPadHeight = padHTop + padHBottom;
147 aW = (outputWidth + totalPadWidth - kernelWidth) % strideWidth;
148 aH = (outputHeight + totalPadHeight - kernelHeight) % strideHeight;
150 const size_t padWidthLeftForward = kernelWidth - padWLeft - 1;
151 const size_t padHeightTopForward = kernelHeight - padHTop - 1;
152 const size_t padWidthRightForward = kernelWidth - padWRight - 1;
153 const size_t padHeightBottomtForward = kernelHeight - padHBottom - 1;
156 padWidthRightForward + aW, padHeightTopForward,
157 padHeightBottomtForward + aH);
158 paddingBackward =
ann::Padding<>(padWLeft, padWRight, padHTop, padHBottom);
162 if (outputWidth != 0 && outputHeight != 0 &&
163 (outputWidth != strideWidth * (inputWidth - 1) +
164 aW + kernelWidth - totalPadWidth ||
165 outputHeight != strideHeight * (inputHeight - 1) +
166 aH + kernelHeight - totalPadHeight))
168 Log::Fatal <<
"The output width / output height is not possible given " 169 <<
"the other parameters of the layer." << std::endl;
174 typename ForwardConvolutionRule,
175 typename BackwardConvolutionRule,
176 typename GradientConvolutionRule,
177 typename InputDataType,
178 typename OutputDataType
181 ForwardConvolutionRule,
182 BackwardConvolutionRule,
183 GradientConvolutionRule,
188 weight = arma::cube(weights.memptr(), kernelWidth, kernelHeight,
189 outSize * inSize,
false,
false);
190 bias = arma::mat(weights.memptr() + weight.n_elem,
191 outSize, 1,
false,
false);
195 typename ForwardConvolutionRule,
196 typename BackwardConvolutionRule,
197 typename GradientConvolutionRule,
198 typename InputDataType,
199 typename OutputDataType
201 template<
typename eT>
203 ForwardConvolutionRule,
204 BackwardConvolutionRule,
205 GradientConvolutionRule,
208 >
::Forward(
const arma::Mat<eT>& input, arma::Mat<eT>& output)
210 batchSize = input.n_cols;
211 arma::cube inputTemp(
const_cast<arma::Mat<eT>&
>(input).memptr(),
212 inputWidth, inputHeight, inSize * batchSize,
false,
false);
214 if (strideWidth > 1 || strideHeight > 1)
216 InsertZeros(inputTemp, strideWidth, strideHeight, inputExpandedTemp);
221 inputPaddedTemp.set_size(inputExpandedTemp.n_rows +
223 inputExpandedTemp.n_cols + paddingForward.
PadHTop() +
224 paddingForward.
PadHBottom(), inputExpandedTemp.n_slices);
226 for (
size_t i = 0; i < inputExpandedTemp.n_slices; ++i)
228 paddingForward.
Forward(inputExpandedTemp.slice(i),
229 inputPaddedTemp.slice(i));
234 inputPaddedTemp = arma::Cube<eT>(inputExpandedTemp.memptr(),
235 inputExpandedTemp.n_rows, inputExpandedTemp.n_cols,
236 inputExpandedTemp.n_slices,
false,
false);;
239 else if (paddingForward.
PadWLeft() != 0 ||
241 paddingForward.
PadHTop() != 0 ||
244 inputPaddedTemp.set_size(inputTemp.n_rows + paddingForward.
PadWLeft() +
245 paddingForward.
PadWRight(), inputTemp.n_cols +
249 for (
size_t i = 0; i < inputTemp.n_slices; ++i)
251 paddingForward.
Forward(inputTemp.slice(i), inputPaddedTemp.slice(i));
255 output.set_size(outputWidth * outputHeight * outSize, batchSize);
256 outputTemp = arma::Cube<eT>(output.memptr(), outputWidth, outputHeight,
257 outSize * batchSize,
false,
false);
260 for (
size_t outMap = 0, outMapIdx = 0, batchCount = 0; outMap <
261 outSize * batchSize; outMap++)
263 if (outMap != 0 && outMap % outSize == 0)
269 for (
size_t inMap = 0; inMap < inSize; inMap++, outMapIdx++)
271 arma::Mat<eT> convOutput, rotatedFilter;
272 Rotate180(weight.slice(outMapIdx), rotatedFilter);
274 if (strideWidth > 1 ||
278 paddingForward.
PadHTop() != 0 ||
281 ForwardConvolutionRule::Convolution(inputPaddedTemp.slice(inMap +
282 batchCount * inSize), rotatedFilter, convOutput, 1, 1);
286 ForwardConvolutionRule::Convolution(inputTemp.slice(inMap +
287 batchCount * inSize), rotatedFilter, convOutput, 1, 1);
290 outputTemp.slice(outMap) += convOutput;
293 outputTemp.slice(outMap) += bias(outMap % outSize);
298 typename ForwardConvolutionRule,
299 typename BackwardConvolutionRule,
300 typename GradientConvolutionRule,
301 typename InputDataType,
302 typename OutputDataType
304 template<
typename eT>
306 ForwardConvolutionRule,
307 BackwardConvolutionRule,
308 GradientConvolutionRule,
312 const arma::Mat<eT>& ,
const arma::Mat<eT>& gy, arma::Mat<eT>& g)
314 arma::Cube<eT> mappedError(((arma::Mat<eT>&) gy).memptr(), outputWidth,
315 outputHeight, outSize * batchSize,
false,
false);
316 arma::Cube<eT> mappedErrorPadded;
320 mappedErrorPadded.set_size(mappedError.n_rows +
322 mappedError.n_cols + paddingBackward.
PadHTop() +
323 paddingBackward.
PadHBottom(), mappedError.n_slices);
325 for (
size_t i = 0; i < mappedError.n_slices; ++i)
327 paddingBackward.
Forward(mappedError.slice(i),
328 mappedErrorPadded.slice(i));
331 g.set_size(inputWidth * inputHeight * inSize, batchSize);
332 gTemp = arma::Cube<eT>(g.memptr(), inputWidth, inputHeight, inSize *
333 batchSize,
false,
false);
337 for (
size_t outMap = 0, outMapIdx = 0, batchCount = 0; outMap <
338 outSize * batchSize; outMap++)
340 if (outMap != 0 && outMap % outSize == 0)
346 for (
size_t inMap = 0; inMap < inSize; inMap++, outMapIdx++)
348 arma::Mat<eT> output;
353 BackwardConvolutionRule::Convolution(mappedErrorPadded.slice(outMap),
354 weight.slice(outMapIdx), output, strideWidth, strideHeight);
358 BackwardConvolutionRule::Convolution(mappedError.slice(outMap),
359 weight.slice(outMapIdx), output, strideWidth, strideHeight);
362 gTemp.slice(inMap + batchCount * inSize) += output;
368 typename ForwardConvolutionRule,
369 typename BackwardConvolutionRule,
370 typename GradientConvolutionRule,
371 typename InputDataType,
372 typename OutputDataType
374 template<
typename eT>
376 ForwardConvolutionRule,
377 BackwardConvolutionRule,
378 GradientConvolutionRule,
382 const arma::Mat<eT>& input,
383 const arma::Mat<eT>& error,
384 arma::Mat<eT>& gradient)
386 arma::Cube<eT> mappedError(((arma::Mat<eT>&) error).memptr(), outputWidth,
387 outputHeight, outSize * batchSize,
false,
false);
388 arma::cube inputTemp(
const_cast<arma::Mat<eT>&
>(input).memptr(),
389 inputWidth, inputHeight, inSize * batchSize,
false,
false);
391 gradient.set_size(weights.n_elem, 1);
392 gradientTemp = arma::Cube<eT>(gradient.memptr(), weight.n_rows,
393 weight.n_cols, weight.n_slices,
false,
false);
394 gradientTemp.zeros();
396 arma::Mat<eT> inputSlice, output, deltaSlice, rotatedOutput;
398 for (
size_t outMap = 0, outMapIdx = 0, batchCount = 0; outMap <
399 outSize * batchSize; outMap++)
401 if (outMap != 0 && outMap % outSize == 0)
407 deltaSlice = mappedError.slice(outMap);
409 for (
size_t inMap = 0; inMap < inSize; inMap++, outMapIdx++)
411 if (strideWidth > 1 ||
415 paddingForward.
PadHTop() != 0 ||
418 inputSlice = inputPaddedTemp.slice(inMap + batchCount * inSize);
422 inputSlice = inputTemp.slice(inMap + batchCount * inSize);
425 GradientConvolutionRule::Convolution(inputSlice, deltaSlice,
427 Rotate180(output, rotatedOutput);
428 gradientTemp.slice(outMapIdx) += rotatedOutput;
431 gradient.submat(weight.n_elem + (outMap % outSize), 0, weight.n_elem +
432 (outMap % outSize), 0) = arma::accu(mappedError.slices(outMap, outMap));
437 typename ForwardConvolutionRule,
438 typename BackwardConvolutionRule,
439 typename GradientConvolutionRule,
440 typename InputDataType,
441 typename OutputDataType
443 template<
typename Archive>
445 ForwardConvolutionRule,
446 BackwardConvolutionRule,
447 GradientConvolutionRule,
452 ar(CEREAL_NVP(inSize));
453 ar(CEREAL_NVP(outSize));
454 ar(CEREAL_NVP(batchSize));
455 ar(CEREAL_NVP(kernelWidth));
456 ar(CEREAL_NVP(kernelHeight));
457 ar(CEREAL_NVP(strideWidth));
458 ar(CEREAL_NVP(strideHeight));
459 ar(CEREAL_NVP(padWLeft));
460 ar(CEREAL_NVP(padWRight));
461 ar(CEREAL_NVP(padHBottom));
462 ar(CEREAL_NVP(padHTop));
463 ar(CEREAL_NVP(inputWidth));
464 ar(CEREAL_NVP(inputHeight));
465 ar(CEREAL_NVP(outputWidth));
466 ar(CEREAL_NVP(outputHeight));
467 ar(CEREAL_NVP(paddingForward));
468 ar(CEREAL_NVP(paddingBackward));
470 if (cereal::is_loading<Archive>())
472 weights.set_size((outSize * inSize * kernelWidth * kernelHeight) + outSize,
474 size_t totalPadWidth = padWLeft + padWRight;
475 size_t totalPadHeight = padHTop + padHBottom;
476 aW = (outputWidth + kernelWidth - totalPadWidth - 2) % strideWidth;
477 aH = (outputHeight + kernelHeight - totalPadHeight - 2) % strideHeight;
482 typename ForwardConvolutionRule,
483 typename BackwardConvolutionRule,
484 typename GradientConvolutionRule,
485 typename InputDataType,
486 typename OutputDataType
489 ForwardConvolutionRule,
490 BackwardConvolutionRule,
491 GradientConvolutionRule,
494 >::InitializeSamePadding(){
503 const size_t totalHorizontalPadding = (strideWidth - 1) * inputWidth +
504 kernelWidth - strideWidth;
505 const size_t totalVerticalPadding = (strideHeight - 1) * inputHeight +
506 kernelHeight - strideHeight;
508 padWLeft = totalVerticalPadding / 2;
509 padWRight = totalVerticalPadding - totalVerticalPadding / 2;
510 padHTop = totalHorizontalPadding / 2;
511 padHBottom = totalHorizontalPadding - totalHorizontalPadding / 2;
void serialize(Archive &ar, const uint32_t)
Serialize the layer.
Definition: transposed_convolution_impl.hpp:450
static MLPACK_EXPORT util::PrefixedOutStream Fatal
Prints fatal messages prefixed with [FATAL], then terminates the program.
Definition: log.hpp:90
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
Implementation of the Transposed Convolution class.
Definition: layer_types.hpp:188
OutputDataType const & Gradient() const
Get the gradient.
Definition: transposed_convolution.hpp:207
Definition: pointer_wrapper.hpp:23
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 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: transposed_convolution_impl.hpp:311
TransposedConvolution()
Create the Transposed Convolution object.
Definition: transposed_convolution_impl.hpp:35
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 WeightSize() const
Get the size of the weight matrix.
Definition: transposed_convolution.hpp:284
size_t PadHTop() const
Get the top padding width.
Definition: padding.hpp:99
size_t PadHBottom() const
Get the bottom padding width.
Definition: padding.hpp:104
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: transposed_convolution_impl.hpp:208