Free cookie consent management tool by TermsFeed Policy Generator

source: branches/3133_ProblemModifiers/HeuristicLab.Problems.Modifiers/Modifier/ModelBasedEvaluationRemoverProblemModifier.cs @ 18029

Last change on this file since 18029 was 18029, checked in by bwerth, 3 years ago

#3133 added implementation of problem modifiers

File size: 12.5 KB
Line 
1#region License Information
2
3/* HeuristicLab
4 * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
5 *
6 * This file is part of HeuristicLab.
7 *
8 * HeuristicLab is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * HeuristicLab is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#endregion License Information
23
24using System;
25using System.Collections.Generic;
26using System.Linq;
27using HEAL.Attic;
28using HeuristicLab.Analysis;
29using HeuristicLab.Common;
30using HeuristicLab.Core;
31using HeuristicLab.Data;
32using HeuristicLab.Encodings.IntegerVectorEncoding;
33using HeuristicLab.Encodings.RealVectorEncoding;
34using HeuristicLab.Optimization;
35using HeuristicLab.Problems.DataAnalysis;
36
37namespace HeuristicLab.Problems.Modifiers {
38  [StorableType("867E0908-9DD4-4924-BB31-10B81B006BE4")]
39  [Item("ModelBasedEvaluationRemoverProblemModifier", " A problem modifier that provides extended Analysis by creating running models (models trained on the evaluations of previous iterations) and analyzing their performance over time")]
40  public abstract class ModelBasedEvaluationRemoverProblemModifier : ProblemModifier {
41    private readonly object locker = new object();
42    #region Properties
43    [Storable]
44    protected ModifiableDataset data;
45    [Storable]
46    protected Dictionary<string, List<double[]>> evaluationsLookUp;
47    [Storable]
48    protected List<Tuple<double[], double[]>> evaluatedThisIteration;
49    [Storable]
50    protected List<Tuple<double[], double[], double[]>> lastPopulation;
51    [Storable]
52    protected List<IRegressionSolution> solutions;
53    [Storable]
54    protected ResultCollection modelingResults;
55    [Storable]
56    protected int iteration;
57    #endregion
58
59    #region constructors
60    [StorableConstructor]
61    protected ModelBasedEvaluationRemoverProblemModifier(StorableConstructorFlag _) : base(_) { }
62    protected ModelBasedEvaluationRemoverProblemModifier(ModelBasedEvaluationRemoverProblemModifier original, Cloner cloner) : base(original, cloner) {
63      data = cloner.Clone(original?.data);
64      evaluationsLookUp = original?.evaluationsLookUp.ToDictionary(e => e.Key, e => e.Value.Select(o => o.ToArray()).ToList());
65      evaluatedThisIteration = original?.evaluatedThisIteration.Select(x => Tuple.Create(x.Item1.ToArray(), x.Item2.ToArray())).ToList();
66      lastPopulation = original?.lastPopulation.Select(x => Tuple.Create(x.Item1.ToArray(), x.Item2.ToArray(), x.Item3.ToArray())).ToList();
67      solutions = original?.solutions?.Select(cloner.Clone).ToList();
68      iteration = original?.iteration ?? 0;
69      modelingResults = cloner.Clone(original?.modelingResults);
70    }
71    protected ModelBasedEvaluationRemoverProblemModifier() {
72      InitializeDataCollection();
73    }
74    #endregion
75
76    #region ProblemModifier
77    public override void ModifiedAnalyze(Individual[] individuals, double[][] qualities, ResultCollection results, IRandom random) {
78      lock (locker) {
79        solutions = new List<IRegressionSolution>();
80        for (var i = 0; i < qualities.First().Length; i++) {
81          // model building and prediction
82          var pd = new RegressionProblemData(data, data.VariableNames.Where(v => v.Contains("X")), TargetVariableName(i));
83          pd.TrainingPartition.Start = 0;
84          pd.TrainingPartition.End = pd.TestPartition.Start = data.Rows;
85          pd.TestPartition.End = data.Rows;
86          var sol = BuildRunningModel(pd, random, i);
87          solutions.Add(sol);
88        }
89
90        var survivors = new HashSet<string>(individuals.Select(ToIdentifier));
91        var newSurvivors = evaluatedThisIteration.Where(x => survivors.Contains(ToIdentifier(x.Item1))).ToArray();
92
93        AddOrExtendScatterPlot(modelingResults,
94          "Real Evaluations",
95          "objective 1",
96          "objective 2",
97          "iteration" + iteration,
98          evaluatedThisIteration.Select(x => new Point2D<double>(x.Item2[0], x.Item2[1])).ToArray()
99        );
100        AddOrExtendDataTable(modelingResults, "Removal Plot", new[] {
101          Tuple.Create("Total Removed Evaluations", (double) ((IntValue) modelingResults["Removed Evaluations"].Value).Value, false),
102          Tuple.Create("Total Performed Evaluations", (double) ((IntValue) modelingResults["Performed Evaluations"].Value).Value, false),
103          Tuple.Create("Removed Evaluations", (double) ((IntValue) modelingResults["Removed Evaluations (current generation)"].Value).Value, false),
104          Tuple.Create("Performed Evaluations", (double) ((IntValue) modelingResults["Performed Evaluations (current generation)"].Value).Value, false),
105          Tuple.Create("Survived Performed Evaluations", (double) newSurvivors.Length, false)
106        });
107        modelingResults.AddOrUpdateResult("Removed Evaluations (current generation)", new IntValue(0));
108        modelingResults.AddOrUpdateResult("Performed Evaluations (current generation)", new IntValue(0));
109
110        foreach (var regressionSolution in solutions) {
111          modelingResults.AddOrUpdateResult("model_" + regressionSolution.ProblemData.TargetVariable, regressionSolution);
112        }
113      }
114
115      iteration++;
116      lastPopulation = individuals.Zip(qualities, (i, q) => Tuple.Create(
117        ExtractInputs(i),
118        q,
119        solutions.Select(sol => sol.Model.GetEstimatedValues(ToDataset(ExtractInputs(i)), new[] { 0 }).Single()).ToArray()
120      )).ToList();
121      results.AddOrUpdateResult("ModelingResults", modelingResults);
122      lock (evaluatedThisIteration) evaluatedThisIteration.Clear();
123
124      base.ModifiedAnalyze(individuals, qualities, results, random);
125    }
126    public override double[] ModifiedEvaluate(Individual individual, IRandom random) {
127      if (RemoveEvaluation(individual, Maximization.CloneAsArray(), random)) {
128        lock (locker) {
129          ((IntValue)modelingResults["Removed Evaluations"].Value).Value++;
130          ((IntValue)modelingResults["Removed Evaluations (current generation)"].Value).Value++;
131        }
132        return Maximization.Select(x => x ? double.MinValue : double.MaxValue).ToArray();
133      }
134
135      var q = base.ModifiedEvaluate(individual, random);
136      lock (locker) {
137        ((IntValue)modelingResults["Performed Evaluations"].Value).Value++;
138        ((IntValue)modelingResults["Performed Evaluations (current generation)"].Value).Value++;
139        ExtendDatasetWithoutDuplicates(new[] { individual }, new[] { q });
140        evaluatedThisIteration.Add(Tuple.Create(ExtractInputs(individual), q.ToArray()));
141      }
142      return q;
143    }
144    #endregion
145
146    protected abstract IRegressionSolution BuildRunningModel(RegressionProblemData pd, IRandom random, int objectiveNumber);
147    protected abstract bool RemoveEvaluation(Individual individual, bool[] maximization, IRandom random);
148
149    #region AnalysisHelpers
150    private static void AddOrExtendScatterPlot(ResultCollection results, string resultName, string xLabel, string yLabel, string rowName, IList<Point2D<double>> points) {
151      ScatterPlot plot;
152      if (results.ContainsKey(resultName)) {
153        plot = (ScatterPlot)results[resultName].Value;
154      } else {
155        plot = new ScatterPlot(resultName, "");
156        results.Add(new Result(resultName, plot));
157        plot.VisualProperties.XAxisTitle = xLabel;
158        plot.VisualProperties.YAxisTitle = yLabel;
159      }
160
161      var row = new ScatterPlotDataRow(rowName, "", points);
162      if (!plot.Rows.ContainsKey(rowName)) plot.Rows.Add(row);
163      else plot.Rows[rowName].Points.AddRange(points);
164    }
165    private static void AddOrExtendDataTable(ResultCollection results, string resultName, IReadOnlyList<Tuple<string, double, bool>> values) {
166      DataTable plot;
167      if (results.ContainsKey(resultName)) {
168        plot = (DataTable)results[resultName].Value;
169      } else {
170        plot = new DataTable(resultName);
171        results.Add(new Result(resultName, plot));
172        plot.VisualProperties.XAxisTitle = "Iteration";
173        plot.VisualProperties.YAxisTitle = "Evaluations";
174      }
175      foreach (var tuple in values) AddOrExtendRow(plot, tuple.Item1, tuple.Item2, tuple.Item3);
176    }
177    private static void AddOrExtendRow(DataTable plot, string rowName, double d, bool secondary = false) {
178      DataRow row;
179      if (plot.Rows.ContainsKey(rowName)) {
180        row = plot.Rows[rowName];
181      } else {
182        row = new DataRow(rowName);
183        plot.Rows.Add(row);
184      }
185      row.Values.Add(d);
186      row.VisualProperties.SecondYAxis = secondary;
187    }
188    #endregion
189
190    #region DataHandling
191    private void InitializeDataCollection() {
192      lock (locker) {
193        evaluatedThisIteration = new List<Tuple<double[], double[]>>();
194        lastPopulation = new List<Tuple<double[], double[], double[]>>();
195        modelingResults = new ResultCollection();
196        iteration = 0;
197        modelingResults.AddOrUpdateResult("Removed Evaluations", new IntValue(0));
198        modelingResults.AddOrUpdateResult("Performed Evaluations", new IntValue(0));
199        modelingResults.AddOrUpdateResult("Removed Evaluations (current generation)", new IntValue(0));
200        modelingResults.AddOrUpdateResult("Performed Evaluations (current generation)", new IntValue(0));
201        data = new ModifiableDataset();
202        if (evaluationsLookUp == null) evaluationsLookUp = new Dictionary<string, List<double[]>>();
203        evaluationsLookUp.Clear();
204      }
205    }
206    private void ExtendDatasetWithoutDuplicates(IReadOnlyList<Individual> individuals, IReadOnlyList<double[]> qualities) {
207      if (data.Rows == 0) {
208        for (var i = 0; i < ExtractInputs(individuals[0]).Length; i++) {
209          var v = InputVariableName(i);
210          if (!data.DoubleVariables.Contains(v))
211            data.AddVariable(v, new List<double>());
212        }
213        for (var i = 0; i < qualities[0].Length; i++) {
214          var v = TargetVariableName(i);
215          if (!data.DoubleVariables.Contains(v))
216            data.AddVariable(v, new List<double>());
217        }
218      }
219      for (var i = 0; i < individuals.Count; i++) {
220        var ins = ExtractInputs(individuals[i]);
221        var id = ToIdentifier(ins);
222        var outs = qualities[i];
223        if (outs.Any(x => double.IsNaN(x) || double.IsInfinity(x) || double.MaxValue / 100 < x || double.MinValue / 100 > x || x > 100000)) continue;
224        if (evaluationsLookUp.ContainsKey(id) && evaluationsLookUp[id].Any(o => Equals(o, outs))) continue;
225
226        if (ins.Length + outs.Length != data.DoubleVariables.Count()) throw new ArgumentException("length of individuals and outputs does not match existing data");
227        data.AddRow(ins.Concat(qualities[i]).Select(x => (object)x));
228        if (!evaluationsLookUp.ContainsKey(id)) evaluationsLookUp.Add(id, new List<double[]>() { outs });
229        else { evaluationsLookUp[id].Add(outs); }
230      }
231    }
232    protected static Dataset ToDataset(double[] ins) {
233      return new Dataset(ins.Select((d, i1) => InputVariableName(i1)), ins.Select(d => new List<double>() { d }));
234    }
235    protected static double[] ExtractInputs(Individual individual) {
236      if (!(individual is SingleEncodingIndividual si)) throw new ArgumentException("Multi encodings are not supported with this problem modifier");
237      var e = si[si.Name];
238      switch (e) {
239        case RealVector rv:
240          return rv.CloneAsArray();
241
242        case IntegerVector iv:
243          return iv.Select(i => (double)i).ToArray();
244
245        default:
246          throw new ArgumentException("Only Integer and Real Vector Individuals can be transformed to input values");
247      }
248    }
249    #endregion DataHandling
250
251    #region Naming
252    public static string ToIdentifier(double[] inputs) {
253      return string.Join(";", inputs);
254    }
255    public static string ToIdentifier(Individual i) {
256      return string.Join(";", ExtractInputs(i));
257    }
258    public static string TargetVariableName(int targetNumber) {
259      return "Y" + targetNumber;
260    }
261    public static string InputVariableName(int inputNumber) {
262      return "X" + inputNumber;
263    }
264    #endregion Naming
265  }
266}
Note: See TracBrowser for help on using the repository browser.