Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkEnsembleModel.cs @ 15739

Last change on this file since 15739 was 15739, checked in by gkronber, 6 years ago

#2891: fixed bug in NN and NN ensemble using a simple lock for processing an input.

File size: 8.3 KB
RevLine 
[6577]1#region License Information
2/* HeuristicLab
[15583]3 * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
[6577]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 HeuristicLab.Common;
26using HeuristicLab.Core;
27using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
28using HeuristicLab.Problems.DataAnalysis;
29
30namespace HeuristicLab.Algorithms.DataAnalysis {
31  /// <summary>
[6580]32  /// Represents a neural network ensembel model for regression and classification
[6577]33  /// </summary>
34  [StorableClass]
[6580]35  [Item("NeuralNetworkEnsembleModel", "Represents a neural network ensemble for regression and classification.")]
[13941]36  public sealed class NeuralNetworkEnsembleModel : ClassificationModel, INeuralNetworkEnsembleModel {
[6577]37
[6580]38    private alglib.mlpensemble mlpEnsemble;
39    public alglib.mlpensemble MultiLayerPerceptronEnsemble {
40      get { return mlpEnsemble; }
[6577]41      set {
[6580]42        if (value != mlpEnsemble) {
[6577]43          if (value == null) throw new ArgumentNullException();
[6580]44          mlpEnsemble = value;
[6577]45          OnChanged(EventArgs.Empty);
46        }
47      }
48    }
49
[13941]50    public override IEnumerable<string> VariablesUsedForPrediction {
[13921]51      get { return allowedInputVariables; }
52    }
53
[6577]54    [Storable]
55    private string targetVariable;
56    [Storable]
57    private string[] allowedInputVariables;
58    [Storable]
59    private double[] classValues;
60    [StorableConstructor]
[6580]61    private NeuralNetworkEnsembleModel(bool deserializing)
[6577]62      : base(deserializing) {
63      if (deserializing)
[6580]64        mlpEnsemble = new alglib.mlpensemble();
[6577]65    }
[6580]66    private NeuralNetworkEnsembleModel(NeuralNetworkEnsembleModel original, Cloner cloner)
[6577]67      : base(original, cloner) {
[6580]68      mlpEnsemble = new alglib.mlpensemble();
[7694]69      string serializedEnsemble;
70      alglib.mlpeserialize(original.mlpEnsemble, out serializedEnsemble);
71      alglib.mlpeunserialize(serializedEnsemble, out this.mlpEnsemble);
[6577]72      targetVariable = original.targetVariable;
73      allowedInputVariables = (string[])original.allowedInputVariables.Clone();
74      if (original.classValues != null)
75        this.classValues = (double[])original.classValues.Clone();
76    }
[6580]77    public NeuralNetworkEnsembleModel(alglib.mlpensemble mlpEnsemble, string targetVariable, IEnumerable<string> allowedInputVariables, double[] classValues = null)
[13941]78      : base(targetVariable) {
[6577]79      this.name = ItemName;
80      this.description = ItemDescription;
[6580]81      this.mlpEnsemble = mlpEnsemble;
[6577]82      this.targetVariable = targetVariable;
83      this.allowedInputVariables = allowedInputVariables.ToArray();
84      if (classValues != null)
85        this.classValues = (double[])classValues.Clone();
86    }
87
88    public override IDeepCloneable Clone(Cloner cloner) {
[6580]89      return new NeuralNetworkEnsembleModel(this, cloner);
[6577]90    }
91
[12509]92    public IEnumerable<double> GetEstimatedValues(IDataset dataset, IEnumerable<int> rows) {
[14843]93      double[,] inputData = dataset.ToArray(allowedInputVariables, rows);
[6577]94
95      int n = inputData.GetLength(0);
96      int columns = inputData.GetLength(1);
97      double[] x = new double[columns];
98      double[] y = new double[1];
99
100      for (int row = 0; row < n; row++) {
101        for (int column = 0; column < columns; column++) {
102          x[column] = inputData[row, column];
103        }
[15739]104        // mlpeprocess writes data in mlpEnsemble and is therefore not thread-safe
105        lock (mlpEnsemble) {
106          alglib.mlpeprocess(mlpEnsemble, x, ref y);
107        }
[6577]108        yield return y[0];
109      }
110    }
111
[13941]112    public override IEnumerable<double> GetEstimatedClassValues(IDataset dataset, IEnumerable<int> rows) {
[14843]113      double[,] inputData = dataset.ToArray(allowedInputVariables, rows);
[6577]114
115      int n = inputData.GetLength(0);
116      int columns = inputData.GetLength(1);
117      double[] x = new double[columns];
118      double[] y = new double[classValues.Length];
119
120      for (int row = 0; row < n; row++) {
121        for (int column = 0; column < columns; column++) {
122          x[column] = inputData[row, column];
123        }
[15739]124        // mlpeprocess writes data in mlpEnsemble and is therefore not thread-safe
125        lock (mlpEnsemble) {
126          alglib.mlpeprocess(mlpEnsemble, x, ref y);
127        }
[6577]128        // find class for with the largest probability value
129        int maxProbClassIndex = 0;
130        double maxProb = y[0];
131        for (int i = 1; i < y.Length; i++) {
132          if (maxProb < y[i]) {
133            maxProb = y[i];
134            maxProbClassIndex = i;
135          }
136        }
137        yield return classValues[maxProbClassIndex];
138      }
139    }
140
[13941]141    public IRegressionSolution CreateRegressionSolution(IRegressionProblemData problemData) {
142      return new NeuralNetworkEnsembleRegressionSolution(this, new RegressionEnsembleProblemData(problemData));
[6603]143    }
[13941]144    public override IClassificationSolution CreateClassificationSolution(IClassificationProblemData problemData) {
145      return new NeuralNetworkEnsembleClassificationSolution(this, new ClassificationEnsembleProblemData(problemData));
[6603]146    }
147
[6577]148    #region events
149    public event EventHandler Changed;
150    private void OnChanged(EventArgs e) {
151      var handlers = Changed;
152      if (handlers != null)
153        handlers(this, e);
154    }
155    #endregion
156
157    #region persistence
158    [Storable]
[7694]159    private string MultiLayerPerceptronEnsembleNetwork {
[6577]160      get {
[7694]161        string serializedNetwork;
162        alglib.mlpeserialize(this.mlpEnsemble, out serializedNetwork);
163        return serializedNetwork;
[6577]164      }
165      set {
[7694]166        alglib.mlpeunserialize(value, out this.mlpEnsemble);
167      }
168    }
169
170    [Storable]
171    private double[] MultiLayerPerceptronEnsembleColumnMeans {
172      get { return mlpEnsemble.innerobj.columnmeans; }
173      set {
[6580]174        mlpEnsemble.innerobj.columnmeans = value;
[7694]175        mlpEnsemble.innerobj.network.columnmeans = value;
[6577]176      }
177    }
178    [Storable]
[6580]179    private double[] MultiLayerPerceptronEnsembleColumnSigmas {
[7694]180      get { return mlpEnsemble.innerobj.columnsigmas; }
[6577]181      set {
[6580]182        mlpEnsemble.innerobj.columnsigmas = value;
[7694]183        mlpEnsemble.innerobj.network.columnsigmas = value;
[6577]184      }
185    }
[7694]186    [Storable(AllowOneWay = true)]
[6580]187    private double[] MultiLayerPerceptronEnsembleDfdnet {
[6577]188      set {
[7694]189        mlpEnsemble.innerobj.network.dfdnet = value;
[6577]190      }
191    }
192    [Storable]
[6580]193    private int MultiLayerPerceptronEnsembleSize {
[7694]194      get { return mlpEnsemble.innerobj.ensemblesize; }
[6577]195      set {
[6580]196        mlpEnsemble.innerobj.ensemblesize = value;
[7694]197        mlpEnsemble.innerobj.ensemblesize = value;
[6577]198      }
199    }
[7694]200    [Storable(AllowOneWay = true)]
[6580]201    private double[] MultiLayerPerceptronEnsembleNeurons {
[7694]202      set { mlpEnsemble.innerobj.network.neurons = value; }
[6577]203    }
[7694]204    [Storable(AllowOneWay = true)]
[6580]205    private double[] MultiLayerPerceptronEnsembleSerializedMlp {
206      set {
[7694]207        mlpEnsemble.innerobj.network.dfdnet = value;
[6580]208      }
209    }
[7694]210    [Storable(AllowOneWay = true)]
[6577]211    private int[] MultiLayerPerceptronStuctinfo {
212      set {
[7694]213        mlpEnsemble.innerobj.network.structinfo = value;
[6577]214      }
215    }
[6580]216
217    [Storable]
218    private double[] MultiLayerPerceptronWeights {
219      get {
220        return mlpEnsemble.innerobj.weights;
221      }
222      set {
223        mlpEnsemble.innerobj.weights = value;
[7694]224        mlpEnsemble.innerobj.network.weights = value;
[6580]225      }
226    }
227    [Storable]
[6577]228    private double[] MultiLayerPerceptronY {
229      get {
[6580]230        return mlpEnsemble.innerobj.y;
[6577]231      }
232      set {
[6580]233        mlpEnsemble.innerobj.y = value;
[7694]234        mlpEnsemble.innerobj.network.y = value;
[6577]235      }
236    }
237    #endregion
238  }
239}
Note: See TracBrowser for help on using the repository browser.