OpenNN  2.2
Open Neural Networks Library
root_mean_squared_error.cpp
1 /****************************************************************************************************************/
2 /* */
3 /* OpenNN: Open Neural Networks Library */
4 /* www.artelnics.com/opennn */
5 /* */
6 /* R O O T M E A N S Q U A R E D E R R O R C L A S S */
7 /* */
8 /* Roberto Lopez */
9 /* Artelnics - Making intelligent use of data */
11 /* */
12 /****************************************************************************************************************/
13 
14 
15 // OpenNN includes
16 
17 #include "root_mean_squared_error.h"
18 
19 namespace OpenNN
20 {
21 
22 // DEFAULT CONSTRUCTOR
23 
28 
30 {
31 }
32 
33 
34 // NEURAL NETWORK CONSTRUCTOR
35 
40 
42 : PerformanceTerm(new_neural_network_pointer)
43 {
44 }
45 
46 
47 // DATA SET CONSTRUCTOR
48 
53 
55 : PerformanceTerm(new_data_set_pointer)
56 {
57 }
58 
59 
60 // NEURAL NETWORK AND DATA SET CONSTRUCTOR
61 
68 
69 RootMeanSquaredError::RootMeanSquaredError(NeuralNetwork* new_neural_network_pointer, DataSet* new_data_set_pointer)
70 : PerformanceTerm(new_neural_network_pointer, new_data_set_pointer)
71 {
72 }
73 
74 
75 // XML CONSTRUCTOR
76 
81 
82 RootMeanSquaredError::RootMeanSquaredError(const tinyxml2::XMLDocument& root_mean_squared_error_document)
83 : PerformanceTerm(root_mean_squared_error_document)
84 {
85 }
86 
87 
88 // DESTRUCTOR
89 
91 
93 {
94 }
95 
96 
97 // METHODS
98 
99 // void check(void) const method
100 
104 
106 {
107  std::ostringstream buffer;
108 
109  // Neural network stuff
110 
112  {
113  buffer << "OpenNN Exception: RootMeanSquaredError class.\n"
114  << "void check(void) const method.\n"
115  << "Pointer to neural network is NULL.\n";
116 
117  throw std::logic_error(buffer.str());
118  }
119 
120  const MultilayerPerceptron* multilayer_perceptron_pointer = neural_network_pointer->get_multilayer_perceptron_pointer();
121 
122  if(!multilayer_perceptron_pointer)
123  {
124  buffer << "OpenNN Exception: RootMeanSquaredError class.\n"
125  << "void check(void) const method.\n"
126  << "Pointer to multilayer perceptron is NULL.\n";
127 
128  throw std::logic_error(buffer.str());
129  }
130 
131  const size_t inputs_number = multilayer_perceptron_pointer->get_inputs_number();
132  const size_t outputs_number = multilayer_perceptron_pointer->get_outputs_number();
133 
134  if(inputs_number == 0)
135  {
136  buffer << "OpenNN Exception: RootMeanSquaredError class.\n"
137  << "void check(void) const method.\n"
138  << "Number of inputs in multilayer perceptron object is zero.\n";
139 
140  throw std::logic_error(buffer.str());
141  }
142 
143  if(outputs_number == 0)
144  {
145  buffer << "OpenNN Exception: RootMeanSquaredError class.\n"
146  << "void check(void) const method.\n"
147  << "Number of outputs in multilayer perceptron object is zero.\n";
148 
149  throw std::logic_error(buffer.str());
150  }
151 
152  // Data set stuff
153 
154  if(!data_set_pointer)
155  {
156  buffer << "OpenNN Exception: RootMeanSquaredError class.\n"
157  << "void check(void) const method.\n"
158  << "Pointer to data set is NULL.\n";
159 
160  throw std::logic_error(buffer.str());
161  }
162 
163  // Sum squared error stuff
164 
165  const Variables& variables = data_set_pointer->get_variables();
166 
167  const size_t data_set_inputs_number = variables.count_inputs_number();
168  const size_t targets_number = variables.count_targets_number();
169 
170  if(data_set_inputs_number != inputs_number)
171  {
172  buffer << "OpenNN Exception: RootMeanSquaredError class.\n"
173  << "void check(void) const method.\n"
174  << "Number of inputs in neural network must be equal to number of inputs in data set.\n";
175 
176  throw std::logic_error(buffer.str());
177  }
178 
179  if(outputs_number != targets_number)
180  {
181  buffer << "OpenNN Exception: RootMeanSquaredError class.\n"
182  << "void check(void) const method.\n"
183  << "Number of outputs in neural network must be equal to number of targets in data set.\n";
184 
185  throw std::logic_error(buffer.str());
186  }
187 }
188 
189 
190 // double calculate_performance(void) const method
191 
194 
196 {
197  // Control sentence
198 
199  #ifndef NDEBUG
200 
201  check();
202 
203  #endif
204 
205  // Neural network stuff
206 
207  const MultilayerPerceptron* multilayer_perceptron_pointer = neural_network_pointer->get_multilayer_perceptron_pointer();
208 
209  const size_t inputs_number = multilayer_perceptron_pointer->get_inputs_number();
210  const size_t outputs_number = multilayer_perceptron_pointer->get_outputs_number();
211 
212  // Data set stuff
213 
214  const Instances& instances = data_set_pointer->get_instances();
215 
216  const size_t training_instances_number = instances.count_training_instances_number();
217 
218  const Vector<size_t> training_indices = instances.arrange_training_indices();
219 
220  size_t training_index;
221 
222  const Variables& variables = data_set_pointer->get_variables();
223 
224  const Vector<size_t> inputs_indices = variables.arrange_inputs_indices();
225  const Vector<size_t> targets_indices = variables.arrange_targets_indices();
226 
227  const MissingValues& missing_values = data_set_pointer->get_missing_values();
228 
229  // Root mean squared error
230 
231  Vector<double> inputs(inputs_number);
232  Vector<double> outputs(outputs_number);
233  Vector<double> targets(outputs_number);
234 
235  double sum_squared_error = 0.0;
236 
237  int i = 0;
238 
239  #pragma omp parallel for private(i, training_index, inputs, outputs, targets) reduction(+:sum_squared_error)
240 
241  for(i = 0; i < (int)training_instances_number; i++)
242  {
243  training_index = training_indices[i];
244 
245  if(missing_values.has_missing_values(training_index))
246  {
247  continue;
248  }
249 
250  // Input vector
251 
252  inputs = data_set_pointer->get_instance(training_index, inputs_indices);
253 
254  // Output vector
255 
256  outputs = multilayer_perceptron_pointer->calculate_outputs(inputs);
257 
258  // Target vector
259 
260  targets = data_set_pointer->get_instance(training_index, targets_indices);
261 
262  // Sum squaresd error
263 
264  sum_squared_error += outputs.calculate_sum_squared_error(targets);
265  }
266 
267  return(sqrt(sum_squared_error/(double)training_instances_number));
268 }
269 
270 
271 // double calculate_performance(const Vector<double>&) const method
272 
277 
279 {
280  // Control sentence (if debug)
281 
282  #ifndef NDEBUG
283 
284  check();
285 
286  #endif
287 
288  #ifndef NDEBUG
289 
290  std::ostringstream buffer;
291 
292  const size_t size = parameters.size();
293 
294  const size_t parameters_number = neural_network_pointer->count_parameters_number();
295 
296  if(size != parameters_number)
297  {
298  buffer << "OpenNN Exception: RootMeanSquaredError class.\n"
299  << "double calculate_performance(const Vector<double>&) const method.\n"
300  << "Size (" << size << ") must be equal to number of parameters (" << parameters_number << ").\n";
301 
302  throw std::logic_error(buffer.str());
303  }
304 
305  #endif
306 
307  // Neural network stuff
308 
309  const MultilayerPerceptron* multilayer_perceptron_pointer = neural_network_pointer->get_multilayer_perceptron_pointer();
310 
311  const size_t inputs_number = multilayer_perceptron_pointer->get_inputs_number();
312  const size_t outputs_number = multilayer_perceptron_pointer->get_outputs_number();
313 
314  // Data set stuff
315 
316  const Instances& instances = data_set_pointer->get_instances();
317 
318  const size_t training_instances_number = instances.count_training_instances_number();
319 
320  const Vector<size_t> training_indices = instances.arrange_training_indices();
321 
322  size_t training_index;
323 
324  const Variables& variables = data_set_pointer->get_variables();
325 
326  const Vector<size_t> inputs_indices = variables.arrange_inputs_indices();
327  const Vector<size_t> targets_indices = variables.arrange_targets_indices();
328 
329  const MissingValues& missing_values = data_set_pointer->get_missing_values();
330 
331  // Root mean squared error
332 
333  Vector<double> inputs(inputs_number);
334  Vector<double> outputs(outputs_number);
335  Vector<double> targets(outputs_number);
336 
337  double sum_squared_error = 0.0;
338 
339  int i = 0;
340 
341  #pragma omp parallel for private(i, training_index, inputs, outputs, targets) reduction(+:sum_squared_error)
342 
343  for(i = 0; i < (int)training_instances_number; i++)
344  {
345  training_index = training_indices[i];
346 
347  if(missing_values.has_missing_values(training_index))
348  {
349  continue;
350  }
351 
352  // Input vector
353 
354  inputs = data_set_pointer->get_instance(training_index, inputs_indices);
355 
356  // Output vector
357 
358  outputs = multilayer_perceptron_pointer->calculate_outputs(inputs, parameters);
359 
360  // Target vector
361 
362  targets = data_set_pointer->get_instance(training_index, targets_indices);
363 
364  // Sum squaresd error
365 
366  sum_squared_error += outputs.calculate_sum_squared_error(targets);
367  }
368 
369  return(sqrt(sum_squared_error/(double)training_instances_number));
370 }
371 
372 
373 // Vector<double> calculate_gradient(void) const method
374 
376 
378 {
379  // Control sentence
380 
381  #ifndef NDEBUG
382 
383  check();
384 
385  #endif
386 
387  // Neural network stuff
388 
389  const MultilayerPerceptron* multilayer_perceptron_pointer = neural_network_pointer->get_multilayer_perceptron_pointer();
390 
391  const size_t inputs_number = multilayer_perceptron_pointer->get_inputs_number();
392  const size_t outputs_number = multilayer_perceptron_pointer->get_outputs_number();
393 
394  const size_t layers_number = multilayer_perceptron_pointer->get_layers_number();
395 
396  const size_t parameters_number = multilayer_perceptron_pointer->count_parameters_number();
397 
398  // Data set stuff
399 
400  Vector< Vector< Vector<double> > > first_order_forward_propagation(2);
401 
402  const bool has_conditions_layer = neural_network_pointer->has_conditions_layer();
403 
404  const ConditionsLayer* conditions_layer_pointer = has_conditions_layer ? neural_network_pointer->get_conditions_layer_pointer() : NULL;
405 
406  Vector<double> particular_solution;
407  Vector<double> homogeneous_solution;
408 
409  // Data set stuff
410 
411  const Instances& instances = data_set_pointer->get_instances();
412 
413  const size_t training_instances_number = instances.count_training_instances_number();
414 
415  const Vector<size_t> training_indices = instances.arrange_training_indices();
416 
417  size_t training_index;
418 
419  const Variables& variables = data_set_pointer->get_variables();
420 
421  const Vector<size_t> inputs_indices = variables.arrange_inputs_indices();
422  const Vector<size_t> targets_indices = variables.arrange_targets_indices();
423 
424  const MissingValues& missing_values = data_set_pointer->get_missing_values();
425 
426  Vector<double> inputs(inputs_number);
427  Vector<double> targets(outputs_number);
428 
429  // Performance functional stuff
430 
431  const double performance = calculate_performance();
432 
433  Vector< Vector<double> > layers_delta;
434 
435  Vector<double> output_gradient(outputs_number);
436 
437  Vector<double> point_gradient(parameters_number, 0.0);
438 
439  // Main loop
440 
441  Vector<double> gradient(parameters_number, 0.0);
442 
443  int i = 0;
444 
445  #pragma omp parallel for private(i, training_index, inputs, targets, first_order_forward_propagation, output_gradient, \
446  layers_delta, particular_solution, homogeneous_solution, point_gradient)
447 
448  for(i = 0; i < (int)training_instances_number; i++)
449  {
450  training_index = training_indices[i];
451 
452  if(missing_values.has_missing_values(training_index))
453  {
454  continue;
455  }
456 
457  inputs = data_set_pointer->get_instance(training_index, inputs_indices);
458 
459  targets = data_set_pointer->get_instance(training_index, targets_indices);
460 
461  first_order_forward_propagation = multilayer_perceptron_pointer->calculate_first_order_forward_propagation(inputs);
462 
463  const Vector< Vector<double> >& layers_activation = first_order_forward_propagation[0];
464  const Vector< Vector<double> >& layers_activation_derivative = first_order_forward_propagation[1];
465 
466  if(!has_conditions_layer)
467  {
468  output_gradient = (layers_activation[layers_number-1]-targets)/(training_instances_number*performance);
469 
470  layers_delta = calculate_layers_delta(layers_activation_derivative, output_gradient);
471  }
472  else
473  {
474  particular_solution = conditions_layer_pointer->calculate_particular_solution(inputs);
475  homogeneous_solution = conditions_layer_pointer->calculate_homogeneous_solution(inputs);
476 
477  output_gradient = (particular_solution+homogeneous_solution*layers_activation[layers_number-1] - targets)/(training_instances_number*performance);
478 
479  layers_delta = calculate_layers_delta(layers_activation_derivative, homogeneous_solution, output_gradient);
480  }
481 
482  point_gradient = calculate_point_gradient(inputs, layers_activation, layers_delta);
483 
484  #pragma omp critical
485 
486  gradient += point_gradient;
487  }
488 
489  return(gradient);
490 }
491 
492 
493 // double calculate_generalization_performance(void) const method
494 
496 
498 {
499  // Control sentence (if debug)
500 
501  #ifndef NDEBUG
502 
503  check();
504 
505  #endif
506 
507  // Neural network staff
508 
509  const MultilayerPerceptron* multilayer_perceptron_pointer = neural_network_pointer->get_multilayer_perceptron_pointer();
510 
511  const size_t inputs_number = multilayer_perceptron_pointer->get_inputs_number();
512  const size_t outputs_number = multilayer_perceptron_pointer->get_outputs_number();
513 
514  // Data set stuff
515 
516  const Instances& instances = data_set_pointer->get_instances();
517  const size_t generalization_instances_number = instances.count_generalization_instances_number();
518 
519  if(generalization_instances_number == 0)
520  {
521  return(0.0);
522  }
523 
524  const Vector<size_t> generalization_indices = instances.arrange_generalization_indices();
525 
526  size_t generalization_index;
527 
528  const MissingValues& missing_values = data_set_pointer->get_missing_values();
529 
530  const Variables& variables = data_set_pointer->get_variables();
531 
532  const Vector<size_t> inputs_indices = variables.arrange_inputs_indices();
533  const Vector<size_t> targets_indices = variables.arrange_targets_indices();
534 
535  Vector<double> inputs(inputs_number);
536  Vector<double> outputs(outputs_number);
537  Vector<double> targets(outputs_number);
538 
539  int i = 0;
540 
541  double generalization_performance = 0.0;
542 
543  #pragma omp parallel for private(i, generalization_index, inputs, outputs, targets) reduction(+ : generalization_performance)
544 
545  for(i = 0; i < (int)generalization_instances_number; i++)
546  {
547  generalization_index = generalization_indices[i];
548 
549  if(missing_values.has_missing_values(generalization_index))
550  {
551  continue;
552  }
553 
554  // Input vector
555 
556  inputs = data_set_pointer->get_instance(generalization_index, inputs_indices);
557 
558  // Output vector
559 
560  outputs = multilayer_perceptron_pointer->calculate_outputs(inputs);
561 
562  // Target vector
563 
564  targets = data_set_pointer->get_instance(generalization_index, targets_indices);
565 
566  // Sum of squares error
567 
568  generalization_performance += outputs.calculate_sum_squared_error(targets);
569  }
570 
571  return(sqrt(generalization_performance/(double)generalization_instances_number));
572 }
573 
574 
575 // Matrix<double> calculate_Hessian(void) const method
576 
578 
580 {
581  Matrix<double> m;
582 
583  return(m);
584 }
585 
586 
587 // std::string write_performance_term_type(void) const method
588 
590 
592 {
593  return("ROOT_MEAN_SQUARED_ERROR");
594 }
595 
596 
597 // tinyxml2::XMLDocument* to_XML(void) const method
598 
601 
602 tinyxml2::XMLDocument* RootMeanSquaredError::to_XML(void) const
603 {
604  std::ostringstream buffer;
605 
606  tinyxml2::XMLDocument* document = new tinyxml2::XMLDocument;
607 
608  // Root mean squared error
609 
610  tinyxml2::XMLElement* root_mean_squared_error_element = document->NewElement("RootMeanSquaredError");
611 
612  document->InsertFirstChild(root_mean_squared_error_element);
613 
614  // Display
615  {
616  tinyxml2::XMLElement* display_element = document->NewElement("Display");
617  root_mean_squared_error_element->LinkEndChild(display_element);
618 
619  buffer.str("");
620  buffer << display;
621 
622  tinyxml2::XMLText* display_text = document->NewText(buffer.str().c_str());
623  display_element->LinkEndChild(display_text);
624  }
625 
626  return(document);
627 }
628 
629 
630 // void from_XML(const tinyxml2::XMLDocument&) method
631 
634 
635 void RootMeanSquaredError::from_XML(const tinyxml2::XMLDocument& document)
636 {
637  const tinyxml2::XMLElement* root_element = document.FirstChildElement("RootMeanSquaredError");
638 
639  if(!root_element)
640  {
641  std::ostringstream buffer;
642 
643  buffer << "OpenNN Exception: RootMeanSquaredError class.\n"
644  << "void from_XML(const tinyxml2::XMLDocument&) method.\n"
645  << "Root mean squared error element is NULL.\n";
646 
647  throw std::logic_error(buffer.str());
648  }
649 
650  // Display
651  {
652  const tinyxml2::XMLElement* element = root_element->FirstChildElement("Display");
653 
654  if(element)
655  {
656  const std::string new_display_string = element->GetText();
657 
658  try
659  {
660  set_display(new_display_string != "0");
661  }
662  catch(const std::logic_error& e)
663  {
664  std::cout << e.what() << std::endl;
665  }
666  }
667  }
668 }
669 
670 }
671 
672 // OpenNN: Open Neural Networks Library.
673 // Copyright (c) 2005-2015 Roberto Lopez.
674 //
675 // This library is free software; you can redistribute it and/or
676 // modify it under the terms of the GNU Lesser General Public
677 // License as published by the Free Software Foundation; either
678 // version 2.1 of the License, or any later version.
679 //
680 // This library is distributed in the hope that it will be useful,
681 // but WITHOUT ANY WARRANTY; without even the implied warranty of
682 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
683 // Lesser General Public License for more details.
684 
685 // You should have received a copy of the GNU Lesser General Public
686 // License along with this library; if not, write to the Free Software
687 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
size_t count_parameters_number(void) const
const Variables & get_variables(void) const
Returns a constant reference to the variables object composing this data set object.
Definition: data_set.cpp:202
double calculate_generalization_performance(void) const
Returns the root mean squared error of the multilayer perceptron measured on the generalization insta...
size_t count_training_instances_number(void) const
Returns the number of instances in the data set which will be used for training.
Definition: instances.cpp:387
size_t get_inputs_number(void) const
Returns the number of inputs to the multilayer perceptron.
Vector< double > calculate_point_gradient(const Vector< double > &, const Vector< Vector< double > > &, const Vector< Vector< double > > &) const
size_t get_layers_number(void) const
Returns the number of layers in the multilayer perceptron.
tinyxml2::XMLDocument * to_XML(void) const
bool has_missing_values(void) const
size_t get_outputs_number(void) const
Returns the number of outputs neurons in the multilayer perceptron.
Vector< double > calculate_outputs(const Vector< double > &) const
const MissingValues & get_missing_values(void) const
Returns a reference to the missing values object in the data set.
Definition: data_set.cpp:275
void set_display(const bool &)
virtual ~RootMeanSquaredError(void)
Destructor.
Vector< size_t > arrange_targets_indices(void) const
Returns the indices of the target variables.
Definition: variables.cpp:519
Vector< size_t > arrange_training_indices(void) const
Returns the indices of the instances which will be used for training.
Definition: instances.cpp:489
size_t count_generalization_instances_number(void) const
Returns the number of instances in the data set which will be used for generalization.
Definition: instances.cpp:409
Vector< double > get_instance(const size_t &) const
Definition: data_set.cpp:684
bool has_conditions_layer(void) const
MultilayerPerceptron * get_multilayer_perceptron_pointer(void) const
Returns a pointer to the multilayer perceptron composing this neural network.
double calculate_sum_squared_error(const Vector< double > &) const
Definition: vector.h:2569
virtual Vector< double > calculate_homogeneous_solution(const Vector< double > &) const
Returns the homogeneous solution for applying boundary conditions.
Vector< double > calculate_gradient(void) const
Calculates the gradient the root mean squared error funcion by means of the back-propagation algorith...
NeuralNetwork * neural_network_pointer
Pointer to a multilayer perceptron object.
std::string write_performance_term_type(void) const
Returns a string with the name of the root mean squared error performance type, "ROOT_MEAN_SQUARED_ER...
virtual Vector< double > calculate_particular_solution(const Vector< double > &) const
Returns the particular solution for applying boundary conditions.
bool display
Display messages to screen.
ConditionsLayer * get_conditions_layer_pointer(void) const
Returns a pointer to the conditions layer composing this neural network.
size_t count_inputs_number(void) const
Returns the number of input variables of the data set.
Definition: variables.cpp:249
Vector< Vector< Vector< double > > > calculate_first_order_forward_propagation(const Vector< double > &) const
DataSet * data_set_pointer
Pointer to a data set object.
size_t count_targets_number(void) const
Returns the number of target variables of the data set.
Definition: variables.cpp:271
Matrix< double > calculate_Hessian(void) const
Vector< Vector< double > > calculate_layers_delta(const Vector< Vector< double > > &, const Vector< double > &) const
Vector< size_t > arrange_generalization_indices(void) const
Returns the indices of the instances which will be used for generalization.
Definition: instances.cpp:516
void from_XML(const tinyxml2::XMLDocument &)
Vector< size_t > arrange_inputs_indices(void) const
Returns the indices of the input variables.
Definition: variables.cpp:493
const Instances & get_instances(void) const
Returns a constant reference to the instances object composing this data set object.
Definition: data_set.cpp:222
size_t count_parameters_number(void) const
Returns the number of parameters (biases and synaptic weights) in the multilayer perceptron.