Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.ArtificialNeuralNetworks/3.2/MultiLayerPerceptronRegression.cs @ 2985

Last change on this file since 2985 was 2985, checked in by gkronber, 14 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.3 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 MultiLayerPerceptronRegression : ItemBase, IEditable, IAlgorithm {
39
40    public virtual string Name { get { return "MultiLayerPerceptronRegression"; } }
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 MultiLayerPerceptronRegression() {
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 DefaultRegressionOperators.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      return injector;
330    }
331
332    protected virtual IOperator CreatePostProcessingOperator() {
333      CombinedOperator op = new CombinedOperator();
334      op.Name = "Model Analyzer";
335
336      SequentialSubScopesProcessor seqSubScopesProc = new SequentialSubScopesProcessor();
337      SequentialProcessor seq = new SequentialProcessor();
338      seqSubScopesProc.AddSubOperator(seq);
339
340      #region simple evaluators
341      MultiLayerPerceptronEvaluator trainingEvaluator = new MultiLayerPerceptronEvaluator();
342      trainingEvaluator.GetVariableInfo("SamplesStart").ActualName = "TrainingSamplesStart";
343      trainingEvaluator.GetVariableInfo("SamplesEnd").ActualName = "TrainingSamplesEnd";
344      trainingEvaluator.GetVariableInfo("Values").ActualName = "TrainingValues";
345
346      MultiLayerPerceptronEvaluator testEvaluator = new MultiLayerPerceptronEvaluator();
347      testEvaluator.GetVariableInfo("SamplesStart").ActualName = "TestSamplesStart";
348      testEvaluator.GetVariableInfo("SamplesEnd").ActualName = "TestSamplesEnd";
349      testEvaluator.GetVariableInfo("Values").ActualName = "TestValues";
350
351      seq.AddSubOperator(trainingEvaluator);
352      seq.AddSubOperator(testEvaluator);
353      #endregion
354
355      #region variable impacts
356      // calculate and set variable impacts
357
358      PredictorBuilder predictorBuilder = new PredictorBuilder();
359
360      seq.AddSubOperator(predictorBuilder);
361      VariableQualityImpactCalculator qualityImpactCalculator = new VariableQualityImpactCalculator();
362      qualityImpactCalculator.GetVariableInfo("SamplesStart").ActualName = "TrainingSamplesStart";
363      qualityImpactCalculator.GetVariableInfo("SamplesEnd").ActualName = "TrainingSamplesEnd";
364
365      seq.AddSubOperator(qualityImpactCalculator);
366      #endregion
367
368      seq.AddSubOperator(CreateModelAnalyzerOperator());
369      op.OperatorGraph.AddOperator(seqSubScopesProc);
370      op.OperatorGraph.InitialOperator = seqSubScopesProc;
371      return op;
372    }
373
374    protected virtual IOperator CreateModelAnalyzerOperator() {
375      return DefaultRegressionOperators.CreatePostProcessingOperator();
376    }
377
378    protected virtual IAnalyzerModel CreateMlpModel(IScope bestModelScope) {
379      var model = new AnalyzerModel();
380      CreateSpecificMlpModel(bestModelScope, model);
381      #region variable impacts
382      ItemList qualityImpacts = bestModelScope.GetVariableValue<ItemList>(ModelingResult.VariableQualityImpact.ToString(), false);
383      foreach (ItemList row in qualityImpacts) {
384        string variableName = ((StringData)row[0]).Data;
385        double impact = ((DoubleData)row[1]).Data;
386        model.SetVariableResult(ModelingResult.VariableQualityImpact, variableName, impact);
387        model.AddInputVariable(variableName);
388      }
389      #endregion
390      return model;
391    }
392
393    protected virtual void CreateSpecificMlpModel(IScope bestModelScope, IAnalyzerModel model) {
394      DefaultRegressionOperators.PopulateAnalyzerModel(bestModelScope, model);
395    }
396
397    protected virtual IOperator GetMainOperator() {
398      CombinedOperator lr = (CombinedOperator)Engine.OperatorGraph.InitialOperator;
399      return lr.OperatorGraph.InitialOperator;
400    }
401
402    protected virtual IOperator GetVariableInjector() {
403      return GetMainOperator().SubOperators[0];
404    }
405
406    public override IView CreateView() {
407      return engine.CreateView();
408    }
409
410    #region IEditable Members
411
412    public virtual IEditor CreateEditor() {
413      return ((SequentialEngine.SequentialEngine)engine).CreateEditor();
414    }
415
416    #endregion
417
418    #region persistence
419    public override object Clone(IDictionary<Guid, object> clonedObjects) {
420      MultiLayerPerceptronRegression clone = (MultiLayerPerceptronRegression)base.Clone(clonedObjects);
421      clone.engine = (IEngine)Auxiliary.Clone(Engine, clonedObjects);
422      return clone;
423    }
424
425    public override XmlNode GetXmlNode(string name, XmlDocument document, IDictionary<Guid, IStorable> persistedObjects) {
426      XmlNode node = base.GetXmlNode(name, document, persistedObjects);
427      node.AppendChild(PersistenceManager.Persist("Engine", engine, document, persistedObjects));
428      return node;
429    }
430
431    public override void Populate(XmlNode node, IDictionary<Guid, IStorable> restoredObjects) {
432      base.Populate(node, restoredObjects);
433      engine = (IEngine)PersistenceManager.Restore(node.SelectSingleNode("Engine"), restoredObjects);
434    }
435    #endregion
436  }
437}
Note: See TracBrowser for help on using the repository browser.