mlpack
noisylinear_impl.hpp
Go to the documentation of this file.
1 
12 #ifndef MLPACK_METHODS_ANN_LAYER_NOISYLINEAR_IMPL_HPP
13 #define MLPACK_METHODS_ANN_LAYER_NOISYLINEAR_IMPL_HPP
14 
15 // In case it hasn't yet been included.
16 #include "noisylinear.hpp"
17 
18 namespace mlpack {
19 namespace ann {
20 
21 template<typename InputDataType, typename OutputDataType>
23  inSize(0),
24  outSize(0)
25 {
26  // Nothing to do here.
27 }
28 
29 template<typename InputDataType, typename OutputDataType>
31  const NoisyLinear& layer) :
32  inSize(layer.inSize),
33  outSize(layer.outSize),
34  weights(layer.weights)
35 {
36  Reset();
37 }
38 
39 template<typename InputDataType, typename OutputDataType>
41  const size_t inSize,
42  const size_t outSize) :
43  inSize(inSize),
44  outSize(outSize)
45 {
46  weights.set_size(WeightSize(), 1);
47  weightEpsilon.set_size(outSize, inSize);
48  biasEpsilon.set_size(outSize, 1);
49 }
50 
51 template<typename InputDataType, typename OutputDataType>
53  NoisyLinear&& layer) :
54  inSize(std::move(layer.inSize)),
55  outSize(std::move(layer.outSize)),
56  weights(std::move(layer.weights))
57 {
58  layer.inSize = 0;
59  layer.outSize = 0;
60  layer.weights = nullptr;
61  Reset();
62 }
63 
64 template<typename InputDataType, typename OutputDataType>
67 {
68  if (this != &layer)
69  {
70  inSize = layer.inSize;
71  outSize = layer.outSize;
72  weights = layer.weights;
73  Reset();
74  }
75  return *this;
76 }
77 
78 template<typename InputDataType, typename OutputDataType>
81 {
82  if (this != &layer)
83  {
84  inSize = std::move(layer.inSize);
85  layer.inSize = 0;
86  outSize = std::move(layer.outSize);
87  layer.outSize = 0;
88  weights = std::move(layer.weights);
89  layer.weights = nullptr;
90  Reset();
91  }
92  return *this;
93 }
94 
95 template<typename InputDataType, typename OutputDataType>
97 {
98  weightMu = arma::mat(weights.memptr(),
99  outSize, inSize, false, false);
100  biasMu = arma::mat(weights.memptr() + weightMu.n_elem,
101  outSize, 1, false, false);
102  weightSigma = arma::mat(weights.memptr() + weightMu.n_elem + biasMu.n_elem,
103  outSize, inSize, false, false);
104  biasSigma = arma::mat(weights.memptr() + weightMu.n_elem * 2 + biasMu.n_elem,
105  outSize, 1, false, false);
106  this->ResetNoise();
107 }
108 
109 template<typename InputDataType, typename OutputDataType>
111 {
112  arma::mat epsilonIn = arma::randn<arma::mat>(inSize, 1);
113  epsilonIn = arma::sign(epsilonIn) % arma::sqrt(arma::abs(epsilonIn));
114  arma::mat epsilonOut = arma::randn<arma::mat>(outSize, 1);
115  epsilonOut = arma::sign(epsilonOut) % arma::sqrt(arma::abs(epsilonOut));
116  weightEpsilon = epsilonOut * epsilonIn.t();
117  biasEpsilon = epsilonOut;
118 }
119 
120 template<typename InputDataType, typename OutputDataType>
122 {
123  const double muRange = 1 / std::sqrt(inSize);
124  weightMu.randu();
125  weightMu = muRange * (weightMu * 2 - 1);
126  biasMu.randu();
127  biasMu = muRange * (biasMu * 2 - 1);
128  weightSigma.fill(0.5 / std::sqrt(inSize));
129  biasSigma.fill(0.5 / std::sqrt(outSize));
130 }
131 
132 template<typename InputDataType, typename OutputDataType>
133 template<typename eT>
135  const arma::Mat<eT>& input, arma::Mat<eT>& output)
136 {
137  weight = weightMu + weightSigma % weightEpsilon;
138  bias = biasMu + biasSigma % biasEpsilon;
139  output = weight * input;
140  output.each_col() += bias;
141 }
142 
143 template<typename InputDataType, typename OutputDataType>
144 template<typename eT>
146  const arma::Mat<eT>& /* input */, const arma::Mat<eT>& gy, arma::Mat<eT>& g)
147 {
148  g = weight.t() * gy;
149 }
150 
151 template<typename InputDataType, typename OutputDataType>
152 template<typename eT>
154  const arma::Mat<eT>& input,
155  const arma::Mat<eT>& error,
156  arma::Mat<eT>& gradient)
157 {
158  // Locally stored to prevent multiplication twice.
159  arma::mat weightGrad = error * input.t();
160 
161  // Gradients for mu values.
162  gradient.rows(0, weight.n_elem - 1) = arma::vectorise(weightGrad);
163  gradient.rows(weight.n_elem, weight.n_elem + bias.n_elem - 1)
164  = arma::sum(error, 1);
165 
166  // Gradients for sigma values.
167  gradient.rows(weight.n_elem + bias.n_elem, gradient.n_elem - bias.n_elem - 1)
168  = arma::vectorise(weightGrad % weightEpsilon);
169  gradient.rows(gradient.n_elem - bias.n_elem, gradient.n_elem - 1)
170  = arma::sum(error, 1) % biasEpsilon;
171 }
172 
173 template<typename InputDataType, typename OutputDataType>
174 template<typename Archive>
176  Archive& ar, const uint32_t /* version */)
177 {
178  ar(CEREAL_NVP(inSize));
179  ar(CEREAL_NVP(outSize));
180 
181  // This is inefficient, but we have to allocate this memory so that
182  // WeightSetVisitor gets the right size.
183  if (cereal::is_loading<Archive>())
184  weights.set_size((outSize * inSize + outSize) * 2, 1);
185 }
186 
187 } // namespace ann
188 } // namespace mlpack
189 
190 #endif
OutputDataType const & Gradient() const
Get the gradient.
Definition: noisylinear.hpp:138
void Forward(const arma::Mat< eT > &input, arma::Mat< eT > &output)
Ordinary feed forward pass of a neural network, evaluating the function f(x) by propagating the activ...
Definition: noisylinear_impl.hpp:134
Linear algebra utility functions, generally performed on matrices or vectors.
Definition: cv.hpp:1
size_t WeightSize() const
Get size of weights.
Definition: noisylinear.hpp:152
Definition: pointer_wrapper.hpp:23
NoisyLinear & operator=(const NoisyLinear &layer)
Operator= copy constructor.
Definition: noisylinear_impl.hpp:66
void serialize(Archive &ar, const uint32_t)
Serialize the layer.
Definition: noisylinear_impl.hpp:175
Implementation of the NoisyLinear layer class.
Definition: layer_types.hpp:107
void Backward(const arma::Mat< eT > &, const arma::Mat< eT > &gy, arma::Mat< eT > &g)
Ordinary feed backward pass of a neural network, calculating the function f(x) by propagating x backw...
Definition: noisylinear_impl.hpp:145
NoisyLinear()
Create the NoisyLinear object.
Definition: noisylinear_impl.hpp:22