00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "../Utilities/Vector.h"
00019 #include "../Utilities/Matrix.h"
00020
00021 #include "ObjectiveFunctional.h"
00022
00023
00024
00025 #include <string>
00026 #include <sstream>
00027 #include <iostream>
00028 #include <cmath>
00029
00030
00031 namespace Flood
00032 {
00033
00034
00035
00039
00040 ObjectiveFunctional::ObjectiveFunctional(MultilayerPerceptron* new_multilayer_perceptron_pointer)
00041 {
00042 multilayer_perceptron_pointer = new_multilayer_perceptron_pointer;
00043
00044 set_default();
00045 }
00046
00047
00048
00049
00052
00053 ObjectiveFunctional::ObjectiveFunctional(void)
00054 {
00055 multilayer_perceptron_pointer = NULL;
00056
00057 set_default();
00058 }
00059
00060
00061
00062
00064
00065 ObjectiveFunctional::~ObjectiveFunctional(void)
00066 {
00067
00068 }
00069
00070
00071
00072
00073
00074
00076
00077 double ObjectiveFunctional::get_objective_weight(void)
00078 {
00079 return(objective_weight);
00080 }
00081
00082
00083
00084
00086
00087 ObjectiveFunctional::RegularizationMethod& ObjectiveFunctional::get_regularization_method(void)
00088 {
00089 return(regularization_method);
00090 }
00091
00092
00093
00094
00096
00097 std::string ObjectiveFunctional::get_regularization_method_name(void)
00098 {
00099 switch(regularization_method)
00100 {
00101 case None:
00102 {
00103 return("None");
00104 }
00105 break;
00106
00107 case NeuralParametersNorm:
00108 {
00109 return("NeuralParametersNorm");
00110 }
00111 break;
00112
00113 default:
00114 {
00115 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
00116 << "std::string get_regularization_method_name(void) method." << std::endl
00117 << "Unknown regularization method." << std::endl;
00118
00119 exit(1);
00120 }
00121 break;
00122 }
00123 }
00124
00125
00126
00127
00129
00130 double ObjectiveFunctional::get_regularization_weight(void)
00131 {
00132 return(regularization_weight);
00133 }
00134
00135
00136
00137
00139
00140 ObjectiveFunctional::NumericalDifferentiationMethod ObjectiveFunctional::get_numerical_differentiation_method(void)
00141 {
00142 return(numerical_differentiation_method);
00143 }
00144
00145
00146
00147
00149
00150 ObjectiveFunctional::NumericalEpsilonMethod ObjectiveFunctional::get_numerical_epsilon_method(void)
00151 {
00152 return(numerical_epsilon_method);
00153 }
00154
00155
00156
00157
00159
00160 std::string ObjectiveFunctional::get_numerical_differentiation_method_name(void)
00161 {
00162 switch(numerical_differentiation_method)
00163 {
00164 case ObjectiveFunctional::ForwardDifferences:
00165 {
00166 return("ForwardDifferences");
00167 }
00168 break;
00169
00170 case ObjectiveFunctional::CentralDifferences:
00171 {
00172 return("CentralDifferences");
00173 }
00174 break;
00175
00176 default:
00177 {
00178 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
00179 << "std::string get_numerical_differentiation_method(void) method." << std::endl
00180 << "Unknown numerical differentiation method." << std::endl;
00181
00182 exit(1);
00183 }
00184 break;
00185 }
00186 }
00187
00188
00189
00190
00192
00193 std::string ObjectiveFunctional::get_numerical_epsilon_method_name(void)
00194 {
00195 switch(numerical_differentiation_method)
00196 {
00197 case Absolute:
00198 {
00199 return("Absolute");
00200 }
00201 break;
00202
00203 case Relative:
00204 {
00205 return("Relative");
00206 }
00207 break;
00208
00209 default:
00210 {
00211 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
00212 << "std::string get_numerical_epsilon_method(int) method." << std::endl
00213 << "Unknown numerical epsilon method." << std::endl;
00214
00215 exit(1);
00216 }
00217 break;
00218 }
00219 }
00220
00221
00222
00223
00226
00227 double ObjectiveFunctional::get_numerical_epsilon(void)
00228 {
00229 return(numerical_epsilon);
00230 }
00231
00232
00233
00234
00236
00237 int ObjectiveFunctional::get_calculate_evaluation_count(void)
00238 {
00239 return(calculate_evaluation_count);
00240 }
00241
00242
00243
00244
00246
00247 int ObjectiveFunctional::get_calculate_gradient_count(void)
00248 {
00249 return(calculate_gradient_count);
00250 }
00251
00252
00253
00254
00256
00257 int ObjectiveFunctional::get_calculate_Hessian_count(void)
00258 {
00259 return(calculate_Hessian_count);
00260 }
00261
00262
00263
00264
00267
00268 bool ObjectiveFunctional::get_display(void)
00269 {
00270 return(display);
00271 }
00272
00273
00274
00275
00280
00281 void ObjectiveFunctional::set_multilayer_perceptron_pointer(MultilayerPerceptron* new_multilayer_perceptron_pointer)
00282 {
00283 multilayer_perceptron_pointer = new_multilayer_perceptron_pointer;
00284 }
00285
00286
00287
00288
00302
00303 void ObjectiveFunctional::set_default(void)
00304 {
00305
00306
00307 objective_weight = 1.0;
00308
00309
00310
00311 regularization_method = None;
00312 regularization_weight = 0.0;
00313
00314
00315
00316 calculate_evaluation_count = 0;
00317 calculate_gradient_count = 0;
00318 calculate_Hessian_count = 0;
00319
00320
00321
00322 numerical_differentiation_method = CentralDifferences;
00323 numerical_epsilon_method = Relative;
00324 numerical_epsilon = 1.0e-6;
00325
00326
00327
00328 display = true;
00329 }
00330
00331
00332
00335
00336 void ObjectiveFunctional::set_numerical_differentiation_method
00337 (const ObjectiveFunctional::NumericalDifferentiationMethod& new_numerical_differentiation_method)
00338 {
00339 numerical_differentiation_method = new_numerical_differentiation_method;
00340 }
00341
00342
00343
00344
00348
00349 void ObjectiveFunctional
00350 ::set_numerical_epsilon_method(const ObjectiveFunctional::NumericalEpsilonMethod& new_numerical_epsilon_method)
00351 {
00352 numerical_epsilon_method = new_numerical_epsilon_method;
00353 }
00354
00355
00356
00357
00360
00361 void ObjectiveFunctional::set_numerical_differentiation_method(const std::string& new_numerical_differentiation_method_name)
00362 {
00363 if(new_numerical_differentiation_method_name == "ForwardDifferences")
00364 {
00365 numerical_differentiation_method = ForwardDifferences;
00366 }
00367 else if(new_numerical_differentiation_method_name == "CentralDifferences")
00368 {
00369 numerical_differentiation_method = CentralDifferences;
00370 }
00371 else
00372 {
00373 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
00374 << "void set_numerical_differentiation_method(const std::string&) method." << std::endl
00375 << "Unknown numerical differentiation method: " << new_numerical_differentiation_method_name << "." <<std::endl;
00376
00377 exit(1);
00378 }
00379 }
00380
00381
00382
00385
00386 void ObjectiveFunctional::set_numerical_epsilon_method(const std::string& new_numerical_epsilon_method_name)
00387 {
00388 if(new_numerical_epsilon_method_name == "Absolute")
00389 {
00390 numerical_epsilon_method = Absolute;
00391 }
00392 else if(new_numerical_epsilon_method_name == "Relative")
00393 {
00394 numerical_epsilon_method = Relative;
00395 }
00396 else
00397 {
00398 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
00399 << "void set_numerical_epsilon_method_name(const std::string&) method." << std::endl
00400 << "Unknown numerical epsilon method: " << new_numerical_epsilon_method_name << "." <<std::endl;
00401
00402 exit(1);
00403 }
00404 }
00405
00406
00407
00408
00412
00413 void ObjectiveFunctional::set_numerical_epsilon(double new_numerical_epsilon)
00414 {
00415
00416
00417 #ifdef _DEBUG
00418
00419 if(new_numerical_epsilon <= 0.0)
00420 {
00421 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
00422 << "void set_numerical_epsilon(double) method." << std::endl
00423 << "Numerical epsilon must be greater than 0." << std::endl;
00424
00425 exit(1);
00426 }
00427
00428 #endif
00429
00430
00431
00432 numerical_epsilon = new_numerical_epsilon;
00433 }
00434
00435
00436
00437
00440
00441 void ObjectiveFunctional::set_objective_weight(double new_objective_weight)
00442 {
00443
00444
00445 #ifdef _DEBUG
00446
00447 if(new_objective_weight < 0.0)
00448 {
00449 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
00450 << "void set_objective_weight(double) method." << std::endl
00451 << "Objective weight must be equal or greater than 0." << std::endl;
00452
00453 exit(1);
00454 }
00455
00456 #endif
00457
00458 objective_weight = new_objective_weight;
00459 }
00460
00461
00462
00463
00466
00467 void ObjectiveFunctional::set_regularization_method
00468 (const ObjectiveFunctional::RegularizationMethod& new_regularization_method)
00469 {
00470 regularization_method = new_regularization_method;
00471 }
00472
00473
00474
00475
00478
00479 void ObjectiveFunctional::set_regularization_method(const std::string& new_regularization_method_name)
00480 {
00481 if(new_regularization_method_name == "None")
00482 {
00483 regularization_method = None;
00484 }
00485 else if(new_regularization_method_name == "NeuralParametersNorm")
00486 {
00487 regularization_method = NeuralParametersNorm;
00488 }
00489 else
00490 {
00491 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
00492 << "void set_regularization_method(const std::string&) method." << std::endl
00493 << "Unknown regularization method: " << new_regularization_method_name << "." <<std::endl;
00494
00495 exit(1);
00496 }
00497 }
00498
00499
00500
00501
00504
00505 void ObjectiveFunctional::set_regularization_weight(double new_regularization_weight)
00506 {
00507
00508
00509 #ifdef _DEBUG
00510
00511 if(new_regularization_weight < 0.0)
00512 {
00513 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
00514 << "void set_regularization_weight(double) method." << std::endl
00515 << "Regularization weight must be equal or greater than 0." << std::endl;
00516
00517 exit(1);
00518 }
00519
00520 #endif
00521
00522 regularization_weight = new_regularization_weight;
00523 }
00524
00525
00526
00527
00530
00531 void ObjectiveFunctional::set_calculate_evaluation_count(int new_calculate_evaluation_count)
00532 {
00533
00534
00535 if(new_calculate_evaluation_count < 0)
00536 {
00537 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
00538 << "void set_calculate_evaluation_count(int) method." << std::endl
00539 << "Count of calculate_evaluation() calls must be equal or greater than 0." << std::endl;
00540
00541 exit(1);
00542 }
00543
00544
00545
00546 calculate_evaluation_count = new_calculate_evaluation_count;
00547 }
00548
00549
00550
00551
00554
00555 void ObjectiveFunctional::set_calculate_gradient_count(int new_calculate_gradient_count)
00556 {
00557
00558
00559 if(new_calculate_gradient_count < 0)
00560 {
00561 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
00562 << "void set_calculate_gradient_count(int) method." << std::endl
00563 << "Count of calculate_gradient() calls must be equal or greater than 0." << std::endl;
00564
00565 exit(1);
00566 }
00567
00568
00569
00570 calculate_gradient_count = new_calculate_gradient_count;
00571 }
00572
00573
00574
00575
00578
00579 void ObjectiveFunctional::set_calculate_Hessian_count(int new_calculate_Hessian_count)
00580 {
00581
00582
00583 if(new_calculate_Hessian_count < 0)
00584 {
00585 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
00586 << "void set_calculate_gradient_count(int) method." << std::endl
00587 << "Count of calculate_Hessian() calls must be equal or greater than 0." << std::endl;
00588
00589 exit(1);
00590 }
00591
00592
00593
00594 calculate_Hessian_count = new_calculate_Hessian_count;
00595 }
00596
00597
00598
00599
00604
00605 void ObjectiveFunctional::set_display(bool new_display)
00606 {
00607 display = new_display;
00608 }
00609
00610
00611
00612
00615
00616 double ObjectiveFunctional::calculate_evaluation(void)
00617 {
00618
00619
00620 calculate_evaluation_count++;
00621
00622 if(regularization_method == None)
00623 {
00624 double objective = calculate_objective();
00625
00626 return(objective_weight*objective);
00627 }
00628 else
00629 {
00630 double objective = calculate_objective();
00631 double regularization = calculate_regularization();
00632
00633 return(objective_weight*objective + regularization_weight*regularization);
00634 }
00635 }
00636
00637
00638
00639
00642
00643 double ObjectiveFunctional::calculate_regularization(void)
00644 {
00645 switch(regularization_method)
00646 {
00647 case None:
00648 {
00649 return(0.0);
00650 }
00651 break;
00652
00653 case NeuralParametersNorm:
00654 {
00655 double regularization = multilayer_perceptron_pointer->calculate_neural_parameters_norm();
00656
00657 return(regularization);
00658 }
00659 break;
00660
00661 default:
00662 {
00663 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
00664 << "double calculate_regularization(void) method." << std::endl
00665 << "Unknown regularization method." << std::endl;
00666
00667 exit(1);
00668 }
00669 break;
00670 }
00671 }
00672
00673
00674
00675
00680
00681 double ObjectiveFunctional::calculate_potential_evaluation(const Vector<double>& potential_parameters)
00682 {
00683
00684
00685 #ifdef _DEBUG
00686
00687 int size = potential_parameters.get_size();
00688
00689 int parameters_number = multilayer_perceptron_pointer->get_parameters_number();
00690
00691 if(size != parameters_number)
00692 {
00693 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
00694 << "double calculate_potential_evaluation(const Vector<double>&) method." << std::endl
00695 << "Size (" << size << ") must be equal to number of parameters (" << parameters_number << ")." << std::endl;
00696
00697 exit(1);
00698 }
00699
00700 #endif
00701
00702 Vector<double> parameters = multilayer_perceptron_pointer->get_parameters();
00703
00704
00705
00706 multilayer_perceptron_pointer->set_parameters(potential_parameters);
00707
00708
00709
00710 double potential_evaluation = calculate_evaluation();
00711
00712
00713
00714 multilayer_perceptron_pointer->set_parameters(parameters);
00715
00716 return(potential_evaluation);
00717 }
00718
00719
00720
00721
00723
00724 Vector<double> ObjectiveFunctional::calculate_gradient(void)
00725 {
00726
00727
00728 calculate_gradient_count++;
00729
00730 if(regularization_method == None)
00731 {
00732 return(calculate_objective_gradient()*objective_weight);
00733 }
00734 else
00735 {
00736 return(calculate_objective_gradient()*objective_weight + calculate_regularization_gradient()*regularization_weight);
00737 }
00738 }
00739
00740
00741
00742
00744
00745 double ObjectiveFunctional::calculate_gradient_norm(void)
00746 {
00747 Vector<double> gradient = calculate_gradient();
00748
00749 return(gradient.calculate_norm());
00750 }
00751
00752
00753
00754
00757
00758 Vector<double> ObjectiveFunctional::calculate_objective_gradient(void)
00759 {
00760 Vector<double> neural_parameters_gradient = calculate_neural_parameters_gradient();
00761 Vector<double> independent_parameters_gradient = calculate_independent_parameters_gradient();
00762
00763 return(neural_parameters_gradient.assemble(independent_parameters_gradient));
00764 }
00765
00766
00767
00768
00770
00771 Vector<double> ObjectiveFunctional::calculate_objective_gradient_numerical_differentiation(void)
00772 {
00773 Vector<double> neural_parameters_gradient_numerical_differentiation = calculate_neural_parameters_gradient_numerical_differentiation();
00774 Vector<double> independent_parameters_gradient_numerical_differentiation = calculate_independent_parameters_gradient_numerical_differentiation();
00775
00776 return(neural_parameters_gradient_numerical_differentiation.assemble(independent_parameters_gradient_numerical_differentiation));
00777 }
00778
00779
00780
00781
00783
00784 Vector<double> ObjectiveFunctional::calculate_regularization_gradient(void)
00785 {
00786 switch(regularization_method)
00787 {
00788 case None:
00789 {
00790 int parameters_number = multilayer_perceptron_pointer->get_parameters_number();
00791
00792 Vector<double> regularization_gradient(parameters_number, 0.0);
00793
00794 return(regularization_gradient);
00795 }
00796 break;
00797
00798 case NeuralParametersNorm:
00799 {
00800 Vector<double> neural_parameters = multilayer_perceptron_pointer->get_neural_parameters();
00801
00802 double neural_parameters_norm = multilayer_perceptron_pointer->calculate_neural_parameters_norm();
00803
00804 Vector<double> neural_parameters_regularization_gradient = neural_parameters/neural_parameters_norm;
00805
00806 int independent_parameters_number = multilayer_perceptron_pointer->get_independent_parameters_number();
00807
00808 Vector<double> independent_parameters_regularization_gradient(independent_parameters_number, 0.0);
00809
00810 return(neural_parameters_regularization_gradient.assemble(independent_parameters_regularization_gradient));
00811 }
00812 break;
00813
00814 default:
00815 {
00816 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
00817 << "Vector<double> calculate_regularization_gradient(double) method." << std::endl
00818 << "Unknown regularization method." << std::endl;
00819
00820 exit(1);
00821 }
00822 break;
00823 }
00824 }
00825
00826
00827
00828
00832
00833 double ObjectiveFunctional::calculate_actual_epsilon(double parameter)
00834 {
00835 double actual_epsilon;
00836
00837
00838
00839 switch(numerical_epsilon_method)
00840 {
00841 case Absolute:
00842 {
00843 actual_epsilon = numerical_epsilon;
00844 }
00845 break;
00846
00847 case Relative:
00848 {
00849 if(fabs(parameter) < 1.0)
00850 {
00851 actual_epsilon = numerical_epsilon;
00852 }
00853 else
00854 {
00855 actual_epsilon = numerical_epsilon*fabs(parameter);
00856 }
00857 }
00858 break;
00859
00860 default:
00861 {
00862 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
00863 << "double calculate_actual_epsilon(double) method." << std::endl
00864 << "Unknown numerical epsilon method." << std::endl;
00865
00866 exit(1);
00867 }
00868 break;
00869 }
00870
00871 return(actual_epsilon);
00872 }
00873
00874
00875
00876
00880
00881 Vector<double> ObjectiveFunctional::calculate_neural_parameters_gradient_numerical_differentiation(void)
00882 {
00883 switch(numerical_differentiation_method)
00884 {
00885 case ForwardDifferences:
00886 {
00887 return(calculate_neural_parameters_gradient_forward_differences());
00888 }
00889
00890 break;
00891
00892 case CentralDifferences:
00893 {
00894 return(calculate_neural_parameters_gradient_central_differences());
00895 }
00896
00897 break;
00898
00899 default:
00900 {
00901 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
00902 << "Vector<double> calculate_neural_parameters_gradient_numerical_differentiation(void) method." << std::endl
00903 << "Unknown numerical differentiation method." << std::endl;
00904
00905 exit(1);
00906 }
00907 break;
00908 }
00909 }
00910
00911
00912
00913
00916
00917 Vector<double> ObjectiveFunctional::calculate_neural_parameters_gradient_forward_differences(void)
00918 {
00919 int neural_parameters_number = multilayer_perceptron_pointer->get_neural_parameters_number();
00920
00921 Vector<double> neural_parameters_gradient(neural_parameters_number);
00922
00923
00924
00925 Vector<double> potential_neural_parameters = multilayer_perceptron_pointer->get_neural_parameters();
00926
00927 Vector<double> scaled_independent_parameters = multilayer_perceptron_pointer->scale_independent_parameters();
00928
00929
00930
00931 double evaluation = calculate_evaluation();
00932
00933 double evaluation_forward;
00934
00935 double actual_epsilon;
00936
00937
00938
00939 for(int i = 0; i < neural_parameters_number; i++)
00940 {
00941
00942
00943 actual_epsilon = calculate_actual_epsilon(potential_neural_parameters[i]);
00944
00945
00946
00947 potential_neural_parameters[i] += actual_epsilon;
00948
00949
00950
00951 evaluation_forward = calculate_potential_evaluation(potential_neural_parameters.assemble(scaled_independent_parameters));
00952
00953
00954
00955 potential_neural_parameters[i] -= actual_epsilon;
00956
00957
00958
00959 neural_parameters_gradient[i] = (evaluation_forward - evaluation)/actual_epsilon;
00960 }
00961
00962 return(neural_parameters_gradient);
00963 }
00964
00965
00966
00967
00970
00971 Vector<double> ObjectiveFunctional::calculate_neural_parameters_gradient_central_differences(void)
00972 {
00973 int neural_parameters_number = multilayer_perceptron_pointer->get_neural_parameters_number();
00974
00975 Vector<double> neural_parameters_gradient(neural_parameters_number);
00976
00977 Vector<double> potential_neural_parameters = multilayer_perceptron_pointer->get_neural_parameters();
00978
00979 Vector<double> scaled_independent_parameters = multilayer_perceptron_pointer->scale_independent_parameters();
00980
00981 double actual_epsilon;
00982
00983 double evaluation_forward;
00984 double evaluation_backward;
00985
00986 for(int i = 0; i < neural_parameters_number; i++)
00987 {
00988
00989
00990 actual_epsilon = calculate_actual_epsilon(potential_neural_parameters[i]);
00991
00992
00993
00994 potential_neural_parameters[i] += actual_epsilon;
00995
00996
00997
00998 evaluation_forward = calculate_potential_evaluation(potential_neural_parameters.assemble(scaled_independent_parameters));
00999
01000
01001
01002 potential_neural_parameters[i] -= actual_epsilon;
01003
01004
01005
01006 potential_neural_parameters[i] -= actual_epsilon;
01007
01008
01009
01010 evaluation_backward = calculate_potential_evaluation(potential_neural_parameters.assemble(scaled_independent_parameters));
01011
01012
01013
01014 potential_neural_parameters[i] += actual_epsilon;
01015
01016
01017
01018 neural_parameters_gradient[i] = (evaluation_forward - evaluation_backward)/(2.0*actual_epsilon);
01019
01020 }
01021
01022 return(neural_parameters_gradient);
01023 }
01024
01025
01026
01027
01031
01032 Vector<double> ObjectiveFunctional::calculate_independent_parameters_gradient_numerical_differentiation(void)
01033 {
01034 switch(numerical_differentiation_method)
01035 {
01036 case ForwardDifferences:
01037 {
01038 return(calculate_independent_parameters_gradient_forward_differences());
01039 }
01040
01041 break;
01042
01043 case CentralDifferences:
01044 {
01045 return(calculate_independent_parameters_gradient_central_differences());
01046 }
01047
01048 break;
01049
01050 default:
01051 {
01052 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
01053 << "Vector<double> calculate_independent_parameters_gradient_numerical_differentiation(void) method." << std::endl
01054 << "Unknown numerical differentiation method." << std::endl;
01055
01056 exit(1);
01057 }
01058 break;
01059
01060 }
01061 }
01062
01063
01064
01065
01068
01069 Vector<double> ObjectiveFunctional::calculate_independent_parameters_gradient_forward_differences(void)
01070 {
01071
01072
01073
01074 Vector<double> neural_parameters = multilayer_perceptron_pointer->get_neural_parameters();
01075
01076 int independent_parameters_number = multilayer_perceptron_pointer->get_independent_parameters_number();
01077
01078 Vector<double> scaled_independent_parameters = multilayer_perceptron_pointer->scale_independent_parameters();
01079
01080 Vector<double> independent_parameters_lower_bound
01081 = multilayer_perceptron_pointer->get_independent_parameters_lower_bound();
01082
01083 Vector<double> independent_parameters_upper_bound
01084 = multilayer_perceptron_pointer->get_independent_parameters_upper_bound();
01085
01086
01087
01088 double evaluation = calculate_evaluation();
01089
01090 Vector<double> independent_parameters_gradient(independent_parameters_number);
01091
01092 double evaluation_forward;
01093 double actual_epsilon;
01094
01095
01096
01097 for(int i = 0; i < independent_parameters_number; i++)
01098 {
01099 if(independent_parameters_lower_bound != 0 && independent_parameters_upper_bound != 0)
01100 {
01101 if(independent_parameters_lower_bound[i] == independent_parameters_upper_bound[i])
01102 {
01103 independent_parameters_gradient[i] = 0.0;
01104 }
01105 }
01106 else
01107 {
01108
01109
01110 actual_epsilon = calculate_actual_epsilon(scaled_independent_parameters[i]);
01111
01112
01113
01114 scaled_independent_parameters[i] += actual_epsilon;
01115
01116
01117
01118 evaluation_forward = calculate_potential_evaluation(neural_parameters.assemble(scaled_independent_parameters));
01119
01120
01121
01122 scaled_independent_parameters[i] -= actual_epsilon;
01123
01124
01125
01126 independent_parameters_gradient[i] = (evaluation_forward - evaluation)/actual_epsilon;
01127 }
01128 }
01129
01130 return(independent_parameters_gradient);
01131 }
01132
01133
01134
01135
01138
01139 Vector<double> ObjectiveFunctional::calculate_independent_parameters_gradient_central_differences(void)
01140 {
01141
01142
01143 Vector<double> neural_parameters = multilayer_perceptron_pointer->get_neural_parameters();
01144
01145 int independent_parameters_number = multilayer_perceptron_pointer->get_independent_parameters_number();
01146
01147 Vector<double> scaled_independent_parameters = multilayer_perceptron_pointer->scale_independent_parameters();
01148
01149 Vector<double> independent_parameters_lower_bound
01150 = multilayer_perceptron_pointer->get_independent_parameters_lower_bound();
01151
01152 Vector<double> independent_parameters_upper_bound
01153 = multilayer_perceptron_pointer->get_independent_parameters_upper_bound();
01154
01155
01156
01157 Vector<double> independent_parameters_gradient(independent_parameters_number);
01158
01159 double actual_epsilon;
01160
01161 double evaluation_forward;
01162 double evaluation_backward;
01163
01164 for(int i = 0; i < independent_parameters_number; i++)
01165 {
01166 if(independent_parameters_lower_bound.get_size() != 0 && independent_parameters_upper_bound.get_size() != 0)
01167 {
01168 if(independent_parameters_lower_bound[i] == independent_parameters_upper_bound[i])
01169 {
01170 independent_parameters_gradient[i] = 0.0;
01171 }
01172 }
01173 else
01174 {
01175
01176
01177 actual_epsilon = calculate_actual_epsilon(scaled_independent_parameters[i]);
01178
01179
01180
01181 scaled_independent_parameters[i] += actual_epsilon;
01182
01183
01184
01185 evaluation_forward = calculate_potential_evaluation(neural_parameters.assemble(scaled_independent_parameters));
01186
01187
01188
01189 scaled_independent_parameters[i] -= actual_epsilon;
01190
01191
01192
01193 scaled_independent_parameters[i] -= actual_epsilon;
01194
01195
01196
01197 evaluation_backward = calculate_potential_evaluation(neural_parameters.assemble(scaled_independent_parameters));
01198
01199
01200
01201 scaled_independent_parameters[i] += actual_epsilon;
01202
01203
01204
01205 independent_parameters_gradient[i] = (evaluation_forward - evaluation_backward)/(2.0*actual_epsilon);
01206 }
01207 }
01208
01209 return(independent_parameters_gradient);
01210 }
01211
01212
01213
01214
01215 Vector<double> ObjectiveFunctional::calculate_neural_parameters_gradient(void)
01216 {
01217 return(calculate_neural_parameters_gradient_numerical_differentiation());
01218 }
01219
01220
01221
01222
01223 Vector<double> ObjectiveFunctional::calculate_independent_parameters_gradient(void)
01224 {
01225 return(calculate_independent_parameters_gradient_numerical_differentiation());
01226 }
01227
01228
01229
01230
01236
01237 Vector<double> ObjectiveFunctional::calculate_potential_gradient(const Vector<double>& potential_parameters)
01238 {
01239 #ifdef _DEBUG
01240
01241 if(multilayer_perceptron_pointer == NULL)
01242 {
01243 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
01244 << "double calculate_potential_gradient(const Vector<double>&) method." << std::endl
01245 << "Multilayer perceptron pointer cannot be NULL." << std::endl;
01246
01247 exit(1);
01248 }
01249
01250 #endif
01251
01252 int parameters_number = multilayer_perceptron_pointer->get_parameters_number();
01253
01254
01255
01256 #ifdef _DEBUG
01257
01258 int size = potential_parameters.get_size();
01259
01260 if(size != parameters_number)
01261 {
01262 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
01263 << "double calculate_potential_gradient(const Vector<double>&) method." << std::endl
01264 << "Size (" << size << ") must be equal to number of parameters (" << parameters_number << ")."
01265 << std::endl;
01266
01267 exit(1);
01268 }
01269
01270 #endif
01271
01272
01273
01274 Vector<double> parameters = multilayer_perceptron_pointer->get_parameters();
01275
01276 Vector<double> potential_gradient(parameters_number);
01277
01278
01279
01280 multilayer_perceptron_pointer->set_parameters(potential_parameters);
01281
01282
01283
01284 potential_gradient = calculate_gradient();
01285
01286
01287
01288 multilayer_perceptron_pointer->set_parameters(parameters);
01289
01290 return(potential_gradient);
01291 }
01292
01293
01294
01295
01299
01300 Matrix<double> ObjectiveFunctional::calculate_Hessian_forward_differences(void)
01301 {
01302 int parameters_number = multilayer_perceptron_pointer->get_parameters_number();
01303
01304 Matrix<double> Hessian(parameters_number, parameters_number);
01305
01306 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
01307 << "Matrix<double> calculate_Hessian_forward_differences(void) method." << std::endl
01308 << "Numerical differentiation of Hessian matrix with forward differences is not yet implemented." << std::endl
01309 << "Please use central differences." << std::endl;
01310
01311
01312 return(Hessian);
01313 }
01314
01315
01316
01317
01320
01321 Matrix<double> ObjectiveFunctional::calculate_Hessian_central_differences(void)
01322 {
01323 int parameters_number = multilayer_perceptron_pointer->get_parameters_number();
01324
01325 Matrix<double> Hessian(parameters_number, parameters_number);
01326
01327 Vector<double> potential_parameters = multilayer_perceptron_pointer->get_parameters();
01328
01329 double actual_epsilon_i = 0.0;
01330 double actual_epsilon_j = 0.0;
01331
01332 double evaluation_backward_backward = 0.0;
01333 double evaluation_backward_forward = 0.0;
01334 double evaluation_forward_backward = 0.0;
01335 double evaluation_forward_forward = 0.0;
01336
01337
01338
01339 for(int i = 0; i < parameters_number; i++)
01340 {
01341
01342
01343 actual_epsilon_i = calculate_actual_epsilon(potential_parameters[i]);
01344
01345 for(int j = i; j < parameters_number; j++)
01346 {
01347
01348
01349 actual_epsilon_j = calculate_actual_epsilon(potential_parameters[j]);
01350
01351
01352
01353 potential_parameters[i] += actual_epsilon_i;
01354 potential_parameters[j] += actual_epsilon_j;
01355
01356
01357
01358 evaluation_forward_forward = calculate_potential_evaluation(potential_parameters);
01359
01360
01361
01362 potential_parameters[i] -= actual_epsilon_i;
01363 potential_parameters[j] -= actual_epsilon_j;
01364
01365
01366
01367 potential_parameters[i] += actual_epsilon_i;
01368 potential_parameters[j] -= actual_epsilon_j;
01369
01370
01371
01372 evaluation_forward_backward = calculate_potential_evaluation(potential_parameters);
01373
01374
01375
01376 potential_parameters[i] -= actual_epsilon_i;
01377 potential_parameters[j] += actual_epsilon_j;
01378
01379
01380
01381 potential_parameters[i] -= actual_epsilon_i;
01382 potential_parameters[j] += actual_epsilon_j;
01383
01384
01385
01386 evaluation_backward_forward = calculate_potential_evaluation(potential_parameters);
01387
01388
01389
01390 potential_parameters[i] += actual_epsilon_i;
01391 potential_parameters[j] -= actual_epsilon_j;
01392
01393
01394
01395 potential_parameters[i] -= actual_epsilon_i;
01396 potential_parameters[j] -= actual_epsilon_j;
01397
01398
01399
01400 evaluation_backward_backward = calculate_potential_evaluation(potential_parameters);
01401
01402
01403
01404 potential_parameters[i] += actual_epsilon_i;
01405 potential_parameters[j] += actual_epsilon_j;
01406
01407
01408
01409 Hessian[i][j] = (evaluation_forward_forward - evaluation_forward_backward
01410 - evaluation_backward_forward + evaluation_backward_backward)
01411 /(4.0*pow(numerical_epsilon,2));
01412 }
01413 }
01414
01415
01416
01417 for(int i = 0; i < parameters_number; i++)
01418 {
01419 for(int j = 0; j < i; j++)
01420 {
01421 Hessian[i][j] = Hessian[j][i];
01422 }
01423 }
01424
01425 return(Hessian);
01426 }
01427
01428
01429
01430
01433
01434 Matrix<double> ObjectiveFunctional::calculate_Hessian_numerical_differentiation(void)
01435 {
01436 switch(numerical_differentiation_method)
01437 {
01438 case ForwardDifferences:
01439 {
01440 return(calculate_Hessian_forward_differences());
01441 }
01442
01443 break;
01444
01445 case CentralDifferences:
01446 {
01447 return(calculate_Hessian_central_differences());
01448 }
01449
01450 break;
01451
01452 default:
01453 {
01454 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
01455 << "double calculate_Hessian_numerical_differentiation(void) method." << std::endl
01456 << "Unknown numerical differentiation method." << std::endl;
01457
01458 exit(1);
01459 }
01460 break;
01461
01462 }
01463 }
01464
01465
01466
01467
01470
01471 Matrix<double> ObjectiveFunctional::calculate_Hessian(void)
01472 {
01473
01474
01475 calculate_Hessian_count++;
01476
01477 return(calculate_Hessian_numerical_differentiation());
01478 }
01479
01480
01481
01482
01488
01489 Matrix<double> ObjectiveFunctional::calculate_potential_Hessian(const Vector<double>& potential_parameters)
01490 {
01491 int parameters_number = multilayer_perceptron_pointer->get_parameters_number();
01492
01493
01494
01495 #ifdef _DEBUG
01496
01497 int size = potential_parameters.get_size();
01498
01499 if(size != parameters_number)
01500 {
01501 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
01502 << "double calculate_potential_Hessian(const Vector<double>&) method." << std::endl
01503 << "Size must be equal to number of parameters." << std::endl;
01504
01505 exit(1);
01506 }
01507
01508 #endif
01509
01510
01511
01512 Vector<double> original_parameters = multilayer_perceptron_pointer->get_parameters();
01513
01514 Matrix<double> potential_Hessian(parameters_number, parameters_number);
01515
01516
01517
01518 multilayer_perceptron_pointer->set_parameters(potential_parameters);
01519
01520
01521
01522 potential_Hessian = calculate_Hessian();
01523
01524
01525
01526 multilayer_perceptron_pointer->set_parameters(original_parameters);
01527
01528 return(potential_Hessian);
01529 }
01530
01531
01532
01533
01536
01537 Matrix<double> ObjectiveFunctional::calculate_inverse_Hessian(void)
01538 {
01539 Matrix<double> Hessian = calculate_Hessian();
01540
01541 Matrix<double> inverse_Hessian = Hessian.calculate_inverse();
01542
01543 return(inverse_Hessian);
01544 }
01545
01546
01547
01548
01556
01557 Matrix<double> ObjectiveFunctional::calculate_DFP_inverse_Hessian(
01558 const Vector<double>& old_parameters, const Vector<double>& parameters, const Vector<double>& old_gradient, const Vector<double>& gradient, const Matrix<double>& old_inverse_Hessian)
01559 {
01560
01561
01562 #ifdef _DEBUG
01563
01564 int parameters_number = multilayer_perceptron_pointer->get_parameters_number();
01565
01566 int old_parameters_size = old_parameters.get_size();
01567 int parameters_size = parameters.get_size();
01568
01569 if(old_parameters_size != parameters_number)
01570 {
01571 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
01572 << "Matrix<double> calculate_DFP_inverse_Hessian(const Vector<double>&, const Vector<double>&, const Vector<double>&, const Vector<double>&, const Matrix<double>&) method." << std::endl
01573 << "Size of old parameters vector must be equal to number of parameters." << std::endl;
01574
01575 exit(1);
01576 }
01577 else if(parameters_size != parameters_number)
01578 {
01579 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
01580 << "Matrix<double> calculate_DFP_inverse_Hessian(const Vector<double>&, const Vector<double>&, const Vector<double>&, const Vector<double>&, const Matrix<double>&) method." << std::endl
01581 << "Size of parameters vector must be equal to number of parameters." << std::endl;
01582
01583 exit(1);
01584 }
01585
01586 int old_gradient_size = old_gradient.get_size();
01587 int gradient_size = gradient.get_size();
01588
01589 if(old_gradient_size != parameters_number)
01590 {
01591 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
01592 << "Matrix<double> calculate_DFP_inverse_Hessian(const Vector<double>&, const Vector<double>&, const Vector<double>&, const Vector<double>&, const Matrix<double>&) method." << std::endl
01593 << "Size of old gradient vector must be equal to number of parameters." << std::endl;
01594
01595 exit(1);
01596 }
01597 else if(gradient_size != parameters_number)
01598 {
01599 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
01600 << "Matrix<double> calculate_DFP_inverse_Hessian(const Vector<double>&, const Vector<double>&, const Vector<double>&, const Vector<double>&, const Matrix<double>&) method." << std::endl
01601 << "Size of gradient vector must be equal to number of parameters." << std::endl
01602 << std::endl;
01603
01604 exit(1);
01605 }
01606
01607 int rows_number = old_inverse_Hessian.get_rows_number();
01608 int columns_number = old_inverse_Hessian.get_columns_number();
01609
01610 if(rows_number != parameters_number)
01611 {
01612 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
01613 << "Matrix<double> calculate_DFP_inverse_Hessian(const Vector<double>&, const Vector<double>&, const Vector<double>&, const Vector<double>&, const Matrix<double>&) method." << std::endl
01614 << "Number of rows in old inverse Hessian must be equal to number of parameters." << std::endl;
01615
01616 exit(1);
01617 }
01618 else if(columns_number != parameters_number)
01619 {
01620 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
01621 << "Matrix<double> calculate_DFP_inverse_Hessian(const Vector<double>&, const Vector<double>&, const Vector<double>&, const Vector<double>&, const Matrix<double>&) method." << std::endl
01622 << "Number of columns in old inverse Hessian must be equal to number of parameters." << std::endl;
01623
01624 exit(1);
01625 }
01626
01627 #endif
01628
01629
01630
01631 Vector<double> parameters_difference = parameters - old_parameters;
01632
01633
01634
01635 #ifdef _DEBUG
01636
01637 if(parameters_difference > -1.0e-50 && parameters_difference < 1.0e-50)
01638 {
01639 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
01640 << "Matrix<double> calculate_DFP_inverse_Hessian(const Vector<double>&, const Vector<double>&, const Vector<double>&, const Vector<double>&, const Matrix<double>&) method." << std::endl
01641 << "Parameters difference vector is zero." << std::endl;
01642
01643 exit(1);
01644 }
01645
01646 #endif
01647
01648
01649
01650 Vector<double> gradient_difference = gradient - old_gradient;
01651
01652
01653
01654 #ifdef _DEBUG
01655
01656 if(gradient_difference > -1.0e-50 && gradient_difference < 1.0e-50)
01657 {
01658 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
01659 << "Matrix<double> calculate_DFP_inverse_Hessian(const Vector<double>&, const Vector<double>&, const Vector<double>&, const Vector<double>&, const Matrix<double>&) method." << std::endl
01660 << "Gradient difference vector is zero." << std::endl;
01661
01662 exit(1);
01663 }
01664
01665 #endif
01666
01667
01668
01669 #ifdef _DEBUG
01670
01671 if(old_inverse_Hessian > -1.0e-50 && old_inverse_Hessian < 1.0e-50)
01672 {
01673 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
01674 << "Matrix<double> calculate_DFP_inverse_Hessian(const Vector<double>&, const Vector<double>&, const Vector<double>&, const Vector<double>&, const Matrix<double>&) method." << std::endl
01675 << "Old inverse Hessian matrix is zero." << std::endl;
01676
01677 exit(1);
01678 }
01679
01680 if(fabs(parameters_difference.dot(gradient_difference)) < 1.0e-50)
01681 {
01682 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
01683 << "Matrix<double> calculate_DFP_inverse_Hessian(const Vector<double>&, const Vector<double>&, const Vector<double>&, const Vector<double>&, const Matrix<double>&) method." << std::endl
01684 << "Denominator of first term is zero." << std::endl;
01685
01686 exit(1);
01687 }
01688 else if(fabs(gradient_difference.dot(old_inverse_Hessian).dot(gradient_difference)) < 1.0e-50)
01689 {
01690 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
01691 << "Matrix<double> calculate_DFP_inverse_Hessian(const Vector<double>&, const Vector<double>&, const Vector<double>&, const Vector<double>&, const Matrix<double>&) method." << std::endl
01692 << "Denominator of second term is zero." << std::endl;
01693
01694 exit(1);
01695 }
01696
01697 #endif
01698
01699 Matrix<double> DFP_inverse_Hessian = old_inverse_Hessian
01700 + parameters_difference.outer(parameters_difference)
01701 /parameters_difference.dot(gradient_difference)
01702 - (old_inverse_Hessian.dot(gradient_difference)).outer(old_inverse_Hessian.dot(gradient_difference))
01703 /gradient_difference.dot(old_inverse_Hessian).dot(gradient_difference);
01704
01705 return(DFP_inverse_Hessian);
01706
01707 }
01708
01709
01710
01711
01719
01720 Matrix<double> ObjectiveFunctional::calculate_BFGS_inverse_Hessian(
01721 const Vector<double>& old_parameters, const Vector<double>& parameters, const Vector<double>& old_gradient, const Vector<double>& gradient, const Matrix<double>& old_inverse_Hessian)
01722 {
01723
01724
01725 #ifdef _DEBUG
01726
01727 int parameters_number = multilayer_perceptron_pointer->get_parameters_number();
01728
01729 int old_parameters_size = old_parameters.get_size();
01730 int parameters_size = parameters.get_size();
01731
01732 if(old_parameters_size != parameters_number)
01733 {
01734 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
01735 << "Matrix<double> calculate_BFGS_inverse_Hessian(const Vector<double>&, const Vector<double>&, const Vector<double>&, const Vector<double>&, const Matrix<double>&) method." << std::endl
01736 << "Size of old parameters vector must be equal to number of parameters." << std::endl;
01737
01738 exit(1);
01739 }
01740 else if(parameters_size != parameters_number)
01741 {
01742 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
01743 << "Matrix<double> calculate_BFGS_inverse_Hessian(const Vector<double>&, const Vector<double>&, const Vector<double>&, const Vector<double>&, const Matrix<double>&) method." << std::endl
01744 << "Size of parameters vector must be equal to number of parameters." << std::endl;
01745
01746 exit(1);
01747 }
01748
01749 int old_gradient_size = old_gradient.get_size();
01750 int gradient_size = gradient.get_size();
01751
01752 if(old_gradient_size != parameters_number)
01753 {
01754 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
01755 << "Matrix<double> calculate_BFGS_inverse_Hessian(const Vector<double>&, const Vector<double>&, const Vector<double>&, const Vector<double>&, const Matrix<double>&) method." << std::endl
01756 << "Size of old gradient vector must be equal to number of parameters." << std::endl;
01757
01758 exit(1);
01759 }
01760 else if(gradient_size != parameters_number)
01761 {
01762 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
01763 << "Matrix<double> calculate_BFGS_inverse_Hessian(const Vector<double>&, const Vector<double>&, const Vector<double>&, const Vector<double>&, const Matrix<double>&) method." << std::endl
01764 << "Size of gradient vector must be equal to number of parameters." << std::endl;
01765
01766 exit(1);
01767 }
01768
01769 int rows_number = old_inverse_Hessian.get_rows_number();
01770 int columns_number = old_inverse_Hessian.get_columns_number();
01771
01772 if(rows_number != parameters_number)
01773 {
01774 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
01775 << "Matrix<double> calculate_BFGS_inverse_Hessian(const Vector<double>&, const Vector<double>&, const Vector<double>&, const Vector<double>&, const Matrix<double>&) method." << std::endl
01776 << "Number of rows in old inverse Hessian must be equal to number of parameters." << std::endl;
01777
01778 exit(1);
01779 }
01780 else if(columns_number != parameters_number)
01781 {
01782 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
01783 << "Matrix<double> calculate_BFGS_inverse_Hessian(const Vector<double>&, const Vector<double>&, const Vector<double>&, const Vector<double>&, const Matrix<double>&) method." << std::endl
01784 << "Number of columns in old inverse Hessian must be equal to number of parameters." << std::endl;
01785
01786 exit(1);
01787 }
01788
01789 #endif
01790
01791
01792
01793 Vector<double> parameters_difference = parameters - old_parameters;
01794
01795
01796
01797 #ifdef _DEBUG
01798
01799 if(parameters_difference > -1.0e-50 && parameters_difference < 1.0e-50)
01800 {
01801 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
01802 << "Matrix<double> calculate_BFGS_inverse_Hessian(const Vector<double>&, const Vector<double>&, const Vector<double>&, const Vector<double>&, const Matrix<double>&) method." << std::endl
01803 << "Parameters difference vector is zero." << std::endl;
01804
01805 exit(1);
01806 }
01807
01808 #endif
01809
01810
01811
01812 Vector<double> gradient_difference = gradient - old_gradient;
01813
01814
01815
01816 #ifdef _DEBUG
01817
01818 if(gradient_difference > -1.0e-50 && gradient_difference < 1.0e-50)
01819 {
01820 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
01821 << "Matrix<double> calculate_DFP_inverse_Hessian(const Vector<double>&, const Vector<double>&, const Vector<double>&, const Vector<double>&, const Matrix<double>&) method." << std::endl
01822 << "Gradient difference vector is zero." << std::endl;
01823
01824 exit(1);
01825 }
01826
01827 #endif
01828
01829
01830
01831 #ifdef _DEBUG
01832
01833 if(old_inverse_Hessian > -1.0e-50 && old_inverse_Hessian < 1.0e-50)
01834 {
01835 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
01836 << "Matrix<double> calculate_DFP_inverse_Hessian(const Vector<double>&, const Vector<double>&, const Vector<double>&, const Vector<double>&, const Matrix<double>&) method." << std::endl
01837 << "Old inverse Hessian matrix is zero." << std::endl;
01838
01839 exit(1);
01840 }
01841
01842 #endif
01843
01844
01845
01846 Vector<double> BFGS = parameters_difference/parameters_difference.dot(gradient_difference)
01847 - old_inverse_Hessian.dot(gradient_difference)
01848 /gradient_difference.dot(old_inverse_Hessian).dot(gradient_difference);
01849
01850
01851
01852 Matrix<double> BFGS_inverse_Hessian = old_inverse_Hessian
01853 + parameters_difference.outer(parameters_difference)
01854 /parameters_difference.dot(gradient_difference)
01855 - (old_inverse_Hessian.dot(gradient_difference)).outer(gradient_difference.dot(old_inverse_Hessian))
01856 /gradient_difference.dot(old_inverse_Hessian).dot(gradient_difference)
01857 + (BFGS.outer(BFGS))*(gradient_difference.dot(old_inverse_Hessian).dot(gradient_difference));
01858
01859 return(BFGS_inverse_Hessian);
01860 }
01861
01862
01863
01864
01869
01870 Vector<double> ObjectiveFunctional::calculate_vector_dot_Hessian_forward_differences(const Vector<double>&)
01871 {
01872 int parameters_number = multilayer_perceptron_pointer->get_parameters_number();
01873
01874 Vector<double> vector_Hessian_product(parameters_number);
01875
01876 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
01877 << "Vector<double> calculate_vector_dot_Hessian(Vector<double>) method." << std::endl
01878 << "Numerical differentiation of vector-Hessian matrix with forward differences is not yet implemented." << std::endl
01879 << "Please use central differences." << std::endl;
01880
01881
01882
01883 return(vector_Hessian_product);
01884 }
01885
01886
01887
01888
01892
01893 Vector<double> ObjectiveFunctional::calculate_vector_dot_Hessian_central_differences(const Vector<double>& vector)
01894 {
01895 int parameters_number = multilayer_perceptron_pointer->get_parameters_number();
01896
01897
01898
01899 #ifdef _DEBUG
01900
01901 int size = vector.get_size();
01902
01903 if(size != parameters_number)
01904 {
01905 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
01906 << "Vector<double> calculate_vector_dot_Hessian_central_differences(Vector<double>) method." << std::endl
01907 << "Size of vector must be equal to number of parameters." << std::endl;
01908
01909 exit(1);
01910 }
01911
01912 #endif
01913
01914 Vector<double> vector_Hessian_product;
01915
01916 Vector<double> gradient_forward(parameters_number);
01917 Vector<double> gradient_backward(parameters_number);
01918
01919 double actual_epsilon;
01920
01921 Vector<double> potential_parameters = multilayer_perceptron_pointer->get_parameters();
01922
01923 for(int i = 0; i < parameters_number; i++)
01924 {
01925
01926
01927 actual_epsilon = calculate_actual_epsilon(potential_parameters[i]);
01928
01929
01930
01931 potential_parameters[i] += actual_epsilon*vector[i];
01932
01933
01934
01935 gradient_forward = calculate_potential_gradient(potential_parameters);
01936
01937
01938
01939 potential_parameters[i] -= actual_epsilon*vector[i];
01940
01941
01942
01943 potential_parameters[i] -= actual_epsilon*vector[i];
01944
01945
01946
01947 gradient_backward = calculate_potential_gradient(potential_parameters);
01948
01949
01950
01951 potential_parameters[i] += actual_epsilon*vector[i];
01952
01953
01954
01955 vector_Hessian_product[i] = (gradient_forward[i] - gradient_backward[i])/(2.0*actual_epsilon);
01956 }
01957
01958 return(vector_Hessian_product);
01959 }
01960
01961
01962
01963
01967
01968 Vector<double> ObjectiveFunctional::calculate_vector_dot_Hessian(const Vector<double>& vector)
01969 {
01970
01971
01972 int size = vector.get_size();
01973
01974 int parameters_number = multilayer_perceptron_pointer->get_parameters_number();
01975
01976 if(size != parameters_number)
01977 {
01978 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
01979 << "Vector<double> calculate_vector_dot_Hessian(Vector<double>) method." << std::endl
01980 << "Size of vector must be equal to number of parameters." << std::endl;
01981
01982 exit(1);
01983 }
01984
01985
01986
01987 Vector<double> vector_Hessian_product(parameters_number);
01988
01989 switch(numerical_differentiation_method)
01990 {
01991 case ForwardDifferences:
01992 {
01993 vector_Hessian_product = calculate_vector_dot_Hessian_forward_differences(vector);
01994 }
01995
01996 break;
01997
01998 case CentralDifferences:
01999 {
02000 vector_Hessian_product = calculate_vector_dot_Hessian_central_differences(vector);
02001 }
02002
02003 break;
02004 }
02005
02006 return(vector_Hessian_product);
02007 }
02008
02009
02010
02011
02012 double ObjectiveFunctional::calculate_validation_error(void)
02013 {
02014 return(0.0);
02015 }
02016
02017
02018
02019
02022
02023 std::string ObjectiveFunctional::to_XML(bool show_declaration)
02024 {
02025 std::stringstream buffer;
02026
02027
02028
02029 if(show_declaration)
02030 {
02031 buffer << "<Flood version='3.0' class='ObjectiveFunctional'>" << std::endl;
02032 }
02033
02034 buffer << "<RegularizationMethod>" << std::endl
02035 << get_regularization_method_name() << std::endl
02036 << "</RegularizationMethod>" << std::endl;
02037
02038 buffer << "<ObjectiveWeight>" << std::endl
02039 << objective_weight << std::endl
02040 << "</ObjectiveWeight>" << std::endl;
02041 buffer << "<RegularizationWeight>" << std::endl
02042 << regularization_weight << std::endl
02043 << "</RegularizationWeight>" << std::endl;
02044
02045 buffer << "<CalculateEvaluationCount>" << std::endl
02046 << calculate_evaluation_count << std::endl
02047 << "</CalculateEvaluationCount>" << std::endl;
02048
02049 buffer << "<CalculateGradientCount>" << std::endl
02050 << calculate_gradient_count << std::endl
02051 << "</CalculateGradientCount>" << std::endl;
02052
02053 buffer << "<CalculateHessianCount>" << std::endl
02054 << calculate_Hessian_count << std::endl
02055 << "</CalculateHessianCount>" << std::endl;
02056
02057 buffer << "<NumericalDifferentiationMethod>" << std::endl
02058 << get_numerical_differentiation_method_name() << std::endl
02059 << "</NumericalDifferentiationMethod>" << std::endl;
02060
02061 buffer << "<NumericalEpsilonMethod>" << std::endl
02062 << get_numerical_epsilon_method_name() << std::endl
02063 << "</NumericalEpsilonMethod>" << std::endl;
02064
02065 buffer << "<NumericalEpsilon>" << std::endl
02066 << numerical_epsilon << std::endl
02067 << "</NumericalEpsilon>" << std::endl;
02068
02069 buffer << "<Display>" << std::endl
02070 << display << std::endl
02071 << "</Display>" << std::endl;
02072
02073 return(buffer.str());
02074 }
02075
02076
02077
02078
02080
02081 void ObjectiveFunctional::print(void)
02082 {
02083 std::cout << to_XML(true) << std::endl;
02084 }
02085
02086
02087
02088
02091
02092 void ObjectiveFunctional::save(const char* filename)
02093 {
02094 std::fstream file;
02095
02096 file.open(filename, std::ios::out);
02097
02098 if(!file.is_open())
02099 {
02100 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
02101 << "void save(const char*) method." << std::endl
02102 << "Cannot open objective functional XML-type file." << std::endl;
02103
02104 exit(1);
02105 }
02106
02107
02108
02109 file << to_XML(true);
02110
02111
02112
02113 file.close();
02114 }
02115
02116
02117
02118
02121
02122 void ObjectiveFunctional::load(const char* filename)
02123 {
02124 std::fstream file;
02125
02126 file.open(filename, std::ios::in);
02127
02128 if(!file.is_open())
02129 {
02130 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
02131 << "void load(const char*) method." << std::endl
02132 << "Cannot open objective functional XML-type file." << std::endl;
02133
02134 exit(1);
02135 }
02136
02137 std::string line;
02138 std::string word;
02139
02140
02141
02142 getline(file, line);
02143
02144 if(line != "<Flood version='3.0' class='ObjectiveFunctional'>")
02145 {
02146
02147
02148
02149
02150
02151 }
02152
02153
02154
02155 while(!file.eof())
02156 {
02157 file >> word;
02158
02159 if(word == "<RegularizationMethod>")
02160 {
02161 std::string new_regularization_method_name;
02162
02163 file >> new_regularization_method_name;
02164
02165 set_regularization_method(new_regularization_method_name);
02166
02167 file >> word;
02168
02169 if(word != "</RegularizationMethod>")
02170 {
02171 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
02172 << "void load(const char*) method." << std::endl
02173 << "Unknown regularization method end tag: " << word << std::endl;
02174
02175 exit(1);
02176 }
02177 }
02178 else if(word == "<ObjectiveWeight>")
02179 {
02180 double new_objective_weight;
02181
02182 file >> new_objective_weight;
02183
02184 set_objective_weight(new_objective_weight);
02185
02186 file >> word;
02187
02188 if(word != "</ObjectiveWeight>")
02189 {
02190 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
02191 << "void load(const char*) method." << std::endl
02192 << "Unknown objective weight end tag: " << word << std::endl;
02193
02194 exit(1);
02195 }
02196 }
02197 else if(word == "<RegularizationWeight>")
02198 {
02199 double new_regularization_weight;
02200
02201 file >> new_regularization_weight;
02202
02203 set_regularization_weight(new_regularization_weight);
02204
02205 file >> word;
02206
02207 if(word != "</RegularizationWeight>")
02208 {
02209 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
02210 << "void load(const char*) method." << std::endl
02211 << "Unknown regularization weight end tag: " << word << std::endl;
02212
02213 exit(1);
02214 }
02215 }
02216 else if(word == "<CalculateEvaluationCount>")
02217 {
02218 int new_calculate_evaluation_count;
02219
02220 file >> new_calculate_evaluation_count;
02221
02222 set_calculate_evaluation_count(new_calculate_evaluation_count);
02223
02224 file >> word;
02225
02226 if(word != "</CalculateEvaluationCount>")
02227 {
02228 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
02229 << "void load(const char*) method." << std::endl
02230 << "Unknown calculate evaluation count end tag: " << word << std::endl;
02231
02232 exit(1);
02233 }
02234 }
02235 else if(word == "<CalculateGradientCount>")
02236 {
02237 int new_calculate_gradient_count;
02238
02239 file >> new_calculate_gradient_count;
02240
02241 set_calculate_gradient_count(new_calculate_gradient_count);
02242
02243 file >> word;
02244
02245 if(word != "</CalculateGradientCount>")
02246 {
02247 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
02248 << "void load(const char*) method." << std::endl
02249 << "Unknown calculate gradient count end tag: " << word << std::endl;
02250
02251 exit(1);
02252 }
02253 }
02254 else if(word == "<CalculateHessianCount>")
02255 {
02256 int new_calculate_Hessian_count;
02257
02258 file >> new_calculate_Hessian_count;
02259
02260 set_calculate_Hessian_count(new_calculate_Hessian_count);
02261
02262 file >> word;
02263
02264 if(word != "</CalculateHessianCount>")
02265 {
02266 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
02267 << "void load(const char*) method." << std::endl
02268 << "Unknown calculate Hessian count end tag: " << word << std::endl;
02269
02270 exit(1);
02271 }
02272 }
02273 else if(word == "<NumericalDifferentiationMethod>")
02274 {
02275 std::string new_numerical_differentiation_method_name;
02276
02277 file >> new_numerical_differentiation_method_name;
02278
02279 set_numerical_differentiation_method(new_numerical_differentiation_method_name);
02280
02281 file >> word;
02282
02283 if(word != "</NumericalDifferentiationMethod>")
02284 {
02285 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
02286 << "void load(const char*) method." << std::endl
02287 << "Unknown numerical differentiation method end tag: " << word << std::endl;
02288
02289 exit(1);
02290 }
02291 }
02292 else if(word == "<NumericalEpsilonMethod>")
02293 {
02294 std::string new_numerical_epsilon_method_name;
02295
02296 file >> new_numerical_epsilon_method_name;
02297
02298 set_numerical_epsilon_method(new_numerical_epsilon_method_name);
02299
02300 file >> word;
02301
02302 if(word != "</NumericalEpsilonMethod>")
02303 {
02304 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
02305 << "void load(const char*) method." << std::endl
02306 << "Unknown numerical epsilon method end tag: " << word << std::endl;
02307
02308 exit(1);
02309 }
02310 }
02311 else if(word == "<NumericalEpsilon>")
02312 {
02313 double new_numerical_epsilon;
02314
02315 file >> new_numerical_epsilon;
02316
02317 set_numerical_epsilon(new_numerical_epsilon);
02318
02319 file >> word;
02320
02321 if(word != "</NumericalEpsilon>")
02322 {
02323 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
02324 << "void load(const char*) method." << std::endl
02325 << "Unknown numerical epsilon end tag: " << word << std::endl;
02326
02327 exit(1);
02328 }
02329 }
02330 else if(word == "<Display>")
02331 {
02332 bool new_display;
02333
02334 file >> new_display;
02335
02336 set_display(new_display);
02337
02338 file >> word;
02339
02340 if(word != "</Display>")
02341 {
02342 std::cerr << "Flood Error: ObjectiveFunctional class." << std::endl
02343 << "void load(const char*) method." << std::endl
02344 << "Unknown display end tag: " << word << std::endl;
02345
02346 exit(1);
02347 }
02348 }
02349 else
02350 {
02351
02352
02353
02354
02355
02356 }
02357 }
02358
02359 file.close();
02360 }
02361
02362
02363
02364
02367
02368 void ObjectiveFunctional::print_information(void)
02369 {
02370
02371 }
02372
02373 }
02374
02375
02376
02377
02378
02379
02380
02381
02382
02383
02384
02385
02386
02387
02388
02389
02390
02391