MachineIntelligenceCore:NeuralNets
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Friends Macros
MultiLayerNeuralNetwork.hpp
Go to the documentation of this file.
1 
23 #ifndef SRC_MLNN_MULTILAYERNEURALNETWORK_HPP_
24 #define SRC_MLNN_MULTILAYERNEURALNETWORK_HPP_
25 
26 #include <types/MatrixTypes.hpp>
28 #include <loss/LossTypes.hpp>
29 
30 #include <fstream>
31 // Include headers that implement a archive in simple text format
32 #include <boost/archive/text_iarchive.hpp>
33 #include <boost/archive/text_oarchive.hpp>
34 
35 // Forward declaration of class boost::serialization::access
36 namespace boost {
37 namespace serialization {
38 class access;
39 }//: serialization
40 }//: access
41 
42 
43 namespace mic {
44 namespace mlnn {
45 
46 using namespace activation_function;
47 using namespace cost_function;
48 using namespace fully_connected;
49 using namespace convolution;
50 using namespace regularisation;
51 
57 template <typename eT>
58 class MultiLayerNeuralNetwork {
59 public:
60 
65  MultiLayerNeuralNetwork(std::string name_ = "mlnn") :
66  name(name_),
67  connected(false) // Initially the network is not connected.
68  {
69 
70  }
71 
76 
82  template <typename LayerType>
83  void pushLayer( LayerType* layer_ptr_){
84  layers.push_back(std::shared_ptr <LayerType> (layer_ptr_));
85  connected = false;
86  }
87 
93  template <typename LayerType>
94  std::shared_ptr<LayerType> getLayer(size_t index_){
95  assert(index_ < layers.size());
96  // Cast the pointer to LayerType.
97  return std::dynamic_pointer_cast< LayerType >( layers[index_] );
98  }
99 
105  std::shared_ptr<Layer<eT> > getLayer(size_t index_){
106  assert(index_ < layers.size());
107  // Cast the pointer to LayerType.
108  return layers[index_];
109  }
110 
115  void popLayer(size_t number_of_layers_ = 1){
116  assert(number_of_layers_ <= layers.size());
117  //layers.erase(layers.back() - number_of_layers_, layers.back());
118  for (size_t i=0; i <number_of_layers_; i++)
119  layers.pop_back();
120  connected = false;
121  }
122 
123 
128  size_t layerInputsSize(size_t layer_number_ = -1) {
129  assert (layer_number_ < layers.size());
130  // Last layer.
131  if (layer_number_ < 0)
132  layer_number_ = layers.size() -1;
133  // Return input size.
134  return layers[layer_number_]->inputsSize();
135  }
136 
141  size_t lastLayerOutputsSize(size_t layer_number_ = -1) {
142  assert (layer_number_ < layers.size());
143  // Last layer.
144  if (layer_number_ < 0)
145  layer_number_ = layers.size() -1;
146  // Return input size.
147  return layers[layer_number_]->outputsSize();
148  }
149 
154  size_t lastLayerBatchSize(size_t layer_number_ = -1) {
155  assert (layer_number_ < layers.size());
156  // Last layer.
157  if (layer_number_ < 0)
158  layer_number_ = layers.size() -1;
159  // Return input size.
160  return layers[layer_number_]->batchSize();
161  }
162 
163 
168  template<typename omT>
169  void setOptimization () {
170  // Iterate through layers and set optimization function for each one.
171  for (size_t i = 0; i < layers.size(); i++)
172  layers[i]->template setOptimization<omT> ();
173  }
174 
175 
181  void update(eT alpha_, eT decay_ = 0.0f) {
182  // The updates are cumulated for a batch, reduce the alpha rate.
183  eT alpha_batch = alpha_/layers[0]->batch_size;
184 
185  for (size_t i = 0; i < layers.size(); i++) {
186  layers[i]->update(alpha_batch, decay_);
187  }//: for
188  }
189 
190 
194  void resetGrads() {
195  for (size_t i = 0; i < layers.size(); i++)
196  layers[i]->resetGrads();
197  }
198 
203  void resizeBatch(size_t batch_size_) {
204  // If current batch size is ok.
205  if ((size_t)(layers[0]->s['x'])->cols() == batch_size_)
206  return;
207 
208  // Else - resize.
209  for (size_t i = 0; i < layers.size(); i++) {
210  layers[i]->resizeBatch(batch_size_);
211  }//: for
212  }
213 
217  mic::types::MatrixPtr<eT> getPredictions() {
218  return layers.back()->s['y'];
219  }
220 
225  mic::types::MatrixPtr<eT> getPredictions(size_t layer_nr_) {
226  assert(layer_nr_ < layers.size());
227  return layers[layer_nr_]->s['y'];
228  }
229 
238  size_t countCorrectPredictions(mic::types::MatrixPtr<eT> targets_, mic::types::MatrixPtr<eT> predictions_) {
239 
240  // Get vectors of indices denoting classes (type of 1-ouf-of-k dencoding).
241  mic::types::Matrix<eT> predicted_classes = predictions_->colwiseReturnMaxIndices();
242  mic::types::Matrix<eT> target_classes = targets_->colwiseReturnMaxIndices();
243 
244  // Get direct pointers to data.
245  eT *p = predicted_classes.data();
246  eT *t = target_classes.data();
247 
248  size_t correct=0;
249  size_t i;
250  for(i=0; i< (size_t) predicted_classes.size(); i++) {
251  if (p[i] == t[i])
252  correct++;
253  }//: for
254 
255  return correct;
256  }
257 
258 
264  friend std::ostream& operator<<(std::ostream& os_, const MultiLayerNeuralNetwork& obj_) {
265  // Display dimensions.
266  os_ << "[" << obj_.name << "]:\n";
267  // Display layers one by one.
268  for (size_t i = 0; i < obj_.layers.size(); i++)
269  os_ << (*obj_.layers[i]) << std::endl;
270 
271  return os_;
272  }
273 
274 
279  bool save(std::string filename_)
280  {
281  try {
282  // Create an output archive
283  std::ofstream ofs(filename_);
284  boost::archive::text_oarchive ar(ofs);
285 
286  // Change batch size to 1 - fastening the save/load procedures.
287  //setBatchSize(1);
288 
289  // Write data
290  ar & (*this);
291  LOG(LINFO) << "Network " << name << " properly saved to file " << filename_;
292  LOG(LDEBUG) << "Saved network: \n" << (*this);
293  } catch(...) {
294  LOG(LERROR) << "Could not write neural network " << name << " to file " << filename_ << "!";
295  // Clear layers - just in case.
296  layers.clear();
297  return false;
298  }
299  return true;
300  }
301 
306  bool load(std::string filename_)
307  {
308  try {
309  // Create and input archive
310  std::ifstream ifs(filename_);
311  boost::archive::text_iarchive ar(ifs);
312  // Load data
313  ar & (*this);
314  LOG(LINFO) << "Network " << name << " properly loaded from file " << filename_;
315  LOG(LDEBUG) << "Loaded network: \n" << (*this);
316  } catch(...) {
317  LOG(LERROR) << "Could not load neural network from file " << filename_ << "!";
318  // Clear layers - just in case.
319  layers.clear();
320  return false;
321  }
322  return true;
323  }
324 
325 
326 
327 protected:
331  std::vector<std::shared_ptr <mic::mlnn::Layer<eT> > > layers;
332 
336  std::string name;
337 
339  bool connected;
340 
341 
342 private:
343  // Friend class - required for using boost serialization.
344  friend class boost::serialization::access;
345 
351  template<class Archive>
352  void save(Archive & ar, const unsigned int version) const {
353  // Serialize name.
354  ar & name;
355 
356  // Serialize number of layers.
357  size_t size = layers.size();
358  ar & size;
359 
360  // Serialize layers one by one.
361  for (size_t i = 0; i < layers.size(); i++) {
362  // Serialize type first - so we can use it in load.
363  ar & layers[i]->layer_type;
364 
365  // Serialize the layer.
366  ar & (*layers[i]);
367  }//: for
368 
369  }
370 
376  template<class Archive>
377  void load(Archive & ar, const unsigned int version) {
378  // Clear the layers vector - just in case.
379  layers.clear();
380  connected = false;
381 
382  // Deserialize name.
383  ar & name;
384 
385  // Deserialize the number of layers.
386  size_t size;
387  ar & size;
388 
389  // Serialize layers one by one.
390  for (size_t i = 0; i < size; i++) {
391  LayerTypes lt;
392  // Get layer type
393  ar & lt;
394 
395  std::shared_ptr<Layer<eT> > layer_ptr;
396  switch(lt) {
397  // activation_function
398  case(LayerTypes::ELU):
399  layer_ptr = std::make_shared<ELU<eT> >(ELU<eT>());
400  LOG(LDEBUG) << "ELU";
401  break;
402  case(LayerTypes::ReLU):
403  layer_ptr = std::make_shared<ReLU<eT> >(ReLU<eT>());
404  LOG(LDEBUG) << "ReLU";
405  break;
406  case(LayerTypes::Sigmoid):
407  layer_ptr = std::make_shared<Sigmoid<eT> >(Sigmoid<eT>());
408  LOG(LDEBUG) << "Sigmoid";
409  break;
410 
411  // convolution
413  layer_ptr = std::make_shared<Convolution<eT> >(Convolution<eT>());
414  LOG(LERROR) << "Convolution Layer serialization not implemented (some params are not serialized)!";
415  break;
416  case(LayerTypes::Cropping):
417  layer_ptr = std::make_shared<Cropping<eT> >(Cropping<eT>());
418  LOG(LERROR) << "Cropping Layer serialization not implemented (some params are not serialized)!";
419  break;
421  layer_ptr = std::make_shared<MaxPooling<eT> >(MaxPooling<eT>());
422  LOG(LERROR) << "MaxPooling Layer serialization not implemented (some params are not serialized)!";
423  break;
424  case(LayerTypes::Padding):
425  layer_ptr = std::make_shared<Padding<eT> >(Padding<eT>());
426  LOG(LERROR) << "Padding Layer serialization not implemented (some params are not serialized)!";
427  break;
428 
429  // cost_function
430  case(LayerTypes::Softmax):
431  layer_ptr = std::make_shared<Softmax<eT> >(Softmax<eT>());
432  LOG(LDEBUG) << "Softmax";
433  break;
434 
435  // fully_connected
436  case(LayerTypes::Linear):
437  //ar.template register_type<mic::mlnn::Linear>();
438  layer_ptr = std::make_shared<Linear<eT> >(Linear<eT>());
439  LOG(LDEBUG) << "Linear";
440  break;
442  layer_ptr = std::make_shared<SparseLinear<eT> >(SparseLinear<eT>());
443  LOG(LDEBUG) << "SparseLinear";
444  break;
446  layer_ptr = std::make_shared<HebbianLinear<eT> >(HebbianLinear<eT>());
447  LOG(LDEBUG) << "HebbianLinear";
448  break;
449 
451  layer_ptr = std::make_shared<BinaryCorrelator<eT> >(BinaryCorrelator<eT>());
452  LOG(LDEBUG) << "BinaryCorrelator";
453  break;
454 
455  // regularisation
456  case(LayerTypes::Dropout):
457  layer_ptr = std::make_shared<Dropout<eT> >(Dropout<eT>());
458  LOG(LERROR) << "Dropout Layer serialization not implemented (some params are not serialized)!";
459  break;
460 
461  default:
462  LOG(LERROR) << "Undefined Layer type detected during deserialization!";
463  }//: switch
464 
465  ar & (*layer_ptr);
466  layers.push_back(layer_ptr);
467  }//: for
468 
469  }
470 
471  // The serialization must be splited as load requires to allocate the memory.
472  BOOST_SERIALIZATION_SPLIT_MEMBER()
473 
474 };
475 
476 
477 } /* namespace mlnn */
478 } /* namespace mic */
479 
480 // Just in the case that something important will change in the MLNN class - set version.
481 BOOST_CLASS_VERSION(mic::mlnn::MultiLayerNeuralNetwork<float>, 2)
482 BOOST_CLASS_VERSION(mic::mlnn::MultiLayerNeuralNetwork<double>, 2)
483 
484 
485 #endif /* SRC_MLNN_MULTILAYERNEURALNETWORK_HPP_ */
Class representing a convolution layer, with "valid padding" and variable stride. ...
Definition: Convolution.hpp:41
size_t lastLayerOutputsSize(size_t layer_number_=-1)
bool connected
Flag denoting whether the layers are interconnected, thus no copying between inputs and outputs of th...
Class implementing the layer with Exponential Linear Unit (ELU). http://arxiv.org/pdf/1511.07289v5.pdf.
Definition: ELU.hpp:39
Layer performing max pooling.
Definition: MaxPooling.hpp:39
Class implementing a linear, fully connected layer.
Class implementing cropping operation - crops the size of image (matrix) by a margin of n pixels on e...
Definition: Cropping.hpp:38
void popLayer(size_t number_of_layers_=1)
std::vector< std::shared_ptr< mic::mlnn::Layer< eT > > > layers
std::shared_ptr< LayerType > getLayer(size_t index_)
Class implementing a linear, fully connected layer.
Droput layer - a layer used for the regularization of neural network by randomly dropping neurons dur...
Definition: Dropout.hpp:39
void update(eT alpha_, eT decay_=0.0f)
size_t countCorrectPredictions(mic::types::MatrixPtr< eT > targets_, mic::types::MatrixPtr< eT > predictions_)
Softmax activation function.
Definition: Softmax.hpp:38
Class representing a multi-layer neural network.
Definition: Layer.hpp:86
Class implementing a linear, fully connected layer.
Definition: Linear.hpp:42
mic::types::MatrixPtr< eT > getPredictions()
LayerTypes
Enumeration of possible layer types.
Definition: Layer.hpp:58
void load(Archive &ar, const unsigned int version)
MultiLayerNeuralNetwork(std::string name_="mlnn")
Class implementing a linear, fully connected layer with sparsity regulation.
Definition: Linear.hpp:34
friend std::ostream & operator<<(std::ostream &os_, const MultiLayerNeuralNetwork &obj_)
Class implementing padding operation - expanding the size of image (matrix) by a margin of n pixels o...
Definition: Padding.hpp:38
size_t lastLayerBatchSize(size_t layer_number_=-1)
std::shared_ptr< Layer< eT > > getLayer(size_t index_)
size_t layerInputsSize(size_t layer_number_=-1)
void save(Archive &ar, const unsigned int version) const
mic::types::MatrixPtr< eT > getPredictions(size_t layer_nr_)