Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.GaussianProcessTuning/HeuristicLab.Algorithms.DataAnalysis.Experimental/EigenGaussianProcessModel.cs @ 10394

Last change on this file since 10394 was 9562, checked in by gkronber, 12 years ago

#1967 worked on Gaussian process evolution.

File size: 9.0 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2012 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 HeuristicLab.Common;
26using HeuristicLab.Core;
27using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
28using HeuristicLab.Problems.DataAnalysis;
29using HeuristicLabEigen;
30using ILNumerics;
31
32namespace HeuristicLab.Algorithms.DataAnalysis {
33  /// <summary>
34  /// Represents a Gaussian process model.
35  /// </summary>
36  [StorableClass]
37  [Item("EigenGaussianProcessModel", "Gaussian process model implemented using ILNumerics.")]
38  public sealed class EigenGaussianProcessModel : NamedItem, IGaussianProcessModel {
39    [Storable]
40    private double negativeLogLikelihood;
41    public double NegativeLogLikelihood {
42      get { return negativeLogLikelihood; }
43    }
44
45    [Storable]
46    private double[] hyperparameterGradients;
47    public double[] HyperparameterGradients {
48      get {
49        var copy = new double[hyperparameterGradients.Length];
50        Array.Copy(hyperparameterGradients, copy, copy.Length);
51        return copy;
52      }
53    }
54
55    [Storable]
56    private ICovarianceFunction covarianceFunction;
57    public ICovarianceFunction CovarianceFunction {
58      get { return covarianceFunction; }
59    }
60    [Storable]
61    private IMeanFunction meanFunction;
62    public IMeanFunction MeanFunction {
63      get { return meanFunction; }
64    }
65    [Storable]
66    private string targetVariable;
67    public string TargetVariable {
68      get { return targetVariable; }
69    }
70    [Storable]
71    private string[] allowedInputVariables;
72    public string[] AllowedInputVariables {
73      get { return allowedInputVariables; }
74    }
75
76
77    [Storable]
78    private double sqrSigmaNoise;
79    public double SigmaNoise {
80      get { return Math.Sqrt(sqrSigmaNoise); }
81    }
82
83    [Storable]
84    private double[] meanParameter;
85    [Storable]
86    private double[] covarianceParameter;
87
88
89    [StorableConstructor]
90    private EigenGaussianProcessModel(bool deserializing) : base(deserializing) { }
91    private EigenGaussianProcessModel(EigenGaussianProcessModel original, Cloner cloner)
92      : base(original, cloner) {
93      this.meanFunction = cloner.Clone(original.meanFunction);
94      this.covarianceFunction = cloner.Clone(original.covarianceFunction);
95      this.negativeLogLikelihood = original.negativeLogLikelihood;
96      this.targetVariable = original.targetVariable;
97      this.sqrSigmaNoise = original.sqrSigmaNoise;
98      if (original.meanParameter != null) {
99        this.meanParameter = (double[])original.meanParameter.Clone();
100      }
101      if (original.covarianceParameter != null) {
102        this.covarianceParameter = (double[])original.covarianceParameter.Clone();
103      }
104
105      // shallow copies of arrays because they cannot be modified
106      this.allowedInputVariables = original.allowedInputVariables;
107    }
108    public EigenGaussianProcessModel(Dataset ds, string targetVariable, IEnumerable<string> allowedInputVariables, IEnumerable<int> rows,
109      IEnumerable<double> hyp, IMeanFunction meanFunction, ICovarianceFunction covarianceFunction)
110      : base() {
111      this.name = ItemName;
112      this.description = ItemDescription;
113      this.meanFunction = (IMeanFunction)meanFunction.Clone();
114      this.covarianceFunction = (ICovarianceFunction)covarianceFunction.Clone();
115      this.targetVariable = targetVariable;
116      this.allowedInputVariables = allowedInputVariables.ToArray();
117
118
119      int nVariables = this.allowedInputVariables.Length;
120      meanParameter = hyp
121        .Take(this.meanFunction.GetNumberOfParameters(nVariables))
122        .ToArray();
123
124      covarianceParameter = hyp.Skip(this.meanFunction.GetNumberOfParameters(nVariables))
125                                             .Take(this.covarianceFunction.GetNumberOfParameters(nVariables))
126                                             .ToArray();
127      sqrSigmaNoise = Math.Exp(2.0 * hyp.Last());
128
129      CalculateModel(ds, rows);
130    }
131
132    private void CalculateModel(Dataset ds, IEnumerable<int> rows) {
133      var inputScaling = new Scaling(ds, allowedInputVariables, rows);
134      var x = AlglibUtil.PrepareAndScaleInputMatrix(ds, allowedInputVariables, rows, inputScaling);
135      var y = ds.GetDoubleValues(targetVariable, rows);
136
137      int n = x.GetLength(0);
138      var l = new double[n * n];
139
140      // calculate means and covariances
141      var mean = meanFunction.GetParameterizedMeanFunction(meanParameter, Enumerable.Range(0, x.GetLength(1)));
142      var cov = covarianceFunction.GetParameterizedCovarianceFunction(covarianceParameter, Enumerable.Range(0, x.GetLength(1)));
143      for (int i = 0; i < n; i++) {
144        for (int j = i; j < n; j++) {
145          l[j + i * n] = cov.Covariance(x, i, j) / sqrSigmaNoise;
146          if (j == i) l[j + i * n] += 1.0;
147        }
148      }
149
150
151      var myEigen = new MyEigen();
152      int info = 0;
153      var alpha = new double[n];
154
155      // solve for alpha
156      double[] ym = y.Zip(Enumerable.Range(0, x.GetLength(0)).Select(r => mean.Mean(x, r)), (a, b) => a - b).ToArray();
157      double[] invL = new double[n * n];
158      double nll;
159
160      unsafe {
161        fixed (double* ap = &alpha[0])
162        fixed (double* ymp = &ym[0])
163        fixed (double* invlP = &invL[0])
164        fixed (double* lp = &l[0]) {
165          myEigen.Solve(lp, ymp, ap, invlP, sqrSigmaNoise, n, &nll, &info);
166        }
167      }
168      if (info != 0) throw new ArgumentException("Matrix is not positive semidefinite");
169
170      this.negativeLogLikelihood = nll;
171
172      double noiseGradient = sqrSigmaNoise * Enumerable.Range(0, n).Select(i => invL[i + i * n]).Sum();
173
174      // derivatives
175      int nAllowedVariables = x.GetLength(1);
176
177      double[] meanGradients = new double[meanFunction.GetNumberOfParameters(nAllowedVariables)];
178      for (int k = 0; k < meanGradients.Length; k++) {
179        var meanGrad = Enumerable.Range(0, alpha.Length)
180        .Select(r => mean.Gradient(x, r, k));
181        meanGradients[k] = -Util.ScalarProd(meanGrad, alpha);
182      }
183
184      double[] covGradients = new double[covarianceFunction.GetNumberOfParameters(nAllowedVariables)];
185      if (covGradients.Length > 0) {
186        for (int i = 0; i < n; i++) {
187          for (int j = 0; j < i; j++) {
188            var g = cov.CovarianceGradient(x, i, j).ToArray();
189            for (int k = 0; k < covGradients.Length; k++) {
190              covGradients[k] += invL[j + i * n] * g[k];
191            }
192          }
193
194          var gDiag = cov.CovarianceGradient(x, i, i).ToArray();
195          for (int k = 0; k < covGradients.Length; k++) {
196            // diag
197            covGradients[k] += 0.5 * invL[i + i * n] * gDiag[k];
198          }
199        }
200      }
201
202      hyperparameterGradients =
203        meanGradients
204        .Concat(covGradients)
205        .Concat(new double[] { noiseGradient }).ToArray();
206
207    }
208
209
210    public override IDeepCloneable Clone(Cloner cloner) {
211      return new EigenGaussianProcessModel(this, cloner);
212    }
213
214    // is called by the solution creator to set all parameter values of the covariance and mean function
215    // to the optimized values (necessary to make the values visible in the GUI)
216    public void FixParameters() {
217      covarianceFunction.SetParameter(covarianceParameter);
218      meanFunction.SetParameter(meanParameter);
219      covarianceParameter = new double[0];
220      meanParameter = new double[0];
221    }
222
223    #region IRegressionModel Members
224    public IEnumerable<double> GetEstimatedValues(Dataset dataset, IEnumerable<int> rows) {
225      return GetEstimatedValuesHelper(dataset, rows);
226    }
227    public GaussianProcessRegressionSolution CreateRegressionSolution(IRegressionProblemData problemData) {
228      return new GaussianProcessRegressionSolution(this, new RegressionProblemData(problemData));
229    }
230    IRegressionSolution IRegressionModel.CreateRegressionSolution(IRegressionProblemData problemData) {
231      return CreateRegressionSolution(problemData);
232    }
233    #endregion
234
235
236    private IEnumerable<double> GetEstimatedValuesHelper(Dataset dataset, IEnumerable<int> rows) {
237
238      return rows.Select(r => 0.0);
239    }
240
241    public IEnumerable<double> GetEstimatedVariance(Dataset dataset, IEnumerable<int> rows) {
242      return rows.Select(r => sqrSigmaNoise);
243    }
244  }
245}
Note: See TracBrowser for help on using the repository browser.