Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/FeatureCorrelation/FeatureCorrelationCalculator.cs @ 8578

Last change on this file since 8578 was 8578, checked in by sforsten, 10 years ago

#1292:

  • added ProblemDataView which has a button to open the feature correlation
  • added abstract base class for feature correlations
  • added caches for the feature correlation
  • created own class for calculation of feature correlation
  • changed SelectedItemChanged to SelectionChangeCommitted events, so the correlation is only calculated if the user changes the selection
File size: 11.5 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2012 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.ComponentModel;
25using System.Linq;
26using HeuristicLab.PluginInfrastructure;
27using FCE = HeuristicLab.Problems.DataAnalysis.FeatureCorrelationEnums;
28
29namespace HeuristicLab.Problems.DataAnalysis {
30  public class FeatureCorrelationCalculator : Object {
31
32    private BackgroundWorker bw;
33    private BackgroundWorkerInfo bwInfo;
34
35    private IDataAnalysisProblemData problemData;
36    public IDataAnalysisProblemData ProblemData {
37      set {
38        if (bw != null) {
39          bw.CancelAsync();
40        }
41        problemData = value;
42      }
43    }
44
45    public FeatureCorrelationCalculator()
46      : base() { }
47
48    public FeatureCorrelationCalculator(IDataAnalysisProblemData problemData)
49      : base() {
50      this.problemData = problemData;
51    }
52
53    public void CalculateElements(FCE.CorrelationCalculators calc, FCE.Partitions partition) {
54      CalculateElements(problemData.Dataset, calc, partition);
55    }
56
57    // returns if any calculation takes place
58    public bool CalculateTimeframeElements(FCE.CorrelationCalculators calc, FCE.Partitions partition, string variable, int frames, double[,] correlation = null) {
59      if (correlation == null || correlation.GetLength(1) <= frames) {
60        CalculateElements(problemData.Dataset, calc, partition, variable, frames, correlation);
61        return true;
62      } else {
63        return false;
64      }
65    }
66
67    private double[,] GetElementsOfCorrelation(double[,] corr, int frames) {
68      double[,] elements = new double[corr.GetLength(0), frames + 1];
69      for (int i = 0; i < corr.GetLength(0); i++) {
70        for (int j = 0; j <= frames; j++) {
71          elements[i, j] = corr[i, j];
72        }
73      }
74      return elements;
75    }
76
77    private void CalculateElements(Dataset dataset, FCE.CorrelationCalculators calc, FCE.Partitions partition, string variable = null, int frames = 0, double[,] alreadyCalculated = null) {
78      bwInfo = new BackgroundWorkerInfo { Dataset = dataset, Calculator = calc, Partition = partition, Variable = variable, Frames = frames, AlreadyCalculated = alreadyCalculated };
79      if (bw == null) {
80        bw = new BackgroundWorker();
81        bw.WorkerReportsProgress = true;
82        bw.WorkerSupportsCancellation = true;
83        bw.DoWork += new DoWorkEventHandler(BwDoWork);
84        bw.ProgressChanged += new ProgressChangedEventHandler(BwProgressChanged);
85        bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(BwRunWorkerCompleted);
86      }
87      if (bw.IsBusy) {
88        bw.CancelAsync();
89      } else {
90        bw.RunWorkerAsync(bwInfo);
91      }
92    }
93
94    #region backgroundworker
95    private void BwDoWork(object sender, DoWorkEventArgs e) {
96      BackgroundWorkerInfo bwInfo = (BackgroundWorkerInfo)e.Argument;
97      if (bwInfo.Variable == null) {
98        BwCalculateCorrelation(sender, e);
99      } else {
100        BwCalculateTimeframeCorrelation(sender, e);
101      }
102    }
103
104    private void BwCalculateCorrelation(object sender, DoWorkEventArgs e) {
105      BackgroundWorker worker = sender as BackgroundWorker;
106
107      BackgroundWorkerInfo bwInfo = (BackgroundWorkerInfo)e.Argument;
108      Dataset dataset = bwInfo.Dataset;
109      FCE.Partitions partition = bwInfo.Partition;
110      FCE.CorrelationCalculators calc = bwInfo.Calculator;
111
112      IList<string> doubleVariableNames = dataset.DoubleVariables.ToList();
113      OnlineCalculatorError error;
114      int length = doubleVariableNames.Count;
115      double[,] elements = new double[length, length];
116      double calculations = (Math.Pow(length, 2) + length) / 2;
117
118      worker.ReportProgress(0);
119
120      for (int i = 0; i < length; i++) {
121        for (int j = 0; j < i + 1; j++) {
122          if (worker.CancellationPending) {
123            e.Cancel = true;
124            return;
125          }
126
127          IEnumerable<double> var1 = GetRelevantValues(problemData, partition, doubleVariableNames[i]);
128          IEnumerable<double> var2 = GetRelevantValues(problemData, partition, doubleVariableNames[j]);
129
130          elements[i, j] = CalculateElementWithCalculator(calc, var1, var2, out error);
131
132          elements[j, i] = elements[i, j];
133          if (!error.Equals(OnlineCalculatorError.None)) {
134            worker.ReportProgress(100);
135            throw new ArgumentException("Calculator returned " + error + Environment.NewLine + "Maybe try another calculator.");
136          }
137          worker.ReportProgress((int)Math.Round((((Math.Pow(i, 2) + i) / 2 + j + 1.0) / calculations) * 100));
138        }
139      }
140      e.Result = elements;
141    }
142
143    private void BwCalculateTimeframeCorrelation(object sender, DoWorkEventArgs e) {
144      BackgroundWorker worker = sender as BackgroundWorker;
145
146      BackgroundWorkerInfo bwInfo = (BackgroundWorkerInfo)e.Argument;
147      Dataset dataset = bwInfo.Dataset;
148      FCE.Partitions partition = bwInfo.Partition;
149      FCE.CorrelationCalculators calc = bwInfo.Calculator;
150      string variable = bwInfo.Variable;
151      int frames = bwInfo.Frames;
152      double[,] alreadyCalculated = bwInfo.AlreadyCalculated;
153
154      IList<string> doubleVariableNames = dataset.DoubleVariables.ToList();
155      OnlineCalculatorError error;
156      int length = doubleVariableNames.Count;
157      double[,] elements = new double[length, frames + 1];
158      double calculations = (frames + 1) * length;
159
160      worker.ReportProgress(0);
161
162      int start = 0;
163      if (alreadyCalculated != null) {
164        for (int i = 0; i < alreadyCalculated.GetLength(0); i++) {
165          Array.Copy(alreadyCalculated, i * alreadyCalculated.GetLength(1), elements, i * elements.GetLength(1), alreadyCalculated.GetLength(1));
166        }
167        start = alreadyCalculated.GetLength(1);
168      }
169
170      for (int i = 0; i < length; i++) {
171        for (int j = start; j <= frames; j++) {
172          if (worker.CancellationPending) {
173            e.Cancel = true;
174            return;
175          }
176
177          IEnumerable<double> var1 = GetRelevantValues(problemData, partition, variable);
178          IEnumerable<double> var2 = GetRelevantValues(problemData, partition, doubleVariableNames[i]);
179
180          var valuesInFrame = var1.Take(j);
181          var help = var1.Skip(j).ToList();
182          help.AddRange(valuesInFrame);
183          var1 = help;
184
185          elements[i, j] = CalculateElementWithCalculator(calc, var1, var2, out error);
186
187          if (!error.Equals(OnlineCalculatorError.None)) {
188            worker.ReportProgress(100);
189            throw new ArgumentException("Calculator returned " + error + Environment.NewLine + "Maybe try another calculator.");
190          }
191          worker.ReportProgress((int)((100.0 / calculations) * (i * (frames + 1) + j + 1)));
192        }
193      }
194      e.Result = elements;
195    }
196
197    private IEnumerable<double> GetRelevantValues(IDataAnalysisProblemData problemData, FCE.Partitions partition, string variable) {
198      IEnumerable<double> var = problemData.Dataset.GetDoubleValues(variable);
199      if (partition.Equals(FCE.Partitions.TrainingSamples)) {
200        var = var.Skip(problemData.TrainingPartition.Start).Take(problemData.TrainingPartition.End - problemData.TrainingPartition.Start);
201      } else if (partition.Equals(FCE.Partitions.TestSamples)) {
202        var = var.Skip(problemData.TestPartition.Start).Take(problemData.TestPartition.End - problemData.TestPartition.Start);
203      }
204      return var;
205    }
206
207    private double CalculateElementWithCalculator(FCE.CorrelationCalculators calc, IEnumerable<double> var1, IEnumerable<double> var2, out OnlineCalculatorError error) {
208      if (calc.Equals(FCE.CorrelationCalculators.HoeffdingsDependence)) {
209        return HoeffdingsDependenceCalculator.Calculate(var1, var2, out error);
210      } else if (calc.Equals(FCE.CorrelationCalculators.SpearmansRank)) {
211        return SpearmansRankCorrelationCoefficientCalculator.Calculate(var1, var2, out error);
212      } else if (calc.Equals(FCE.CorrelationCalculators.PearsonsRSquared)) {
213        return OnlinePearsonsRSquaredCalculator.Calculate(var1, var2, out error);
214      } else {
215        return Math.Sqrt(OnlinePearsonsRSquaredCalculator.Calculate(var1, var2, out error));
216      }
217    }
218
219    private void BwRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
220      BackgroundWorker worker = sender as BackgroundWorker;
221      if (!e.Cancelled && !worker.CancellationPending) {
222        if (!(e.Error == null)) {
223          ErrorHandling.ShowErrorDialog(e.Error);
224        } else {
225          OnCorrelationCalculationFinished((double[,])e.Result, bwInfo.Calculator, bwInfo.Partition, bwInfo.Variable);
226        }
227      } else {
228        bw.RunWorkerAsync(bwInfo);
229      }
230    }
231    #endregion
232
233    #region events
234    public class CorrelationCalculationFinishedArgs : EventArgs {
235      public double[,] Correlation { get; private set; }
236      public FCE.CorrelationCalculators Calculcator { get; private set; }
237      public FCE.Partitions Partition { get; private set; }
238      public string Variable { get; private set; }
239
240      public CorrelationCalculationFinishedArgs(double[,] correlation, FCE.CorrelationCalculators calculator, FCE.Partitions partition, string variable = null) {
241        this.Correlation = correlation;
242        this.Calculcator = calculator;
243        this.Partition = partition;
244        this.Variable = variable;
245      }
246    }
247    public delegate void CorrelationCalculationFinishedHandler(object sender, CorrelationCalculationFinishedArgs e);
248    public event CorrelationCalculationFinishedHandler CorrelationCalculationFinished;
249    protected virtual void OnCorrelationCalculationFinished(double[,] correlation, FCE.CorrelationCalculators calculator, FCE.Partitions partition, string variable = null) {
250      var handler = CorrelationCalculationFinished;
251      if (handler != null)
252        handler(this, new CorrelationCalculationFinishedArgs(correlation, calculator, partition, variable));
253    }
254
255    public delegate void ProgressCalculationHandler(object sender, ProgressChangedEventArgs e);
256    public event ProgressCalculationHandler ProgressCalculation;
257    protected void BwProgressChanged(object sender, ProgressChangedEventArgs e) {
258      BackgroundWorker worker = sender as BackgroundWorker;
259      if (!worker.CancellationPending && ProgressCalculation != null) {
260        ProgressCalculation(sender, e);
261      }
262    }
263    #endregion
264
265    protected class BackgroundWorkerInfo {
266      public Dataset Dataset { get; set; }
267      public FCE.CorrelationCalculators Calculator { get; set; }
268      public FCE.Partitions Partition { get; set; }
269      public string Variable { get; set; }
270      public int Frames { get; set; }
271      public double[,] AlreadyCalculated { get; set; }
272    }
273  }
274}
Note: See TracBrowser for help on using the repository browser.