OpenNN  2.2
Open Neural Networks Library
conjugate_gradient.cpp
1 /****************************************************************************************************************/
2 /* */
3 /* OpenNN: Open Neural Networks Library */
4 /* www.artelnics.com/opennn */
5 /* */
6 /* C O N J U G A T E G R A D I E N T 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 "conjugate_gradient.h"
17 
18 namespace OpenNN
19 {
20 
21 // DEFAULT CONSTRUCTOR
22 
26 
28 {
29  set_default();
30 }
31 
32 
33 // GENERAL CONSTRUCTOR
34 
39 
40 ConjugateGradient::ConjugateGradient(PerformanceFunctional* new_performance_functional_pointer)
41 : TrainingAlgorithm(new_performance_functional_pointer)
42 {
43  training_rate_algorithm.set_performance_functional_pointer(new_performance_functional_pointer);
44 
45  set_default();
46 }
47 
48 
49 // XML CONSTRUCTOR
50 
55 
56 ConjugateGradient::ConjugateGradient(const tinyxml2::XMLDocument& conjugate_gradient_document)
57  : TrainingAlgorithm(conjugate_gradient_document)
58 {
59  set_default();
60 
61  from_XML(conjugate_gradient_document);
62 }
63 
64 
65 // DESTRUCTOR
66 
68 
70 {
71 }
72 
73 
74 // METHODS
75 
76 // const TrainingRateAlgorithm& get_training_rate_algorithm(void) const method
77 
79 
81 {
83 }
84 
85 
86 // TrainingRateAlgorithm* get_training_rate_algorithm_pointer(void) method
87 
89 
91 {
92  return(&training_rate_algorithm);
93 }
94 
95 
96 // TrainingDirectionMethod get_training_direction_method(void) const method
97 
99 
101 {
103 }
104 
105 
106 // std::string write_training_direction_method(void) const method
107 
109 
111 {
113  {
114  case PR:
115  {
116  return("PR");
117  }
118  break;
119 
120  case FR:
121  {
122  return("FR");
123  }
124  break;
125 
126  default:
127  {
128  std::ostringstream buffer;
129 
130  buffer << "OpenNN Exception: ConjugateGradient class.\n"
131  << "std::string write_training_direction_method(void) const method.\n"
132  << "Unknown training direction method.\n";
133 
134  throw std::logic_error(buffer.str());
135  }
136  break;
137  }
138 }
139 
140 
141 // const double& get_warning_parameters_norm(void) const method
142 
144 
146 {
147  return(warning_parameters_norm);
148 }
149 
150 
151 // const double& get_warning_gradient_norm(void) const method
152 
154 
156 {
157  return(warning_gradient_norm);
158 }
159 
160 
161 // const double& get_warning_training_rate(void) const method
162 
164 
166 {
167  return(warning_training_rate);
168 }
169 
170 
171 // const double& get_error_parameters_norm(void) const method
172 
174 
176 {
177  return(error_parameters_norm);
178 }
179 
180 
181 // const double& get_error_gradient_norm(void) const method
182 
185 
187 {
188  return(error_gradient_norm);
189 }
190 
191 
192 // const double& get_error_training_rate(void) const method
193 
196 
198 {
199  return(error_training_rate);
200 }
201 
202 
203 // const double& get_minimum_parameters_increment_norm(void) const method
204 
206 
208 {
210 }
211 
212 
213 // const double& get_minimum_performance_increase(void) const method
214 
216 
218 {
220 }
221 
222 
223 // const double& get_performance_goal(void) const method
224 
227 
229 {
230  return(performance_goal);
231 }
232 
233 
234 // const double& get_gradient_norm_goal(void) const method
235 
238 
240 {
241  return(gradient_norm_goal);
242 }
243 
244 
245 // const size_t& get_maximum_generalization_performance_decreases(void) const method
246 
248 
250 {
252 }
253 
254 
255 // const size_t& get_maximum_iterations_number(void) const method
256 
258 
260 {
262 }
263 
264 
265 // const double& get_maximum_time(void) const method
266 
268 
269 const double& ConjugateGradient::get_maximum_time(void) const
270 {
271  return(maximum_time);
272 }
273 
274 
275 // const bool& get_reserve_parameters_history(void) const method
276 
278 
280 {
282 }
283 
284 
285 // const bool& get_reserve_parameters_norm_history(void) const method
286 
288 
290 {
292 }
293 
294 
295 // const bool& get_reserve_performance_history(void) const method
296 
298 
300 {
302 }
303 
304 
305 // const bool& get_reserve_gradient_history(void) const method
306 
308 
310 {
311  return(reserve_gradient_history);
312 }
313 
314 
315 // const bool& get_reserve_gradient_norm_history(void) const method
316 
318 
320 {
322 }
323 
324 
325 
326 // const bool& get_reserve_training_direction_history(void) const method
327 
329 
331 {
333 }
334 
335 
336 // const bool& get_reserve_training_rate_history(void) const method
337 
339 
341 {
343 }
344 
345 
346 // const bool& get_reserve_elapsed_time_history(void) const method
347 
349 
351 {
353 }
354 
355 
356 // const bool& get_reserve_generalization_performance_history(void) const method
357 
359 
361 {
363 }
364 
365 
366 // void set_performance_functional_pointer(PerformanceFunctional*) method
367 
371 
373 {
374  performance_functional_pointer = new_performance_functional_pointer;
375 
376  training_rate_algorithm.set_performance_functional_pointer(new_performance_functional_pointer);
377 }
378 
379 
380 // void set_training_direction_method(const TrainingDirectionMethod&) method
381 
384 
386 (const ConjugateGradient::TrainingDirectionMethod& new_training_direction_method)
387 {
388  training_direction_method = new_training_direction_method;
389 }
390 
391 
392 // void set_training_direction_method(const std::string&) method
393 
401 
402 void ConjugateGradient::set_training_direction_method(const std::string& new_training_direction_method_name)
403 {
404  if(new_training_direction_method_name == "PR")
405  {
407  }
408  else if(new_training_direction_method_name == "FR")
409  {
411  }
412  else
413  {
414  std::ostringstream buffer;
415 
416  buffer << "OpenNN Exception: ConjugateGradient class.\n"
417  << "void set_training_direction_method(const std::string&) method.\n"
418  << "Unknown training direction method: " << new_training_direction_method_name << ".\n";
419 
420  throw std::logic_error(buffer.str());
421  }
422 }
423 
424 
425 // void set_reserve_all_training_history(bool) method
426 
442 
443 void ConjugateGradient::set_reserve_all_training_history(const bool& new_reserve_all_training_history)
444 {
445 
446  // Multilayer perceptron
447 
448  reserve_parameters_history = new_reserve_all_training_history;
449  reserve_parameters_norm_history = new_reserve_all_training_history;
450 
451  // Performance functional
452 
453  reserve_performance_history = new_reserve_all_training_history;
454  reserve_gradient_history = new_reserve_all_training_history;
455  reserve_gradient_norm_history = new_reserve_all_training_history;
456 
457  reserve_generalization_performance_history = new_reserve_all_training_history;
458 
459  // Training algorithm
460 
461  reserve_training_direction_history = new_reserve_all_training_history;
462  reserve_training_rate_history = new_reserve_all_training_history;
463  reserve_elapsed_time_history = new_reserve_all_training_history;
464 }
465 
466 
467 // void set_default(void) method
468 
503 
505 {
506  // TRAINING PARAMETERS
507 
508  warning_parameters_norm = 1.0e6;
509  warning_gradient_norm = 1.0e6;
510  warning_training_rate = 1.0e6;
511 
512  error_parameters_norm = 1.0e9;
513  error_gradient_norm = 1.0e9;
514  error_training_rate = 1.0e9;
515 
516  // STOPPING CRITERIA
517 
519 
521  performance_goal = -1.0e99;
522  gradient_norm_goal = 0.0;
524 
526  maximum_time = 1000.0;
527 
528  // TRAINING HISTORY
529 
532 
534  reserve_gradient_history = false;
537 
541 
542  // UTILITIES
543 
544  display = true;
545  display_period = 10;
546 
548 }
549 
550 
551 // void set_warning_parameters_norm(const double&) method
552 
556 
557 void ConjugateGradient::set_warning_parameters_norm(const double& new_warning_parameters_norm)
558 {
559  // Control sentence (if debug)
560 
561  #ifndef NDEBUG
562 
563  if(new_warning_parameters_norm < 0.0)
564  {
565  std::ostringstream buffer;
566 
567  buffer << "OpenNN Exception: ConjugateGradient class.\n"
568  << "void set_warning_parameters_norm(const double&) method.\n"
569  << "Warning parameters norm must be equal or greater than 0.\n";
570 
571  throw std::logic_error(buffer.str());
572  }
573 
574  #endif
575 
576  // Set warning parameters norm
577 
578  warning_parameters_norm = new_warning_parameters_norm;
579 }
580 
581 
582 // void set_warning_gradient_norm(const double&) method
583 
587 
588 void ConjugateGradient::set_warning_gradient_norm(const double& new_warning_gradient_norm)
589 {
590  // Control sentence (if debug)
591 
592  #ifndef NDEBUG
593 
594  if(new_warning_gradient_norm < 0.0)
595  {
596  std::ostringstream buffer;
597 
598  buffer << "OpenNN Exception: ConjugateGradient class.\n"
599  << "void set_warning_gradient_norm(const double&) method.\n"
600  << "Warning gradient norm must be equal or greater than 0.\n";
601 
602  throw std::logic_error(buffer.str());
603  }
604 
605  #endif
606 
607  // Set warning gradient norm
608 
609  warning_gradient_norm = new_warning_gradient_norm;
610 }
611 
612 
613 // void set_warning_training_rate(const double&) method
614 
618 
619 void ConjugateGradient::set_warning_training_rate(const double& new_warning_training_rate)
620 {
621  // Control sentence (if debug)
622 
623  #ifndef NDEBUG
624 
625  if(new_warning_training_rate < 0.0)
626  {
627  std::ostringstream buffer;
628 
629  buffer << "OpenNN Exception: ConjugateGradient class.\n"
630  << "void set_warning_training_rate(const double&) method.\n"
631  << "Warning training rate must be equal or greater than 0.\n";
632 
633  throw std::logic_error(buffer.str());
634  }
635 
636  #endif
637 
638  warning_training_rate = new_warning_training_rate;
639 }
640 
641 
642 // void set_error_parameters_norm(const double&) method
643 
647 
648 void ConjugateGradient::set_error_parameters_norm(const double& new_error_parameters_norm)
649 {
650  // Control sentence (if debug)
651 
652  #ifndef NDEBUG
653 
654  if(new_error_parameters_norm < 0.0)
655  {
656  std::ostringstream buffer;
657 
658  buffer << "OpenNN Exception: ConjugateGradient class.\n"
659  << "void set_error_parameters_norm(const double&) method.\n"
660  << "Error parameters norm must be equal or greater than 0.\n";
661 
662  throw std::logic_error(buffer.str());
663  }
664 
665  #endif
666 
667  // Set error parameters norm
668 
669  error_parameters_norm = new_error_parameters_norm;
670 }
671 
672 
673 // void set_error_gradient_norm(const double&) method
674 
678 
679 void ConjugateGradient::set_error_gradient_norm(const double& new_error_gradient_norm)
680 {
681  // Control sentence (if debug)
682 
683  #ifndef NDEBUG
684 
685  if(new_error_gradient_norm < 0.0)
686  {
687  std::ostringstream buffer;
688 
689  buffer << "OpenNN Exception: ConjugateGradient class.\n"
690  << "void set_error_gradient_norm(const double&) method.\n"
691  << "Error gradient norm must be equal or greater than 0.\n";
692 
693  throw std::logic_error(buffer.str());
694  }
695 
696  #endif
697 
698  // Set error gradient norm
699 
700  error_gradient_norm = new_error_gradient_norm;
701 }
702 
703 
704 // void set_error_training_rate(const double&) method
705 
709 
710 void ConjugateGradient::set_error_training_rate(const double& new_error_training_rate)
711 {
712  // Control sentence (if debug)
713 
714  #ifndef NDEBUG
715 
716  if(new_error_training_rate < 0.0)
717  {
718  std::ostringstream buffer;
719 
720  buffer << "OpenNN Exception: ConjugateGradient class.\n"
721  << "void set_error_training_rate(const double&) method.\n"
722  << "Error training rate must be equal or greater than 0.\n";
723 
724  throw std::logic_error(buffer.str());
725  }
726 
727  #endif
728 
729  // Set error training rate
730 
731  error_training_rate = new_error_training_rate;
732 }
733 
734 
735 // void set_minimum_parameters_increment_norm(const double&) method
736 
739 
740 void ConjugateGradient::set_minimum_parameters_increment_norm(const double& new_minimum_parameters_increment_norm)
741 {
742  // Control sentence (if debug)
743 
744  #ifndef NDEBUG
745 
746  if(new_minimum_parameters_increment_norm < 0.0)
747  {
748  std::ostringstream buffer;
749 
750  buffer << "OpenNN Exception: ConjugateGradient class.\n"
751  << "void new_minimum_parameters_increment_norm(const double&) method.\n"
752  << "Minimum parameters increment norm must be equal or greater than 0.\n";
753 
754  throw std::logic_error(buffer.str());
755  }
756 
757  #endif
758 
759  // Set error training rate
760 
761  minimum_parameters_increment_norm = new_minimum_parameters_increment_norm;
762 }
763 
764 
765 // void set_minimum_performance_increase(const double&) method
766 
769 
770 void ConjugateGradient::set_minimum_performance_increase(const double& new_minimum_performance_increase)
771 {
772  // Control sentence (if debug)
773 
774  #ifndef NDEBUG
775 
776  if(new_minimum_performance_increase < 0.0)
777  {
778  std::ostringstream buffer;
779 
780  buffer << "OpenNN Exception: ConjugateGradient class.\n"
781  << "void set_minimum_performance_increase(const double&) method.\n"
782  << "Minimum performance improvement must be equal or greater than 0.\n";
783 
784  throw std::logic_error(buffer.str());
785  }
786 
787  #endif
788 
789  // Set minimum performance improvement
790 
791  minimum_performance_increase = new_minimum_performance_increase;
792 }
793 
794 
795 // void set_performance_goal(const double&) method
796 
800 
801 void ConjugateGradient::set_performance_goal(const double& new_performance_goal)
802 {
803  performance_goal = new_performance_goal;
804 }
805 
806 
807 // void set_gradient_norm_goal(const double&) method
808 
812 
813 void ConjugateGradient::set_gradient_norm_goal(const double& new_gradient_norm_goal)
814 {
815  // Control sentence (if debug)
816 
817  #ifndef NDEBUG
818 
819  if(new_gradient_norm_goal < 0.0)
820  {
821  std::ostringstream buffer;
822 
823  buffer << "OpenNN Exception: ConjugateGradient class.\n"
824  << "void set_gradient_norm_goal(const double&) method.\n"
825  << "Gradient norm goal must be equal or greater than 0.\n";
826 
827  throw std::logic_error(buffer.str());
828  }
829 
830  #endif
831 
832  // Set gradient norm goal
833 
834  gradient_norm_goal = new_gradient_norm_goal;
835 }
836 
837 
838 // void set_maximum_generalization_performance_decreases(const size_t&) method
839 
842 
843 void ConjugateGradient::set_maximum_generalization_performance_decreases(const size_t& new_maximum_generalization_performance_decreases)
844 {
845  maximum_generalization_performance_decreases = new_maximum_generalization_performance_decreases;
846 }
847 
848 
849 // void set_maximum_iterations_number(size_t) method
850 
853 
854 void ConjugateGradient::set_maximum_iterations_number(const size_t& new_maximum_iterations_number)
855 {
856  maximum_iterations_number = new_maximum_iterations_number;
857 }
858 
859 
860 // void set_maximum_time(const double&) method
861 
864 
865 void ConjugateGradient::set_maximum_time(const double& new_maximum_time)
866 {
867  // Control sentence (if debug)
868 
869  #ifndef NDEBUG
870 
871  if(new_maximum_time < 0.0)
872  {
873  std::ostringstream buffer;
874 
875  buffer << "OpenNN Exception: ConjugateGradient class.\n"
876  << "void set_maximum_time(const double&) method.\n"
877  << "Maximum time must be equal or greater than 0.\n";
878 
879  throw std::logic_error(buffer.str());
880  }
881 
882  #endif
883 
884  // Set maximum time
885 
886  maximum_time = new_maximum_time;
887 }
888 
889 
890 // void set_reserve_parameters_history(bool) method
891 
894 
895 void ConjugateGradient::set_reserve_parameters_history(const bool& new_reserve_parameters_history)
896 {
897  reserve_parameters_history = new_reserve_parameters_history;
898 }
899 
900 
901 // void set_reserve_parameters_norm_history(bool) method
902 
905 
906 void ConjugateGradient::set_reserve_parameters_norm_history(const bool& new_reserve_parameters_norm_history)
907 {
908  reserve_parameters_norm_history = new_reserve_parameters_norm_history;
909 }
910 
911 
912 // void set_reserve_performance_history(bool) method
913 
916 
917 void ConjugateGradient::set_reserve_performance_history(const bool& new_reserve_performance_history)
918 {
919  reserve_performance_history = new_reserve_performance_history;
920 }
921 
922 
923 // void set_reserve_gradient_history(bool) method
924 
927 
928 void ConjugateGradient::set_reserve_gradient_history(const bool& new_reserve_gradient_history)
929 {
930  reserve_gradient_history = new_reserve_gradient_history;
931 }
932 
933 
934 // void set_reserve_gradient_norm_history(bool) method
935 
939 
940 void ConjugateGradient::set_reserve_gradient_norm_history(const bool& new_reserve_gradient_norm_history)
941 {
942  reserve_gradient_norm_history = new_reserve_gradient_norm_history;
943 }
944 
945 
946 // void set_reserve_training_direction_history(bool) method
947 
951 
952 void ConjugateGradient::set_reserve_training_direction_history(const bool& new_reserve_training_direction_history)
953 {
954  reserve_training_direction_history = new_reserve_training_direction_history;
955 }
956 
957 
958 // void set_reserve_training_rate_history(bool) method
959 
963 
964 void ConjugateGradient::set_reserve_training_rate_history(const bool& new_reserve_training_rate_history)
965 {
966  reserve_training_rate_history = new_reserve_training_rate_history;
967 }
968 
969 
970 // void set_reserve_elapsed_time_history(bool) method
971 
975 
976 void ConjugateGradient::set_reserve_elapsed_time_history(const bool& new_reserve_elapsed_time_history)
977 {
978  reserve_elapsed_time_history = new_reserve_elapsed_time_history;
979 }
980 
981 
982 // void set_reserve_generalization_performance_history(bool) method
983 
987 
988 void ConjugateGradient::set_reserve_generalization_performance_history(const bool& new_reserve_generalization_performance_history)
989 {
990  reserve_generalization_performance_history = new_reserve_generalization_performance_history;
991 }
992 
993 
994 // void set_display_period(const size_t&) method
995 
999 
1000 void ConjugateGradient::set_display_period(const size_t& new_display_period)
1001 {
1002  // Control sentence (if debug)
1003 
1004  #ifndef NDEBUG
1005 
1006  if(new_display_period <= 0)
1007  {
1008  std::ostringstream buffer;
1009 
1010  buffer << "OpenNN Exception: ConjugateGradient class.\n"
1011  << "void set_display_period(const double&) method.\n"
1012  << "Display period must be greater than 0.\n";
1013 
1014  throw std::logic_error(buffer.str());
1015  }
1016 
1017  #endif
1018 
1019  display_period = new_display_period;
1020 }
1021 
1022 
1023 // void set_save_period(size_t) method
1024 
1028 
1029 void ConjugateGradient::set_save_period(const size_t& new_save_period)
1030 {
1031  // Control sentence (if debug)
1032 
1033  #ifndef NDEBUG
1034 
1035  if(new_save_period <= 0)
1036  {
1037  std::ostringstream buffer;
1038 
1039  buffer << "OpenNN Exception: ConjugateGradient class.\n"
1040  << "void set_save_period(const double&) method.\n"
1041  << "Save period must be greater than 0.\n";
1042 
1043  throw std::logic_error(buffer.str());
1044  }
1045 
1046  #endif
1047 
1048  save_period = new_save_period;
1049 }
1050 
1051 
1052 // double calculate_FR_parameter(const Vector<double>&, const Vector<double>&) const method
1053 
1058 
1059 double ConjugateGradient::calculate_FR_parameter(const Vector<double>& old_gradient, const Vector<double>& gradient) const
1060 {
1061  // Control sentence (if debug)
1062 
1063  #ifndef NDEBUG
1064 
1065  std::ostringstream buffer;
1066 
1068  {
1069  buffer << "OpenNN Exception: ConjugateGradient class.\n"
1070  << "double calculate_FR_parameter(const Vector<double>&, const Vector<double>&) const method.\n"
1071 
1072  << "Performance functional pointer is NULL.\n";
1073 
1074  throw std::logic_error(buffer.str());
1075  }
1076 
1077  const NeuralNetwork* neural_network_pointer = performance_functional_pointer->get_neural_network_pointer();
1078 
1079  const size_t parameters_number = neural_network_pointer->count_parameters_number();
1080 
1081  const size_t old_gradient_size = old_gradient.size();
1082 
1083  if(old_gradient_size != parameters_number)
1084  {
1085  buffer << "OpenNN Exception: ConjugateGradient class.\n"
1086  << "double calculate_FR_parameter(const Vector<double>&, const Vector<double>&) const method.\n"
1087  << "Size of old gradient (" << old_gradient_size << ") is not equal to number of parameters (" << parameters_number << ").\n";
1088 
1089  throw std::logic_error(buffer.str());
1090  }
1091 
1092  const size_t gradient_size = gradient.size();
1093 
1094  if(gradient_size != parameters_number)
1095  {
1096  buffer << "OpenNN Exception: ConjugateGradient class.\n"
1097  << "double calculate_FR_parameter(const Vector<double>&, const Vector<double>&) const method.\n"
1098  << "Size of gradient (" << gradient_size << ") is not equal to number of parameters (" << parameters_number << ").\n";
1099 
1100  throw std::logic_error(buffer.str());
1101  }
1102 
1103  #endif
1104 
1105  double FR_parameter = 0.0;
1106 
1107  const double numerator = gradient.dot(gradient);
1108  const double denominator = old_gradient.dot(old_gradient);
1109 
1110  // Prevent a possible division by 0
1111 
1112  if(denominator == 0.0)
1113  {
1114  FR_parameter = 0.0;
1115  }
1116  else
1117  {
1118  FR_parameter = numerator/denominator;
1119  }
1120 
1121  // Bound the Fletcher-Reeves parameter between 0 and 1
1122 
1123  if(FR_parameter < 0.0)
1124  FR_parameter = 0.0;
1125 
1126  if(FR_parameter > 1.0)
1127  FR_parameter = 1.0;
1128 
1129  return(FR_parameter);
1130 }
1131 
1132 
1133 // double calculate_PR_parameter(const Vector<double>&, const Vector<double>&) const method
1134 
1138 
1139 double ConjugateGradient::calculate_PR_parameter(const Vector<double>& old_gradient, const Vector<double>& gradient) const
1140 {
1141  // Control sentence (if debug)
1142 
1143  #ifndef NDEBUG
1144 
1145  std::ostringstream buffer;
1146 
1148  {
1149  buffer << "OpenNN Exception: ConjugateGradient class.\n"
1150  << "double calculate_PR_parameter(const Vector<double>&, const Vector<double>&) const method.\n"
1151 
1152  << "Performance functional pointer is NULL.\n";
1153 
1154  throw std::logic_error(buffer.str());
1155  }
1156 
1157  const NeuralNetwork* neural_network_pointer = performance_functional_pointer->get_neural_network_pointer();
1158 
1159  const size_t parameters_number = neural_network_pointer->count_parameters_number();
1160 
1161  const size_t old_gradient_size = old_gradient.size();
1162 
1163  if(old_gradient_size != parameters_number)
1164  {
1165  buffer << "OpenNN Exception: ConjugateGradient class.\n"
1166  << "double calculate_PR_parameter(const Vector<double>&, const Vector<double>&) const method.\n"
1167  << "Size of old gradient (" << old_gradient_size << ") is not equal to number of parameters (" << parameters_number << ").\n";
1168 
1169  throw std::logic_error(buffer.str());
1170  }
1171 
1172  const size_t gradient_size = gradient.size();
1173 
1174  if(gradient_size != parameters_number)
1175  {
1176  buffer << "OpenNN Exception: ConjugateGradient class.\n"
1177  << "double calculate_PR_parameter(const Vector<double>&, const Vector<double>&) const method.\n"
1178  << "Size of gradient (" << gradient_size << ") is not equal to number of parameters (" << parameters_number << ").\n";
1179 
1180  throw std::logic_error(buffer.str());
1181  }
1182 
1183  #endif
1184 
1185  double PR_parameter = 0.0;
1186 
1187  const double numerator = (gradient-old_gradient).dot(gradient);
1188  const double denominator = old_gradient.dot(old_gradient);
1189 
1190  // Prevent a possible division by 0
1191 
1192  if(denominator == 0.0)
1193  {
1194  PR_parameter = 0.0;
1195  }
1196  else
1197  {
1198  PR_parameter = numerator/denominator;
1199  }
1200 
1201  // Bound the Polak-Ribiere parameter between 0 and 1
1202 
1203  if(PR_parameter < 0.0)
1204  {
1205  PR_parameter = 0.0;
1206  }
1207 
1208  if(PR_parameter > 1.0)
1209  {
1210  PR_parameter = 1.0;
1211  }
1212 
1213  return(PR_parameter);
1214 }
1215 
1216 
1217 // Vector<double> calculate_PR_training_direction(const Vector<double>&, const Vector<double>&, const Vector<double>&) const method
1218 
1223 
1225 (const Vector<double>& old_gradient, const Vector<double>& gradient, const Vector<double>& old_training_direction) const
1226 {
1227  // Control sentence (if debug)
1228 
1229  #ifndef NDEBUG
1230 
1231  std::ostringstream buffer;
1232 
1233  if(!performance_functional_pointer)
1234  {
1235  buffer << "OpenNN Exception: ConjugateGradient class.\n"
1236  << "Vector<double> calculate_PR_training_direction(const Vector<double>&, const Vector<double>&, const Vector<double>&) const method.\n"
1237  << "Performance functional pointer is NULL.\n";
1238 
1239  throw std::logic_error(buffer.str());
1240  }
1241 
1242  const NeuralNetwork* neural_network_pointer = performance_functional_pointer->get_neural_network_pointer();
1243 
1244  const size_t parameters_number = neural_network_pointer->count_parameters_number();
1245 
1246  const size_t old_gradient_size = old_gradient.size();
1247 
1248  if(old_gradient_size != parameters_number)
1249  {
1250  buffer << "OpenNN Exception: ConjugateGradient class.\n"
1251  << "Vector<double> calculate_PR_training_direction(const Vector<double>&, const Vector<double>&, const Vector<double>&) const method.\n"
1252  << "Size of old gradient (" << old_gradient_size << ") is not equal to number of parameters (" << parameters_number << ").\n";
1253 
1254  throw std::logic_error(buffer.str());
1255  }
1256 
1257  const size_t gradient_size = gradient.size();
1258 
1259  if(gradient_size != parameters_number)
1260  {
1261  buffer << "OpenNN Exception: ConjugateGradient class.\n"
1262  << "Vector<double> calculate_PR_training_direction(const Vector<double>&, const Vector<double>&, const Vector<double>&) const method.\n"
1263  << "Size of gradient (" << gradient_size << ") is not equal to number of parameters (" << parameters_number << ").\n";
1264 
1265  throw std::logic_error(buffer.str());
1266  }
1267 
1268  const size_t old_training_direction_size = old_training_direction.size();
1269 
1270  if(old_training_direction_size != parameters_number)
1271  {
1272  buffer << "OpenNN Exception: ConjugateGradient class.\n"
1273  << "Vector<double> calculate_PR_training_direction(const Vector<double>&, const Vector<double>&, const Vector<double>&) const method.\n"
1274  << "Size of old training direction (" << old_training_direction_size << ") is not equal to number of parameters (" << parameters_number << ").\n";
1275 
1276  throw std::logic_error(buffer.str());
1277  }
1278 
1279  #endif
1280 
1281  const double PR_parameter = calculate_PR_parameter(old_gradient, gradient);
1282 
1283  const Vector<double> gradient_descent_term = calculate_gradient_descent_training_direction(gradient);
1284  const Vector<double> conjugate_direction_term = old_training_direction*PR_parameter;
1285 
1286  const Vector<double> PR_training_direction = gradient_descent_term + conjugate_direction_term;
1287 
1288  const double PR_training_direction_norm = PR_training_direction.calculate_norm();
1289 
1290  return(PR_training_direction/PR_training_direction_norm);
1291 }
1292 
1293 
1294 // Vector<double> calculate_FR_training_direction(const Vector<double>&, const Vector<double>&, const Vector<double>&) const method
1295 
1300 
1302 (const Vector<double>& old_gradient, const Vector<double>& gradient, const Vector<double>& old_training_direction) const
1303 {
1304  // Control sentence (if debug)
1305 
1306  #ifndef NDEBUG
1307 
1308  std::ostringstream buffer;
1309 
1310  if(!performance_functional_pointer)
1311  {
1312  buffer << "OpenNN Exception: ConjugateGradient class.\n"
1313  << "Vector<double> calculate_FR_training_direction(const Vector<double>&, const Vector<double>&, const Vector<double>&) const method.\n"
1314  << "Performance functional pointer is NULL.\n";
1315 
1316  throw std::logic_error(buffer.str());
1317  }
1318 
1319  const NeuralNetwork* neural_network_pointer = performance_functional_pointer->get_neural_network_pointer();
1320 
1321  const size_t parameters_number = neural_network_pointer->count_parameters_number();
1322 
1323  const size_t old_gradient_size = old_gradient.size();
1324 
1325  if(old_gradient_size != parameters_number)
1326  {
1327  buffer << "OpenNN Exception: ConjugateGradient class.\n"
1328  << "Vector<double> calculate_FR_training_direction(const Vector<double>&, const Vector<double>&, const Vector<double>&) const method.\n"
1329  << "Size of old gradient (" << old_gradient_size << ") is not equal to number of parameters (" << parameters_number << ").\n";
1330 
1331  throw std::logic_error(buffer.str());
1332  }
1333 
1334  const size_t gradient_size = gradient.size();
1335 
1336  if(gradient_size != parameters_number)
1337  {
1338  buffer << "OpenNN Exception: ConjugateGradient class.\n"
1339  << "Vector<double> calculate_FR_training_direction(const Vector<double>&, const Vector<double>&, const Vector<double>&) const method.\n"
1340  << "Size of gradient (" << gradient_size << ") is not equal to number of parameters (" << parameters_number << ").\n";
1341 
1342  throw std::logic_error(buffer.str());
1343  }
1344 
1345  const size_t old_training_direction_size = old_training_direction.size();
1346 
1347  if(old_training_direction_size != parameters_number)
1348  {
1349  buffer << "OpenNN Exception: ConjugateGradient class.\n"
1350  << "Vector<double> calculate_FR_training_direction(const Vector<double>&, const Vector<double>&, const Vector<double>&) const method.\n"
1351  << "Size of old training direction (" << old_training_direction_size << ") is not equal to number of parameters (" << parameters_number << ").\n";
1352 
1353  throw std::logic_error(buffer.str());
1354  }
1355 
1356  #endif
1357 
1358  const double FR_parameter = calculate_FR_parameter(old_gradient, gradient);
1359 
1360  const Vector<double> gradient_descent_term = calculate_gradient_descent_training_direction(gradient);
1361  const Vector<double> conjugate_direction_term = old_training_direction*FR_parameter;
1362 
1363  const Vector<double> FR_training_direction = gradient_descent_term + conjugate_direction_term;
1364 
1365  const double FR_training_direction_norm = FR_training_direction.calculate_norm();
1366 
1367  return(FR_training_direction/FR_training_direction_norm);
1368 }
1369 
1370 
1371 // Vector<double> calculate_training_direction(const Vector<double>&, const Vector<double>&, const Vector<double>&) const method
1372 
1377 
1379 (const Vector<double>& old_gradient, const Vector<double>& gradient, const Vector<double>& old_training_direction) const
1380 {
1381  const NeuralNetwork* neural_network_pointer = performance_functional_pointer->get_neural_network_pointer();
1382 
1383  const size_t parameters_number = neural_network_pointer->count_parameters_number();
1384 
1385  // Control sentence (if debug)
1386 
1387  #ifndef NDEBUG
1388 
1389  std::ostringstream buffer;
1390 
1391  if(!performance_functional_pointer)
1392  {
1393  buffer << "OpenNN Exception: ConjugateGradient class.\n"
1394  << "Vector<double> calculate_training_direction(const Vector<double>&, const Vector<double>&, const Vector<double>&) const method.\n"
1395  << "Performance functional pointer is NULL.\n";
1396 
1397  throw std::logic_error(buffer.str());
1398  }
1399 
1400  const size_t old_gradient_size = old_gradient.size();
1401 
1402  if(old_gradient_size != parameters_number)
1403  {
1404  buffer << "OpenNN Exception: ConjugateGradient class.\n"
1405  << "Vector<double> calculate_training_direction(const Vector<double>&, const Vector<double>&, const Vector<double>&) const method.\n"
1406  << "Size of old gradient (" << old_gradient_size << ") is not equal to number of parameters (" << parameters_number << ").\n";
1407 
1408  throw std::logic_error(buffer.str());
1409  }
1410 
1411  const size_t gradient_size = gradient.size();
1412 
1413  if(gradient_size != parameters_number)
1414  {
1415  buffer << "OpenNN Exception: ConjugateGradient class.\n"
1416  << "Vector<double> calculate_training_direction(const Vector<double>&, const Vector<double>&, const Vector<double>&) const method.\n"
1417  << "Size of gradient (" << gradient_size << ") is not equal to number of parameters (" << parameters_number << ").\n";
1418 
1419  throw std::logic_error(buffer.str());
1420  }
1421 
1422  const size_t old_training_direction_size = old_training_direction.size();
1423 
1424  if(old_training_direction_size != parameters_number)
1425  {
1426  buffer << "OpenNN Exception: ConjugateGradient class.\n"
1427  << "Vector<double> calculate_training_direction(const Vector<double>&, const Vector<double>&, const Vector<double>&) const method.\n"
1428  << "Size of old training direction (" << old_training_direction_size << ") is not equal to number of parameters (" << parameters_number << ").\n";
1429 
1430  throw std::logic_error(buffer.str());
1431  }
1432 
1433  #endif
1434 
1435  switch(training_direction_method)
1436  {
1437  case FR:
1438  {
1439  return(calculate_FR_training_direction(old_gradient, gradient, old_training_direction));
1440  }
1441  break;
1442 
1443  case PR:
1444  {
1445  return(calculate_PR_training_direction(old_gradient, gradient, old_training_direction));
1446  }
1447  break;
1448 
1449  default:
1450  {
1451  std::ostringstream buffer;
1452 
1453  buffer << "OpenNN Exception: ConjugateGradient class.\n"
1454  << "Vector<double> calculate_training_direction(const Vector<double>&, const Vector<double>&, const Vector<double>&) const method.\n"
1455  << "Unknown training direction method: " << training_direction_method << ".\n";
1456 
1457  throw std::logic_error(buffer.str());
1458  }
1459  break;
1460  }
1461 
1462  // Never reach here
1463 
1464  const Vector<double> training_direction(parameters_number, 0.0);
1465 
1466  return(training_direction);
1467 
1468 }
1469 
1470 
1471 // Vector<double> calculate_gradient_descent_training_direction(const Vector<double>&) const method
1472 
1475 
1477 {
1478  // Control sentence (if debug)
1479 
1480  #ifndef NDEBUG
1481 
1482  std::ostringstream buffer;
1483 
1485  {
1486  buffer << "OpenNN Exception: ConjugateGradient class.\n"
1487  << "Vector<double> calculate_gradient_descent_training_direction(const Vector<double>&) const method.\n"
1488  << "Performance functional pointer is NULL.\n";
1489 
1490  throw std::logic_error(buffer.str());
1491  }
1492 
1493  const NeuralNetwork* neural_network_pointer = performance_functional_pointer->get_neural_network_pointer();
1494 
1495  const size_t parameters_number = neural_network_pointer->count_parameters_number();
1496 
1497  const size_t gradient_size = gradient.size();
1498 
1499  if(gradient_size != parameters_number)
1500  {
1501  buffer << "OpenNN Exception: ConjugateGradient class.\n"
1502  << "Vector<double> calculate_gradient_descent_training_direction(const Vector<double>&) const method.\n"
1503  << "Size of gradient (" << gradient_size << ") is not equal to number of parameters (" << parameters_number << ").\n";
1504 
1505  throw std::logic_error(buffer.str());
1506  }
1507 
1508  #endif
1509 
1510  return(gradient.calculate_normalized()*(-1.0));
1511 }
1512 
1513 
1514 // void resize_training_history(const size_t&) method
1515 
1518 
1520 {
1521  // Control sentence (if debug)
1522 
1523  #ifndef NDEBUG
1524 
1525  if(conjugate_gradient_pointer == NULL)
1526  {
1527  std::ostringstream buffer;
1528 
1529  buffer << "OpenNN Exception: ConjugateGradientResults structure.\n"
1530  << "void resize_training_history(const size_t&) method.\n"
1531  << "Conjugate gradient pointer is NULL.\n";
1532 
1533  throw std::logic_error(buffer.str());
1534  }
1535 
1536  #endif
1537 
1539  {
1540  parameters_history.resize(new_size);
1541  }
1542 
1544  {
1545  parameters_norm_history.resize(new_size);
1546  }
1547 
1549  {
1550  performance_history.resize(new_size);
1551  }
1552 
1554  {
1555  generalization_performance_history.resize(new_size);
1556  }
1557 
1559  {
1560  gradient_history.resize(new_size);
1561  }
1562 
1564  {
1565  gradient_norm_history.resize(new_size);
1566  }
1567 
1569  {
1570  training_direction_history.resize(new_size);
1571  }
1572 
1574  {
1575  training_rate_history.resize(new_size);
1576  }
1577 
1579  {
1580  elapsed_time_history.resize(new_size);
1581  }
1582 }
1583 
1584 
1585 // std::string to_string(void) const method
1586 
1588 {
1589  std::ostringstream buffer;
1590 
1591  // Parameters history
1592 
1593  if(!parameters_history.empty())
1594  {
1595  if(!parameters_history[0].empty())
1596  {
1597  buffer << "% Parameters history:\n"
1598  << parameters_history << "\n";
1599  }
1600  }
1601 
1602  // Parameters norm history
1603 
1604  if(!parameters_norm_history.empty())
1605  {
1606  buffer << "% Parameters norm history:\n"
1607  << parameters_norm_history << "\n";
1608  }
1609 
1610  // performance history
1611 
1612  if(!performance_history.empty())
1613  {
1614  buffer << "% performance history:\n"
1615  << performance_history << "\n";
1616  }
1617 
1618  // Generalization performance history
1619 
1620  if(!generalization_performance_history.empty())
1621  {
1622  buffer << "% Generalization performance history:\n"
1623  << generalization_performance_history << "\n";
1624  }
1625 
1626  // Gradient history
1627 
1628  if(!gradient_history.empty())
1629  {
1630  if(!gradient_history[0].empty())
1631  {
1632  buffer << "% Gradient history:\n"
1633  << gradient_history << "\n";
1634  }
1635  }
1636 
1637  // Gradient norm history
1638 
1639  if(!gradient_norm_history.empty())
1640  {
1641  buffer << "% Gradient norm history:\n"
1642  << gradient_norm_history << "\n";
1643  }
1644 
1645  // Training direction history
1646 
1647  if(!training_direction_history.empty())
1648  {
1649  if(!training_direction_history[0].empty())
1650  {
1651  buffer << "% Training direction history:\n"
1652  << training_direction_history << "\n";
1653  }
1654  }
1655 
1656  // Training rate history
1657 
1658  if(!training_rate_history.empty())
1659  {
1660  buffer << "% Training rate history:\n"
1661  << training_rate_history << "\n";
1662  }
1663 
1664  // Elapsed time history
1665 
1666  if(!elapsed_time_history.empty())
1667  {
1668  buffer << "% Elapsed time history:\n"
1669  << elapsed_time_history << "\n";
1670  }
1671 
1672  return(buffer.str());
1673 }
1674 
1675 
1676 // Matrix<std::string> write_final_results(const size_t& precision) const method
1677 
1679 {
1680  std::ostringstream buffer;
1681 
1682  Vector<std::string> names;
1683  Vector<std::string> values;
1684 
1685  // Final parameters norm
1686 
1687  names.push_back("Final parameters norm");
1688 
1689  buffer.str("");
1690  buffer << std::setprecision(precision) << final_parameters_norm;
1691 
1692  values.push_back(buffer.str());
1693 
1694  // Final performance
1695 
1696  names.push_back("Final performance");
1697 
1698  buffer.str("");
1699  buffer << std::setprecision(precision) << final_performance;
1700 
1701  values.push_back(buffer.str());
1702 
1703  // Final generalization performance
1704 
1705  const PerformanceFunctional* performance_functional_pointer = conjugate_gradient_pointer->get_performance_functional_pointer();
1706 
1707  if(performance_functional_pointer->has_generalization())
1708  {
1709  names.push_back("Final generalization performance");
1710 
1711  buffer.str("");
1712  buffer << std::setprecision(precision) << final_generalization_performance;
1713 
1714  values.push_back(buffer.str());
1715  }
1716 
1717  // Final gradient norm
1718 
1719  names.push_back("Final gradient norm");
1720 
1721  buffer.str("");
1722  buffer << std::setprecision(precision) << final_gradient_norm;
1723 
1724  values.push_back(buffer.str());
1725 
1726  // Final training rate
1727 
1728 // names.push_back("Final training rate");
1729 
1730 // buffer.str("");
1731 // buffer << std::setprecision(precision) << final_training_rate;
1732 
1733 // values.push_back(buffer.str());
1734 
1735  // Iterations number
1736 
1737  names.push_back("Iterations number");
1738 
1739  buffer.str("");
1740  buffer << iterations_number;
1741 
1742  values.push_back(buffer.str());
1743 
1744  // Elapsed time
1745 
1746  names.push_back("Elapsed time");
1747 
1748  buffer.str("");
1749  buffer << elapsed_time;
1750 
1751  values.push_back(buffer.str());
1752 
1753  const size_t rows_number = names.size();
1754  const size_t columns_number = 2;
1755 
1756  Matrix<std::string> final_results(rows_number, columns_number);
1757 
1758  final_results.set_column(0, names);
1759  final_results.set_column(1, values);
1760 
1761  return(final_results);
1762 }
1763 
1764 
1765 // ConjugateGradientResults* perform_training(void) method
1766 
1769 
1771 {
1772  // Control sentence (if debug)
1773 
1774  #ifndef NDEBUG
1775 
1776  check();
1777 
1778  #endif
1779 
1780  // Start training
1781 
1782  if(display)
1783  {
1784  std::cout << "Training with conjugate gradient...\n";
1785  }
1786 
1787  ConjugateGradientResults* results_pointer = new ConjugateGradientResults(this);
1789 
1790  // Elapsed time
1791 
1792  time_t beginning_time, current_time;
1793  time(&beginning_time);
1794  double elapsed_time;
1795 
1796  // Neural network stuff
1797 
1799 
1800  const size_t parameters_number = neural_network_pointer->count_parameters_number();
1801 
1802  Vector<double> parameters = neural_network_pointer->arrange_parameters();
1803  double parameters_norm;
1804 
1805  // Performance functional stuff
1806 
1807  double performance = 0.0;
1808  double old_performance = 0.0;
1809  double performance_increase = 0.0;
1810 
1811  Vector<double> gradient(parameters_number);
1812  double gradient_norm;
1813 
1814  double generalization_performance = 0.0;
1815  double old_generalization_performance = 0.0;
1816 
1817  std::string information;
1818 
1819  // Training algorithm stuff
1820 
1821  // const double& first_training_rate = training_rate_algorithm.get_first_training_rate();
1822  const double first_training_rate = 0.01;
1823 
1824  Vector<double> parameters_increment(parameters_number);
1825  double parameters_increment_norm;
1826 
1827  Vector<double> old_gradient(parameters_number);
1828  Vector<double> training_direction(parameters_number);
1829  Vector<double> old_training_direction(parameters_number);
1830 
1831  double training_slope;
1832 
1833  double initial_training_rate = 0.0;
1834  double training_rate = 0.0;
1835  double old_training_rate = 0.0;
1836 
1837  Vector<double> directional_point(2, 0.0);
1838 
1839  bool stop_training = false;
1840 
1841  size_t generalization_failures = 0;
1842 
1843  // Main loop
1844 
1845  for(size_t iteration = 0; iteration <= maximum_iterations_number; iteration++)
1846  {
1847 
1848  // Neural network
1849 
1850  parameters = neural_network_pointer->arrange_parameters();
1851 
1852  parameters_norm = parameters.calculate_norm();
1853 
1854  if(parameters_norm >= error_parameters_norm)
1855  {
1856  std::ostringstream buffer;
1857 
1858  buffer << "OpenNN Exception: ConjugateGradient class.\n"
1859  << "ConjugateGradientResults* perform_training(void) method.\n"
1860  << "Parameters norm is greater than error parameters norm.\n";
1861 
1862  throw std::logic_error(buffer.str());
1863  }
1864  else if(display && parameters_norm >= warning_parameters_norm)
1865  {
1866  std::cout << "OpenNN Warning: Parameters norm is " << parameters_norm << ".\n";
1867  }
1868 
1869  // Performance functional stuff
1870 
1871  if(iteration == 0)
1872  {
1874  performance_increase = 0.0;
1875  }
1876  else
1877  {
1878  performance = directional_point[1];
1879  performance_increase = old_performance - performance;
1880  }
1881 
1883 
1884  gradient_norm = gradient.calculate_norm();
1885 
1886  if(display && gradient_norm >= warning_gradient_norm)
1887  {
1888  std::cout << "OpenNN Warning: Gradient norm is " << gradient_norm << ".\n";
1889  }
1890 
1892 
1893  if(iteration != 0 && generalization_performance > old_generalization_performance)
1894  {
1895  generalization_failures++;
1896  }
1897 
1898  // Training algorithm
1899 
1900  if(iteration == 0 || iteration % parameters_number == 0)
1901  {
1902  // Gradient descent training direction
1903 
1904  training_direction = calculate_gradient_descent_training_direction(gradient);
1905  }
1906  else if(fabs(old_gradient.dot(gradient)) >= 0.2*gradient.dot(gradient)) // Powell-Bealle restarts
1907  {
1908  // Gradient descent training direction
1909 
1910  training_direction = calculate_gradient_descent_training_direction(gradient);
1911  }
1912  else
1913  {
1914  // Conjugate gradient training direction
1915 
1916  training_direction = calculate_training_direction(old_gradient, gradient, old_training_direction);
1917  }
1918 
1919  // Calculate performance training_slope
1920 
1921  training_slope = (gradient/gradient_norm).dot(training_direction);
1922 
1923  // Check for a descent direction
1924 
1925  if(training_slope >= 0.0)
1926  {
1927  // Reset training direction
1928 
1929  training_direction = calculate_gradient_descent_training_direction(gradient);
1930  }
1931 
1932  // Get initial training rate
1933 
1934  if(iteration == 0)
1935  {
1936  initial_training_rate = first_training_rate;
1937  }
1938  else
1939  {
1940  initial_training_rate = old_training_rate;
1941  }
1942 
1943  directional_point = training_rate_algorithm.calculate_directional_point(performance, training_direction, initial_training_rate);
1944 
1945  training_rate = directional_point[0];
1946 
1947  if(iteration != 0 && training_rate < 1.0e-99)
1948  {
1949  // Reset training direction
1950 
1951  training_direction = calculate_gradient_descent_training_direction(gradient);
1952 
1953  directional_point = training_rate_algorithm.calculate_directional_point(performance, training_direction, first_training_rate);
1954 
1955  training_rate = directional_point[0];
1956  }
1957 
1958  parameters_increment = training_direction*training_rate;
1959  parameters_increment_norm = parameters_increment.calculate_norm();
1960 
1961  // Elapsed time
1962 
1963  time(&current_time);
1964  elapsed_time = difftime(current_time, beginning_time);
1965 
1966  // Training history neural network
1967 
1969  {
1970  results_pointer->parameters_history[iteration] = parameters;
1971  }
1972 
1974  {
1975  results_pointer->parameters_norm_history[iteration] = parameters_norm;
1976  }
1977 
1978  // Training history performance functional
1979 
1981  {
1982  results_pointer->performance_history[iteration] = performance;
1983  }
1984 
1986  {
1987  results_pointer->generalization_performance_history[iteration] = generalization_performance;
1988  }
1989 
1991  {
1992  results_pointer->gradient_history[iteration] = gradient;
1993  }
1994 
1996  {
1997  results_pointer->gradient_norm_history[iteration] = gradient_norm;
1998  }
1999 
2000  // Training history training algorithm
2001 
2003  {
2004  results_pointer->training_direction_history[iteration] = training_direction;
2005  }
2006 
2008  {
2009  results_pointer->training_rate_history[iteration] = training_rate;
2010  }
2011 
2013  {
2014  results_pointer->elapsed_time_history[iteration] = elapsed_time;
2015  }
2016 
2017  // Stopping Criteria
2018 
2019  if(parameters_increment_norm <= minimum_parameters_increment_norm)
2020  {
2021  if(display)
2022  {
2023  std::cout << "Iteration " << iteration << ": Minimum parameters increment norm reached.\n";
2024  std::cout << "Parameters increment norm: " << parameters_increment_norm << std::endl;
2025  }
2026 
2027  stop_training = true;
2028  }
2029 
2030  else if(iteration != 0 && performance_increase <= minimum_performance_increase)
2031  {
2032  if(display)
2033  {
2034  std::cout << "Iteration " << iteration << ": Minimum performance increase reached.\n";
2035  std::cout << "Performance increase: " << performance_increase << std::endl;
2036  }
2037 
2038  stop_training = true;
2039  }
2040 
2041  else if(performance <= performance_goal)
2042  {
2043  if(display)
2044  {
2045  std::cout << "Iteration " << iteration << ": Performance goal reached.\n";
2046  }
2047 
2048  stop_training = true;
2049  }
2050 
2051  else if(gradient_norm <= gradient_norm_goal)
2052  {
2053  if(display)
2054  {
2055  std::cout << "Iteration " << iteration << ": Gradient norm goal reached.\n";
2056  }
2057 
2058  stop_training = true;
2059  }
2060 
2061  else if(generalization_failures > maximum_generalization_performance_decreases)
2062  {
2063  if(display)
2064  {
2065  std::cout << "Iteration " << iteration << ": Maximum generalization failures reached.\n"
2066  << "Generalization failures: " << generalization_failures << std::endl;
2067  }
2068 
2069  stop_training = true;
2070  }
2071 
2072  else if(iteration == maximum_iterations_number)
2073  {
2074  if(display)
2075  {
2076  std::cout << "Iteration " << iteration << ": Maximum number of iterations reached.\n";
2077  }
2078 
2079  stop_training = true;
2080  }
2081 
2082  else if(elapsed_time >= maximum_time)
2083  {
2084  if(display)
2085  {
2086  std::cout << "Iteration " << iteration << ": Maximum training time reached.\n";
2087  }
2088 
2089  stop_training = true;
2090  }
2091 
2092  if(iteration != 0 && iteration % save_period == 0)
2093  {
2094  neural_network_pointer->save(neural_network_file_name);
2095  }
2096 
2097  if(stop_training)
2098  {
2099  if(display)
2100  {
2102 
2103  std::cout << "Parameters norm: " << parameters_norm << "\n"
2104  << "Performance: " << performance << "\n"
2105  << "Gradient norm: " << gradient_norm << "\n"
2106  << information
2107  << "Training rate: " << training_rate << "\n"
2108  << "Elapsed time: " << elapsed_time << std::endl;
2109 
2110  if(generalization_performance != 0)
2111  {
2112  std::cout << "Generalization performance: " << generalization_performance << std::endl;
2113  }
2114  }
2115 
2116  results_pointer->resize_training_history(1+iteration);
2117 
2118  results_pointer->final_parameters = parameters;
2119  results_pointer->final_parameters_norm = parameters_norm;
2120 
2121  results_pointer->final_performance = performance;
2122  results_pointer->final_generalization_performance = generalization_performance;
2123 
2124  results_pointer->final_gradient = gradient;
2125  results_pointer->final_gradient_norm = gradient_norm;
2126 
2127  results_pointer->final_training_direction = training_direction;
2128  results_pointer->final_training_rate = training_rate;
2129  results_pointer->elapsed_time = elapsed_time;
2130 
2131  results_pointer->iterations_number = iteration;
2132 
2133  break;
2134  }
2135 
2136  else if(display && iteration % display_period == 0)
2137  {
2139 
2140  std::cout << "Iteration " << iteration << ";\n"
2141  << "Parameters norm: " << parameters_norm << "\n"
2142  << "Performance: " << performance << "\n"
2143  << "Gradient norm: " << gradient_norm << "\n"
2144  << information
2145  << "Training rate: " << training_rate << "\n"
2146  << "Elapsed time: " << elapsed_time << std::endl;
2147 
2148  if(generalization_performance != 0)
2149  {
2150  std::cout << "Generalization performance: " << generalization_performance << std::endl;
2151  }
2152  }
2153 
2154  // Set new parameters
2155 
2156  parameters += parameters_increment;
2157 
2158  neural_network_pointer->set_parameters(parameters);
2159 
2160  // Update stuff
2161 
2162  old_performance = performance;
2163  old_gradient = gradient;
2164  old_generalization_performance = generalization_performance;
2165 
2166  old_training_direction = training_direction;
2167  old_training_rate = training_rate;
2168  }
2169 
2170  return(results_pointer);
2171 
2172 }
2173 
2174 
2175 // std::string write_training_algorithm_type(void) const method
2176 
2178 {
2179  return("CONJUGATE_GRADIENT");
2180 }
2181 
2182 
2183 // Matrix<std::string> to_string_matrix(void) const method
2184 
2185 // the most representative
2186 
2188 {
2189  std::ostringstream buffer;
2190 
2191  Vector<std::string> labels;
2192  Vector<std::string> values;
2193 
2194  // Training direction method
2195 
2196  labels.push_back("Training direction method");
2197 
2198  const std::string training_direction_method_string = write_training_direction_method();
2199 
2200  values.push_back(training_direction_method_string);
2201 
2202  // Training rate method
2203 
2204  labels.push_back("Training rate method");
2205 
2206  const std::string training_rate_method = training_rate_algorithm.write_training_rate_method();
2207 
2208  values.push_back(training_rate_method);
2209 
2210  // Training rate tolerance
2211 
2212  labels.push_back("Training rate tolerance");
2213 
2214  buffer.str("");
2216 
2217  values.push_back(buffer.str());
2218 
2219  // Minimum parameters increment norm
2220 
2221  labels.push_back("Minimum parameters increment norm");
2222 
2223  buffer.str("");
2225 
2226  values.push_back(buffer.str());
2227 
2228  // Minimum performance increase
2229 
2230  labels.push_back("Minimum performance increase");
2231 
2232  buffer.str("");
2233  buffer << minimum_performance_increase;
2234 
2235  values.push_back(buffer.str());
2236 
2237  // Performance goal
2238 
2239  labels.push_back("Performance goal");
2240 
2241  buffer.str("");
2242  buffer << performance_goal;
2243 
2244  values.push_back(buffer.str());
2245 
2246  // Gradient norm goal
2247 
2248  labels.push_back("Gradient norm goal");
2249 
2250  buffer.str("");
2251  buffer << gradient_norm_goal;
2252 
2253  values.push_back(buffer.str());
2254 
2255  // Maximum generalization failures
2256 
2257  labels.push_back("Maximum generalization failures");
2258 
2259  buffer.str("");
2261 
2262  values.push_back(buffer.str());
2263 
2264  // Maximum iterations number
2265 
2266  labels.push_back("Maximum iterations number");
2267 
2268  buffer.str("");
2269  buffer << maximum_iterations_number;
2270 
2271  values.push_back(buffer.str());
2272 
2273  // Maximum time
2274 
2275  labels.push_back("Maximum time");
2276 
2277  buffer.str("");
2278  buffer << maximum_time;
2279 
2280  values.push_back(buffer.str());
2281 
2282  // Reserve parameters norm history
2283 
2284  labels.push_back("Reserve parameters norm history");
2285 
2286  buffer.str("");
2288 
2289  values.push_back(buffer.str());
2290 
2291  // Reserve performance history
2292 
2293  labels.push_back("Reserve performance history");
2294 
2295  buffer.str("");
2296  buffer << reserve_performance_history;
2297 
2298  values.push_back(buffer.str());
2299 
2300  // Reserve gradient norm history
2301 
2302  labels.push_back("Reserve gradient norm history");
2303 
2304  buffer.str("");
2306 
2307  values.push_back(buffer.str());
2308 
2309  // Reserve generalization performance history
2310 
2311  labels.push_back("Reserve generalization performance history");
2312 
2313  buffer.str("");
2315 
2316  values.push_back(buffer.str());
2317 
2318  // Reserve training direction norm history
2319 
2320 // labels.push_back("");
2321 
2322 // buffer.str("");
2323 // buffer << reserve_training_direction_norm_history;
2324 
2325  // Reserve training rate history
2326 
2327 // labels.push_back("");
2328 
2329 // buffer.str("");
2330 // buffer << reserve_training_rate_history;
2331 
2332 // values.push_back(buffer.str());
2333 
2334  // Reserve elapsed time history
2335 
2336  labels.push_back("Reserve elapsed time history");
2337 
2338  buffer.str("");
2339  buffer << reserve_elapsed_time_history;
2340 
2341  values.push_back(buffer.str());
2342 
2343  const size_t rows_number = labels.size();
2344  const size_t columns_number = 2;
2345 
2346  Matrix<std::string> string_matrix(rows_number, columns_number);
2347 
2348  string_matrix.set_column(0, labels);
2349  string_matrix.set_column(1, values);
2350 
2351  return(string_matrix);
2352 }
2353 
2354 
2355 // tinyxml2::XMLDocument* to_XML(void) const method
2356 
2359 
2360 tinyxml2::XMLDocument* ConjugateGradient::to_XML(void) const
2361 {
2362  std::ostringstream buffer;
2363 
2364  tinyxml2::XMLDocument* document = new tinyxml2::XMLDocument;
2365 
2366  // Conjugate gradient
2367 
2368  tinyxml2::XMLElement* root_element = document->NewElement("ConjugateGradient");
2369 
2370  document->InsertFirstChild(root_element);
2371 
2372  tinyxml2::XMLElement* element = NULL;
2373  tinyxml2::XMLText* text = NULL;
2374 
2375 
2376  // Training direction method
2377  {
2378  element = document->NewElement("TrainingDirectionMethod");
2379  root_element->LinkEndChild(element);
2380 
2381  text = document->NewText(write_training_direction_method().c_str());
2382  element->LinkEndChild(text);
2383  }
2384 
2385  // Training rate algorithm
2386  {
2387  tinyxml2::XMLElement* element = document->NewElement("TrainingRateAlgorithm");
2388  root_element->LinkEndChild(element);
2389 
2390  const tinyxml2::XMLDocument* training_rate_algorithm_document = training_rate_algorithm.to_XML();
2391 
2392  const tinyxml2::XMLElement* training_rate_algorithm_element = training_rate_algorithm_document->FirstChildElement("TrainingRateAlgorithm");
2393 
2394  DeepClone(element, training_rate_algorithm_element, document, NULL);
2395 
2396  delete training_rate_algorithm_document;
2397  }
2398 
2399  // Warning parameters norm
2400  {
2401  element = document->NewElement("WarningParametersNorm");
2402  root_element->LinkEndChild(element);
2403 
2404  buffer.str("");
2405  buffer << warning_parameters_norm;
2406 
2407  text = document->NewText(buffer.str().c_str());
2408  element->LinkEndChild(text);
2409  }
2410 
2411  // Warning gradient norm
2412  {
2413  element = document->NewElement("WarningGradientNorm");
2414  root_element->LinkEndChild(element);
2415 
2416  buffer.str("");
2417  buffer << warning_gradient_norm;
2418 
2419  text = document->NewText(buffer.str().c_str());
2420  element->LinkEndChild(text);
2421  }
2422 
2423  // Warning training rate
2424  {
2425  element = document->NewElement("WarningTrainingRate");
2426  root_element->LinkEndChild(element);
2427 
2428  buffer.str("");
2429  buffer << warning_training_rate;
2430 
2431  text = document->NewText(buffer.str().c_str());
2432  element->LinkEndChild(text);
2433  }
2434 
2435  // Error parameters norm
2436  {
2437  element = document->NewElement("ErrorParametersNorm");
2438  root_element->LinkEndChild(element);
2439 
2440  buffer.str("");
2441  buffer << error_parameters_norm;
2442 
2443  text = document->NewText(buffer.str().c_str());
2444  element->LinkEndChild(text);
2445  }
2446 
2447  // Error gradient norm
2448  {
2449  element = document->NewElement("ErrorGradientNorm");
2450  root_element->LinkEndChild(element);
2451 
2452  buffer.str("");
2453  buffer << error_gradient_norm;
2454 
2455  text = document->NewText(buffer.str().c_str());
2456  element->LinkEndChild(text);
2457  }
2458 
2459  // Error training rate
2460  {
2461  element = document->NewElement("ErrorTrainingRate");
2462  root_element->LinkEndChild(element);
2463 
2464  buffer.str("");
2465  buffer << error_training_rate;
2466 
2467  text = document->NewText(buffer.str().c_str());
2468  element->LinkEndChild(text);
2469  }
2470 
2471  // Minimum parameters increment norm
2472  {
2473  element = document->NewElement("MinimumParametersIncrementNorm");
2474  root_element->LinkEndChild(element);
2475 
2476  buffer.str("");
2478 
2479  text = document->NewText(buffer.str().c_str());
2480  element->LinkEndChild(text);
2481  }
2482 
2483  // Minimum performance increase
2484  {
2485  element = document->NewElement("MinimumPerformanceIncrease");
2486  root_element->LinkEndChild(element);
2487 
2488  buffer.str("");
2489  buffer << minimum_performance_increase;
2490 
2491  text = document->NewText(buffer.str().c_str());
2492  element->LinkEndChild(text);
2493  }
2494 
2495  // Performance goal
2496  {
2497  element = document->NewElement("PerformanceGoal");
2498  root_element->LinkEndChild(element);
2499 
2500  buffer.str("");
2501  buffer << performance_goal;
2502 
2503  text = document->NewText(buffer.str().c_str());
2504  element->LinkEndChild(text);
2505  }
2506 
2507  // Gradient norm goal
2508  {
2509  element = document->NewElement("GradientNormGoal");
2510  root_element->LinkEndChild(element);
2511 
2512  buffer.str("");
2513  buffer << gradient_norm_goal;
2514 
2515  text = document->NewText(buffer.str().c_str());
2516  element->LinkEndChild(text);
2517  }
2518 
2519  // Maximum generalization performance decreases
2520  {
2521  element = document->NewElement("MaximumGeneralizationPerformanceDecreases");
2522  root_element->LinkEndChild(element);
2523 
2524  buffer.str("");
2526 
2527  text = document->NewText(buffer.str().c_str());
2528  element->LinkEndChild(text);
2529  }
2530 
2531  // Maximum iterations number
2532  {
2533  element = document->NewElement("MaximumIterationsNumber");
2534  root_element->LinkEndChild(element);
2535 
2536  buffer.str("");
2537  buffer << maximum_iterations_number;
2538 
2539  text = document->NewText(buffer.str().c_str());
2540  element->LinkEndChild(text);
2541  }
2542 
2543  // Maximum time
2544  {
2545  element = document->NewElement("MaximumTime");
2546  root_element->LinkEndChild(element);
2547 
2548  buffer.str("");
2549  buffer << maximum_time;
2550 
2551  text = document->NewText(buffer.str().c_str());
2552  element->LinkEndChild(text);
2553  }
2554 
2555  // Reserve parameters history
2556  {
2557  element = document->NewElement("ReserveParametersHistory");
2558  root_element->LinkEndChild(element);
2559 
2560  buffer.str("");
2561  buffer << reserve_parameters_history;
2562 
2563  text = document->NewText(buffer.str().c_str());
2564  element->LinkEndChild(text);
2565  }
2566 
2567  // Reserve parameters norm history
2568  {
2569  element = document->NewElement("ReserveParametersNormHistory");
2570  root_element->LinkEndChild(element);
2571 
2572  buffer.str("");
2574 
2575  text = document->NewText(buffer.str().c_str());
2576  element->LinkEndChild(text);
2577  }
2578 
2579  // Reserve performance history
2580  {
2581  element = document->NewElement("ReservePerformanceHistory");
2582  root_element->LinkEndChild(element);
2583 
2584  buffer.str("");
2585  buffer << reserve_performance_history;
2586 
2587  text = document->NewText(buffer.str().c_str());
2588  element->LinkEndChild(text);
2589  }
2590 
2591  // Reserve generalization performance history
2592  {
2593  element = document->NewElement("ReserveGeneralizationPerformanceHistory");
2594  root_element->LinkEndChild(element);
2595 
2596  buffer.str("");
2598 
2599  text = document->NewText(buffer.str().c_str());
2600  element->LinkEndChild(text);
2601  }
2602 
2603  // Reserve gradient history
2604  {
2605  element = document->NewElement("ReserveGradientHistory");
2606  root_element->LinkEndChild(element);
2607 
2608  buffer.str("");
2609  buffer << reserve_gradient_history;
2610 
2611  text = document->NewText(buffer.str().c_str());
2612  element->LinkEndChild(text);
2613  }
2614 
2615  // Reserve gradient norm history
2616  {
2617  element = document->NewElement("ReserveGradientNormHistory");
2618  root_element->LinkEndChild(element);
2619 
2620  buffer.str("");
2622 
2623  text = document->NewText(buffer.str().c_str());
2624  element->LinkEndChild(text);
2625  }
2626 
2627  // Reserve training direction history
2628  {
2629  element = document->NewElement("ReserveTrainingDirectionHistory");
2630  root_element->LinkEndChild(element);
2631 
2632  buffer.str("");
2634 
2635  text = document->NewText(buffer.str().c_str());
2636  element->LinkEndChild(text);
2637  }
2638 
2639  // Reserve training rate history
2640  {
2641  tinyxml2::XMLElement* element = document->NewElement("ReserveTrainingRateHistory");
2642  root_element->LinkEndChild(element);
2643 
2644  buffer.str("");
2646 
2647  text = document->NewText(buffer.str().c_str());
2648  element->LinkEndChild(text);
2649  }
2650 
2651  // Reserve elapsed time history
2652  {
2653  element = document->NewElement("ReserveElapsedTimeHistory");
2654  root_element->LinkEndChild(element);
2655 
2656  buffer.str("");
2657  buffer << reserve_elapsed_time_history;
2658 
2659  text = document->NewText(buffer.str().c_str());
2660  element->LinkEndChild(text);
2661  }
2662 
2663  // Reserve generalization performance history
2664  {
2665  element = document->NewElement("ReserveGeneralizationPerformanceHistory");
2666  root_element->LinkEndChild(element);
2667 
2668  buffer.str("");
2670 
2671  text = document->NewText(buffer.str().c_str());
2672  element->LinkEndChild(text);
2673  }
2674 
2675  // Display period
2676  {
2677  element = document->NewElement("DisplayPeriod");
2678  root_element->LinkEndChild(element);
2679 
2680  buffer.str("");
2681  buffer << display_period;
2682 
2683  text = document->NewText(buffer.str().c_str());
2684  element->LinkEndChild(text);
2685  }
2686 
2687  // Save period
2688  {
2689  element = document->NewElement("SavePeriod");
2690  root_element->LinkEndChild(element);
2691 
2692  buffer.str("");
2693  buffer << save_period;
2694 
2695  text = document->NewText(buffer.str().c_str());
2696  element->LinkEndChild(text);
2697  }
2698 
2699  // Neural network file name
2700  {
2701  element = document->NewElement("NeuralNetworkFileName");
2702  root_element->LinkEndChild(element);
2703 
2704  text = document->NewText(neural_network_file_name.c_str());
2705  element->LinkEndChild(text);
2706  }
2707 
2708  // Display
2709  {
2710  element = document->NewElement("Display");
2711  root_element->LinkEndChild(element);
2712 
2713  buffer.str("");
2714  buffer << display;
2715 
2716  text = document->NewText(buffer.str().c_str());
2717  element->LinkEndChild(text);
2718  }
2719 
2720  return(document);
2721 }
2722 
2723 
2724 // void from_XML(const tinyxml2::XMLDocument&) method
2725 
2728 
2729 void ConjugateGradient::from_XML(const tinyxml2::XMLDocument& document)
2730 {
2731  const tinyxml2::XMLElement* root_element = document.FirstChildElement("ConjugateGradient");
2732 
2733  if(!root_element)
2734  {
2735  std::ostringstream buffer;
2736 
2737  buffer << "OpenNN Exception: ConjugateGradient class.\n"
2738  << "void from_XML(const tinyxml2::XMLDocument&) method.\n"
2739  << "Conjugate gradient element is NULL.\n";
2740 
2741  throw std::logic_error(buffer.str());
2742  }
2743 
2744  // Training direction method
2745  {
2746  const tinyxml2::XMLElement* training_direction_method_element = root_element->FirstChildElement("TrainingDirectionMethod");
2747 
2748  if(training_direction_method_element)
2749  {
2750  const std::string new_training_direction_method = training_direction_method_element->GetText();
2751 
2752  try
2753  {
2754  set_training_direction_method(new_training_direction_method);
2755  }
2756  catch(const std::logic_error& e)
2757  {
2758  std::cout << e.what() << std::endl;
2759  }
2760  }
2761  }
2762 
2763  // Training rate algorithm
2764  {
2765  const tinyxml2::XMLElement* training_rate_algorithm_element = root_element->FirstChildElement("TrainingRateAlgorithm");
2766 
2767  if(training_rate_algorithm_element)
2768  {
2769  tinyxml2::XMLDocument training_rate_algorithm_document;
2770 
2771  tinyxml2::XMLElement* element_clone = training_rate_algorithm_document.NewElement("TrainingRateAlgorithm");
2772  training_rate_algorithm_document.InsertFirstChild(element_clone);
2773 
2774  DeepClone(element_clone, training_rate_algorithm_element, &training_rate_algorithm_document, NULL);
2775 
2776  training_rate_algorithm.from_XML(training_rate_algorithm_document);
2777  }
2778  }
2779 
2780  // Warning parameters norm
2781  {
2782  const tinyxml2::XMLElement* warning_parameters_norm_element = root_element->FirstChildElement("WarningParametersNorm");
2783 
2784  if(warning_parameters_norm_element)
2785  {
2786  const double new_warning_parameters_norm = atof(warning_parameters_norm_element->GetText());
2787 
2788  try
2789  {
2790  set_warning_parameters_norm(new_warning_parameters_norm);
2791  }
2792  catch(const std::logic_error& e)
2793  {
2794  std::cout << e.what() << std::endl;
2795  }
2796  }
2797  }
2798 
2799  // Warning gradient norm
2800  {
2801  const tinyxml2::XMLElement* warning_gradient_norm_element = root_element->FirstChildElement("WarningGradientNorm");
2802 
2803  if(warning_gradient_norm_element)
2804  {
2805  const double new_warning_gradient_norm = atof(warning_gradient_norm_element->GetText());
2806 
2807  try
2808  {
2809  set_warning_gradient_norm(new_warning_gradient_norm);
2810  }
2811  catch(const std::logic_error& e)
2812  {
2813  std::cout << e.what() << std::endl;
2814  }
2815  }
2816  }
2817 
2818  // Warning training rate
2819  {
2820  const tinyxml2::XMLElement* warning_training_rate_element = root_element->FirstChildElement("WarningTrainingRate");
2821 
2822  if(warning_training_rate_element)
2823  {
2824  const double new_warning_training_rate = atof(warning_training_rate_element->GetText());
2825 
2826  try
2827  {
2828  set_warning_training_rate(new_warning_training_rate);
2829  }
2830  catch(const std::logic_error& e)
2831  {
2832  std::cout << e.what() << std::endl;
2833  }
2834  }
2835  }
2836 
2837  // Error parameters norm
2838  {
2839  const tinyxml2::XMLElement* error_parameters_norm_element = root_element->FirstChildElement("ErrorParametersNorm");
2840 
2841  if(error_parameters_norm_element)
2842  {
2843  const double new_error_parameters_norm = atof(error_parameters_norm_element->GetText());
2844 
2845  try
2846  {
2847  set_error_parameters_norm(new_error_parameters_norm);
2848  }
2849  catch(const std::logic_error& e)
2850  {
2851  std::cout << e.what() << std::endl;
2852  }
2853  }
2854  }
2855 
2856  // Error gradient norm
2857  {
2858  const tinyxml2::XMLElement* error_gradient_norm_element = root_element->FirstChildElement("ErrorGradientNorm");
2859 
2860  if(error_gradient_norm_element)
2861  {
2862  const double new_error_gradient_norm = atof(error_gradient_norm_element->GetText());
2863 
2864  try
2865  {
2866  set_error_gradient_norm(new_error_gradient_norm);
2867  }
2868  catch(const std::logic_error& e)
2869  {
2870  std::cout << e.what() << std::endl;
2871  }
2872  }
2873  }
2874 
2875  // Error training rate
2876  {
2877  const tinyxml2::XMLElement* error_training_rate_element = root_element->FirstChildElement("ErrorTrainingRate");
2878 
2879  if(error_training_rate_element)
2880  {
2881  const double new_error_training_rate = atof(error_training_rate_element->GetText());
2882 
2883  try
2884  {
2885  set_error_training_rate(new_error_training_rate);
2886  }
2887  catch(const std::logic_error& e)
2888  {
2889  std::cout << e.what() << std::endl;
2890  }
2891  }
2892  }
2893 
2894  // Minimum parameters increment norm
2895  {
2896  const tinyxml2::XMLElement* minimum_parameters_increment_norm_element = root_element->FirstChildElement("MinimumParametersIncrementNorm");
2897 
2898  if(minimum_parameters_increment_norm_element)
2899  {
2900  const double new_minimum_parameters_increment_norm = atof(minimum_parameters_increment_norm_element->GetText());
2901 
2902  try
2903  {
2904  set_minimum_parameters_increment_norm(new_minimum_parameters_increment_norm);
2905  }
2906  catch(const std::logic_error& e)
2907  {
2908  std::cout << e.what() << std::endl;
2909  }
2910  }
2911  }
2912 
2913  // Minimum performance increase
2914  {
2915  const tinyxml2::XMLElement* minimum_performance_increase_element = root_element->FirstChildElement("MinimumPerformanceIncrease");
2916 
2917  if(minimum_performance_increase_element)
2918  {
2919  const double new_minimum_performance_increase = atof(minimum_performance_increase_element->GetText());
2920 
2921  try
2922  {
2923  set_minimum_performance_increase(new_minimum_performance_increase);
2924  }
2925  catch(const std::logic_error& e)
2926  {
2927  std::cout << e.what() << std::endl;
2928  }
2929  }
2930  }
2931 
2932  // Performance goal
2933  {
2934  const tinyxml2::XMLElement* performance_goal_element = root_element->FirstChildElement("PerformanceGoal");
2935 
2936  if(performance_goal_element)
2937  {
2938  const double new_performance_goal = atof(performance_goal_element->GetText());
2939 
2940  try
2941  {
2942  set_performance_goal(new_performance_goal);
2943  }
2944  catch(const std::logic_error& e)
2945  {
2946  std::cout << e.what() << std::endl;
2947  }
2948  }
2949  }
2950 
2951  // Gradient norm goal
2952  {
2953  const tinyxml2::XMLElement* gradient_norm_goal_element = root_element->FirstChildElement("GradientNormGoal");
2954 
2955  if(gradient_norm_goal_element)
2956  {
2957  const double new_gradient_norm_goal = atof(gradient_norm_goal_element->GetText());
2958 
2959  try
2960  {
2961  set_gradient_norm_goal(new_gradient_norm_goal);
2962  }
2963  catch(const std::logic_error& e)
2964  {
2965  std::cout << e.what() << std::endl;
2966  }
2967  }
2968  }
2969 
2970  // Maximum generalization performance decreases
2971  {
2972  const tinyxml2::XMLElement* maximum_generalization_performance_decreases_element = root_element->FirstChildElement("MaximumGeneralizationPerformanceDecreases");
2973 
2974  if(maximum_generalization_performance_decreases_element)
2975  {
2976  const size_t new_maximum_generalization_performance_decreases = atoi(maximum_generalization_performance_decreases_element->GetText());
2977 
2978  try
2979  {
2980  set_maximum_generalization_performance_decreases(new_maximum_generalization_performance_decreases);
2981  }
2982  catch(const std::logic_error& e)
2983  {
2984  std::cout << e.what() << std::endl;
2985  }
2986  }
2987  }
2988 
2989  // Maximum iterations number
2990  {
2991  const tinyxml2::XMLElement* maximum_iterations_number_element = root_element->FirstChildElement("MaximumIterationsNumber");
2992 
2993  if(maximum_iterations_number_element)
2994  {
2995  const size_t new_maximum_iterations_number = atoi(maximum_iterations_number_element->GetText());
2996 
2997  try
2998  {
2999  set_maximum_iterations_number(new_maximum_iterations_number);
3000  }
3001  catch(const std::logic_error& e)
3002  {
3003  std::cout << e.what() << std::endl;
3004  }
3005  }
3006  }
3007 
3008  // Maximum time
3009  {
3010  const tinyxml2::XMLElement* maximum_time_element = root_element->FirstChildElement("MaximumTime");
3011 
3012  if(maximum_time_element)
3013  {
3014  const double new_maximum_time = atof(maximum_time_element->GetText());
3015 
3016  try
3017  {
3018  set_maximum_time(new_maximum_time);
3019  }
3020  catch(const std::logic_error& e)
3021  {
3022  std::cout << e.what() << std::endl;
3023  }
3024  }
3025  }
3026 
3027  // Reserve parameters history
3028  {
3029  const tinyxml2::XMLElement* reserve_parameters_history_element = root_element->FirstChildElement("ReserveParametersHistory");
3030 
3031  if(reserve_parameters_history_element)
3032  {
3033  const std::string new_reserve_parameters_history = reserve_parameters_history_element->GetText();
3034 
3035  try
3036  {
3037  set_reserve_parameters_history(new_reserve_parameters_history != "0");
3038  }
3039  catch(const std::logic_error& e)
3040  {
3041  std::cout << e.what() << std::endl;
3042  }
3043  }
3044  }
3045 
3046  // Reserve parameters norm history
3047  {
3048  const tinyxml2::XMLElement* reserve_parameters_norm_history_element = root_element->FirstChildElement("ReserveParametersNormHistory");
3049 
3050  if(reserve_parameters_norm_history_element)
3051  {
3052  const std::string new_reserve_parameters_norm_history = reserve_parameters_norm_history_element->GetText();
3053 
3054  try
3055  {
3056  set_reserve_parameters_norm_history(new_reserve_parameters_norm_history != "0");
3057  }
3058  catch(const std::logic_error& e)
3059  {
3060  std::cout << e.what() << std::endl;
3061  }
3062  }
3063  }
3064 
3065  // Reserve performance history
3066  {
3067  const tinyxml2::XMLElement* reserve_performance_history_element = root_element->FirstChildElement("ReservePerformanceHistory");
3068 
3069  if(reserve_performance_history_element)
3070  {
3071  const std::string new_reserve_performance_history = reserve_performance_history_element->GetText();
3072 
3073  try
3074  {
3075  set_reserve_performance_history(new_reserve_performance_history != "0");
3076  }
3077  catch(const std::logic_error& e)
3078  {
3079  std::cout << e.what() << std::endl;
3080  }
3081  }
3082  }
3083 
3084  // Reserve generalization performance history
3085  {
3086  const tinyxml2::XMLElement* reserve_generalization_performance_history_element = root_element->FirstChildElement("ReserveGeneralizationPerformanceHistory");
3087 
3088  if(reserve_generalization_performance_history_element)
3089  {
3090  const std::string new_reserve_generalization_performance_history = reserve_generalization_performance_history_element->GetText();
3091 
3092  try
3093  {
3094  set_reserve_generalization_performance_history(new_reserve_generalization_performance_history != "0");
3095  }
3096  catch(const std::logic_error& e)
3097  {
3098  std::cout << e.what() << std::endl;
3099  }
3100  }
3101  }
3102 
3103  // Reserve gradient history
3104  {
3105  const tinyxml2::XMLElement* reserve_gradient_history_element = root_element->FirstChildElement("ReserveGradientHistory");
3106 
3107  if(reserve_gradient_history_element)
3108  {
3109  const std::string new_reserve_gradient_history = reserve_gradient_history_element->GetText();
3110 
3111  try
3112  {
3113  set_reserve_gradient_history(new_reserve_gradient_history != "0");
3114  }
3115  catch(const std::logic_error& e)
3116  {
3117  std::cout << e.what() << std::endl;
3118  }
3119  }
3120 
3121  // Reserve gradient norm history
3122  {
3123  const tinyxml2::XMLElement* reserve_gradient_norm_history_element = root_element->FirstChildElement("ReserveGradientNormHistory");
3124 
3125  if(reserve_gradient_norm_history_element)
3126  {
3127  const std::string new_reserve_gradient_norm_history = reserve_gradient_norm_history_element->GetText();
3128 
3129  try
3130  {
3131  set_reserve_gradient_norm_history(new_reserve_gradient_norm_history != "0");
3132  }
3133  catch(const std::logic_error& e)
3134  {
3135  std::cout << e.what() << std::endl;
3136  }
3137  }
3138  }
3139 
3140  // Reserve training direction history
3141  {
3142  const tinyxml2::XMLElement* reserve_training_direction_history_element = root_element->FirstChildElement("ReserveTrainingDirectionHistory");
3143 
3144  if(reserve_training_direction_history_element)
3145  {
3146  const std::string new_reserve_training_direction_history = reserve_training_direction_history_element->GetText();
3147 
3148  try
3149  {
3150  set_reserve_training_direction_history(new_reserve_training_direction_history != "0");
3151  }
3152  catch(const std::logic_error& e)
3153  {
3154  std::cout << e.what() << std::endl;
3155  }
3156  }
3157  }
3158 
3159  // Reserve training rate history
3160  {
3161  const tinyxml2::XMLElement* reserve_training_rate_history_element = root_element->FirstChildElement("ReserveTrainingRateHistory");
3162 
3163  if(reserve_training_rate_history_element)
3164  {
3165  const std::string new_reserve_training_rate_history = reserve_training_rate_history_element->GetText();
3166 
3167  try
3168  {
3169  set_reserve_training_rate_history(new_reserve_training_rate_history != "0");
3170  }
3171  catch(const std::logic_error& e)
3172  {
3173  std::cout << e.what() << std::endl;
3174  }
3175  }
3176  }
3177 
3178  // Reserve elapsed time history
3179  {
3180  const tinyxml2::XMLElement* reserve_elapsed_time_history_element = root_element->FirstChildElement("ReserveElapsedTimeHistory");
3181 
3182  if(reserve_elapsed_time_history_element)
3183  {
3184  const std::string new_reserve_elapsed_time_history = reserve_elapsed_time_history_element->GetText();
3185 
3186  try
3187  {
3188  set_reserve_elapsed_time_history(new_reserve_elapsed_time_history != "0");
3189  }
3190  catch(const std::logic_error& e)
3191  {
3192  std::cout << e.what() << std::endl;
3193  }
3194  }
3195  }
3196 
3197  // Reserve generalization performance history
3198  {
3199  const tinyxml2::XMLElement* reserve_generalization_performance_history_element = root_element->FirstChildElement("ReserveGeneralizationPerformanceHistory");
3200 
3201  if(reserve_generalization_performance_history_element)
3202  {
3203  const std::string new_reserve_generalization_performance_history = reserve_generalization_performance_history_element->GetText();
3204 
3205  try
3206  {
3207  set_reserve_generalization_performance_history(new_reserve_generalization_performance_history != "0");
3208  }
3209  catch(const std::logic_error& e)
3210  {
3211  std::cout << e.what() << std::endl;
3212  }
3213  }
3214  }
3215 
3216  // Display period
3217  {
3218  const tinyxml2::XMLElement* display_period_element = root_element->FirstChildElement("DisplayPeriod");
3219 
3220  if(display_period_element)
3221  {
3222  const size_t new_display_period = atoi(display_period_element->GetText());
3223 
3224  try
3225  {
3226  set_display_period(new_display_period);
3227  }
3228  catch(const std::logic_error& e)
3229  {
3230  std::cout << e.what() << std::endl;
3231  }
3232  }
3233  }
3234 
3235  // Save period
3236  {
3237  const tinyxml2::XMLElement* element = root_element->FirstChildElement("SavePeriod");
3238 
3239  if(element)
3240  {
3241  const size_t new_save_period = atoi(element->GetText());
3242 
3243  try
3244  {
3245  set_save_period(new_save_period);
3246  }
3247  catch(const std::logic_error& e)
3248  {
3249  std::cout << e.what() << std::endl;
3250  }
3251  }
3252  }
3253 
3254  // Neural network file name
3255  {
3256  const tinyxml2::XMLElement* element = root_element->FirstChildElement("NeuralNetworkFileName");
3257 
3258  if(element)
3259  {
3260  const std::string new_neural_network_file_name = element->GetText();
3261 
3262  try
3263  {
3264  set_neural_network_file_name(new_neural_network_file_name);
3265  }
3266  catch(const std::logic_error& e)
3267  {
3268  std::cout << e.what() << std::endl;
3269  }
3270  }
3271  }
3272 
3273  // Display
3274  {
3275  const tinyxml2::XMLElement* display_element = root_element->FirstChildElement("Display");
3276 
3277  if(display_element)
3278  {
3279  const std::string new_display = display_element->GetText();
3280 
3281  try
3282  {
3283  set_display(new_display != "0");
3284  }
3285  catch(const std::logic_error& e)
3286  {
3287  std::cout << e.what() << std::endl;
3288  }
3289  }
3290  }
3291 }
3292 }
3293 }
3294 
3295 // OpenNN: Open Neural Networks Library.
3296 // Copyright (c) 2005-2015 Roberto Lopez.
3297 //
3298 // This library is free software; you can redistribute it and/or
3299 // modify it under the terms of the GNU Lesser General Public
3300 // License as published by the Free Software Foundation; either
3301 // version 2.1 of the License, or any later version.
3302 //
3303 // This library is distributed in the hope that it will be useful,
3304 // but WITHOUT ANY WARRANTY; without even the implied warranty of
3305 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
3306 // Lesser General Public License for more details.
3307 
3308 // You should have received a copy of the GNU Lesser General Public
3309 // License along with this library; if not, write to the Free Software
3310 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Vector< double > calculate_FR_training_direction(const Vector< double > &, const Vector< double > &, const Vector< double > &) const
TrainingDirectionMethod training_direction_method
Applied method for calculating the conjugate gradient direction.
Vector< double > calculate_training_direction(const Vector< double > &, const Vector< double > &, const Vector< double > &) const
virtual double calculate_generalization_performance(void) const
void set_gradient_norm_goal(const double &)
size_t count_parameters_number(void) const
void set_performance_goal(const double &)
const double & get_warning_parameters_norm(void) const
Returns the minimum value for the norm of the parameters vector at wich a warning message is written ...
double warning_training_rate
Training rate value at wich a warning message is written to the screen.
Vector< Vector< double > > gradient_history
History of the performance function gradient over the training iterations.
double elapsed_time
Elapsed time of the training process.
const bool & get_reserve_performance_history(void) const
Returns true if the performance history vector is to be reserved, and false otherwise.
Vector< double > calculate_gradient(void) const
Returns the performance function gradient, as the sum of the objective and the regularization gradien...
Matrix< std::string > write_final_results(const size_t &precision=3) const
Returns a default (empty) string matrix with the final results from training.
double maximum_time
Maximum training time. It is used as a stopping criterion.
Vector< double > gradient_norm_history
History of the gradient norm over the training iterations.
const TrainingDirectionMethod & get_training_direction_method(void) const
Returns the conjugate gradient training direction method used for training.
void from_XML(const tinyxml2::XMLDocument &)
const bool & get_reserve_training_rate_history(void) const
Returns true if the training rate history vector is to be reserved, and false otherwise.
Vector< double > arrange_parameters(void) const
void set_reserve_training_rate_history(const bool &)
void set_performance_functional_pointer(PerformanceFunctional *)
const bool & get_reserve_parameters_history(void) const
Returns true if the parameters history matrix is to be reserved, and false otherwise.
double error_parameters_norm
Value for the parameters norm at which the training process is assumed to fail.
double error_training_rate
Training rate at wich the line minimization algorithm is assumed to be unable to bracket a minimum...
bool display
Display messages to screen.
NeuralNetwork * get_neural_network_pointer(void) const
Returns a pointer to the neural network associated to the performance functional. ...
double warning_parameters_norm
Value for the parameters norm at which a warning message is written to the screen.
const double & get_minimum_performance_increase(void) const
Returns the minimum performance improvement during training.
double calculate_FR_parameter(const Vector< double > &, const Vector< double > &) const
void set_reserve_gradient_history(const bool &)
void set_reserve_parameters_norm_history(const bool &)
bool reserve_parameters_history
True if the parameters history matrix is to be reserved, false otherwise.
double final_parameters_norm
Final neural network parameters norm.
const double & get_warning_gradient_norm(void) const
Returns the minimum value for the norm of the gradient vector at wich a warning message is written to...
const double & get_gradient_norm_goal(void) const
std::string to_string(void) const
Returns a string representation of the results structure.
const bool & get_reserve_generalization_performance_history(void) const
Returns true if the Generalization performance history vector is to be reserved, and false otherwise...
std::string write_training_rate_method(void) const
Returns a string with the name of the training rate method to be used.
tinyxml2::XMLDocument * to_XML(void) const
void set_warning_parameters_norm(const double &)
double minimum_parameters_increment_norm
Norm of the parameters increment vector at which training stops.
Vector< double > calculate_gradient_descent_training_direction(const Vector< double > &) const
void set_error_training_rate(const double &)
ConjugateGradient * conjugate_gradient_pointer
Pointer to the conjugate gradient object for which the training results are to be stored...
double performance_goal
Goal value for the performance. It is used as a stopping criterion.
double error_gradient_norm
Value for the gradient norm at which the training process is assumed to fail.
Vector< double > performance_history
History of the performance function performance over the training iterations.
const double & get_warning_training_rate(void) const
Returns the training rate value at wich a warning message is written to the screen during line minimi...
void set_reserve_generalization_performance_history(const bool &)
virtual ~ConjugateGradient(void)
Destructor.
void set_maximum_iterations_number(const size_t &)
Vector< Vector< double > > parameters_history
History of the neural network parameters over the training iterations.
const double & get_minimum_parameters_increment_norm(void) const
Returns the minimum norm of the parameter increment vector used as a stopping criteria when training...
void set_performance_functional_pointer(PerformanceFunctional *)
size_t save_period
Number of iterations between the training saving progress.
bool reserve_parameters_norm_history
True if the parameters norm history vector is to be reserved, false otherwise.
bool reserve_gradient_norm_history
True if the gradient norm history vector is to be reserved, false otherwise.
Vector< double > calculate_directional_point(const double &, const Vector< double > &, const double &) const
double warning_gradient_norm
Value for the gradient norm at which a warning message is written to the screen.
ConjugateGradientResults * perform_training(void)
Vector< double > final_parameters
Final neural network parameters vector.
virtual std::string write_information(void)
void set_error_parameters_norm(const double &)
double calculate_norm(void) const
Returns the vector norm.
Definition: vector.h:2358
void set_maximum_generalization_performance_decreases(const size_t &)
void set_minimum_parameters_increment_norm(const double &)
std::string neural_network_file_name
Path where the neural network is saved.
void set_reserve_elapsed_time_history(const bool &)
Vector< double > calculate_PR_training_direction(const Vector< double > &, const Vector< double > &, const Vector< double > &) const
void set_neural_network_file_name(const std::string &)
void set_minimum_performance_increase(const double &)
void set_column(const size_t &, const Vector< T > &)
Definition: matrix.h:1774
bool reserve_performance_history
True if the performance history vector is to be reserved, false otherwise.
Vector< T > calculate_normalized(void) const
Returns this vector divided by its norm.
Definition: vector.h:2530
std::string write_training_algorithm_type(void) const
This method writes a string with the type of training algoritm.
Vector< double > training_rate_history
History of the training rate over the training iterations.
size_t maximum_iterations_number
Maximum number of iterations to perform_training. It is used as a stopping criterion.
TrainingRateAlgorithm training_rate_algorithm
Training rate algorithm object for one-dimensional minimization.
const bool & get_reserve_gradient_history(void) const
Returns true if the gradient history vector of vectors is to be reserved, and false otherwise...
void from_XML(const tinyxml2::XMLDocument &)
double calculate_PR_parameter(const Vector< double > &, const Vector< double > &) const
double dot(const Vector< double > &) const
Definition: vector.h:3654
Vector< double > final_training_direction
Final conjugate gradient training direction.
const double & get_performance_goal(void) const
void set_training_direction_method(const TrainingDirectionMethod &)
const bool & get_reserve_gradient_norm_history(void) const
Returns true if the gradient norm history vector is to be reserved, and false otherwise.
const double & get_training_rate_tolerance(void) const
Returns the tolerance value in line minimization.
Vector< double > final_gradient
Final performance function gradient.
size_t iterations_number
Maximum number of training iterations.
void save(const std::string &) const
bool reserve_elapsed_time_history
True if the elapsed time history vector is to be reserved, false otherwise.
virtual void check(void) const
double final_training_rate
Final conjugate gradient training rate.
double minimum_performance_increase
Minimum performance improvement between two successive iterations. It is used as a stopping criterion...
Vector< double > generalization_performance_history
History of the generalization performance over the training iterations.
void set_warning_gradient_norm(const double &)
const size_t & get_maximum_generalization_performance_decreases(void) const
Returns the maximum number of generalization failures during the training process.
const bool & get_reserve_elapsed_time_history(void) const
Returns true if the elapsed time history vector is to be reserved, and false otherwise.
tinyxml2::XMLDocument * to_XML(void) const
Matrix< std::string > to_string_matrix(void) const
const bool & get_reserve_training_direction_history(void) const
Returns true if the training direction history matrix is to be reserved, and false otherwise...
std::string write_training_direction_method(void) const
Returns a string with the name of the training direction.
Vector< Vector< double > > training_direction_history
History of the conjugate gradient training direction over the training iterations.
double gradient_norm_goal
Goal value for the norm of the objective function gradient. It is used as a stopping criterion...
const TrainingRateAlgorithm & get_training_rate_algorithm(void) const
Returns a constant reference to the training rate algorithm object inside the conjugate gradient meth...
Vector< double > parameters_norm_history
History of the parameters norm over the training iterations.
void set_error_gradient_norm(const double &)
bool reserve_training_rate_history
True if the training rate history vector is to be reserved, false otherwise.
bool reserve_generalization_performance_history
True if the Generalization performance history vector is to be reserved, false otherwise.
double final_performance
Final performance function evaluation.
void set_maximum_time(const double &)
const bool & get_reserve_parameters_norm_history(void) const
Returns true if the parameters norm history vector is to be reserved, and false otherwise.
bool reserve_training_direction_history
True if the training direction history matrix is to be reserved, false otherwise. ...
TrainingDirectionMethod
Enumeration of the available training operators for obtaining the training direction.
PerformanceFunctional * performance_functional_pointer
Pointer to a performance functional for a multilayer perceptron object.
TrainingRateAlgorithm * get_training_rate_algorithm_pointer(void)
Returns a pointer to the training rate algorithm object inside the conjugate gradient method object...
void set_save_period(const size_t &)
void set_warning_training_rate(const double &)
const size_t & get_maximum_iterations_number(void) const
Returns the maximum number of iterations for training.
void set_reserve_gradient_norm_history(const bool &)
void set_reserve_all_training_history(const bool &)
bool reserve_gradient_history
True if the gradient history matrix is to be reserved, false otherwise.
size_t display_period
Number of iterations between the training showing progress.
void set_display_period(const size_t &)
const double & get_error_training_rate(void) const
const double & get_maximum_time(void) const
Returns the maximum training time.
double final_generalization_performance
Final generalization performance.
void set_reserve_parameters_history(const bool &)
void set_reserve_training_direction_history(const bool &)
void set_reserve_performance_history(const bool &)
const double & get_error_gradient_norm(void) const
void set_parameters(const Vector< double > &)
const double & get_error_parameters_norm(void) const
Returns the value for the norm of the parameters vector at wich an error message is written to the sc...
Vector< double > elapsed_time_history
History of the elapsed time over the training iterations.