mlpack
sequential_impl.hpp
Go to the documentation of this file.
1 
13 #ifndef MLPACK_METHODS_ANN_LAYER_SEQUENTIAL_IMPL_HPP
14 #define MLPACK_METHODS_ANN_LAYER_SEQUENTIAL_IMPL_HPP
15 
16 // In case it hasn't yet been included.
17 #include "sequential.hpp"
18 
19 #include "../visitor/forward_visitor.hpp"
20 #include "../visitor/backward_visitor.hpp"
21 #include "../visitor/gradient_visitor.hpp"
22 #include "../visitor/set_input_height_visitor.hpp"
23 #include "../visitor/set_input_width_visitor.hpp"
24 #include "../visitor/input_shape_visitor.hpp"
25 
26 namespace mlpack {
27 namespace ann {
28 
29 template <typename InputDataType, typename OutputDataType, bool Residual,
30  typename... CustomLayers>
32 Sequential(const bool model) :
33  model(model), reset(false), width(0), height(0), ownsLayers(!model)
34 {
35  // Nothing to do here.
36 }
37 
38 template <typename InputDataType, typename OutputDataType, bool Residual,
39  typename... CustomLayers>
41 Sequential(const bool model, const bool ownsLayers) :
42  model(model), reset(false), width(0), height(0), ownsLayers(ownsLayers)
43 {
44  // Nothing to do here.
45 }
46 
47 template <typename InputDataType, typename OutputDataType, bool Residual,
48  typename... CustomLayers>
50 Sequential(const Sequential& layer) :
51  model(layer.model),
52  reset(layer.reset),
53  width(layer.width),
54  height(layer.height),
55  ownsLayers(layer.ownsLayers)
56 {
57  // Nothing to do here.
58 }
59 
60 template <typename InputDataType, typename OutputDataType, bool Residual,
61  typename... CustomLayers>
62 Sequential<InputDataType, OutputDataType, Residual, CustomLayers...>&
64 operator = (const Sequential& layer)
65 {
66  if (this != &layer)
67  {
68  model = layer.model;
69  reset = layer.reset;
70  width = layer.width;
71  height = layer.height;
72  ownsLayers = layer.ownsLayers;
73  parameters = layer.parameters;
74  network.clear();
75  // Build new layers according to source network.
76  for (size_t i = 0; i < layer.network.size(); ++i)
77  {
78  this->network.push_back(boost::apply_visitor(copyVisitor,
79  layer.network[i]));
80  }
81  }
82  return *this;
83 }
84 
85 
86 template <typename InputDataType, typename OutputDataType, bool Residual,
87  typename... CustomLayers>
89  InputDataType, OutputDataType, Residual, CustomLayers...>::~Sequential()
90 {
91  if (!model && ownsLayers)
92  {
93  for (LayerTypes<CustomLayers...>& layer : network)
94  boost::apply_visitor(deleteVisitor, layer);
95  }
96 }
97 
98 template<typename InputDataType, typename OutputDataType, bool Residual,
99  typename... CustomLayers>
101 InputShape() const
102 {
103  size_t inputShape = 0;
104 
105  for (size_t l = 0; l < network.size(); ++l)
106  {
107  if (inputShape == 0)
108  inputShape = boost::apply_visitor(InShapeVisitor(), network[l]);
109  else
110  break;
111  }
112 
113  return inputShape;
114 }
115 
116 template<typename InputDataType, typename OutputDataType, bool Residual,
117  typename... CustomLayers>
118 template<typename eT>
120 Forward(const arma::Mat<eT>& input, arma::Mat<eT>& output)
121 {
122  boost::apply_visitor(ForwardVisitor(input,
123  boost::apply_visitor(outputParameterVisitor, network.front())),
124  network.front());
125 
126  if (!reset)
127  {
128  if (boost::apply_visitor(outputWidthVisitor, network.front()) != 0)
129  {
130  width = boost::apply_visitor(outputWidthVisitor, network.front());
131  }
132 
133  if (boost::apply_visitor(outputHeightVisitor, network.front()) != 0)
134  {
135  height = boost::apply_visitor(outputHeightVisitor, network.front());
136  }
137  }
138 
139  for (size_t i = 1; i < network.size(); ++i)
140  {
141  if (!reset)
142  {
143  // Set the input width.
144  boost::apply_visitor(SetInputWidthVisitor(width), network[i]);
145 
146  // Set the input height.
147  boost::apply_visitor(SetInputHeightVisitor(height), network[i]);
148  }
149 
150  boost::apply_visitor(ForwardVisitor(boost::apply_visitor(
151  outputParameterVisitor, network[i - 1]),
152  boost::apply_visitor(outputParameterVisitor, network[i])),
153  network[i]);
154 
155  if (!reset)
156  {
157  // Get the output width.
158  if (boost::apply_visitor(outputWidthVisitor, network[i]) != 0)
159  {
160  width = boost::apply_visitor(outputWidthVisitor, network[i]);
161  }
162 
163  // Get the output height.
164  if (boost::apply_visitor(outputHeightVisitor, network[i]) != 0)
165  {
166  height = boost::apply_visitor(outputHeightVisitor, network[i]);
167  }
168  }
169  }
170 
171  if (!reset)
172  {
173  reset = true;
174  }
175 
176  output = boost::apply_visitor(outputParameterVisitor, network.back());
177 
178  if (Residual)
179  {
180  if (arma::size(output) != arma::size(input))
181  {
182  Log::Fatal << "The sizes of the output and input matrices of the Residual"
183  << " block should be equal. Please examine the network architecture."
184  << std::endl;
185  }
186  output += input;
187  }
188 }
189 
190 template<typename InputDataType, typename OutputDataType, bool Residual,
191  typename... CustomLayers>
192 template<typename eT>
193 void Sequential<
194  InputDataType, OutputDataType, Residual, CustomLayers...>::Backward(
195  const arma::Mat<eT>& /* input */,
196  const arma::Mat<eT>& gy,
197  arma::Mat<eT>& g)
198 {
199  boost::apply_visitor(BackwardVisitor(boost::apply_visitor(
200  outputParameterVisitor, network.back()), gy,
201  boost::apply_visitor(deltaVisitor, network.back())),
202  network.back());
203 
204  for (size_t i = 2; i < network.size() + 1; ++i)
205  {
206  boost::apply_visitor(BackwardVisitor(boost::apply_visitor(
207  outputParameterVisitor, network[network.size() - i]),
208  boost::apply_visitor(deltaVisitor, network[network.size() - i + 1]),
209  boost::apply_visitor(deltaVisitor, network[network.size() - i])),
210  network[network.size() - i]);
211  }
212 
213  g = boost::apply_visitor(deltaVisitor, network.front());
214 
215  if (Residual)
216  {
217  g += gy;
218  }
219 }
220 
221 template<typename InputDataType, typename OutputDataType, bool Residual,
222  typename... CustomLayers>
223 template<typename eT>
225 Gradient(const arma::Mat<eT>& input,
226  const arma::Mat<eT>& error,
227  arma::Mat<eT>& /* gradient */)
228 {
229  boost::apply_visitor(GradientVisitor(boost::apply_visitor(
230  outputParameterVisitor, network[network.size() - 2]), error),
231  network.back());
232 
233  for (size_t i = 2; i < network.size(); ++i)
234  {
235  boost::apply_visitor(GradientVisitor(boost::apply_visitor(
236  outputParameterVisitor, network[network.size() - i - 1]),
237  boost::apply_visitor(deltaVisitor, network[network.size() - i + 1])),
238  network[network.size() - i]);
239  }
240 
241  boost::apply_visitor(GradientVisitor(input,
242  boost::apply_visitor(deltaVisitor, network[1])), network.front());
243 }
244 
245 template<typename InputDataType, typename OutputDataType, bool Residual,
246  typename... CustomLayers>
247 template<typename Archive>
248 void Sequential<
249  InputDataType, OutputDataType, Residual, CustomLayers...>::serialize(
250  Archive& ar, const uint32_t /* version */)
251 {
252  // If loading, delete the old layers.
253  if (cereal::is_loading<Archive>())
254  {
255  for (LayerTypes<CustomLayers...>& layer : network)
256  {
257  boost::apply_visitor(deleteVisitor, layer);
258  }
259  }
260 
261  ar(CEREAL_NVP(model));
262  ar(CEREAL_VECTOR_VARIANT_POINTER(network));
263 
264  ar(CEREAL_NVP(ownsLayers));
265 }
266 
267 } // namespace ann
268 } // namespace mlpack
269 
270 #endif
~Sequential()
Destroy the Sequential object.
Definition: sequential_impl.hpp:89
SetInputHeightVisitor updates the input height parameter with the given input height.
Definition: set_input_height_visitor.hpp:27
BackwardVisitor executes the Backward() function given the input, error and delta parameter...
Definition: backward_visitor.hpp:28
static MLPACK_EXPORT util::PrefixedOutStream Fatal
Prints fatal messages prefixed with [FATAL], then terminates the program.
Definition: log.hpp:90
Linear algebra utility functions, generally performed on matrices or vectors.
Definition: cv.hpp:1
SetInputWidthVisitor updates the input width parameter with the given input width.
Definition: set_input_width_visitor.hpp:27
Sequential(const bool model=true)
Create the Sequential object using the specified parameters.
Definition: sequential_impl.hpp:32
ForwardVisitor executes the Forward() function given the input and output parameter.
Definition: forward_visitor.hpp:28
arma::mat const & Gradient() const
Get the gradient.
Definition: sequential.hpp:182
InShapeVisitor returns the input shape a Layer expects.
Definition: input_shape_visitor.hpp:29
Sequential & operator=(const Sequential &layer)
Copy assignment operator.
Definition: sequential_impl.hpp:64
SearchModeVisitor executes the Gradient() method of the given module using the input and delta parame...
Definition: gradient_visitor.hpp:28
void Backward(const arma::Mat< eT > &, const arma::Mat< eT > &gy, arma::Mat< eT > &g)
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.
Definition: sequential_impl.hpp:194
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: sequential_impl.hpp:120
Implementation of the Sequential class.
Definition: layer_types.hpp:145
void serialize(Archive &ar, const uint32_t)
Serialize the layer.
Definition: sequential_impl.hpp:249
#define CEREAL_VECTOR_VARIANT_POINTER(T)
Cereal does not support the serialization of raw pointer.
Definition: pointer_vector_variant_wrapper.hpp:92