normalized_squared_error.cpp
1// OpenNN: Open Neural Networks Library
2// www.opennn.net
3//
4// N O R M A L I Z E D S Q U A R E D E R R O R C L A S S
5//
6// Artificial Intelligence Techniques SL
7// artelnics@artelnics.com
8
9#include "normalized_squared_error.h"
10
11namespace OpenNN
12{
13
18
20{
22}
23
24
30
31NormalizedSquaredError::NormalizedSquaredError(NeuralNetwork* new_neural_network_pointer, DataSet* new_data_set_pointer)
32 : LossIndex(new_neural_network_pointer, new_data_set_pointer)
33{
35}
36
37
39
41{
42}
43
44
46
48{
50}
51
52
54
56{
57 return selection_normalization_coefficient;
58}
59
60
64
66{
67 data_set_pointer = new_data_set_pointer;
68
70 {
72 }
73 else
74 {
76 }
77}
78
79
82
84{
85 // Data set
86
87 const Tensor<type, 1> targets_mean = data_set_pointer->calculate_used_targets_mean();
88
89 // Targets matrix
90
91 const Tensor<type, 2> targets = data_set_pointer->get_target_data();
92
93 // Normalization coefficient
94
96}
97
98
100
102{
103 //Targets matrix
104
105 const Tensor<type, 2> targets = data_set_pointer->get_target_data();
106
107 const Index rows = targets.dimension(0)-1;
108 const Index columns = targets.dimension(1);
109
110 Tensor<type, 2> targets_t(rows, columns);
111 Tensor<type, 2> targets_t_1(rows, columns);
112
113 for(Index i = 0; i < columns; i++)
114 {
115 memcpy(targets_t_1.data() + targets_t_1.dimension(0) * i,
116 targets.data() + targets.dimension(0) * i,
117 static_cast<size_t>(rows)*sizeof(type));
118 }
119
120 for(Index i = 0; i < columns; i++)
121 {
122 memcpy(targets_t.data() + targets_t.dimension(0) * i,
123 targets.data() + targets.dimension(0) * i + 1,
124 static_cast<size_t>(rows)*sizeof(type));
125 }
126
127 //Normalization coefficient
128
129 normalization_coefficient = calculate_time_series_normalization_coefficient(targets_t_1, targets_t);
130}
131
132
133type NormalizedSquaredError::calculate_time_series_normalization_coefficient(const Tensor<type, 2>& targets_t_1,
134 const Tensor<type, 2>& targets_t) const
135{
136#ifdef OPENNN_DEBUG
137
138 check();
139
140 const Index target_t_1_samples_number = targets_t_1.dimension(0);
141 const Index target_t_1_variables_number = targets_t_1.dimension(1);
142 const Index target_t_samples_number = targets_t.dimension(0);
143 const Index target_t_variables_number = targets_t.dimension(1);
144
145 if(target_t_1_samples_number != target_t_samples_number || target_t_1_variables_number != target_t_variables_number)
146 {
147 ostringstream buffer;
148
149 buffer << "OpenNN Exception: NormalizedquaredError class.\n"
150 << "type calculate_time_series_normalization_coefficient(const Tensor<type, 2>& targets_t_1, const Tensor<type, 2>& targets_t) function.\n"
151 << " The columns number of targets("<< target_t_variables_number <<") must be equal("<< target_t_1_variables_number<<").\n"
152 << " The samples number of targets("<< target_t_1_samples_number <<") must be equal("<< target_t_samples_number<<").\n";
153
154 throw logic_error(buffer.str());
155 }
156#endif
157
158 const Index target_samples_number = targets_t_1.dimension(0);
159 const Index target_varaibles_number = targets_t_1.dimension(1);
160
161 type normalization_coefficient = type(0);
162
163 for(Index i = 0; i < target_samples_number; i++)
164 {
165 for(Index j = 0; j < target_varaibles_number; j++)
166 {
167 normalization_coefficient += (targets_t_1(i,j) - targets_t(i,j)) * (targets_t_1(i,j) - targets_t(i,j));
168 }
169 }
170
172}
173
174
177
178void NormalizedSquaredError::set_normalization_coefficient(const type& new_normalization_coefficient)
179{
180 normalization_coefficient = new_normalization_coefficient;
181}
182
183
186
188{
189 // Data set
190
191 const Tensor<Index, 1> selection_indices = data_set_pointer->get_selection_samples_indices();
192
193 const Index selection_samples_number = selection_indices.size();
194
195 if(selection_samples_number == 0) return;
196
197 const Tensor<type, 1> selection_targets_mean = data_set_pointer->calculate_selection_targets_mean();
198
199 const Tensor<type, 2> targets = data_set_pointer->get_selection_target_data();
200
201 // Normalization coefficient
202
203 selection_normalization_coefficient = calculate_normalization_coefficient(targets, selection_targets_mean);
204}
205
206
209
210void NormalizedSquaredError::set_selection_normalization_coefficient(const type& new_selection_normalization_coefficient)
211{
212 selection_normalization_coefficient = new_selection_normalization_coefficient;
213}
214
215
217
219{
221 {
224 }
225 else
226 {
227 normalization_coefficient = type(NAN);
228 selection_normalization_coefficient = type(NAN);
229 }
230}
231
232
237
239 const Tensor<type, 1>& targets_mean) const
240{
241#ifdef OPENNN_DEBUG
242
243 check();
244
245 const Index means_number = targets_mean.dimension(0);
246 const Index targets_number = targets.dimension(1);
247
248 if(targets_number != means_number)
249 {
250 ostringstream buffer;
251
252 buffer << "OpenNN Exception: NormalizedquaredError class.\n"
253 << "type calculate_normalization_coefficient(const Tensor<type, 2>& targets, const Tensor<type, 1>& targets_mean) function.\n"
254 << " The columns number of targets("<< targets_number <<") must be equal("<< means_number<<").\n";
255
256 throw logic_error(buffer.str());
257 }
258#endif
259
260 const Index size = targets.dimension(0);
261
262 type normalization_coefficient = type(0);
263
264 for(Index i = 0; i < size; i++)
265 {
266 const Tensor<type, 0> norm = (targets.chip(i,0) - targets_mean).square().sum();
267
268 normalization_coefficient += norm(0);
269 }
270
271 if(static_cast<type>(normalization_coefficient) < type(NUMERIC_LIMITS_MIN)) normalization_coefficient = type(1);
272
274}
275
276
281
284 LossIndexBackPropagation& back_propagation) const
285{
286#ifdef OPENNN_DEBUG
287
289 {
290 ostringstream buffer;
291
292 buffer << "OpenNN Exception: NormalizedquaredError class.\n"
293 << "calculate_error() method.\n"
294 << "Normalization coefficient is NAN.\n";
295
296 throw logic_error(buffer.str());
297 }
298#endif
299
300 Tensor<type, 0> sum_squared_error;
301
302 sum_squared_error.device(*thread_pool_device) = back_propagation.errors.contract(back_propagation.errors, SSE);
303
304 const Index batch_samples_number = batch.get_samples_number();
305 const Index total_samples_number = data_set_pointer->get_samples_number();
306
307 const type coefficient = ((static_cast<type>(batch_samples_number)/static_cast<type>(total_samples_number))*normalization_coefficient);
308
309 back_propagation.error
310 = sum_squared_error(0)/coefficient;
311}
312
313
314void NormalizedSquaredError::calculate_error_lm(const DataSetBatch& batch,
316 LossIndexBackPropagationLM& back_propagation) const
317{
318#ifdef OPENNN_DEBUG
319
321 {
322 ostringstream buffer;
323
324 buffer << "OpenNN Exception: NormalizedquaredError class.\n"
325 << "calculate_error() method.\n"
326 << "Normalization coefficient is NAN.\n";
327
328 throw logic_error(buffer.str());
329 }
330#endif
331
332 Tensor<type, 0> sum_squared_error;
333
334 sum_squared_error.device(*thread_pool_device) = (back_propagation.squared_errors*back_propagation.squared_errors).sum();
335
336 const Index batch_samples_number = batch.get_samples_number();
337 const Index total_samples_number = data_set_pointer->get_samples_number();
338
339 const type coefficient = ((static_cast<type>(batch_samples_number)/static_cast<type>(total_samples_number))*normalization_coefficient);
340
341 back_propagation.error = sum_squared_error(0)/coefficient;
342}
343
344
345void NormalizedSquaredError::calculate_output_delta(const DataSetBatch& batch,
346 NeuralNetworkForwardPropagation&,
347 LossIndexBackPropagation& back_propagation) const
348{
349#ifdef OPENNN_DEBUG
350
351 check();
352
353#endif
354
355 const Index trainable_layers_number = neural_network_pointer->get_trainable_layers_number();
356
357 LayerBackPropagation* output_layer_back_propagation = back_propagation.neural_network.layers(trainable_layers_number-1);
358
359 Layer* output_layer_pointer = output_layer_back_propagation->layer_pointer;
360
361 const Index batch_samples_number = batch.get_samples_number();
362 const Index total_samples_number = data_set_pointer->get_samples_number();
363
364 const type coefficient
365 = static_cast<type>(2)/(static_cast<type>(batch_samples_number)/static_cast<type>(total_samples_number)*normalization_coefficient);
366
367 switch(output_layer_pointer->get_type())
368 {
369 case Layer::Type::Perceptron:
370 {
371 PerceptronLayerBackPropagation* perceptron_layer_back_propagation
372 = static_cast<PerceptronLayerBackPropagation*>(output_layer_back_propagation);
373
374 perceptron_layer_back_propagation->delta.device(*thread_pool_device) = coefficient*back_propagation.errors;
375 }
376 break;
377
378 case Layer::Type::Probabilistic:
379 {
380 ProbabilisticLayerBackPropagation* probabilistic_layer_back_propagation
381 = static_cast<ProbabilisticLayerBackPropagation*>(output_layer_back_propagation);
382
383 probabilistic_layer_back_propagation->delta.device(*thread_pool_device) = coefficient*back_propagation.errors;
384 }
385 break;
386
387 case Layer::Type::Recurrent:
388 {
389 RecurrentLayerBackPropagation* recurrent_layer_back_propagation
390 = static_cast<RecurrentLayerBackPropagation*>(output_layer_back_propagation);
391
392 recurrent_layer_back_propagation->delta.device(*thread_pool_device) = coefficient*back_propagation.errors;
393 }
394 break;
395
396 case Layer::Type::LongShortTermMemory:
397 {
398 LongShortTermMemoryLayerBackPropagation* long_short_term_memory_layer_back_propagation
399 = static_cast<LongShortTermMemoryLayerBackPropagation*>(output_layer_back_propagation);
400
401 long_short_term_memory_layer_back_propagation->delta.device(*thread_pool_device) = coefficient*back_propagation.errors;
402 }
403 break;
404
405 default: break;
406 }
407}
408
409
410void NormalizedSquaredError::calculate_output_delta_lm(const DataSetBatch& ,
411 NeuralNetworkForwardPropagation&,
412 LossIndexBackPropagationLM & loss_index_back_propagation) const
413{
414#ifdef OPENNN_DEBUG
415 check();
416#endif
417
418 const Index trainable_layers_number = neural_network_pointer->get_trainable_layers_number();
419
420 LayerBackPropagationLM* output_layer_back_propagation = loss_index_back_propagation.neural_network.layers(trainable_layers_number-1);
421
422 Layer* output_layer_pointer = output_layer_back_propagation->layer_pointer;
423
424 switch(output_layer_pointer->get_type())
425 {
426 case Layer::Type::Perceptron:
427 {
428 PerceptronLayerBackPropagationLM* perceptron_layer_back_propagation
429 = static_cast<PerceptronLayerBackPropagationLM*>(output_layer_back_propagation);
430
431 memcpy(perceptron_layer_back_propagation->delta.data(),
432 loss_index_back_propagation.errors.data(),
433 static_cast<size_t>(loss_index_back_propagation.errors.size())*sizeof(type));
434
435 divide_columns(perceptron_layer_back_propagation->delta, loss_index_back_propagation.squared_errors);
436 }
437 break;
438
439 case Layer::Type::Probabilistic:
440 {
441 ProbabilisticLayerBackPropagationLM* probabilistic_layer_back_propagation
442 = static_cast<ProbabilisticLayerBackPropagationLM*>(output_layer_back_propagation);
443
444 memcpy(probabilistic_layer_back_propagation->delta.data(),
445 loss_index_back_propagation.errors.data(),
446 static_cast<size_t>(loss_index_back_propagation.errors.size())*sizeof(type));
447
448 divide_columns(probabilistic_layer_back_propagation->delta, loss_index_back_propagation.squared_errors);
449 }
450 break;
451
452 default:
453 {
454 ostringstream buffer;
455
456 buffer << "OpenNN Exception: NeuralNetwork class.\n"
457 << "Levenberg-Marquardt can only be used with Perceptron and Probabilistic layers.\n";
458
459 throw logic_error(buffer.str());
460 }
461 }
462}
463
464
465void NormalizedSquaredError::calculate_error_gradient_lm(const DataSetBatch& batch,
466 LossIndexBackPropagationLM& loss_index_back_propagation_lm) const
467{
468 const Index batch_samples_number = batch.get_samples_number();
469 const Index total_samples_number = data_set_pointer->get_samples_number();
470
471 const type coefficient = type(2)/((static_cast<type>(batch_samples_number)/static_cast<type>(total_samples_number))*normalization_coefficient);
472
473 loss_index_back_propagation_lm.gradient.device(*thread_pool_device)
474 = loss_index_back_propagation_lm.squared_errors_jacobian.contract(loss_index_back_propagation_lm.squared_errors, AT_B);
475
476 loss_index_back_propagation_lm.gradient.device(*thread_pool_device) = coefficient * loss_index_back_propagation_lm.gradient;
477}
478
479
480void NormalizedSquaredError::calculate_error_hessian_lm(const DataSetBatch& batch,
481 LossIndexBackPropagationLM& loss_index_back_propagation_lm) const
482{
483#ifdef OPENNN_DEBUG
484
485 check();
486
487#endif
488
489 const Index batch_samples_number = batch.get_samples_number();
490 const Index total_samples_number = data_set_pointer->get_samples_number();
491
492 const type coefficient = type(2)/((static_cast<type>(batch_samples_number)/static_cast<type>(total_samples_number))*normalization_coefficient);
493
494 loss_index_back_propagation_lm.hessian.device(*thread_pool_device) =
495 loss_index_back_propagation_lm.squared_errors_jacobian.contract(loss_index_back_propagation_lm.squared_errors_jacobian, AT_B);
496
497 loss_index_back_propagation_lm.hessian.device(*thread_pool_device) = coefficient*loss_index_back_propagation_lm.hessian;
498}
499
500
502
504{
505 return "NORMALIZED_SQUARED_ERROR";
506}
507
508
510
512{
513 return "Normalized squared error";
514}
515
516
519
521{
522 // Error type
523
524 file_stream.OpenElement("NormalizedSquaredError");
525
526 file_stream.CloseElement();
527}
528
529
532
534{
535 const tinyxml2::XMLElement* root_element = document.FirstChildElement("NormalizedSquaredError");
536
537 if(!root_element)
538 {
539 ostringstream buffer;
540
541 buffer << "OpenNN Exception: NormalizedSquaredError class.\n"
542 << "void from_XML(const tinyxml2::XMLDocument&) method.\n"
543 << "Normalized squared element is nullptr.\n";
544
545 throw logic_error(buffer.str());
546 }
547}
548
549}
550
551// OpenNN: Open Neural Networks Library.
552// Copyright(C) 2005-2021 Artificial Intelligence Techniques, SL.
553//
554// This library is free software; you can redistribute it and/or
555// modify it under the terms of the GNU Lesser General Public
556// License as published by the Free Software Foundation; either
557// version 2.1 of the License, or any later version.
558//
559// This library is distributed in the hope that it will be useful,
560// but WITHOUT ANY WARRANTY; without even the implied warranty of
561// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
562// Lesser General Public License for more details.
563
564// You should have received a copy of the GNU Lesser General Public
565// License along with this library; if not, write to the Free Software
566// 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
Tensor< type, 2 > get_target_data() const
Definition: data_set.cpp:3972
Tensor< Index, 1 > get_selection_samples_indices() const
Returns the indices of the samples which will be used for selection.
Definition: data_set.cpp:1098
Tensor< type, 1 > calculate_selection_targets_mean() const
Returns the mean values of the target variables on the selection.
Definition: data_set.cpp:5843
bool is_empty() const
Returns true if the data matrix is empty, and false otherwise.
Definition: data_set.cpp:3658
Tensor< type, 2 > get_selection_target_data() const
Definition: data_set.cpp:4052
This abstract class represents the concept of loss index composed of an error term and a regularizati...
Definition: loss_index.h:48
DataSet * data_set_pointer
Pointer to a data set object.
Definition: loss_index.h:258
NeuralNetwork * neural_network_pointer
Pointer to a neural network object.
Definition: loss_index.h:254
void check() const
Definition: loss_index.cpp:295
bool has_data_set() const
Definition: loss_index.cpp:86
bool has_neural_network() const
Definition: loss_index.cpp:70
bool has_long_short_term_memory_layer() const
bool has_recurrent_layer() const
type normalization_coefficient
Coefficient of normalization for the calculation of the training error.
type get_selection_normalization_coefficient() const
Returns the selection normalization coefficient.
void from_XML(const tinyxml2::XMLDocument &)
void set_default()
Sets the default values.
void calculate_error(const DataSetBatch &, const NeuralNetworkForwardPropagation &, LossIndexBackPropagation &) const
NormalizedSquaredError::calculate_error.
type get_normalization_coefficient() const
Returns the normalization coefficient.
string get_error_type() const
Returns a string with the name of the normalized squared error loss type, "NORMALIZED_SQUARED_ERROR".
type calculate_normalization_coefficient(const Tensor< type, 2 > &, const Tensor< type, 1 > &) const
void set_data_set_pointer(DataSet *new_data_set_pointer)
set_data_set_pointer
void write_XML(tinyxml2::XMLPrinter &) const
string get_error_type_text() const
Returns a string with the name of the normalized squared error loss type in text format.
virtual void CloseElement(bool compactMode=false)
If streaming, close the Element.
Definition: tinyxml2.cpp:2834
HALF_CONSTEXPR bool isnan(half arg)
Definition: half.hpp:4385
A loss index composed of several terms, this structure represent the First Order for this function.
Definition: loss_index.h:383