[mlpack-git] master: Replacement for the convolution connection class using the new network API. (e1977d2)

gitdub at big.cc.gt.atl.ga.us gitdub at big.cc.gt.atl.ga.us
Sat Aug 29 08:23:40 EDT 2015


Repository : https://github.com/mlpack/mlpack

On branch  : master
Link       : https://github.com/mlpack/mlpack/compare/ea45ace1ff744390a4c35183528eda881eda5c61...fd336238de224ed72fc23b84e1e2f02ae3c879d6

>---------------------------------------------------------------

commit e1977d2c93da0229acfb99788978774021a93951
Author: Marcus Edel <marcus.edel at fu-berlin.de>
Date:   Wed Aug 26 17:57:05 2015 +0200

    Replacement for the convolution connection class using the new network API.


>---------------------------------------------------------------

e1977d2c93da0229acfb99788978774021a93951
 src/mlpack/methods/ann/layer/conv_layer.hpp | 370 ++++++++++++++++++++++++++++
 1 file changed, 370 insertions(+)

diff --git a/src/mlpack/methods/ann/layer/conv_layer.hpp b/src/mlpack/methods/ann/layer/conv_layer.hpp
new file mode 100644
index 0000000..7fac606
--- /dev/null
+++ b/src/mlpack/methods/ann/layer/conv_layer.hpp
@@ -0,0 +1,370 @@
+/**
+ * @file conv_layer.hpp
+ * @author Marcus Edel
+ *
+ * Definition of the ConvLayer class.
+ */
+#ifndef __MLPACK_METHODS_ANN_LAYER_CONV_LAYER_HPP
+#define __MLPACK_METHODS_ANN_LAYER_CONV_LAYER_HPP
+
+#include <mlpack/core.hpp>
+#include <mlpack/methods/ann/layer/layer_traits.hpp>
+#include <mlpack/methods/ann/init_rules/nguyen_widrow_init.hpp>
+#include <mlpack/methods/ann/optimizer/rmsprop.hpp>
+#include <mlpack/methods/ann/convolution_rules/border_modes.hpp>
+#include <mlpack/methods/ann/convolution_rules/naive_convolution.hpp>
+
+namespace mlpack {
+namespace ann /** Artificial Neural Network. */ {
+
+/**
+ * Implementation of the ConvLayer class. The ConvLayer class represents a
+ * single layer of a neural network.
+ *
+ * @tparam OptimizerType Type of the optimizer used to update the weights.
+ * @tparam WeightInitRule Rule used to initialize the weight matrix.
+ * @tparam ForwardConvolutionRule Convolution to perform forward process.
+ * @tparam BackwardConvolutionRule Convolution to perform backward process.
+ * @tparam GradientConvolutionRule Convolution to calculate gradient.
+ * @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 <
+    template<typename, typename> class OptimizerType = mlpack::ann::RMSPROP,
+    class WeightInitRule = NguyenWidrowInitialization,
+    typename ForwardConvolutionRule = NaiveConvolution<ValidConvolution>,
+    typename BackwardConvolutionRule = NaiveConvolution<FullConvolution>,
+    typename GradientConvolutionRule = NaiveConvolution<ValidConvolution>,
+    typename InputDataType = arma::cube,
+    typename OutputDataType = arma::cube
+>
+class ConvLayer
+{
+ public:
+  /**
+   * Create the ConvLayer object using the specified number of input maps,
+   * output maps, filter size, stride and padding parameter.
+   *
+   * @param inMaps The number of input maps.
+   * @param outMaps The number of output maps.
+   * @param wfilter Width of the filter/kernel.
+   * @param wfilter Height of the filter/kernel.
+   * @param xStride Stride of filter application in the x direction.
+   * @param yStride Stride of filter application in the y direction.
+   * @param wPad Spatial padding width of the input.
+   * @param hPad Spatial padding height of the input.
+   * @param WeightInitRule The weight initialization rule used to initialize the
+   *        weight matrix.
+   */
+  ConvLayer(const size_t inMaps,
+            const size_t outMaps,
+            const size_t wfilter,
+            const size_t hfilter,
+            const size_t xStride = 1,
+            const size_t yStride = 1,
+            const size_t wPad = 0,
+            const size_t hPad = 0,
+            WeightInitRule weightInitRule = WeightInitRule()) :
+      wfilter(wfilter),
+      hfilter(hfilter),
+      inMaps(inMaps),
+      outMaps(outMaps),
+      xStride(xStride),
+      yStride(yStride),
+      wPad(wPad),
+      hPad(hPad),
+      optimizer(new OptimizerType<ConvLayer<OptimizerType,
+                                            WeightInitRule,
+                                            ForwardConvolutionRule,
+                                            BackwardConvolutionRule,
+                                            GradientConvolutionRule,
+                                            InputDataType,
+                                            OutputDataType>,
+                                            OutputDataType>(*this)),
+      ownsOptimizer(true)
+  {
+    weightInitRule.Initialize(weights, wfilter, hfilter, inMaps * outMaps);
+  }
+
+  /**
+   * Delete the convolution layer object and its optimizer.
+   */
+  ~ConvLayer()
+  {
+    if (ownsOptimizer)
+      delete optimizer;
+  }
+
+  /**
+   * 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::Cube<eT>& input, arma::Cube<eT>& output)
+  {
+    const size_t wConv = ConvOutSize(input.n_rows, wfilter, xStride, wPad);
+    const size_t hConv = ConvOutSize(input.n_cols, hfilter, yStride, hPad);
+
+    output = arma::Cube<eT>(wConv, hConv, outMaps);
+    for (size_t outMap = 0, outMapIdx = 0; outMap < outMaps; outMap++)
+    {
+      for (size_t inMap = 0; inMap < inMaps; inMap++, outMapIdx++)
+      {
+        arma::Cube<eT> inputSlices = input.slices(inMap, inMap);
+
+        arma::Cube<eT> convOutput;
+        ForwardConvolutionRule::Convolution(inputSlices,
+            weights.slice(inMap * outMaps +
+            outMap), convOutput);
+
+        output.slices(outMap, outMap) += convOutput;
+      }
+    }
+  }
+
+  /**
+   * Ordinary feed backward pass of a neural network, 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::Cube<eT>& input,
+                const arma::Cube<eT>& gy,
+                arma::Cube<eT>& g)
+  {
+    g = arma::zeros<arma::Cube<eT> >(input.n_rows,
+                                     input.n_cols,
+                                     input.n_slices);
+
+    for (size_t outMap = 0, outMapIdx = 0; outMap < inMaps; outMap++)
+    {
+      for (size_t inMap = 0; inMap < outMaps; inMap++, outMapIdx++)
+      {
+        arma::Cube<eT> errorSlices = gy.slices(inMap, inMap);
+
+        arma::Mat<eT> rotatedFilter;
+        Rotate180(weights.slice(outMap * outMaps + inMap), rotatedFilter);
+
+        arma::Cube<eT> output;
+        BackwardConvolutionRule::Convolution(errorSlices, rotatedFilter,
+            output);
+
+        g.slices(outMap, outMap) += output;
+      }
+    }
+  }
+
+  /*
+   * Calculate the gradient using the output delta and the input activation.
+   *
+   * @param d The calculated error.
+   * @param g The calculated gradient.
+   */
+  template<typename eT>
+  void Gradient(arma::Cube<eT>& d, arma::Cube<eT>& g)
+  {
+    g = arma::zeros<arma::Cube<eT> >(weights.n_rows, weights.n_cols,
+        weights.n_slices);
+
+    for (size_t outMap = 0; outMap < outMaps; outMap++)
+    {
+      for (size_t inMap = 0, s = outMap; inMap < inMaps; inMap++, s += outMaps)
+      {
+        arma::Cube<eT> inputSlices = inputParameter.slices(inMap, inMap);
+        arma::Cube<eT> deltaSlices = d.slices(outMap, outMap);
+
+        arma::Cube<eT> output;
+        GradientConvolutionRule::Convolution(inputSlices, deltaSlices, output);
+
+        for (size_t i = 0; i < output.n_slices; i++)
+          g.slice(s) += output.slice(i);
+      }
+    }
+  }
+
+  //! Get the optimizer.
+  OptimizerType<ConvLayer<OptimizerType,
+                          WeightInitRule,
+                          ForwardConvolutionRule,
+                          BackwardConvolutionRule,
+                          GradientConvolutionRule,
+                          InputDataType,
+                          OutputDataType>, OutputDataType>& Optimizer() const
+  {
+    return *optimizer;
+  }
+  //! Modify the optimizer.
+  OptimizerType<ConvLayer<OptimizerType,
+                          WeightInitRule,
+                          ForwardConvolutionRule,
+                          BackwardConvolutionRule,
+                          GradientConvolutionRule,
+                          InputDataType,
+                          OutputDataType>, OutputDataType>& Optimizer()
+  {
+    return *optimizer;
+  }
+
+  //! Get the weights.
+  OutputDataType& Weights() const { return weights; }
+  //! Modify the weights.
+  OutputDataType& Weights() { return weights; }
+
+  //! Get the input parameter.
+  InputDataType& InputParameter() const {return inputParameter; }
+  //! Modify the input parameter.
+  InputDataType& InputParameter() { return inputParameter; }
+
+  //! Get the output parameter.
+  OutputDataType& OutputParameter() const {return outputParameter; }
+  //! Modify the output parameter.
+  OutputDataType& OutputParameter() { return outputParameter; }
+
+  //! Get the delta.
+  OutputDataType& Delta() const {return delta; }
+  //! Modify the delta.
+  OutputDataType& Delta() { return delta; }
+
+  //! Get the gradient.
+  OutputDataType& Gradient() const {return gradient; }
+  //! Modify the gradient.
+  OutputDataType& Gradient() { return gradient; }
+
+ private:
+  /*
+   * Rotates a 3rd-order tesor counterclockwise by 180 degrees.
+   *
+   * @param input The input data to be rotated.
+   * @param output The rotated output.
+   */
+  template<typename eT>
+  void Rotate180(const arma::Cube<eT>& input, arma::Cube<eT>& output)
+  {
+    output = arma::Cube<eT>(input.n_rows, input.n_cols, input.n_slices);
+
+    // * left-right flip, up-down flip */
+    for (size_t s = 0; s < output.n_slices; s++)
+      output.slice(s) = arma::fliplr(arma::flipud(input.slice(s)));
+  }
+
+  /*
+   * Rotates a dense matrix counterclockwise by 180 degrees.
+   *
+   * @param input The input data to be rotated.
+   * @param output The rotated output.
+   */
+  template<typename eT>
+  void Rotate180(const arma::Mat<eT>& input, arma::Mat<eT>& output)
+  {
+    // * left-right flip, up-down flip */
+    output = arma::fliplr(arma::flipud(input));
+  }
+
+  /*
+   * Return the convolution output size.
+   *
+   * @param size The size of the input (row or column).
+   * @param k The size of the filter (width or height).
+   * @param s The stride size (x or y direction).
+   * @param p The size of the padding (width or height).
+   * @return The convolution output size.
+   */
+  size_t ConvOutSize(const size_t size,
+                     const size_t k,
+                     const size_t s,
+                     const size_t p)
+  {
+    return std::floor(size + p * 2 - k) / s + 1;
+  }
+
+  //! Locally-stored filter/kernel width.
+  const size_t wfilter;
+
+  //! Locally-stored filter/kernel height.
+  const size_t hfilter;
+
+  //! Locally-stored number of input maps.
+  const size_t inMaps;
+
+  //! Locally-stored number of output maps.
+  const size_t outMaps;
+
+  //! Locally-stored stride of the filter in x-direction.
+  const size_t xStride;
+
+  //! Locally-stored stride of the filter in y-direction.
+  const size_t yStride;
+
+  //! Locally-stored padding width.
+  const size_t wPad;
+
+  //! Locally-stored padding height.
+  const size_t hPad;
+
+  //! Locally-stored weight object.
+  OutputDataType weights;
+
+  //! Locally-stored delta object.
+  OutputDataType delta;
+
+  //! Locally-stored gradient object.
+  OutputDataType gradient;
+
+  //! Locally-stored input parameter object.
+  InputDataType inputParameter;
+
+  //! Locally-stored output parameter object.
+  OutputDataType outputParameter;
+
+  //! Locally-stored pointer to the optimzer object.
+  OptimizerType<ConvLayer<OptimizerType,
+                          WeightInitRule,
+                          ForwardConvolutionRule,
+                          BackwardConvolutionRule,
+                          GradientConvolutionRule,
+                          InputDataType,
+                          OutputDataType>, OutputDataType>* optimizer;
+
+  //! Parameter that indicates if the class owns a optimizer object.
+  bool ownsOptimizer;
+}; // class ConvLayer
+
+//! Layer traits for the convolution layer.
+template<
+    template<typename, typename> class OptimizerType,
+    typename WeightInitRule,
+    typename ForwardConvolutionRule,
+    typename BackwardConvolutionRule,
+    typename GradientConvolutionRule,
+    typename InputDataType,
+    typename OutputDataType
+>
+class LayerTraits<ConvLayer<OptimizerType,
+                            WeightInitRule,
+                            ForwardConvolutionRule,
+                            BackwardConvolutionRule,
+                            GradientConvolutionRule,
+                            InputDataType,
+                            OutputDataType> >
+{
+ public:
+  static const bool IsBinary = false;
+  static const bool IsOutputLayer = false;
+  static const bool IsBiasLayer = false;
+  static const bool IsLSTMLayer = false;
+  static const bool IsConnection = true;
+};
+
+}; // namespace ann
+}; // namespace mlpack
+
+#endif



More information about the mlpack-git mailing list