Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkModel.cs @ 18122

Last change on this file since 18122 was 17931, checked in by gkronber, 4 years ago

#3117: update alglib to version 3.17

File size: 6.5 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 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
22extern alias alglib_3_7;
23using System;
24using System.Collections.Generic;
25using System.Linq;
26using HeuristicLab.Common;
27using HeuristicLab.Core;
28using HEAL.Attic;
29using HeuristicLab.Problems.DataAnalysis;
30
31namespace HeuristicLab.Algorithms.DataAnalysis {
32  /// <summary>
33  /// Represents a neural network model for regression and classification
34  /// </summary>
35  [StorableType("DABDBD64-E93B-4F50-A343-C8A92C1C48A4")]
36  [Item("NeuralNetworkModel", "Represents a neural network for regression and classification.")]
37  public sealed class NeuralNetworkModel : ClassificationModel, INeuralNetworkModel {
38
39    private object mlpLocker = new object();
40
41
42
43    private alglib.multilayerperceptron multiLayerPerceptron;
44    [Storable]
45    private string SerializedMultiLayerPerceptron {
46      get { alglib.mlpserialize(multiLayerPerceptron, out var ser); return ser; }
47      set { if (value != null) alglib.mlpunserialize(value, out multiLayerPerceptron); }
48    }
49
50    public override IEnumerable<string> VariablesUsedForPrediction {
51      get { return allowedInputVariables; }
52    }
53
54    [Storable]
55    private string[] allowedInputVariables;
56    [Storable]
57    private double[] classValues;
58    [StorableConstructor]
59    private NeuralNetworkModel(StorableConstructorFlag _) : base(_) { }
60    private NeuralNetworkModel(NeuralNetworkModel original, Cloner cloner)
61      : base(original, cloner) {
62      if (original.multiLayerPerceptron != null)
63        multiLayerPerceptron = (alglib.multilayerperceptron)original.multiLayerPerceptron.make_copy();
64      allowedInputVariables = (string[])original.allowedInputVariables.Clone();
65      if (original.classValues != null)
66        this.classValues = (double[])original.classValues.Clone();
67    }
68    public NeuralNetworkModel(alglib.multilayerperceptron multiLayerPerceptron, string targetVariable, IEnumerable<string> allowedInputVariables, double[] classValues = null)
69      : base(targetVariable) {
70      this.name = ItemName;
71      this.description = ItemDescription;
72      this.multiLayerPerceptron = (alglib.multilayerperceptron)multiLayerPerceptron.make_copy();
73      this.allowedInputVariables = allowedInputVariables.ToArray();
74      if (classValues != null)
75        this.classValues = (double[])classValues.Clone();
76    }
77
78    public override IDeepCloneable Clone(Cloner cloner) {
79      return new NeuralNetworkModel(this, cloner);
80    }
81
82    public IEnumerable<double> GetEstimatedValues(IDataset dataset, IEnumerable<int> rows) {
83      double[,] inputData = dataset.ToArray(allowedInputVariables, rows);
84
85      int n = inputData.GetLength(0);
86      int columns = inputData.GetLength(1);
87      double[] x = new double[columns];
88      double[] y = new double[1];
89
90      for (int row = 0; row < n; row++) {
91        for (int column = 0; column < columns; column++) {
92          x[column] = inputData[row, column];
93        }
94        // NOTE: mlpprocess changes data in multiLayerPerceptron and is therefore not thread-safe!
95        lock (mlpLocker) {
96          alglib.mlpprocess(multiLayerPerceptron, x, ref y);
97        }
98        yield return y[0];
99      }
100    }
101
102    public override IEnumerable<double> GetEstimatedClassValues(IDataset dataset, IEnumerable<int> rows) {
103      double[,] inputData = dataset.ToArray(allowedInputVariables, rows);
104
105      int n = inputData.GetLength(0);
106      int columns = inputData.GetLength(1);
107      double[] x = new double[columns];
108      double[] y = new double[classValues.Length];
109
110      for (int row = 0; row < n; row++) {
111        for (int column = 0; column < columns; column++) {
112          x[column] = inputData[row, column];
113        }
114        // NOTE: mlpprocess changes data in multiLayerPerceptron and is therefore not thread-safe!
115        lock (mlpLocker) {
116          alglib.mlpprocess(multiLayerPerceptron, x, ref y);
117        }
118        // find class for with the largest probability value
119        int maxProbClassIndex = 0;
120        double maxProb = y[0];
121        for (int i = 1; i < y.Length; i++) {
122          if (maxProb < y[i]) {
123            maxProb = y[i];
124            maxProbClassIndex = i;
125          }
126        }
127        yield return classValues[maxProbClassIndex];
128      }
129    }
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 compatible with this neural network. Instead a " + problemData.GetType().GetPrettyName() + " was provided.", "problemData");
147    }
148
149    public IRegressionSolution CreateRegressionSolution(IRegressionProblemData problemData) {
150      return new NeuralNetworkRegressionSolution(this, new RegressionProblemData(problemData));
151    }
152    public override IClassificationSolution CreateClassificationSolution(IClassificationProblemData problemData) {
153      return new NeuralNetworkClassificationSolution(this, new ClassificationProblemData(problemData));
154    }
155  }
156}
Note: See TracBrowser for help on using the repository browser.