Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.TimeSeries/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/TimeSeriesPrognosis/TimeSeriesPrognosisSolutionBase.cs @ 7989

Last change on this file since 7989 was 7989, checked in by mkommend, 12 years ago

#1081: Improved performance of time series prognosis.

File size: 22.8 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.Data;
27using HeuristicLab.Optimization;
28using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
29
30namespace HeuristicLab.Problems.DataAnalysis {
31  [StorableClass]
32  public abstract class TimeSeriesPrognosisSolutionBase : DataAnalysisSolution, ITimeSeriesPrognosisSolution {
33    private const string TrainingMeanSquaredErrorResultName = "Mean squared error (training)";
34    private const string TestMeanSquaredErrorResultName = "Mean squared error (test)";
35    private const string TrainingMeanAbsoluteErrorResultName = "Mean absolute error (training)";
36    private const string TestMeanAbsoluteErrorResultName = "Mean absolute error (test)";
37    private const string TrainingSquaredCorrelationResultName = "Pearson's R² (training)";
38    private const string TestSquaredCorrelationResultName = "Pearson's R² (test)";
39    private const string TrainingRelativeErrorResultName = "Average relative error (training)";
40    private const string TestRelativeErrorResultName = "Average relative error (test)";
41    private const string TrainingNormalizedMeanSquaredErrorResultName = "Normalized mean squared error (training)";
42    private const string TestNormalizedMeanSquaredErrorResultName = "Normalized mean squared error (test)";
43    private const string TrainingDirectionalSymmetryResultName = "Average directional symmetry (training)";
44    private const string TestDirectionalSymmetryResultName = "Average directional symmetry (test)";
45    private const string TrainingWeightedDirectionalSymmetryResultName = "Average weighted directional symmetry (training)";
46    private const string TestWeightedDirectionalSymmetryResultName = "Average weighted directional symmetry (test)";
47    private const string TrainingTheilsUStatisticLastResultName = "Average Theil's U (last) (training)";
48    private const string TestTheilsUStatisticLastResultName = "Average Theil's U (last) (test)";
49    private const string TrainingTheilsUStatisticMeanResultName = "Average Theil's U (mean) (training)";
50    private const string TestTheilsUStatisticMeanResultName = "Average Theil's U (mean) (test)";
51    private const string TrainingTheilsUStatisticMaResultName = "Average Theil's U (moving average) (training)";
52    private const string TestTheilsUStatisticMaResultName = "Average Theil's U (moving average) (test)";
53
54    public new ITimeSeriesPrognosisModel Model {
55      get { return (ITimeSeriesPrognosisModel)base.Model; }
56      protected set { base.Model = value; }
57    }
58
59    public new ITimeSeriesPrognosisProblemData ProblemData {
60      get { return (ITimeSeriesPrognosisProblemData)base.ProblemData; }
61      set { base.ProblemData = value; }
62    }
63
64    [Storable]
65    private int horizon;
66    public int Horizon {
67      get { return horizon; }
68      set {
69        if (horizon != value) {
70          horizon = value;
71          RecalculateResults();
72        }
73      }
74    }
75
76    public abstract IEnumerable<IEnumerable<double>> GetPrognosedValues(IEnumerable<int> rows, int horizon);
77
78    #region Results
79    public double TrainingMeanSquaredError {
80      get { return ((DoubleValue)this[TrainingMeanSquaredErrorResultName].Value).Value; }
81      private set { ((DoubleValue)this[TrainingMeanSquaredErrorResultName].Value).Value = value; }
82    }
83    public double TestMeanSquaredError {
84      get { return ((DoubleValue)this[TestMeanSquaredErrorResultName].Value).Value; }
85      private set { ((DoubleValue)this[TestMeanSquaredErrorResultName].Value).Value = value; }
86    }
87    public double TrainingMeanAbsoluteError {
88      get { return ((DoubleValue)this[TrainingMeanAbsoluteErrorResultName].Value).Value; }
89      private set { ((DoubleValue)this[TrainingMeanAbsoluteErrorResultName].Value).Value = value; }
90    }
91    public double TestMeanAbsoluteError {
92      get { return ((DoubleValue)this[TestMeanAbsoluteErrorResultName].Value).Value; }
93      private set { ((DoubleValue)this[TestMeanAbsoluteErrorResultName].Value).Value = value; }
94    }
95    public double TrainingRSquared {
96      get { return ((DoubleValue)this[TrainingSquaredCorrelationResultName].Value).Value; }
97      private set { ((DoubleValue)this[TrainingSquaredCorrelationResultName].Value).Value = value; }
98    }
99    public double TestRSquared {
100      get { return ((DoubleValue)this[TestSquaredCorrelationResultName].Value).Value; }
101      private set { ((DoubleValue)this[TestSquaredCorrelationResultName].Value).Value = value; }
102    }
103    public double TrainingRelativeError {
104      get { return ((DoubleValue)this[TrainingRelativeErrorResultName].Value).Value; }
105      private set { ((DoubleValue)this[TrainingRelativeErrorResultName].Value).Value = value; }
106    }
107    public double TestRelativeError {
108      get { return ((DoubleValue)this[TestRelativeErrorResultName].Value).Value; }
109      private set { ((DoubleValue)this[TestRelativeErrorResultName].Value).Value = value; }
110    }
111    public double TrainingNormalizedMeanSquaredError {
112      get { return ((DoubleValue)this[TrainingNormalizedMeanSquaredErrorResultName].Value).Value; }
113      private set { ((DoubleValue)this[TrainingNormalizedMeanSquaredErrorResultName].Value).Value = value; }
114    }
115    public double TestNormalizedMeanSquaredError {
116      get { return ((DoubleValue)this[TestNormalizedMeanSquaredErrorResultName].Value).Value; }
117      private set { ((DoubleValue)this[TestNormalizedMeanSquaredErrorResultName].Value).Value = value; }
118    }
119    public double TrainingDirectionalSymmetry {
120      get { return ((DoubleValue)this[TrainingDirectionalSymmetryResultName].Value).Value; }
121      private set { ((DoubleValue)this[TrainingDirectionalSymmetryResultName].Value).Value = value; }
122    }
123    public double TestDirectionalSymmetry {
124      get { return ((DoubleValue)this[TestDirectionalSymmetryResultName].Value).Value; }
125      private set { ((DoubleValue)this[TestDirectionalSymmetryResultName].Value).Value = value; }
126    }
127    public double TrainingWeightedDirectionalSymmetry {
128      get { return ((DoubleValue)this[TrainingWeightedDirectionalSymmetryResultName].Value).Value; }
129      private set { ((DoubleValue)this[TrainingWeightedDirectionalSymmetryResultName].Value).Value = value; }
130    }
131    public double TestWeightedDirectionalSymmetry {
132      get { return ((DoubleValue)this[TestWeightedDirectionalSymmetryResultName].Value).Value; }
133      private set { ((DoubleValue)this[TestWeightedDirectionalSymmetryResultName].Value).Value = value; }
134    }
135    public double TrainingTheilsUStatisticLast {
136      get { return ((DoubleValue)this[TrainingTheilsUStatisticLastResultName].Value).Value; }
137      private set { ((DoubleValue)this[TrainingTheilsUStatisticLastResultName].Value).Value = value; }
138    }
139    public double TestTheilsUStatisticLast {
140      get { return ((DoubleValue)this[TestTheilsUStatisticLastResultName].Value).Value; }
141      private set { ((DoubleValue)this[TestTheilsUStatisticLastResultName].Value).Value = value; }
142    }
143    public double TrainingTheilsUStatisticMean {
144      get { return ((DoubleValue)this[TrainingTheilsUStatisticMeanResultName].Value).Value; }
145      private set { ((DoubleValue)this[TrainingTheilsUStatisticMeanResultName].Value).Value = value; }
146    }
147    public double TestTheilsUStatisticMean {
148      get { return ((DoubleValue)this[TestTheilsUStatisticMeanResultName].Value).Value; }
149      private set { ((DoubleValue)this[TestTheilsUStatisticMeanResultName].Value).Value = value; }
150    }
151    public double TrainingTheilsUStatisticMovingAverage {
152      get { return ((DoubleValue)this[TrainingTheilsUStatisticMaResultName].Value).Value; }
153      private set { ((DoubleValue)this[TrainingTheilsUStatisticMaResultName].Value).Value = value; }
154    }
155    public double TestTheilsUStatisticMovingAverage {
156      get { return ((DoubleValue)this[TestTheilsUStatisticMaResultName].Value).Value; }
157      private set { ((DoubleValue)this[TestTheilsUStatisticMaResultName].Value).Value = value; }
158    }
159    #endregion
160
161    [StorableConstructor]
162    protected TimeSeriesPrognosisSolutionBase(bool deserializing) : base(deserializing) { }
163    protected TimeSeriesPrognosisSolutionBase(TimeSeriesPrognosisSolutionBase original, Cloner cloner)
164      : base(original, cloner) {
165      this.horizon = original.horizon;
166    }
167    protected TimeSeriesPrognosisSolutionBase(ITimeSeriesPrognosisModel model, ITimeSeriesPrognosisProblemData problemData)
168      : base(model, problemData) {
169      Add(new Result(TrainingMeanSquaredErrorResultName, "Mean of squared errors of the model on the training partition", new DoubleValue()));
170      Add(new Result(TestMeanSquaredErrorResultName, "Mean of squared errors of the model on the test partition", new DoubleValue()));
171      Add(new Result(TrainingMeanAbsoluteErrorResultName, "Mean of absolute errors of the model on the training partition", new DoubleValue()));
172      Add(new Result(TestMeanAbsoluteErrorResultName, "Mean of absolute errors of the model on the test partition", new DoubleValue()));
173      Add(new Result(TrainingSquaredCorrelationResultName, "Squared Pearson's correlation coefficient of the model output and the actual values on the training partition", new DoubleValue()));
174      Add(new Result(TestSquaredCorrelationResultName, "Squared Pearson's correlation coefficient of the model output and the actual values on the test partition", new DoubleValue()));
175      Add(new Result(TrainingRelativeErrorResultName, "Average of the relative errors of the model output and the actual values on the training partition", new DoubleValue()));
176      Add(new Result(TestRelativeErrorResultName, "Average of the relative errors of the model output and the actual values on the test partition", new DoubleValue()));
177      Add(new Result(TrainingNormalizedMeanSquaredErrorResultName, "Normalized mean of squared errors of the model on the training partition", new DoubleValue()));
178      Add(new Result(TestNormalizedMeanSquaredErrorResultName, "Normalized mean of squared errors of the model on the test partition", new DoubleValue()));
179      Add(new Result(TrainingDirectionalSymmetryResultName, "The average directional symmetry of the forecasts of the model on the training partition", new DoubleValue()));
180      Add(new Result(TestDirectionalSymmetryResultName, "The average directional symmetry of the forecasts of the model on the test partition", new DoubleValue()));
181      Add(new Result(TrainingWeightedDirectionalSymmetryResultName, "The average weighted directional symmetry of the forecasts of the model on the training partition", new DoubleValue()));
182      Add(new Result(TestWeightedDirectionalSymmetryResultName, "The average weighted directional symmetry of the forecasts of the model on the test partition", new DoubleValue()));
183      Add(new Result(TrainingTheilsUStatisticLastResultName, "The average Theil's U statistic (reference: previous value) of the forecasts of the model on the training partition", new DoubleValue()));
184      Add(new Result(TestTheilsUStatisticLastResultName, "The average Theil's U statistic (reference: previous value) of the forecasts of the model on the test partition", new DoubleValue()));
185      Add(new Result(TrainingTheilsUStatisticMeanResultName, "The average Theil's U statistic (reference: mean value) of the forecasts of the model on the training partition", new DoubleValue()));
186      Add(new Result(TestTheilsUStatisticMeanResultName, "The average Theil's U statistic (reference: mean value) of the forecasts of the model on the test partition", new DoubleValue()));
187      Add(new Result(TrainingTheilsUStatisticMaResultName, "The average Theil's U statistic (reference: moving average) of the forecasts of the model on the training partition", new DoubleValue()));
188      Add(new Result(TestTheilsUStatisticMaResultName, "The average Theil's U statistic (reference: moving average) of the forecasts of the model on the test partition", new DoubleValue()));
189      horizon = 1;
190    }
191
192
193    protected void CalculateResults() {
194      string targetVariable = ProblemData.TargetVariable;
195
196      var trainingMseCalculators = new OnlineMeanSquaredErrorCalculator();
197      var testMseCalculators = new OnlineMeanSquaredErrorCalculator();
198      var trainingMaeCalculators = new OnlineMeanAbsoluteErrorCalculator();
199      var testMaeCalculators = new OnlineMeanAbsoluteErrorCalculator();
200      var trainingRSquaredCalculators = new OnlinePearsonsRSquaredCalculator();
201      var testRSquaredCalculators = new OnlinePearsonsRSquaredCalculator();
202      var trainingRelErrorCalculators = new OnlineMeanAbsolutePercentageErrorCalculator();
203      var testRelErrorCalculators = new OnlineMeanAbsolutePercentageErrorCalculator();
204      var trainingNmseCalculators = new OnlineNormalizedMeanSquaredErrorCalculator();
205      var testNmseCalculators = new OnlineNormalizedMeanSquaredErrorCalculator();
206
207      var trainingDsCalculators = new OnlineDirectionalSymmetryCalculator();
208      var testDsCalculators = new OnlineDirectionalSymmetryCalculator();
209      var trainingWdsCalculators = new OnlineWeightedDirectionalSymmetryCalculator();
210      var testWdsCalculators = new OnlineWeightedDirectionalSymmetryCalculator();
211      var trainingTheilsULastCalculators = new OnlineTheilsUStatisticCalculator();
212      var testTheilsULastCalculators = new OnlineTheilsUStatisticCalculator();
213      var trainingTheilsUMeanCalculators = new OnlineTheilsUStatisticCalculator();
214      var testTheilsUMeanCalculators = new OnlineTheilsUStatisticCalculator();
215      var trainingTheilsUMovingAverageCalculators = new OnlineTheilsUStatisticCalculator();
216      var testTheilsUMovingAverageCalculators = new OnlineTheilsUStatisticCalculator();
217
218      double mean = ProblemData.Dataset.GetDoubleValues(targetVariable, ProblemData.TrainingIndizes).Average();
219
220      foreach (var row in ProblemData.TrainingIndizes) {
221        if (row + horizon < ProblemData.Dataset.Rows) {
222          var actualContinuation = ProblemData.Dataset.GetDoubleValues(targetVariable, Enumerable.Range(row, horizon)).ToList();
223          var prognosedContinuation = GetPrognosedValues(new List<int> { row }, horizon).First().ToList();
224
225          int maWindow = 10 * horizon;
226          var movingAverageContinuation = from h in Enumerable.Range(0, horizon)
227                                          select (from r in Enumerable.Range(row + h - maWindow, maWindow - h)
228                                                  where r > 0
229                                                  select ProblemData.Dataset.GetDoubleValue(targetVariable, r)
230                                                 ).Average();
231
232          double startValue = ProblemData.Dataset.GetDoubleValue(targetVariable, row - 1);
233
234          trainingDsCalculators.Add(startValue, actualContinuation, prognosedContinuation);
235          trainingWdsCalculators.Add(startValue, actualContinuation, prognosedContinuation);
236          trainingTheilsULastCalculators.Add(startValue, actualContinuation, prognosedContinuation);
237          trainingTheilsUMeanCalculators.Add(startValue, actualContinuation.Select(x => mean), actualContinuation, prognosedContinuation);
238          trainingTheilsUMovingAverageCalculators.Add(startValue, movingAverageContinuation, actualContinuation, prognosedContinuation);
239
240          var actualContinuationEnumerator = actualContinuation.GetEnumerator();
241          var prognosedContinuationEnumerator = prognosedContinuation.GetEnumerator();
242
243          while (actualContinuationEnumerator.MoveNext() & prognosedContinuationEnumerator.MoveNext()) {
244            trainingMseCalculators.Add(actualContinuationEnumerator.Current, prognosedContinuationEnumerator.Current);
245            trainingMaeCalculators.Add(actualContinuationEnumerator.Current, prognosedContinuationEnumerator.Current);
246            trainingRelErrorCalculators.Add(actualContinuationEnumerator.Current, prognosedContinuationEnumerator.Current);
247            trainingRSquaredCalculators.Add(actualContinuationEnumerator.Current, prognosedContinuationEnumerator.Current);
248            trainingNmseCalculators.Add(actualContinuationEnumerator.Current, prognosedContinuationEnumerator.Current);
249          }
250          if (actualContinuationEnumerator.MoveNext() | prognosedContinuationEnumerator.MoveNext())
251            throw new ArgumentException("Different number of elements in Actual continuation and prognosed continuation.");
252        }
253      }
254
255      mean = ProblemData.Dataset.GetDoubleValues(targetVariable, ProblemData.TestIndizes).Average();
256      foreach (var row in ProblemData.TestIndizes) {
257        if (row + horizon < ProblemData.Dataset.Rows) {
258          var actualContinuation = ProblemData.Dataset.GetDoubleValues(targetVariable, Enumerable.Range(row, horizon)).ToList();
259          var prognosedContinuation = GetPrognosedValues(new List<int> { row }, horizon).First().ToList();
260
261          int maWindow = 10 * horizon;
262          var movingAverageContinuation = from h in Enumerable.Range(0, horizon)
263                                          select (from r in Enumerable.Range(row + h - maWindow, maWindow - h)
264                                                  where r > 0
265                                                  select ProblemData.Dataset.GetDoubleValue(targetVariable, r)
266                                                 ).Average();
267
268          double startValue = ProblemData.Dataset.GetDoubleValue(targetVariable, row - 1);
269          testDsCalculators.Add(startValue, actualContinuation, prognosedContinuation);
270          testWdsCalculators.Add(startValue, actualContinuation, prognosedContinuation);
271          testTheilsULastCalculators.Add(startValue, actualContinuation, prognosedContinuation);
272          testTheilsUMeanCalculators.Add(startValue, actualContinuation.Select(x => mean), actualContinuation, prognosedContinuation);
273          testTheilsUMovingAverageCalculators.Add(startValue, movingAverageContinuation, actualContinuation, prognosedContinuation);
274
275          var actualContinuationEnumerator = actualContinuation.GetEnumerator();
276          var prognosedContinuationEnumerator = prognosedContinuation.GetEnumerator();
277          while (actualContinuationEnumerator.MoveNext() & prognosedContinuationEnumerator.MoveNext()) {
278            testMseCalculators.Add(actualContinuationEnumerator.Current, prognosedContinuationEnumerator.Current);
279            testMaeCalculators.Add(actualContinuationEnumerator.Current, prognosedContinuationEnumerator.Current);
280            testRelErrorCalculators.Add(actualContinuationEnumerator.Current, prognosedContinuationEnumerator.Current);
281            testRSquaredCalculators.Add(actualContinuationEnumerator.Current, prognosedContinuationEnumerator.Current);
282            testNmseCalculators.Add(actualContinuationEnumerator.Current, prognosedContinuationEnumerator.Current);
283          }
284          if (actualContinuationEnumerator.MoveNext() | prognosedContinuationEnumerator.MoveNext())
285            throw new ArgumentException("Different number of elements in Actual continuation and prognosed continuation.");
286        }
287      }
288
289      TrainingMeanSquaredError = trainingMseCalculators.ErrorState == OnlineCalculatorError.None ? trainingMseCalculators.Value : double.PositiveInfinity;
290      TestMeanSquaredError = testMseCalculators.ErrorState == OnlineCalculatorError.None ? testMseCalculators.Value : double.PositiveInfinity;
291      TrainingMeanAbsoluteError = trainingMaeCalculators.ErrorState == OnlineCalculatorError.None ? trainingMaeCalculators.Value : double.PositiveInfinity;
292      TestMeanAbsoluteError = testMaeCalculators.ErrorState == OnlineCalculatorError.None ? testMaeCalculators.Value : double.PositiveInfinity;
293      TrainingRelativeError = trainingRelErrorCalculators.ErrorState == OnlineCalculatorError.None ? trainingRelErrorCalculators.Value : double.PositiveInfinity;
294      TestRelativeError = testRelErrorCalculators.ErrorState == OnlineCalculatorError.None ? testRelErrorCalculators.Value : double.PositiveInfinity;
295      TrainingRSquared = trainingRSquaredCalculators.ErrorState == OnlineCalculatorError.None ? trainingRSquaredCalculators.Value : 0.0;
296      TestRSquared = testRSquaredCalculators.ErrorState == OnlineCalculatorError.None ? testRSquaredCalculators.Value : 0.0;
297      TrainingNormalizedMeanSquaredError = trainingNmseCalculators.ErrorState == OnlineCalculatorError.None ? trainingNmseCalculators.Value : double.PositiveInfinity;
298      TestNormalizedMeanSquaredError = testNmseCalculators.ErrorState == OnlineCalculatorError.None ? testNmseCalculators.Value : double.PositiveInfinity;
299
300      TrainingDirectionalSymmetry = trainingDsCalculators.ErrorState == OnlineCalculatorError.None ? trainingDsCalculators.Value : 0.0;
301      TestDirectionalSymmetry = testDsCalculators.ErrorState == OnlineCalculatorError.None ? testDsCalculators.Value : 0.0;
302      TrainingWeightedDirectionalSymmetry = trainingWdsCalculators.ErrorState == OnlineCalculatorError.None ? trainingWdsCalculators.Value : double.PositiveInfinity;
303      TestWeightedDirectionalSymmetry = testWdsCalculators.ErrorState == OnlineCalculatorError.None ? testWdsCalculators.Value : double.PositiveInfinity;
304      TrainingTheilsUStatisticLast = trainingTheilsULastCalculators.ErrorState == OnlineCalculatorError.None ? trainingTheilsULastCalculators.Value : double.PositiveInfinity;
305      TestTheilsUStatisticLast = testTheilsULastCalculators.ErrorState == OnlineCalculatorError.None ? testTheilsULastCalculators.Value : double.PositiveInfinity;
306      TrainingTheilsUStatisticMean = trainingTheilsUMeanCalculators.ErrorState == OnlineCalculatorError.None ? trainingTheilsUMeanCalculators.Value : double.PositiveInfinity;
307      TestTheilsUStatisticMean = testTheilsUMeanCalculators.ErrorState == OnlineCalculatorError.None ? testTheilsUMeanCalculators.Value : double.PositiveInfinity;
308      TrainingTheilsUStatisticMovingAverage = trainingTheilsUMovingAverageCalculators.ErrorState == OnlineCalculatorError.None ? trainingTheilsUMovingAverageCalculators.Value : double.PositiveInfinity;
309      TestTheilsUStatisticMovingAverage = testTheilsUMovingAverageCalculators.ErrorState == OnlineCalculatorError.None ? testTheilsUMovingAverageCalculators.Value : double.PositiveInfinity;
310    }
311  }
312}
Note: See TracBrowser for help on using the repository browser.