OpenNN  2.2
Open Neural Networks Library
multilayer_perceptron.cpp
1 /****************************************************************************************************************/
2 /* */
3 /* OpenNN: Open Neural MultilayerPerceptrons Library */
4 /* www.artelnics.com/opennn */
5 /* */
6 /* M U L T I L A Y E R P E R C E P T R O N C L A S S */
7 /* */
8 /* Roberto Lopez */
9 /* Artelnics - Making intelligent use of data */
11 /* */
12 /****************************************************************************************************************/
13 
14 // OpenNN includes
15 
16 #include "multilayer_perceptron.h"
17 
18 namespace OpenNN
19 {
20 
21 // DEFAULT CONSTRUCTOR
22 
26 
28 {
29  set();
30 }
31 
32 
33 // LAYERS CONSTRUCTOR
34 
38 
40 {
41  set(new_layers);
42 }
43 
44 
45 // NETWORK ARCHITECTURE CONSTRUCTOR
46 
54 
56 {
57  set(new_architecture);
58 }
59 
60 
61 // ONE LAYER CONSTRUCTOR
62 
72 
73 MultilayerPerceptron::MultilayerPerceptron(const size_t& new_inputs_number, const size_t& new_neurons_number)
74 {
75  set(new_inputs_number, new_neurons_number);
76 }
77 
78 
79 // TWO LAYERS CONSTRUCTOR
80 
89 
90 MultilayerPerceptron::MultilayerPerceptron(const size_t& new_inputs_number, const size_t& new_hidden_neurons_number, const size_t& new_outputs_number)
91 {
92  set(new_inputs_number, new_hidden_neurons_number, new_outputs_number);
93 
94  set_default();
95 }
96 
97 
98 // COPY CONSTRUCTOR
99 
103 
105 {
106  set(other_multilayer_perceptron);
107 }
108 
109 
110 // DESTRUCTOR
111 
114 
116 {
117 }
118 
119 
120 // ASSIGNMENT OPERATOR
121 
125 
127 {
128  if(this != &other_multilayer_perceptron)
129  {
130  layers = other_multilayer_perceptron.layers;
131 
132  display = other_multilayer_perceptron.display;
133  }
134 
135  return(*this);
136 }
137 
138 
139 // EQUAL TO OPERATOR
140 
141 // bool operator == (const MultilayerPerceptron&) const method
142 
147 
148 bool MultilayerPerceptron::operator == (const MultilayerPerceptron& other_multilayer_perceptron) const
149 {
150  if(layers == other_multilayer_perceptron.layers
151  && display == other_multilayer_perceptron.display)
152  {
153  return(true);
154  }
155  else
156  {
157  return(false);
158  }
159 }
160 
161 
162 // METHODS
163 
164 // const Vector<PerceptronLayer>& get_layers(void) const method
165 
169 
171 {
172  return(layers);
173 }
174 
175 
176 // const PerceptronLayer& get_layer(const size_t&) const method
177 
180 
182 {
183  // Control sentence (if debug)
184 
185  #ifndef NDEBUG
186 
187  const size_t layers_number = get_layers_number();
188 
189  if(i >= layers_number)
190  {
191  std::ostringstream buffer;
192 
193  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
194  << "const PerceptronLayer get_layer(const size_t&) const method.\n"
195  << "Index of layer must be less than number of layers.\n";
196 
197  throw std::logic_error(buffer.str());
198  }
199 
200  #endif
201 
202  return(layers[i]);
203 }
204 
205 
206 // PerceptronLayer* get_layer_pointer(const size_t&) const method
207 
210 
212 {
213  // Control sentence (if debug)
214 
215  #ifndef NDEBUG
216 
217  const size_t layers_number = get_layers_number();
218 
219  if(i >= layers_number)
220  {
221  std::ostringstream buffer;
222 
223  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
224  << "PerceptronLayer* get_layer_pointer(const size_t&) const method.\n"
225  << "Index of layer must be less than number of layers.\n";
226 
227  throw std::logic_error(buffer.str());
228  }
229 
230  #endif
231 
232  return(&layers[i]);
233 }
234 
235 
236 // size_t count_perceptrons_number(void) const method
237 
240 
242 {
243  const Vector<size_t> layers_perceptrons_number = arrange_layers_perceptrons_numbers();
244 
245  return(layers_perceptrons_number.calculate_sum());
246 }
247 
248 
249 // Vector<size_t> count_cumulative_perceptrons_number(void) const method
250 
252 
254 {
255  const size_t layers_number = get_layers_number();
256 
257  Vector<size_t> cumulative_neurons_number(layers_number);
258 
259  if(layers_number != 0)
260  {
262 
263  cumulative_neurons_number[0] = layers_size[0];
264 
265  for(size_t i = 1; i < layers_number; i++)
266  {
267  cumulative_neurons_number[i] = cumulative_neurons_number[i-1] + layers_size[i];
268  }
269  }
270 
271  return(cumulative_neurons_number);
272 }
273 
274 
275 // Vector<size_t> arrange_layers_parameters_number(void) const method
276 
279 
281 {
282  const size_t layers_number = get_layers_number();
283 
284  Vector<size_t> layers_parameters_number(layers_number);
285 
286  for(size_t i = 0; i < layers_number; i++)
287  {
288  layers_parameters_number[i] = layers[i].count_parameters_number();
289  }
290 
291  return(layers_parameters_number);
292 }
293 
294 
295 // Vector<size_t> arrange_layers_cumulative_parameters_number(void) const method
296 
299 
301 {
302  const size_t layers_number = get_layers_number();
303 
304  Vector<size_t> layers_cumulative_parameters_number(layers_number);
305 
306  layers_cumulative_parameters_number[0] = layers[0].count_parameters_number();
307 
308  for(size_t i = 1; i < layers_number; i++)
309  {
310  layers_cumulative_parameters_number[i] = layers_cumulative_parameters_number[i-1] + layers[i].count_parameters_number();
311  }
312 
313  return(layers_cumulative_parameters_number);
314 }
315 
316 
317 // Vector< Vector<double> > arrange_layers_biases(void) const method
318 
323 
325 {
326  const size_t layers_number = get_layers_number();
327 
328  Vector< Vector<double> > layers_biases(layers_number);
329 
330  for(size_t i = 0; i < layers_number; i++)
331  {
332  layers_biases[i] = layers[i].arrange_biases();
333  }
334 
335  return(layers_biases);
336 }
337 
338 
339 // Vector< Matrix<double> > arrange_layers_synaptic_weights(void) const method
340 
346 
348 {
349  const size_t layers_number = get_layers_number();
350 
351  Vector< Matrix<double> > layers_synaptic_weights(layers_number);
352 
353  for(size_t i = 0; i < layers_number; i++)
354  {
355  layers_synaptic_weights[i] = layers[i].arrange_synaptic_weights();
356  }
357 
358  return(layers_synaptic_weights);
359 }
360 
361 
362 // Vector< Matrix<double> > get_layers_parameters(void) const method
363 
370 
372 {
373  const size_t layers_number = get_layers_number();
374 
375  Vector< Vector<double> > layers_parameters(layers_number);
376 
377  for(size_t i = 0; i < layers_number; i++)
378  {
379  layers_parameters[i] = layers[i].arrange_parameters();
380  }
381 
382  return(layers_parameters);
383 }
384 
385 
386 // size_t count_parameters_number(void) const method
387 
389 
391 {
392  const size_t layers_number = get_layers_number();
393 
394  size_t parameters_number = 0;
395 
396  for(size_t i = 0; i < layers_number; i++)
397  {
398  parameters_number += layers[i].count_parameters_number();
399  }
400 
401  return(parameters_number);
402 }
403 
404 
405 // Vector<double> arrange_parameters(void) const method
406 
408 
410 {
411  const size_t layers_number = get_layers_number();
412 
413  const size_t parameters_number = count_parameters_number();
414 
415  Vector<double> parameters(parameters_number);
416 
417  size_t position = 0;
418 
419  for(size_t i = 0; i < layers_number; i++)
420  {
421  const Vector<double> layer_parameters = layers[i].arrange_parameters();
422  const size_t layer_parameters_number = layer_parameters.size();
423 
424  parameters.tuck_in(position, layer_parameters);
425  position += layer_parameters_number;
426  }
427 
428  return(parameters);
429 }
430 
431 
432 // Vector<size_t> count_layers_parameters_numbers(void) const method
433 
437 
439 {
440  const size_t layers_number = get_layers_number();
441 
442  Vector<size_t> layers_parameters_numbers(layers_number);
443 
444  for(size_t i = 0; i < layers_number; i++)
445  {
446  layers_parameters_numbers[i] = layers[i].count_parameters_number();
447  }
448 
449  return(layers_parameters_numbers);
450 }
451 
452 
453 // size_t get_layer_index(const size_t&) const method
454 
457 
458 size_t MultilayerPerceptron::get_layer_index(const size_t& neuron_index) const
459 {
460  // Control sentence (if debug)
461 
462  #ifndef NDEBUG
463 
464  const size_t neurons_number = count_perceptrons_number();
465 
466  if(neuron_index >= neurons_number)
467  {
468  std::ostringstream buffer;
469 
470  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
471  << "int get_layer_index(const size_t&) const method.\n"
472  << "Index of neuron must be less than number of neurons.\n";
473 
474  throw std::logic_error(buffer.str());
475  }
476 
477  #endif
478 
479  const Vector<size_t> cumulative_neurons_number = count_cumulative_perceptrons_number();
480 
481  const size_t layer_index = cumulative_neurons_number.calculate_cumulative_index(neuron_index);
482 
483  return(layer_index);
484 }
485 
486 
487 // size_t get_perceptron_index(const size_t&, const size_t&) const method
488 
492 
493 size_t MultilayerPerceptron::get_perceptron_index(const size_t& layer_index, const size_t& perceptron_position) const
494 {
495  if(layer_index == 0)
496  {
497  return(perceptron_position);
498  }
499  else
500  {
501  const Vector<size_t> cumulative_neurons_number = count_cumulative_perceptrons_number();
502 
503  return(cumulative_neurons_number[layer_index-1] + perceptron_position);
504  }
505 }
506 
507 
508 // size_t get_layer_bias_index(const size_t&, const size_t&) const method
509 
513 
514 size_t MultilayerPerceptron::get_layer_bias_index(const size_t& layer_index, const size_t& perceptron_index) const
515 {
516  // Control sentence (if debug)
517 
518  #ifndef NDEBUG
519 
520  const size_t layers_number = get_layers_number();
521 
522  if(layer_index >= layers_number)
523  {
524  std::ostringstream buffer;
525 
526  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
527  << "size_t get_layer_bias_index(const size_t&, const size_t&) const method.\n"
528  << "Index of layer must be less than number of layers.\n";
529 
530  throw std::logic_error(buffer.str());
531  }
532 
533  const size_t layer_perceptrons_number = layers[layer_index].get_perceptrons_number();
534 
535  if(perceptron_index >= layer_perceptrons_number)
536  {
537  std::ostringstream buffer;
538 
539  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
540  << "size_t get_layer_bias_index(const size_t&, const size_t&) const method.\n"
541  << "Index of perceptron must be less than number of perceptrons in that layer.\n";
542 
543  throw std::logic_error(buffer.str());
544  }
545 
546  #endif
547 
548  size_t layer_bias_index = 0;
549 
550  // Previous layers
551 
552  for(size_t i = 0; i < layer_index; i++)
553  {
554  layer_bias_index += layers[i].count_parameters_number();
555  }
556 
557  // Previous layer neurons
558 
559  for(size_t j = 0; j < perceptron_index; j++)
560  {
561  layer_bias_index += layers[layer_index].get_perceptron(j).count_parameters_number();
562  }
563 
564  return(layer_bias_index);
565 }
566 
567 
568 // size_t get_layer_synaptic_weight_index(const size_t&, const size_t&, const size_t&) const method
569 
574 
576 (const size_t& layer_index, const size_t& perceptron_index, const size_t& input_index) const
577 {
578  // Control sentence (if debug)
579 
580  #ifndef NDEBUG
581 
582  const size_t layers_number = get_layers_number();
583 
584  if(layer_index >= layers_number)
585  {
586  std::ostringstream buffer;
587 
588  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
589  << "size_t get_layer_synaptic_weight_index(const size_t&, const size_t&, const size_t&) method.\n"
590  << "Index of layer must be less than number of layers.\n";
591 
592  throw std::logic_error(buffer.str());
593  }
594 
595  const size_t layer_perceptrons_number = layers[layer_index].get_perceptrons_number();
596 
597  if(perceptron_index >= layer_perceptrons_number)
598  {
599  std::ostringstream buffer;
600 
601  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
602  << "size_t get_layer_synaptic_weight_index(const size_t&, const size_t&, const size_t&) method.\n"
603  << "Index of perceptron must be less than number of perceptrons in layer.\n";
604 
605  throw std::logic_error(buffer.str());
606  }
607 
608  const size_t layer_inputs_number = layers[layer_index].get_inputs_number();
609 
610  if(input_index >= layer_inputs_number)
611  {
612  std::ostringstream buffer;
613 
614  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
615  << "size_t get_layer_synaptic_weight_index(const size_t&, const size_t&, const size_t&) method.\n"
616  << "Index of inputs must be less than number of inputs in perceptron.\n";
617 
618  throw std::logic_error(buffer.str());
619  }
620 
621  #endif
622 
623  size_t layer_synaptic_weight_index = 0;
624 
625  // Previous layers
626 
627  if(layer_index > 0)
628  {
629  for(size_t i = 0; i < layer_index-1; i++)
630  {
631  layer_synaptic_weight_index += layers[layer_index].count_parameters_number();
632  }
633  }
634 
635  // Previous layer neurons
636 
637  if(perceptron_index > 0)
638  {
639  for(size_t i = 0; i < perceptron_index-1; i++)
640  {
641  layer_synaptic_weight_index += layers[layer_index].get_perceptron(i).count_parameters_number();
642  }
643  }
644 
645  // Hidden neuron bias
646 
647  layer_synaptic_weight_index += 1;
648 
649  // Synaptic weight index
650 
651  layer_synaptic_weight_index += input_index;
652 
653  return(layer_synaptic_weight_index);
654 }
655 
656 
657 // Vector<size_t> arrange_parameter_indices(const size_t&) const method
658 
661 
663 {
664  // Control sentence (if debug)
665 
666  #ifndef NDEBUG
667 
668  const size_t parameters_number = count_parameters_number();
669 
670  if(parameter_index >= parameters_number)
671  {
672  std::ostringstream buffer;
673 
674  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
675  << "Vector<int> arrange_parameter_indices(const size_t&) const method.\n"
676  << "Index of neural parameter must be less than number of multilayer perceptron parameters.\n";
677 
678  throw std::logic_error(buffer.str());
679  }
680 
681  #endif
682 
683  return(arrange_parameters_indices().arrange_row(parameter_index));
684 }
685 
686 
687 // Matrix<size_t> arrange_parameters_indices(void) const method
688 
693 
695 {
696  size_t perceptron_parameters_number;
697 
698  const size_t layers_number = get_layers_number();
700 
701  const size_t parameters_number = count_parameters_number();
702 
703  Matrix<size_t> parameters_indices(parameters_number, 3);
704 
705  size_t parameter_index = 0;
706 
707  for(size_t i = 0; i < layers_number; i++)
708  {
709  for(size_t j = 0; j < layers_size[i]; j++)
710  {
711  perceptron_parameters_number = layers[i].get_perceptron(j).count_parameters_number();
712 
713  for(size_t k = 0; k < perceptron_parameters_number; k++)
714  {
715  parameters_indices(parameter_index,0) = i;
716  parameters_indices(parameter_index,1) = j;
717  parameters_indices(parameter_index,2) = k;
718  parameter_index++;
719  }
720  }
721  }
722 
723  return(parameters_indices);
724 }
725 
726 
727 // Vector<Perceptron::ActivationFunction> get_layers_activation_function(void) const method
728 
730 
732 {
733  const size_t layers_number = get_layers_number();
734 
735  Vector<Perceptron::ActivationFunction> layers_activation_function(layers_number);
736 
737  for(size_t i = 0; i < layers_number; i++)
738  {
739  layers_activation_function[i] = layers[i].get_activation_function();
740  }
741 
742  return(layers_activation_function);
743 }
744 
745 
746 // Vector<std::string> write_layers_activation_function(void) const method
747 
750 
752 {
753  const size_t layers_number = get_layers_number();
754 
755  Vector<std::string> layers_activation_function(layers_number);
756 
757  for(size_t i = 0; i < layers_number; i++)
758  {
759  layers_activation_function[i] = layers[i].write_activation_function();
760  }
761 
762  return(layers_activation_function);
763 }
764 
765 
766 // const bool& get_display(void) const method
767 
770 
771 const bool& MultilayerPerceptron::get_display(void) const
772 {
773  return(display);
774 }
775 
776 
777 // void set_default(void) method
778 
785 
787 {
788  // Multilayer perceptron architecture
789 
790  const size_t layers_number = get_layers_number();
791 
792  if(layers_number > 0)
793  {
794  for(size_t i = 0; i < layers_number-1; i++)
795  {
796  layers[i].set_activation_function(Perceptron::HyperbolicTangent);
797  }
798 
799  layers[layers_number-1].set_activation_function(Perceptron::Linear);
800  }
801 
802  // Display messages
803 
804  set_display(true);
805 }
806 
807 
808 // void set(void) method
809 
811 
813 {
814  layers.set();
815 }
816 
817 
818 // void set(const Vector<PerceptronLayer>&) method
819 
822 
824 {
825  layers = new_layers;
826 }
827 
828 
829 // void set(const Vector<size_t>&) method
830 
838 
839 void MultilayerPerceptron::set(const Vector<size_t>& new_architecture)
840 {
841  std::ostringstream buffer;
842 
843  const size_t new_architecture_size = new_architecture.size();
844 
845  if(new_architecture_size == 0)
846  {
847  set();
848  }
849  else if(new_architecture_size == 1)
850  {
851  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
852  << "void set_architecture(const Vector<size_t>&) method.\n"
853  << "Size of architecture cannot be one.\n";
854 
855  throw std::logic_error(buffer.str());
856  }
857  else
858  {
859  for(size_t i = 0; i < new_architecture_size; i++)
860  {
861  if(new_architecture[i] == 0)
862  {
863  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
864  << "void set_architecture(const Vector<size_t>&) method.\n"
865  << "Size " << i << " must be greater than zero.\n";
866 
867  throw std::logic_error(buffer.str());
868  }
869  }
870 
871  const size_t new_layers_number = new_architecture_size-1;
872  layers.set(new_layers_number);
873 
874  // First layer
875 
876  for(size_t i = 0; i < new_layers_number; i++)
877  {
878  layers[i].set(new_architecture[i], new_architecture[i+1]);
879  }
880 
881  // Activation
882 
883  for(size_t i = 0; i < new_layers_number-1; i++)
884  {
885  layers[i].set_activation_function(Perceptron::HyperbolicTangent);
886  }
887 
888  layers[new_layers_number-1].set_activation_function(Perceptron::Linear);
889  }
890 }
891 
892 
893 // void set(const size_t&, const size_t&) method
894 
898 
899 void MultilayerPerceptron::set(const size_t& new_inputs_number, const size_t& new_perceptrons_number)
900 {
901  // Control sentence (if debug)
902 
903  #ifndef NDEBUG
904 
905  std::ostringstream buffer;
906 
907  if(new_inputs_number == 0)
908  {
909  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
910  << "void set(const size_t&, const size_t&) method.\n"
911  << "Number of inputs cannot be zero.\n";
912 
913  throw std::logic_error(buffer.str());
914  }
915  else if(new_perceptrons_number == 0)
916  {
917  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
918  << "void set_architecture(const size_t&, const size_t&) method.\n"
919  << "Number of perceptrons cannot be zero.\n";
920 
921  throw std::logic_error(buffer.str());
922  }
923 
924  #endif
925 
926  layers.set(1);
927 
928  layers[0].set(new_inputs_number, new_perceptrons_number);
929 }
930 
931 
932 // void set(const size_t&, const size_t&, const size_t&) method
933 
938 
939 void MultilayerPerceptron::set(const size_t& new_inputs_number, const size_t& new_hidden_neurons_number, const size_t& new_outputs_number)
940 {
941  // Control sentence (if debug)
942 
943  #ifndef NDEBUG
944 
945  std::ostringstream buffer;
946 
947  if(new_inputs_number == 0)
948  {
949  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
950  << "void set(const size_t&, const size_t&, const size_t&) method.\n"
951  << "Number of inputs must be greater than zero.\n";
952 
953  throw std::logic_error(buffer.str());
954  }
955  else if(new_hidden_neurons_number == 0)
956  {
957  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
958  << "void set(const size_t&, const size_t&, const size_t&) method.\n"
959  << "Number of hidden neurons must be greater than zero.\n";
960 
961  throw std::logic_error(buffer.str());
962  }
963  else if(new_outputs_number == 0)
964  {
965  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
966  << "void set(const size_t&, const size_t&, const size_t&) method.\n"
967  << "Number of outputs must be greater than zero.\n";
968 
969  throw std::logic_error(buffer.str());
970  }
971 
972  #endif
973 
974  layers.set(2);
975 
976  layers[0].set(new_inputs_number, new_hidden_neurons_number);
977  layers[0].set_activation_function(Perceptron::HyperbolicTangent);
978 
979  layers[1].set(new_hidden_neurons_number, new_outputs_number);
980  layers[1].set_activation_function(Perceptron::Linear);
981 }
982 
983 
984 // void set(const MultilayerPerceptron&) method
985 
988 
989 void MultilayerPerceptron::set(const MultilayerPerceptron& other_multilayer_perceptron)
990 {
991  layers = other_multilayer_perceptron.layers;
992 
993  display = other_multilayer_perceptron.display;
994 }
995 
996 
997 // void set_inputs_number(const size_t&) method
998 
1001 
1002 void MultilayerPerceptron::set_inputs_number(const size_t& new_inputs_number)
1003 {
1004  if(is_empty())
1005  {
1006  std::ostringstream buffer;
1007 
1008  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
1009  << "void set_inputs_number(const size_t&) method.\n"
1010  << "Multilayer perceptron is empty.\n";
1011 
1012  throw std::logic_error(buffer.str());
1013  }
1014 
1015  layers[0].set_inputs_number(new_inputs_number);
1016 }
1017 
1018 
1019 // void set_layers_perceptrons_number(const Vector<size_t>&) method
1020 
1025 
1027 {
1028  const Vector<size_t> inputs_number(1, get_inputs_number());
1029 
1030  set(inputs_number.assemble(new_layers_size));
1031 }
1032 
1033 
1034 // void set_layer_perceptrons_number(const size_t&, const size_t&) method
1035 
1040 
1041 void MultilayerPerceptron::set_layer_perceptrons_number(const size_t& layer_index, const size_t& new_layer_perceptrons_number)
1042 {
1043  const size_t layer_inputs_number = layers[layer_index].get_inputs_number();
1044 
1045  layers[layer_index].set_perceptrons_number(new_layer_perceptrons_number);
1046 
1047  layers[layer_index].set_inputs_number(layer_inputs_number);
1048 
1049  const size_t layers_number = get_layers_number();
1050 
1051  if(layer_index < layers_number-1)
1052  {
1053  layers[layer_index+1].set_inputs_number(new_layer_perceptrons_number);
1054  }
1055 }
1056 
1057 
1058 // void set_layers(const Vector<PerceptronLayer>&) method
1059 
1062 
1064 {
1065  layers = new_layers;
1066 }
1067 
1068 
1069 // void set_layers_biases(const Vector< Vector<double> >&) method
1070 
1076 
1078 {
1079  const size_t layers_number = get_layers_number();
1080 
1081  // Control sentence (if debug)
1082 
1083  #ifndef NDEBUG
1084 
1085  const size_t size = new_layers_biases.size();
1086 
1087  if(size != layers_number)
1088  {
1089  std::ostringstream buffer;
1090 
1091  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
1092  << "void set_layers_biases(const Vector< Vector<double> >&) method.\n"
1093  << "Size (" << size << ") must be equal to number of layers (" << layers_number << ").\n";
1094 
1095  throw std::logic_error(buffer.str());
1096  }
1097 
1098  #endif
1099 
1100  const Vector<size_t> layers_size = arrange_layers_perceptrons_numbers();
1101 
1102  for(size_t i = 0; i < layers_number; i++)
1103  {
1104  layers[i].set_biases(new_layers_biases[i]);
1105  }
1106 }
1107 
1108 
1109 // void set_layers_synaptic_weights(const Vector< Matrix<double> >&) method
1110 
1117 
1119 {
1120  const size_t layers_number = get_layers_number();
1121 
1122  // Control sentence (if debug)
1123 
1124  #ifndef NDEBUG
1125 
1126  const size_t size = new_layers_synaptic_weights.size();
1127 
1128  if(size != layers_number)
1129  {
1130  std::ostringstream buffer;
1131 
1132  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
1133  << "void set_layers_synaptic_weights(const Vector< Matrix<double> >&) method.\n"
1134  << "Size must be equal to number of layers.\n";
1135 
1136  throw std::logic_error(buffer.str());
1137  }
1138 
1139  #endif
1140 
1141  for(size_t i = 0; i < layers_number; i++)
1142  {
1143  layers[i].set_synaptic_weights(new_layers_synaptic_weights[i]);
1144  }
1145 
1146 }
1147 
1148 
1149 // void set_layers_parameters(const Vector< Vector<double> >&) method
1150 
1156 
1158 {
1159  const size_t layers_number = get_layers_number();
1160 
1161  // Control sentence (if debug)
1162 
1163  #ifndef NDEBUG
1164 
1165  const size_t new_layers_parameters_size = new_layers_parameters.size();
1166 
1167  if(new_layers_parameters_size != layers_number)
1168  {
1169  std::ostringstream buffer;
1170 
1171  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
1172  << "void set_layers_parameters(const Vector< Vector<double> >&) method.\n"
1173  << "Size of layer parameters must be equal to number of layers.\n";
1174 
1175  throw std::logic_error(buffer.str());
1176  }
1177 
1178  #endif
1179 
1180  for(size_t i = 0; i < layers_number; i++)
1181  {
1182  layers[i].set_parameters(new_layers_parameters[i]);
1183  }
1184 }
1185 
1186 
1187 // void set_parameters(const Vector<double>&) method
1188 
1191 
1193 {
1194  // Control sentence (if debug)
1195 
1196  #ifndef NDEBUG
1197 
1198  const size_t size = new_parameters.size();
1199 
1200  const size_t parameters_number = count_parameters_number();
1201 
1202  if(size != parameters_number)
1203  {
1204  std::ostringstream buffer;
1205 
1206  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
1207  << "void set_parameters(const Vector<double>&) method.\n"
1208  << "Size (" << size << ") must be equal to number of biases and synaptic weights (" << parameters_number << ").\n";
1209 
1210  throw std::logic_error(buffer.str());
1211  }
1212 
1213  #endif
1214 
1215  const size_t layers_number = get_layers_number();
1216 
1217  size_t layer_parameters_number;
1218  Vector<double> layer_parameters;
1219 
1220  size_t position = 0;
1221 
1222  for(size_t i = 0; i < layers_number; i++)
1223  {
1224  layer_parameters_number = layers[i].count_parameters_number();
1225  layer_parameters = layers[i].arrange_parameters();
1226 
1227  layer_parameters = new_parameters.take_out(position, layer_parameters_number);
1228 
1229  layers[i].set_parameters(layer_parameters);
1230  position += layer_parameters_number;
1231  }
1232 }
1233 
1234 
1235 // void set_layers_activation_function(const Vector<Perceptron::ActivationFunction>&) method
1236 
1241 
1243 (const Vector<Perceptron::ActivationFunction>& new_layers_activation_function)
1244 {
1245  const size_t layers_number = get_layers_number();
1246 
1247  // Control sentence (if debug)
1248 
1249  #ifndef NDEBUG
1250 
1251  const size_t new_layers_activation_function_size = new_layers_activation_function.size();
1252 
1253  if(new_layers_activation_function_size != layers_number)
1254  {
1255  std::ostringstream buffer;
1256 
1257  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
1258  << "void set_layers_activation_function(const Vector<Perceptron::ActivationFunction>&) method.\n"
1259  << "Size of activation function of layers must be equal to number of layers.\n";
1260 
1261  throw std::logic_error(buffer.str());
1262  }
1263 
1264  #endif
1265 
1266  for(size_t i = 0; i < layers_number; i++)
1267  {
1268  layers[i].set_activation_function(new_layers_activation_function[i]);
1269  }
1270 }
1271 
1272 
1273 // void set_layer_activation_function(const size_t&, const Perceptron::ActivationFunction&) method
1274 
1278 
1280 (const size_t& i, const Perceptron::ActivationFunction& new_layer_activation_function)
1281 {
1282  // Control sentence (if debug)
1283 
1284  #ifndef NDEBUG
1285 
1286  const size_t layers_number = get_layers_number();
1287 
1288  if(i >= layers_number)
1289  {
1290  std::ostringstream buffer;
1291 
1292  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
1293  << "void set_layer_activation_function(const size_t&, const Perceptron::ActivationFunction&) method.\n"
1294  << "Index of layer is equal or greater than number of layers.\n";
1295 
1296  throw std::logic_error(buffer.str());
1297  }
1298 
1299  #endif
1300 
1301  layers[i].set_activation_function(new_layer_activation_function);
1302 }
1303 
1304 
1305 // void set_layers_activation_function(const Vector<std::string>&) method
1306 
1310 
1312 {
1313  const size_t layers_number = get_layers_number();
1314 
1315  // Control sentence (if debug)
1316 
1317  #ifndef NDEBUG
1318 
1319  const size_t size = new_layers_activation_function.size();
1320 
1321  if(size != layers_number)
1322  {
1323  std::ostringstream buffer;
1324 
1325  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
1326  << "void set_layer_activation_function(const Vector<std::string>&) method.\n"
1327  << "Size of layers activation function is not equal to number of layers.\n";
1328 
1329  throw std::logic_error(buffer.str());
1330  }
1331 
1332  #endif
1333 
1334 
1335  for(size_t i = 0; i < layers_number; i++)
1336  {
1337  layers[i].set_activation_function(new_layers_activation_function[i]);
1338  }
1339 }
1340 
1341 
1342 // void set_display(const bool&) method
1343 
1348 
1349 void MultilayerPerceptron::set_display(const bool& new_display)
1350 {
1351  display = new_display;
1352 }
1353 
1354 
1355 // bool is_empty(void) const method
1356 
1358 
1360 {
1361  if(layers.empty())
1362  {
1363  return(true);
1364  }
1365  else
1366  {
1367  return(false);
1368  }
1369 }
1370 
1371 
1372 // void grow_input(void) method
1373 
1375 
1377 {
1378  const size_t layers_number = get_layers_number();
1379 
1380  if(layers_number > 0)
1381  {
1382 // layers[0].grow_input();
1383  }
1384 }
1385 
1386 
1387 // void grow_layer(const size_t&, const size_t&) method
1388 
1392 
1393 void MultilayerPerceptron::grow_layer(const size_t& layer_index, const size_t& perceptrons_number)
1394 {
1395  #ifndef NDEBUG
1396 
1397  if(layer_index >= (layers.size()-1))
1398  {
1399  std::ostringstream buffer;
1400 
1401  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
1402  << "void grow_layer(const size_t&, const size_t&) method.\n"
1403  << "Index of layer is equal or greater than number of layers-1.\n";
1404 
1405  throw std::logic_error(buffer.str());
1406  }
1407 
1408  if(perceptrons_number == 0)
1409  {
1410  std::ostringstream buffer;
1411 
1412  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
1413  << "void grow_layer(const size_t&, const size_t&) method.\n"
1414  << "Number of perceptrons must be greater than 0.\n";
1415 
1416  throw std::logic_error(buffer.str());
1417  }
1418 
1419  #endif
1420 
1421  for (size_t i = 0; i < perceptrons_number; i++)
1422  {
1423  layers[layer_index].grow_perceptrons(1);
1424  layers[layer_index+1].grow_inputs(1);
1425  }
1426 }
1427 
1428 
1429 // void prune_input(const size_t&) method
1430 
1433 
1434 void MultilayerPerceptron::prune_input(const size_t& index)
1435 {
1436  // Control sentence (if debug)
1437 
1438  #ifndef NDEBUG
1439 
1440  const size_t inputs_number = get_inputs_number();
1441 
1442  if(index >= inputs_number)
1443  {
1444  std::ostringstream buffer;
1445 
1446  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
1447  << "void prune_input(const size_t&) method.\n"
1448  << "Index of input is equal or greater than number of inputs.\n";
1449 
1450  throw std::logic_error(buffer.str());
1451  }
1452 
1453  #endif
1454 
1455  const size_t layers_number = get_layers_number();
1456 
1457  if(layers_number > 0)
1458  {
1459  layers[0].prune_input(index);
1460  }
1461 }
1462 
1463 
1464 // void prune_output(const size_t&) method
1465 
1468 
1469 void MultilayerPerceptron::prune_output(const size_t& index)
1470 {
1471  // Control sentence (if debug)
1472 
1473  #ifndef NDEBUG
1474 
1475  const size_t outputs_number = get_outputs_number();
1476 
1477  if(index >= outputs_number)
1478  {
1479  std::ostringstream buffer;
1480 
1481  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
1482  << "void prune_output(const size_t&) method.\n"
1483  << "Index of output is equal or greater than number of outputs.\n";
1484 
1485  throw std::logic_error(buffer.str());
1486  }
1487 
1488  #endif
1489 
1490  const size_t layers_number = get_layers_number();
1491 
1492  if(layers_number > 0)
1493  {
1494  layers[layers_number-1].prune_perceptron(index);
1495  }
1496 }
1497 
1498 
1499 // void prune_layer(const size_t&, const size_t&) method
1500 
1504 
1505 void MultilayerPerceptron::prune_layer(const size_t& layer_index, const size_t& perceptron_index)
1506 {
1507  #ifndef NDEBUG
1508 
1509  if(layer_index >= (layers.size()-1))
1510  {
1511  std::ostringstream buffer;
1512 
1513  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
1514  << "void prune_layer(const size_t&, const size_t&) method.\n"
1515  << "Index of layer is equal or greater than number of layers-1.\n";
1516 
1517  throw std::logic_error(buffer.str());
1518  }
1519 
1520  if(perceptron_index >= layers[layer_index].get_perceptrons_number())
1521  {
1522  std::ostringstream buffer;
1523 
1524  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
1525  << "void prune_layer(const size_t&, const size_t&) method.\n"
1526  << "Index of perceptron is equal or greater than number of perceptrons in the layer.\n";
1527 
1528  throw std::logic_error(buffer.str());
1529  }
1530 
1531  #endif
1532 
1533  layers[layer_index].prune_perceptron(perceptron_index);
1534  layers[layer_index+1].prune_input(perceptron_index);
1535 }
1536 
1537 
1538 // void initialize_random(void) method
1539 
1543 
1545 {
1546  const size_t architecture_size = rand()%10 + 2;
1547 
1548  Vector<size_t> architecture(architecture_size);
1549 
1550  for(size_t i = 0; i < architecture_size; i++)
1551  {
1552  architecture[i] = rand()%10 + 1;
1553  }
1554 
1555  set(architecture);
1556 
1557  const size_t layers_number = get_layers_number();
1558 
1559  // Layers activation function
1560 
1561  for(size_t i = 0; i < layers_number; i++)
1562  {
1563  switch(rand()%5)
1564  {
1565  case 0:
1566  {
1567  layers[i].set_activation_function(Perceptron::Logistic);
1568  }
1569  break;
1570 
1571  case 1:
1572  {
1573  layers[i].set_activation_function(Perceptron::HyperbolicTangent);
1574  }
1575  break;
1576 
1577  case 2:
1578  {
1579  layers[i].set_activation_function(Perceptron::Threshold);
1580  }
1581  break;
1582 
1583  case 3:
1584  {
1585  layers[i].set_activation_function(Perceptron::SymmetricThreshold);
1586  }
1587  break;
1588 
1589  case 4:
1590  {
1591  layers[i].set_activation_function(Perceptron::Linear);
1592  }
1593  break;
1594 
1595  default:
1596  {
1597  std::ostringstream buffer;
1598 
1599  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
1600  << "void initialize_random(void) method.\n"
1601  << "Unknown layer activation function.\n";
1602 
1603  throw std::logic_error(buffer.str());
1604  }
1605  break;
1606  }
1607  }
1608 
1609  // Display messages
1610 
1611  set_display(true);
1612 }
1613 
1614 
1615 // void initialize_biases(const double&) method
1616 
1619 
1621 {
1622  const size_t layers_number = get_layers_number();
1623 
1624  for(size_t i = 0; i < layers_number; i++)
1625  {
1626  layers[i].initialize_biases(value);
1627  }
1628 }
1629 
1630 
1631 // void initialize_synaptic_weights(const double&) const method
1632 
1635 
1637 {
1638  const size_t layers_number = get_layers_number();
1639  const Vector<size_t> layers_size = arrange_layers_perceptrons_numbers();
1640 
1641  for(size_t i = 0; i < layers_number; i++)
1642  {
1643  layers[i].initialize_synaptic_weights(value);
1644  }
1645 }
1646 
1647 
1648 // void initialize_parameters(const double&) method
1649 
1652 
1654 {
1655  const size_t parameters_number = count_parameters_number();
1656 
1657  const Vector<double> parameters(parameters_number, value);
1658 
1659  set_parameters(parameters);
1660 }
1661 
1662 
1663 // void randomize_parameters_uniform(void) method
1664 
1667 
1669 {
1670  const size_t parameters_number = count_parameters_number();
1671 
1672  Vector<double> parameters(parameters_number);
1673 
1674  parameters.randomize_uniform();
1675 
1676  set_parameters(parameters);
1677 }
1678 
1679 
1680 // void randomize_parameters_uniform(const double&, const double&) method
1681 
1686 
1687 void MultilayerPerceptron::randomize_parameters_uniform(const double& minimum, const double& maximum)
1688 {
1689  const size_t parameters_number = count_parameters_number();
1690 
1691  Vector<double> parameters(parameters_number);
1692 
1693  parameters.randomize_uniform(minimum, maximum);
1694 
1695  set_parameters(parameters);
1696 }
1697 
1698 
1699 // void randomize_parameters_uniform(const Vector<double>&, const Vector<double>&) method
1700 
1705 
1707 {
1708  const size_t parameters_number = count_parameters_number();
1709 
1710  Vector<double> parameters(parameters_number);
1711 
1712  parameters.randomize_uniform(minimum, maximum);
1713 
1714  set_parameters(parameters);
1715 }
1716 
1717 
1718 // void initializeparameters_uniform(const Vector< Vector<double> >&) method
1719 
1726 
1728 {
1729  const size_t parameters_number = count_parameters_number();
1730 
1731  Vector<double> parameters(parameters_number);
1732 
1733  parameters.randomize_uniform(minimum_maximum[0], minimum_maximum[1]);
1734 
1735  set_parameters(parameters);
1736 }
1737 
1738 
1739 // void randomize_parameters_normal(void) method
1740 
1743 
1745 {
1746  const size_t parameters_number = count_parameters_number();
1747 
1748  Vector<double> parameters(parameters_number);
1749 
1750  parameters.randomize_normal();
1751 
1752  set_parameters(parameters);
1753 }
1754 
1755 
1756 // void randomize_parameters_normal(const double&, const double&) method
1757 
1762 
1763 void MultilayerPerceptron::randomize_parameters_normal(const double& mean, const double& standard_deviation)
1764 {
1765  const size_t parameters_number = count_parameters_number();
1766 
1767  Vector<double> parameters(parameters_number);
1768 
1769  parameters.randomize_normal(mean, standard_deviation);
1770 
1771  set_parameters(parameters);
1772 }
1773 
1774 
1775 // void randomize_parameters_normal(const Vector<double>&, const Vector<double>&) method
1776 
1781 
1783 {
1784  const size_t parameters_number = count_parameters_number();
1785 
1786  Vector<double> parameters(parameters_number);
1787 
1788  parameters.randomize_normal(mean, standard_deviation);
1789 
1790  set_parameters(parameters);
1791 }
1792 
1793 
1794 // void randomize_parameters_normal(const Vector< Vector<double> >&) method
1795 
1802 
1804 {
1805  const size_t parameters_number = count_parameters_number();
1806 
1807  Vector<double> parameters(parameters_number);
1808 
1809  parameters.randomize_normal(mean_standard_deviation[0], mean_standard_deviation[1]);
1810 
1811  set_parameters(parameters);
1812 }
1813 
1814 
1815 // void initialize_parameters(void) method
1816 
1818 
1820 {
1822 }
1823 
1824 
1825 // void perturbate_parameters(const double&) method
1826 
1829 
1830 void MultilayerPerceptron::perturbate_parameters(const double& perturbation)
1831 {
1832  #ifndef NDEBUG
1833 
1834  if(perturbation < 0)
1835  {
1836  std::ostringstream buffer;
1837 
1838  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
1839  << "void perturbate_parameters(const double&) method.\n"
1840  << "Perturbation must be equal or greater than 0.\n";
1841 
1842  throw std::logic_error(buffer.str());
1843  }
1844 
1845  #endif
1846 
1847  Vector<double> parameters = arrange_parameters();
1848 
1849  Vector<double> parameters_perturbation(parameters);
1850 
1851  parameters_perturbation.randomize_uniform(-perturbation,perturbation);
1852 
1853  parameters = parameters + parameters_perturbation;
1854 
1855  set_parameters(parameters);
1856 }
1857 
1858 
1859 // double calculate_parameters_norm(void) const const method
1860 
1862 
1864 {
1865  const Vector<double> parameters = arrange_parameters();
1866 
1867  const double parameters_norm = parameters.calculate_norm();
1868 
1869  return(parameters_norm);
1870 }
1871 
1872 
1873 // Vector<double> calculate_outputs(const Vector<double>&) const method
1874 
1878 
1880 {
1881  // Control sentence (if debug)
1882 
1883  #ifndef NDEBUG
1884 
1885  const size_t size = inputs.size();
1886 
1887  const size_t inputs_number = get_inputs_number();
1888 
1889  if(size != inputs_number)
1890  {
1891  std::ostringstream buffer;
1892 
1893  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
1894  << "Vector<double> calculate_outputs(const Vector<double>&) const method.\n"
1895  << "Size of inputs (" << size <<") must be equal to number of inputs (" << inputs_number << ").\n";
1896 
1897  throw std::logic_error(buffer.str());
1898  }
1899 
1900  #endif
1901 
1902  const size_t layers_number = get_layers_number();
1903 
1904  Vector<double> outputs;
1905 
1906  if(layers_number == 0)
1907  {
1908  return(outputs);
1909  }
1910  else
1911  {
1912  outputs = layers[0].calculate_outputs(inputs);
1913 
1914  for(size_t i = 1; i < layers_number; i++)
1915  {
1916  outputs = layers[i].calculate_outputs(outputs);
1917  }
1918  }
1919 
1920  return(outputs);
1921 }
1922 
1923 
1924 // Matrix<double> calculate_Jacobian(const Vector<double>&) const method
1925 
1929 
1931 {
1932  #ifndef NDEBUG
1933 
1934  const size_t size = inputs.size();
1935 
1936  const size_t inputs_number = get_inputs_number();
1937 
1938  if(size != inputs_number)
1939  {
1940  std::ostringstream buffer;
1941 
1942  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
1943  << "Matrix<double> calculate_Jacobian(const Vector<double>&) const method.\n"
1944  << "Size must be equal to number of inputs.\n";
1945 
1946  throw std::logic_error(buffer.str());
1947  }
1948 
1949  #endif
1950 
1951  const size_t layers_number = get_layers_number();
1952 
1953  if(layers_number == 0)
1954  {
1955  Matrix<double> Jacobian;
1956 
1957  return(Jacobian);
1958  }
1959  else
1960  {
1961  const Vector< Matrix<double> > layers_Jacobian = calculate_layers_Jacobian(inputs);
1962 
1963  Matrix<double> Jacobian = layers_Jacobian[layers_number-1];
1964 
1965  for(int i = (int)layers_number-2; i > -1; i--)
1966  {
1967  Jacobian = Jacobian.dot(layers_Jacobian[i]);
1968  }
1969 
1970  return(Jacobian);
1971  }
1972 }
1973 
1974 
1975 // Vector< Matrix<double> > calculate_Hessian_form(const Vector<double>&) const
1976 
1980 
1982 {
1983  #ifndef NDEBUG
1984 
1985  const size_t size = inputs.size();
1986 
1987  const size_t inputs_number = get_inputs_number();
1988 
1989  if(size != inputs_number)
1990  {
1991  std::ostringstream buffer;
1992 
1993  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
1994  << "Vector< Matrix<double> > calculate_Hessian_form(const Vector<double>&) const method.\n"
1995  << "Size must be equal to number of inputs.\n";
1996 
1997  throw std::logic_error(buffer.str());
1998  }
1999 
2000  #endif
2001 
2002  const size_t layers_number = get_layers_number();
2003  const Vector<size_t> layers_size = arrange_layers_perceptrons_numbers();
2004  const size_t outputs_number = get_outputs_number();
2005 
2006  // Calculate forward propagation of outputs, Jacobian and Hessian form
2007 
2008  const Vector< Matrix<double> > layers_Jacobian = calculate_layers_Jacobian(inputs);
2009 
2010  const Vector< Vector< Matrix<double> > > layers_Hessian_form = calculate_layers_Hessian_form(inputs);
2011 
2012  // Calculate multilayer_perceptron_pointer Hessian form
2013 
2014  Vector< Matrix<double> > Hessian_form = layers_Hessian_form[layers_number-1];
2015  Matrix<double> Jacobian = layers_Jacobian[layers_number-1];
2016 
2017  for(size_t layer_index = layers_number-2; layer_index != 0; layer_index--)
2018  {
2019  for(size_t output_index = 0; output_index < outputs_number; output_index++)
2020  {
2021  Hessian_form[output_index] = (layers_Jacobian[layer_index].calculate_transpose()).dot(Hessian_form[output_index]).dot(layers_Jacobian[layer_index]);
2022 
2023  for(size_t neuron_index = 0; neuron_index < layers_size[layer_index]; neuron_index++)
2024  {
2025  Hessian_form[output_index] += layers_Hessian_form[layer_index][neuron_index]*Jacobian(output_index,neuron_index);
2026  }
2027  }
2028 
2029  Jacobian = Jacobian.dot(layers_Jacobian[layer_index]);
2030  }
2031 
2032 // Matrix<double> hidden_layer_Jacobian = layers_Jacobian[0];
2033 // Matrix<double> output_layer_Jacobian = layers_Jacobian[1];
2034 
2035 // const Vector< Matrix<double> > hidden_layer_Hessian_form = layers_Hessian_form[0];
2036 // const Vector< Matrix<double> > output_layer_Hessian_form = layers_Hessian_form[1];
2037 
2038 // const Vector< Matrix<double> > Hessian_form(outputs_number);
2039 
2040 // for(size_t output_index = 0; output_index < outputs_number; output_index++)
2041 // {
2042 // Hessian_form[output_index] = (hidden_layer_Jacobian.calculate_transpose()).dot(output_layer_Hessian_form[output_index]).dot(hidden_layer_Jacobian);
2043 
2044 // for(size_t neuron_index = 0; neuron_index < layers_size[0]; neuron_index++)
2045 // {
2046 // Hessian_form[output_index] += hidden_layer_Hessian_form[neuron_index]*output_layer_Jacobian[output_index][neuron_index];
2047 // }
2048 // }
2049 
2050  return(Hessian_form);
2051 }
2052 
2053 
2054 // Vector<double> calculate_layer_combination_combination(const size_t&, const Vector<double>&) const method
2055 
2059 
2060 Vector<double> MultilayerPerceptron::calculate_layer_combination_combination(const size_t& layer_index, const Vector<double>& previous_layer_combination) const
2061 {
2062  // Control sentence (if debug)
2063 
2064  #ifndef NDEBUG
2065 
2066  const size_t layers_number = get_layers_number();
2067 
2068  if(layer_index == 0)
2069  {
2070  std::ostringstream buffer;
2071 
2072  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
2073  << "Matrix<double> calculate_layer_combination_combination(const size_t&, const Vector<double>&) const.\n"
2074  << "Index of layer must be greater than zero.\n";
2075 
2076  throw std::logic_error(buffer.str());
2077  }
2078  else if(layer_index >= layers_number)
2079  {
2080  std::ostringstream buffer;
2081 
2082  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
2083  << "Matrix<double> calculate_layer_combination_combination(const size_t&, const Vector<double>&) const.\n"
2084  << "Index of layer must be less than numnber of layers.\n";
2085 
2086  throw std::logic_error(buffer.str());
2087  }
2088 
2089  const size_t size = previous_layer_combination.size();
2090  const size_t previous_layer_perceptrons_number = layers[layer_index-1].get_perceptrons_number();
2091 
2092  if(size != previous_layer_perceptrons_number)
2093  {
2094  std::ostringstream buffer;
2095 
2096  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
2097  << "Matrix<double> calculate_layer_combination_combination(const size_t&, const Vector<double>&) const.\n"
2098  << "Size must be equal to size of previous layer.\n";
2099 
2100  throw std::logic_error(buffer.str());
2101  }
2102 
2103  #endif
2104 
2105  // Calculate combination to layer
2106 
2107  const Vector<double> previous_layer_activation = layers[layer_index-1].calculate_activations(previous_layer_combination);
2108 
2109  const Vector<double> layer_combination_combination = layers[layer_index].calculate_combinations(previous_layer_activation);
2110 
2111  return(layer_combination_combination);
2112 }
2113 
2114 
2115 // Matrix<double> calculate_layer_combination_combination_Jacobian(const size_t&, const Vector<double>&) const method
2116 
2122 
2123 Matrix<double> MultilayerPerceptron::calculate_layer_combination_combination_Jacobian(const size_t& layer_index, const Vector<double>& previous_layer_activation_derivative) const
2124 {
2125  const size_t previous_layer_perceptrons_number = layers[layer_index-1].get_perceptrons_number();
2126 
2127  // Control sentence (if debug)
2128 
2129  #ifndef NDEBUG
2130 
2131  const size_t layers_number = get_layers_number();
2132 
2133  if(layer_index == 0)
2134  {
2135  std::ostringstream buffer;
2136 
2137  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
2138  << "Matrix<double> calculate_layer_combination_combination_Jacobian(const size_t&, const Vector<double>&) const.\n"
2139  << "Index of layer must be greater than zero.\n";
2140 
2141  throw std::logic_error(buffer.str());
2142  }
2143  else if(layer_index >= layers_number)
2144  {
2145  std::ostringstream buffer;
2146 
2147  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
2148  << "Matrix<double> calculate_layer_combination_combination_Jacobian(const size_t&, const Vector<double>&) const.\n"
2149  << "Index of layer must be less than numnber of layers.\n";
2150 
2151  throw std::logic_error(buffer.str());
2152  }
2153 
2154  const size_t size = previous_layer_activation_derivative.size();
2155 
2156  if(size != previous_layer_perceptrons_number)
2157  {
2158  std::ostringstream buffer;
2159 
2160  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
2161  << "Matrix<double> calculate_layer_combination_combination_Jacobian(const size_t&, const Vector<double>&).\n"
2162  << "Size of activation derivative must be equal to size of previous layer.\n";
2163 
2164  throw std::logic_error(buffer.str());
2165  }
2166 
2167  #endif
2168 
2169  const Matrix<double> layer_synaptic_weights = layers[layer_index].arrange_synaptic_weights();
2170 
2171  Matrix<double> previous_layer_activation_Jacobian(previous_layer_perceptrons_number, previous_layer_perceptrons_number, 0.0);
2172  previous_layer_activation_Jacobian.set_diagonal(previous_layer_activation_derivative);
2173 
2174  return(layer_synaptic_weights.dot(previous_layer_activation_Jacobian));
2175 }
2176 
2177 
2178 // Vector<double> calculate_interlayer_combination_combination(const size_t&, const size_t&, const Vector<double>&) const method
2179 
2184 
2185 Vector<double> MultilayerPerceptron::calculate_interlayer_combination_combination(const size_t& domain_layer_index, const size_t& image_layer_index, const Vector<double>& domain_layer_combination) const
2186 {
2187  if(domain_layer_index > image_layer_index)
2188  {
2189  std::ostringstream buffer;
2190 
2191  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
2192  << "Vector<double> calculate_interlayer_combination_combination(const size_t&, const size_t&, const Vector<double>&) const method.\n"
2193  << "Index of domain layer must be less or equal than index of image layer.\n";
2194 
2195  throw std::logic_error(buffer.str());
2196  }
2197 
2198  if(domain_layer_index == image_layer_index)
2199  {
2200  return(domain_layer_combination);
2201  }
2202  else
2203  {
2204  Vector<double> interlayer_combination_combination(domain_layer_combination);
2205 
2206  for(size_t i = domain_layer_index+1; i <= image_layer_index; i++)
2207  {
2208  interlayer_combination_combination = calculate_layer_combination_combination(i, interlayer_combination_combination);
2209  }
2210 
2211  return(interlayer_combination_combination);
2212  }
2213 }
2214 
2215 
2216 // Matrix<double> calculate_interlayer_combination_combination_Jacobian(const size_t&, const size_t&, const Vector<double>&) const method
2217 
2223 
2224 Matrix<double> MultilayerPerceptron::calculate_interlayer_combination_combination_Jacobian(const size_t& domain_layer_index, const size_t& image_layer_index, const Vector<double>& domain_layer_combination) const
2225 {
2226  Matrix<double> interlayer_combination_combination_Jacobian;
2227 
2228  if(domain_layer_index < image_layer_index)
2229  {
2230  const size_t size = image_layer_index-domain_layer_index;
2231 
2232  Vector< Vector<double> > layers_combination_combination(size);
2233  Vector< Matrix<double> > layers_combination_combination_Jacobian(size);
2234 
2235  layers_combination_combination[0] = calculate_layer_combination_combination(domain_layer_index+1, domain_layer_combination);
2236  layers_combination_combination_Jacobian[0] = calculate_layer_combination_combination_Jacobian(domain_layer_index+1, layers[domain_layer_index].calculate_activations_derivatives(domain_layer_combination));
2237 
2238  for(size_t i = 1; i < size; i++)
2239  {
2240  layers_combination_combination[i] = calculate_layer_combination_combination(domain_layer_index+i+1, layers_combination_combination[i-1]);
2241 
2242  layers_combination_combination_Jacobian[i] = calculate_layer_combination_combination_Jacobian(domain_layer_index+i+1, layers_combination_combination[i-1]);
2243  }
2244 
2245  interlayer_combination_combination_Jacobian = layers_combination_combination_Jacobian[size-1];
2246 
2247  for(int i = (int)size-2; i > -1; i--)
2248  {
2249  interlayer_combination_combination_Jacobian = interlayer_combination_combination_Jacobian.dot(layers_combination_combination_Jacobian[i]);
2250  }
2251  }
2252  else if(domain_layer_index == image_layer_index)
2253  {
2254  const size_t image_layer_perceptrons_number = layers[image_layer_index].get_perceptrons_number();
2255 
2256  interlayer_combination_combination_Jacobian.set_identity(image_layer_perceptrons_number);
2257  }
2258  else
2259  {
2260  const size_t image_layer_perceptrons_number = layers[image_layer_index].get_perceptrons_number();
2261  const size_t domain_layer_perceptrons_number = layers[domain_layer_index].get_perceptrons_number();
2262 
2263  interlayer_combination_combination_Jacobian.set(image_layer_perceptrons_number, domain_layer_perceptrons_number, 0.0);
2264  }
2265 
2266  return(interlayer_combination_combination_Jacobian);
2267 }
2268 
2269 
2270 // Vector<double> calculate_output_layer_combination(const size_t&, const Vector<double>&) const method
2271 
2275 
2276 Vector<double> MultilayerPerceptron::calculate_output_layer_combination(const size_t& layer_index, const Vector<double>& layer_combinations) const
2277 {
2278  // Control sentence (if debug)
2279 
2280  #ifndef NDEBUG
2281 
2282  const size_t size = layer_combinations.size();
2283 
2284  const size_t layer_perceptrons_number = layers[layer_index].get_perceptrons_number();
2285 
2286  if(size != layer_perceptrons_number)
2287  {
2288  std::ostringstream buffer;
2289 
2290  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
2291  << "Vector<double> calculate_output_layer_combination(const size_t&, const Vector<double>&) const method.\n"
2292  << "Size must be equal to layer size.\n";
2293 
2294  throw std::logic_error(buffer.str());
2295  }
2296 
2297  #endif
2298 
2299  const size_t layers_number = get_layers_number();
2300 
2301  Vector<double> outputs = layers[layer_index].calculate_activations(layer_combinations);
2302 
2303  if(layer_index < layers_number)
2304  {
2305  for(size_t i = layer_index+1; i < layers_number; i++)
2306  {
2307  outputs = layers[i].calculate_outputs(outputs);
2308  }
2309  }
2310 
2311  return(outputs);
2312 }
2313 
2314 
2315 // Vector< Matrix<double> > calculate_output_layers_delta(const Vector< Vector<double> >&, const Vector<double>&) method
2316 
2320 
2322 {
2323  // Control sentence (if debug)
2324 
2325  const size_t layers_number = get_layers_number();
2326  const Vector<size_t> layers_size = arrange_layers_perceptrons_numbers();
2327 
2328  // Control sentence (if debug)
2329 
2330  #ifndef NDEBUG
2331 
2332  // Forward propagation activation derivative size
2333 
2334  const size_t layers_activation_derivative_size = layers_activation_derivative.size();
2335 
2336  if(layers_activation_derivative_size != layers_number)
2337  {
2338  std::ostringstream buffer;
2339 
2340  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
2341  << "Vector< Vector<double> > calculate_output_layers_delta(const Vector< Vector<double> >&) method.\n"
2342  << "Size of forward propagation activation derivative vector must be equal to number of layers.\n";
2343 
2344  throw std::logic_error(buffer.str());
2345  }
2346 
2347  #endif
2348 
2349  Vector< Matrix<double> > output_layers_delta(layers_number);
2350 
2351  if(layers_number > 0)
2352  {
2353  // Output layer
2354 
2355  output_layers_delta[layers_number-1] = layers[layers_number-1].arrange_activations_Jacobian(layers_activation_derivative[layers_number-1]);
2356 
2357  // Rest of layers
2358 
2359  for(int i = (int)layers_number-2; i >= 0; i--)
2360  {
2361  output_layers_delta[i] = output_layers_delta[i+1].dot(layers[i+1].arrange_synaptic_weights()).dot(layers[i].arrange_activations_Jacobian(layers_activation_derivative[i]));
2362  }
2363  }
2364 
2365  return(output_layers_delta);
2366 }
2367 
2368 
2369 // Matrix< Vector< Matrix<double> > > calculate_output_interlayers_Delta(void) method
2370 
2375 
2377 (const Vector< Vector< Vector<double> > >& second_order_forward_propagation,
2378  const Matrix< Matrix<double> >& interlayers_combination_combination_Jacobian,
2379  const Vector< Matrix<double> >& output_layers_delta) const
2380 {
2381  const size_t layers_number = get_layers_number();
2382  const Vector<size_t> layers_size = arrange_layers_perceptrons_numbers();
2383  const size_t outputs_number = get_outputs_number();
2384 
2385  // Control sentence (if debug)
2386 
2387  #ifndef NDEBUG
2388 
2389  std::ostringstream buffer;
2390 
2391  // Second order forward propagation
2392 
2393  const size_t second_order_forward_propagation_size = second_order_forward_propagation.size();
2394 
2395  if(second_order_forward_propagation_size != 3)
2396  {
2397  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
2398  << "Matrix< Vector< Matrix<double> > > calculate_output_interlayers_delta() method.\n"
2399  << "Size of second order forward propagation must be three.\n";
2400 
2401  throw std::logic_error(buffer.str());
2402  }
2403 
2404  // Interlayers combination-combination Jacobian
2405 
2406  const size_t interlayers_combination_combination_Jacobian_rows_number = interlayers_combination_combination_Jacobian.get_rows_number();
2407 
2408  if(interlayers_combination_combination_Jacobian_rows_number != layers_number)
2409  {
2410  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
2411  << "Matrix< Vector< Matrix<double> > > calculate_output_interlayers_delta() method.\n"
2412  << "Number of rows of interlayers combination-combination Jacobian must be equal to number of layers.\n";
2413 
2414  throw std::logic_error(buffer.str());
2415  }
2416 
2417  // Multilayer perceptron outputs layers delta
2418 
2419  const size_t output_layers_delta_size = output_layers_delta.size();
2420 
2421  if(output_layers_delta_size != layers_number)
2422  {
2423  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
2424  << "Matrix< Vector< Matrix<double> > > calculate_output_interlayers_delta() method.\n"
2425  << "Size of multilayer perceptron outputs layers delta must be equal to number of layers.\n";
2426 
2427  throw std::logic_error(buffer.str());
2428  }
2429 
2430  #endif
2431 
2432  const Vector< Matrix<double> > layers_synaptic_weights = arrange_layers_synaptic_weights();
2433 
2434  const Vector< Vector<double> >& layers_activation_derivative = second_order_forward_propagation[1];
2435  const Vector< Vector<double> >& layers_activation_second_derivative = second_order_forward_propagation[2];
2436 
2437  // The Delta form consists of a square matrix of size the number of layers
2438 
2439  Matrix< Vector< Matrix<double> > > output_interlayers_Delta(layers_number, layers_number);
2440 
2441  // Each Delta element is a vector of size the number of outputs
2442 
2443  for(size_t i = 0; i < layers_number; i++)
2444  {
2445  for(size_t j = 0; j < layers_number; j++)
2446  {
2447  output_interlayers_Delta(i,j).set(outputs_number);
2448  }
2449  }
2450 
2451  // The subelements are matrices with rows and columns numbers the sizes of the first and the second layers
2452 
2453  for(size_t i = 0; i < layers_number; i++)
2454  {
2455  for(size_t j = 0; j < layers_number; j++)
2456  {
2457  for(size_t k = 0; k < outputs_number; k++)
2458  {
2459  output_interlayers_Delta(i,j)[k].set(layers_size[i], layers_size[j]);
2460  }
2461  }
2462  }
2463 
2464 
2465  if(layers_number > 0)
2466  {
2467  // Output-outputs layer (OK)
2468 
2469  output_interlayers_Delta(layers_number-1,layers_number-1) = layers[layers_number-1].arrange_activations_Hessian_form(layers_activation_second_derivative[layers_number-1]);
2470 
2471  // Rest of hidden layers
2472 
2473  double sum_1;
2474  double sum_2;
2475 
2476  for(size_t L = layers_number-1; L != 0; L--)
2477  {
2478  for(size_t M = layers_number-1; M >= L; M--)
2479  {
2480  if(!(L == layers_number-1 && M == layers_number-1))
2481  {
2482  for(size_t i = 0; i < outputs_number; i++)
2483  {
2484  for(size_t j = 0; j < layers_size[L]; j++)
2485  {
2486  sum_1 = 0.0;
2487 
2488  for(size_t l = 0; l < layers_size[L+1]; l++)
2489  {
2490  sum_1 += output_layers_delta[L+1](i,l)*layers_synaptic_weights[L+1](l,j);
2491  }
2492 
2493  for(size_t k = 0; k < layers_size[M]; k++)
2494  {
2495  sum_2 = 0.0;
2496 
2497  for(size_t l = 0; l < layers_size[L+1]; l++)
2498  {
2499  sum_2 += output_interlayers_Delta(L+1,M)[i](l,k)*layers_synaptic_weights[L+1](l,j);
2500  }
2501 
2502  output_interlayers_Delta(L,M)[i](j,k)
2503  = layers_activation_second_derivative[L][j]
2504  *interlayers_combination_combination_Jacobian(L,M)(j,k)*sum_1
2505  + layers_activation_derivative[L][j]*sum_2;
2506 
2507  output_interlayers_Delta(M,L)[i](k,j) = output_interlayers_Delta(L,M)[i](j,k);
2508  }
2509  }
2510  }
2511  }
2512  }
2513  }
2514  }
2515 
2516  return(output_interlayers_Delta);
2517 }
2518 
2519 
2520 // Vector<double> calculate_parametrs_outputs(const Vector<double>&, const Vector<double>&) const method
2521 
2526 
2528 {
2529  // Control sentence (if debug)
2530 
2531  #ifndef NDEBUG
2532 
2533  const size_t size = inputs.size();
2534 
2535  const size_t inputs_number = get_inputs_number();
2536 
2537  if(size != inputs_number)
2538  {
2539  std::ostringstream buffer;
2540 
2541  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
2542  << "Vector<double> calculate_outputs(const Vector<double>&, const Vector<double>&) const method.\n"
2543  << "Size of inputs (" << size <<") must be equal to number of inputs (" << inputs_number << ").\n";
2544 
2545  throw std::logic_error(buffer.str());
2546  }
2547 
2548  const size_t parameters_size = parameters.size();
2549 
2550  const size_t parameters_number = count_parameters_number();
2551 
2552  if(parameters_size != parameters_number)
2553  {
2554  std::ostringstream buffer;
2555 
2556  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
2557  << "Vector<double> calculate_outputs(const Vector<double>&, const Vector<double>&) const method.\n"
2558  << "Size of parameters (" << parameters_size <<") must be equal to number of parameters (" << parameters_number << ").\n";
2559 
2560  throw std::logic_error(buffer.str());
2561  }
2562 
2563  #endif
2564 
2565  const size_t layers_number = get_layers_number();
2566 
2567  Vector<double> outputs;
2568 
2569  if(layers_number == 0)
2570  {
2571  return(outputs);
2572  }
2573  else
2574  {
2575  const Vector<size_t> layers_parameters_numbers = count_layers_parameters_numbers();
2576 
2577  const Vector<size_t> layers_cumulative_parameters_number = arrange_layers_cumulative_parameters_number();
2578 
2579  Vector<double> layer_parameters;
2580 
2581  layer_parameters = parameters.take_out(0, layers_parameters_numbers[0]);
2582 
2583  outputs = layers[0].calculate_outputs(inputs, layer_parameters);
2584 
2585  for(size_t i = 1; i < layers_number; i++)
2586  {
2587  layer_parameters = parameters.take_out(layers_cumulative_parameters_number[i-1], layers_parameters_numbers[i]);
2588 
2589  outputs = layers[i].calculate_outputs(outputs, layer_parameters);
2590  }
2591  }
2592 
2593  return(outputs);
2594 }
2595 
2596 
2597 // Matrix<double> calculate_parameters_Jacobian(const Vector<double>&, const Vector<double>&) const method
2598 
2601 
2603 {
2604  #ifndef NDEBUG
2605 
2606  const size_t inputs_number = get_inputs_number();
2607  const size_t size = inputs.size();
2608 
2609  if(size != inputs_number)
2610  {
2611  std::ostringstream buffer;
2612 
2613  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
2614  << "void calculate_Jacobian(Vector<double>&, const Vector<double>&) const method.\n"
2615  << "Size must be equal to number of inputs.\n";
2616 
2617  throw std::logic_error(buffer.str());
2618  }
2619 
2620  #endif
2621 
2622  // Neural network stuff
2623 
2624  const size_t layers_number = get_layers_number();
2625  const Vector<size_t> layers_size = arrange_layers_perceptrons_numbers();
2626 
2627  // Calculate required quantities
2628 
2629  const Vector< Vector< Vector<double> > > first_order_forward_propagation = calculate_first_order_forward_propagation(inputs);
2630  const Vector< Vector<double> >& layers_activation = first_order_forward_propagation[0];
2631  const Vector< Vector<double> >& layers_activation_derivative = first_order_forward_propagation[1];
2632 
2633  const Vector< Vector<double> > layers_inputs = arrange_layers_input(inputs, layers_activation);
2634 
2635  const Vector< Matrix<double> > layers_combination_parameters_Jacobian = calculate_layers_combination_parameters_Jacobian(layers_inputs);
2636 
2637  const Vector< Matrix<double> > output_layers_delta = calculate_output_layers_delta(layers_activation_derivative);
2638 
2639  Matrix<double> parameters_Jacobian = output_layers_delta[0].dot(layers_combination_parameters_Jacobian[0]);
2640 
2641  for(size_t i = 1; i < layers_number; i++)
2642  {
2643  parameters_Jacobian = parameters_Jacobian.assemble_columns(output_layers_delta[i].dot(layers_combination_parameters_Jacobian[i]));
2644  }
2645 
2646  return(parameters_Jacobian);
2647 }
2648 
2649 
2650 // Vector< Matrix<double> > calculate_Hessian_form(const Vector<double>&, const Vector<double>&) const
2651 
2654 
2656 {
2657  // Neural network stuff
2658 
2659  const size_t layers_number = get_layers_number();
2660  const Vector<size_t> layers_size = arrange_layers_perceptrons_numbers();
2661  const size_t outputs_number = get_outputs_number();
2662 
2663  const size_t parameters_number = count_parameters_number();
2664 
2665  const Vector< Matrix<double> > layers_synaptic_weights = arrange_layers_synaptic_weights();
2666 
2667  // Calculate required quantities
2668 
2669  const Vector< Vector< Vector<double> > > second_order_forward_propagation = calculate_second_order_forward_propagation(inputs);
2670 
2671  const Vector< Vector<double> >& layers_activation = second_order_forward_propagation[0];
2672  const Vector< Vector<double> >& layers_activation_derivative = second_order_forward_propagation[1];
2673 // const Vector< Vector<double> >& layers_activation_second_derivative = second_order_forward_propagation[2];
2674 
2675  const Vector< Vector<double> > layers_inputs = arrange_layers_input(inputs, layers_activation);
2676 
2677  const Vector< Vector< Vector<double> > > perceptrons_combination_parameters_gradient = calculate_perceptrons_combination_parameters_gradient(layers_inputs);
2678 
2679  const Matrix< Matrix<double> > interlayers_combination_combination_Jacobian = calculate_interlayers_combination_combination_Jacobian(inputs);
2680 
2681  const Vector< Matrix<double> > output_layers_delta = calculate_output_layers_delta(layers_activation_derivative);
2682 
2683  const Matrix< Vector< Matrix<double> > > output_interlayers_Delta
2684  = calculate_output_interlayers_Delta(second_order_forward_propagation, interlayers_combination_combination_Jacobian, output_layers_delta);
2685 
2686  // Size multilayer_perceptron_pointer parameters Hessian form
2687 
2688  Vector< Matrix<double> > parameters_Hessian_form(outputs_number);
2689 
2690  for(size_t i = 0; i < outputs_number; i++)
2691  {
2692  parameters_Hessian_form[i].set(parameters_number, parameters_number);
2693  }
2694 
2695  // Calculate Hessian form elements
2696 
2697  if(layers_number > 0)
2698  {
2699  const Matrix<size_t> parameters_indices = arrange_parameters_indices();
2700 
2701  size_t layer_j;
2702  size_t neuron_j;
2703  size_t parameter_j;
2704 
2705  size_t layer_k;
2706  size_t neuron_k;
2707  size_t parameter_k;
2708 
2709  Vector<double> neuron_j_combination_parameters_gradient;
2710  Vector<double> neuron_k_combination_parameters_gradient;
2711 
2712  for(size_t i = 0; i < outputs_number; i++)
2713  {
2714  for(size_t j = 0; j < parameters_number; j++)
2715  {
2716  layer_j = parameters_indices(j,0);
2717  neuron_j = parameters_indices(j,1);
2718  parameter_j = parameters_indices(j,2);
2719 
2720  for(size_t k = j; k < parameters_number; k++)
2721  {
2722  layer_k = parameters_indices(k,0);
2723  neuron_k = parameters_indices(k,1);
2724  parameter_k = parameters_indices(k,2);
2725 
2726  parameters_Hessian_form[i](j,k) =
2727  output_interlayers_Delta(layer_j,layer_k)[i](neuron_j,neuron_k)
2728  *perceptrons_combination_parameters_gradient[layer_j][neuron_j][parameter_j]
2729  *perceptrons_combination_parameters_gradient[layer_k][neuron_k][parameter_k]
2730  ;
2731 
2732  if(layer_j != 0 && parameter_j != 0) // Neither the first layer nor parameter is a bias
2733  {
2734  //parameters_Hessian_form[i](j,k) +=
2735  //output_layers_delta[layer_j][i][neuron_j]
2736  //*layers_activation_derivative[layer_j-1][parameter_j-1]
2737  //*interlayers_combination_combination_Jacobian[layer_j-1][layer_k][parameter_j-1][neuron_k]
2738  //*perceptrons_combination_parameters_gradient[layer_k][neuron_k][parameter_k]
2739  ;
2740  }
2741 
2742  if(layer_k != 0 && parameter_k != 0)
2743  {
2744  parameters_Hessian_form[i](j,k) +=
2745  output_layers_delta[layer_k](i,neuron_k)
2746  *layers_activation_derivative[layer_k-1][parameter_k-1]
2747  *interlayers_combination_combination_Jacobian(layer_k-1,layer_j)(parameter_k-1,neuron_j)
2748  *perceptrons_combination_parameters_gradient[layer_j][neuron_j][parameter_j]
2749  ;
2750  }
2751 
2752  parameters_Hessian_form[i](k,j) = parameters_Hessian_form[i](j,k);
2753  }
2754  }
2755  }
2756  }
2757 
2758  return(parameters_Hessian_form);
2759 }
2760 
2761 
2762 // Vector< Vector<double> > arrange_layers_input(const Vector<double>&, const Vector< Vector<double> >&) const method
2763 
2770 
2772 {
2773  // Neural network stuff
2774 
2775  const size_t layers_number = get_layers_number();
2776 
2777  #ifndef NDEBUG
2778 
2779  const size_t inputs_number = get_inputs_number();
2780  const size_t inputs_size = inputs.size();
2781 
2782  if(inputs_size != inputs_number)
2783  {
2784  std::ostringstream buffer;
2785 
2786  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
2787  << "Vector< Vector<double> > arrange_layers_input(const Vector<double>&, const Vector< Vector<double> >&) const method.\n"
2788  << "Size must be equal to number of inputs.\n";
2789 
2790  throw std::logic_error(buffer.str());
2791  }
2792 
2793  const size_t layers_activation_size = layers_activation.size();
2794 
2795  if(layers_activation_size != layers_number)
2796  {
2797  std::ostringstream buffer;
2798 
2799  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
2800  << "Vector< Vector<double> > arrange_layers_input(const Vector<double>&, const Vector< Vector<double> >&) const method.\n"
2801  << "Size must be equal to number of inputs.\n";
2802 
2803  throw std::logic_error(buffer.str());
2804  }
2805 
2806  #endif
2807 
2808  // Arrange layers inputs
2809 
2810  Vector< Vector<double> > layers_inputs(layers_number);
2811 
2812  if(layers_number != 0)
2813  {
2814  layers_inputs[0] = inputs;
2815 
2816  for(size_t j = 1; j < layers_number; j++)
2817  {
2818  layers_inputs[j] = layers_activation[j-1];
2819  }
2820  }
2821 
2822  return(layers_inputs);
2823 }
2824 
2825 
2826 // Vector< Vector<double> > arrange_layers_input(const Vector<double>&, const Vector< Vector< Vector<double> > >&) const method
2827 
2834 
2835 Vector< Vector<double> > MultilayerPerceptron::arrange_layers_input(const Vector<double>& input, const Vector< Vector< Vector<double> > >& first_order_forward_propagation) const
2836 {
2837  const size_t layers_number = get_layers_number();
2838 
2839  Vector< Vector<double> > layers_inputs(layers_number);
2840 
2841  const Vector< Vector<double> >& layers_activation = first_order_forward_propagation[0];
2842 
2843  layers_inputs[0] = input;
2844 
2845  for(size_t j = 1; j < layers_number; j++)
2846  {
2847  layers_inputs[j] = layers_activation[j-1];
2848  }
2849 
2850  return(layers_inputs);
2851 }
2852 
2853 
2854 // Vector< Vector<double> > calculate_layers_input(const Vector<double>&) const method
2855 
2859 
2861 {
2862  const size_t layers_number = get_layers_number();
2863 
2864  Vector< Vector<double> > layers_inputs(layers_number);
2865 
2866  layers_inputs[0] = inputs;
2867 
2868  for(size_t i = 1; i < layers_number; i++)
2869  {
2870  layers_inputs[i] = layers[i-1].calculate_outputs(layers_inputs[i-1]);
2871  }
2872 
2873  return(layers_inputs);
2874 }
2875 
2876 
2877 // Vector< Vector<double> > calculate_layers_combination(const Vector<double>&) const method
2878 
2882 
2884 {
2885  // Control sentence (if debug)
2886 
2887  #ifndef NDEBUG
2888 
2889  const size_t inputs_size = inputs.size();
2890 
2891  const size_t inputs_number = get_inputs_number();
2892 
2893  if(inputs_size != inputs_number)
2894  {
2895  std::ostringstream buffer;
2896 
2897  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
2898  << "Vector< Vector<double> > calculate_layers_combination(const Vector<double>&) const method.\n"
2899  << "Size must be equal to number of inputs.\n";
2900 
2901  throw std::logic_error(buffer.str());
2902  }
2903 
2904  #endif
2905 
2906  const size_t layers_number = get_layers_number();
2907 
2908  Vector< Vector<double> > layers_combination(layers_number);
2909 
2910  if(layers_number > 0)
2911  {
2912  Vector< Vector<double> > layers_activation(layers_number);
2913 
2914  layers_combination[0] = layers[0].calculate_combinations(inputs);
2915 
2916  layers_activation[0] = layers[0].calculate_activations(layers_combination[0]);
2917 
2918  for(size_t i = 1; i < layers_number; i++)
2919  {
2920  layers_combination[i] = layers[i].calculate_combinations(layers_activation[i-1]);
2921 
2922  layers_activation[i] = layers[i].calculate_activations(layers_combination[i]);
2923  }
2924  }
2925 
2926  return(layers_combination);
2927 }
2928 
2929 
2930 // Vector< Matrix<double> > calculate_layers_combination_Jacobian(const Vector<double>&) const method
2931 
2934 
2936 {
2937  const size_t layers_number = get_layers_number();
2938 
2939  Vector< Matrix<double> > layers_combination_Jacobian(layers_number-2);
2940 
2941  Vector< Vector<double> > layers_output(layers_number);
2942 
2943  Vector< Matrix<double> > layers_Jacobian(layers_number);
2944 
2945  // Hidden and outputs layers Jacobian
2946 
2947  layers_output[0] = layers[0].calculate_outputs(inputs);
2948 
2949  layers_combination_Jacobian[0] = layers[0].calculate_combinations_Jacobian(inputs);
2950 
2951  for(size_t i = 1; i < layers_number; i++)
2952  {
2953  layers_output[i] = layers[i].calculate_outputs(layers_output[i-1]);
2954 
2955  layers_Jacobian[i] = layers[i].calculate_Jacobian(layers_output[i-1]);
2956  }
2957 
2958  Matrix<double> output_layer_Jacobian = layers[layers_number-1].calculate_Jacobian(layers_output[layers_number-1]);
2959 
2960  // Calculate forward propagation Jacobian
2961 
2962  layers_Jacobian[layers_number] = output_layer_Jacobian;
2963 
2964  for(int i = (int)layers_number-1; i > -1; i--)
2965  {
2966  layers_Jacobian[layers_number] = layers_Jacobian[layers_number].dot(layers_Jacobian[i]);
2967  }
2968 
2969  for(int i = (int)layers_number-1; i > -1; i--)
2970  {
2971  layers_Jacobian[i] = layers_Jacobian[i];
2972 
2973  for(int j = (int)i-1; j > -1; j--)
2974  {
2975  layers_Jacobian[i] = layers_Jacobian[i].dot(layers_Jacobian[j]);
2976  }
2977  }
2978 
2979  return(layers_combination_Jacobian);
2980 }
2981 
2982 
2983 // Vector< Matrix<double> > calculate_layers_combination_parameters_Jacobian(const Vector< Vector<double> >&) const method
2984 
2989 
2991 {
2992  const size_t layers_number = get_layers_number();
2993 
2994  Vector< Matrix<double> > layers_combination_parameters_Jacobian(layers_number);
2995 
2996  const Vector<double> dummy;
2997 
2998  for(size_t i = 0; i < layers_number; i++)
2999  {
3000  layers_combination_parameters_Jacobian[i] = layers[i].calculate_combinations_Jacobian(layers_inputs[i], dummy);
3001  }
3002 
3003  return(layers_combination_parameters_Jacobian);
3004 }
3005 
3006 
3007 // Vector< Vector< Vector<double> > > calculate_perceptrons_combination_parameters_gradient(const Vector< Vector<double> >&) const method
3008 
3016 
3018 {
3019  const size_t layers_number = get_layers_number();
3020 
3021  // Control sentence (if debug)
3022 
3023  #ifndef NDEBUG
3024 
3025  const size_t layers_input_size = layers_inputs.size();
3026 
3027  if(layers_input_size != layers_number)
3028  {
3029  std::ostringstream buffer;
3030 
3031  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
3032  << "Vector< Vector< Vector<double> > > calculate_perceptrons_combination_parameters_gradient(const Vector< Vector<double> >&) const method.\n"
3033  << "Size must be equal to number of layers.\n";
3034 
3035  throw std::logic_error(buffer.str());
3036  }
3037 
3038  #endif
3039 
3040  const Vector<size_t> layers_inputs_number = get_layers_inputs_number();
3041 
3042  #ifndef NDEBUG
3043 
3044  for(size_t i = 0; i < layers_number; i++)
3045  {
3046  if(layers_inputs[i].size() != layers_inputs_number[i])
3047  {
3048  std::ostringstream buffer;
3049 
3050  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
3051  << "Vector< Vector< Vector<double> > > calculate_perceptrons_combination_parameters_gradient(const Vector< Vector<double> >&) const method.\n"
3052  << "Size of inputs to layer " << i << " must be equal to size of that layer.\n";
3053 
3054  throw std::logic_error(buffer.str());
3055  }
3056  }
3057 
3058  #endif
3059 
3060  const Vector<size_t> layers_size = arrange_layers_perceptrons_numbers();
3061 
3062  Vector<double> dummy_layer_parameters;
3063 
3064  Vector< Vector< Vector<double> > > perceptrons_combination_gradient(layers_number);
3065 
3066  for(size_t i = 0; i < layers_number; i++)
3067  {
3068  perceptrons_combination_gradient[i].set(layers_size[i]);
3069 
3070  for(size_t j = 0; j < layers_size[i]; j++)
3071  {
3072  const Perceptron& perceptron = layers[i].get_perceptron(j);
3073 
3074  perceptrons_combination_gradient[i][j] = perceptron.calculate_combination_gradient(layers_inputs[i], dummy_layer_parameters);
3075  }
3076  }
3077 
3078  return(perceptrons_combination_gradient);
3079 }
3080 
3081 
3082 // Vector< Vector<double> > calculate_layers_activation(const Vector<double>&) const method
3083 
3087 
3089 {
3090  // Control sentence (if debug)
3091 
3092  #ifndef NDEBUG
3093 
3094  const size_t inputs_size = inputs.size();
3095 
3096  const size_t inputs_number = get_inputs_number();
3097 
3098  if(inputs_size != inputs_number)
3099  {
3100  std::ostringstream buffer;
3101 
3102  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
3103  << "Vector< Vector<double> > calculate_layers_activation(const Vector<double>&) const method.\n"
3104  << "Size must be equal to number of inputs.\n";
3105 
3106  throw std::logic_error(buffer.str());
3107  }
3108 
3109  #endif
3110 
3111  const size_t layers_number = get_layers_number();
3112 
3113  Vector< Vector<double> > layers_combination(layers_number);
3114  Vector< Vector<double> > layers_activation(layers_number);
3115 
3116  layers_combination[0] = layers[0].calculate_combinations(inputs);
3117  layers_activation[0] = layers[0].calculate_activations(layers_combination[0]);
3118 
3119  for(size_t i = 1; i < layers_number; i++)
3120  {
3121  layers_combination[i] = layers[i].calculate_combinations(layers_activation[i-1]);
3122  layers_activation[i] = layers[i].calculate_activations(layers_combination[i]);
3123  }
3124 
3125  return(layers_activation);
3126 }
3127 
3128 
3129 // Vector< Vector<double> > calculate_layers_activation_derivative(const Vector<double>&) const method
3130 
3134 
3136 {
3137  // Control sentence (if debug)
3138 
3139  #ifndef NDEBUG
3140 
3141  const size_t inputs_size = inputs.size();
3142  const size_t inputs_number = get_inputs_number();
3143 
3144  if(inputs_size != inputs_number)
3145  {
3146  std::ostringstream buffer;
3147 
3148  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
3149  << "Vector< Vector<double> > calculate_layers_activation_derivative(const Vector<double>&) const method.\n"
3150  << "Size must be equal to number of inputs.\n";
3151 
3152  throw std::logic_error(buffer.str());
3153  }
3154 
3155  #endif
3156 
3157  const size_t layers_number = get_layers_number();
3158 
3159  Vector< Vector<double> > layers_combination(layers_number);
3160  Vector< Vector<double> > layers_activation(layers_number);
3161  Vector< Vector<double> > layers_activation_derivatives(layers_number);
3162 
3163  if(layers_number != 0)
3164  {
3165  layers_combination[0] = layers[0].calculate_combinations(inputs);
3166  layers_activation[0] = layers[0].calculate_activations(layers_combination[0]);
3167  layers_activation_derivatives[0] = layers[0].calculate_activations_derivatives(layers_combination[0]);
3168 
3169  for(size_t i = 1; i < layers_number; i++)
3170  {
3171  layers_combination[i] = layers[i].calculate_combinations(layers_activation[i-1]);
3172  layers_activation[i] = layers[i].calculate_activations(layers_combination[i]);
3173  layers_activation_derivatives[i] = layers[i].calculate_activations_derivatives(layers_combination[i]);
3174  }
3175  }
3176 
3177  return(layers_activation_derivatives);
3178 }
3179 
3180 
3181 // Vector< Vector<double> > calculate_layers_activation_second_derivative(const Vector<double>&) const method
3182 
3191 
3193 {
3194  // Control sentence (if debug)
3195 
3196  #ifndef NDEBUG
3197 
3198  const size_t inputs_size = inputs.size();
3199 
3200  const size_t inputs_number = get_inputs_number();
3201 
3202  if(inputs_size != inputs_number)
3203  {
3204  std::ostringstream buffer;
3205 
3206  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
3207  << "Vector< Vector<double> > calculate_layers_activation_second_derivative(const Vector<double>&) const method.\n"
3208  << "Size must be equal to number of inputs.\n";
3209 
3210  throw std::logic_error(buffer.str());
3211  }
3212 
3213  #endif
3214 
3215  const size_t layers_number = get_layers_number();
3216 
3217  Vector< Vector<double> > layers_combination(layers_number);
3218  Vector< Vector<double> > layers_activation(layers_number);
3219  Vector< Vector<double> > layers_activation_second_derivatives(layers_number);
3220 
3221  layers_combination[0] = layers[0].calculate_combinations(inputs);
3222  layers_activation[0] = layers[0].calculate_activations(layers_combination[0]);
3223  layers_activation_second_derivatives[0] = layers[0].calculate_activations_second_derivatives(layers_combination[0]);
3224 
3225  for(size_t i = 1; i < layers_number; i++)
3226  {
3227  layers_combination[i] = layers[i].calculate_combinations(layers_activation[i-1]);
3228 
3229  layers_activation[i] = layers[i].calculate_activations(layers_combination[i]);
3230 
3231  layers_activation_second_derivatives[i] = layers[i].calculate_activations_second_derivatives(layers_combination[i]);
3232  }
3233 
3234  return(layers_activation_second_derivatives);
3235 }
3236 
3237 
3238 // Vector< Matrix<double> > calculate_layers_Jacobian(const Vector<double>&) const method
3239 
3244 
3246 {
3247  const size_t layers_number = get_layers_number();
3248 
3249  Vector<Vector<double> > layers_output(layers_number);
3250  Vector< Matrix<double> > layers_Jacobian(layers_number);
3251 
3252  layers_output[0] = layers[0].calculate_outputs(inputs);
3253  layers_Jacobian[0] = layers[0].calculate_Jacobian(inputs);
3254 
3255  for(size_t i = 1; i < layers_number; i++)
3256  {
3257  layers_output[i] = layers[i].calculate_outputs(layers_output[i-1]);
3258 
3259  layers_Jacobian[i] = layers[i].calculate_Jacobian(layers_output[i-1]);
3260  }
3261 
3262  return(layers_Jacobian);
3263 }
3264 
3265 
3266 // Vector< Matrix<double> > calculate_layers_Jacobian(const Vector<double>&) const method
3267 
3272 
3274 {
3275  const size_t layers_number = get_layers_number();
3276 
3277  Vector<Vector<double> > layers_output(layers_number);
3278  Vector< Vector< Matrix<double> > > layers_Hessian_form(layers_number);
3279 
3280  layers_output[0] = layers[0].calculate_outputs(inputs);
3281  layers_Hessian_form[0] = layers[0].calculate_Hessian_form(inputs);
3282 
3283  for(size_t i = 1; i < layers_number; i++)
3284  {
3285  layers_output[i] = layers[i].calculate_outputs(layers_output[i-1]);
3286 
3287  layers_Hessian_form[i] = layers[i].calculate_Hessian_form(layers_output[i-1]);
3288  }
3289 
3290  return(layers_Hessian_form);
3291 }
3292 
3293 
3294 // Matrix< Matrix<double> > calculate_interlayers_combination_combination_Jacobian(const Vector<double>&) const method
3295 
3299 
3301 {
3302  #ifndef NDEBUG
3303 
3304  const size_t size = inputs.size();
3305 
3306  const size_t inputs_number = get_inputs_number();
3307 
3308  if(size != inputs_number)
3309  {
3310  std::ostringstream buffer;
3311 
3312  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
3313  << "Matrix< Matrix<double> > calculate_interlayers_combination_combination_Jacobian(const Vector<double>&) const method.\n"
3314  << "Size of inpouts must be equal to number of inputs.\n";
3315 
3316  throw std::logic_error(buffer.str());
3317  }
3318 
3319  #endif
3320 
3321  const Vector< Vector<double> > layers_combination = calculate_layers_combination(inputs);
3322 
3323  return(calculate_interlayers_combination_combination_Jacobian(layers_combination));
3324 }
3325 
3326 
3327 // Matrix <Matrix<double> > calculate_interlayers_combination_combination_Jacobian(const Vector< Vector<double> >&) const method
3328 
3332 
3334 {
3335  const size_t layers_number = get_layers_number();
3336 
3337  #ifndef NDEBUG
3338 
3339  size_t size;
3340 
3341  const Vector<size_t> layers_size = arrange_layers_perceptrons_numbers();
3342 
3343  for(size_t i = 0; i < layers_number; i++)
3344  {
3345  size = layers_combination[i].size();
3346 
3347  if(size != layers_size[i])
3348  {
3349  std::ostringstream buffer;
3350 
3351  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
3352  << "Matrix< Matrix<double> > calculate_interlayers_combination_combination_Jacobian(const Vector< Vector<double> >&) const method.\n"
3353  << "Size must be equal to size of layer.\n";
3354 
3355  throw std::logic_error(buffer.str());
3356  }
3357  }
3358 
3359  #endif
3360 
3361  // Calculate interlayers combination combination Jacobian
3362 
3363  Matrix< Matrix<double> > interlayers_combination_combination_Jacobian(layers_number, layers_number);
3364 
3365  for(size_t image_index = 0; image_index < layers_number; image_index++)
3366  {
3367  for(size_t domain_index = 0; domain_index < layers_number; domain_index++)
3368  {
3369  interlayers_combination_combination_Jacobian(image_index,domain_index) =
3370  calculate_interlayer_combination_combination_Jacobian(domain_index, image_index, layers_combination[domain_index]);
3371  }
3372  }
3373 
3374  return(interlayers_combination_combination_Jacobian);
3375 }
3376 
3377 
3378 // Vector< Vector< Vector<double> > > calculate_first_order_forward_propagation(const Vector<double>&) const method
3379 
3387 
3389 {
3390  // Control sentence (if debug)
3391 
3392  #ifndef NDEBUG
3393 
3394  const size_t inputs_size = inputs.size();
3395 
3396  const size_t inputs_number = get_inputs_number();
3397 
3398  if(inputs_size != inputs_number)
3399  {
3400  std::ostringstream buffer;
3401 
3402  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
3403  << "Vector< Vector< Vector<double> > > calculate_first_order_forward_propagation(const Vector<double>&) const method.\n"
3404  << "Size must be equal to number of inputs.\n";
3405 
3406  throw std::logic_error(buffer.str());
3407  }
3408 
3409  #endif
3410 
3411  const size_t layers_number = get_layers_number();
3412 
3413  Vector< Vector<double> > layers_combination(layers_number);
3414 
3415  Vector< Vector< Vector<double> > > first_order_forward_propagation(2);
3416 
3417  first_order_forward_propagation[0].set(layers_number);
3418  first_order_forward_propagation[1].set(layers_number);
3419 
3420  layers_combination[0] = layers[0].calculate_combinations(inputs);
3421 
3422  first_order_forward_propagation[0][0] = layers[0].calculate_activations(layers_combination[0]);
3423 
3424  first_order_forward_propagation[1][0] = layers[0].calculate_activations_derivatives(layers_combination[0]);
3425 
3426  for(size_t i = 1; i < layers_number; i++)
3427  {
3428  layers_combination[i] = layers[i].calculate_combinations(first_order_forward_propagation[0][i-1]);
3429 
3430  first_order_forward_propagation[0][i] = layers[i].calculate_activations(layers_combination[i]);
3431 
3432  first_order_forward_propagation[1][i] = layers[i].calculate_activations_derivatives(layers_combination[i]);
3433  }
3434 
3435  return(first_order_forward_propagation);
3436 }
3437 
3438 
3439 // Vector< Vector< Vector<double> > > calculate_second_order_forward_propagation(const Vector<double>&) const method
3440 
3448 
3450 {
3451  // Control sentence (if debug)
3452 
3453  #ifndef NDEBUG
3454 
3455  const size_t inputs_size = inputs.size();
3456 
3457  const size_t inputs_number = get_inputs_number();
3458 
3459  if(inputs_size != inputs_number)
3460  {
3461  std::ostringstream buffer;
3462 
3463  buffer << "OpenNN Exception: MultilayerPerceptron class.\n"
3464  << "Vector< Vector< Vector<double> > > calculate_second_order_forward_propagation(const Vector<double>&) const method.\n"
3465  << "Size of multilayer perceptron inputs must be equal to number of inputs.\n";
3466 
3467  throw std::logic_error(buffer.str());
3468  }
3469 
3470  #endif
3471 
3472  const size_t layers_number = get_layers_number();
3473 
3474  Vector< Vector<double> > layers_combination(layers_number);
3475 
3476  Vector< Vector< Vector<double> > > second_order_forward_propagation(3);
3477 
3478  second_order_forward_propagation[0].set(layers_number);
3479  second_order_forward_propagation[1].set(layers_number);
3480  second_order_forward_propagation[2].set(layers_number);
3481 
3482  layers_combination[0] = layers[0].calculate_combinations(inputs);
3483 
3484  second_order_forward_propagation[0][0] = layers[0].calculate_activations(layers_combination[0]);
3485 
3486  second_order_forward_propagation[1][0] = layers[0].calculate_activations_derivatives(layers_combination[0]);
3487 
3488  second_order_forward_propagation[2][0] = layers[0].calculate_activations_second_derivatives(layers_combination[0]);
3489 
3490  for(size_t i = 1; i < layers_number; i++)
3491  {
3492  layers_combination[i] = layers[i].calculate_combinations(second_order_forward_propagation[0][i-1]);
3493 
3494  second_order_forward_propagation[0][i] = layers[i].calculate_activations(layers_combination[i]);
3495 
3496  second_order_forward_propagation[1][i] = layers[i].calculate_activations_derivatives(layers_combination[i]);
3497 
3498  second_order_forward_propagation[2][i] = layers[i].calculate_activations_second_derivatives(layers_combination[i]);
3499  }
3500 
3501  return(second_order_forward_propagation);
3502 }
3503 
3504 
3505 // std::string to_string(void) const method
3506 
3508 
3509 std::string MultilayerPerceptron::to_string(void) const
3510 {
3511  std::ostringstream buffer;
3512 
3513  buffer << "MultilayerPerceptron\n"
3514  << "Architecture: " << arrange_architecture() << "\n"
3515  << "Layers activation function: " << write_layers_activation_function() << "\n"
3516  << "Parameters: " << arrange_parameters() << "\n"
3517  << "Display: " << display << "\n";
3518 
3519  return(buffer.str());
3520 }
3521 
3522 
3523 // tinyxml2::XMLDocument* to_XML(void) const method
3524 
3527 
3528 tinyxml2::XMLDocument* MultilayerPerceptron::to_XML(void) const
3529 {
3530  std::ostringstream buffer;
3531 
3532  tinyxml2::XMLDocument* document = new tinyxml2::XMLDocument;
3533 
3534  tinyxml2::XMLElement* multilayer_perceptron_element = document->NewElement("MultilayerPerceptron");
3535 
3536  document->InsertFirstChild(multilayer_perceptron_element);
3537 
3538  // Architecture
3539  {
3540  tinyxml2::XMLElement* architecture_element = document->NewElement("Architecture");
3541  multilayer_perceptron_element->LinkEndChild(architecture_element);
3542 
3543  std::string architecture_string = arrange_architecture().to_string();
3544 
3545  tinyxml2::XMLText* architecture_text = document->NewText(architecture_string.c_str());
3546  architecture_element->LinkEndChild(architecture_text);
3547  }
3548 
3549  // Layers activation function
3550  {
3551  tinyxml2::XMLElement* layers_activation_function_element = document->NewElement("LayersActivationFunction");
3552  multilayer_perceptron_element->LinkEndChild(layers_activation_function_element);
3553 
3554  std::string layers_activation_function_string = write_layers_activation_function().to_string();
3555 
3556  tinyxml2::XMLText* layers_activation_function_text = document->NewText(layers_activation_function_string.c_str());
3557  layers_activation_function_element->LinkEndChild(layers_activation_function_text);
3558  }
3559 
3560  // Parameters
3561  {
3562  tinyxml2::XMLElement* parameters_element = document->NewElement("Parameters");
3563  multilayer_perceptron_element->LinkEndChild(parameters_element);
3564 
3565  const std::string parameters_string = arrange_parameters().to_string();
3566 
3567  tinyxml2::XMLText* parameters_text = document->NewText(parameters_string.c_str());
3568  parameters_element->LinkEndChild(parameters_text);
3569  }
3570 
3571  // Display
3572  {
3573  tinyxml2::XMLElement* display_element = document->NewElement("Display");
3574  multilayer_perceptron_element->LinkEndChild(display_element);
3575 
3576  buffer.str("");
3577  buffer << display;
3578 
3579  tinyxml2::XMLText* display_text = document->NewText(buffer.str().c_str());
3580  display_element->LinkEndChild(display_text);
3581  }
3582 
3583  return(document);
3584 }
3585 
3586 
3587 // void from_XML(const tinyxml2::XMLDocument&) method
3588 
3591 
3592 void MultilayerPerceptron::from_XML(const tinyxml2::XMLDocument& document)
3593 {
3594  const tinyxml2::XMLElement* root_element = document.FirstChildElement("MultilayerPerceptron");
3595 
3596  if(!root_element)
3597  {
3598  return;
3599  }
3600 
3601  // Architecture
3602  {
3603  const tinyxml2::XMLElement* architecture_element = root_element->FirstChildElement("Architecture");
3604 
3605  if(architecture_element)
3606  {
3607  const char* architecture_text = architecture_element->GetText();
3608 
3609  if(architecture_text)
3610  {
3611  Vector<size_t> new_architecture;
3612  new_architecture.parse(architecture_text);
3613 
3614  try
3615  {
3616  set(new_architecture);
3617  }
3618  catch(const std::logic_error& e)
3619  {
3620  std::cout << e.what() << std::endl;
3621  }
3622  }
3623  }
3624  }
3625 
3626  // Layers activation function
3627  {
3628  const tinyxml2::XMLElement* layers_activation_function_element = root_element->FirstChildElement("LayersActivationFunction");
3629 
3630  if(layers_activation_function_element)
3631  {
3632  const char* layers_activation_function_text = layers_activation_function_element->GetText();
3633 
3634  if(layers_activation_function_text)
3635  {
3636  Vector<std::string> new_layers_activation_function;
3637  new_layers_activation_function.parse(layers_activation_function_text);
3638 
3639  try
3640  {
3641  set_layers_activation_function(new_layers_activation_function);
3642  }
3643  catch(const std::logic_error& e)
3644  {
3645  std::cout << e.what() << std::endl;
3646  }
3647  }
3648  }
3649  }
3650 
3651  // Parameters
3652  {
3653  const tinyxml2::XMLElement* parameters_element = root_element->FirstChildElement("Parameters");
3654 
3655  if(parameters_element)
3656  {
3657  const char* parameters_text = parameters_element->GetText();
3658 
3659  if(parameters_text)
3660  {
3661  Vector<double> new_parameters;
3662  new_parameters.parse(parameters_text);
3663 
3664  try
3665  {
3666  set_parameters(new_parameters);
3667  }
3668  catch(const std::logic_error& e)
3669  {
3670  std::cout << e.what() << std::endl;
3671  }
3672  }
3673  }
3674  }
3675 
3676  // Display
3677  {
3678  const tinyxml2::XMLElement* display_element = root_element->FirstChildElement("Display");
3679 
3680  if(display_element)
3681  {
3682  std::string new_display_string = display_element->GetText();
3683 
3684  try
3685  {
3686  set_display(new_display_string != "0");
3687  }
3688  catch(const std::logic_error& e)
3689  {
3690  std::cout << e.what() << std::endl;
3691  }
3692  }
3693  }
3694 }
3695 
3696 
3697 // Matrix<std::string> write_information(void) const method
3698 
3703 
3705 {
3706  std::ostringstream buffer;
3707 
3708  const size_t layers_number = get_layers_number();
3709 
3710  if(layers_number == 0)
3711  {
3712  Matrix<std::string> information;
3713 
3714  return(information);
3715 
3716  }
3717  else
3718  {
3719  Matrix<std::string> information(layers_number, 3);
3720 
3721  for(size_t i = 0; i < layers_number; i++)
3722  {
3723  // Inputs number
3724 
3725  buffer.str("");
3726  buffer << layers[i].get_inputs_number();
3727 
3728  information(i,0) = buffer.str();
3729 
3730  // Perceptrons number
3731 
3732  buffer.str("");
3733  buffer << layers[i].get_perceptrons_number();
3734 
3735  information(i,1) = buffer.str();
3736 
3737  // Activation function
3738 
3739  information(i,2) = layers[i].write_activation_function();
3740  }
3741 
3742  return(information);
3743 
3744  }
3745 }
3746 
3747 
3748 // std::string write_expression(const Vector<std::string>&, const Vector<std::string>&) const method
3749 
3753 
3754 std::string MultilayerPerceptron::write_expression(const Vector<std::string>& inputs_name, const Vector<std::string>& outputs_name) const
3755 {
3756  const size_t layers_number = get_layers_number();
3757  const Vector<size_t> layers_perceptrons_number = arrange_layers_perceptrons_numbers();
3758 
3759  std::ostringstream buffer;
3760 
3761  if(layers_number == 0)
3762  {
3763  }
3764  else if(layers_number == 1)
3765  {
3766  buffer << layers[0].write_expression(inputs_name, outputs_name) << "\n";
3767  }
3768  else
3769  {
3770  Vector< Vector<std::string> > layers_outputs_name(layers_number);
3771 
3772  for(size_t i = 0; i < layers_number; i++)
3773  {
3774  layers_outputs_name[i].set(layers_perceptrons_number[i]);
3775 
3776  for(size_t j = 0; j < layers_perceptrons_number[i]; j++)
3777  {
3778  std::ostringstream new_buffer;
3779  new_buffer << "y_" << i+1 << "_" << j+1;
3780  layers_outputs_name[i][j] = new_buffer.str();
3781  }
3782  }
3783 
3784  buffer << layers[0].write_expression(inputs_name, layers_outputs_name[0]);
3785 
3786  for(size_t i = 1; i < layers_number-1; i++)
3787  {
3788  buffer << layers[i].write_expression(layers_outputs_name[i-1], layers_outputs_name[i]);
3789  }
3790 
3791  buffer << layers[layers_number-1].write_expression(layers_outputs_name[layers_number-2], outputs_name);
3792  }
3793 
3794  return(buffer.str());
3795 }
3796 
3797 }
3798 
3799 // OpenNN: Open Neural MultilayerPerceptrons Library.
3800 // Copyright (c) 2005-2015 Roberto Lopez.
3801 //
3802 // This library is free software; you can redistribute it and/or
3803 // modify it under the terms of the GNU Lesser General Public
3804 // License as published by the Free Software Foundation; either
3805 // version 2.1 of the License, or any later version.
3806 //
3807 // This library is distributed in the hope that it will be useful,
3808 // but WITHOUT ANY WARRANTY; without even the implied warranty of
3809 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
3810 // Lesser General Public License for more details.
3811 
3812 // You should have received a copy of the GNU Lesser General Public
3813 // License along with this library; if not, write to the Free Software
3814 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
void parse(const std::string &)
Definition: vector.h:5217
Vector< double > calculate_output_layer_combination(const size_t &, const Vector< double > &) const
void randomize_uniform(const double &=-1.0, const double &=1.0)
Definition: vector.h:781
void set_layer_perceptrons_number(const size_t &, const size_t &)
tinyxml2::XMLDocument * to_XML(void) const
Vector< size_t > count_layers_parameters_numbers(void) const
Vector< std::string > write_layers_activation_function(void) const
bool is_empty(void) const
Returns true if the number of layers in the multilayer perceptron is zero, and false otherwise...
Vector< Perceptron::ActivationFunction > get_layers_activation_function(void) const
Returns the activation function of every layer in a single vector.
const Vector< PerceptronLayer > & get_layers(void) const
std::string write_expression(const Vector< std::string > &, const Vector< std::string > &) const
void set_layers_activation_function(const Vector< Perceptron::ActivationFunction > &)
Vector< Vector< double > > arrange_layers_biases(void) const
Matrix< double > calculate_interlayer_combination_combination_Jacobian(const size_t &, const size_t &, const Vector< double > &) const
Vector< T > take_out(const size_t &, const size_t &) const
Definition: vector.h:4928
void initialize_synaptic_weights(const double &)
size_t get_layer_synaptic_weight_index(const size_t &, const size_t &, const size_t &) const
Vector< Vector< Matrix< double > > > calculate_layers_Hessian_form(const Vector< double > &) const
size_t get_layer_bias_index(const size_t &, const size_t &) const
size_t get_inputs_number(void) const
Returns the number of inputs to the multilayer perceptron.
Matrix< size_t > arrange_parameters_indices(void) const
Matrix< Matrix< double > > calculate_interlayers_combination_combination_Jacobian(const Vector< double > &) const
void set(void)
Sets the size of a vector to zero.
Definition: vector.h:656
size_t get_layers_number(void) const
Returns the number of layers in the multilayer perceptron.
Vector< double > calculate_layer_combination_combination(const size_t &, const Vector< double > &) const
void from_XML(const tinyxml2::XMLDocument &)
Vector< Matrix< double > > calculate_layers_combination_Jacobian(const Vector< double > &) const
void perturbate_parameters(const double &)
Vector< size_t > arrange_layers_perceptrons_numbers(void) const
Returns a vector with the size of each layer.
ActivationFunction
Enumeration of available activation functions for the perceptron neuron model.
Definition: perceptron.h:72
size_t get_outputs_number(void) const
Returns the number of outputs neurons in the multilayer perceptron.
Vector< double > calculate_outputs(const Vector< double > &) const
Vector< Vector< double > > get_layers_parameters(void) const
Matrix< Vector< Matrix< double > > > calculate_output_interlayers_Delta(const Vector< Vector< Vector< double > > > &, const Matrix< Matrix< double > > &, const Vector< Matrix< double > > &) const
Vector< Vector< double > > calculate_layers_combination(const Vector< double > &) const
void set_parameters(const Vector< double > &)
void set_diagonal(const T &)
Definition: matrix.h:1858
void set(void)
Sets an empty multilayer_perceptron_pointer architecture.
Vector< size_t > arrange_layers_parameters_number(void) const
Vector< size_t > arrange_parameter_indices(const size_t &) const
Vector< T > assemble(const Vector< T > &) const
Definition: vector.h:5110
Vector< Vector< double > > calculate_layers_input(const Vector< double > &) const
size_t count_perceptrons_number(void) const
void initialize_parameters(void)
Initializes the parameters at random with values chosen from a normal distribution with mean 0 and st...
void grow_layer(const size_t &, const size_t &)
Vector< Vector< Vector< double > > > calculate_perceptrons_combination_parameters_gradient(const Vector< Vector< double > > &) const
Vector< double > calculate_combination_gradient(const Vector< double > &) const
Returns the partial derivatives of the combination with respect to the inputs.
void set_layers_parameters(const Vector< Vector< double > > &)
double calculate_parameters_norm(void) const
Returns the norm of the vector of multilayer perceptron parameters.
const bool & get_display(void) const
const PerceptronLayer & get_layer(const size_t &) const
size_t calculate_cumulative_index(const T &) const
Definition: vector.h:1920
double calculate_norm(void) const
Returns the vector norm.
Definition: vector.h:2358
Matrix< T > assemble_columns(const Matrix< T > &) const
Definition: matrix.h:2465
Vector< size_t > arrange_architecture(void) const
void prune_layer(const size_t &, const size_t &)
std::string to_string(void) const
Returns a string representation of the current multilayer perceptron object.
Vector< Vector< double > > calculate_layers_activation_second_derivative(const Vector< double > &) const
void set_identity(const size_t &)
Definition: matrix.h:1239
Matrix< double > calculate_Jacobian(const Vector< double > &) const
PerceptronLayer * get_layer_pointer(const size_t &)
Matrix< double > calculate_layer_combination_combination_Jacobian(const size_t &, const Vector< double > &) const
Vector< PerceptronLayer > layers
Vector< size_t > get_layers_inputs_number(void) const
Returns a vector with the number of inputs of each layer.
Vector< double > calculate_interlayer_combination_combination(const size_t &, const size_t &, const Vector< double > &) const
Vector< Matrix< double > > calculate_layers_combination_parameters_Jacobian(const Vector< Vector< double > > &) const
void tuck_in(const size_t &, const Vector< T > &)
Definition: vector.h:4891
void randomize_normal(const double &=0.0, const double &=1.0)
Definition: vector.h:867
double dot(const Vector< double > &) const
Definition: vector.h:3654
void set(void)
This method set the numbers of rows and columns of the matrix to zero.
Definition: matrix.h:1101
Vector< Vector< double > > calculate_layers_activation_derivative(const Vector< double > &) const
Vector< size_t > count_cumulative_perceptrons_number(void) const
Returns a vector of size the number of layers, where each element is equal to the total number of neu...
Vector< Matrix< double > > calculate_layers_Jacobian(const Vector< double > &) const
void set_layers_perceptrons_number(const Vector< size_t > &)
Vector< Vector< double > > calculate_layers_activation(const Vector< double > &) const
Vector< Matrix< double > > calculate_output_layers_delta(const Vector< Vector< double > > &) const
void set_layers_synaptic_weights(const Vector< Matrix< double > > &)
Vector< double > dot(const Vector< double > &) const
Definition: matrix.h:5772
Matrix< std::string > write_information(void) const
size_t get_perceptron_index(const size_t &, const size_t &) const
Vector< double > arrange_parameters(void) const
Returns the values of all the biases and synaptic weights in the multilayer perceptron as a single ve...
Vector< Vector< Vector< double > > > calculate_first_order_forward_propagation(const Vector< double > &) const
Vector< size_t > arrange_layers_cumulative_parameters_number(void) const
MultilayerPerceptron & operator=(const MultilayerPerceptron &)
void set_layers(const Vector< PerceptronLayer > &)
void set_layer_activation_function(const size_t &, const Perceptron::ActivationFunction &)
Vector< Matrix< double > > calculate_Hessian_form(const Vector< double > &) const
bool operator==(const MultilayerPerceptron &) const
T calculate_sum(void) const
Returns the sum of the elements in the vector.
Definition: vector.h:2005
bool display
Display messages to screen.
void set_layers_biases(const Vector< Vector< double > > &)
std::string to_string(const std::string &=" ") const
Returns a string representation of this vector.
Definition: vector.h:5255
size_t get_layer_index(const size_t &) const
Vector< Vector< Vector< double > > > calculate_second_order_forward_propagation(const Vector< double > &) const
Vector< Matrix< double > > arrange_layers_synaptic_weights(void) const
Vector< Vector< double > > arrange_layers_input(const Vector< double > &, const Vector< Vector< double > > &) const
size_t count_parameters_number(void) const
Returns the number of parameters (biases and synaptic weights) in the multilayer perceptron.