loss_index.cpp
1// OpenNN: Open Neural Networks Library
2// www.opennn.net
3//
4// L O S S I N D E X C L A S S
5//
6// Artificial Intelligence Techniques SL
7// artelnics@artelnics.com
8
9#include "loss_index.h"
10
11namespace OpenNN
12{
13
17
19 : neural_network_pointer(nullptr),
20 data_set_pointer(nullptr)
21{
23}
24
25
32
33LossIndex::LossIndex(NeuralNetwork* new_neural_network_pointer, DataSet* new_data_set_pointer)
34 : neural_network_pointer(new_neural_network_pointer),
35 data_set_pointer(new_data_set_pointer)
36{
38}
39
40
42
44{
45 delete non_blocking_thread_pool;
46 delete thread_pool_device;
47}
48
49
51
53{
55}
56
57
60
61const bool& LossIndex::get_display() const
62{
63 return display;
64}
65
66
69
71{
73 {
74 return true;
75 }
76 else
77 {
78 return false;
79 }
80}
81
82
85
87{
89 {
90 return true;
91 }
92 else
93 {
94 return false;
95 }
96}
97
98
100
102{
104}
105
106
109
111{
112 neural_network_pointer = nullptr;
113 data_set_pointer = nullptr;
114
115 set_default();
116}
117
118
122
123void LossIndex::set(NeuralNetwork* new_neural_network_pointer)
124{
125 neural_network_pointer = new_neural_network_pointer;
126 data_set_pointer = nullptr;
127
128 set_default();
129}
130
131
135
136void LossIndex::set(DataSet* new_data_set_pointer)
137{
138 neural_network_pointer = nullptr;
139 data_set_pointer = new_data_set_pointer;
140
141 set_default();
142}
143
144
149
150void LossIndex::set(NeuralNetwork* new_neural_network_pointer, DataSet* new_data_set_pointer)
151{
152 neural_network_pointer = new_neural_network_pointer;
153
154 data_set_pointer = new_data_set_pointer;
155
156 set_default();
157}
158
159
162
163void LossIndex::set(const LossIndex& other_error_term)
164{
166
167 data_set_pointer = other_error_term.data_set_pointer;
168
170
171 display = other_error_term.display;
172}
173
174
175void LossIndex::set_threads_number(const int& new_threads_number)
176{
177 if(non_blocking_thread_pool != nullptr) delete this->non_blocking_thread_pool;
178 if(thread_pool_device != nullptr) delete this->thread_pool_device;
179
180 non_blocking_thread_pool = new NonBlockingThreadPool(new_threads_number);
181 thread_pool_device = new ThreadPoolDevice(non_blocking_thread_pool, new_threads_number);
182}
183
184
187
189{
190 neural_network_pointer = new_neural_network_pointer;
191}
192
193
195
196void LossIndex::set_data_set_pointer(DataSet* new_data_set_pointer)
197{
198 data_set_pointer = new_data_set_pointer;
199}
200
201
203
205{
206 delete non_blocking_thread_pool;
207 delete thread_pool_device;
208
209 const int n = omp_get_max_threads();
210
211 non_blocking_thread_pool = new NonBlockingThreadPool(n);
212 thread_pool_device = new ThreadPoolDevice(non_blocking_thread_pool, n);
213
214 regularization_method = RegularizationMethod::L2;
215}
216
217
220
221void LossIndex::set_regularization_method(const string& new_regularization_method)
222{
223 if(new_regularization_method == "L1_NORM")
224 {
225 set_regularization_method(RegularizationMethod::L1);
226 }
227 else if(new_regularization_method == "L2_NORM")
228 {
229 set_regularization_method(RegularizationMethod::L2);
230 }
231 else if(new_regularization_method == "NO_REGULARIZATION")
232 {
233 set_regularization_method(RegularizationMethod::NoRegularization);
234 }
235 else
236 {
237 ostringstream buffer;
238
239 buffer << "OpenNN Exception: LossIndex class.\n"
240 << "void set_regularization_method(const string&) const method.\n"
241 << "Unknown regularization method: " << new_regularization_method << ".";
242
243 throw logic_error(buffer.str());
244 }
245}
246
247
250
252{
253 regularization_method = new_regularization_method;
254}
255
256
259
260void LossIndex::set_regularization_weight(const type& new_regularization_weight)
261{
262 regularization_weight = new_regularization_weight;
263}
264
265
270
271void LossIndex::set_display(const bool& new_display)
272{
273 display = new_display;
274}
275
276
278
280{
282 {
283 return true;
284 }
285 else
286 {
287 return false;
288 }
289}
290
291
294
296{
297 ostringstream buffer;
298
300 {
301 buffer << "OpenNN Exception: LossIndex class.\n"
302 << "void check() const.\n"
303 << "Pointer to neural network is nullptr.\n";
304
305 throw logic_error(buffer.str());
306 }
307
308 // Data set
309
311 {
312 buffer << "OpenNN Exception: LossIndex class.\n"
313 << "void check() const method.\n"
314 << "Pointer to data set is nullptr.\n";
315
316 throw logic_error(buffer.str());
317 }
318}
319
320
321void LossIndex::calculate_errors(const DataSetBatch& batch,
322 const NeuralNetworkForwardPropagation& forward_propagation,
323 LossIndexBackPropagation& back_propagation) const
324{
325 const Index trainable_layers_number = neural_network_pointer->get_trainable_layers_number();
326
327 switch(forward_propagation.layers(trainable_layers_number-1)->layer_pointer->get_type())
328 {
329 case Layer::Type::Perceptron:
330 {
331 back_propagation.errors.device(*thread_pool_device) =
332 static_cast<PerceptronLayerForwardPropagation*>(forward_propagation.layers(trainable_layers_number-1))->activations -
333 batch.targets_2d;
334 }
335 break;
336
337 case Layer::Type::Probabilistic:
338 {
339 back_propagation.errors.device(*thread_pool_device) =
340 static_cast<ProbabilisticLayerForwardPropagation*>(forward_propagation.layers(trainable_layers_number-1))->activations -
341 batch.targets_2d;
342 }
343 break;
344
345 case Layer::Type::Recurrent:
346 {
347 back_propagation.errors.device(*thread_pool_device) =
348 static_cast<RecurrentLayerForwardPropagation*>(forward_propagation.layers(trainable_layers_number-1))->activations -
349 batch.targets_2d;
350 }
351 break;
352
353 case Layer::Type::LongShortTermMemory:
354 {
355 back_propagation.errors.device(*thread_pool_device) =
356 static_cast<LongShortTermMemoryLayerForwardPropagation*>(forward_propagation.layers(trainable_layers_number-1))->activations -
357 batch.targets_2d;
358 }
359 break;
360
361 default: break;
362 }
363}
364
365
366void LossIndex::calculate_errors_lm(const DataSetBatch& batch,
367 const NeuralNetworkForwardPropagation & neural_network_forward_propagation,
368 LossIndexBackPropagationLM & loss_index_back_propagation) const
369{
370 const Index trainable_layers_number = neural_network_pointer->get_trainable_layers_number();
371
372 switch(neural_network_forward_propagation.layers(trainable_layers_number-1)->layer_pointer->get_type())
373 {
374 case Layer::Type::Perceptron:
375
376 loss_index_back_propagation.errors.device(*thread_pool_device) =
377 static_cast<PerceptronLayerForwardPropagation*>(neural_network_forward_propagation.layers(trainable_layers_number-1))->activations -
378 batch.targets_2d;
379
380 break;
381
382 case Layer::Type::Probabilistic:
383
384 loss_index_back_propagation.errors.device(*thread_pool_device) =
385 static_cast<ProbabilisticLayerForwardPropagation*>(neural_network_forward_propagation.layers(trainable_layers_number-1))->activations -
386 batch.targets_2d;
387
388 break;
389
390 case Layer::Type::Recurrent:
391
392 loss_index_back_propagation.errors.device(*thread_pool_device) =
393 static_cast<RecurrentLayerForwardPropagation*>(neural_network_forward_propagation.layers(trainable_layers_number-1))->activations -
394 batch.targets_2d;
395
396 break;
397
398 case Layer::Type::LongShortTermMemory:
399
400 loss_index_back_propagation.errors.device(*thread_pool_device) =
401 static_cast<LongShortTermMemoryLayerForwardPropagation*>(neural_network_forward_propagation.layers(trainable_layers_number-1))->activations -
402 batch.targets_2d;
403
404 break;
405
406 default: break;
407 }
408}
409
410
411void LossIndex::calculate_squared_errors_lm(const DataSetBatch& ,
412 const NeuralNetworkForwardPropagation& ,
413 LossIndexBackPropagationLM& loss_index_back_propagation_lm) const
414{
415 loss_index_back_propagation_lm.squared_errors.device(*thread_pool_device) = loss_index_back_propagation_lm.errors.square().sum(rows_sum).sqrt();
416}
417
418
419void LossIndex::back_propagate(const DataSetBatch& batch,
420 NeuralNetworkForwardPropagation& forward_propagation,
421 LossIndexBackPropagation& back_propagation) const
422{
423 // Loss index
424
425 calculate_errors(batch, forward_propagation, back_propagation);
426
427 calculate_error(batch, forward_propagation, back_propagation);
428
429 calculate_layers_delta(batch, forward_propagation, back_propagation);
430
431 calculate_error_gradient(batch, forward_propagation, back_propagation);
432
433 // Loss
434
435 back_propagation.loss = back_propagation.error;
436
437 // Regularization
438
439 if(regularization_method != RegularizationMethod::NoRegularization)
440 {
441 const type regularization = calculate_regularization(back_propagation.parameters);
442
443 back_propagation.loss += regularization_weight*regularization;
444
445 calculate_regularization_gradient(back_propagation.parameters, back_propagation.regularization_gradient);
446
447 back_propagation.gradient.device(*thread_pool_device) += regularization_weight*back_propagation.regularization_gradient;
448 }
449}
450
451
456
458 NeuralNetworkForwardPropagation& forward_propagation,
459 LossIndexBackPropagationLM& loss_index_back_propagation_lm) const
460{
461 calculate_errors_lm(batch, forward_propagation, loss_index_back_propagation_lm);
462
463 calculate_squared_errors_lm(batch, forward_propagation, loss_index_back_propagation_lm);
464
465 calculate_error_lm(batch, forward_propagation, loss_index_back_propagation_lm);
466
467 calculate_layers_delta_lm(batch, forward_propagation, loss_index_back_propagation_lm);
468
469 calculate_squared_errors_jacobian_lm(batch, forward_propagation, loss_index_back_propagation_lm);
470
471 calculate_error_gradient_lm(batch, loss_index_back_propagation_lm);
472
473 calculate_error_hessian_lm(batch, loss_index_back_propagation_lm);
474
475 // Loss
476
477 loss_index_back_propagation_lm.loss = loss_index_back_propagation_lm.error;
478
479 // Regularization
480
481 if(regularization_method != RegularizationMethod::NoRegularization)
482 {
483 const type regularization = calculate_regularization(loss_index_back_propagation_lm.parameters);
484
485 loss_index_back_propagation_lm.loss += regularization_weight*regularization;
486
487 calculate_regularization_gradient(loss_index_back_propagation_lm.parameters, loss_index_back_propagation_lm.regularization_gradient);
488
489 loss_index_back_propagation_lm.gradient.device(*thread_pool_device) += regularization_weight*loss_index_back_propagation_lm.regularization_gradient;
490
491 calculate_regularization_hessian(loss_index_back_propagation_lm.parameters, loss_index_back_propagation_lm.regularization_hessian);
492
493 loss_index_back_propagation_lm.hessian += regularization_weight*loss_index_back_propagation_lm.regularization_hessian;
494 }
495}
496
497
507
509 NeuralNetworkForwardPropagation& forward_propagation,
510 LossIndexBackPropagationLM& loss_index_back_propagation_lm) const
511{
512 const Index trainable_layers_number = neural_network_pointer->get_trainable_layers_number();
513
514 loss_index_back_propagation_lm.squared_errors_jacobian.setZero();
515
516 const Index batch_samples_number = batch.get_samples_number();
517
518 Index mem_index = 0;
519
520 Tensor<Layer*, 1> trainable_layers_pointers = neural_network_pointer->get_trainable_layers_pointers();
521
522 const Tensor<Index, 1> trainable_layers_parameters_number = neural_network_pointer->get_trainable_layers_parameters_numbers();
523
524 // Layer 0
525
526 if(trainable_layers_pointers(0)->get_type() != Layer::Type::Perceptron && trainable_layers_pointers(0)->get_type() != Layer::Type::Probabilistic)
527 {
528 ostringstream buffer;
529
530 buffer << "OpenNN Exception: LossIndex class.\n"
531 << "void calculate_squared_errors_jacobian_lm(const DataSetBatch&, NeuralNetworkForwardPropagation&, LossIndexBackPropagationLM&) const method "
532 << "Levenberg - Marquardt algorithm can only be used with Perceptron and Probabilistic layers.\n";
533
534 throw logic_error(buffer.str());
535 }
536 else
537 {
538 trainable_layers_pointers(0)->calculate_squared_errors_Jacobian_lm(batch.inputs_2d,
539 forward_propagation.layers(0),
540 loss_index_back_propagation_lm.neural_network.layers(0));
541
542 trainable_layers_pointers(0)->insert_squared_errors_Jacobian_lm(loss_index_back_propagation_lm.neural_network.layers(0),
543 mem_index,
544 loss_index_back_propagation_lm.squared_errors_jacobian);
545
546 mem_index += trainable_layers_parameters_number(0)*batch_samples_number;
547 }
548
549 // Rest of the layers
550
551 for(Index i = 1; i < trainable_layers_number; i++)
552 {
553 switch (forward_propagation.layers(i-1)->layer_pointer->get_type())
554 {
555 case Layer::Type::Perceptron:
556 {
557 PerceptronLayerForwardPropagation* perceptron_layer_forward_propagation
558 = static_cast<PerceptronLayerForwardPropagation*>(forward_propagation.layers(i-1));
559
560 trainable_layers_pointers(i)->calculate_squared_errors_Jacobian_lm(perceptron_layer_forward_propagation->activations,
561 forward_propagation.layers(i),
562 loss_index_back_propagation_lm.neural_network.layers(i));
563
564 trainable_layers_pointers(i)->insert_squared_errors_Jacobian_lm(loss_index_back_propagation_lm.neural_network.layers(i),
565 mem_index,
566 loss_index_back_propagation_lm.squared_errors_jacobian);
567
568 mem_index += trainable_layers_parameters_number(i)*batch_samples_number;
569 }
570 break;
571
572 case Layer::Type::Probabilistic:
573 {
574 ostringstream buffer;
575
576 buffer << "OpenNN Exception: LossIndex class.\n"
577 << "void calculate_squared_errors_jacobian_lm(const DataSetBatch&, NeuralNetworkForwardPropagation&, LossIndexBackPropagationLM&) const method "
578 << "Probabilistic layer can only occupy the last position in the neural network. Please, check network structure.\n";
579
580 throw logic_error(buffer.str());
581 }
582
583 default:
584 {
585 ostringstream buffer;
586
587 buffer << "OpenNN Exception: LossIndex class.\n"
588 << "void calculate_squared_errors_jacobian_lm(const DataSetBatch&, NeuralNetworkForwardPropagation&, LossIndexBackPropagationLM&) const method "
589 << "Levenberg - Marquardt algorithm can only be used with Perceptron and Probabilistic layers.\n";
590
591 throw logic_error(buffer.str());
592 }
593 }
594 }
595}
596
597
598void LossIndex::calculate_error_gradient_lm(const DataSetBatch& batch,
599 LossIndexBackPropagationLM& loss_index_back_propagation_lm) const
600{
601 loss_index_back_propagation_lm.gradient.device(*thread_pool_device)
602 = loss_index_back_propagation_lm.squared_errors_jacobian.contract(loss_index_back_propagation_lm.squared_errors, AT_B);
603}
604
605
607
609{
610 return "USER_ERROR_TERM";
611}
612
613
615
617{
618 return "USER_ERROR_TERM";
619}
620
621
624
626{
628 {
629 case RegularizationMethod::NoRegularization:
630 return "NO_REGULARIZATION";
631
632 case RegularizationMethod::L1:
633 return "L1_NORM";
634
635 case RegularizationMethod::L2:
636 return "L2_NORM";
637 }
638
639 return string();
640}
641
642
647
648type LossIndex::calculate_regularization(const Tensor<type, 1>& parameters) const
649{
651 {
652 case RegularizationMethod::NoRegularization: return type(0);
653
654 case RegularizationMethod::L1: return l1_norm(thread_pool_device, parameters);
655
656 case RegularizationMethod::L2: return l2_norm(thread_pool_device, parameters);
657 }
658
659 return type(0);
660}
661
662
668
669void LossIndex::calculate_regularization_gradient(const Tensor<type, 1>& parameters, Tensor<type, 1>& regularization_gradient) const
670{
672 {
673 case RegularizationMethod::L1: l1_norm_gradient(thread_pool_device, parameters, regularization_gradient); return;
674
675 case RegularizationMethod::L2: l2_norm_gradient(thread_pool_device, parameters, regularization_gradient); return;
676
677 default: return;
678 }
679}
680
681
687
688void LossIndex::calculate_regularization_hessian(const Tensor<type, 1>& parameters, Tensor<type, 2>& regularization_hessian) const
689{
691 {
692 case RegularizationMethod::L1: l1_norm_hessian(thread_pool_device, parameters, regularization_hessian); return;
693
694 case RegularizationMethod::L2: l2_norm_hessian(thread_pool_device, parameters, regularization_hessian); return;
695
696 default: return;
697 }
698}
699
700
701void LossIndex::calculate_layers_delta(const DataSetBatch& batch,
702 NeuralNetworkForwardPropagation& forward_propagation,
703 LossIndexBackPropagation& back_propagation) const
704{
705 const Index trainable_layers_number = neural_network_pointer->get_trainable_layers_number();
706
707 if(trainable_layers_number == 0) return;
708
709 const Tensor<Layer*, 1> trainable_layers_pointers = neural_network_pointer->get_trainable_layers_pointers();
710
711 // Output layer
712
713 calculate_output_delta(batch,
714 forward_propagation,
715 back_propagation);
716
717 // Hidden layers
718
719 for(Index i = static_cast<Index>(trainable_layers_number)-2; i >= 0; i--)
720 {
721 trainable_layers_pointers(i)
722 ->calculate_hidden_delta(forward_propagation.layers(i+1),
723 back_propagation.neural_network.layers(i+1),
724 back_propagation.neural_network.layers(i));
725 }
726}
727
728
729void LossIndex::calculate_layers_delta_lm(const DataSetBatch& batch,
730 NeuralNetworkForwardPropagation& forward_propagation,
731 LossIndexBackPropagationLM& back_propagation) const
732{
733 const Index trainable_layers_number = neural_network_pointer->get_trainable_layers_number();
734
735 if(trainable_layers_number == 0) return;
736
737 const Tensor<Layer*, 1> trainable_layers_pointers = neural_network_pointer->get_trainable_layers_pointers();
738
739 // Output layer
740
741 calculate_output_delta_lm(batch,
742 forward_propagation,
743 back_propagation);
744
745 // Hidden layers
746
747 for(Index i = static_cast<Index>(trainable_layers_number)-2; i >= 0; i--)
748 {
749 trainable_layers_pointers(i)
750 ->calculate_hidden_delta_lm(forward_propagation.layers(i+1),
751 back_propagation.neural_network.layers(i+1),
752 back_propagation.neural_network.layers(i));
753 }
754}
755
756
757void LossIndex::calculate_error_gradient(const DataSetBatch& batch,
758 const NeuralNetworkForwardPropagation& forward_propagation,
759 LossIndexBackPropagation& back_propagation) const
760{
761 #ifdef OPENNN_DEBUG
762
763 check();
764
765 #endif
766
767 const Tensor<Layer*, 1> trainable_layers_pointers = neural_network_pointer->get_trainable_layers_pointers();
768
769 const Index trainable_layers_number = trainable_layers_pointers.size();
770
771 const Tensor<Index, 1> trainable_layers_parameters_number
772 = neural_network_pointer->get_trainable_layers_parameters_numbers();
773
774 if(trainable_layers_pointers(0)->get_type() == Layer::Type::Convolutional)
775 {
776 trainable_layers_pointers(0)->calculate_error_gradient(batch.inputs_4d,
777 forward_propagation.layers(0),
778 back_propagation.neural_network.layers(0));
779 }
780 else
781 {
782 trainable_layers_pointers(0)->calculate_error_gradient(batch.inputs_2d,
783 forward_propagation.layers(0),
784 back_propagation.neural_network.layers(0));
785 }
786
787 Index index = 0;
788
789 trainable_layers_pointers(0)->insert_gradient(back_propagation.neural_network.layers(0),
790 index,
791 back_propagation.gradient);
792
793 index += trainable_layers_parameters_number(0);
794
795 for(Index i = 1; i < trainable_layers_number; i++)
796 {
797 switch(forward_propagation.layers(i-1)->layer_pointer->get_type())
798 {
799 case Layer::Type::Perceptron:
800 {
801 PerceptronLayerForwardPropagation* perceptron_layer_forward_propagation
802 = static_cast<PerceptronLayerForwardPropagation*>(forward_propagation.layers(i-1));
803
804 trainable_layers_pointers(i)->
805 calculate_error_gradient(perceptron_layer_forward_propagation->activations,
806 forward_propagation.layers(i),
807 back_propagation.neural_network.layers(i));
808 }
809 break;
810
811 case Layer::Type::Probabilistic:
812 {
813 ProbabilisticLayerForwardPropagation* probabilistic_layer_forward_propagation
814 = static_cast<ProbabilisticLayerForwardPropagation*>(forward_propagation.layers(i-1));
815
816 trainable_layers_pointers(i)->
817 calculate_error_gradient(probabilistic_layer_forward_propagation->activations,
818 forward_propagation.layers(i),
819 back_propagation.neural_network.layers(i));
820 }
821 break;
822
823 case Layer::Type::Recurrent:
824 {
825 RecurrentLayerForwardPropagation* recurrent_layer_forward_propagation
826 = static_cast<RecurrentLayerForwardPropagation*>(forward_propagation.layers(i-1));
827
828 trainable_layers_pointers(i)->
829 calculate_error_gradient(recurrent_layer_forward_propagation->activations,
830 forward_propagation.layers(i),
831 back_propagation.neural_network.layers(i));
832 }
833 break;
834
835 case Layer::Type::LongShortTermMemory:
836 {
837 LongShortTermMemoryLayerForwardPropagation* long_short_term_memory_layer_forward_propagation
838 = static_cast<LongShortTermMemoryLayerForwardPropagation*>(forward_propagation.layers(i-1));
839
840 trainable_layers_pointers(i)->
841 calculate_error_gradient(long_short_term_memory_layer_forward_propagation->activations,
842 forward_propagation.layers(i),
843 back_propagation.neural_network.layers(i));
844 }
845 break;
846
847 case Layer::Type::Convolutional:
848 {
849 // @todo
850
851 //trainable_layers_pointers(i)->
852 // calculate_error_gradient(static_cast<ConvolutionalLayer::ConvolutionalLayerForwardPropagation*>(forward_propagation.layers(i-1))->activations,
853 // forward_propagation.layers(i),
854 // back_propagation.neural_network.layers(i));
855 }
856 break;
857
858 case Layer::Type::Pooling:
859 {
860 // @todo
861 }
862 break;
863
864 default: break;
865
866 }
867
868 trainable_layers_pointers(i)->insert_gradient(back_propagation.neural_network.layers(i),
869 index,
870 back_propagation.gradient);
871
872 index += trainable_layers_parameters_number(i);
873 }
874}
875
876
877
880
882{
883 ostringstream buffer;
884
885 file_stream.OpenElement("LossIndex");
886
887 file_stream.CloseElement();
888}
889
890
891void LossIndex::regularization_from_XML(const tinyxml2::XMLDocument& document)
892{
893 const tinyxml2::XMLElement* root_element = document.FirstChildElement("Regularization");
894
895 if(!root_element)
896 {
897 ostringstream buffer;
898
899 buffer << "OpenNN Exception: LossIndex class.\n"
900 << "void from_XML(const tinyxml2::XMLDocument&) method.\n"
901 << "Regularization tag not found.\n";
902
903 throw logic_error(buffer.str());
904 }
905
906 const string new_regularization_method = root_element->Attribute("Type");
907
908 set_regularization_method(new_regularization_method);
909
910 const tinyxml2::XMLElement* element = root_element->FirstChildElement("RegularizationWeight");
911
912 if(element)
913 {
914 const type new_regularization_weight = static_cast<type>(atof(element->GetText()));
915
916 try
917 {
918 set_regularization_weight(new_regularization_weight);
919 }
920 catch(const logic_error& e)
921 {
922 cerr << e.what() << endl;
923 }
924 }
925}
926
927
928void LossIndex::write_regularization_XML(tinyxml2::XMLPrinter& file_stream) const
929{
930 ostringstream buffer;
931
932 file_stream.OpenElement("Regularization");
933
934 // Regularization method
935
937 {
938 case RegularizationMethod::L1:
939 {
940 file_stream.PushAttribute("Type", "L1_NORM");
941 }
942 break;
943
944 case RegularizationMethod::L2:
945 {
946 file_stream.PushAttribute("Type", "L2_NORM");
947 }
948 break;
949
950 case RegularizationMethod::NoRegularization:
951 {
952 file_stream.PushAttribute("Type", "NO_REGULARIZATION");
953 }
954 break;
955 }
956
957 // Regularization weight
958
959 file_stream.OpenElement("RegularizationWeight");
960
961 buffer.str("");
962 buffer << regularization_weight;
963
964 file_stream.PushText(buffer.str().c_str());
965
966 // Close regularization weight
967
968 file_stream.CloseElement();
969
970 // Close regularization
971
972 file_stream.CloseElement();
973}
974
975
978
980{
981 const tinyxml2::XMLElement* root_element = document.FirstChildElement("MeanSquaredError");
982
983 if(!root_element)
984 {
985 ostringstream buffer;
986
987 buffer << "OpenNN Exception: MeanSquaredError class.\n"
988 << "void from_XML(const tinyxml2::XMLDocument&) method.\n"
989 << "Mean squared element is nullptr.\n";
990
991 throw logic_error(buffer.str());
992 }
993
994 // Regularization
995
996 tinyxml2::XMLDocument regularization_document;
997 tinyxml2::XMLNode* element_clone;
998
999 const tinyxml2::XMLElement* regularization_element = root_element->FirstChildElement("Regularization");
1000
1001 element_clone = regularization_element->DeepClone(&regularization_document);
1002
1003 regularization_document.InsertFirstChild(element_clone);
1004
1005 regularization_from_XML(regularization_document);
1006}
1007
1008
1010
1012{
1013}
1014
1015
1016Tensor<type, 1> LossIndex::calculate_gradient_numerical_differentiation()
1017{
1018 const Index samples_number = data_set_pointer->get_training_samples_number();
1019
1020 const Tensor<Index, 1> samples_indices = data_set_pointer->get_training_samples_indices();
1021 const Tensor<Index, 1> input_variables_indices = data_set_pointer->get_input_variables_indices();
1022 const Tensor<Index, 1> target_variables_indices = data_set_pointer->get_target_variables_indices();
1023
1024 DataSetBatch batch(samples_number, data_set_pointer);
1025 batch.fill(samples_indices, input_variables_indices, target_variables_indices);
1026
1027 NeuralNetworkForwardPropagation forward_propagation(samples_number, neural_network_pointer);
1028
1029 LossIndexBackPropagation back_propagation(samples_number, this);
1030
1031 const Tensor<type, 1> parameters = neural_network_pointer->get_parameters();
1032
1033 const Index parameters_number = parameters.size();
1034
1035 type h;
1036 Tensor<type, 1> parameters_forward(parameters);
1037 Tensor<type, 1> parameters_backward(parameters);
1038
1039 type error_forward;
1040 type error_backward;
1041
1042 Tensor<type, 1> gradient_numerical_differentiation(parameters_number);
1043
1044 for(Index i = 0; i < parameters_number; i++)
1045 {
1046 h = calculate_h(parameters(i));
1047
1048 parameters_forward(i) += h;
1049
1050 neural_network_pointer->forward_propagate(batch, parameters_forward, forward_propagation);
1051
1052 calculate_errors(batch, forward_propagation, back_propagation);
1053
1054 calculate_error(batch, forward_propagation, back_propagation);
1055
1056 error_forward = back_propagation.error;
1057
1058 parameters_forward(i) -= h;
1059
1060 parameters_backward(i) -= h;
1061
1062 neural_network_pointer->forward_propagate(batch, parameters_backward, forward_propagation);
1063 calculate_errors(batch, forward_propagation, back_propagation);
1064 calculate_error(batch, forward_propagation, back_propagation);
1065 error_backward = back_propagation.error;
1066
1067 parameters_backward(i) += h;
1068
1069 gradient_numerical_differentiation(i) = (error_forward - error_backward)/(type(2)*h);
1070 }
1071
1072 return gradient_numerical_differentiation;
1073}
1074
1075
1076Tensor<type, 2> LossIndex::calculate_jacobian_numerical_differentiation()
1077{
1078 LossIndexBackPropagationLM back_propagation_lm;
1079
1080 const Index samples_number = data_set_pointer->get_training_samples_number();
1081
1082 DataSetBatch batch(samples_number, data_set_pointer);
1083
1084 const Tensor<Index, 1> samples_indices = data_set_pointer->get_training_samples_indices();
1085
1086 const Tensor<Index, 1> input_variables_indices = data_set_pointer->get_input_variables_indices();
1087 const Tensor<Index, 1> target_variables_indices = data_set_pointer->get_target_variables_indices();
1088
1089 batch.fill(samples_indices, input_variables_indices, target_variables_indices);
1090
1091 NeuralNetworkForwardPropagation forward_propagation(samples_number, neural_network_pointer);
1092
1093 LossIndexBackPropagation back_propagation(samples_number, this);
1094
1095 Tensor<type, 1> parameters = neural_network_pointer->get_parameters();
1096
1097 const Index parameters_number = parameters.size();
1098
1099 back_propagation_lm.set(samples_number, this);
1100
1101 neural_network_pointer->forward_propagate(batch, parameters, forward_propagation);
1102 calculate_errors_lm(batch, forward_propagation, back_propagation_lm);
1103 calculate_squared_errors_lm(batch, forward_propagation, back_propagation_lm);
1104
1105 type h;
1106
1107 Tensor<type, 1> parameters_forward(parameters);
1108 Tensor<type, 1> parameters_backward(parameters);
1109
1110 Tensor<type, 1> error_terms_forward(parameters_number);
1111 Tensor<type, 1> error_terms_backward(parameters_number);
1112
1113 Tensor<type, 2> jacobian(samples_number,parameters_number);
1114
1115 for(Index j = 0; j < parameters_number; j++)
1116 {
1117 h = calculate_h(parameters(j));
1118
1119 parameters_backward(j) -= h;
1120 neural_network_pointer->forward_propagate(batch, parameters_backward, forward_propagation);
1121 calculate_errors_lm(batch, forward_propagation, back_propagation_lm);
1122 calculate_squared_errors_lm(batch, forward_propagation, back_propagation_lm);
1123 error_terms_backward = back_propagation_lm.squared_errors;
1124 parameters_backward(j) += h;
1125
1126 parameters_forward(j) += h;
1127 neural_network_pointer->forward_propagate(batch, parameters_forward, forward_propagation);
1128 calculate_errors_lm(batch, forward_propagation, back_propagation_lm);
1129 calculate_squared_errors_lm(batch, forward_propagation, back_propagation_lm);
1130 error_terms_forward = back_propagation_lm.squared_errors;
1131 parameters_forward(j) -= h;
1132
1133 for(Index i = 0; i < samples_number; i++)
1134 {
1135 jacobian(i,j) = (error_terms_forward(i) - error_terms_backward(i))/(static_cast<type>(2.0)*h);
1136 }
1137 }
1138
1139 return jacobian;
1140}
1141
1142
1143type LossIndex::calculate_eta() const
1144{
1145 const Index precision_digits = 6;
1146
1147 return pow(static_cast<type>(10.0), static_cast<type>(-1.0*precision_digits));
1148}
1149
1150
1153
1154type LossIndex::calculate_h(const type& x) const
1155{
1156 const type eta = calculate_eta();
1157
1158 return sqrt(eta)*(static_cast<type>(1.0) + abs(x));
1159}
1160
1161}
1162
1163// OpenNN: Open Neural Networks Library.
1164// Copyright(C) 2005-2021 Artificial Intelligence Techniques, SL.
1165//
1166// This library is free software; you can redistribute it and/or
1167// modify it under the terms of the GNU Lesser General Public
1168// License as published by the Free Software Foundation; either
1169// version 2.1 of the License, or any later version.
1170//
1171// This library is distributed in the hope that it will be useful,
1172// but WITHOUT ANY WARRANTY; without even the implied warranty of
1173// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1174// Lesser General Public License for more details.
1175
1176// You should have received a copy of the GNU Lesser General Public
1177// License along with this library; if not, write to the Free Software
1178// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
This class represents the concept of data set for data modelling problems, such as approximation,...
Definition: data_set.h:57
Index get_training_samples_number() const
Returns the number of samples in the data set which will be used for training.
Definition: data_set.cpp:1382
Tensor< Index, 1 > get_training_samples_indices() const
Returns the indices of the samples which will be used for training.
Definition: data_set.cpp:1073
Tensor< Index, 1 > get_target_variables_indices() const
Returns the indices of the target variables.
Definition: data_set.cpp:3094
Index get_selection_samples_number() const
Returns the number of samples in the data set which will be used for selection.
Definition: data_set.cpp:1402
Tensor< Index, 1 > get_input_variables_indices() const
Returns the indices of the input variables.
Definition: data_set.cpp:3047
This abstract class represents the concept of loss index composed of an error term and a regularizati...
Definition: loss_index.h:48
type calculate_h(const type &) const
void calculate_regularization_hessian(const Tensor< type, 1 > &, Tensor< type, 2 > &) const
Definition: loss_index.cpp:688
DataSet * data_set_pointer
Pointer to a data set object.
Definition: loss_index.h:258
void set_regularization_method(const RegularizationMethod &)
Definition: loss_index.cpp:251
NeuralNetwork * neural_network_pointer
Pointer to a neural network object.
Definition: loss_index.h:254
virtual void set_data_set_pointer(DataSet *)
Sets a new data set on which the error term is to be measured.
Definition: loss_index.cpp:196
const bool & get_display() const
Definition: loss_index.cpp:61
bool has_selection() const
Returns true if there are selection samples and false otherwise.
Definition: loss_index.cpp:279
void from_XML(const tinyxml2::XMLDocument &)
Definition: loss_index.cpp:979
void set_default()
Sets the members of the error term to their default values:
Definition: loss_index.cpp:204
void check() const
Definition: loss_index.cpp:295
void calculate_squared_errors_jacobian_lm(const DataSetBatch &, NeuralNetworkForwardPropagation &, LossIndexBackPropagationLM &) const
Definition: loss_index.cpp:508
bool display
Display messages to screen.
Definition: loss_index.h:270
bool has_data_set() const
Definition: loss_index.cpp:86
void back_propagate_lm(const DataSetBatch &, NeuralNetworkForwardPropagation &, LossIndexBackPropagationLM &) const
Definition: loss_index.cpp:457
type regularization_weight
Regularization weight value.
Definition: loss_index.h:266
bool has_neural_network() const
Definition: loss_index.cpp:70
virtual string get_error_type() const
Returns a string with the default type of error term, "USER_PERFORMANCE_TERM".
Definition: loss_index.cpp:608
RegularizationMethod get_regularization_method() const
Returns the regularization method.
Definition: loss_index.cpp:101
virtual ~LossIndex()
Destructor.
Definition: loss_index.cpp:43
type calculate_regularization(const Tensor< type, 1 > &) const
Definition: loss_index.cpp:648
const type & get_regularization_weight() const
Returns regularization weight.
Definition: loss_index.cpp:52
void set_neural_network_pointer(NeuralNetwork *)
Definition: loss_index.cpp:188
string write_regularization_method() const
Definition: loss_index.cpp:625
RegularizationMethod regularization_method
Pointer to a regularization method object.
Definition: loss_index.h:262
void set_display(const bool &)
Definition: loss_index.cpp:271
RegularizationMethod
Enumeration of available regularization methods.
Definition: loss_index.h:66
virtual void write_XML(tinyxml2::XMLPrinter &) const
Definition: loss_index.cpp:881
void calculate_regularization_gradient(const Tensor< type, 1 > &, Tensor< type, 1 > &) const
Definition: loss_index.cpp:669
virtual string get_error_type_text() const
Returns a string with the default type of error term in text format, "USER_PERFORMANCE_TERM".
Definition: loss_index.cpp:616
void set_regularization_weight(const type &)
Definition: loss_index.cpp:260
Tensor< Layer *, 1 > get_trainable_layers_pointers() const
Returns a pointer to the trainable layers object composing this neural network object.
void forward_propagate(const DataSetBatch &, NeuralNetworkForwardPropagation &) const
Calculate forward propagation in neural network.
Tensor< type, 1 > get_parameters() const
void PushText(const char *text, bool cdata=false)
Add a text node.
Definition: tinyxml2.cpp:2878
void PushAttribute(const char *name, const char *value)
If streaming, add an attribute to an open element.
Definition: tinyxml2.cpp:2783
virtual void CloseElement(bool compactMode=false)
If streaming, close the Element.
Definition: tinyxml2.cpp:2834
HALF_CONSTEXPR half abs(half arg)
Definition: half.hpp:2735
half pow(half x, half y)
Definition: half.hpp:3427
virtual ~LossIndexBackPropagation()
Destructor.
A loss index composed of several terms, this structure represent the First Order for this function.
Definition: loss_index.h:383