source: trunk/sources/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis-3.4/StatisticCalculatorsTest.cs @ 6974

Last change on this file since 6974 was 6974, checked in by gkronber, 8 years ago

#1081: cleared up definition of accuracy metrics for time series prognosis to make the distinction between one n-step forecast and n one-step forecasts clearer. Implemented calculators for time series accuracy metrics to support the calculation of the average accuracy over m n-step forecasts and adapted the unit tests accordingly.

File size: 10.1 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2011 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.Linq;
25using HeuristicLab.Common;
26using HeuristicLab.Problems.DataAnalysis;
27using Microsoft.VisualStudio.TestTools.UnitTesting;
28namespace HeuristicLab.Problems.DataAnalysis_3_4.Tests {
29
30  [TestClass()]
31  public class StatisticCalculatorsTest {
32    private double[,] testData = new double[,] {
33     {5,1,1,1,2,1,3,1,1,2},
34     {5,4,4,5,7,10,3,2,1,2},
35     {3,1,1,1,2,2,3,1,1,2},
36     {6,8,8,1,3,4,3,7,1,2},
37     {4,1,1,3,2,1,3,1,1,2},
38     {8,10,10,8,7,10,9,7,1,4},           
39     {1,1,1,1,2,10,3,1,1,2},             
40     {2,1,2,1,2,1,3,1,1,2},                 
41     {2,1,1,1,2,1,1,1,5,2},                 
42     {4,2,1,1,2,1,2,1,1,2},                   
43     {1,1,1,1,1,1,3,1,1,2},   
44     {2,1,1,1,2,1,2,1,1,2},                   
45     {5,3,3,3,2,3,4,4,1,4},                         
46     {8,7,5,10,7,9,5,5,4,4},         
47     {7,4,6,4,6,1,4,3,1,4},                         
48     {4,1,1,1,2,1,2,1,1,2},     
49     {4,1,1,1,2,1,3,1,1,2},     
50     {10,7,7,6,4,10,4,1,2,4}, 
51     {6,1,1,1,2,1,3,1,1,2},     
52     {7,3,2,10,5,10,5,4,4,4},   
53     {10,5,5,3,6,7,7,10,1,4} 
54      };
55
56    [TestMethod]
57    public void CalculateMeanAndVarianceTest() {
58      System.Random random = new System.Random(31415);
59
60      int n = testData.GetLength(0);
61      int cols = testData.GetLength(1);
62      {
63        for (int col = 0; col < cols; col++) {
64          double scale = random.NextDouble();
65          IEnumerable<double> x = from rows in Enumerable.Range(0, n)
66                                  select testData[rows, col] * scale;
67          double[] xs = x.ToArray();
68          double mean_alglib, variance_alglib;
69          mean_alglib = variance_alglib = 0.0;
70          double tmp = 0;
71
72          alglib.samplemoments(xs, n, out  mean_alglib, out variance_alglib, out tmp, out tmp);
73
74          var calculator = new OnlineMeanAndVarianceCalculator();
75          for (int i = 0; i < n; i++) {
76            calculator.Add(xs[i]);
77          }
78          double mean = calculator.Mean;
79          double variance = calculator.Variance;
80
81          Assert.IsTrue(mean_alglib.IsAlmost(mean));
82          Assert.IsTrue(variance_alglib.IsAlmost(variance));
83        }
84      }
85    }
86
87    [TestMethod]
88    public void CalculatePearsonsRSquaredTest() {
89      System.Random random = new System.Random(31415);
90      int n = testData.GetLength(0);
91      int cols = testData.GetLength(1);
92      for (int c1 = 0; c1 < cols; c1++) {
93        for (int c2 = c1 + 1; c2 < cols; c2++) {
94          {
95            double c1Scale = random.NextDouble() * 1E7;
96            double c2Scale = random.NextDouble() * 1E7;
97            IEnumerable<double> x = from rows in Enumerable.Range(0, n)
98                                    select testData[rows, c1] * c1Scale;
99            IEnumerable<double> y = from rows in Enumerable.Range(0, n)
100                                    select testData[rows, c2] * c2Scale;
101            double[] xs = x.ToArray();
102            double[] ys = y.ToArray();
103            double r2_alglib = alglib.pearsoncorrelation(xs, ys, n);
104            r2_alglib *= r2_alglib;
105
106            var r2Calculator = new OnlinePearsonsRSquaredCalculator();
107            for (int i = 0; i < n; i++) {
108              r2Calculator.Add(xs[i], ys[i]);
109            }
110            double r2 = r2Calculator.RSquared;
111
112            Assert.IsTrue(r2_alglib.IsAlmost(r2));
113          }
114        }
115      }
116    }
117    [TestMethod]
118    public void CalculatePearsonsRSquaredOfConstantTest() {
119      System.Random random = new System.Random(31415);
120      int n = 12;
121      int cols = testData.GetLength(1);
122      for (int c1 = 0; c1 < cols; c1++) {
123        double c1Scale = random.NextDouble() * 1E7;
124        double c2Scale = 1.0;
125        IEnumerable<double> x = from rows in Enumerable.Range(0, n)
126                                select testData[rows, c1] * c1Scale;
127        IEnumerable<double> y = (new List<double>() { 150494407424305.47 })
128          .Concat(Enumerable.Repeat(150494407424305.47, n - 1));
129        double[] xs = x.ToArray();
130        double[] ys = y.ToArray();
131        double r2_alglib = alglib.pearsoncorrelation(xs, ys, n);
132        r2_alglib *= r2_alglib;
133
134        var r2Calculator = new OnlinePearsonsRSquaredCalculator();
135        for (int i = 0; i < n; i++) {
136          r2Calculator.Add(xs[i], ys[i]);
137        }
138        double r2 = r2Calculator.RSquared;
139
140        Assert.AreEqual(r2_alglib.ToString(), r2.ToString());
141      }
142    }
143
144    [TestMethod]
145    public void CalculateDirectionalSymmetryTest() {
146      // delta: +0.01, +1, -0.01, -2, -0.01, -1, +0.01, +2
147      var original = new double[]
148                       {
149                         0, 
150                         0.01, 
151                         1.01, 
152                         1, 
153                         -1, 
154                         -1.01, 
155                         -2.01, 
156                         -2, 
157                         0
158                       };
159      // delta to original(t-1): +1, +0, -1, -0, -1, +0.01, +0.01, +2
160      var estimated = new double[]
161                        {
162                          -1, 
163                          1, 
164                          0.01,
165                          0.01,
166                          1,
167                          -1,
168                          -1.02,
169                          -2.02,
170                          0
171                        };
172
173      // one-step forecast
174      var startValues = original;
175      var actualContinuations = from x in original.Skip(1)
176                                select Enumerable.Repeat(x, 1);
177      var predictedContinuations = from x in estimated.Skip(1)
178                                   select Enumerable.Repeat(x, 1);
179      double expected = 0.5;  // half of the predicted deltas are correct
180      OnlineCalculatorError errorState;
181      double actual = OnlineDirectionalSymmetryCalculator.Calculate(startValues, actualContinuations, predictedContinuations, out errorState);
182      Assert.AreEqual(expected, actual, 1E-9);
183    }
184    [TestMethod]
185    public void CalculateWeightedDirectionalSymmetryTest() {
186      var original = new double[] { 0, 0.01, 1.01, 1, -1, -1.01, -2.01, -2, 0 }; // +0.01, +1, -0.01, -2, -0.01, -1, +0.01, +2
187      var estimated = new double[] { 1, 2, 2, 1, 1, 0, 0.01, 0.02, 2.02 }; // delta to original: +2, +1.99, -0.01, 0, +1, -1.02, +2.01, +4.02
188      // one-step forecast
189      var startValues = original;
190      var actualContinuations = from x in original.Skip(1)
191                                select Enumerable.Repeat(x, 1);
192      var predictedContinuations = from x in estimated.Skip(1)
193                                   select Enumerable.Repeat(x, 1);
194      // absolute errors = 1.99, 0.99, 0, 2, 1.01, 2.02, 2.02, 2.02     
195      // sum of absolute errors for correctly predicted deltas = 2.97
196      // sum of absolute errors for incorrectly predicted deltas = 3.03
197      double expected = 5.03 / 7.02;
198      OnlineCalculatorError errorState;
199      double actual = OnlineWeightedDirectionalSymmetryCalculator.Calculate(startValues, actualContinuations, predictedContinuations, out errorState);
200      Assert.AreEqual(expected, actual, 1E-9);
201    }
202    [TestMethod]
203    public void CalculateTheilsUTest() {
204      var original = new double[] { 0, 0.01, 1.01, 1, -1, -1.01, -2.01, -2, 0 };
205      var estimated = new double[] { 1, 1.01, 0.01, 2, 0, -0.01, -1.01, -3, 1 };
206      // one-step forecast
207      var startValues = original;
208      var actualContinuations = from x in original.Skip(1)
209                                select Enumerable.Repeat(x, 1);
210      var predictedContinuations = from x in estimated.Skip(1)
211                                   select Enumerable.Repeat(x, 1);
212      // Sum of squared errors of model y(t+1) = y(t) = 10.0004
213      // Sum of squared errors of predicted values = 8 
214      double expected = Math.Sqrt(8 / 10.0004);
215      OnlineCalculatorError errorState;
216      double actual = OnlineTheilsUStatisticCalculator.Calculate(startValues, actualContinuations, predictedContinuations, out errorState);
217      Assert.AreEqual(expected, actual, 1E-9);
218    }
219    [TestMethod]
220    public void CalculateAccuracyTest() {
221      var original = new double[] { 1, 1, 0, 0 };
222      var estimated = new double[] { 1, 0, 1, 0 };
223      double expected = 0.5;
224      OnlineCalculatorError errorState;
225      double actual = OnlineAccuracyCalculator.Calculate(original, estimated, out errorState);
226      Assert.AreEqual(expected, actual, 1E-9);
227    }
228
229    [TestMethod]
230    public void CalculateMeanAbsolutePercentageErrorTest() {
231      var original = new double[] { 1, 2, 3, 1, 5 };
232      var estimated = new double[] { 2, 1, 3, 1, 0 };
233      double expected = 0.5;
234      OnlineCalculatorError errorState;
235      double actual = OnlineMeanAbsolutePercentageErrorCalculator.Calculate(original, estimated, out errorState);
236      Assert.AreEqual(expected, actual, 1E-9);
237      Assert.AreEqual(OnlineCalculatorError.None, errorState);
238
239      // if the original contains zero values the result is not defined
240      var original2 = new double[] { 1, 2, 0, 0, 0 };
241      OnlineMeanAbsolutePercentageErrorCalculator.Calculate(original2, estimated, out errorState);
242      Assert.AreEqual(OnlineCalculatorError.InvalidValueAdded, errorState);
243    }
244  }
245}
Note: See TracBrowser for help on using the repository browser.