Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2904_CalculateImpacts/HeuristicLab.Problems.DataAnalysis.Views/3.4/Classification/ClassificationSolutionVariableImpactsView.cs @ 16042

Last change on this file since 16042 was 16042, checked in by fholzing, 6 years ago

#2904: Renamed variableImactsArrayView to variableImpactsArrayView

File size: 10.5 KB
RevLine 
[14348]1#region License Information
2/* HeuristicLab
[15583]3 * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
[14348]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
[15667]21
[14348]22using System;
[15667]23using System.Collections.Generic;
[14348]24using System.Linq;
[15753]25using System.Threading;
26using System.Threading.Tasks;
[15667]27using HeuristicLab.Common;
[14348]28using HeuristicLab.Data;
29using HeuristicLab.MainForm;
30
31namespace HeuristicLab.Problems.DataAnalysis.Views {
32  [View("Variable Impacts")]
[15638]33  [Content(typeof(IClassificationSolution))]
34  public partial class ClassificationSolutionVariableImpactsView : DataAnalysisSolutionEvaluationView {
[15674]35    private enum SortingCriteria {
36      ImpactValue,
37      Occurrence,
38      VariableName
39    }
[16036]40    private CancellationTokenSource cancellationToken = new CancellationTokenSource();
41    private List<Tuple<string, double>> rawVariableImpacts = new List<Tuple<string, double>>();
[15674]42
[15638]43    public new IClassificationSolution Content {
44      get { return (IClassificationSolution)base.Content; }
[14348]45      set {
46        base.Content = value;
47      }
48    }
49
[15638]50    public ClassificationSolutionVariableImpactsView()
[14348]51      : base() {
52      InitializeComponent();
[15667]53
[15729]54      //Set the default values
[14348]55      this.dataPartitionComboBox.SelectedIndex = 0;
[16036]56      this.replacementComboBox.SelectedIndex = 3;
[14826]57      this.factorVarReplComboBox.SelectedIndex = 0;
[16036]58      this.sortByComboBox.SelectedItem = SortingCriteria.ImpactValue;
[14348]59    }
60
61    protected override void RegisterContentEvents() {
62      base.RegisterContentEvents();
63      Content.ModelChanged += new EventHandler(Content_ModelChanged);
64      Content.ProblemDataChanged += new EventHandler(Content_ProblemDataChanged);
65    }
66    protected override void DeregisterContentEvents() {
67      base.DeregisterContentEvents();
68      Content.ModelChanged -= new EventHandler(Content_ModelChanged);
69      Content.ProblemDataChanged -= new EventHandler(Content_ProblemDataChanged);
70    }
71
72    protected virtual void Content_ProblemDataChanged(object sender, EventArgs e) {
73      OnContentChanged();
74    }
75    protected virtual void Content_ModelChanged(object sender, EventArgs e) {
76      OnContentChanged();
77    }
78    protected override void OnContentChanged() {
79      base.OnContentChanged();
80      if (Content == null) {
[16042]81        variableImpactsArrayView.Content = null;
[14348]82      } else {
[15753]83        UpdateVariableImpact();
[14348]84      }
85    }
[15753]86    private void ClassificationSolutionVariableImpactsView_VisibleChanged(object sender, EventArgs e) {
[16036]87      cancellationToken.Cancel();
[15753]88    }
89
[15667]90    private void dataPartitionComboBox_SelectedIndexChanged(object sender, EventArgs e) {
[15753]91      UpdateVariableImpact();
[15667]92    }
93    private void replacementComboBox_SelectedIndexChanged(object sender, EventArgs e) {
[15753]94      UpdateVariableImpact();
[15667]95    }
96    private void sortByComboBox_SelectedIndexChanged(object sender, EventArgs e) {
97      //Update the default ordering (asc,desc), but remove the eventHandler beforehand (otherwise the data would be ordered twice)
98      ascendingCheckBox.CheckedChanged -= ascendingCheckBox_CheckedChanged;
[16036]99      ascendingCheckBox.Checked = (SortingCriteria)sortByComboBox.SelectedItem != SortingCriteria.ImpactValue;
[15667]100      ascendingCheckBox.CheckedChanged += ascendingCheckBox_CheckedChanged;
101
[16036]102      UpdateOrdering();
[15667]103    }
104    private void ascendingCheckBox_CheckedChanged(object sender, EventArgs e) {
[16036]105      UpdateOrdering();
[15667]106    }
[15729]107
[16036]108    private async void UpdateVariableImpact() {
[15729]109      //Check if the selection is valid
[15674]110      if (Content == null) { return; }
111      if (replacementComboBox.SelectedIndex < 0) { return; }
112      if (dataPartitionComboBox.SelectedIndex < 0) { return; }
113      if (factorVarReplComboBox.SelectedIndex < 0) { return; }
114
[16036]115      IProgress progress;
116
[15729]117      //Prepare arguments
[15674]118      var mainForm = (MainForm.WindowsForms.MainForm)MainFormManager.MainForm;
119      var replMethod = (ClassificationSolutionVariableImpactsCalculator.ReplacementMethodEnum)replacementComboBox.Items[replacementComboBox.SelectedIndex];
120      var factorReplMethod = (ClassificationSolutionVariableImpactsCalculator.FactorReplacementMethodEnum)factorVarReplComboBox.Items[factorVarReplComboBox.SelectedIndex];
121      var dataPartition = (ClassificationSolutionVariableImpactsCalculator.DataPartitionEnum)dataPartitionComboBox.SelectedItem;
122
[16042]123      variableImpactsArrayView.Caption = Content.Name + " Variable Impacts";
[16036]124      progress = mainForm.AddOperationProgressToView(this, "Calculating variable impacts for " + Content.Name);
125      progress.ProgressValue = 0;
[15753]126
[16036]127      cancellationToken = new CancellationTokenSource();
[15753]128
[16036]129      try {
[15753]130        var problemData = Content.ProblemData;
131        var inputvariables = new HashSet<string>(problemData.AllowedInputVariables.Union(Content.Model.VariablesUsedForPrediction));
[16036]132        //Remember the original ordering of the variables
133        var originalVariableOrdering = problemData.Dataset.VariableNames
134          .Where(v => inputvariables.Contains(v))
135          .Where(v => problemData.Dataset.VariableHasType<double>(v) || problemData.Dataset.VariableHasType<string>(v))
136          .ToList();
[15753]137
[16036]138        List<Tuple<string, double>> impacts = null;
139
140        await Task.Run(() => { impacts = CalculateVariableImpacts(originalVariableOrdering, (IClassificationModel)Content.Model.Clone(), problemData, Content.EstimatedClassValues, dataPartition, replMethod, factorReplMethod, cancellationToken.Token, progress); });
141        if (impacts == null) { return; }
142
[15753]143        rawVariableImpacts.Clear();
[16036]144        originalVariableOrdering.ForEach(v => rawVariableImpacts.Add(new Tuple<string, double>(v, impacts.First(vv => vv.Item1 == v).Item2)));
145        UpdateOrdering();
146      }
147      finally {
148        ((MainForm.WindowsForms.MainForm)MainFormManager.MainForm).RemoveOperationProgressFromView(this);
149      }
[14348]150    }
151
[16036]152    private List<Tuple<string, double>> CalculateVariableImpacts(List<string> originalVariableOrdering,
153      IClassificationModel model,
154      IClassificationProblemData problemData,
155      IEnumerable<double> estimatedValues,
156      ClassificationSolutionVariableImpactsCalculator.DataPartitionEnum dataPartition,
157      ClassificationSolutionVariableImpactsCalculator.ReplacementMethodEnum replMethod,
158      ClassificationSolutionVariableImpactsCalculator.FactorReplacementMethodEnum factorReplMethod,
159      CancellationToken token,
160      IProgress progress) {
161      List<Tuple<string, double>> impacts = new List<Tuple<string, double>>();
162      int count = originalVariableOrdering.Count;
163      int i = 0;
164      var modifiableDataset = ((Dataset)(problemData.Dataset).Clone()).ToModifiable();
165      IEnumerable<int> rows = ClassificationSolutionVariableImpactsCalculator.GetPartitionRows(dataPartition, problemData);
166
167      //Calculate original quality-values (via calculator, default is R²)
168      OnlineCalculatorError error;
169      IEnumerable<double> targetValuesPartition = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows);
[16041]170      IEnumerable<double> estimatedValuesPartition = Content.GetEstimatedClassValues(rows);
[16036]171      var originalCalculatorValue = ClassificationSolutionVariableImpactsCalculator.CalculateVariableImpact(targetValuesPartition, estimatedValuesPartition, out error);
172      if (error != OnlineCalculatorError.None) throw new InvalidOperationException("Error during calculation.");
173
174      foreach (var variableName in originalVariableOrdering) {
175        if (cancellationToken.Token.IsCancellationRequested) { return null; }
176        progress.ProgressValue = (double)++i / count;
177        progress.Status = string.Format("Calculating impact for variable {0} ({1} of {2})", variableName, i, count);
178
[16041]179        double impact = 0;
180        //If the variable isn't used for prediction, it has zero impact.
181        if (model.VariablesUsedForPrediction.Contains(variableName)) {
182          impact = ClassificationSolutionVariableImpactsCalculator.CalculateImpact(variableName, model, modifiableDataset, rows, targetValuesPartition, originalCalculatorValue, replMethod, factorReplMethod);
183        }
[16036]184        impacts.Add(new Tuple<string, double>(variableName, impact));
185      }
186
187      return impacts;
188    }
189
[15667]190    /// <summary>
[16042]191    /// Updates the <see cref="variableImpactsArrayView"/> according to the selected ordering <see cref="ascendingCheckBox"/> of the selected Column <see cref="sortByComboBox"/>
[15667]192    /// The default is "Descending" by "VariableImpact" (as in previous versions)
193    /// </summary>
[16036]194    private void UpdateOrdering() {
[15667]195      //Check if valid sortingCriteria is selected and data exists
[15674]196      if (sortByComboBox.SelectedIndex == -1) { return; }
197      if (rawVariableImpacts == null) { return; }
198      if (!rawVariableImpacts.Any()) { return; }
[14348]199
[15674]200      var selectedItem = (SortingCriteria)sortByComboBox.SelectedItem;
[15667]201      bool ascending = ascendingCheckBox.Checked;
[14348]202
[16036]203      IEnumerable<Tuple<string, double>> orderedEntries = null;
[15667]204
205      //Sort accordingly
206      switch (selectedItem) {
[15674]207        case SortingCriteria.ImpactValue:
[16036]208          orderedEntries = rawVariableImpacts.OrderBy(v => v.Item2);
[15667]209          break;
[15674]210        case SortingCriteria.Occurrence:
211          orderedEntries = rawVariableImpacts;
[15667]212          break;
[15674]213        case SortingCriteria.VariableName:
[16036]214          orderedEntries = rawVariableImpacts.OrderBy(v => v.Item1, new NaturalStringComparer());
[15667]215          break;
216        default:
[15674]217          throw new NotImplementedException("Ordering for selected SortingCriteria not implemented");
[15667]218      }
219
[15674]220      if (!ascending) { orderedEntries = orderedEntries.Reverse(); }
221
[15667]222      //Write the data back
[16036]223      var impactArray = new DoubleArray(orderedEntries.Select(i => i.Item2).ToArray()) {
224        ElementNames = orderedEntries.Select(i => i.Item1)
[15667]225      };
[15729]226
[15753]227      //Could be, if the View was closed
[16042]228      if (!variableImpactsArrayView.IsDisposed) {
229        variableImpactsArrayView.Content = (DoubleArray)impactArray.AsReadOnly();
[15729]230      }
[14348]231    }
232  }
233}
Note: See TracBrowser for help on using the repository browser.