From 7dc424359ec8599b9580b6a5cc27164024d85bdf Mon Sep 17 00:00:00 2001 From: nishantkr18 Date: Sat, 23 May 2020 22:50:58 +0530 Subject: [PATCH] Added NoisyLayer layout --- src/mlpack/methods/ann/layer/CMakeLists.txt | 2 + src/mlpack/methods/ann/layer/layer.hpp | 1 + src/mlpack/methods/ann/layer/layer_types.hpp | 6 + src/mlpack/methods/ann/layer/noisylinear.hpp | 166 ++++++++++++++++++ .../methods/ann/layer/noisylinear_impl.hpp | 94 ++++++++++ src/mlpack/methods/ann/layer_names.hpp | 11 ++ .../q_networks/dueling_dqn.hpp | 2 +- 7 files changed, 281 insertions(+), 1 deletion(-) create mode 100644 src/mlpack/methods/ann/layer/noisylinear.hpp create mode 100644 src/mlpack/methods/ann/layer/noisylinear_impl.hpp diff --git a/src/mlpack/methods/ann/layer/CMakeLists.txt b/src/mlpack/methods/ann/layer/CMakeLists.txt index 78b77b2a09..c1cd11e897 100644 --- a/src/mlpack/methods/ann/layer/CMakeLists.txt +++ b/src/mlpack/methods/ann/layer/CMakeLists.txt @@ -75,6 +75,8 @@ set(SOURCES multiply_constant_impl.hpp multiply_merge.hpp multiply_merge_impl.hpp + noisylinear.hpp + noisylinear_impl.hpp parametric_relu.hpp parametric_relu_impl.hpp recurrent.hpp diff --git a/src/mlpack/methods/ann/layer/layer.hpp b/src/mlpack/methods/ann/layer/layer.hpp index 62090e324e..904eb64d9a 100644 --- a/src/mlpack/methods/ann/layer/layer.hpp +++ b/src/mlpack/methods/ann/layer/layer.hpp @@ -52,6 +52,7 @@ #include "minibatch_discrimination.hpp" #include "multiply_constant.hpp" #include "multiply_merge.hpp" +#include "noisylinear.hpp" #include "padding.hpp" #include "parametric_relu.hpp" #include "recurrent_attention.hpp" diff --git a/src/mlpack/methods/ann/layer/layer_types.hpp b/src/mlpack/methods/ann/layer/layer_types.hpp index 2dc90a324b..173872ff4e 100644 --- a/src/mlpack/methods/ann/layer/layer_types.hpp +++ b/src/mlpack/methods/ann/layer/layer_types.hpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -83,6 +84,10 @@ template class LinearNoBias; +template +class NoisyLinear; + template @@ -257,6 +262,7 @@ using LayerTypes = boost::variant< MultiplyConstant*, MultiplyMerge*, NegativeLogLikelihood*, + NoisyLinear*, Padding*, PReLU*, WeightNorm*, diff --git a/src/mlpack/methods/ann/layer/noisylinear.hpp b/src/mlpack/methods/ann/layer/noisylinear.hpp new file mode 100644 index 0000000000..2260b27dbe --- /dev/null +++ b/src/mlpack/methods/ann/layer/noisylinear.hpp @@ -0,0 +1,166 @@ +/** + * @file methods/ann/layer/noisylinear.hpp + * @author Nishant Kumar + * + * Definition of the NoisyLinear 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_NOISYLINEAR_HPP +#define MLPACK_METHODS_ANN_LAYER_NOISYLINEAR_HPP + +#include + +#include "layer_types.hpp" + +namespace mlpack { +namespace ann /** Artificial Neural Network. */ { + +/** + * Implementation of the NoisyLinear layer class. It represents a single + * layer of a neural network, with parametric noise added to its weights. + * + * @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 NoisyLinear +{ + public: + //! Create the NoisyLinear object. + NoisyLinear(); + + /** + * Create the NoisyLinear layer object using the specified number of units. + * + * @param inSize The number of input units. + * @param outSize The number of output units. + */ + NoisyLinear(const size_t inSize, + const size_t outSize); + + /* + * Reset the layer parameter. + */ + void Reset(); + + /** + * 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, calculating the function + * f(x) by propagating x backwards trough 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 */, + const arma::Mat& gy, + arma::Mat& g); + + /* + * Calculate the gradient using the output delta and the input activation. + * + * @param input The input parameter used for calculating the gradient. + * @param error The calculated error. + * @param gradient The calculated gradient. + */ + template + void Gradient(const arma::Mat& input, + const arma::Mat& error, + arma::Mat& gradient); + + //! Get the parameters. + OutputDataType const& Parameters() const { return weights; } + //! Modify the parameters. + OutputDataType& Parameters() { return weights; } + + //! Get the input parameter. + InputDataType const& InputParameter() const { return inputParameter; } + //! Modify the input parameter. + InputDataType& InputParameter() { return inputParameter; } + + //! 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 input size. + size_t InputSize() const { return inSize; } + + //! Get the output size. + size_t OutputSize() const { return outSize; } + + //! Get the gradient. + OutputDataType const& Gradient() const { return gradient; } + //! Modify the gradient. + OutputDataType& Gradient() { return gradient; } + + //! Modify the bias weights of the layer. + arma::mat& Bias() { return bias; } + + /** + * Serialize the layer + */ + template + void serialize(Archive& ar, const unsigned int /* version */); + + private: + //! Locally-stored number of input units. + size_t inSize; + + //! Locally-stored number of output units. + size_t outSize; + + //! Locally-stored weight object. + OutputDataType weights; + + //! Locally-stored weight parameters. + OutputDataType weight; + + //! Locally-stored bias term parameters. + OutputDataType bias; + + //! 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; +}; // class NoisyLinear + +} // namespace ann +} // namespace mlpack + +// Include implementation. +#include "noisylinear_impl.hpp" + +#endif diff --git a/src/mlpack/methods/ann/layer/noisylinear_impl.hpp b/src/mlpack/methods/ann/layer/noisylinear_impl.hpp new file mode 100644 index 0000000000..849f29278f --- /dev/null +++ b/src/mlpack/methods/ann/layer/noisylinear_impl.hpp @@ -0,0 +1,94 @@ +/** + * @file methods/ann/layer/noisylinear_impl.hpp + * @author Nishant Kumar + * + * Implementation of the NoisyLinear 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_NOISYLINEAR_IMPL_HPP +#define MLPACK_METHODS_ANN_LAYER_NOISYLINEAR_IMPL_HPP + +// In case it hasn't yet been included. +#include "noisylinear.hpp" + +namespace mlpack { +namespace ann /** Artificial Neural Network. */ { + +template +NoisyLinear::NoisyLinear() : + inSize(0), + outSize(0) +{ + // Nothing to do here. +} + +template +NoisyLinear::NoisyLinear( + const size_t inSize, + const size_t outSize) : + inSize(inSize), + outSize(outSize) +{ + weights.set_size(outSize * inSize + outSize, 1); +} + +template +void NoisyLinear::Reset() +{ + weight = arma::mat(weights.memptr(), outSize, inSize, false, false); + bias = arma::mat(weights.memptr() + weight.n_elem, + outSize, 1, false, false); +} + +template +template +void NoisyLinear::Forward( + const arma::Mat& input, arma::Mat& output) +{ + output = weight * input; + output.each_col() += bias; +} + +template +template +void NoisyLinear::Backward( + const arma::Mat& /* input */, const arma::Mat& gy, arma::Mat& g) +{ + g = weight.t() * gy; +} + +template +template +void NoisyLinear::Gradient( + const arma::Mat& input, + const arma::Mat& error, + arma::Mat& gradient) +{ + gradient.submat(0, 0, weight.n_elem - 1, 0) = arma::vectorise( + error * input.t()); + gradient.submat(weight.n_elem, 0, gradient.n_elem - 1, 0) = + arma::sum(error, 1); +} + +template +template +void NoisyLinear::serialize( + Archive& ar, const unsigned int /* version */) +{ + ar & BOOST_SERIALIZATION_NVP(inSize); + ar & BOOST_SERIALIZATION_NVP(outSize); + + // This is inefficient, but we have to allocate this memory so that + // WeightSetVisitor gets the right size. + if (Archive::is_loading::value) + weights.set_size(outSize * inSize + outSize, 1); +} + +} // namespace ann +} // namespace mlpack + +#endif diff --git a/src/mlpack/methods/ann/layer_names.hpp b/src/mlpack/methods/ann/layer_names.hpp index 5d4fe21450..be1b1f7fcb 100644 --- a/src/mlpack/methods/ann/layer_names.hpp +++ b/src/mlpack/methods/ann/layer_names.hpp @@ -173,6 +173,17 @@ class LayerNameVisitor : public boost::static_visitor return "linearnobias"; } + /** + * Return the name of the given layer of type NoisyLinear as a string. + * + * @param * Given layer of type NoisyLinear. + * @return The string representation of the layer. + */ + std::string LayerString(NoisyLinear<>* /*layer*/) const + { + return "noisylinear"; + } + /** * Return the name of the given layer of type MaxPooling as a string. * diff --git a/src/mlpack/methods/reinforcement_learning/q_networks/dueling_dqn.hpp b/src/mlpack/methods/reinforcement_learning/q_networks/dueling_dqn.hpp index 56a586c32d..93f4c68d01 100644 --- a/src/mlpack/methods/reinforcement_learning/q_networks/dueling_dqn.hpp +++ b/src/mlpack/methods/reinforcement_learning/q_networks/dueling_dqn.hpp @@ -118,7 +118,7 @@ class DuelingDQN // featureNetwork.Forward(state, output); // actionValue = advantage.each_row() + // (value - arma::mean(arma::mean(advantage))); - + // networkOutput = output; }