Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
11/09/11 10:59:31 (12 years ago)
Author:
gkronber
Message:

#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:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/OnlineWeightedDirectionalSymmetryCalculator.cs

    r6964 r6974  
    2222using System;
    2323using System.Collections.Generic;
     24using HeuristicLab.Common;
    2425
    2526
    2627namespace HeuristicLab.Problems.DataAnalysis {
    27   public class OnlineWeightedDirectionalSymmetryCalculator : IOnlineCalculator {
     28  public class OnlineWeightedDirectionalSymmetryCalculator : IOnlineTimeSeriesCalculator {
    2829    private double prevEstimated;
    2930    private double prevOriginal;
     
    5253    }
    5354
    54     public void Add(double original, double estimated) {
    55       if (double.IsNaN(estimated) || double.IsInfinity(estimated) || double.IsNaN(original) || double.IsInfinity(original) || (errorState & OnlineCalculatorError.InvalidValueAdded) > 0) {
     55    public void Add(double startValue, IEnumerable<double> actualContinuation, IEnumerable<double> predictedContinuation) {
     56      if (double.IsNaN(startValue) || (errorState & OnlineCalculatorError.InvalidValueAdded) > 0) {
    5657        errorState = errorState | OnlineCalculatorError.InvalidValueAdded;
    57       } else if (n == 0) {
    58         prevOriginal = original;
    59         prevEstimated = estimated;
    60         n++;
    6158      } else {
    62         double err = Math.Abs(original - estimated);
    63         if ((original - prevOriginal) * (estimated - prevEstimated) >= 0.0) {
    64           correctSum += err;
     59        var actualEnumerator = actualContinuation.GetEnumerator();
     60        var predictedEnumerator = predictedContinuation.GetEnumerator();
     61        while (actualEnumerator.MoveNext() & predictedEnumerator.MoveNext() & errorState != OnlineCalculatorError.InvalidValueAdded) {
     62          double actual = actualEnumerator.Current;
     63          double predicted = predictedEnumerator.Current;
     64          if (double.IsNaN(actual) || double.IsNaN(predicted)) {
     65            errorState = errorState | OnlineCalculatorError.InvalidValueAdded;
     66          } else {
     67            double err = Math.Abs(actual - predicted);
     68            // count as correct only if the trend (positive/negative/no change) is predicted correctly
     69            if ((actual - startValue) * (predicted - startValue) > 0.0 ||
     70              (actual - startValue).IsAlmost(predicted - startValue)) {
     71              correctSum += err;
     72            } else {
     73              incorrectSum += err;
     74            }
     75            n++;
     76          }
     77        }
     78        // check if both enumerators are at the end to make sure both enumerations have the same length
     79        if (actualEnumerator.MoveNext() || predictedEnumerator.MoveNext()) {
     80          errorState = errorState | OnlineCalculatorError.InvalidValueAdded;
    6581        } else {
    66           incorrectSum += err;
     82          errorState = errorState & (~OnlineCalculatorError.InsufficientElementsAdded); // n >= 1
    6783        }
    68         n++;
    69         errorState = errorState & (~OnlineCalculatorError.InsufficientElementsAdded);        // n >= 1
    70         prevOriginal = original;
    71         prevEstimated = estimated;
    7284      }
    7385    }
     
    8395
    8496
    85     public static double Calculate(IEnumerable<double> originalValues, IEnumerable<double> estimatedValues, out OnlineCalculatorError errorState) {
    86       IEnumerator<double> originalEnumerator = originalValues.GetEnumerator();
    87       IEnumerator<double> estimatedEnumerator = estimatedValues.GetEnumerator();
    88       OnlineWeightedDirectionalSymmetryCalculator dsCalculator = new OnlineWeightedDirectionalSymmetryCalculator();
     97    public static double Calculate(IEnumerable<double> startValues, IEnumerable<IEnumerable<double>> actualContinuations, IEnumerable<IEnumerable<double>> predictedContinuations, out OnlineCalculatorError errorState) {
     98      IEnumerator<double> startValueEnumerator = startValues.GetEnumerator();
     99      IEnumerator<IEnumerable<double>> actualContinuationsEnumerator = actualContinuations.GetEnumerator();
     100      IEnumerator<IEnumerable<double>> predictedContinuationsEnumerator = predictedContinuations.GetEnumerator();
     101      OnlineWeightedDirectionalSymmetryCalculator calculator = new OnlineWeightedDirectionalSymmetryCalculator();
    89102
    90       // add first element of time series as a reference point
    91       originalEnumerator.MoveNext();
    92       estimatedEnumerator.MoveNext();
    93       dsCalculator.Add(originalEnumerator.Current, estimatedEnumerator.Current);
    94 
    95       // always move forward both enumerators (do not use short-circuit evaluation!)
    96       while (originalEnumerator.MoveNext() & estimatedEnumerator.MoveNext()) {
    97         double original = originalEnumerator.Current;
    98         double estimated = estimatedEnumerator.Current;
    99         dsCalculator.Add(original, estimated);
    100         if (dsCalculator.ErrorState != OnlineCalculatorError.None) break;
     103      // always move forward all enumerators (do not use short-circuit evaluation!)
     104      while (startValueEnumerator.MoveNext() & actualContinuationsEnumerator.MoveNext() & predictedContinuationsEnumerator.MoveNext()) {
     105        calculator.Add(startValueEnumerator.Current, actualContinuationsEnumerator.Current, predictedContinuationsEnumerator.Current);
     106        if (calculator.ErrorState != OnlineCalculatorError.None) break;
    101107      }
    102108
    103       // check if both enumerators are at the end to make sure both enumerations have the same length
    104       if (dsCalculator.ErrorState == OnlineCalculatorError.None &&
    105           (originalEnumerator.MoveNext() || estimatedEnumerator.MoveNext())) {
    106         throw new ArgumentException("Number of elements in originalValues and estimatedValues enumerations doesn't match.");
     109      // check if all enumerators are at the end to make sure both enumerations have the same length
     110      if (calculator.ErrorState == OnlineCalculatorError.None &&
     111          (startValueEnumerator.MoveNext() || actualContinuationsEnumerator.MoveNext() || predictedContinuationsEnumerator.MoveNext())) {
     112        throw new ArgumentException("Number of elements in startValues, actualContinuations and estimatedValues predictedContinuations doesn't match.");
    107113      } else {
    108         errorState = dsCalculator.ErrorState;
    109         return dsCalculator.WeightedDirectionalSymmetry;
     114        errorState = calculator.ErrorState;
     115        return calculator.WeightedDirectionalSymmetry;
    110116      }
    111117    }
Note: See TracChangeset for help on using the changeset viewer.