Add adaptive poolin
Add adaptive poolin Resolve merge conflict Add empty line at eof
This commit is contained in:
+1
-1
@@ -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).
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 <mlpack/prereqs.hpp>
|
||||
|
||||
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<size_t, size_t> 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<typename eT>
|
||||
void Forward(const arma::Mat<eT>&& input, arma::Mat<eT>&& 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<typename eT>
|
||||
void Backward(const arma::Mat<eT>&& /* input */,
|
||||
arma::Mat<eT>&& gy,
|
||||
arma::Mat<eT>&& 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<typename Archive>
|
||||
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<typename eT>
|
||||
void PoolingOperation(const arma::Mat<eT>& input,
|
||||
arma::Mat<eT>& output,
|
||||
arma::Mat<eT>& 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<size_t> 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<typename eT>
|
||||
void Unpooling(const arma::Mat<eT>& error,
|
||||
arma::Mat<eT>& output,
|
||||
arma::Mat<eT>& 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<size_t> indices;
|
||||
|
||||
//! Locally-stored pooling strategy.
|
||||
MaxPoolingRule pooling;
|
||||
|
||||
//! Locally-stored indices column parameter.
|
||||
arma::Col<size_t> indicesCol;
|
||||
|
||||
//! Locally-stored pooling indicies.
|
||||
std::vector<arma::cube> poolingIndices;
|
||||
}; // class AdaptiveMaxPooling
|
||||
|
||||
} // namespace ann
|
||||
} // namespace mlpack
|
||||
|
||||
// Include implementation.
|
||||
#include "adaptive_max_pooling_impl.hpp"
|
||||
|
||||
#endif
|
||||
@@ -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<typename InputDataType, typename OutputDataType>
|
||||
AdaptiveMaxPooling<InputDataType, OutputDataType>::AdaptiveMaxPooling()
|
||||
{
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
template <typename InputDataType, typename OutputDataType>
|
||||
AdaptiveMaxPooling<InputDataType, OutputDataType>::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 <typename InputDataType, typename OutputDataType>
|
||||
AdaptiveMaxPooling<InputDataType, OutputDataType>::AdaptiveMaxPooling(
|
||||
const std::tuple<size_t, size_t> 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<typename InputDataType, typename OutputDataType>
|
||||
template<typename eT>
|
||||
void AdaptiveMaxPooling<InputDataType, OutputDataType>::Forward(
|
||||
const arma::Mat<eT>&& input, arma::Mat<eT>&& output)
|
||||
{
|
||||
IntializeAdaptivePadding();
|
||||
batchSize = input.n_cols;
|
||||
inSize = input.n_elem / (inputWidth * inputHeight);
|
||||
inputTemp = arma::cube(const_cast<arma::Mat<eT>&&>(input).memptr(),
|
||||
inputWidth, inputHeight, batchSize * inSize, false, false);
|
||||
outputTemp = arma::zeros<arma::Cube<eT> >(outputWidth, outputHeight,
|
||||
batchSize * inSize);
|
||||
|
||||
size_t elements = inputWidth * inputHeight;
|
||||
indicesCol = arma::linspace<arma::Col<size_t> >(0, (elements - 1),
|
||||
elements);
|
||||
indices = arma::Mat<size_t>(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<eT>(outputTemp.memptr(), outputTemp.n_elem / batchSize,
|
||||
batchSize);
|
||||
|
||||
outSize = batchSize * inSize;
|
||||
}
|
||||
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
template<typename eT>
|
||||
void AdaptiveMaxPooling<InputDataType, OutputDataType>::Backward(
|
||||
const arma::Mat<eT>&& /* input */,
|
||||
arma::Mat<eT>&& gy,
|
||||
arma::Mat<eT>&& g)
|
||||
{
|
||||
arma::cube mappedError = arma::cube(gy.memptr(), outputWidth,
|
||||
outputHeight, outSize, false, false);
|
||||
|
||||
gTemp = arma::zeros<arma::cube>(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<typename InputDataType, typename OutputDataType>
|
||||
template<typename Archive>
|
||||
void AdaptiveMaxPooling<InputDataType, OutputDataType>::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
|
||||
@@ -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 <mlpack/prereqs.hpp>
|
||||
|
||||
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<size_t, size_t> 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<typename eT>
|
||||
void Forward(const arma::Mat<eT>&& input, arma::Mat<eT>&& 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<typename eT>
|
||||
void Backward(const arma::Mat<eT>&& /* input */,
|
||||
arma::Mat<eT>&& gy,
|
||||
arma::Mat<eT>&& 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<typename Archive>
|
||||
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<typename eT>
|
||||
void Pooling(const arma::Mat<eT>& input, arma::Mat<eT>& 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<typename eT>
|
||||
void Unpooling(const arma::Mat<eT>& input,
|
||||
const arma::Mat<eT>& error,
|
||||
arma::Mat<eT>& output)
|
||||
{
|
||||
const size_t rStep = input.n_rows / error.n_rows;
|
||||
const size_t cStep = input.n_cols / error.n_cols;
|
||||
|
||||
arma::Mat<eT> 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<eT>& inputArea = input(arma::span(i, i + rStep - 1),
|
||||
arma::span(j, j + cStep - 1));
|
||||
|
||||
unpooledError = arma::Mat<eT>(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
|
||||
@@ -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<typename InputDataType, typename OutputDataType>
|
||||
AdaptiveMeanPooling<InputDataType, OutputDataType>::AdaptiveMeanPooling()
|
||||
{
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
template <typename InputDataType, typename OutputDataType>
|
||||
AdaptiveMeanPooling<InputDataType, OutputDataType>::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 <typename InputDataType, typename OutputDataType>
|
||||
AdaptiveMeanPooling<InputDataType, OutputDataType>::AdaptiveMeanPooling(
|
||||
const std::tuple<size_t, size_t> 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<typename InputDataType, typename OutputDataType>
|
||||
template<typename eT>
|
||||
void AdaptiveMeanPooling<InputDataType, OutputDataType>::Forward(
|
||||
const arma::Mat<eT>&& input, arma::Mat<eT>&& output)
|
||||
{
|
||||
IntializeAdaptivePadding();
|
||||
batchSize = input.n_cols;
|
||||
inSize = input.n_elem / (inputWidth * inputHeight);
|
||||
inputTemp = arma::cube(const_cast<arma::Mat<eT>&&>(input).memptr(),
|
||||
inputWidth, inputHeight, batchSize * inSize, false, false);
|
||||
outputTemp = arma::zeros<arma::Cube<eT> >(outputWidth, outputHeight,
|
||||
batchSize * inSize);
|
||||
for (size_t s = 0; s < inputTemp.n_slices; s++)
|
||||
Pooling(inputTemp.slice(s), outputTemp.slice(s));
|
||||
|
||||
output = arma::Mat<eT>(outputTemp.memptr(), outputTemp.n_elem / batchSize,
|
||||
batchSize);
|
||||
|
||||
outSize = batchSize * inSize;
|
||||
}
|
||||
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
template<typename eT>
|
||||
void AdaptiveMeanPooling<InputDataType, OutputDataType>::Backward(
|
||||
const arma::Mat<eT>&& /* input */,
|
||||
arma::Mat<eT>&& gy,
|
||||
arma::Mat<eT>&& g)
|
||||
{
|
||||
arma::cube mappedError = arma::cube(gy.memptr(), outputWidth,
|
||||
outputHeight, outSize, false, false);
|
||||
|
||||
gTemp = arma::zeros<arma::cube>(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<typename InputDataType, typename OutputDataType>
|
||||
template<typename Archive>
|
||||
void AdaptiveMeanPooling<InputDataType, OutputDataType>::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
|
||||
Reference in New Issue
Block a user