00001 /****************************************************************************************************************/ 00002 /* */ 00003 /* OpenNN: Open Neural Networks Library */ 00004 /* www.opennn.cimne.com */ 00005 /* */ 00006 /* M U L T I L A Y E R P E R C E P T R O N C L A S S */ 00007 /* */ 00008 /* Roberto Lopez */ 00009 /* International Center for Numerical Methods in Engineering (CIMNE) */ 00010 /* Technical University of Catalonia (UPC) */ 00011 /* Barcelona, Spain */ 00012 /* E-mail: rlopez@cimne.upc.edu */ 00013 /* */ 00014 /****************************************************************************************************************/ 00015 00016 // System includes 00017 00018 #include <cmath> 00019 #include <cstdlib> 00020 #include <fstream> 00021 #include <iostream> 00022 #include <string> 00023 #include <sstream> 00024 00025 // OpenNN includes 00026 00027 #include "probabilistic_layer.h" 00028 00029 // TinyXml includes 00030 00031 #include "../../parsers/tinyxml/tinyxml.h" 00032 00033 namespace OpenNN 00034 { 00035 00036 // DEFAULT CONSTRUCTOR 00037 00040 00041 ProbabilisticLayer::ProbabilisticLayer(void) 00042 { 00043 set(); 00044 } 00045 00046 00047 // PROBABILISTIC NEURONS NUMBER CONSTRUCTOR 00048 00052 00053 ProbabilisticLayer::ProbabilisticLayer(const unsigned int& new_probabilistic_neurons_number) 00054 { 00055 set(new_probabilistic_neurons_number); 00056 } 00057 00058 00059 // COPY CONSTRUCTOR 00060 00064 00065 ProbabilisticLayer::ProbabilisticLayer(const ProbabilisticLayer& other_probabilistic_layer) 00066 { 00067 set(other_probabilistic_layer); 00068 } 00069 00070 00071 // DESTRUCTOR 00072 00075 00076 ProbabilisticLayer::~ProbabilisticLayer(void) 00077 { 00078 } 00079 00080 00081 // ASSIGNMENT OPERATOR 00082 00086 00087 ProbabilisticLayer& ProbabilisticLayer::operator = (const ProbabilisticLayer& other_probabilistic_layer) 00088 { 00089 if(this != &other_probabilistic_layer) 00090 { 00091 probabilistic_neurons_number = other_probabilistic_layer.probabilistic_neurons_number; 00092 00093 probabilistic_method = other_probabilistic_layer.probabilistic_method; 00094 00095 display = other_probabilistic_layer.display; 00096 } 00097 00098 return(*this); 00099 } 00100 00101 00102 // EQUAL TO OPERATOR 00103 00104 // bool operator == (const ProbabilisticLayer&) const method 00105 00110 00111 bool ProbabilisticLayer::operator == (const ProbabilisticLayer& other_probabilistic_layer) const 00112 { 00113 if(probabilistic_neurons_number == other_probabilistic_layer.probabilistic_neurons_number 00114 && probabilistic_method == other_probabilistic_layer.probabilistic_method 00115 && display == other_probabilistic_layer.display) 00116 { 00117 return(true); 00118 } 00119 else 00120 { 00121 return(false); 00122 } 00123 } 00124 00125 00126 // METHODS 00127 00128 // const unsigned int& get_outputs_number(void) const method 00129 00131 00132 const unsigned int& ProbabilisticLayer::get_probabilistic_neurons_number(void) const 00133 { 00134 return(probabilistic_neurons_number); 00135 } 00136 00137 00138 // const ProbabilisticMethod& get_probabilistic_method(void) const method 00139 00142 00143 const ProbabilisticLayer::ProbabilisticMethod& ProbabilisticLayer::get_probabilistic_method(void) const 00144 { 00145 return(probabilistic_method); 00146 } 00147 00148 00149 // std::string write_probabilistic_method(void) const method 00150 00152 00153 std::string ProbabilisticLayer::write_probabilistic_method(void) const 00154 { 00155 if(probabilistic_method == Competitive) 00156 { 00157 return("Competitive"); 00158 } 00159 else if(probabilistic_method == Softmax) 00160 { 00161 return("Softmax"); 00162 } 00163 else 00164 { 00165 std::ostringstream buffer; 00166 00167 buffer << "OpenNN Exception: ProbabilisticLayer class.\n" 00168 << "std::string write_probabilistic_method(void) const method.\n" 00169 << "Unknown probabilistic method.\n"; 00170 00171 throw std::logic_error(buffer.str()); 00172 } 00173 } 00174 00175 00176 // const bool& get_display(void) const method 00177 00180 00181 const bool& ProbabilisticLayer::get_display(void) const 00182 { 00183 return(display); 00184 } 00185 00186 00187 // void set(void) method 00188 00191 00192 void ProbabilisticLayer::set(void) 00193 { 00194 probabilistic_neurons_number = 0; 00195 00196 set_default(); 00197 } 00198 00199 00200 // void set(const unsigned int&) method 00201 00205 00206 void ProbabilisticLayer::set(const unsigned int& new_probabilistic_neurons_number) 00207 { 00208 probabilistic_neurons_number = new_probabilistic_neurons_number; 00209 00210 set_default(); 00211 } 00212 00213 00214 // void set(const ProbabilisticLayer&) method 00215 00218 00219 void ProbabilisticLayer::set(const ProbabilisticLayer& other_probabilistic_layer) 00220 { 00221 probabilistic_neurons_number = other_probabilistic_layer.probabilistic_neurons_number; 00222 00223 probabilistic_method = other_probabilistic_layer.probabilistic_method; 00224 00225 display = other_probabilistic_layer.display; 00226 } 00227 00228 00229 // void set_probabilistic_neurons_number(const unsigned int&) method 00230 00233 00234 void ProbabilisticLayer::set_probabilistic_neurons_number(const unsigned int& new_probabilistic_neurons_number) 00235 { 00236 probabilistic_neurons_number = new_probabilistic_neurons_number; 00237 } 00238 00239 00240 // void set_default(void) method 00241 00247 00248 void ProbabilisticLayer::set_default(void) 00249 { 00250 probabilistic_method = Softmax; 00251 00252 display = true; 00253 } 00254 00255 00256 // void set_probablistic_method(const ProbabilisticMethod&) method 00257 00261 00262 void ProbabilisticLayer::set_probabilistic_method(const ProbabilisticMethod& new_probabilistic_method) 00263 { 00264 probabilistic_method = new_probabilistic_method; 00265 } 00266 00267 00268 // void set_probabilistic_method(const std::string&) method 00269 00273 00274 void ProbabilisticLayer::set_probabilistic_method(const std::string& new_probabilistic_method) 00275 { 00276 if(new_probabilistic_method == "Competitive") 00277 { 00278 set_probabilistic_method(Competitive); 00279 } 00280 else if(new_probabilistic_method == "Softmax") 00281 { 00282 set_probabilistic_method(Softmax); 00283 } 00284 else 00285 { 00286 std::ostringstream buffer; 00287 00288 buffer << "OpenNN Exception: ProbabilisticLayer class.\n" 00289 << "void set_probabilistic_method(const std::string&) method.\n" 00290 << "Unknown probabilistic method: " << new_probabilistic_method << ".\n"; 00291 00292 throw std::logic_error(buffer.str()); 00293 } 00294 } 00295 00296 00297 // void set_display(const bool&) method 00298 00303 00304 void ProbabilisticLayer::set_display(const bool& new_display) 00305 { 00306 display = new_display; 00307 } 00308 00309 00310 // void initialize_random(void) method 00311 00313 00314 void ProbabilisticLayer::initialize_random(void) 00315 { 00316 00317 } 00318 00319 00320 // Vector<double> calculate_outputs(const Vector<double>&) const method 00321 00325 00326 Vector<double> ProbabilisticLayer::calculate_outputs(const Vector<double>& inputs) const 00327 { 00328 // Control sentence (if debug) 00329 00330 #ifdef _DEBUG 00331 00332 const unsigned int size = inputs.size(); 00333 00334 if(size != probabilistic_neurons_number) 00335 { 00336 std::ostringstream buffer; 00337 00338 buffer << "OpenNN Exception: ProbabilisticLayer class.\n" 00339 << "Vector<double> calculate_outputs(const Vector<double>&) const method.\n" 00340 << "Size must be equal to number of probabilistic neurons.\n"; 00341 00342 throw std::logic_error(buffer.str()); 00343 } 00344 00345 #endif 00346 00347 switch(probabilistic_method) 00348 { 00349 case Competitive: 00350 { 00351 return(calculate_competitive_output(inputs)); 00352 } 00353 break; 00354 00355 case Softmax: 00356 { 00357 return(calculate_softmax_output(inputs)); 00358 } 00359 break; 00360 00361 default: 00362 { 00363 std::ostringstream buffer; 00364 00365 buffer << "OpenNN Exception: ProbabilisticLayer class.\n" 00366 << "Vector<double> calculate_outputs(const Vector<double>&) const method.\n" 00367 << "Unknown probabilistic method.\n"; 00368 00369 throw std::logic_error(buffer.str()); 00370 }// end default 00371 break; 00372 00373 }// end switch 00374 } 00375 00376 00377 // Matrix<double> calculate_Jacobian(const Vector<double>&) const method 00378 00383 00384 Matrix<double> ProbabilisticLayer::calculate_Jacobian(const Vector<double>& inputs) const 00385 { 00386 // Control sentence (if debug) 00387 00388 #ifdef _DEBUG 00389 00390 const unsigned int size = inputs.size(); 00391 00392 if(size != probabilistic_neurons_number) 00393 { 00394 std::ostringstream buffer; 00395 00396 buffer << "OpenNN Exception: ProbabilisticLayer class.\n" 00397 << "Matrix<double> calculate_Jacobian(const Vector<double>&) const method.\n" 00398 << "Size must be equal to number of probabilistic neurons.\n"; 00399 00400 throw std::logic_error(buffer.str()); 00401 } 00402 00403 #endif 00404 00405 switch(probabilistic_method) 00406 { 00407 case Competitive: 00408 { 00409 return(calculate_competitive_Jacobian(inputs)); 00410 } 00411 break; 00412 00413 case Softmax: 00414 { 00415 return(calculate_softmax_Jacobian(inputs)); 00416 } 00417 break; 00418 00419 default: 00420 { 00421 std::ostringstream buffer; 00422 00423 buffer << "OpenNN Exception: ProbabilisticLayer class.\n" 00424 << "Matrix<double> calculate_Jacobian(const Vector<double>&) const method.\n" 00425 << "Unknown probabilistic method.\n"; 00426 00427 throw std::logic_error(buffer.str()); 00428 }// end default 00429 break; 00430 00431 }// end switch 00432 } 00433 00434 00435 // Vector< Matrix<double> > calculate_Hessian_form(const Vector<double>&) const method 00436 00440 00441 Vector< Matrix<double> > ProbabilisticLayer::calculate_Hessian_form(const Vector<double>& inputs) const 00442 { 00443 // Control sentence (if debug) 00444 00445 #ifdef _DEBUG 00446 00447 const unsigned int size = inputs.size(); 00448 00449 if(size != probabilistic_neurons_number) 00450 { 00451 std::ostringstream buffer; 00452 00453 buffer << "OpenNN Exception: ProbabilisticLayer class.\n" 00454 << "Matrix<double> calculate_Hessian_form(const Vector<double>&) const method.\n" 00455 << "Size must be equal to number of probabilistic neurons.\n"; 00456 00457 throw std::logic_error(buffer.str()); 00458 } 00459 00460 #endif 00461 00462 switch(probabilistic_method) 00463 { 00464 case Competitive: 00465 { 00466 return(calculate_competitive_Hessian_form(inputs)); 00467 } 00468 break; 00469 00470 case Softmax: 00471 { 00472 return(calculate_softmax_Hessian_form(inputs)); 00473 } 00474 break; 00475 00476 default: 00477 { 00478 std::ostringstream buffer; 00479 00480 buffer << "OpenNN Exception: ProbabilisticLayer class.\n" 00481 << "Matrix<double> calculate_Hessian_form(const Vector<double>&) const method.\n" 00482 << "Unknown probabilistic method.\n"; 00483 00484 throw std::logic_error(buffer.str()); 00485 }// end default 00486 break; 00487 00488 }// end switch 00489 } 00490 00491 00492 // Vector<double> calculate_competitive_output(const Vector<double>&) const method 00493 00496 00497 Vector<double> ProbabilisticLayer::calculate_competitive_output(const Vector<double>& inputs) const 00498 { 00499 return(inputs.calculate_competitive()); 00500 } 00501 00502 00503 // Matrix<double> calculate_competitive_Jacobian(const Vector<double>&) const method 00504 00506 00507 Matrix<double> ProbabilisticLayer::calculate_competitive_Jacobian(const Vector<double>&) const 00508 { 00509 std::ostringstream buffer; 00510 00511 buffer << "OpenNN Exception: ProbabilisticLayer class.\n" 00512 << "Matrix<double> calculate_competitive_Jacobian(const Vector<double>&) const method.\n" 00513 << "The competitive function is not derivable.\n"; 00514 00515 throw std::logic_error(buffer.str()); 00516 } 00517 00518 00519 // Vector< Matrix<double> > calculate_competitive_Hessian_form(const Vector<double>&) const method 00520 00522 00523 Vector< Matrix<double> > ProbabilisticLayer::calculate_competitive_Hessian_form(const Vector<double>&) const 00524 { 00525 std::ostringstream buffer; 00526 00527 buffer << "OpenNN Exception: ProbabilisticLayer class.\n" 00528 << "Vector< Matrix<double> > calculate_competitive_Hessian_form(const Vector<double>&) const method.\n" 00529 << "The competitive function is not derivable.\n"; 00530 00531 throw std::logic_error(buffer.str()); 00532 } 00533 00534 00535 // Vector<double> calculate_softmax_output(const Vector<double>&) const method 00536 00539 00540 Vector<double> ProbabilisticLayer::calculate_softmax_output(const Vector<double>& inputs) const 00541 { 00542 return(inputs.calculate_softmax()); 00543 } 00544 00545 00546 // Matrix<double> calculate_softmax_Jacobian(const Vector<double>&) const method 00547 00550 00551 Matrix<double> ProbabilisticLayer::calculate_softmax_Jacobian(const Vector<double>& inputs) const 00552 { 00553 Matrix<double> probabilistic_Jacobian(probabilistic_neurons_number, probabilistic_neurons_number); 00554 00555 const Vector<double> outputs = inputs.calculate_softmax(); 00556 00557 for(unsigned int i = 0; i < probabilistic_neurons_number; i++) 00558 { 00559 for(unsigned int j = 0; j < probabilistic_neurons_number; j++) 00560 { 00561 if(i == j) 00562 { 00563 probabilistic_Jacobian[i][i] = outputs[i]*(1.0 - outputs[i]); 00564 } 00565 else 00566 { 00567 probabilistic_Jacobian[i][j] = -outputs[i]*outputs[j]; 00568 } 00569 } 00570 } 00571 00572 return(probabilistic_Jacobian); 00573 } 00574 00575 00576 // Vector< Matrix<double> > calculate_softmax_Hessian_form(const Vector<double>&) const method 00577 00581 00582 Vector< Matrix<double> > ProbabilisticLayer::calculate_softmax_Hessian_form(const Vector<double>&) const 00583 { 00584 Vector< Matrix<double> > Hessian_form; 00585 00586 return(Hessian_form); 00587 } 00588 00589 00590 // std::string to_string(void) const method 00591 00593 00594 std::string ProbabilisticLayer::to_string(void) const 00595 { 00596 std::ostringstream buffer; 00597 00598 buffer << "Probabilistic layer\n" 00599 << "Probabilistic neurons number: " << probabilistic_neurons_number << "\n" 00600 << "Probabilistic method: " << write_probabilistic_method() << "\n" 00601 << "Display: "<< display << "\n"; 00602 00603 return(buffer.str()); 00604 } 00605 00606 00607 // TiXmlElement* to_XML(void) const method 00608 00611 00612 TiXmlElement* ProbabilisticLayer::to_XML(void) const 00613 { 00614 std::ostringstream buffer; 00615 00616 TiXmlElement* probabilistic_layer_element = new TiXmlElement("ProbabilisticLayer"); 00617 probabilistic_layer_element->SetAttribute("Version", 4); 00618 00619 // Probabilistic neurons number 00620 { 00621 TiXmlElement* element = new TiXmlElement("ProbabilisticNeuronsNumber"); 00622 probabilistic_layer_element->LinkEndChild(element); 00623 00624 buffer.str(""); 00625 buffer << probabilistic_neurons_number; 00626 00627 TiXmlText* text = new TiXmlText(buffer.str().c_str()); 00628 element->LinkEndChild(text); 00629 } 00630 00631 // Probabilistic method 00632 00633 { 00634 TiXmlElement* element = new TiXmlElement("ProbabilisticMethod"); 00635 probabilistic_layer_element->LinkEndChild(element); 00636 00637 TiXmlText* text = new TiXmlText(write_probabilistic_method().c_str()); 00638 element->LinkEndChild(text); 00639 } 00640 00641 // Display 00642 { 00643 TiXmlElement* element = new TiXmlElement("Display"); 00644 probabilistic_layer_element->LinkEndChild(element); 00645 00646 buffer.str(""); 00647 buffer << display; 00648 00649 TiXmlText* text = new TiXmlText(buffer.str().c_str()); 00650 element->LinkEndChild(text); 00651 } 00652 00653 return(probabilistic_layer_element); 00654 } 00655 00656 00657 // void from_XML(TiXmlElement*) method 00658 00661 00662 void ProbabilisticLayer::from_XML(TiXmlElement* probabilistic_layer_element) 00663 { 00664 if(probabilistic_layer_element) 00665 { 00666 // Probabilistic neurons number 00667 { 00668 TiXmlElement* element = probabilistic_layer_element->FirstChildElement("ProbabilisticNeuronsNumber"); 00669 00670 if(element) 00671 { 00672 const char* text = element->GetText(); 00673 00674 if(text) 00675 { 00676 try 00677 { 00678 set_probabilistic_neurons_number(atoi(text)); 00679 } 00680 catch(std::exception& e) 00681 { 00682 std::cout << e.what() << std::endl; 00683 } 00684 } 00685 } 00686 } 00687 00688 // Probabilistic method 00689 { 00690 TiXmlElement* element = probabilistic_layer_element->FirstChildElement("ProbabilisticMethod"); 00691 00692 if(element) 00693 { 00694 const char* text = element->GetText(); 00695 00696 if(text) 00697 { 00698 try 00699 { 00700 std::string new_probabilistic_method(text); 00701 00702 set_probabilistic_method(new_probabilistic_method); 00703 } 00704 catch(std::exception& e) 00705 { 00706 std::cout << e.what() << std::endl; 00707 } 00708 } 00709 } 00710 } 00711 00712 // Display 00713 { 00714 TiXmlElement* display_element = probabilistic_layer_element->FirstChildElement("Display"); 00715 00716 if(display_element) 00717 { 00718 std::string new_display_string = display_element->GetText(); 00719 00720 try 00721 { 00722 set_display(new_display_string != "0"); 00723 } 00724 catch(std::exception& e) 00725 { 00726 std::cout << e.what() << std::endl; 00727 } 00728 } 00729 } 00730 } 00731 } 00732 00733 00734 // std::string write_competitive_expression(const Vector<std::string>&, const Vector<std::string>&) const method 00735 00739 00740 std::string ProbabilisticLayer::write_competitive_expression(const Vector<std::string>& inputs_names, const Vector<std::string>& outputs_names) const 00741 { 00742 std::ostringstream buffer; 00743 00744 for(unsigned int i = 0; i < probabilistic_neurons_number; i++) 00745 { 00746 buffer << outputs_names[i] << "= Competitive(" << inputs_names.to_string() << ");\n"; 00747 } 00748 00749 return(buffer.str()); 00750 } 00751 00752 00753 // std::string write_softmax_expression(const Vector<std::string>&, const Vector<std::string>&) const method 00754 00758 00759 std::string ProbabilisticLayer::write_softmax_expression(const Vector<std::string>& inputs_names, const Vector<std::string>& outputs_names) const 00760 { 00761 std::ostringstream buffer; 00762 00763 for(unsigned int i = 0; i < probabilistic_neurons_number; i++) 00764 { 00765 buffer << outputs_names[i] << "= Softmax(" << inputs_names.to_string() << ");\n"; 00766 } 00767 00768 return(buffer.str()); 00769 } 00770 00771 00772 // std::string write_expression(const Vector<std::string>&, const Vector<std::string>&) const method 00773 00778 00779 std::string ProbabilisticLayer::write_expression(const Vector<std::string>& inputs_names, const Vector<std::string>& outputs_names) const 00780 { 00781 switch(probabilistic_method) 00782 { 00783 case Competitive: 00784 { 00785 return(write_competitive_expression(inputs_names, outputs_names)); 00786 } 00787 break; 00788 00789 case Softmax: 00790 { 00791 return(write_softmax_expression(inputs_names, outputs_names)); 00792 } 00793 break; 00794 00795 default: 00796 { 00797 std::ostringstream buffer; 00798 00799 buffer << "OpenNN Exception: ProbabilisticLayer class.\n" 00800 << "std::string write_expression(const Vector<std::string>&, const Vector<std::string>&) const method.\n" 00801 << "Unknown probabilistic method.\n"; 00802 00803 throw std::logic_error(buffer.str()); 00804 }// end default 00805 break; 00806 }// end switch 00807 } 00808 00809 } 00810 00811 // OpenNN: Open Neural Networks Library. 00812 // Copyright (C) 2005-2012 Roberto Lopez 00813 // 00814 // This library is free software; you can redistribute it and/or 00815 // modify it under the terms of the GNU Lesser General Public 00816 // License as published by the Free Software Foundation; either 00817 // version 2.1 of the License, or any later version. 00818 // 00819 // This library is distributed in the hope that it will be useful, 00820 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00821 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00822 // Lesser General Public License for more details. 00823 00824 // You should have received a copy of the GNU Lesser General Public 00825 // License along with this library; if not, write to the Free Software 00826 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA