Add adaptive poolin

Add adaptive poolin

Resolve merge conflict

Add empty line at eof
This commit is contained in:
kartikdutt18
2020-05-02 00:23:23 +05:30
parent 5322aaafdf
commit b2c247f6d3
6 changed files with 801 additions and 1 deletions
+1 -1
View File
@@ -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