Free cookie consent management tool by TermsFeed Policy Generator

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

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

#2520: merged changes from PersistenceOverhaul branch (r16451:16564) into trunk

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