correlations.cpp
1// OpenNN: Open Neural Networks Library
2// www.opennn.net
3//
4// C O R R E L A T I O N S
5//
6// Artificial Intelligence Techniques SL
7// artelnics@artelnics.com
8
9#include "correlations.h"
10#include "data_set.h"
11#include "neural_network.h"
12#include "training_strategy.h"
13
14namespace OpenNN
15{
16
20
21Correlation linear_correlation(const ThreadPoolDevice* thread_pool_device,
22 const Tensor<type, 1>& x,
23 const Tensor<type, 1>& y)
24{
25#ifdef OPENNN_DEBUG
26
27 const Index x_size = x.size();
28
29 ostringstream buffer;
30
31 if(x_size != y.size())
32 {
33 buffer << "OpenNN Exception: Vector Template.\n"
34 << "Correlation linear_correlation(const Tensor<type, 1>&) const method.\n"
35 << "Y size must be equal to X size.\n";
36
37 throw logic_error(buffer.str());
38 }
39
40#endif
41
42 Correlation linear_correlation;
43
44 linear_correlation.correlation_type = CorrelationMethod::Linear;
45
46 if(is_constant(y))
47 {
48 linear_correlation.a = y(0);
49 linear_correlation.b = type(0);
50 linear_correlation.r = type(1);
51
52 return linear_correlation;
53 }
54
55 pair<Tensor<type, 1>, Tensor<type, 1>> filter_vectors = filter_missing_values_vector_vector(x,y);
56
57 const Tensor<double, 1> x_filter = filter_vectors.first.cast<double>();
58 const Tensor<double, 1> y_filter = filter_vectors.second.cast<double>();
59
60 Tensor<double, 0> s_x;
61 Tensor<double, 0> s_y;
62
63 Tensor<double, 0> s_xx;
64 Tensor<double, 0> s_yy;
65
66 Tensor<double, 0> s_xy;
67
68 s_x.device(*thread_pool_device) = x_filter.sum();
69 s_y.device(*thread_pool_device) = y_filter.sum();
70 s_xx.device(*thread_pool_device) = x_filter.square().sum();
71 s_yy.device(*thread_pool_device) = y_filter.square().sum();
72 s_xy.device(*thread_pool_device) = (y_filter*x_filter).sum();
73
74 if(abs(s_x()) < NUMERIC_LIMITS_MIN
75 && abs(s_y()) < NUMERIC_LIMITS_MIN
76 && abs(s_xx()) < NUMERIC_LIMITS_MIN
77 && abs(s_yy()) < NUMERIC_LIMITS_MIN
78 && abs(s_xy()) < NUMERIC_LIMITS_MIN)
79 {
80 linear_correlation.a = type(0);
81
82 linear_correlation.b = type(0);
83
84 linear_correlation.r = type(1);
85 }
86 else
87 {
88 const Index n = x_filter.size();
89
90 linear_correlation.a =
91 type((s_y() * s_xx() - s_x() * s_xy())/(static_cast<double>(n) * s_xx() - s_x() * s_x()));
92
93 linear_correlation.b =
94 type(((static_cast<double>(n) * s_xy()) - (s_x() * s_y())) /((static_cast<double>(n) * s_xx()) - (s_x() * s_x())));
95
96 if(sqrt((static_cast<double>(n) * s_xx() - s_x() * s_x()) *(static_cast<double>(n) * s_yy() - s_y() * s_y())) < NUMERIC_LIMITS_MIN)
97 {
98 linear_correlation.r = type(1);
99 }
100 else
101 {
102 linear_correlation.r =
103 type((static_cast<double>(n) * s_xy() - s_x() * s_y()) /
104 sqrt((static_cast<double>(n) * s_xx() - s_x() * s_x()) *(static_cast<double>(n) * s_yy() - s_y() * s_y())));
105 }
106 }
107
108 return linear_correlation;
109}
110
111
116
117Correlation logarithmic_correlation(const ThreadPoolDevice* thread_pool_device, const Tensor<type, 1>& x, const Tensor<type, 1>& y)
118{
119#ifdef OPENNN_DEBUG
120
121 Index n = y.size();
122
123 const Index x_size = x.size();
124
125 ostringstream buffer;
126
127 if(x_size != n)
128 {
129 buffer << "OpenNN Exception: Vector Template.\n"
130 << "Correlation "
131 "logarithmic_correlation(const Tensor<type, 1>&) const "
132 "method.\n"
133 << "Y size must be equal to X size.\n";
134
135 throw logic_error(buffer.str());
136 }
137
138#endif
139
140 // Check negative values from x
141
142 Correlation logarithmic_correlation;
143
144 for(Index i = 0; i < x.dimension(0); i++)
145 {
146 if(!isnan(x(i)) && x(i) <= type(0))
147 {
148 logarithmic_correlation.r = type(NAN);
149
150 return logarithmic_correlation;
151 }
152 }
153
154 logarithmic_correlation = linear_correlation(thread_pool_device, x.log(), y);
155
156 logarithmic_correlation.correlation_type = CorrelationMethod::Logarithmic;
157
158 return logarithmic_correlation;
159}
160
161
165
166Correlation exponential_correlation(const ThreadPoolDevice* thread_pool_device, const Tensor<type, 1>& x, const Tensor<type, 1>& y)
167{
168#ifdef OPENNN_DEBUG
169
170 ostringstream buffer;
171
172 if(x.size() != y.size())
173 {
174 buffer << "OpenNN Exception: Vector Template.\n"
175 << "Correlation "
176 "exponential_correlation(const Tensor<type, 1>&, const Tensor<type, 1>&) const method.\n"
177 << "Y size must be equal to X size.\n";
178
179 throw logic_error(buffer.str());
180 }
181
182#endif
183
184 // Check negative values from y
185
186 Correlation exponential_correlation;
187
188 for(Index i = 0; i < y.dimension(0); i++)
189 {
190 if(!isnan(y(i)) && y(i) <= type(0))
191 {
192 exponential_correlation.r = type(NAN);
193
194 return exponential_correlation;
195 }
196 }
197
198 exponential_correlation = linear_correlation(thread_pool_device, x, y.log());
199
200 exponential_correlation.correlation_type = CorrelationMethod::Exponential;
201
202 exponential_correlation.a = exp(exponential_correlation.a);
203 exponential_correlation.b = exponential_correlation.b;
204
205 return exponential_correlation;
206}
207
208
212
213Correlation power_correlation(const ThreadPoolDevice* thread_pool_device, const Tensor<type, 1>& x, const Tensor<type, 1>& y)
214{
215#ifdef OPENNN_DEBUG
216
217 ostringstream buffer;
218
219 if(x.size() != y.size())
220 {
221 buffer << "OpenNN Exception: Vector Template.\n"
222 << "Correlation "
223 "power_correlation(const Tensor<type, 1>&) const "
224 "method.\n"
225 << "Y size must be equal to X size.\n";
226
227 throw logic_error(buffer.str());
228 }
229
230#endif
231
232 // Check negative values from x and y
233
234 Correlation power_correlation;
235
236 for(Index i = 0; i < x.dimension(0); i++)
237 {
238 if(!isnan(x(i)) && x(i) <= type(0))
239 {
240 power_correlation.r = type(NAN);
241
242 return power_correlation;
243 }
244
245 if(!isnan(y(i)) && y(i) <= type(0))
246 {
247 power_correlation.r = type(NAN);
248
249 return power_correlation;
250 }
251 }
252
253 power_correlation = linear_correlation(thread_pool_device, x.log(), y.log());
254
255 power_correlation.correlation_type = CorrelationMethod::Power;
256
257 power_correlation.a = exp(power_correlation.a);
258
259 return power_correlation;
260}
261
262
266
267Correlation logistic_correlation_vector_vector(const ThreadPoolDevice* thread_pool_device, const Tensor<type, 1>& x, const Tensor<type, 1>& y)
268{
269 Correlation correlation;
270
271 const Tensor<type, 2> data = assemble_vector_vector(x, y);
272
273 DataSet data_set(data);
274 data_set.set_training();
275
276 data_set.set_columns_scalers(Scaler::MinimumMaximum);
277
278 NeuralNetwork neural_network(NeuralNetwork::ProjectType::Classification, {1,1});
279
280 neural_network.get_probabilistic_layer_pointer()->set_activation_function(ProbabilisticLayer::ActivationFunction::Logistic);
281
282 TrainingStrategy training_strategy(&neural_network, &data_set);
283 training_strategy.set_display(false);
284 training_strategy.set_display_period(1);
285
286 training_strategy.set_loss_method(TrainingStrategy::LossMethod::NORMALIZED_SQUARED_ERROR);
287 training_strategy.get_loss_index_pointer()->set_regularization_method(LossIndex::RegularizationMethod::NoRegularization);
288
289 training_strategy.set_optimization_method(TrainingStrategy::OptimizationMethod::LEVENBERG_MARQUARDT_ALGORITHM);
290
291 training_strategy.perform_training();
292
293 const Tensor<type, 2> inputs = data_set.get_input_data();
294 const Tensor<type, 2> targets = data_set.get_target_data();
295 const Tensor<type, 2> outputs = neural_network.calculate_outputs(inputs);
296
297 // Logistic correlation
298
299 const Eigen::array<Index, 1> vector{{x.size()}};
300
301 correlation.r = linear_correlation(thread_pool_device, outputs.reshape(vector), targets.reshape(vector)).r;
302
303 correlation.correlation_type = CorrelationMethod::Logistic;
304
305 const Tensor<type, 1> coefficients = neural_network.get_parameters();
306
307 correlation.a = coefficients(0);
308 correlation.b = coefficients(1);
309
310 if(correlation.b < type(0)) correlation.r *= type(-1);
311
312 return correlation;
313}
314
315
316Correlation logistic_correlation_vector_matrix(const ThreadPoolDevice* thread_pool_device,
317 const Tensor<type, 1>& x,
318 const Tensor<type, 2>& y)
319{
320 Correlation correlation;
321
322 const Tensor<type, 2> data = OpenNN::assemble_vector_matrix(x, y);
323
324 Tensor<Index, 1> input_columns_indices(1);
325 input_columns_indices(0) = 0;
326
327 Tensor<Index, 1> target_columns_indices(y.dimension(1));
328 for(Index i = 0; i < y.dimension(1); i++) target_columns_indices(i) = 1+i;
329
330 DataSet data_set(data);
331
332 data_set.set_input_target_columns(input_columns_indices, target_columns_indices);
333
334 data_set.set_training();
335
336 const Index input_variables_number = data_set.get_input_variables_number();
337 const Index target_variables_number = data_set.get_target_variables_number();
338
339 NeuralNetwork neural_network(NeuralNetwork::ProjectType::Classification, {input_variables_number, target_variables_number});
340 neural_network.get_probabilistic_layer_pointer()->set_activation_function(ProbabilisticLayer::ActivationFunction::Logistic);
341
342 TrainingStrategy training_strategy(&neural_network, &data_set);
343
344 training_strategy.get_loss_index_pointer()->set_regularization_method(LossIndex::RegularizationMethod::NoRegularization);
345
346 training_strategy.set_optimization_method(TrainingStrategy::OptimizationMethod::LEVENBERG_MARQUARDT_ALGORITHM);
347
348 training_strategy.set_display(false);
349
350 training_strategy.perform_training();
351
352 // Logistic correlation
353
354 const Tensor<type, 2> inputs = data_set.get_input_data();
355 const Tensor<type, 2> targets = data_set.get_target_data();
356 const Tensor<type, 2> outputs = neural_network.calculate_outputs(inputs);
357
358 const Eigen::array<Index, 1> vector{{targets.size()}};
359
360 correlation.r = linear_correlation(thread_pool_device, outputs.reshape(vector), targets.reshape(vector)).r;
361
362 correlation.correlation_type = CorrelationMethod::Logistic;
363
364 return correlation;
365}
366
367
368Correlation logistic_correlation_matrix_vector(const ThreadPoolDevice* thread_pool_device,
369 const Tensor<type, 2>& x, const Tensor<type, 1>& y)
370{
371 return OpenNN::logistic_correlation_vector_matrix(thread_pool_device, y, x);
372}
373
374
375Correlation logistic_correlation_matrix_matrix(const ThreadPoolDevice* thread_pool_device, const Tensor<type, 2>& x, const Tensor<type, 2>& y)
376{
377 Correlation correlation;
378
379 const Tensor<type, 2> data = OpenNN::assemble_matrix_matrix(x, y);
380
381 Tensor<Index, 1> input_columns_indices(1);
382 input_columns_indices(0) = 0;
383
384 Tensor<Index, 1> target_columns_indices(y.dimension(1));
385 for(Index i = 0; i < y.dimension(1); i++) target_columns_indices(i) = 1+i;
386
387 DataSet data_set(data);
388
389 data_set.set_input_target_columns(input_columns_indices, target_columns_indices);
390
391 data_set.set_training();
392
393 const Index input_variables_number = data_set.get_input_variables_number();
394 const Index target_variables_number = data_set.get_target_variables_number();
395
396 NeuralNetwork neural_network(NeuralNetwork::ProjectType::Classification, {input_variables_number, target_variables_number});
397 neural_network.get_probabilistic_layer_pointer()->set_activation_function(ProbabilisticLayer::ActivationFunction::Logistic);
398
399 TrainingStrategy training_strategy(&neural_network, &data_set);
400
401 training_strategy.get_loss_index_pointer()->set_regularization_method(LossIndex::RegularizationMethod::NoRegularization);
402
403 training_strategy.set_optimization_method(TrainingStrategy::OptimizationMethod::LEVENBERG_MARQUARDT_ALGORITHM);
404
405 training_strategy.set_display(false);
406
407 training_strategy.perform_training();
408
409 // Logistic correlation
410
411 const Tensor<type, 2> inputs = data_set.get_input_data();
412 const Tensor<type, 2> targets = data_set.get_target_data();
413 const Tensor<type, 2> outputs = neural_network.calculate_outputs(inputs);
414
415 const Eigen::array<Index, 1> vector{{targets.size()}};
416
417 correlation.r = linear_correlation(thread_pool_device, outputs.reshape(vector), targets.reshape(vector)).r;
418
419 correlation.correlation_type = CorrelationMethod::Logistic;
420
421 return correlation;
422}
423
424
425Correlation correlation(const ThreadPoolDevice* thread_pool_device, const Tensor<type, 2>& x, const Tensor<type, 2>& y)
426{
427 Correlation correlation;
428
429 const Index x_rows = x.dimension(0);
430 const Index x_columns = x.dimension(1);
431 const Index y_columns = y.dimension(1);
432
433 const bool x_binary = is_binary(x);
434 const bool y_binary = is_binary(y);
435
436 const Eigen::array<Index, 1> vector{{x_rows}};
437
438 if(x_columns == 1 && y_columns == 1)
439 {
440 if(!x_binary && !y_binary)
441 {
442 const Correlation linear_correlation
443 = OpenNN::linear_correlation(thread_pool_device, x.reshape(vector), y.reshape(vector));
444
445 const Correlation exponential_correlation
446 = OpenNN::exponential_correlation(thread_pool_device, x.reshape(vector), y.reshape(vector));
447
448 const Correlation logarithmic_correlation
449 = OpenNN::logarithmic_correlation(thread_pool_device, x.reshape(vector), y.reshape(vector));
450
451 const Correlation power_correlation
452 = OpenNN::power_correlation(thread_pool_device, x.reshape(vector), y.reshape(vector));
453
454 Correlation strongest_correlation = linear_correlation;
455
456 if(abs(exponential_correlation.r) > abs(strongest_correlation.r))
457 strongest_correlation = exponential_correlation;
458
459 if(abs(logarithmic_correlation.r) > abs(strongest_correlation.r))
460 strongest_correlation = logarithmic_correlation;
461
462 if(abs(power_correlation.r) > abs(strongest_correlation.r))
463 strongest_correlation = power_correlation;
464
465 return strongest_correlation;
466 }
467 else if(!x_binary && y_binary)
468 {
469 return OpenNN::logistic_correlation_vector_vector(thread_pool_device, x.reshape(vector), y.reshape(vector));
470 }
471 else if(x_binary && !y_binary)
472 {
473 return OpenNN::logistic_correlation_vector_vector(thread_pool_device, y.reshape(vector), x.reshape(vector));
474 }
475 else if(x_binary && y_binary)
476 {
477 return OpenNN::linear_correlation(thread_pool_device, x.reshape(vector), y.reshape(vector));
478 }
479 }
480 else if(x_columns != 1 && y_columns == 1)
481 {
482 return OpenNN::logistic_correlation_matrix_vector(thread_pool_device, x, y.reshape(vector));
483 }
484 else if(x_columns == 1 && y_columns != 1)
485 {
486 return OpenNN::logistic_correlation_vector_matrix(thread_pool_device, x.reshape(vector), y);
487 }
488 else if(x_columns != 1 && y_columns != 1)
489 {
490 return OpenNN::logistic_correlation_matrix_matrix(thread_pool_device, x, y);
491 }
492 else
493 {
494 throw logic_error("Correlations Exception: Unknown case.");
495 }
496
497 return correlation;
498}
499
500
502
503pair<Tensor<type, 1>, Tensor<type, 1>> filter_missing_values_vector_vector(const Tensor<type, 1>& x, const Tensor<type, 1>& y)
504{
505 Index new_size = 0;
506
507 for(Index i = 0; i < x.size(); i++)
508 {
509 if(!isnan(x(i)) && !isnan(y(i))) new_size++;
510 }
511
512 if(new_size == x.size())
513 {
514 return make_pair(x, y);
515 }
516
517 Tensor<type, 1> new_x(new_size);
518
519 Tensor<type, 1> new_y(new_size);
520
521 Index index = 0;
522
523 for(Index i = 0; i < x.size(); i++)
524 {
525 if(!isnan(x(i)) && !isnan(y(i)))
526 {
527 new_x(index) = x(i);
528 new_y(index) = y(i);
529
530 index++;
531 }
532 }
533
534 return make_pair(new_x, new_y);
535}
536
537
538pair<Tensor<type, 2>, Tensor<type, 2>> filter_missing_values_matrix_matrix(const Tensor<type, 2>& x, const Tensor<type, 2>& y)
539{
540 const Index rows_number = x.dimension(0);
541 const Index x_columns_number = x.dimension(1);
542 const Index y_columns_number = y.dimension(1);
543
544 Index new_rows_number = 0;
545
546 Tensor<bool, 1> not_NAN_row(rows_number);
547
548 for(Index i = 0; i < rows_number; i++)
549 {
550 not_NAN_row(i) = true;
551
552 if(float(isnan(y(i))))
553 {
554 not_NAN_row(i) = false;
555 }
556 else
557 {
558 for(Index j = 0; j < x_columns_number; j++)
559 {
560 if(float(isnan(x(i,j))))
561 {
562 not_NAN_row(i) = false;
563 break;
564 }
565 }
566 }
567
568 if(not_NAN_row(i)) new_rows_number++;
569 }
570
571 Tensor<type, 2> new_x(new_rows_number, x_columns_number);
572
573 Tensor<type, 2> new_y(new_rows_number,y_columns_number);
574
575 Index index = 0;
576
577 for(Index i = 0; i < rows_number; i++)
578 {
579 if(not_NAN_row(i))
580 {
581 for(Index j = 0; j < y_columns_number; j++)
582 {
583 new_y(index, j) = y(i,j);
584 }
585
586 for(Index j = 0; j < x_columns_number; j++)
587 {
588 new_x(index, j) = x(i, j);
589 }
590
591 index++;
592 }
593 }
594
595 return make_pair(new_x, new_y);
596}
597
598
602
603Tensor<type, 1> autocorrelations(const ThreadPoolDevice* thread_pool_device, const Tensor<type, 1>& x, const Index& lags_number)
604{
605 Tensor<type, 1> autocorrelation(lags_number);
606
607 const Index this_size = x.size();
608
609 for(Index i = 0; i < lags_number; i++)
610 {
611 Tensor<type, 1> column_x(this_size-i);
612 Tensor<type, 1> column_y(this_size-i);
613
614 for(Index j = 0; j < this_size - i; j++)
615 {
616 column_x(j) = x(j);
617 column_y(j) = x(j + i);
618 }
619
620 autocorrelation(i) = linear_correlation(thread_pool_device, column_x, column_y).r;
621 }
622
623 return autocorrelation;
624}
625
626
631
632Tensor<type, 1> cross_correlations(const ThreadPoolDevice* thread_pool_device,
633 const Tensor<type, 1>& x, const Tensor<type, 1>& y, const Index& maximum_lags_number)
634{
635 if(y.size() != x.size())
636 {
637 ostringstream buffer;
638
639 buffer << "OpenNN Exception: Correlations.\n"
640 << "Tensor<type, 1> calculate_cross_correlation(const Tensor<type, 1>&) method.\n"
641 << "Both vectors must have the same size.\n";
642
643 throw logic_error(buffer.str());
644 }
645
646 Tensor<type, 1> cross_correlation(maximum_lags_number);
647
648 const Index this_size = x.size();
649
650 for(Index i = 0; i < maximum_lags_number; i++)
651 {
652 Tensor<type, 1> column_x(this_size-i);
653 Tensor<type, 1> column_y(this_size-i);
654
655 for(Index j = 0; j < this_size - i; j++)
656 {
657 column_x(j) = x(j);
658 column_y(j) = y(j + i);
659 }
660
661 cross_correlation[i] = linear_correlation(thread_pool_device, column_x, column_y).r;
662 }
663
664 return cross_correlation;
665}
666
667
668Tensor<type, 2> get_correlation_values(const Tensor<Correlation, 2>& correlations)
669{
670 const Index rows_number = correlations.dimension(0);
671 const Index columns_number = correlations.dimension(1);
672
673 Tensor<type, 2> values(rows_number, columns_number);
674
675 for(Index i = 0; i < rows_number; i++)
676 {
677 for(Index j = 0; j < columns_number; j++)
678 {
679 values(i,j) = correlations(i,j).r;
680 }
681 }
682
683 return values;
684}
685
686}
687
688// OpenNN: Open Neural Networks Library.
689// Copyright(C) 2005-2021 Artificial Intelligence Techniques, SL.
690//
691// This library is free software; you can redistribute it and/or
692// modify it under the terms of the GNU Lesser General Public
693// License as published by the Free Software Foundation; either
694// version 2.1 of the License, or any later version.
695//
696// This library is distributed in the hope that it will be useful,
697// but WITHOUT ANY WARRANTY; without even the implied warranty of
698// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
699// Lesser General Public License for more details.
700
701// You should have received a copy of the GNU Lesser General Public
702// License along with this library; if not, write to the Free Software
703// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
uint32 sqrt(uint32 &r, int &exp)
Definition: half.hpp:1480
HALF_CONSTEXPR half abs(half arg)
Definition: half.hpp:2735
HALF_CONSTEXPR bool isnan(half arg)
Definition: half.hpp:4385
half exp(half arg)
Definition: half.hpp:2936
type a
Independent coefficient of the logistic function.
Definition: correlations.h:70
CorrelationMethod correlation_type
Regression method type.
Definition: correlations.h:82
type r
Correlation coefficient of the regression.
Definition: correlations.h:78
type b
x coefficient of the logistic function.
Definition: correlations.h:74