From b2c247f6d3dcd6fcdbed79d26d8644920895dbb0 Mon Sep 17 00:00:00 2001 From: kartikdutt18 Date: Mon, 10 Feb 2020 17:49:47 +0530 Subject: [PATCH] Add adaptive poolin Add adaptive poolin Resolve merge conflict Add empty line at eof --- HISTORY.md | 2 +- src/mlpack/methods/ann/layer/CMakeLists.txt | 4 + .../ann/layer/adaptive_max_pooling.hpp | 276 ++++++++++++++++++ .../ann/layer/adaptive_max_pooling_impl.hpp | 130 +++++++++ .../ann/layer/adaptive_mean_pooling.hpp | 268 +++++++++++++++++ .../ann/layer/adaptive_mean_pooling_impl.hpp | 122 ++++++++ 6 files changed, 801 insertions(+), 1 deletion(-) create mode 100644 src/mlpack/methods/ann/layer/adaptive_max_pooling.hpp create mode 100644 src/mlpack/methods/ann/layer/adaptive_max_pooling_impl.hpp create mode 100644 src/mlpack/methods/ann/layer/adaptive_mean_pooling.hpp create mode 100644 src/mlpack/methods/ann/layer/adaptive_mean_pooling_impl.hpp diff --git a/HISTORY.md b/HISTORY.md index 7ae74ad6f1..fc4dbf8f9b 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -82,7 +82,7 @@ * Add CELU activation function (#2191) - * Add Log-Hyperbolic-Cosine Loss function (#2207) + * Add Log-Hyperbolic-Cosine Loss function (#2207). * Change neural network types to avoid unnecessary use of rvalue references (#2259). diff --git a/src/mlpack/methods/ann/layer/CMakeLists.txt b/src/mlpack/methods/ann/layer/CMakeLists.txt index 2cc3e3fb98..78b77b2a09 100644 --- a/src/mlpack/methods/ann/layer/CMakeLists.txt +++ b/src/mlpack/methods/ann/layer/CMakeLists.txt @@ -5,6 +5,10 @@ set(SOURCES add_impl.hpp add_merge.hpp add_merge_impl.hpp + adaptive_max_pooling.hpp + adaptive_max_pooling_impl.hpp + adaptive_mean_pooling.hpp + adaptive_mean_pooling_impl.hpp alpha_dropout.hpp alpha_dropout_impl.hpp atrous_convolution.hpp diff --git a/src/mlpack/methods/ann/layer/adaptive_max_pooling.hpp b/src/mlpack/methods/ann/layer/adaptive_max_pooling.hpp new file mode 100644 index 0000000000..fb86ef1c8e --- /dev/null +++ b/src/mlpack/methods/ann/layer/adaptive_max_pooling.hpp @@ -0,0 +1,276 @@ +/** + * @file adaptive_max_pooling.hpp + * @author Kartik Dutt + * + * Definition of the Adaptive Mean Pooling layer class. + * + * mlpack is free software; you may redistribute it and/or modify it under the + * terms of the 3-clause BSD license. You should have received a copy of the + * 3-clause BSD license along with mlpack. If not, see + * http://www.opensource.org/licenses/BSD-3-Clause for more information. + */ + +#ifndef MLPACK_METHODS_ANN_LAYER_ADAPTIVE_MAX_POOLING_HPP +#define MLPACK_METHODS_ANN_LAYER_ADAPTIVE_MAX_POOLING_HPP + +#include + +namespace mlpack { +namespace ann /** Artificial Neural Network. */ { + +/** + * Implementation of the AdaptiveMaxPooling. + * + * @tparam InputDataType Type of the input data (arma::colvec, arma::mat, + * arma::sp_mat or arma::cube). + * @tparam OutputDataType Type of the output data (arma::colvec, arma::mat, + * arma::sp_mat or arma::cube). + */ +template < + typename InputDataType = arma::mat, + typename OutputDataType = arma::mat +> +class AdaptiveMaxPooling +{ + public: + //! Create the AdaptiveMaxPooling object. + AdaptiveMaxPooling(); + + /** + * Create the AdaptiveMaxPooling object. + * + * @param outputWidth Width of the output. + * @param outputHeight Height of the output. + */ + AdaptiveMaxPooling(const size_t outputWidth, + const size_t outputHeight); + + /** + * Create the AdaptiveMaxPooling object. + * + * @param outputShape A two-value tuple indicating width and height of the output. + */ + AdaptiveMaxPooling(const std::tuple outputShape); + + /** + * Ordinary feed forward pass of a neural network, evaluating the function + * f(x) by propagating the activity forward through f. + * + * @param input Input data used for evaluating the specified function. + * @param output Resulting output activation. + */ + template + void Forward(const arma::Mat&& input, arma::Mat&& output); + + /** + * Ordinary feed backward pass of a neural network, using 3rd-order tensors as + * input, calculating the function f(x) by propagating x backwards through f. + * Using the results from the feed forward pass. + * + * @param input The propagated input activation. + * @param gy The backpropagated error. + * @param g The calculated gradient. + */ + template + void Backward(const arma::Mat&& /* input */, + arma::Mat&& gy, + arma::Mat&& g); + + //! Get the output parameter. + OutputDataType const &OutputParameter() const { return outputParameter; } + //! Modify the output parameter. + OutputDataType &OutputParameter() { return outputParameter; } + + //! Get the delta. + OutputDataType const &Delta() const { return delta; } + //! Modify the delta. + OutputDataType &Delta() { return delta; } + + //! Get the width. + size_t const &InputWidth() const { return inputWidth; } + //! Modify the width. + size_t &InputWidth() { return inputWidth; } + + //! Get the height. + size_t const &InputHeight() const { return inputHeight; } + //! Modify the height. + size_t &InputHeight() { return inputHeight; } + + //! Get the width. + size_t const &OutputWidth() const { return outputWidth; } + //! Modify the width. + size_t &OutputWidth() { return outputWidth; } + + //! Get the height. + size_t const &OutputHeight() const { return outputHeight; } + //! Modify the height. + size_t &OutputHeight() { return outputHeight; } + + //! Get the input size. + size_t InputSize() const { return inSize; } + + //! Get the output size. + size_t OutputSize() const { return outSize; } + + //! Get the value of the deterministic parameter. + bool Deterministic() const { return deterministic; } + //! Modify the value of the deterministic parameter. + bool &Deterministic() { return deterministic; } + + /** + * Serialize the layer + */ + template + void serialize(Archive& ar, const unsigned int /* version */); + + private: + /** + * Initialize Kernel Size and Stride for Adaptive Pooling. + */ + void IntializeAdaptivePadding() + { + strideWidth = std::floor(inputWidth / outputWidth); + strideHeight = std::floor(inputHeight / outputHeight); + + kernelWidth = inputWidth - (outputWidth - 1) * strideWidth; + kernelHeight = inputHeight - (outputHeight - 1) * strideHeight; + + if(kernelHeight < 0 || kernelWidth < 0) + { + Log::Fatal << "Given output shape is not possible for given " + << " Input shape." << std::endl; + } + } + + /** + * Apply pooling to the input and store the results. + * + * @param input The input to be apply the pooling rule. + * @param output The pooled result. + * @param poolingIndices The pooled indices. + */ + template + void PoolingOperation(const arma::Mat& input, + arma::Mat& output, + arma::Mat& poolingIndices) + { + for (size_t j = 0, colidx = 0; j < output.n_cols; + ++j, colidx += strideWidth) + { + for (size_t i = 0, rowidx = 0; i < output.n_rows; + ++i, rowidx += strideHeight) + { + arma::mat subInput = input( + arma::span(rowidx, rowidx + kernelWidth - 1), + arma::span(colidx, colidx + kernelHeight - 1)); + + const size_t idx = pooling.Pooling(subInput); + output(i, j) = subInput(idx); + + if (!deterministic) + { + arma::Mat subIndices = indices(arma::span(rowidx, + rowidx + kernelWidth - 1), + arma::span(colidx, colidx + kernelHeight - 1)); + + poolingIndices(i, j) = subIndices(idx); + } + } + } + } + + /** + * Apply unpooling to the input and store the results. + * + * @param error The backward error. + * @param output The pooled result. + * @param poolingIndices The pooled indices. + */ + template + void Unpooling(const arma::Mat& error, + arma::Mat& output, + arma::Mat& poolingIndices) + { + for (size_t i = 0; i < poolingIndices.n_elem; ++i) + { + output(poolingIndices(i)) += error(i); + } + } + + //! Locally-stored width of the pooling window. + size_t kernelWidth; + + //! Locally-stored height of the pooling window. + size_t kernelHeight; + + //! Locally-stored width of the stride operation. + size_t strideWidth; + + //! Locally-stored height of the stride operation. + size_t strideHeight; + + //! Locally-stored number of input channels. + size_t inSize; + + //! Locally-stored number of output channels. + size_t outSize; + + //! Locally-stored input width. + size_t inputWidth; + + //! Locally-stored input height. + size_t inputHeight; + + //! Locally-stored output width. + size_t outputWidth; + + //! Locally-stored output height. + size_t outputHeight; + + //! Locally-stored reset parameter used to initialize the module once. + bool reset; + + //! If true use maximum a posteriori during the forward pass. + bool deterministic; + + //! Locally-stored number of input units. + size_t batchSize; + + //! Locally-stored output parameter. + arma::cube outputTemp; + + //! Locally-stored transformed input parameter. + arma::cube inputTemp; + + //! Locally-stored transformed output parameter. + arma::cube gTemp; + + //! Locally-stored delta object. + OutputDataType delta; + + //! Locally-stored gradient object. + OutputDataType gradient; + + //! Locally-stored output parameter object. + OutputDataType outputParameter; + + //! Locally-stored indices matrix parameter. + arma::Mat indices; + + //! Locally-stored pooling strategy. + MaxPoolingRule pooling; + + //! Locally-stored indices column parameter. + arma::Col indicesCol; + + //! Locally-stored pooling indicies. + std::vector poolingIndices; +}; // class AdaptiveMaxPooling + +} // namespace ann +} // namespace mlpack + +// Include implementation. +#include "adaptive_max_pooling_impl.hpp" + +#endif diff --git a/src/mlpack/methods/ann/layer/adaptive_max_pooling_impl.hpp b/src/mlpack/methods/ann/layer/adaptive_max_pooling_impl.hpp new file mode 100644 index 0000000000..db2e20d36a --- /dev/null +++ b/src/mlpack/methods/ann/layer/adaptive_max_pooling_impl.hpp @@ -0,0 +1,130 @@ +/** + * @file adaptive_max_pooling_impl.hpp + * @author Kartik Dutt + * + * Implementation of the Adaptive Max Pooling layer class. + * + * mlpack is free software; you may redistribute it and/or modify it under the + * terms of the 3-clause BSD license. You should have received a copy of the + * 3-clause BSD license along with mlpack. If not, see + * http://www.opensource.org/licenses/BSD-3-Clause for more information. + */ +#ifndef MLPACK_METHODS_ANN_LAYER_ADAPTIVE_MAX_POOLING_IMPL_HPP +#define MLPACK_METHODS_ANN_LAYER_ADAPTIVE_MAX_POOLING_IMPL_HPP + +// In case it hasn't yet been included. +#include "adaptive_max_pooling.hpp" + +namespace mlpack { +namespace ann /** Artificial Neural Network. */ { + +template +AdaptiveMaxPooling::AdaptiveMaxPooling() +{ + // Nothing to do here. +} + +template +AdaptiveMaxPooling::AdaptiveMaxPooling( + const size_t outputWidth, + const size_t outputHeight) : + inSize(0), + outSize(0), + inputWidth(0), + inputHeight(0), + outputWidth(outputWidth), + outputHeight(outputHeight), + reset(false), + deterministic(false), + batchSize(0) +{ + // Nothing to do here. +} + +template +AdaptiveMaxPooling::AdaptiveMaxPooling( + const std::tuple outputShape): + inSize(0), + outSize(0), + inputWidth(0), + inputHeight(0), + outputWidth(std::get<0>(outputShape)), + outputHeight(std::get<1>(outputShape)), + reset(false), + deterministic(false), + batchSize(0) +{ + // Nothing to do here. +} + +template +template +void AdaptiveMaxPooling::Forward( + const arma::Mat&& input, arma::Mat&& output) +{ + IntializeAdaptivePadding(); + batchSize = input.n_cols; + inSize = input.n_elem / (inputWidth * inputHeight); + inputTemp = arma::cube(const_cast&&>(input).memptr(), + inputWidth, inputHeight, batchSize * inSize, false, false); + outputTemp = arma::zeros >(outputWidth, outputHeight, + batchSize * inSize); + + size_t elements = inputWidth * inputHeight; + indicesCol = arma::linspace >(0, (elements - 1), + elements); + indices = arma::Mat(indicesCol.memptr(), inputWidth, inputHeight); + poolingIndices.push_back(outputTemp); + for (size_t s = 0; s < inputTemp.n_slices; s++) + PoolingOperation(inputTemp.slice(s), outputTemp.slice(s), + outputTemp.slice(s)); + + output = arma::Mat(outputTemp.memptr(), outputTemp.n_elem / batchSize, + batchSize); + + outSize = batchSize * inSize; +} + +template +template +void AdaptiveMaxPooling::Backward( + const arma::Mat&& /* input */, + arma::Mat&& gy, + arma::Mat&& g) +{ + arma::cube mappedError = arma::cube(gy.memptr(), outputWidth, + outputHeight, outSize, false, false); + + gTemp = arma::zeros(inputTemp.n_rows, + inputTemp.n_cols, inputTemp.n_slices); + + for (size_t s = 0; s < mappedError.n_slices; s++) + { + Unpooling(mappedError.slice(s), gTemp.slice(s), + poolingIndices.back().slice(s)); + } + poolingIndices.pop_back(); + g = arma::mat(gTemp.memptr(), gTemp.n_elem / batchSize, batchSize); +} + +template +template +void AdaptiveMaxPooling::serialize( + Archive& ar, + const unsigned int /* version */) +{ + ar & BOOST_SERIALIZATION_NVP(kernelWidth); + ar & BOOST_SERIALIZATION_NVP(kernelHeight); + ar & BOOST_SERIALIZATION_NVP(strideWidth); + ar & BOOST_SERIALIZATION_NVP(strideHeight); + ar & BOOST_SERIALIZATION_NVP(batchSize); + ar & BOOST_SERIALIZATION_NVP(inputWidth); + ar & BOOST_SERIALIZATION_NVP(inputHeight); + ar & BOOST_SERIALIZATION_NVP(outputWidth); + ar & BOOST_SERIALIZATION_NVP(outputHeight); +} + +} // namespace ann +} // namespace mlpack + +#endif \ No newline at end of file diff --git a/src/mlpack/methods/ann/layer/adaptive_mean_pooling.hpp b/src/mlpack/methods/ann/layer/adaptive_mean_pooling.hpp new file mode 100644 index 0000000000..25c3d2e81d --- /dev/null +++ b/src/mlpack/methods/ann/layer/adaptive_mean_pooling.hpp @@ -0,0 +1,268 @@ +/** + * @file adaptive_mean_pooling.hpp + * @author Kartik Dutt + * + * Definition of the Adaptive Mean Pooling layer class. + * + * mlpack is free software; you may redistribute it and/or modify it under the + * terms of the 3-clause BSD license. You should have received a copy of the + * 3-clause BSD license along with mlpack. If not, see + * http://www.opensource.org/licenses/BSD-3-Clause for more information. + */ + +#ifndef MLPACK_METHODS_ANN_LAYER_ADAPTIVE_MEAN_POOLING_HPP +#define MLPACK_METHODS_ANN_LAYER_ADAPTIVE_MEAN_POOLING_HPP + +#include + +namespace mlpack { +namespace ann /** Artificial Neural Network. */ { + +/** + * Implementation of the AdaptiveMeanPooling. + * + * @tparam InputDataType Type of the input data (arma::colvec, arma::mat, + * arma::sp_mat or arma::cube). + * @tparam OutputDataType Type of the output data (arma::colvec, arma::mat, + * arma::sp_mat or arma::cube). + */ +template < + typename InputDataType = arma::mat, + typename OutputDataType = arma::mat +> +class AdaptiveMeanPooling +{ + public: + //! Create the AdaptiveMeanPooling object. + AdaptiveMeanPooling(); + + /** + * Create the AdaptiveMeanPooling object. + * + * @param outputWidth Width of the output. + * @param outputHeight Height of the output. + */ + AdaptiveMeanPooling(const size_t outputWidth, + const size_t outputHeight); + + /** + * Create the AdaptiveMeanPooling object. + * + * @param outputShape A two-value tuple indicating width and height of the output. + */ + AdaptiveMeanPooling(const std::tuple outputShape); + + /** + * Ordinary feed forward pass of a neural network, evaluating the function + * f(x) by propagating the activity forward through f. + * + * @param input Input data used for evaluating the specified function. + * @param output Resulting output activation. + */ + template + void Forward(const arma::Mat&& input, arma::Mat&& output); + + /** + * Ordinary feed backward pass of a neural network, using 3rd-order tensors as + * input, calculating the function f(x) by propagating x backwards through f. + * Using the results from the feed forward pass. + * + * @param input The propagated input activation. + * @param gy The backpropagated error. + * @param g The calculated gradient. + */ + template + void Backward(const arma::Mat&& /* input */, + arma::Mat&& gy, + arma::Mat&& g); + + //! Get the output parameter. + OutputDataType const &OutputParameter() const { return outputParameter; } + //! Modify the output parameter. + OutputDataType &OutputParameter() { return outputParameter; } + + //! Get the delta. + OutputDataType const &Delta() const { return delta; } + //! Modify the delta. + OutputDataType &Delta() { return delta; } + + //! Get the width. + size_t const &InputWidth() const { return inputWidth; } + //! Modify the width. + size_t &InputWidth() { return inputWidth; } + + //! Get the height. + size_t const &InputHeight() const { return inputHeight; } + //! Modify the height. + size_t &InputHeight() { return inputHeight; } + + //! Get the width. + size_t const &OutputWidth() const { return outputWidth; } + //! Modify the width. + size_t &OutputWidth() { return outputWidth; } + + //! Get the height. + size_t const &OutputHeight() const { return outputHeight; } + //! Modify the height. + size_t &OutputHeight() { return outputHeight; } + + //! Get the input size. + size_t InputSize() const { return inSize; } + + //! Get the output size. + size_t OutputSize() const { return outSize; } + + //! Get the value of the deterministic parameter. + bool Deterministic() const { return deterministic; } + //! Modify the value of the deterministic parameter. + bool &Deterministic() { return deterministic; } + + /** + * Serialize the layer + */ + template + void serialize(Archive& ar, const unsigned int /* version */); + + private: + /** + * Initialize Kernel Size and Stride for Adaptive Pooling. + */ + void IntializeAdaptivePadding() + { + strideWidth = std::floor(inputWidth / outputWidth); + strideHeight = std::floor(inputHeight / outputHeight); + + kernelWidth = inputWidth - (outputWidth - 1) * strideWidth; + kernelHeight = inputHeight - (outputHeight - 1) * strideHeight; + + if(kernelHeight < 0 || kernelWidth < 0) + { + Log::Fatal << "Given output shape is not possible for given " + << " Input shape." << std::endl; + } + } + + /** + * Apply pooling to the input and store the results. + * + * @param input The input to be apply the pooling rule. + * @param output The pooled result. + */ + template + void Pooling(const arma::Mat& input, arma::Mat& output) + { + const size_t rStep = kernelWidth; + const size_t cStep = kernelHeight; + + for (size_t j = 0, colidx = 0; j < output.n_cols; + ++j, colidx += strideHeight) + { + for (size_t i = 0, rowidx = 0; i < output.n_rows; + ++i, rowidx += strideWidth) + { + arma::mat subInput = input( + arma::span(rowidx, rowidx + rStep - 1), + arma::span(colidx, colidx + cStep - 1)); + + output(i, j) = arma::mean(arma::mean(subInput)); + } + } + } + + /** + * Apply unpooling to the input and store the results. + * + * @param input The input to be apply the unpooling rule. + * @param output The pooled result. + */ + template + void Unpooling(const arma::Mat& input, + const arma::Mat& error, + arma::Mat& output) + { + const size_t rStep = input.n_rows / error.n_rows; + const size_t cStep = input.n_cols / error.n_cols; + + arma::Mat unpooledError; + for (size_t j = 0; j < input.n_cols - cStep; j += cStep) + { + for (size_t i = 0; i < input.n_rows - rStep; i += rStep) + { + const arma::Mat& inputArea = input(arma::span(i, i + rStep - 1), + arma::span(j, j + cStep - 1)); + + unpooledError = arma::Mat(inputArea.n_rows, inputArea.n_cols); + unpooledError.fill(error(i / rStep, j / cStep) / inputArea.n_elem); + + output(arma::span(i, i + rStep - 1), + arma::span(j, j + cStep - 1)) += unpooledError; + } + } + } + + //! Locally-stored width of the pooling window. + size_t kernelWidth; + + //! Locally-stored height of the pooling window. + size_t kernelHeight; + + //! Locally-stored width of the stride operation. + size_t strideWidth; + + //! Locally-stored height of the stride operation. + size_t strideHeight; + + //! Locally-stored number of input channels. + size_t inSize; + + //! Locally-stored number of output channels. + size_t outSize; + + //! Locally-stored input width. + size_t inputWidth; + + //! Locally-stored input height. + size_t inputHeight; + + //! Locally-stored output width. + size_t outputWidth; + + //! Locally-stored output height. + size_t outputHeight; + + //! Locally-stored reset parameter used to initialize the module once. + bool reset; + + //! If true use maximum a posteriori during the forward pass. + bool deterministic; + + //! Locally-stored number of input units. + size_t batchSize; + + //! Locally-stored output parameter. + arma::cube outputTemp; + + //! Locally-stored transformed input parameter. + arma::cube inputTemp; + + //! Locally-stored transformed output parameter. + arma::cube gTemp; + + //! Locally-stored delta object. + OutputDataType delta; + + //! Locally-stored gradient object. + OutputDataType gradient; + + //! Locally-stored output parameter object. + OutputDataType outputParameter; + +}; // class AdaptiveMeanPooling + +} // namespace ann +} // namespace mlpack + +// Include implementation. +#include "adaptive_mean_pooling_impl.hpp" + +#endif diff --git a/src/mlpack/methods/ann/layer/adaptive_mean_pooling_impl.hpp b/src/mlpack/methods/ann/layer/adaptive_mean_pooling_impl.hpp new file mode 100644 index 0000000000..98cbe356b7 --- /dev/null +++ b/src/mlpack/methods/ann/layer/adaptive_mean_pooling_impl.hpp @@ -0,0 +1,122 @@ +/** + * @file adaptive_mean_pooling_impl.hpp + * @author Kartik Dutt + * + * Implementation of the Adaptive Mean Pooling layer class. + * + * mlpack is free software; you may redistribute it and/or modify it under the + * terms of the 3-clause BSD license. You should have received a copy of the + * 3-clause BSD license along with mlpack. If not, see + * http://www.opensource.org/licenses/BSD-3-Clause for more information. + */ +#ifndef MLPACK_METHODS_ANN_LAYER_ADAPTIVE_MEAN_POOLING_IMPL_HPP +#define MLPACK_METHODS_ANN_LAYER_ADAPTIVE_MEAN_POOLING_IMPL_HPP + +// In case it hasn't yet been included. +#include "adaptive_mean_pooling.hpp" + +namespace mlpack { +namespace ann /** Artificial Neural Network. */ { + +template +AdaptiveMeanPooling::AdaptiveMeanPooling() +{ + // Nothing to do here. +} + +template +AdaptiveMeanPooling::AdaptiveMeanPooling( + const size_t outputWidth, + const size_t outputHeight) : + inSize(0), + outSize(0), + inputWidth(0), + inputHeight(0), + outputWidth(outputWidth), + outputHeight(outputHeight), + reset(false), + deterministic(false), + batchSize(0) +{ + // Nothing to do here. +} + +template +AdaptiveMeanPooling::AdaptiveMeanPooling( + const std::tuple outputShape): + inSize(0), + outSize(0), + inputWidth(0), + inputHeight(0), + outputWidth(std::get<0>(outputShape)), + outputHeight(std::get<1>(outputShape)), + reset(false), + deterministic(false), + batchSize(0) +{ + // Nothing to do here. +} + +template +template +void AdaptiveMeanPooling::Forward( + const arma::Mat&& input, arma::Mat&& output) +{ + IntializeAdaptivePadding(); + batchSize = input.n_cols; + inSize = input.n_elem / (inputWidth * inputHeight); + inputTemp = arma::cube(const_cast&&>(input).memptr(), + inputWidth, inputHeight, batchSize * inSize, false, false); + outputTemp = arma::zeros >(outputWidth, outputHeight, + batchSize * inSize); + for (size_t s = 0; s < inputTemp.n_slices; s++) + Pooling(inputTemp.slice(s), outputTemp.slice(s)); + + output = arma::Mat(outputTemp.memptr(), outputTemp.n_elem / batchSize, + batchSize); + + outSize = batchSize * inSize; +} + +template +template +void AdaptiveMeanPooling::Backward( + const arma::Mat&& /* input */, + arma::Mat&& gy, + arma::Mat&& g) +{ + arma::cube mappedError = arma::cube(gy.memptr(), outputWidth, + outputHeight, outSize, false, false); + + gTemp = arma::zeros(inputTemp.n_rows, + inputTemp.n_cols, inputTemp.n_slices); + + for (size_t s = 0; s < mappedError.n_slices; s++) + { + Unpooling(inputTemp.slice(s), mappedError.slice(s), gTemp.slice(s)); + } + + g = arma::mat(gTemp.memptr(), gTemp.n_elem / batchSize, batchSize); +} + +template +template +void AdaptiveMeanPooling::serialize( + Archive& ar, + const unsigned int /* version */) +{ + ar & BOOST_SERIALIZATION_NVP(kernelWidth); + ar & BOOST_SERIALIZATION_NVP(kernelHeight); + ar & BOOST_SERIALIZATION_NVP(strideWidth); + ar & BOOST_SERIALIZATION_NVP(strideHeight); + ar & BOOST_SERIALIZATION_NVP(batchSize); + ar & BOOST_SERIALIZATION_NVP(inputWidth); + ar & BOOST_SERIALIZATION_NVP(inputHeight); + ar & BOOST_SERIALIZATION_NVP(outputWidth); + ar & BOOST_SERIALIZATION_NVP(outputHeight); +} + +} // namespace ann +} // namespace mlpack + +#endif \ No newline at end of file