From b2c247f6d3dcd6fcdbed79d26d8644920895dbb0 Mon Sep 17 00:00:00 2001 From: kartikdutt18 Date: Mon, 10 Feb 2020 17:49:47 +0530 Subject: [PATCH 1/7] 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 From 1a17ff6d69f526a1ecdcb5606101d0575d7be716 Mon Sep 17 00:00:00 2001 From: kartikdutt18 Date: Tue, 11 Feb 2020 19:32:55 +0530 Subject: [PATCH 2/7] Completed and tested MaxPooling, Added both layers to layer_names.hpp Style Fix Minor style fix --- .../ann/layer/adaptive_max_pooling.hpp | 86 ++++++++---------- .../ann/layer/adaptive_max_pooling_impl.hpp | 9 +- .../ann/layer/adaptive_mean_pooling.hpp | 12 +-- .../ann/layer/adaptive_mean_pooling_impl.hpp | 2 +- src/mlpack/methods/ann/layer_names.hpp | 21 +++++ src/mlpack/tests/ann_layer_test.cpp | 89 +++++++++++++++++++ 6 files changed, 157 insertions(+), 62 deletions(-) diff --git a/src/mlpack/methods/ann/layer/adaptive_max_pooling.hpp b/src/mlpack/methods/ann/layer/adaptive_max_pooling.hpp index fb86ef1c8e..91826211c1 100644 --- a/src/mlpack/methods/ann/layer/adaptive_max_pooling.hpp +++ b/src/mlpack/methods/ann/layer/adaptive_max_pooling.hpp @@ -2,14 +2,13 @@ * @file adaptive_max_pooling.hpp * @author Kartik Dutt * - * Definition of the Adaptive Mean Pooling layer class. + * Definition of the AdaptiveMaxPooling 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 @@ -19,7 +18,7 @@ namespace mlpack { namespace ann /** Artificial Neural Network. */ { /** - * Implementation of the AdaptiveMaxPooling. + * Implementation of the AdaptiveMaxPooling layer. * * @tparam InputDataType Type of the input data (arma::colvec, arma::mat, * arma::sp_mat or arma::cube). @@ -43,7 +42,7 @@ class AdaptiveMaxPooling * @param outputHeight Height of the output. */ AdaptiveMaxPooling(const size_t outputWidth, - const size_t outputHeight); + const size_t outputHeight); /** * Create the AdaptiveMaxPooling object. @@ -77,34 +76,34 @@ class AdaptiveMaxPooling arma::Mat&& g); //! Get the output parameter. - OutputDataType const &OutputParameter() const { return outputParameter; } + const OutputDataType& OutputParameter() const { return outputParameter; } //! Modify the output parameter. - OutputDataType &OutputParameter() { return outputParameter; } + OutputDataType& OutputParameter() { return outputParameter; } //! Get the delta. - OutputDataType const &Delta() const { return delta; } + const OutputDataType& Delta() const { return delta; } //! Modify the delta. - OutputDataType &Delta() { return delta; } + OutputDataType& Delta() { return delta; } //! Get the width. - size_t const &InputWidth() const { return inputWidth; } + size_t InputWidth() const { return inputWidth; } //! Modify the width. - size_t &InputWidth() { return inputWidth; } + size_t& InputWidth() { return inputWidth; } //! Get the height. - size_t const &InputHeight() const { return inputHeight; } + size_t InputHeight() const { return inputHeight; } //! Modify the height. - size_t &InputHeight() { return inputHeight; } + size_t& InputHeight() { return inputHeight; } //! Get the width. - size_t const &OutputWidth() const { return outputWidth; } + size_t OutputWidth() const { return outputWidth; } //! Modify the width. - size_t &OutputWidth() { return outputWidth; } + size_t& OutputWidth() { return outputWidth; } //! Get the height. - size_t const &OutputHeight() const { return outputHeight; } + size_t OutputHeight() const { return outputHeight; } //! Modify the height. - size_t &OutputHeight() { return outputHeight; } + size_t& OutputHeight() { return outputHeight; } //! Get the input size. size_t InputSize() const { return inSize; } @@ -112,11 +111,6 @@ class AdaptiveMaxPooling //! 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 */ @@ -131,14 +125,15 @@ class AdaptiveMaxPooling { 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) + if (kernelHeight < 0 || kernelWidth < 0) { - Log::Fatal << "Given output shape is not possible for given " - << " Input shape." << std::endl; + Log::Fatal << "Given output shape (" << outputWidth << ", " + << outputHeight << ") is not possible for given input shape (" + << inputWidth <<", "<< inputHeight << ")."<< std::endl; } } @@ -154,27 +149,23 @@ class AdaptiveMaxPooling arma::Mat& output, arma::Mat& poolingIndices) { + const size_t rStep = kernelWidth; + const size_t cStep = kernelHeight; for (size_t j = 0, colidx = 0; j < output.n_cols; - ++j, colidx += strideWidth) + ++j, colidx += strideHeight) { for (size_t i = 0, rowidx = 0; i < output.n_rows; - ++i, rowidx += strideHeight) + ++i, rowidx += strideWidth) { arma::mat subInput = input( - arma::span(rowidx, rowidx + kernelWidth - 1), - arma::span(colidx, colidx + kernelHeight - 1)); - + arma::span(rowidx, rowidx + rStep - 1), + arma::span(colidx, colidx + cStep - 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); - } + arma::Mat subIndices = indices(arma::span(rowidx, + rowidx + rStep - 1), + arma::span(colidx, colidx + cStep - 1)); + poolingIndices(i, j) = subIndices(idx); } } } @@ -215,6 +206,9 @@ class AdaptiveMaxPooling //! Locally-stored number of output channels. size_t outSize; + //! Locally-stored reset parameter used to initialize the module once. + bool reset; + //! Locally-stored input width. size_t inputWidth; @@ -227,12 +221,6 @@ class AdaptiveMaxPooling //! 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; @@ -245,6 +233,9 @@ class AdaptiveMaxPooling //! Locally-stored transformed output parameter. arma::cube gTemp; + //! Locally-stored pooling strategy. + MaxPoolingRule pooling; + //! Locally-stored delta object. OutputDataType delta; @@ -257,15 +248,12 @@ class AdaptiveMaxPooling //! 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 +}; // class MaxPooling } // namespace ann } // namespace mlpack diff --git a/src/mlpack/methods/ann/layer/adaptive_max_pooling_impl.hpp b/src/mlpack/methods/ann/layer/adaptive_max_pooling_impl.hpp index db2e20d36a..d75c2199f4 100644 --- a/src/mlpack/methods/ann/layer/adaptive_max_pooling_impl.hpp +++ b/src/mlpack/methods/ann/layer/adaptive_max_pooling_impl.hpp @@ -35,7 +35,6 @@ AdaptiveMaxPooling::AdaptiveMaxPooling( outputWidth(outputWidth), outputHeight(outputHeight), reset(false), - deterministic(false), batchSize(0) { // Nothing to do here. @@ -51,7 +50,6 @@ AdaptiveMaxPooling::AdaptiveMaxPooling( outputWidth(std::get<0>(outputShape)), outputHeight(std::get<1>(outputShape)), reset(false), - deterministic(false), batchSize(0) { // Nothing to do here. @@ -69,15 +67,14 @@ void AdaptiveMaxPooling::Forward( inputWidth, inputHeight, batchSize * inSize, false, false); outputTemp = arma::zeros >(outputWidth, outputHeight, batchSize * inSize); - + poolingIndices.push_back(outputTemp); 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)); + poolingIndices.back().slice(s)); output = arma::Mat(outputTemp.memptr(), outputTemp.n_elem / batchSize, batchSize); @@ -127,4 +124,4 @@ void AdaptiveMaxPooling::serialize( } // namespace ann } // namespace mlpack -#endif \ No newline at end of file +#endif diff --git a/src/mlpack/methods/ann/layer/adaptive_mean_pooling.hpp b/src/mlpack/methods/ann/layer/adaptive_mean_pooling.hpp index 25c3d2e81d..b32294fabf 100644 --- a/src/mlpack/methods/ann/layer/adaptive_mean_pooling.hpp +++ b/src/mlpack/methods/ann/layer/adaptive_mean_pooling.hpp @@ -2,7 +2,7 @@ * @file adaptive_mean_pooling.hpp * @author Kartik Dutt * - * Definition of the Adaptive Mean Pooling layer class. + * Definition of the AdaptiveMeanPooling 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 @@ -131,14 +131,15 @@ class AdaptiveMeanPooling { 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) + if (kernelHeight < 0 || kernelWidth < 0) { - Log::Fatal << "Given output shape is not possible for given " - << " Input shape." << std::endl; + Log::Fatal << "Given output shape (" << outputWidth << ", " + << outputHeight << ") is not possible for given input shape (" + << inputWidth <<", "<< inputHeight << ")."<< std::endl; } } @@ -256,7 +257,6 @@ class AdaptiveMeanPooling //! Locally-stored output parameter object. OutputDataType outputParameter; - }; // class AdaptiveMeanPooling } // namespace ann diff --git a/src/mlpack/methods/ann/layer/adaptive_mean_pooling_impl.hpp b/src/mlpack/methods/ann/layer/adaptive_mean_pooling_impl.hpp index 98cbe356b7..c32d4836db 100644 --- a/src/mlpack/methods/ann/layer/adaptive_mean_pooling_impl.hpp +++ b/src/mlpack/methods/ann/layer/adaptive_mean_pooling_impl.hpp @@ -119,4 +119,4 @@ void AdaptiveMeanPooling::serialize( } // namespace ann } // namespace mlpack -#endif \ No newline at end of file +#endif diff --git a/src/mlpack/methods/ann/layer_names.hpp b/src/mlpack/methods/ann/layer_names.hpp index ea1150b14e..2a0cb83a60 100644 --- a/src/mlpack/methods/ann/layer_names.hpp +++ b/src/mlpack/methods/ann/layer_names.hpp @@ -29,6 +29,27 @@ class LayerNameVisitor : public boost::static_visitor LayerNameVisitor() { } + /* + * Return the name of the given layer of type AdaptiveMaxPooling as string. + * + * @param Given layer of type AdaptiveMaxPooling. + * @return The string representation of the layer. + */ + std::string LayerString(AdaptiveMaxPooling<> * /*layer*/) const + { + return "adaptivemaxpooling"; + } + + /* + * Return the name of the given layer of type AdaptiveMeanPooling as string. + * + * @param Given layer of type AdaptiveMeanPooling. + * @return The string representation of the layer. + */ + std::string LayerString(AdaptiveMeanPooling<> * /*layer*/) const + { + return "adaptivemeanpooling"; + } /** * Return the name of the given layer of type AtrousConvolution as a string. diff --git a/src/mlpack/tests/ann_layer_test.cpp b/src/mlpack/tests/ann_layer_test.cpp index c064d61d9a..b8eb7d8c6c 100644 --- a/src/mlpack/tests/ann_layer_test.cpp +++ b/src/mlpack/tests/ann_layer_test.cpp @@ -3053,7 +3053,11 @@ BOOST_AUTO_TEST_CASE(MaxPoolingTestCase) input(11) = 9; // Output-Size should be 2 x 2. // Square output. +<<<<<<< HEAD MaxPooling<> module1(2, 2, 2, 1); +======= + AdaptiveMeanPooling<> module1(2, 2); +>>>>>>> Completed and tested MaxPooling, Added both layers to layer_names.hpp module1.InputHeight() = 3; module1.InputWidth() = 4; module1.Forward(input, output); @@ -3117,4 +3121,89 @@ BOOST_AUTO_TEST_CASE(MaxPoolingTestCase) BOOST_REQUIRE_EQUAL(output.n_elem, 4); BOOST_REQUIRE_EQUAL(output.n_cols, 1); } +<<<<<<< HEAD +======= + +BOOST_AUTO_TEST_CASE(AdaptiveMaxPoolingTestCase) +{ + // For rectangular input. + arma::mat input = arma::mat(12, 1); + arma::mat output; + input.zeros(); + input(0) = 1; + input(1) = 2; + input(2) = 3; + input(3) = input(8) = 7; + input(4) = 4; + input(5) = 5; + input(6) = input(7) = 6; + input(10) = 8; + input(11) = 9; + // Output-Size should be 2 x 2. + // Square output. + AdaptiveMaxPooling<> module1(2, 2); + module1.InputHeight() = 3; + module1.InputWidth() = 4; + module1.Forward(std::move(input), std::move(output)); + // Calculated using torch.nn.AdaptiveMaxPool2d(). + BOOST_REQUIRE_EQUAL(arma::accu(output), 28); + BOOST_REQUIRE_EQUAL(output.n_elem, 4); + BOOST_REQUIRE_EQUAL(output.n_cols, 1); + + // For Square input. + input = arma::mat(9, 1); + input.zeros(); + input(0) = 6; + input(1) = 3; + input(2) = 9; + input(3) = 3; + input(6) = 3; + // Output-Size should be 1 x 2. + // Rectangular output. + AdaptiveMaxPooling<> module2(2, 1); + module2.InputHeight() = 3; + module2.InputWidth() = 3; + module2.Forward(std::move(input), std::move(output)); + // Calculated using torch.nn.AdaptiveMaxPool2d(). + BOOST_REQUIRE_EQUAL(arma::accu(output), 15.0); + BOOST_REQUIRE_EQUAL(output.n_elem, 2); + BOOST_REQUIRE_EQUAL(output.n_cols, 1); + + // For Square input. + input = arma::mat(16, 1); + input.zeros(); + input(0) = 6; + input(1) = 3; + input(2) = 9; + input(4) = 3; + input(8) = 3; + // Output-Size should be 3 x 3. + // Square output. + AdaptiveMaxPooling<> module3(std::tuple(3, 3)); + module3.InputHeight() = 4; + module3.InputWidth() = 4; + module3.Forward(std::move(input), std::move(output)); + // Calculated using torch.nn.AdaptiveMaxPool2d(). + BOOST_REQUIRE_EQUAL(arma::accu(output), 30.0); + BOOST_REQUIRE_EQUAL(output.n_elem, 9); + BOOST_REQUIRE_EQUAL(output.n_cols, 1); + + // For Rectangular input. + input = arma::mat(6, 1); + input.zeros(); + input(0) = 1; + input(1) = 1; + input(3) = 1; + // Output-Size should be 2 x 2. + // Square output. + AdaptiveMaxPooling<> module4(std::tuple(2, 2)); + module4.InputHeight() = 2; + module4.InputWidth() = 3; + module4.Forward(std::move(input), std::move(output)); + // Calculated using torch.nn.AdaptiveMaxPool2d(). + BOOST_REQUIRE_EQUAL(arma::accu(output), 3); + BOOST_REQUIRE_EQUAL(output.n_elem, 4); + BOOST_REQUIRE_EQUAL(output.n_cols, 1); +} +>>>>>>> Completed and tested MaxPooling, Added both layers to layer_names.hpp BOOST_AUTO_TEST_SUITE_END(); From fe29ecbdeb7c37464cf51d1ab0f8f7cdd1a1b7b4 Mon Sep 17 00:00:00 2001 From: kartikdutt18 <39593019+kartikdutt18@users.noreply.github.com> Date: Thu, 27 Feb 2020 11:14:00 +0530 Subject: [PATCH 3/7] Update adaptive_max_pooling --- src/mlpack/methods/ann/layer/adaptive_max_pooling_impl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/methods/ann/layer/adaptive_max_pooling_impl.hpp b/src/mlpack/methods/ann/layer/adaptive_max_pooling_impl.hpp index d75c2199f4..5603fcf463 100644 --- a/src/mlpack/methods/ann/layer/adaptive_max_pooling_impl.hpp +++ b/src/mlpack/methods/ann/layer/adaptive_max_pooling_impl.hpp @@ -64,7 +64,7 @@ void AdaptiveMaxPooling::Forward( batchSize = input.n_cols; inSize = input.n_elem / (inputWidth * inputHeight); inputTemp = arma::cube(const_cast&&>(input).memptr(), - inputWidth, inputHeight, batchSize * inSize, false, false); + inputWidth, inputHeight, batchSize * inSize); outputTemp = arma::zeros >(outputWidth, outputHeight, batchSize * inSize); poolingIndices.push_back(outputTemp); From c73e194b083203a04a435f358af9db80ade61e8a Mon Sep 17 00:00:00 2001 From: kartikdutt18 <39593019+kartikdutt18@users.noreply.github.com> Date: Thu, 27 Feb 2020 11:15:16 +0530 Subject: [PATCH 4/7] Update adaptive_mean_pooling Reverting to prev method wrapper --- .../ann/layer/adaptive_max_pooling.hpp | 165 ++++-------------- .../ann/layer/adaptive_max_pooling_impl.hpp | 70 ++------ src/mlpack/tests/ann_layer_test.cpp | 15 +- 3 files changed, 48 insertions(+), 202 deletions(-) diff --git a/src/mlpack/methods/ann/layer/adaptive_max_pooling.hpp b/src/mlpack/methods/ann/layer/adaptive_max_pooling.hpp index 91826211c1..0e1637425e 100644 --- a/src/mlpack/methods/ann/layer/adaptive_max_pooling.hpp +++ b/src/mlpack/methods/ann/layer/adaptive_max_pooling.hpp @@ -59,7 +59,7 @@ class AdaptiveMaxPooling * @param output Resulting output activation. */ template - void Forward(const arma::Mat&& input, arma::Mat&& output); + void Forward(const arma::Mat& input, arma::Mat& output); /** * Ordinary feed backward pass of a neural network, using 3rd-order tensors as @@ -71,51 +71,53 @@ class AdaptiveMaxPooling * @param g The calculated gradient. */ template - void Backward(const arma::Mat&& /* input */, - arma::Mat&& gy, - arma::Mat&& g); + void Backward(const arma::Mat& input, + arma::Mat& gy, + arma::Mat& g); //! Get the output parameter. - const OutputDataType& OutputParameter() const { return outputParameter; } + const OutputDataType& OutputParameter() const + { return poolingLayer.OutputParameter(); } + //! Modify the output parameter. - OutputDataType& OutputParameter() { return outputParameter; } + OutputDataType& OutputParameter() { return poolingLayer.OutputParameter(); } //! Get the delta. - const OutputDataType& Delta() const { return delta; } + const OutputDataType& Delta() const { return poolingLayer.Delta(); } //! Modify the delta. - OutputDataType& Delta() { return delta; } + OutputDataType& Delta() { return poolingLayer.Delta(); } //! Get the width. - size_t InputWidth() const { return inputWidth; } + size_t InputWidth() const { return poolingLayer.InputWidth(); } //! Modify the width. - size_t& InputWidth() { return inputWidth; } + size_t& InputWidth() { return poolingLayer.InputWidth(); } //! Get the height. - size_t InputHeight() const { return inputHeight; } + size_t InputHeight() const { return poolingLayer.InputHeight(); } //! Modify the height. - size_t& InputHeight() { return inputHeight; } + size_t& InputHeight() { return poolingLayer.InputHeight(); } //! Get the width. size_t OutputWidth() const { return outputWidth; } //! Modify the width. - size_t& OutputWidth() { return outputWidth; } + size_t& OutputWidth() { return outputHeight; } //! Get the height. - size_t OutputHeight() const { return outputHeight; } + size_t OutputHeight() const { return poolingLayer.OutputHeight(); } //! Modify the height. - size_t& OutputHeight() { return outputHeight; } + size_t& OutputHeight() { return poolingLayer.OutputHeight(); } //! Get the input size. - size_t InputSize() const { return inSize; } + size_t InputSize() const { return poolingLayer.InputSize(); } //! Get the output size. - size_t OutputSize() const { return outSize; } + size_t OutputSize() const { return poolingLayer.OutputSize(); } /** * Serialize the layer */ template - void serialize(Archive& ar, const unsigned int /* version */); + void serialize(Archive& ar, const unsigned int version); private: /** @@ -123,97 +125,26 @@ class AdaptiveMaxPooling */ void IntializeAdaptivePadding() { - strideWidth = std::floor(inputWidth / outputWidth); - strideHeight = std::floor(inputHeight / outputHeight); + poolingLayer.StrideWidth() = std::floor(poolingLayer.InputWidth() / + outputWidth); + poolingLayer.StrideHeight() = std::floor(poolingLayer.InputHeight() / + outputHeight); - kernelWidth = inputWidth - (outputWidth - 1) * strideWidth; - kernelHeight = inputHeight - (outputHeight - 1) * strideHeight; + poolingLayer.KernelWidth() = poolingLayer.InputWidth() - (outputWidth - 1) * + poolingLayer.StrideWidth(); + poolingLayer.KernelHeight() = poolingLayer.InputHeight() - (outputHeight - 1) * + poolingLayer.StrideHeight(); - if (kernelHeight < 0 || kernelWidth < 0) + if (poolingLayer.KernelHeight() < 0 || poolingLayer.KernelWidth() < 0) { Log::Fatal << "Given output shape (" << outputWidth << ", " << outputHeight << ") is not possible for given input shape (" - << inputWidth <<", "<< inputHeight << ")."<< std::endl; + << poolingLayer.InputWidth() <<", "<< poolingLayer.InputHeight() << ")."<< 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) - { - 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)); - const size_t idx = pooling.Pooling(subInput); - output(i, j) = subInput(idx); - arma::Mat subIndices = indices(arma::span(rowidx, - rowidx + rStep - 1), - arma::span(colidx, colidx + cStep - 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 reset parameter used to initialize the module once. - bool reset; - - //! Locally-stored input width. - size_t inputWidth; - - //! Locally-stored input height. - size_t inputHeight; + //! Locally stored MaxPooling Object. + ann::MaxPooling<> poolingLayer; //! Locally-stored output width. size_t outputWidth; @@ -221,38 +152,6 @@ class AdaptiveMaxPooling //! Locally-stored output height. size_t outputHeight; - //! 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 pooling strategy. - MaxPoolingRule pooling; - - //! 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 indices column parameter. - arma::Col indicesCol; - - //! Locally-stored pooling indicies. - std::vector poolingIndices; }; // class MaxPooling } // namespace ann diff --git a/src/mlpack/methods/ann/layer/adaptive_max_pooling_impl.hpp b/src/mlpack/methods/ann/layer/adaptive_max_pooling_impl.hpp index 5603fcf463..72399333b0 100644 --- a/src/mlpack/methods/ann/layer/adaptive_max_pooling_impl.hpp +++ b/src/mlpack/methods/ann/layer/adaptive_max_pooling_impl.hpp @@ -28,14 +28,8 @@ 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), - batchSize(0) + outputHeight(outputHeight) { // Nothing to do here. } @@ -43,14 +37,8 @@ AdaptiveMaxPooling::AdaptiveMaxPooling( 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), - batchSize(0) + outputHeight(std::get<1>(outputShape)) { // Nothing to do here. } @@ -58,67 +46,33 @@ AdaptiveMaxPooling::AdaptiveMaxPooling( template template void AdaptiveMaxPooling::Forward( - const arma::Mat&& input, arma::Mat&& output) + 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); - outputTemp = arma::zeros >(outputWidth, outputHeight, - batchSize * inSize); - poolingIndices.push_back(outputTemp); - size_t elements = inputWidth * inputHeight; - indicesCol = arma::linspace >(0, (elements - 1), - elements); - indices = arma::Mat(indicesCol.memptr(), inputWidth, inputHeight); - for (size_t s = 0; s < inputTemp.n_slices; s++) - PoolingOperation(inputTemp.slice(s), outputTemp.slice(s), - poolingIndices.back().slice(s)); - - output = arma::Mat(outputTemp.memptr(), outputTemp.n_elem / batchSize, - batchSize); - - outSize = batchSize * inSize; + poolingLayer.Forward(input, output); } template template void AdaptiveMaxPooling::Backward( - const arma::Mat&& /* input */, - arma::Mat&& gy, - arma::Mat&& g) + 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); + poolingLayer.Backward(input, gy, g); } template template void AdaptiveMaxPooling::serialize( Archive& ar, - const unsigned int /* version */) + 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); + + if (version > 0) + ar & BOOST_SERIALIZATION_NVP(poolingLayer); } } // namespace ann diff --git a/src/mlpack/tests/ann_layer_test.cpp b/src/mlpack/tests/ann_layer_test.cpp index b8eb7d8c6c..4a350a7506 100644 --- a/src/mlpack/tests/ann_layer_test.cpp +++ b/src/mlpack/tests/ann_layer_test.cpp @@ -3053,11 +3053,7 @@ BOOST_AUTO_TEST_CASE(MaxPoolingTestCase) input(11) = 9; // Output-Size should be 2 x 2. // Square output. -<<<<<<< HEAD MaxPooling<> module1(2, 2, 2, 1); -======= - AdaptiveMeanPooling<> module1(2, 2); ->>>>>>> Completed and tested MaxPooling, Added both layers to layer_names.hpp module1.InputHeight() = 3; module1.InputWidth() = 4; module1.Forward(input, output); @@ -3121,8 +3117,6 @@ BOOST_AUTO_TEST_CASE(MaxPoolingTestCase) BOOST_REQUIRE_EQUAL(output.n_elem, 4); BOOST_REQUIRE_EQUAL(output.n_cols, 1); } -<<<<<<< HEAD -======= BOOST_AUTO_TEST_CASE(AdaptiveMaxPoolingTestCase) { @@ -3144,7 +3138,7 @@ BOOST_AUTO_TEST_CASE(AdaptiveMaxPoolingTestCase) AdaptiveMaxPooling<> module1(2, 2); module1.InputHeight() = 3; module1.InputWidth() = 4; - module1.Forward(std::move(input), std::move(output)); + module1.Forward(input, output); // Calculated using torch.nn.AdaptiveMaxPool2d(). BOOST_REQUIRE_EQUAL(arma::accu(output), 28); BOOST_REQUIRE_EQUAL(output.n_elem, 4); @@ -3163,7 +3157,7 @@ BOOST_AUTO_TEST_CASE(AdaptiveMaxPoolingTestCase) AdaptiveMaxPooling<> module2(2, 1); module2.InputHeight() = 3; module2.InputWidth() = 3; - module2.Forward(std::move(input), std::move(output)); + module2.Forward(input, output); // Calculated using torch.nn.AdaptiveMaxPool2d(). BOOST_REQUIRE_EQUAL(arma::accu(output), 15.0); BOOST_REQUIRE_EQUAL(output.n_elem, 2); @@ -3182,7 +3176,7 @@ BOOST_AUTO_TEST_CASE(AdaptiveMaxPoolingTestCase) AdaptiveMaxPooling<> module3(std::tuple(3, 3)); module3.InputHeight() = 4; module3.InputWidth() = 4; - module3.Forward(std::move(input), std::move(output)); + module3.Forward(input, output); // Calculated using torch.nn.AdaptiveMaxPool2d(). BOOST_REQUIRE_EQUAL(arma::accu(output), 30.0); BOOST_REQUIRE_EQUAL(output.n_elem, 9); @@ -3199,11 +3193,10 @@ BOOST_AUTO_TEST_CASE(AdaptiveMaxPoolingTestCase) AdaptiveMaxPooling<> module4(std::tuple(2, 2)); module4.InputHeight() = 2; module4.InputWidth() = 3; - module4.Forward(std::move(input), std::move(output)); + module4.Forward(input, output); // Calculated using torch.nn.AdaptiveMaxPool2d(). BOOST_REQUIRE_EQUAL(arma::accu(output), 3); BOOST_REQUIRE_EQUAL(output.n_elem, 4); BOOST_REQUIRE_EQUAL(output.n_cols, 1); } ->>>>>>> Completed and tested MaxPooling, Added both layers to layer_names.hpp BOOST_AUTO_TEST_SUITE_END(); From 6eae57e18e0164e15ba1d69f263c6b04fb3f4ebf Mon Sep 17 00:00:00 2001 From: kartikdutt18 Date: Thu, 19 Mar 2020 16:42:20 +0530 Subject: [PATCH 5/7] Finished new definition as wrapper and added tests Style Fix Remaining style fix Add reset option Style and Typo fixes Style and Typo fixes Typo-Fix Removed reset line that used to set it to false Changed reset Update History.md Better comments Better comments in pooling layers as well Update History.md --- HISTORY.md | 4 + .../ann/layer/adaptive_max_pooling.hpp | 40 ++-- .../ann/layer/adaptive_max_pooling_impl.hpp | 16 +- .../ann/layer/adaptive_mean_pooling.hpp | 188 ++++-------------- .../ann/layer/adaptive_mean_pooling_impl.hpp | 73 ++----- src/mlpack/methods/ann/layer/max_pooling.hpp | 16 +- src/mlpack/methods/ann/layer/mean_pooling.hpp | 16 +- src/mlpack/methods/ann/layer_names.hpp | 5 +- src/mlpack/tests/ann_layer_test.cpp | 125 +++++++++++- 9 files changed, 239 insertions(+), 244 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index fc4dbf8f9b..2c314f0547 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -11,6 +11,7 @@ * Add L1 Loss function (#2203). +<<<<<<< HEAD * Pass CMAKE_CXX_FLAGS (compilation options) correctly to Python build (#2367). @@ -20,6 +21,9 @@ * Add serialization support from Julia; use `mlpack.serialize()` and `mlpack.deserialize()` to save and load from `IOBuffer`s. +======= + * Add adaptive max pooling and adaptive mean pooling layers (#2195). +>>>>>>> df2354a79... Finished new definition as wrapper and added tests ### mlpack 3.3.0 ###### 2020-04-07 diff --git a/src/mlpack/methods/ann/layer/adaptive_max_pooling.hpp b/src/mlpack/methods/ann/layer/adaptive_max_pooling.hpp index 0e1637425e..fb54112a71 100644 --- a/src/mlpack/methods/ann/layer/adaptive_max_pooling.hpp +++ b/src/mlpack/methods/ann/layer/adaptive_max_pooling.hpp @@ -87,25 +87,25 @@ class AdaptiveMaxPooling //! Modify the delta. OutputDataType& Delta() { return poolingLayer.Delta(); } - //! Get the width. + //! Get the input width. size_t InputWidth() const { return poolingLayer.InputWidth(); } - //! Modify the width. + //! Modify the input width. size_t& InputWidth() { return poolingLayer.InputWidth(); } - //! Get the height. + //! Get the input height. size_t InputHeight() const { return poolingLayer.InputHeight(); } - //! Modify the height. + //! Modify the input height. size_t& InputHeight() { return poolingLayer.InputHeight(); } - //! Get the width. + //! Get the output width. size_t OutputWidth() const { return outputWidth; } - //! Modify the width. - size_t& OutputWidth() { return outputHeight; } + //! Modify the output width. + size_t& OutputWidth() { return outputWidth; } - //! Get the height. - size_t OutputHeight() const { return poolingLayer.OutputHeight(); } - //! Modify the height. - size_t& OutputHeight() { return poolingLayer.OutputHeight(); } + //! Get the output height. + size_t OutputHeight() const { return outputHeight; } + //! Modify the output height. + size_t& OutputHeight() { return outputHeight; } //! Get the input size. size_t InputSize() const { return poolingLayer.InputSize(); } @@ -130,16 +130,18 @@ class AdaptiveMaxPooling poolingLayer.StrideHeight() = std::floor(poolingLayer.InputHeight() / outputHeight); - poolingLayer.KernelWidth() = poolingLayer.InputWidth() - (outputWidth - 1) * - poolingLayer.StrideWidth(); - poolingLayer.KernelHeight() = poolingLayer.InputHeight() - (outputHeight - 1) * - poolingLayer.StrideHeight(); + poolingLayer.KernelWidth() = poolingLayer.InputWidth() - + (outputWidth - 1) * poolingLayer.StrideWidth(); + poolingLayer.KernelHeight() = poolingLayer.InputHeight() - + (outputHeight - 1) * poolingLayer.StrideHeight(); - if (poolingLayer.KernelHeight() < 0 || poolingLayer.KernelWidth() < 0) + if (poolingLayer.KernelHeight() <= 0 || poolingLayer.KernelWidth() <= 0 || + poolingLayer.StrideWidth() <= 0 || poolingLayer.StrideHeight() <= 0) { Log::Fatal << "Given output shape (" << outputWidth << ", " << outputHeight << ") is not possible for given input shape (" - << poolingLayer.InputWidth() <<", "<< poolingLayer.InputHeight() << ")."<< std::endl; + << poolingLayer.InputWidth() << ", " << poolingLayer.InputHeight() + << ")." << std::endl; } } @@ -152,7 +154,9 @@ class AdaptiveMaxPooling //! Locally-stored output height. size_t outputHeight; -}; // class MaxPooling + //! Locally-stored reset parameter used to initialize the layer once. + bool reset; +}; // class AdaptiveMaxPooling } // namespace ann } // namespace mlpack diff --git a/src/mlpack/methods/ann/layer/adaptive_max_pooling_impl.hpp b/src/mlpack/methods/ann/layer/adaptive_max_pooling_impl.hpp index 72399333b0..3896c52104 100644 --- a/src/mlpack/methods/ann/layer/adaptive_max_pooling_impl.hpp +++ b/src/mlpack/methods/ann/layer/adaptive_max_pooling_impl.hpp @@ -28,8 +28,7 @@ template AdaptiveMaxPooling::AdaptiveMaxPooling( const size_t outputWidth, const size_t outputHeight) : - outputWidth(outputWidth), - outputHeight(outputHeight) + AdaptiveMaxPooling(std::tuple(outputWidth, outputHeight)) { // Nothing to do here. } @@ -38,9 +37,10 @@ template AdaptiveMaxPooling::AdaptiveMaxPooling( const std::tuple outputShape): outputWidth(std::get<0>(outputShape)), - outputHeight(std::get<1>(outputShape)) + outputHeight(std::get<1>(outputShape)), + reset(false) { - // Nothing to do here. + poolingLayer = ann::MaxPooling<>(0, 0); } template @@ -48,7 +48,12 @@ template void AdaptiveMaxPooling::Forward( const arma::Mat& input, arma::Mat& output) { - IntializeAdaptivePadding(); + if (!reset) + { + IntializeAdaptivePadding(); + reset = true; + } + poolingLayer.Forward(input, output); } @@ -70,6 +75,7 @@ void AdaptiveMaxPooling::serialize( { ar & BOOST_SERIALIZATION_NVP(outputWidth); ar & BOOST_SERIALIZATION_NVP(outputHeight); + ar & BOOST_SERIALIZATION_NVP(reset); if (version > 0) ar & BOOST_SERIALIZATION_NVP(poolingLayer); diff --git a/src/mlpack/methods/ann/layer/adaptive_mean_pooling.hpp b/src/mlpack/methods/ann/layer/adaptive_mean_pooling.hpp index b32294fabf..b0782febc6 100644 --- a/src/mlpack/methods/ann/layer/adaptive_mean_pooling.hpp +++ b/src/mlpack/methods/ann/layer/adaptive_mean_pooling.hpp @@ -60,7 +60,7 @@ class AdaptiveMeanPooling * @param output Resulting output activation. */ template - void Forward(const arma::Mat&& input, arma::Mat&& output); + void Forward(const arma::Mat& input, arma::Mat& output); /** * Ordinary feed backward pass of a neural network, using 3rd-order tensors as @@ -72,56 +72,53 @@ class AdaptiveMeanPooling * @param g The calculated gradient. */ template - void Backward(const arma::Mat&& /* input */, - arma::Mat&& gy, - arma::Mat&& g); + void Backward(const arma::Mat& input, + arma::Mat& gy, + arma::Mat& g); //! Get the output parameter. - OutputDataType const &OutputParameter() const { return outputParameter; } + const OutputDataType& OutputParameter() const + { return poolingLayer.OutputParameter(); } + //! Modify the output parameter. - OutputDataType &OutputParameter() { return outputParameter; } + OutputDataType& OutputParameter() { return poolingLayer.OutputParameter(); } //! Get the delta. - OutputDataType const &Delta() const { return delta; } + const OutputDataType& Delta() const { return poolingLayer.Delta(); } //! Modify the delta. - OutputDataType &Delta() { return delta; } + OutputDataType& Delta() { return poolingLayer.Delta(); } - //! Get the width. - size_t const &InputWidth() const { return inputWidth; } - //! Modify the width. - size_t &InputWidth() { return inputWidth; } + //! Get the input width. + size_t InputWidth() const { return poolingLayer.InputWidth(); } + //! Modify the input width. + size_t& InputWidth() { return poolingLayer.InputWidth(); } - //! Get the height. - size_t const &InputHeight() const { return inputHeight; } - //! Modify the height. - size_t &InputHeight() { return inputHeight; } + //! Get the input height. + size_t InputHeight() const { return poolingLayer.InputHeight(); } + //! Modify the input height. + size_t& InputHeight() { return poolingLayer.InputHeight(); } - //! Get the width. - size_t const &OutputWidth() const { return outputWidth; } - //! Modify the width. - size_t &OutputWidth() { return outputWidth; } + //! Get the output width. + size_t OutputWidth() const { return outputWidth; } + //! Modify the output 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 output height. + size_t OutputHeight() const { return outputHeight; } + //! Modify the output height. + size_t& OutputHeight() { return outputHeight; } //! Get the input size. - size_t InputSize() const { return inSize; } + size_t InputSize() const { return poolingLayer.InputSize(); } //! 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; } + size_t OutputSize() const { return poolingLayer.OutputSize(); } /** * Serialize the layer */ template - void serialize(Archive& ar, const unsigned int /* version */); + void serialize(Archive& ar, const unsigned int version); private: /** @@ -129,101 +126,28 @@ class AdaptiveMeanPooling */ void IntializeAdaptivePadding() { - strideWidth = std::floor(inputWidth / outputWidth); - strideHeight = std::floor(inputHeight / outputHeight); + poolingLayer.StrideWidth() = std::floor(poolingLayer.InputWidth() / + outputWidth); + poolingLayer.StrideHeight() = std::floor(poolingLayer.InputHeight() / + outputHeight); - kernelWidth = inputWidth - (outputWidth - 1) * strideWidth; - kernelHeight = inputHeight - (outputHeight - 1) * strideHeight; + poolingLayer.KernelWidth() = poolingLayer.InputWidth() - + (outputWidth - 1) * poolingLayer.StrideWidth(); + poolingLayer.KernelHeight() = poolingLayer.InputHeight() - + (outputHeight - 1) * poolingLayer.StrideHeight(); - if (kernelHeight < 0 || kernelWidth < 0) + if (poolingLayer.KernelHeight() <= 0 || poolingLayer.KernelWidth() <= 0 || + poolingLayer.StrideWidth() <= 0 || poolingLayer.StrideHeight() <= 0) { Log::Fatal << "Given output shape (" << outputWidth << ", " << outputHeight << ") is not possible for given input shape (" - << inputWidth <<", "<< inputHeight << ")."<< std::endl; + << poolingLayer.InputWidth() << ", " << poolingLayer.InputHeight() + << ")." << 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 MeanPooling Object. + ann::MeanPooling<> poolingLayer; //! Locally-stored output width. size_t outputWidth; @@ -231,32 +155,8 @@ class AdaptiveMeanPooling //! Locally-stored output height. size_t outputHeight; - //! Locally-stored reset parameter used to initialize the module once. + //! Locally-stored reset parameter used to initialize the layer 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 diff --git a/src/mlpack/methods/ann/layer/adaptive_mean_pooling_impl.hpp b/src/mlpack/methods/ann/layer/adaptive_mean_pooling_impl.hpp index c32d4836db..f3dc5c00de 100644 --- a/src/mlpack/methods/ann/layer/adaptive_mean_pooling_impl.hpp +++ b/src/mlpack/methods/ann/layer/adaptive_mean_pooling_impl.hpp @@ -28,15 +28,7 @@ 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) + AdaptiveMeanPooling(std::tuple(outputWidth, outputHeight)) { // Nothing to do here. } @@ -44,76 +36,49 @@ AdaptiveMeanPooling::AdaptiveMeanPooling( 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) + reset(false) { - // Nothing to do here. + poolingLayer = ann::MeanPooling<>(0, 0); } template template void AdaptiveMeanPooling::Forward( - const arma::Mat&& input, arma::Mat&& output) + 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)); + if (!reset) + { + IntializeAdaptivePadding(); + reset = true; + } - output = arma::Mat(outputTemp.memptr(), outputTemp.n_elem / batchSize, - batchSize); - - outSize = batchSize * inSize; + poolingLayer.Forward(input, output); } template template void AdaptiveMeanPooling::Backward( - const arma::Mat&& /* input */, - arma::Mat&& gy, - arma::Mat&& g) + 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); + poolingLayer.Backward(input, gy, g); } template template void AdaptiveMeanPooling::serialize( Archive& ar, - const unsigned int /* version */) + 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); + ar & BOOST_SERIALIZATION_NVP(reset); + + if (version > 0) + ar & BOOST_SERIALIZATION_NVP(poolingLayer); } } // namespace ann diff --git a/src/mlpack/methods/ann/layer/max_pooling.hpp b/src/mlpack/methods/ann/layer/max_pooling.hpp index 3f3af81949..cffa5292f4 100644 --- a/src/mlpack/methods/ann/layer/max_pooling.hpp +++ b/src/mlpack/methods/ann/layer/max_pooling.hpp @@ -104,24 +104,24 @@ class MaxPooling //! Modify the delta. OutputDataType& Delta() { return delta; } - //! Get the width. + //! Get the input width. size_t InputWidth() const { return inputWidth; } - //! Modify the width. + //! Modify the input width. size_t& InputWidth() { return inputWidth; } - //! Get the height. + //! Get the input height. size_t InputHeight() const { return inputHeight; } - //! Modify the height. + //! Modify the input height. size_t& InputHeight() { return inputHeight; } - //! Get the width. + //! Get the output width. size_t OutputWidth() const { return outputWidth; } - //! Modify the width. + //! Modify the output width. size_t& OutputWidth() { return outputWidth; } - //! Get the height. + //! Get the output height. size_t OutputHeight() const { return outputHeight; } - //! Modify the height. + //! Modify the output height. size_t& OutputHeight() { return outputHeight; } //! Get the input size. diff --git a/src/mlpack/methods/ann/layer/mean_pooling.hpp b/src/mlpack/methods/ann/layer/mean_pooling.hpp index 34c3a811e2..4680e4ab59 100644 --- a/src/mlpack/methods/ann/layer/mean_pooling.hpp +++ b/src/mlpack/methods/ann/layer/mean_pooling.hpp @@ -84,24 +84,24 @@ class MeanPooling //! Modify the delta. OutputDataType& Delta() { return delta; } - //! Get the width. + //! Get the intput width. size_t const& InputWidth() const { return inputWidth; } - //! Modify the width. + //! Modify the input width. size_t& InputWidth() { return inputWidth; } - //! Get the height. + //! Get the input height. size_t const& InputHeight() const { return inputHeight; } - //! Modify the height. + //! Modify the input height. size_t& InputHeight() { return inputHeight; } - //! Get the width. + //! Get the output width. size_t const& OutputWidth() const { return outputWidth; } - //! Modify the width. + //! Modify the output width. size_t& OutputWidth() { return outputWidth; } - //! Get the height. + //! Get the output height. size_t const& OutputHeight() const { return outputHeight; } - //! Modify the height. + //! Modify the output height. size_t& OutputHeight() { return outputHeight; } //! Get the input size. diff --git a/src/mlpack/methods/ann/layer_names.hpp b/src/mlpack/methods/ann/layer_names.hpp index 2a0cb83a60..a3671a6837 100644 --- a/src/mlpack/methods/ann/layer_names.hpp +++ b/src/mlpack/methods/ann/layer_names.hpp @@ -29,7 +29,8 @@ class LayerNameVisitor : public boost::static_visitor LayerNameVisitor() { } - /* + + /** * Return the name of the given layer of type AdaptiveMaxPooling as string. * * @param Given layer of type AdaptiveMaxPooling. @@ -40,7 +41,7 @@ class LayerNameVisitor : public boost::static_visitor return "adaptivemaxpooling"; } - /* + /** * Return the name of the given layer of type AdaptiveMeanPooling as string. * * @param Given layer of type AdaptiveMeanPooling. diff --git a/src/mlpack/tests/ann_layer_test.cpp b/src/mlpack/tests/ann_layer_test.cpp index 4a350a7506..839b99ce6b 100644 --- a/src/mlpack/tests/ann_layer_test.cpp +++ b/src/mlpack/tests/ann_layer_test.cpp @@ -3118,11 +3118,15 @@ BOOST_AUTO_TEST_CASE(MaxPoolingTestCase) BOOST_REQUIRE_EQUAL(output.n_cols, 1); } +/** + * Simple test for Adaptive pooling for Max Pooling layer. + */ BOOST_AUTO_TEST_CASE(AdaptiveMaxPoolingTestCase) { // For rectangular input. arma::mat input = arma::mat(12, 1); - arma::mat output; + arma::mat output, delta; + input.zeros(); input(0) = 1; input(1) = 2; @@ -3143,6 +3147,9 @@ BOOST_AUTO_TEST_CASE(AdaptiveMaxPoolingTestCase) BOOST_REQUIRE_EQUAL(arma::accu(output), 28); BOOST_REQUIRE_EQUAL(output.n_elem, 4); BOOST_REQUIRE_EQUAL(output.n_cols, 1); + // Test the Backward Function. + module1.Backward(input, output, delta); + BOOST_REQUIRE_EQUAL(arma::accu(delta), 28.0); // For Square input. input = arma::mat(9, 1); @@ -3162,6 +3169,9 @@ BOOST_AUTO_TEST_CASE(AdaptiveMaxPoolingTestCase) BOOST_REQUIRE_EQUAL(arma::accu(output), 15.0); BOOST_REQUIRE_EQUAL(output.n_elem, 2); BOOST_REQUIRE_EQUAL(output.n_cols, 1); + // Test the Backward Function. + module2.Backward(input, output, delta); + BOOST_REQUIRE_EQUAL(arma::accu(delta), 15.0); // For Square input. input = arma::mat(16, 1); @@ -3181,9 +3191,12 @@ BOOST_AUTO_TEST_CASE(AdaptiveMaxPoolingTestCase) BOOST_REQUIRE_EQUAL(arma::accu(output), 30.0); BOOST_REQUIRE_EQUAL(output.n_elem, 9); BOOST_REQUIRE_EQUAL(output.n_cols, 1); + // Test the Backward Function. + module3.Backward(input, output, delta); + BOOST_REQUIRE_EQUAL(arma::accu(delta), 30.0); // For Rectangular input. - input = arma::mat(6, 1); + input = arma::mat(20, 1); input.zeros(); input(0) = 1; input(1) = 1; @@ -3191,12 +3204,114 @@ BOOST_AUTO_TEST_CASE(AdaptiveMaxPoolingTestCase) // Output-Size should be 2 x 2. // Square output. AdaptiveMaxPooling<> module4(std::tuple(2, 2)); - module4.InputHeight() = 2; - module4.InputWidth() = 3; + module4.InputHeight() = 4; + module4.InputWidth() = 5; module4.Forward(input, output); // Calculated using torch.nn.AdaptiveMaxPool2d(). - BOOST_REQUIRE_EQUAL(arma::accu(output), 3); + BOOST_REQUIRE_EQUAL(arma::accu(output), 2); BOOST_REQUIRE_EQUAL(output.n_elem, 4); BOOST_REQUIRE_EQUAL(output.n_cols, 1); + // Test the Backward Function. + module4.Backward(input, output, delta); + BOOST_REQUIRE_EQUAL(arma::accu(delta), 2.0); } + +/** + * Simple test for Adaptive pooling for Mean Pooling layer. + */ +BOOST_AUTO_TEST_CASE(AdaptiveMeanPoolingTestCase) +{ + // For rectangular input. + arma::mat input = arma::mat(12, 1); + arma::mat output, delta; + + input.zeros(); + input(0) = 1; + input(1) = 2; + input(2) = 3; + input(3) = input(8) = 7; + input(4) = 4; + input(5) = 5; + input(6) = input(7) = 6; + input(10) = 8; + input(11) = 9; + // Output-Size should be 2 x 2. + // Square output. + AdaptiveMeanPooling<> module1(2, 2); + module1.InputHeight() = 3; + module1.InputWidth() = 4; + module1.Forward(input, output); + // Calculated using torch.nn.AdaptiveAvgPool2d(). + BOOST_REQUIRE_EQUAL(arma::accu(output), 19.75); + BOOST_REQUIRE_EQUAL(output.n_elem, 4); + BOOST_REQUIRE_EQUAL(output.n_cols, 1); + // Test the Backward Function. + module1.Backward(input, output, delta); + BOOST_REQUIRE_EQUAL(arma::accu(delta), 7.0); + + // For Square input. + input = arma::mat(9, 1); + input.zeros(); + input(0) = 6; + input(1) = 3; + input(2) = 9; + input(3) = 3; + input(6) = 3; + // Output-Size should be 1 x 2. + // Rectangular output. + AdaptiveMeanPooling<> module2(1, 2); + module2.InputHeight() = 3; + module2.InputWidth() = 3; + module2.Forward(input, output); + // Calculated using torch.nn.AdaptiveAvgPool2d(). + BOOST_REQUIRE_EQUAL(arma::accu(output), 4.5); + BOOST_REQUIRE_EQUAL(output.n_elem, 2); + BOOST_REQUIRE_EQUAL(output.n_cols, 1); + // Test the Backward Function. + module2.Backward(input, output, delta); + BOOST_REQUIRE_EQUAL(arma::accu(delta), 0.0); + + // For Square input. + input = arma::mat(16, 1); + input.zeros(); + input(0) = 6; + input(1) = 3; + input(2) = 9; + input(4) = 3; + input(8) = 3; + // Output-Size should be 3 x 3. + // Square output. + AdaptiveMeanPooling<> module3(std::tuple(3, 3)); + module3.InputHeight() = 4; + module3.InputWidth() = 4; + module3.Forward(input, output); + // Calculated using torch.nn.AdaptiveAvgPool2d(). + BOOST_REQUIRE_EQUAL(arma::accu(output), 10.5); + BOOST_REQUIRE_EQUAL(output.n_elem, 9); + BOOST_REQUIRE_EQUAL(output.n_cols, 1); + // Test the Backward Function. + module3.Backward(input, output, delta); + BOOST_REQUIRE_EQUAL(arma::accu(delta), 10.5); + + // For Rectangular input. + input = arma::mat(24, 1); + input.zeros(); + input(0) = 3; + input(1) = 3; + input(4) = 3; + // Output-Size should be 3 x 3. + // Square output. + AdaptiveMeanPooling<> module4(std::tuple(3, 3)); + module4.InputHeight() = 4; + module4.InputWidth() = 6; + module4.Forward(input, output); + // Calculated using torch.nn.AdaptiveAvgPool2d(). + BOOST_REQUIRE_EQUAL(arma::accu(output), 2.25); + BOOST_REQUIRE_EQUAL(output.n_elem, 9); + BOOST_REQUIRE_EQUAL(output.n_cols, 1); + // Test the Backward Function. + module4.Backward(input, output, delta); + BOOST_REQUIRE_EQUAL(arma::accu(delta), 1.5); +} + BOOST_AUTO_TEST_SUITE_END(); From baa7416b1e285c391debc360a99a0ea5e11a64e4 Mon Sep 17 00:00:00 2001 From: kartikdutt18 Date: Fri, 10 Apr 2020 18:35:24 +0530 Subject: [PATCH 6/7] Added layer to layernames, layer_types --- .../methods/ann/layer/adaptive_max_pooling.hpp | 9 +++++---- .../ann/layer/adaptive_max_pooling_impl.hpp | 4 ++-- .../methods/ann/layer/adaptive_mean_pooling.hpp | 9 +++++---- .../ann/layer/adaptive_mean_pooling_impl.hpp | 4 ++-- src/mlpack/methods/ann/layer/layer.hpp | 2 ++ src/mlpack/methods/ann/layer/layer_types.hpp | 14 ++++++++++++++ src/mlpack/methods/ann/layer/max_pooling.hpp | 2 +- src/mlpack/methods/ann/layer/mean_pooling.hpp | 2 +- 8 files changed, 32 insertions(+), 14 deletions(-) diff --git a/src/mlpack/methods/ann/layer/adaptive_max_pooling.hpp b/src/mlpack/methods/ann/layer/adaptive_max_pooling.hpp index fb54112a71..302b61f368 100644 --- a/src/mlpack/methods/ann/layer/adaptive_max_pooling.hpp +++ b/src/mlpack/methods/ann/layer/adaptive_max_pooling.hpp @@ -13,6 +13,7 @@ #define MLPACK_METHODS_ANN_LAYER_ADAPTIVE_MAX_POOLING_HPP #include +#include "layer_types.hpp" namespace mlpack { namespace ann /** Artificial Neural Network. */ { @@ -49,7 +50,7 @@ class AdaptiveMaxPooling * * @param outputShape A two-value tuple indicating width and height of the output. */ - AdaptiveMaxPooling(const std::tuple outputShape); + AdaptiveMaxPooling(const std::tuple& outputShape); /** * Ordinary feed forward pass of a neural network, evaluating the function @@ -72,7 +73,7 @@ class AdaptiveMaxPooling */ template void Backward(const arma::Mat& input, - arma::Mat& gy, + const arma::Mat& gy, arma::Mat& g); //! Get the output parameter. @@ -114,7 +115,7 @@ class AdaptiveMaxPooling size_t OutputSize() const { return poolingLayer.OutputSize(); } /** - * Serialize the layer + * Serialize the layer. */ template void serialize(Archive& ar, const unsigned int version); @@ -146,7 +147,7 @@ class AdaptiveMaxPooling } //! Locally stored MaxPooling Object. - ann::MaxPooling<> poolingLayer; + MaxPooling poolingLayer; //! Locally-stored output width. size_t outputWidth; diff --git a/src/mlpack/methods/ann/layer/adaptive_max_pooling_impl.hpp b/src/mlpack/methods/ann/layer/adaptive_max_pooling_impl.hpp index 3896c52104..c0c4266f93 100644 --- a/src/mlpack/methods/ann/layer/adaptive_max_pooling_impl.hpp +++ b/src/mlpack/methods/ann/layer/adaptive_max_pooling_impl.hpp @@ -35,7 +35,7 @@ AdaptiveMaxPooling::AdaptiveMaxPooling( template AdaptiveMaxPooling::AdaptiveMaxPooling( - const std::tuple outputShape): + const std::tuple& outputShape): outputWidth(std::get<0>(outputShape)), outputHeight(std::get<1>(outputShape)), reset(false) @@ -61,7 +61,7 @@ template template void AdaptiveMaxPooling::Backward( const arma::Mat& input, - arma::Mat& gy, + const arma::Mat& gy, arma::Mat& g) { poolingLayer.Backward(input, gy, g); diff --git a/src/mlpack/methods/ann/layer/adaptive_mean_pooling.hpp b/src/mlpack/methods/ann/layer/adaptive_mean_pooling.hpp index b0782febc6..703a9e3084 100644 --- a/src/mlpack/methods/ann/layer/adaptive_mean_pooling.hpp +++ b/src/mlpack/methods/ann/layer/adaptive_mean_pooling.hpp @@ -14,6 +14,7 @@ #define MLPACK_METHODS_ANN_LAYER_ADAPTIVE_MEAN_POOLING_HPP #include +#include "layer_types.hpp" namespace mlpack { namespace ann /** Artificial Neural Network. */ { @@ -50,7 +51,7 @@ class AdaptiveMeanPooling * * @param outputShape A two-value tuple indicating width and height of the output. */ - AdaptiveMeanPooling(const std::tuple outputShape); + AdaptiveMeanPooling(const std::tuple& outputShape); /** * Ordinary feed forward pass of a neural network, evaluating the function @@ -73,7 +74,7 @@ class AdaptiveMeanPooling */ template void Backward(const arma::Mat& input, - arma::Mat& gy, + const arma::Mat& gy, arma::Mat& g); //! Get the output parameter. @@ -115,7 +116,7 @@ class AdaptiveMeanPooling size_t OutputSize() const { return poolingLayer.OutputSize(); } /** - * Serialize the layer + * Serialize the layer. */ template void serialize(Archive& ar, const unsigned int version); @@ -147,7 +148,7 @@ class AdaptiveMeanPooling } //! Locally stored MeanPooling Object. - ann::MeanPooling<> poolingLayer; + MeanPooling poolingLayer; //! Locally-stored output width. size_t outputWidth; diff --git a/src/mlpack/methods/ann/layer/adaptive_mean_pooling_impl.hpp b/src/mlpack/methods/ann/layer/adaptive_mean_pooling_impl.hpp index f3dc5c00de..6cf2c5116c 100644 --- a/src/mlpack/methods/ann/layer/adaptive_mean_pooling_impl.hpp +++ b/src/mlpack/methods/ann/layer/adaptive_mean_pooling_impl.hpp @@ -35,7 +35,7 @@ AdaptiveMeanPooling::AdaptiveMeanPooling( template AdaptiveMeanPooling::AdaptiveMeanPooling( - const std::tuple outputShape): + const std::tuple& outputShape): outputWidth(std::get<0>(outputShape)), outputHeight(std::get<1>(outputShape)), reset(false) @@ -61,7 +61,7 @@ template template void AdaptiveMeanPooling::Backward( const arma::Mat& input, - arma::Mat& gy, + const arma::Mat& gy, arma::Mat& g) { poolingLayer.Backward(input, gy, g); diff --git a/src/mlpack/methods/ann/layer/layer.hpp b/src/mlpack/methods/ann/layer/layer.hpp index 44cc8b667f..a9b1380933 100644 --- a/src/mlpack/methods/ann/layer/layer.hpp +++ b/src/mlpack/methods/ann/layer/layer.hpp @@ -13,6 +13,8 @@ #define MLPACK_METHODS_ANN_LAYER_LAYER_HPP #include "add.hpp" +#include "adaptive_max_pooling.hpp" +#include "adaptive_mean_pooling.hpp" #include "add_merge.hpp" #include "alpha_dropout.hpp" #include "atrous_convolution.hpp" diff --git a/src/mlpack/methods/ann/layer/layer_types.hpp b/src/mlpack/methods/ann/layer/layer_types.hpp index 5a07c59016..70e6ddef3f 100644 --- a/src/mlpack/methods/ann/layer/layer_types.hpp +++ b/src/mlpack/methods/ann/layer/layer_types.hpp @@ -36,6 +36,8 @@ #include #include #include +#include +#include #include #include #include @@ -179,6 +181,16 @@ template class WeightNorm; +template +class AdaptiveMaxPooling; + +template +class AdaptiveMeanPooling; + using MoreTypes = boost::variant< Recurrent*, RecurrentAttention*, @@ -194,6 +206,8 @@ using MoreTypes = boost::variant< template using LayerTypes = boost::variant< + AdaptiveMaxPooling*, + AdaptiveMeanPooling*, Add*, AddMerge*, AtrousConvolution, diff --git a/src/mlpack/methods/ann/layer/max_pooling.hpp b/src/mlpack/methods/ann/layer/max_pooling.hpp index cffa5292f4..48a05e8c06 100644 --- a/src/mlpack/methods/ann/layer/max_pooling.hpp +++ b/src/mlpack/methods/ann/layer/max_pooling.hpp @@ -161,7 +161,7 @@ class MaxPooling bool& Deterministic() { return deterministic; } /** - * Serialize the layer + * Serialize the layer. */ template void serialize(Archive& ar, const unsigned int /* version */); diff --git a/src/mlpack/methods/ann/layer/mean_pooling.hpp b/src/mlpack/methods/ann/layer/mean_pooling.hpp index 4680e4ab59..f1368eb078 100644 --- a/src/mlpack/methods/ann/layer/mean_pooling.hpp +++ b/src/mlpack/methods/ann/layer/mean_pooling.hpp @@ -141,7 +141,7 @@ class MeanPooling bool& Deterministic() { return deterministic; } /** - * Serialize the layer + * Serialize the layer. */ template void serialize(Archive& ar, const unsigned int /* version */); From 39e08d63555e7093627cbc3c58dc7968ad5dbe6d Mon Sep 17 00:00:00 2001 From: kartikdutt18 Date: Sat, 2 May 2020 00:24:54 +0530 Subject: [PATCH 7/7] History updated --- HISTORY.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 2c314f0547..f516fd8834 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,6 @@ ### mlpack ?.?.? ###### ????-??-?? + * Add adaptive max pooling and adaptive mean pooling layers (#2195). ### mlpack 3.3.1 ###### 2020-04-29 @@ -11,7 +12,6 @@ * Add L1 Loss function (#2203). -<<<<<<< HEAD * Pass CMAKE_CXX_FLAGS (compilation options) correctly to Python build (#2367). @@ -21,9 +21,6 @@ * Add serialization support from Julia; use `mlpack.serialize()` and `mlpack.deserialize()` to save and load from `IOBuffer`s. -======= - * Add adaptive max pooling and adaptive mean pooling layers (#2195). ->>>>>>> df2354a79... Finished new definition as wrapper and added tests ### mlpack 3.3.0 ###### 2020-04-07