Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.ArtificialNeuralNetworks/3.2/MultiLayerPerceptronRegressionOperator.cs @ 3042

Last change on this file since 3042 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: 10.6 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
21using System;
22using System.Collections.Generic;
23using System.Linq;
24using System.Text;
25using HeuristicLab.Core;
26using HeuristicLab.Data;
27using HeuristicLab.DataAnalysis;
28using HeuristicLab.Modeling;
29
30namespace HeuristicLab.ArtificialNeuralNetworks {
31  public class MultiLayerPerceptronRegressionOperator : OperatorBase {
32
33    public MultiLayerPerceptronRegressionOperator() {
34      AddVariableInfo(new VariableInfo("TargetVariable", "Name of the target variable", typeof(StringData), VariableKind.In));
35      AddVariableInfo(new VariableInfo("Dataset", "Dataset with all samples on which to apply the function", typeof(Dataset), VariableKind.In));
36      AddVariableInfo(new VariableInfo("SamplesStart", "Start index of samples in dataset to evaluate", typeof(IntData), VariableKind.In));
37      AddVariableInfo(new VariableInfo("SamplesEnd", "End index of samples in dataset to evaluate", typeof(IntData), VariableKind.In));
38      AddVariableInfo(new VariableInfo("ValidationSamplesStart", "Start of validation set", typeof(IntData), VariableKind.In));
39      AddVariableInfo(new VariableInfo("ValidationSamplesEnd", "End of validation set", typeof(IntData), VariableKind.In));
40      AddVariableInfo(new VariableInfo("NumberOfHiddenLayerNeurons", "The number of nodes in the hidden layer.", typeof(IntData), VariableKind.In));
41      AddVariableInfo(new VariableInfo("MaxTimeOffset", "(optional) Maximal time offset for time-series prognosis", typeof(IntData), VariableKind.In));
42      AddVariableInfo(new VariableInfo("MinTimeOffset", "(optional) Minimal time offset for time-series prognosis", typeof(IntData), VariableKind.In));
43      AddVariableInfo(new VariableInfo("MultiLayerPerceptron", "Formula that was calculated by multi layer perceptron regression", typeof(MultiLayerPerceptron), VariableKind.Out | VariableKind.New));
44    }
45
46    public override IOperation Apply(IScope scope) {
47      Dataset dataset = GetVariableValue<Dataset>("Dataset", scope, true);
48      string targetVariable = GetVariableValue<StringData>("TargetVariable", scope, true).Data;
49      int targetVariableIndex = dataset.GetVariableIndex(targetVariable);
50      int start = GetVariableValue<IntData>("SamplesStart", scope, true).Data;
51      int end = GetVariableValue<IntData>("SamplesEnd", scope, true).Data;
52
53      int valStart = GetVariableValue<IntData>("ValidationSamplesStart", scope, true).Data;
54      int valEnd = GetVariableValue<IntData>("ValidationSamplesEnd", scope, true).Data;
55
56
57      IntData maxTimeOffsetData = GetVariableValue<IntData>("MaxTimeOffset", scope, true, false);
58      int maxTimeOffset = maxTimeOffsetData == null ? 0 : maxTimeOffsetData.Data;
59      IntData minTimeOffsetData = GetVariableValue<IntData>("MinTimeOffset", scope, true, false);
60      int minTimeOffset = minTimeOffsetData == null ? 0 : minTimeOffsetData.Data;
61      int nHiddenNodes = GetVariableValue<IntData>("NumberOfHiddenLayerNeurons", scope, true).Data;
62
63      var perceptron = CreateModel(dataset, targetVariable, dataset.VariableNames, start, end, valStart, valEnd, minTimeOffset, maxTimeOffset, nHiddenNodes);
64      scope.AddVariable(new HeuristicLab.Core.Variable(scope.TranslateName("MultiLayerPerceptron"), perceptron));
65      return null;
66    }
67
68    //public static MultiLayerPerceptron CreateModel(Dataset dataset, string targetVariable, IEnumerable<string> inputVariables, int start, int end, int nHiddenNodes) {
69    //  return CreateModel(dataset, targetVariable, inputVariables, start, end, 0, 0, nHiddenNodes);
70    //}
71
72    public static MultiLayerPerceptron CreateModel(Dataset dataset, string targetVariable, IEnumerable<string> inputVariables,
73        int start, int end, int valStart, int valEnd,
74        int minTimeOffset, int maxTimeOffset, int nHiddenNodes) {
75      double[,] inputMatrix;
76      double[,] validationData;
77      double[] targetVector;
78      double[] validationTargetVector;
79      PrepareDataset(dataset, targetVariable, inputVariables, start, end, minTimeOffset, maxTimeOffset, out inputMatrix, out targetVector);
80      PrepareDataset(dataset, targetVariable, inputVariables, valStart, valEnd, minTimeOffset, maxTimeOffset, out validationData, out validationTargetVector);
81      var perceptron = TrainPerceptron(inputMatrix, targetVector, nHiddenNodes, validationData, validationTargetVector);
82      return new MultiLayerPerceptron(perceptron, inputVariables, minTimeOffset, maxTimeOffset);
83    }
84
85
86
87    private static alglib.mlpbase.multilayerperceptron TrainPerceptron(double[,] inputMatrix, double[] targetVector, int nHiddenNodes, double[,] validationData, double[] validationTargetVector) {
88      int retVal = 0;
89      int n = targetVector.Length;
90      int validationN = validationTargetVector.Length;
91      int p = inputMatrix.GetLength(1);
92      alglib.mlpbase.multilayerperceptron perceptron = new alglib.mlpbase.multilayerperceptron();
93      alglib.mlpbase.mlpcreate1(p - 1, nHiddenNodes, 1, ref perceptron);
94      alglib.mlptrain.mlpreport report = new alglib.mlptrain.mlpreport();
95      double[,] dataset = new double[n, p];
96      for (int row = 0; row < n; row++) {
97        for (int column = 0; column < p - 1; column++) {
98          dataset[row, column] = inputMatrix[row, column];
99        }
100        dataset[row, p - 1] = targetVector[row];
101      }
102      double[,] validationDataset = new double[validationN, p];
103      for (int row = 0; row < validationN; row++) {
104        for (int column = 0; column < p - 1; column++) {
105          validationDataset[row, column] = validationData[row, column];
106        }
107        validationDataset[row, p - 1] = validationTargetVector[row];
108      }
109      //alglib.mlptrain.mlptrainlbfgs(ref perceptron, ref dataset, n, 0.001, 10, 0.01, 0, ref retVal, ref report);
110      alglib.mlptrain.mlptraines(ref perceptron, ref dataset, n, ref validationDataset, validationN, 0.001, 10, ref retVal, ref report);
111      if (retVal != 2 && retVal != 6) throw new ArgumentException("Error in training of multi layer perceptron");
112      return perceptron;
113    }
114
115    public static void PrepareDataset(Dataset dataset, string targetVariable, IEnumerable<string> inputVariables, int start, int end, int minTimeOffset, int maxTimeOffset,
116      out double[,] inputMatrix, out double[] targetVector) {
117      int targetVariableIndex = dataset.GetVariableIndex(targetVariable);
118      List<int> allowedColumns = CalculateAllowedColumns(dataset, targetVariableIndex, inputVariables.Select(x => dataset.GetVariableIndex(x)), start, end);
119      List<int> allowedRows = CalculateAllowedRows(dataset, targetVariableIndex, allowedColumns, start, end, minTimeOffset, maxTimeOffset);
120
121      inputMatrix = PrepareInputMatrix(dataset, allowedColumns, allowedRows, minTimeOffset, maxTimeOffset);
122      targetVector = PrepareTargetVector(dataset, targetVariableIndex, allowedRows);
123
124    }
125
126    //returns list of valid row indexes (rows without NaN values)
127    private static List<int> CalculateAllowedRows(Dataset dataset, int targetVariable, IList<int> allowedColumns, int start, int end, int minTimeOffset, int maxTimeOffset) {
128      List<int> allowedRows = new List<int>();
129      bool add;
130      for (int row = start; row < end; row++) {
131        add = true;
132        for (int colIndex = 0; colIndex < allowedColumns.Count && add == true; colIndex++) {
133          for (int timeOffset = minTimeOffset; timeOffset <= maxTimeOffset; timeOffset++) {
134            if (
135              row + timeOffset < 0 ||
136              row + timeOffset > dataset.Rows ||
137              double.IsNaN(dataset.GetValue(row + timeOffset, allowedColumns[colIndex])) ||
138              double.IsInfinity(dataset.GetValue(row + timeOffset, allowedColumns[colIndex])) ||
139              double.IsNaN(dataset.GetValue(row + timeOffset, targetVariable))) {
140              add = false;
141            }
142          }
143        }
144        if (add)
145          allowedRows.Add(row);
146        add = true;
147      }
148      return allowedRows;
149    }
150
151    //returns list of valid column indexes (columns which contain max. 10% NaN (or infinity) and contain at least two different values)
152    private static List<int> CalculateAllowedColumns(Dataset dataset, int targetVariable, IEnumerable<int> inputVariables, int start, int end) {
153      List<int> allowedColumns = new List<int>();
154      double n = end - start;
155      foreach (int inputVariable in inputVariables) {// = 0; i < dataset.Columns; i++) {
156        double nanRatio = dataset.CountMissingValues(inputVariable, start, end) / n;
157        if (inputVariable != targetVariable && nanRatio < 0.1 && dataset.GetRange(inputVariable, start, end) > 0.0) {
158          allowedColumns.Add(inputVariable);
159        }
160      }
161      return allowedColumns;
162    }
163
164    private static double[,] PrepareInputMatrix(Dataset dataset, List<int> allowedColumns, List<int> allowedRows, int minTimeOffset, int maxTimeOffset) {
165      int rowCount = allowedRows.Count;
166      int timeOffsetRange = (maxTimeOffset - minTimeOffset + 1);
167      double[,] matrix = new double[rowCount, (allowedColumns.Count * timeOffsetRange)];
168      for (int row = 0; row < allowedRows.Count; row++)
169        for (int col = 0; col < allowedColumns.Count; col++) {
170          for (int timeOffset = minTimeOffset; timeOffset <= maxTimeOffset; timeOffset++)
171            matrix[row, (col * timeOffsetRange) + (timeOffset - minTimeOffset)] = dataset.GetValue(allowedRows[row] + timeOffset, allowedColumns[col]);
172        }
173      return matrix;
174    }
175
176    private static double[] PrepareTargetVector(Dataset dataset, int targetVariable, List<int> allowedRows) {
177      int rowCount = allowedRows.Count;
178      double[] targetVector = new double[rowCount];
179      double[] samples = dataset.Samples;
180      for (int row = 0; row < rowCount; row++) {
181        targetVector[row] = dataset.GetValue(allowedRows[row], targetVariable);
182      }
183      return targetVector;
184    }
185  }
186}
Note: See TracBrowser for help on using the repository browser.