Free cookie consent management tool by TermsFeed Policy Generator

source: branches/Classification-Extensions/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/QualityCalculator.cs @ 11622

Last change on this file since 11622 was 11622, checked in by ehopf, 8 years ago

#2278 implemented classification quality measures
-true positive rate
-true negative rate
-positive predictive value
-negative predictive value
-false positive rate
-false discovery rate

File size: 4.8 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2014 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 System.Text;
26using HeuristicLab.Common;
27
28namespace HeuristicLab.Problems.DataAnalysis {
29  public class QualityCalculator //: IOnlineCalculator
30  {
31
32    public QualityCalculator(double positiveClassValue) {
33      this.positiveClassValue = positiveClassValue;
34      Reset();
35    }
36
37    private double positiveClassValue;
38    private int truePositive, falsePositive, trueNegative, falseNegative;
39
40    public double TruePositiveRate {
41      get {
42        double divisor = truePositive + falseNegative;
43        return divisor.IsAlmost(0) ? double.NaN : truePositive / divisor;
44      }
45    }
46    public double TrueNegativeRate {
47      get {
48        double divisor = falsePositive + trueNegative;
49        return divisor.IsAlmost(0) ? double.NaN : trueNegative / divisor;
50      }
51    }
52    public double PositivePredictiveValue {
53      get {
54        double divisor = truePositive + falsePositive;
55        return divisor.IsAlmost(0) ? double.NaN : truePositive / divisor;
56      }
57    }
58    public double NegativePredictiveValue {
59      get {
60        double divisor = trueNegative + falseNegative;
61        return divisor.IsAlmost(0) ? double.NaN : trueNegative / divisor;
62      }
63    }
64    public double FalsePositiveRate {
65      get {
66        double divisor = falsePositive + trueNegative;
67        return divisor.IsAlmost(0) ? double.NaN : falsePositive / divisor;
68      }
69    }
70    public double FalseDiscoveryRate {
71      get {
72        double divisor = falsePositive + truePositive;
73        return divisor.IsAlmost(0) ? double.NaN : falsePositive / divisor;
74      }
75    }
76    //#region IOnlineCalculator Members
77    private OnlineCalculatorError errorState;
78    public OnlineCalculatorError ErrorState {
79      get { return errorState; }
80    }
81
82    /*
83    public double Value
84    {
85        get { return FalsePositiveRate; }
86    }*/
87
88    public void Reset() {
89      truePositive = 0;
90      falseNegative = 0;
91      trueNegative = 0;
92      falseNegative = 0;
93      errorState = OnlineCalculatorError.InsufficientElementsAdded;
94    }
95    public void Add(double original, double estimated) {
96      // ignore cases where original is NaN completely
97      if (!double.IsNaN(original)) {
98        if (original.IsAlmost(positiveClassValue) || estimated.IsAlmost(positiveClassValue)) //positive class/positive estimation
99                {
100          if (estimated.IsAlmost(original)) {
101            truePositive++;
102          } else {
103            if (estimated.IsAlmost(positiveClassValue))
104              falsePositive++;
105            else
106              falseNegative++;
107          }
108        } else { //negative class/negative estimation
109          trueNegative++;
110        }
111        errorState = OnlineCalculatorError.None; // number of (non-NaN) samples >= 1
112      }
113    }
114    //#endregion
115
116    public void Calculate(IEnumerable<double> originalValues, IEnumerable<double> estimatedValues, out OnlineCalculatorError errorState) {
117      IEnumerator<double> originalEnumerator = originalValues.GetEnumerator();
118      IEnumerator<double> estimatedEnumerator = estimatedValues.GetEnumerator();
119
120      // always move forward both enumerators (do not use short-circuit evaluation!)
121      while (originalEnumerator.MoveNext() & estimatedEnumerator.MoveNext()) {
122        double original = originalEnumerator.Current;
123        double estimated = estimatedEnumerator.Current;
124        Add(original, estimated);
125        if (ErrorState != OnlineCalculatorError.None) break;
126      }
127
128      // check if both enumerators are at the end to make sure both enumerations have the same length
129      if (ErrorState == OnlineCalculatorError.None &&
130          (estimatedEnumerator.MoveNext() || originalEnumerator.MoveNext())) {
131        throw new ArgumentException("Number of elements in originalValues and estimatedValues enumerations doesn't match.");
132      } else {
133        errorState = ErrorState;
134      }
135    }
136  }
137}
Note: See TracBrowser for help on using the repository browser.