From c930da157610d78d81d355e032563dc69b439c2d Mon Sep 17 00:00:00 2001
From: Martin Beseda <martin.beseda@vsb.cz>
Date: Tue, 22 Jan 2019 15:06:16 +0100
Subject: [PATCH] FIX: MSE is now evaluated againts de-normalized data

---
 src/ErrorFunction/ErrorFunctions.cpp | 59 ++++++++++++++++++++++------
 1 file changed, 48 insertions(+), 11 deletions(-)

diff --git a/src/ErrorFunction/ErrorFunctions.cpp b/src/ErrorFunction/ErrorFunctions.cpp
index 89f5cde2..e4b386d2 100644
--- a/src/ErrorFunction/ErrorFunctions.cpp
+++ b/src/ErrorFunction/ErrorFunctions.cpp
@@ -111,6 +111,7 @@ namespace lib4neuro {
         size_t n_elements = data->size();
 
         //TODO instead use something smarter
+        std::vector<std::vector<double>> outputs(data->size());
         std::vector<double> output(dim_out);
 
         COUT_DEBUG("Evaluation of the error function MSE on the given data-set (format 'data-set element index' 'input'"
@@ -127,8 +128,16 @@ namespace lib4neuro {
                                    output,
                                    weights);
 
-            /* Compute difference for every element of the output vector */
+            outputs.at(i) = output;
+        }
+
+        if(data_set->is_normalized()) {
+            data_set->de_normalize();
+        }
+
+        for (auto i = 0; i < data->size(); i++) {
 
+            /* Compute difference for every element of the output vector */
 #ifdef L4N_DEBUG
             std::stringstream ss_input;
             for(auto j = 0; j < dim_in-1; j++) {
@@ -139,16 +148,18 @@ namespace lib4neuro {
             std::stringstream ss_real_output;
             std::stringstream ss_predicted_output;
 #endif
+            double denormalized_output;
             for (size_t j = 0; j < dim_out; ++j) {
+                denormalized_output = data_set->get_normalization_strategy()->de_normalize(outputs.at(i).at(j));
 #ifdef L4N_DEBUG
                 ss_real_output << data->at(i).second.at(j);
-                ss_predicted_output << output.at(j);
+                ss_predicted_output << denormalized_output;
 #endif
 
-                val = output.at(j) - data->at(i).second.at(j);
+                val = denormalized_output - data->at(i).second.at(j);
                 error += val * val;
 
-                output_norm += output.at(j) * output.at(j);
+                output_norm += denormalized_output * denormalized_output;
             }
 #ifdef L4N_DEBUG
             COUT_DEBUG(i << ": "
@@ -184,6 +195,7 @@ namespace lib4neuro {
         std::vector<std::pair<std::vector<double>, std::vector<double>>>* data = data_set->get_data();
 
         //TODO instead use something smarter
+        std::vector<std::vector<double>> outputs(data->size());
         std::vector<double> output(dim_out);
 
         COUT_DEBUG(
@@ -204,23 +216,32 @@ namespace lib4neuro {
                                    output,
                                    weights);
 
+            outputs.at(i) = output;
+        }
+
+        if(data_set->is_normalized()) {
+            data_set->de_normalize();
+        }
+
+        for(auto i = 0; i < data->size(); i++) {
             /* Compute difference for every element of the output vector */
+            double denormalized_output;
             for (size_t j = 0; j < dim_out; ++j) {
+                denormalized_output = data_set->get_normalization_strategy()->de_normalize(outputs.at(i).at(j));
                 COUT_DEBUG("Element " << i << ": "
                                       << data->at(i).first.at(j) << " "
                                       << data->at(i).second.at(j) << " "
-                                      << output.at(j) << std::endl);
+                                      << denormalized_output << std::endl);
 
                 ofs << data->at(i).first.at(j) << " "
                     << data->at(i).second.at(j) << " "
-                    << output.at(j) << std::endl;
+                    << denormalized_output << std::endl;
 
-                val = output.at(j) - data->at(i).second.at(j);
+                val = denormalized_output - data->at(i).second.at(j);
                 error += val * val;
             }
 
             ofs << std::endl;
-
         }
 
         ofs.close();
@@ -236,12 +257,14 @@ namespace lib4neuro {
         std::vector<std::pair<std::vector<double>, std::vector<double>>>* data = data_set->get_data();
 
         //TODO instead use something smarter
+        std::vector<std::vector<double>> outputs(data->size());
         std::vector<double> output(dim_out);
 
         COUT_DEBUG(
                 "Evaluation of the error function MSE on the given data-set (format 'input' 'real output' 'predicted output'):"
                         << std::endl);
 
+        /* Compute predicted outputs */
         for (auto i = 0; i < data->size(); i++) {  // Iterate through every element in the test set
 
             /* Compute the net output and store it into 'output' variable */
@@ -249,17 +272,31 @@ namespace lib4neuro {
                                    output,
                                    weights);
 
+            outputs.at(i) = output;
+        }
+
+        /* De-normalize data-set, if it's normalized */
+        if(data_set->is_normalized()) {
+            data_set->de_normalize();
+        }
+
+        /* Evaluate the prediction error on de-normalized data */
+        for(auto i = 0; i < data->size(); i++) {
+
             /* Compute difference for every element of the output vector */
-            for (size_t j = 0; j < dim_out; ++j) {
+            double denormalized_output;
+            for (auto j = 0; j < dim_out; ++j) {
+                denormalized_output = data_set->get_normalization_strategy()->de_normalize(outputs.at(i).at(j));
                 COUT_DEBUG("Element " << i << ": "
                                       << data->at(i).first.at(j) << " "
                                       << data->at(i).second.at(j) << " "
-                                      << output.at(j) << std::endl);
+                                      << denormalized_output << std::endl);
 
-                val = output.at(j) - data->at(i).second.at(j);
+                val = denormalized_output - data->at(i).second.at(j);
                 error += val * val;
             }
         }
+
         return error / n_elements;
     }
 
-- 
GitLab