Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.GeneticProgramming.BloodGlucosePrediction/Problem.cs @ 14310

Last change on this file since 14310 was 14310, checked in by gkronber, 8 years ago

changed interpreter and grammar to smooth ch and ins uptake using a compartement model

File size: 9.6 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2015 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;
24using System.Collections.Generic;
25using System.Linq;
26using HeuristicLab.Analysis;
27using HeuristicLab.Common;
28using HeuristicLab.Core;
29using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
30using HeuristicLab.Optimization;
31using HeuristicLab.Parameters;
32using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
33using HeuristicLab.Problems.DataAnalysis;
34using HeuristicLab.Problems.Instances;
35
36
37namespace HeuristicLab.Problems.GeneticProgramming.GlucosePrediction {
38  [Item("Blood Glucose Forecast", "See MedGEC Workshop at GECCO 2016")]
39  [Creatable(CreatableAttribute.Categories.GeneticProgrammingProblems, Priority = 999)]
40  [StorableClass]
41  public sealed class Problem : SymbolicExpressionTreeProblem, IRegressionProblem, IProblemInstanceConsumer<IRegressionProblemData>, IProblemInstanceExporter<IRegressionProblemData> {
42
43    #region parameter names
44    private const string ProblemDataParameterName = "ProblemData";
45    #endregion
46
47    #region Parameter Properties
48    IParameter IDataAnalysisProblem.ProblemDataParameter { get { return ProblemDataParameter; } }
49
50    public IValueParameter<IRegressionProblemData> ProblemDataParameter {
51      get { return (IValueParameter<IRegressionProblemData>)Parameters[ProblemDataParameterName]; }
52    }
53    #endregion
54
55    #region Properties
56    public IRegressionProblemData ProblemData {
57      get { return ProblemDataParameter.Value; }
58      set { ProblemDataParameter.Value = value; }
59    }
60    IDataAnalysisProblemData IDataAnalysisProblem.ProblemData { get { return ProblemData; } }
61    #endregion
62
63    public event EventHandler ProblemDataChanged;
64
65    public override bool Maximization {
66      get { return true; }
67    }
68
69    #region item cloning and persistence
70    // persistence
71    [StorableConstructor]
72    private Problem(bool deserializing) : base(deserializing) { }
73    [StorableHook(HookType.AfterDeserialization)]
74    private void AfterDeserialization() {
75      RegisterEventHandlers();
76    }
77
78    // cloning
79    private Problem(Problem original, Cloner cloner)
80      : base(original, cloner) {
81      RegisterEventHandlers();
82    }
83    public override IDeepCloneable Clone(Cloner cloner) { return new Problem(this, cloner); }
84    #endregion
85
86    public Problem()
87      : base() {
88      Parameters.Add(new ValueParameter<IRegressionProblemData>(ProblemDataParameterName, "The data for the glucose prediction problem", new RegressionProblemData()));
89
90      var g = new SimpleSymbolicExpressionGrammar(); // empty grammar is replaced in UpdateGrammar()
91      base.Encoding = new SymbolicExpressionTreeEncoding(g, 100, 17);
92
93      UpdateGrammar();
94      RegisterEventHandlers();
95    }
96
97
98    public override double Evaluate(ISymbolicExpressionTree tree, IRandom random) {
99      var problemData = ProblemData;
100      var rows = problemData.TrainingIndices.ToArray();
101      var target = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows);
102      var predicted0 = Interpreter.Apply(tree.Root.GetSubtree(0).GetSubtree(0).GetSubtree(0), problemData.Dataset, rows);
103      var predicted1 = Interpreter.Apply(tree.Root.GetSubtree(0).GetSubtree(0).GetSubtree(1), problemData.Dataset, rows);
104      var predicted2 = Interpreter.Apply(tree.Root.GetSubtree(0).GetSubtree(0).GetSubtree(2), problemData.Dataset, rows);
105
106      var pred0_rsq = Rsq(predicted0, target);
107      var pred1_rsq = Rsq(predicted1, target);
108      var pred2_rsq = Rsq(predicted2, target);
109      return pred0_rsq + pred1_rsq + pred2_rsq;
110    }
111
112    private double Rsq(IEnumerable<double> predicted, IEnumerable<double> target) {
113      // only take predictions for which the target is not NaN
114      var selectedTuples = target.Zip(predicted, Tuple.Create).Where(t => !double.IsNaN(t.Item1)).ToArray();
115      target = selectedTuples.Select(t => t.Item1);
116      predicted = selectedTuples.Select(t => t.Item2);
117
118      OnlineCalculatorError errorState;
119      var r = OnlinePearsonsRCalculator.Calculate(target, predicted, out errorState);
120      if (errorState != OnlineCalculatorError.None) r = 0;
121      return r * r;
122    }
123
124    public override void Analyze(ISymbolicExpressionTree[] trees, double[] qualities, ResultCollection results,
125      IRandom random) {
126      base.Analyze(trees, qualities, results, random);
127
128      if (!results.ContainsKey("Solution")) {
129        results.Add(new Result("Solution", typeof(IRegressionSolution)));
130      }
131      if (!results.ContainsKey("Terms")) {
132        results.Add(new Result("Terms", typeof(DataTable)));
133      }
134
135      var bestTree = trees.First();
136      var bestQuality = qualities.First();
137      for (int i = 1; i < trees.Length; i++) {
138        if (qualities[i] > bestQuality) {
139          bestQuality = qualities[i];
140          bestTree = trees[i];
141        }
142      }
143
144
145      var clonedProblemData = (IRegressionProblemData)ProblemData.Clone();
146      var rows = clonedProblemData.TrainingIndices.ToArray();
147      var target = clonedProblemData.Dataset.GetDoubleValues(clonedProblemData.TargetVariable, rows).ToArray();
148      var predicted0 =
149        Interpreter.Apply(bestTree.Root.GetSubtree(0).GetSubtree(0).GetSubtree(0), clonedProblemData.Dataset, rows)
150          .ToArray();
151      var predicted1 =
152        Interpreter.Apply(bestTree.Root.GetSubtree(0).GetSubtree(0).GetSubtree(1), clonedProblemData.Dataset, rows)
153          .ToArray();
154      var predicted2 =
155        Interpreter.Apply(bestTree.Root.GetSubtree(0).GetSubtree(0).GetSubtree(2), clonedProblemData.Dataset, rows)
156          .ToArray();
157
158      var termsTable = new HeuristicLab.Analysis.DataTable("Terms");
159      var r0 = new DataRow("GlucTerm", "GlucTerm", predicted0);
160      var r1 = new DataRow("InsTerm", "InsTerm", predicted1);
161      r1.VisualProperties.SecondYAxis = true;
162      var r2 = new DataRow("ChTerm", "ChTerm", predicted2);
163      r2.VisualProperties.SecondYAxis = true;
164      var r3 = new DataRow("Target", "Target", target);
165      termsTable.Rows.Add(r0);
166      termsTable.Rows.Add(r1);
167      termsTable.Rows.Add(r2);
168      termsTable.Rows.Add(r3);
169      results["Terms"].Value = termsTable;
170
171
172      var filteredPredicted0 = rows.Where(r => !double.IsNaN(target[r])).Select(r => predicted0[r]).ToArray();
173      var filteredPredicted1 = rows.Where(r => !double.IsNaN(target[r])).Select(r => predicted1[r]).ToArray();
174      var filteredPredicted2 = rows.Where(r => !double.IsNaN(target[r])).Select(r => predicted2[r]).ToArray();
175      var filteredTarget = target.Where(t => !double.IsNaN(t)).ToArray();
176
177
178      var ds = new ModifiableDataset(new string[] { "pred0", "pred1", "pred2", "target" },
179        new List<IList>
180        {
181          filteredPredicted0.ToList(),
182          filteredPredicted1.ToList(),
183          filteredPredicted2.ToList(),
184          filteredTarget.ToList()
185        });
186      var lrProbData = new RegressionProblemData(ds, new string[] { "pred0", "pred1", "pred2" }, "target");
187      lrProbData.TrainingPartition.Start = clonedProblemData.TrainingPartition.Start;
188      lrProbData.TrainingPartition.End = clonedProblemData.TrainingPartition.End;
189      lrProbData.TestPartition.Start = clonedProblemData.TestPartition.Start;
190      lrProbData.TestPartition.End = clonedProblemData.TestPartition.End;
191
192      try {
193        double rmsError, cvRmsError;
194        var lrSolution = HeuristicLab.Algorithms.DataAnalysis.LinearRegression.CreateLinearRegressionSolution(
195          lrProbData, out rmsError, out cvRmsError);
196        results["Solution"].Value = lrSolution;
197      } catch (Exception) {
198        // ignore
199      }
200    }
201
202    #region events
203    private void RegisterEventHandlers() {
204      ProblemDataParameter.ValueChanged += new EventHandler(ProblemDataParameter_ValueChanged);
205      if (ProblemDataParameter.Value != null) ProblemDataParameter.Value.Changed += new EventHandler(ProblemData_Changed);
206    }
207
208    private void ProblemDataParameter_ValueChanged(object sender, EventArgs e) {
209      ProblemDataParameter.Value.Changed += new EventHandler(ProblemData_Changed);
210      OnProblemDataChanged();
211      OnReset();
212    }
213
214    private void ProblemData_Changed(object sender, EventArgs e) {
215      OnReset();
216    }
217
218    private void OnProblemDataChanged() {
219      UpdateGrammar();
220
221      var handler = ProblemDataChanged;
222      if (handler != null) handler(this, EventArgs.Empty);
223    }
224
225    private void UpdateGrammar() {
226      // whenever ProblemData is changed we create a new grammar with the necessary symbols
227      var g = new Grammar();
228      Encoding.Grammar = g;
229    }
230    #endregion
231
232    #region Import & Export
233    public void Load(IRegressionProblemData data) {
234      Name = data.Name;
235      Description = data.Description;
236      ProblemData = data;
237    }
238
239    public IRegressionProblemData Export() {
240      return ProblemData;
241    }
242    #endregion
243  }
244}
Note: See TracBrowser for help on using the repository browser.