Free cookie consent management tool by TermsFeed Policy Generator

source: branches/PerformanceComparison/HeuristicLab.OptimizationExpertSystem/3.3/Views/PerformanceModelingView.cs @ 13794

Last change on this file since 13794 was 13794, checked in by abeham, 8 years ago

#2457: worked on recommendation algorithms (x-validation)

File size: 9.8 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2016 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 HeuristicLab.Analysis;
23using HeuristicLab.Common.Resources;
24using HeuristicLab.Core;
25using HeuristicLab.Data;
26using HeuristicLab.MainForm;
27using HeuristicLab.Optimization;
28using HeuristicLab.OptimizationExpertSystem.Common;
29using HeuristicLab.PluginInfrastructure;
30using System;
31using System.Collections.Generic;
32using System.Linq;
33
34namespace HeuristicLab.OptimizationExpertSystem {
35  [View("Performance Modeling View")]
36  [Content(typeof(KnowledgeCenter), IsDefaultView = false)]
37  public partial class PerformanceModelingView : KnowledgeCenterViewBase {
38    private readonly CheckedItemList<StringValue> characteristics;
39
40    public PerformanceModelingView() {
41      InitializeComponent();
42      characteristics = new CheckedItemList<StringValue>();
43      characteristics.CheckedItemsChanged += CharacteristicsOnCheckedItemsChanged;
44      characteristicsViewHost.Content = characteristics;
45      recommendStartButton.Text = string.Empty;
46      recommendStartButton.Image = VSImageLibrary.Play;
47      refreshCharacteristicsButton.Text = string.Empty;
48      refreshCharacteristicsButton.Image = VSImageLibrary.Refresh;
49      UpdateRecommenderCombobox();
50    }
51
52    protected override void OnContentChanged() {
53      base.OnContentChanged();
54      if (Content == null) {
55        minTargetView.Content = null;
56      } else {
57        minTargetView.Content = Content.MinimumTarget;
58      }
59      UpdateCharacteristics();
60    }
61
62    protected override void SetEnabledStateOfControls() {
63      base.SetEnabledStateOfControls();
64      // TODO: up/download state
65      recommendStartButton.Enabled = Content != null && recommenderComboBox.SelectedIndex >= 0 && characteristics.CheckedItems.Any();
66      characteristicsViewHost.Enabled = Content != null;
67      xValidateButton.Enabled = Content != null && recommenderComboBox.SelectedIndex >= 0 && characteristics.CheckedItems.Any();
68    }
69
70    #region Update Controls
71    private void UpdateRecommenderCombobox() {
72      if (InvokeRequired) { Invoke((Action)UpdateRecommenderCombobox); return; }
73      var prevSelection = (IAlgorithmInstanceRecommender)recommenderComboBox.SelectedItem;
74      var prevNewIndex = -1;
75      recommenderComboBox.Items.Clear();
76
77      var i = 0;
78      foreach (var rcmd in ApplicationManager.Manager.GetInstances<IAlgorithmInstanceRecommender>()) {
79        recommenderComboBox.Items.Add(rcmd);
80        if (prevSelection == null || rcmd.GetType() == prevSelection.GetType())
81          prevNewIndex = prevSelection == null ? 0 : i;
82        i++;
83      }
84     
85      recommenderComboBox.SelectedIndex = prevNewIndex;
86    }
87
88    private void UpdateCharacteristics() {
89      if (InvokeRequired) { Invoke((Action)UpdateCharacteristics); return; }
90
91      var @checked = new HashSet<string>(characteristics.CheckedItems.Select(x => x.Value.Value));
92      if (@checked.Count == 0 && Content.ProblemInstances.ResultNames.Any(x => x.StartsWith("Characteristic.")))
93        @checked = new HashSet<string>(Content.ProblemInstances.ResultNames.Where(x => x.StartsWith("Characteristic.")));
94
95      characteristics.Clear();
96      if (Content == null || Content.ProblemInstances.Count == 0) return;
97
98      foreach (var c in Content.ProblemInstances.ResultNames) {
99        characteristics.Add(new StringValue(c), @checked.Contains(c));
100      }
101    }
102    #endregion
103
104    #region Content Event Handlers
105    protected override void OnProblemInstancesChanged() {
106      base.OnProblemInstancesChanged();
107      UpdateCharacteristics();
108      SetEnabledStateOfControls();
109    }
110    #endregion
111
112    #region Control Event Handlers
113    private void RecommenderComboBoxOnSelectedIndexChanged(object sender, EventArgs e) {
114      if (InvokeRequired) { Invoke((Action<object, EventArgs>)RecommenderComboBoxOnSelectedIndexChanged, sender, e); return; }
115      var rcmd = (IAlgorithmInstanceRecommender)recommenderComboBox.SelectedItem;
116      parameterCollectionView.Content = rcmd != null ? rcmd.Parameters : null;
117      SetEnabledStateOfControls();
118    }
119
120    private void RecommendStartButtonOnClick(object sender, EventArgs e) {
121      var rcmd = (IAlgorithmInstanceRecommender)recommenderComboBox.SelectedItem;
122      var trainingSet = Content.ProblemInstances.Where(x => !Content.IsCurrentInstance(x)).ToArray();
123      Content.RecommendationModel = rcmd.TrainModel(trainingSet, Content, characteristics.CheckedItems.Select(x => x.Value.Value).ToArray());
124    }
125
126    private void RefreshCharacteristicsButtonOnClick(object sender, EventArgs e) {
127      UpdateCharacteristics();
128      SetEnabledStateOfControls();
129    }
130
131    private void xValidateButton_Click(object sender, EventArgs e) {
132      var recommender = (IAlgorithmInstanceRecommender)recommenderComboBox.SelectedItem;
133      var features = characteristics.CheckedItems.Select(x => x.Value.Value).ToArray();
134
135      var trainingSet = Content.ProblemInstances.Where(x => !Content.IsCurrentInstance(x)).ToArray();
136
137      var absErr = 0.0;
138      var confMatrix = new int[6, 6];
139      var tau = 0.0;
140      // leave one out crossvalidation
141      foreach (var pi in trainingSet) {
142        var model = recommender.TrainModel(trainingSet.Where(x => x != pi).ToArray(), Content, features);
143        var predicted = model.GetRanking(pi).ToDictionary(x => x.Key, x => x.Value);
144        var observed = Content.GetAlgorithmPerformance(pi);
145        absErr += AbsoluteError(observed, predicted);
146        var confMat = ConfusionMatrix(observed, predicted);
147        for (var i = 0; i < confMat.GetLength(0); i++)
148          for (var j = 0; j < confMat.GetLength(1); j++)
149            confMatrix[i, j] += confMat[i, j];
150        tau += KendallsTau(observed, predicted);
151        // average NCDG ... relevance determined by clustering (unsuccessful algorithms being penalized with negative relevance)
152        // mean reciprocal rank
153        // optional: expected reciprocal rank
154      }
155      absErr /= trainingSet.Length;
156      tau /= trainingSet.Length;
157
158      confusionMatrixView.Content = new IntMatrix(confMatrix);
159      absoluteErrorView.Content = new DoubleValue(absErr);
160      kendallsTauView.Content = new DoubleValue(tau);
161    }
162
163    private static double AbsoluteError(Dictionary<IAlgorithm, double> performance, Dictionary<IAlgorithm, double> ranking) {
164      var error = 0.0;
165      foreach (var tuple in ranking) {
166        double actual;
167        if (!performance.TryGetValue(tuple.Key, out actual)) continue;
168        if (double.IsNaN(actual)) actual = int.MaxValue;
169        error += Math.Abs(actual - tuple.Value);
170      }
171      return error;
172    }
173
174    private static int[,] ConfusionMatrix(Dictionary<IAlgorithm, double> performance, Dictionary<IAlgorithm, double> ranking) {
175      var confMatrix = new int[6,6];
176      var clusteredPerformance = ClusteringHelper<IAlgorithm>.Cluster(5, performance, a => double.IsNaN(a.Value)).GetByInstance().ToDictionary(x => x.Key, x => x.Value.Item2);
177      var clusteredRanks = ClusteringHelper<IAlgorithm>.Cluster(5, ranking, x => double.IsNaN(x.Value) || x.Value >= int.MaxValue).GetByInstance().ToDictionary(x => x.Key, x => x.Value.Item2);
178      foreach (var cr in clusteredRanks) {
179        int realRank;
180        if (!clusteredPerformance.TryGetValue(cr.Key, out realRank)) continue;
181        confMatrix[realRank, cr.Value]++;
182      }
183      return confMatrix;
184    }
185
186    private static double KendallsTau(Dictionary<IAlgorithm, double> performance, Dictionary<IAlgorithm, double> ranking) {
187      var commonKeys = performance.Keys.Intersect(ranking.Keys).ToList();
188      var n = commonKeys.Count;
189      if (n == 0) return 0.0;
190
191      var actualRanks = commonKeys.Select((x, i) => new { Alg = x, Index = i, Perf = performance[x] })
192                                  .OrderBy(x => x.Perf).Select((x, i) => new { Index = x.Index, Rank = i })
193                                  .OrderBy(x => x.Index).Select(x => x.Rank).ToList();
194      var predictedRanks = commonKeys.Select((x, i) => new { Alg = x, Index = i, Perf = ranking[x] })
195                                     .OrderBy(x => x.Perf).Select((x, i) => new { Index = x.Index, Rank = i })
196                                     .OrderBy(x => x.Index).Select(x => x.Rank).ToList();
197     
198      var paired = actualRanks.Zip(predictedRanks, (a, p) => new { Actual = a, Predicted = p }).ToList();
199      var concordant = 0;
200      var discordant = 0;
201      for (var i = 0; i < paired.Count - 1; i++)
202        for (var j = 0; j < paired.Count; j++) {
203          if (paired[i].Actual > paired[j].Actual && paired[i].Predicted > paired[j].Predicted
204            || paired[i].Actual < paired[j].Actual && paired[i].Predicted < paired[j].Predicted)
205            concordant++;
206          else discordant++;
207        }
208      return (2.0 * (concordant - discordant)) / (n * (n - 1));
209    }
210    #endregion
211
212    #region Other Event Handlers
213    private void CharacteristicsOnCheckedItemsChanged(object sender, EventArgs e) {
214      SetEnabledStateOfControls();
215    }
216    #endregion
217  }
218}
Note: See TracBrowser for help on using the repository browser.