00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <iostream>
00019 #include <fstream>
00020 #include <math.h>
00021
00022
00023
00024 #include "cross_entropy_error.h"
00025
00026
00027
00028 #include "../../parsers/tinyxml/tinyxml.h"
00029
00030
00031 namespace OpenNN
00032 {
00033
00034
00035
00040
00041 CrossEntropyError::CrossEntropyError(void) : PerformanceTerm()
00042 {
00043 }
00044
00045
00046
00047
00052
00053 CrossEntropyError::CrossEntropyError(NeuralNetwork* new_neural_network_pointer)
00054 : PerformanceTerm(new_neural_network_pointer)
00055 {
00056 }
00057
00058
00059
00060
00065
00066 CrossEntropyError::CrossEntropyError(DataSet* new_data_set_pointer)
00067 : PerformanceTerm(new_data_set_pointer)
00068 {
00069 }
00070
00071
00072
00073
00079
00080 CrossEntropyError::CrossEntropyError(NeuralNetwork* new_neural_network_pointer, DataSet* new_data_set_pointer)
00081 : PerformanceTerm(new_neural_network_pointer, new_data_set_pointer)
00082 {
00083 }
00084
00085
00086
00087
00092
00093 CrossEntropyError::CrossEntropyError(TiXmlElement* sum_squared_error_element)
00094 : PerformanceTerm(sum_squared_error_element)
00095 {
00096 }
00097
00098
00099
00100
00101
00106
00107 CrossEntropyError::CrossEntropyError(const CrossEntropyError& new_cross_entropy_error)
00108 : PerformanceTerm(new_cross_entropy_error)
00109 {
00110
00111 }
00112
00113
00114
00115
00117
00118 CrossEntropyError::~CrossEntropyError(void)
00119 {
00120 }
00121
00122
00123
00124
00127
00128 CrossEntropyError& CrossEntropyError::operator = (const CrossEntropyError& other_cross_entropy_error)
00129 {
00130 if(this != &other_cross_entropy_error)
00131 {
00132 *neural_network_pointer = *other_cross_entropy_error.neural_network_pointer;
00133 *data_set_pointer = *other_cross_entropy_error.data_set_pointer;
00134 display = other_cross_entropy_error.display;
00135 }
00136
00137 return(*this);
00138
00139 }
00140
00141
00142
00146
00147 bool CrossEntropyError::operator == (const CrossEntropyError& other_cross_entropy_error) const
00148 {
00149 if(*neural_network_pointer == *other_cross_entropy_error.neural_network_pointer
00150 && *mathematical_model_pointer == *other_cross_entropy_error.mathematical_model_pointer
00151 && display == other_cross_entropy_error.display)
00152 {
00153 return(true);
00154 }
00155 else
00156 {
00157 return(false);
00158 }
00159
00160 }
00161
00162
00163
00164
00165
00166
00167
00170
00171 void CrossEntropyError::check(void) const
00172 {
00173 std::ostringstream buffer;
00174
00175
00176
00177 if(!neural_network_pointer)
00178 {
00179 buffer << "OpenNN Exception: CrossEntropyError class.\n"
00180 << "void check(void) const method.\n"
00181 << "Pointer to neural network is NULL.\n";
00182
00183 throw std::logic_error(buffer.str().c_str());
00184 }
00185
00186 const MultilayerPerceptron* multilayer_perceptron_pointer = neural_network_pointer->get_multilayer_perceptron_pointer();
00187
00188 if(!multilayer_perceptron_pointer)
00189 {
00190 buffer << "OpenNN Exception: CrossEntropyError class.\n"
00191 << "void check(void) const method.\n"
00192 << "Pointer to multilayer perceptron is NULL.\n";
00193
00194 throw std::logic_error(buffer.str().c_str());
00195 }
00196
00197 const unsigned int inputs_number = multilayer_perceptron_pointer->count_inputs_number();
00198 const unsigned int outputs_number = multilayer_perceptron_pointer->count_outputs_number();
00199
00200 if(inputs_number == 0)
00201 {
00202 buffer << "OpenNN Exception: CrossEntropyError class.\n"
00203 << "void check(void) const method.\n"
00204 << "Number of inputs in multilayer perceptron object is zero.\n";
00205
00206 throw std::logic_error(buffer.str().c_str());
00207 }
00208
00209 if(outputs_number == 0)
00210 {
00211 buffer << "OpenNN Exception: CrossEntropyError class.\n"
00212 << "void check(void) const method.\n"
00213 << "Number of outputs in multilayer perceptron object is zero.\n";
00214
00215 throw std::logic_error(buffer.str().c_str());
00216 }
00217
00218 const bool probabilistic_layer_flag = neural_network_pointer->get_probabilistic_layer_flag();
00219
00220 if(probabilistic_layer_flag == false)
00221 {
00222 buffer << "OpenNN Exception: CrossEntropyError class.\n"
00223 << "double calculate_evaluation(void) const method.\n"
00224 << "Probabilistc prostprocessing flag must be true.\n";
00225
00226 throw std::logic_error(buffer.str().c_str());
00227 }
00228
00229 const ProbabilisticLayer* probabilistic_layer_pointer = neural_network_pointer->get_probabilistic_layer_pointer();
00230
00231 if(!probabilistic_layer_pointer)
00232 {
00233 buffer << "OpenNN Exception: CrossEntropyError class.\n"
00234 << "void check(void) const method.\n"
00235 << "Pointer to probabilistic layer is NULL.\n";
00236
00237 throw std::logic_error(buffer.str().c_str());
00238 }
00239
00240 const ProbabilisticLayer::ProbabilisticMethod& outputs_probabilizing_method = probabilistic_layer_pointer->get_probabilistic_method();
00241
00242 if(outputs_probabilizing_method != ProbabilisticLayer::Softmax)
00243 {
00244 buffer << "OpenNN Exception: CrossEntropyError class.\n"
00245 << "void check(void) const method.\n"
00246 << "Probabilistic method is not Softmax.\n";
00247
00248 throw std::logic_error(buffer.str().c_str());
00249 }
00250
00251
00252
00253 if(!data_set_pointer)
00254 {
00255 buffer << "OpenNN Exception: CrossEntropyError class.\n"
00256 << "void check(void) const method.\n"
00257 << "Pointer to data set is NULL.\n";
00258
00259 throw std::logic_error(buffer.str().c_str());
00260 }
00261
00262
00263
00264 const VariablesInformation& variables_information = data_set_pointer->get_variables_information();
00265
00266 const unsigned int targets_number = variables_information.count_targets_number();
00267
00268 if(inputs_number != inputs_number)
00269 {
00270 buffer << "OpenNN Exception: CrossEntropyError class.\n"
00271 << "void check(void) const method.\n"
00272 << "Number of inputs in multilayer perceptron must be equal to number of inputs in data set.\n";
00273
00274 throw std::logic_error(buffer.str().c_str());
00275 }
00276
00277 if(outputs_number != targets_number)
00278 {
00279 buffer << "OpenNN Exception: CrossEntropyError class.\n"
00280 << "void check(void) const method.\n"
00281 << "Number of outputs in multilayer perceptron must be equal to number of targets in data set.\n";
00282
00283 throw std::logic_error(buffer.str().c_str());
00284 }
00285 }
00286
00287
00288
00289
00291
00292 double CrossEntropyError::calculate_evaluation(void) const
00293 {
00294 std::ostringstream buffer;
00295
00296 buffer << "OpenNN Exception: CrossEntropyError class.\n"
00297 << "double calculate_evaluation(void) method.\n"
00298 << "This method is under development.\n";
00299
00300 throw std::logic_error(buffer.str().c_str());
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354 }
00355
00356
00357
00358
00361
00362
00363 double CrossEntropyError::calculate_evaluation(const Vector<double>&) const
00364 {
00365 std::ostringstream buffer;
00366
00367 buffer << "OpenNN Exception: CrossEntropyError class.\n"
00368 << "double calculate_evaluation() method.\n"
00369 << "This method is under development.\n";
00370
00371 throw std::logic_error(buffer.str().c_str());
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409 }
00410
00411
00412
00413
00416
00417 double CrossEntropyError::calculate_minimum_objective(void)
00418 {
00419 return(0.0);
00420 }
00421
00422
00423
00424
00427
00428 double CrossEntropyError::calculate_generalization_evaluation(void) const
00429 {
00430
00431
00432 #ifdef _DEBUG
00433
00434 check();
00435
00436 #endif
00437
00438
00439
00440 const MultilayerPerceptron* multilayer_perceptron_pointer = neural_network_pointer->get_multilayer_perceptron_pointer();
00441
00442 const unsigned int inputs_number = multilayer_perceptron_pointer->count_inputs_number();
00443 const unsigned int outputs_number = multilayer_perceptron_pointer->count_outputs_number();
00444
00445
00446
00447 const InstancesInformation& instances_information = data_set_pointer->get_instances_information();
00448
00449 const unsigned int generalization_instances_number = instances_information.count_generalization_instances_number();
00450
00451 Vector<double> inputs(inputs_number);
00452 Vector<double> outputs(outputs_number);
00453 Vector<double> targets(outputs_number);
00454
00455 double generalization_evaluation = 0.0;
00456
00457 for(unsigned int i = 0; i < generalization_instances_number; i++)
00458 {
00459
00460
00461 inputs = data_set_pointer->get_generalization_input_instance(i);
00462
00463
00464
00465 outputs = multilayer_perceptron_pointer->calculate_outputs(inputs);
00466
00467
00468
00469 targets = data_set_pointer->get_generalization_target_instance(i);
00470
00471
00472
00473 for(unsigned int j = 0; j < outputs_number; j++)
00474 {
00475 generalization_evaluation -= targets[j]*log(outputs[j]) + (1.0 - targets[j])*log(1.0 - outputs[j]);
00476 }
00477 }
00478
00479 return(generalization_evaluation);
00480 }
00481
00482
00483
00484
00487
00488 double CrossEntropyError::calculate_minimum_generalization_objective(void)
00489 {
00490 return(0.0);
00491 }
00492
00493
00494
00495
00499
00500 Vector<double> CrossEntropyError::calculate_gradient(void) const
00501 {
00502 #ifdef _DEBUG
00503
00504 check();
00505
00506 #endif
00507
00508
00509
00510 const MultilayerPerceptron* multilayer_perceptron_pointer = neural_network_pointer->get_multilayer_perceptron_pointer();
00511
00512 const unsigned int inputs_number = multilayer_perceptron_pointer->count_inputs_number();
00513 const unsigned int outputs_number = multilayer_perceptron_pointer->count_outputs_number();
00514
00515 const unsigned int layers_number = multilayer_perceptron_pointer->count_layers_number();
00516
00517 const unsigned int network_parameters_number = multilayer_perceptron_pointer->count_parameters_number();
00518
00519 const ConditionsLayer* conditions_layer_pointer = neural_network_pointer->get_conditions_layer_pointer();
00520
00521 const bool& conditions_layer_flag = neural_network_pointer->get_conditions_layer_flag();
00522
00523 #ifdef _DEBUG
00524
00525 std::ostringstream buffer;
00526
00527 const Matrix<double> target_data = data_set_pointer->arrange_target_data();
00528
00529 if(target_data < 0.0)
00530 {
00531 buffer << "OpenNN Exception: CrossEntropyError class.\n"
00532 << "Vector<double> calculate_gradient(void) const method.\n"
00533 << "Target data must be equal or greater than zero.\n";
00534
00535 throw std::logic_error(buffer.str().c_str());
00536 }
00537
00538 if(target_data > 1.0)
00539 {
00540 buffer << "OpenNN Exception: CrossEntropyError class.\n"
00541 << "Vector<double> calculate_gradient(void) const method.\n"
00542 << "Target data must be less or equal or than one.\n";
00543
00544 throw std::logic_error(buffer.str().c_str());
00545 }
00546
00547 #endif
00548
00549
00550
00551 Vector< Vector< Vector<double> > > first_order_forward_propagation(2);
00552
00553 Vector<double> particular_solution;
00554 Vector<double> homogeneous_solution;
00555
00556
00557
00558 const InstancesInformation& instances_information = data_set_pointer->get_instances_information();
00559
00560 const unsigned int training_instances_number = instances_information.count_training_instances_number();
00561
00562 Vector<double> inputs(inputs_number);
00563 Vector<double> targets(outputs_number);
00564
00565
00566
00567 Vector<double> output_objective_gradient(outputs_number);
00568
00569 Vector< Vector<double> > layers_delta;
00570
00571 Vector<double> point_gradient(network_parameters_number, 0.0);
00572
00573 Vector<double> gradient(network_parameters_number, 0.0);
00574
00575
00576 for(unsigned int i = 0; i < training_instances_number; i++)
00577 {
00578 inputs = data_set_pointer->get_training_input_instance(i);
00579
00580 targets = data_set_pointer->get_training_target_instance(i);
00581
00582 first_order_forward_propagation = multilayer_perceptron_pointer->calculate_first_order_forward_propagation(inputs);
00583
00584 const Vector< Vector<double> >& layers_activation = first_order_forward_propagation[0];
00585 const Vector< Vector<double> >& layers_activation_derivative = first_order_forward_propagation[1];
00586
00587 if(!conditions_layer_flag)
00588 {
00589 const Vector<double>& outputs = layers_activation[layers_number-1];
00590
00591 for(unsigned int j = 0; j < outputs_number; j++)
00592 {
00593 output_objective_gradient[j] = -targets[j]/outputs[j] + (1.0 - targets[j])*(1.0 - outputs[j]);
00594 }
00595
00596 layers_delta = calculate_layers_delta(layers_activation_derivative, output_objective_gradient);
00597 }
00598 else
00599 {
00600 particular_solution = conditions_layer_pointer->calculate_particular_solution(inputs);
00601 homogeneous_solution = conditions_layer_pointer->calculate_homogeneous_solution(inputs);
00602
00603 Vector<double> outputs = particular_solution + homogeneous_solution*layers_activation[layers_number-1];
00604
00605 for(unsigned int j = 0; j < outputs_number; j++)
00606 {
00607 output_objective_gradient[j] = -targets[j]/outputs[j] + (1.0 - targets[j])*(1.0 - outputs[j]);
00608 }
00609
00610 layers_delta = calculate_layers_delta(layers_activation_derivative, homogeneous_solution, output_objective_gradient);
00611 }
00612
00613 point_gradient = calculate_point_gradient(inputs, layers_activation, layers_delta);
00614
00615 gradient += point_gradient;
00616 }
00617
00618 return(gradient);
00619 }
00620
00621
00622
00623
00625
00626 Matrix<double> CrossEntropyError::calculate_Hessian(void) const
00627 {
00628 Matrix<double> objective_Hessian;
00629
00630 return(objective_Hessian);
00631 }
00632
00633
00634
00635
00637
00638 std::string CrossEntropyError::write_performance_term_type(void) const
00639 {
00640 return("CROSS_ENTROPY_ERROR");
00641 }
00642
00643
00644
00645
00648
00649 TiXmlElement* CrossEntropyError::to_XML(void) const
00650 {
00651 std::ostringstream buffer;
00652
00653
00654
00655 TiXmlElement* cross_entropy_error_element = new TiXmlElement("CrossEntropyError");
00656 cross_entropy_error_element->SetAttribute("Version", 4);
00657
00658
00659
00660 {
00661 TiXmlElement* display_element = new TiXmlElement("Display");
00662 cross_entropy_error_element->LinkEndChild(display_element);
00663
00664 buffer.str("");
00665 buffer << display;
00666
00667 TiXmlText* display_text = new TiXmlText(buffer.str().c_str());
00668 display_element->LinkEndChild(display_text);
00669 }
00670
00671 return(cross_entropy_error_element);
00672 }
00673
00674
00675
00676
00679
00680 void CrossEntropyError::from_XML(TiXmlElement* cross_entropy_error_element)
00681 {
00682 if(cross_entropy_error_element)
00683 {
00684
00685 {
00686 TiXmlElement* display_element = cross_entropy_error_element->FirstChildElement("Display");
00687
00688 if(display_element)
00689 {
00690 std::string new_display_string = display_element->GetText();
00691
00692 try
00693 {
00694 set_display(new_display_string != "0");
00695 }
00696 catch(std::logic_error& e)
00697 {
00698 std::cout << e.what() << std::endl;
00699 }
00700 }
00701 }
00702 }
00703 }
00704
00705 }
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723