Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.ArtificialNeuralNetworks/3.2/MultiLayerPerceptronTimeSeries.cs @ 3051

Last change on this file since 3051 was 2985, checked in by gkronber, 15 years ago

Fixed bugs in MLP operators, extended operators to work for time series prognosis and added pre-configured engine for time series prognosis with MLP. #882 (Artificial neural networks engine for time series prognosis)

File size: 19.5 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2008 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.Linq;
25using System.Text;
26using HeuristicLab.Core;
27using System.Xml;
28using System.Diagnostics;
29using HeuristicLab.DataAnalysis;
30using HeuristicLab.Data;
31using HeuristicLab.Modeling;
32using HeuristicLab.Operators;
33using HeuristicLab.Random;
34using HeuristicLab.Selection;
35using HeuristicLab.Operators.Programmable;
36
37namespace HeuristicLab.ArtificialNeuralNetworks {
38  public class MultiLayerPerceptronTimeSeries : ItemBase, IEditable, ITimeSeriesAlgorithm {
39
40    public virtual string Name { get { return "MultiLayerPerceptron - Time Series Prognosis"; } }
41    public virtual string Description { get { return "TODO"; } }
42
43    private IEngine engine;
44    public virtual IEngine Engine {
45      get { return engine; }
46    }
47
48    public virtual Dataset Dataset {
49      get { return ProblemInjector.GetVariableValue<Dataset>("Dataset", null, false); }
50      set { ProblemInjector.GetVariable("Dataset").Value = value; }
51    }
52
53    public virtual string TargetVariable {
54      get { return ProblemInjector.GetVariableValue<StringData>("TargetVariable", null, false).Data; }
55      set { ProblemInjector.GetVariableValue<StringData>("TargetVariable", null, false).Data = value; }
56    }
57
58    public virtual IOperator ProblemInjector {
59      get {
60        IOperator main = GetMainOperator();
61        CombinedOperator probInjector = (CombinedOperator)main.SubOperators[2];
62        return probInjector.OperatorGraph.InitialOperator.SubOperators[0];
63      }
64      set {
65        IOperator main = GetMainOperator();
66        CombinedOperator probInjector = (CombinedOperator)main.SubOperators[2];
67        probInjector.OperatorGraph.InitialOperator.RemoveSubOperator(0);
68        probInjector.OperatorGraph.InitialOperator.AddSubOperator(value, 0);
69      }
70    }
71    public IEnumerable<string> AllowedVariables {
72      get {
73        ItemList<StringData> allowedVariables = ProblemInjector.GetVariableValue<ItemList<StringData>>("AllowedFeatures", null, false);
74        return allowedVariables.Select(x => x.Data);
75      }
76      set {
77        ItemList<StringData> allowedVariables = ProblemInjector.GetVariableValue<ItemList<StringData>>("AllowedFeatures", null, false);
78        foreach (string x in value) allowedVariables.Add(new StringData(x));
79      }
80    }
81
82    public int TrainingSamplesStart {
83      get { return ProblemInjector.GetVariableValue<IntData>("TrainingSamplesStart", null, false).Data; }
84      set { ProblemInjector.GetVariableValue<IntData>("TrainingSamplesStart", null, false).Data = value; }
85    }
86
87    public int TrainingSamplesEnd {
88      get { return ProblemInjector.GetVariableValue<IntData>("TrainingSamplesEnd", null, false).Data; }
89      set { ProblemInjector.GetVariableValue<IntData>("TrainingSamplesEnd", null, false).Data = value; }
90    }
91
92    public int ValidationSamplesStart {
93      get { return ProblemInjector.GetVariableValue<IntData>("ValidationSamplesStart", null, false).Data; }
94      set { ProblemInjector.GetVariableValue<IntData>("ValidationSamplesStart", null, false).Data = value; }
95    }
96
97    public int ValidationSamplesEnd {
98      get { return ProblemInjector.GetVariableValue<IntData>("ValidationSamplesEnd", null, false).Data; }
99      set { ProblemInjector.GetVariableValue<IntData>("ValidationSamplesEnd", null, false).Data = value; }
100    }
101
102    public int TestSamplesStart {
103      get { return ProblemInjector.GetVariableValue<IntData>("TestSamplesStart", null, false).Data; }
104      set { ProblemInjector.GetVariableValue<IntData>("TestSamplesStart", null, false).Data = value; }
105    }
106
107    public int TestSamplesEnd {
108      get { return ProblemInjector.GetVariableValue<IntData>("TestSamplesEnd", null, false).Data; }
109      set { ProblemInjector.GetVariableValue<IntData>("TestSamplesEnd", null, false).Data = value; }
110    }
111
112    public IntArrayData NumberOfHiddenNodesList {
113      get { return GetVariableInjector().GetVariable("NumberOfHiddenNodesList").GetValue<IntArrayData>(); }
114      set { GetVariableInjector().GetVariable("NumberOfHiddenNodesList").Value = value; }
115    }
116
117    public int MaxNumberOfHiddenNodesListIndex {
118      get { return GetVariableInjector().GetVariable("MaxNumberOfHiddenNodesIndex").GetValue<IntData>().Data; }
119      set { GetVariableInjector().GetVariable("MaxNumberOfHiddenNodesIndex").GetValue<IntData>().Data = value; }
120    }
121
122    public virtual IAnalyzerModel Model {
123      get {
124        if (!engine.Terminated) throw new InvalidOperationException("The algorithm is still running. Wait until the algorithm is terminated to retrieve the result.");
125        IScope bestModelScope = engine.GlobalScope.SubScopes[0];
126        return CreateMlpModel(bestModelScope);
127      }
128    }
129
130    public MultiLayerPerceptronTimeSeries() {
131      engine = new SequentialEngine.SequentialEngine();
132      CombinedOperator algo = CreateAlgorithm();
133      engine.OperatorGraph.AddOperator(algo);
134      engine.OperatorGraph.InitialOperator = algo;
135      MaxNumberOfHiddenNodesListIndex = NumberOfHiddenNodesList.Data.Length;
136    }
137
138    protected virtual CombinedOperator CreateAlgorithm() {
139      CombinedOperator algo = new CombinedOperator();
140      SequentialProcessor seq = new SequentialProcessor();
141      algo.Name = Name;
142      seq.Name = Name;
143
144      IOperator globalInjector = CreateGlobalInjector();
145
146      IOperator mainLoop = CreateMainLoop();
147
148      seq.AddSubOperator(globalInjector);
149      seq.AddSubOperator(new RandomInjector());
150      seq.AddSubOperator(CreateProblemInjector());
151      seq.AddSubOperator(mainLoop);
152      seq.AddSubOperator(CreatePostProcessingOperator());
153
154      algo.OperatorGraph.InitialOperator = seq;
155      algo.OperatorGraph.AddOperator(seq);
156
157      return algo;
158    }
159
160    private IOperator CreateMainLoop() {
161      SequentialProcessor seq = new SequentialProcessor();
162
163      #region initial solution
164      SubScopesCreater modelScopeCreator = new SubScopesCreater();
165      modelScopeCreator.GetVariableInfo("SubScopes").Local = true;
166      modelScopeCreator.AddVariable(new HeuristicLab.Core.Variable("SubScopes", new IntData(1)));
167      seq.AddSubOperator(modelScopeCreator);
168
169      SequentialSubScopesProcessor seqSubScopesProc = new SequentialSubScopesProcessor();
170      IOperator modelProcessor = CreateModelProcessor();
171
172      seqSubScopesProc.AddSubOperator(modelProcessor);
173      seq.AddSubOperator(seqSubScopesProc);
174      #endregion
175
176
177      Counter nHiddenNodesCounter = new Counter();
178      nHiddenNodesCounter.GetVariableInfo("Value").ActualName = "NumberOfHiddenNodesIndex";
179      nHiddenNodesCounter.Name = "NumberOfHiddenNodesIndexCounter";
180
181      LessThanComparator comparator = new LessThanComparator();
182      comparator.Name = "NumberOfHiddenNodesIndexComparator";
183      comparator.GetVariableInfo("LeftSide").ActualName = "NumberOfHiddenNodesIndex";
184      comparator.GetVariableInfo("RightSide").ActualName = "MaxNumberOfHiddenNodesIndex";
185      comparator.GetVariableInfo("Result").ActualName = "RepeatNumberOfHiddenNodesIndexLoop";
186
187      ConditionalBranch branch = new ConditionalBranch();
188      branch.Name = "IfValidNumberOfHiddenNodesIndex";
189      branch.GetVariableInfo("Condition").ActualName = "RepeatNumberOfHiddenNodesIndexLoop";
190
191
192
193      // build loop
194      SequentialProcessor loop = new SequentialProcessor();
195      loop.Name = "HiddenNodesLoop";
196
197      #region selection of better solution
198
199      loop.AddSubOperator(modelScopeCreator);
200      SequentialSubScopesProcessor subScopesProcessor = new SequentialSubScopesProcessor();
201      loop.AddSubOperator(subScopesProcessor);
202      subScopesProcessor.AddSubOperator(new EmptyOperator());
203      subScopesProcessor.AddSubOperator(CreateModelProcessor());
204
205      Sorter sorter = new Sorter();
206      sorter.GetVariableInfo("Value").ActualName = "ValidationQuality";
207      sorter.GetVariableInfo("Descending").Local = true;
208      sorter.AddVariable(new Variable("Descending", new BoolData(false)));
209      loop.AddSubOperator(sorter);
210
211      LeftSelector selector = new LeftSelector();
212      selector.GetVariableInfo("Selected").Local = true;
213      selector.AddVariable(new Variable("Selected", new IntData(1)));
214      loop.AddSubOperator(selector);
215
216      RightReducer reducer = new RightReducer();
217      loop.AddSubOperator(reducer);
218      #endregion
219
220      loop.AddSubOperator(nHiddenNodesCounter);
221      loop.AddSubOperator(comparator);
222
223      branch.AddSubOperator(loop);
224      loop.AddSubOperator(branch);
225
226
227      seq.AddSubOperator(loop);
228      return seq;
229    }
230
231    private IOperator CreateModelProcessor() {
232      SequentialProcessor modelProcessor = new SequentialProcessor();
233      modelProcessor.AddSubOperator(CreateSetNextParameterValueOperator("NumberOfHiddenNodes"));
234
235      MultiLayerPerceptronRegressionOperator trainingOperator = new MultiLayerPerceptronRegressionOperator();
236      trainingOperator.GetVariableInfo("NumberOfHiddenLayerNeurons").ActualName = "NumberOfHiddenNodes";
237      trainingOperator.GetVariableInfo("SamplesStart").ActualName = "ActualTrainingSamplesStart";
238      trainingOperator.GetVariableInfo("SamplesEnd").ActualName = "ActualTrainingSamplesEnd";
239
240      modelProcessor.AddSubOperator(trainingOperator);
241      CombinedOperator trainingEvaluator = (CombinedOperator)CreateEvaluator("ActualTraining");
242      trainingEvaluator.OperatorGraph.InitialOperator.SubOperators[1].GetVariableInfo("MSE").ActualName = "Quality";
243      modelProcessor.AddSubOperator(trainingEvaluator);
244      modelProcessor.AddSubOperator(CreateEvaluator("Validation"));
245
246      DataCollector collector = new DataCollector();
247      collector.GetVariableInfo("Values").ActualName = "Log";
248      ((ItemList<StringData>)collector.GetVariable("VariableNames").Value).Add(new StringData("NumberOfHiddenNodes"));
249      ((ItemList<StringData>)collector.GetVariable("VariableNames").Value).Add(new StringData("ValidationQuality"));
250      modelProcessor.AddSubOperator(collector);
251      return modelProcessor;
252    }
253
254    protected virtual IOperator CreateEvaluator(string p) {
255      CombinedOperator op = new CombinedOperator();
256      op.Name = p + "Evaluator";
257      SequentialProcessor seqProc = new SequentialProcessor();
258
259      MultiLayerPerceptronEvaluator evaluator = new MultiLayerPerceptronEvaluator();
260      evaluator.Name = p + "SimpleEvaluator";
261      evaluator.GetVariableInfo("SamplesStart").ActualName = p + "SamplesStart";
262      evaluator.GetVariableInfo("SamplesEnd").ActualName = p + "SamplesEnd";
263      evaluator.GetVariableInfo("Values").ActualName = p + "Values";
264      SimpleMSEEvaluator mseEvaluator = new SimpleMSEEvaluator();
265      mseEvaluator.Name = p + "MseEvaluator";
266      mseEvaluator.GetVariableInfo("Values").ActualName = p + "Values";
267      mseEvaluator.GetVariableInfo("MSE").ActualName = p + "Quality";
268      SimpleR2Evaluator r2Evaluator = new SimpleR2Evaluator();
269      r2Evaluator.Name = p + "R2Evaluator";
270      r2Evaluator.GetVariableInfo("Values").ActualName = p + "Values";
271      r2Evaluator.GetVariableInfo("R2").ActualName = p + "R2";
272      SimpleMeanAbsolutePercentageErrorEvaluator mapeEvaluator = new SimpleMeanAbsolutePercentageErrorEvaluator();
273      mapeEvaluator.Name = p + "MAPEEvaluator";
274      mapeEvaluator.GetVariableInfo("Values").ActualName = p + "Values";
275      mapeEvaluator.GetVariableInfo("MAPE").ActualName = p + "MAPE";
276      SimpleMeanAbsolutePercentageOfRangeErrorEvaluator mapreEvaluator = new SimpleMeanAbsolutePercentageOfRangeErrorEvaluator();
277      mapreEvaluator.Name = p + "MAPREEvaluator";
278      mapreEvaluator.GetVariableInfo("Values").ActualName = p + "Values";
279      mapreEvaluator.GetVariableInfo("MAPRE").ActualName = p + "MAPRE";
280      SimpleVarianceAccountedForEvaluator vafEvaluator = new SimpleVarianceAccountedForEvaluator();
281      vafEvaluator.Name = p + "VAFEvaluator";
282      vafEvaluator.GetVariableInfo("Values").ActualName = p + "Values";
283      vafEvaluator.GetVariableInfo("VAF").ActualName = p + "VAF";
284
285      seqProc.AddSubOperator(evaluator);
286      seqProc.AddSubOperator(mseEvaluator);
287      seqProc.AddSubOperator(r2Evaluator);
288      seqProc.AddSubOperator(mapeEvaluator);
289      seqProc.AddSubOperator(mapreEvaluator);
290      seqProc.AddSubOperator(vafEvaluator);
291
292      op.OperatorGraph.AddOperator(seqProc);
293      op.OperatorGraph.InitialOperator = seqProc;
294      return op;
295    }
296
297    private IOperator CreateSetNextParameterValueOperator(string paramName) {
298      ProgrammableOperator progOp = new ProgrammableOperator();
299      progOp.Name = "SetNext" + paramName;
300      progOp.RemoveVariableInfo("Result");
301      progOp.AddVariableInfo(new VariableInfo("Value", "Value", typeof(IntData), VariableKind.New));
302      progOp.AddVariableInfo(new VariableInfo("ValueIndex", "ValueIndex", typeof(IntData), VariableKind.In));
303      progOp.AddVariableInfo(new VariableInfo("ValueList", "ValueList", typeof(IntArrayData), VariableKind.In));
304      progOp.Code =
305@"
306Value.Data = ValueList.Data[ValueIndex.Data];
307";
308
309      progOp.GetVariableInfo("Value").ActualName = paramName;
310      progOp.GetVariableInfo("ValueIndex").ActualName = paramName + "Index";
311      progOp.GetVariableInfo("ValueList").ActualName = paramName + "List";
312      return progOp;
313    }
314
315
316    protected virtual IOperator CreateProblemInjector() {
317      return DefaultTimeSeriesOperators.CreateProblemInjector();
318    }
319
320    protected virtual VariableInjector CreateGlobalInjector() {
321      VariableInjector injector = new VariableInjector();
322
323      injector.AddVariable(new HeuristicLab.Core.Variable("MaxNumberOfTrainingSamples", new IntData(4000)));
324      injector.AddVariable(new HeuristicLab.Core.Variable("PunishmentFactor", new DoubleData(1000)));
325      injector.AddVariable(new HeuristicLab.Core.Variable("NumberOfHiddenNodesIndex", new IntData(0)));
326      injector.AddVariable(new HeuristicLab.Core.Variable("MaxNumberOfHiddenNodesIndex", new IntData(0)));
327      injector.AddVariable(new HeuristicLab.Core.Variable("NumberOfHiddenNodesList", new IntArrayData(new int[] { 2, 4, 8, 16, 32, 64, 128 })));
328      injector.AddVariable(new HeuristicLab.Core.Variable("Log", new ItemList()));
329      injector.AddVariable(new HeuristicLab.Core.Variable("MaxTimeOffset", new IntData(0)));
330      injector.AddVariable(new HeuristicLab.Core.Variable("MinTimeOffset", new IntData(1)));
331      return injector;
332    }
333
334    protected virtual IOperator CreatePostProcessingOperator() {
335      CombinedOperator op = new CombinedOperator();
336      op.Name = "Model Analyzer";
337
338      SequentialSubScopesProcessor seqSubScopesProc = new SequentialSubScopesProcessor();
339      SequentialProcessor seq = new SequentialProcessor();
340      seqSubScopesProc.AddSubOperator(seq);
341
342      #region simple evaluators
343      MultiLayerPerceptronEvaluator trainingEvaluator = new MultiLayerPerceptronEvaluator();
344      trainingEvaluator.GetVariableInfo("SamplesStart").ActualName = "TrainingSamplesStart";
345      trainingEvaluator.GetVariableInfo("SamplesEnd").ActualName = "TrainingSamplesEnd";
346      trainingEvaluator.GetVariableInfo("Values").ActualName = "TrainingValues";
347
348      MultiLayerPerceptronEvaluator testEvaluator = new MultiLayerPerceptronEvaluator();
349      testEvaluator.GetVariableInfo("SamplesStart").ActualName = "TestSamplesStart";
350      testEvaluator.GetVariableInfo("SamplesEnd").ActualName = "TestSamplesEnd";
351      testEvaluator.GetVariableInfo("Values").ActualName = "TestValues";
352
353      seq.AddSubOperator(trainingEvaluator);
354      seq.AddSubOperator(testEvaluator);
355      #endregion
356
357      #region variable impacts
358      // calculate and set variable impacts
359
360      PredictorBuilder predictorBuilder = new PredictorBuilder();
361
362      seq.AddSubOperator(predictorBuilder);
363      VariableQualityImpactCalculator qualityImpactCalculator = new VariableQualityImpactCalculator();
364      qualityImpactCalculator.GetVariableInfo("SamplesStart").ActualName = "TrainingSamplesStart";
365      qualityImpactCalculator.GetVariableInfo("SamplesEnd").ActualName = "TrainingSamplesEnd";
366
367      seq.AddSubOperator(qualityImpactCalculator);
368      #endregion
369
370      seq.AddSubOperator(CreateModelAnalyzerOperator());
371      op.OperatorGraph.AddOperator(seqSubScopesProc);
372      op.OperatorGraph.InitialOperator = seqSubScopesProc;
373      return op;
374    }
375
376    protected virtual IOperator CreateModelAnalyzerOperator() {
377      return DefaultTimeSeriesOperators.CreatePostProcessingOperator();
378    }
379
380    protected virtual IAnalyzerModel CreateMlpModel(IScope bestModelScope) {
381      var model = new AnalyzerModel();
382      CreateSpecificMlpModel(bestModelScope, model);
383      #region variable impacts
384      ItemList qualityImpacts = bestModelScope.GetVariableValue<ItemList>(ModelingResult.VariableQualityImpact.ToString(), false);
385      foreach (ItemList row in qualityImpacts) {
386        string variableName = ((StringData)row[0]).Data;
387        double impact = ((DoubleData)row[1]).Data;
388        model.SetVariableResult(ModelingResult.VariableQualityImpact, variableName, impact);
389        model.AddInputVariable(variableName);
390      }
391      #endregion
392      return model;
393    }
394
395    protected virtual void CreateSpecificMlpModel(IScope bestModelScope, IAnalyzerModel model) {
396      DefaultTimeSeriesOperators.PopulateAnalyzerModel(bestModelScope, model);
397    }
398
399    protected virtual IOperator GetMainOperator() {
400      CombinedOperator lr = (CombinedOperator)Engine.OperatorGraph.InitialOperator;
401      return lr.OperatorGraph.InitialOperator;
402    }
403
404    protected virtual IOperator GetVariableInjector() {
405      return GetMainOperator().SubOperators[0];
406    }
407
408    public override IView CreateView() {
409      return engine.CreateView();
410    }
411
412    #region IEditable Members
413
414    public virtual IEditor CreateEditor() {
415      return ((SequentialEngine.SequentialEngine)engine).CreateEditor();
416    }
417
418    #endregion
419
420    #region persistence
421    public override object Clone(IDictionary<Guid, object> clonedObjects) {
422      MultiLayerPerceptronTimeSeries clone = (MultiLayerPerceptronTimeSeries)base.Clone(clonedObjects);
423      clone.engine = (IEngine)Auxiliary.Clone(Engine, clonedObjects);
424      return clone;
425    }
426
427    public override XmlNode GetXmlNode(string name, XmlDocument document, IDictionary<Guid, IStorable> persistedObjects) {
428      XmlNode node = base.GetXmlNode(name, document, persistedObjects);
429      node.AppendChild(PersistenceManager.Persist("Engine", engine, document, persistedObjects));
430      return node;
431    }
432
433    public override void Populate(XmlNode node, IDictionary<Guid, IStorable> restoredObjects) {
434      base.Populate(node, restoredObjects);
435      engine = (IEngine)PersistenceManager.Restore(node.SelectSingleNode("Engine"), restoredObjects);
436    }
437    #endregion
438  }
439}
Note: See TracBrowser for help on using the repository browser.