Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.GaussianProcessTuning/HeuristicLab.Algorithms.DataAnalysis.Experimental/ToeplitzGaussianProcessModel.cs @ 10792

Last change on this file since 10792 was 10792, checked in by gkronber, 10 years ago

worked on a GP model for time series using toeplitz structure

File size: 12.4 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 System.Runtime.InteropServices;
26using HeuristicLab.Common;
27using HeuristicLab.Core;
28using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
29using HeuristicLab.Problems.DataAnalysis;
30using HeuristicLabEigen;
31using ILNumerics;
32
33namespace HeuristicLab.Algorithms.DataAnalysis {
34  /// <summary>
35  /// Represents a Gaussian process model.
36  /// </summary>
37  [StorableClass]
38  [Item("ToeplitzGaussianProcessModel", "Gaussian process model implemented using ILNumerics.")]
39  public sealed class ToeplitzGaussianProcessModel : NamedItem, IGaussianProcessModel {
40
41    [DllImport("toeplitz.dll", CallingConvention = CallingConvention.Cdecl)]
42    public static extern void r4to_sl_(ref int n, float[] a, float[] x, float[] b, ref int job);
43
44
45
46    [Storable]
47    private double negativeLogLikelihood;
48    public double NegativeLogLikelihood {
49      get { return negativeLogLikelihood; }
50    }
51
52    [Storable]
53    private double[] hyperparameterGradients;
54    public double[] HyperparameterGradients {
55      get {
56        var copy = new double[hyperparameterGradients.Length];
57        Array.Copy(hyperparameterGradients, copy, copy.Length);
58        return copy;
59      }
60    }
61
62    [Storable]
63    private ICovarianceFunction covarianceFunction;
64    public ICovarianceFunction CovarianceFunction {
65      get { return covarianceFunction; }
66    }
67    [Storable]
68    private IMeanFunction meanFunction;
69    public IMeanFunction MeanFunction {
70      get { return meanFunction; }
71    }
72    [Storable]
73    private string targetVariable;
74    public string TargetVariable {
75      get { return targetVariable; }
76    }
77    [Storable]
78    private string[] allowedInputVariables;
79    public string[] AllowedInputVariables {
80      get { return allowedInputVariables; }
81    }
82
83
84    [Storable]
85    private double sqrSigmaNoise;
86    public double SigmaNoise {
87      get { return Math.Sqrt(sqrSigmaNoise); }
88    }
89
90    [Storable]
91    private double[] meanParameter;
92    [Storable]
93    private double[] covarianceParameter;
94    [Storable]
95    private float[] alpha;
96
97
98    [Storable]
99    private double[,] x;
100    [Storable]
101    private Scaling inputScaling;
102
103    [StorableConstructor]
104    private ToeplitzGaussianProcessModel(bool deserializing) : base(deserializing) { }
105    private ToeplitzGaussianProcessModel(ToeplitzGaussianProcessModel original, Cloner cloner)
106      : base(original, cloner) {
107      this.meanFunction = cloner.Clone(original.meanFunction);
108      this.covarianceFunction = cloner.Clone(original.covarianceFunction);
109      this.inputScaling = cloner.Clone(original.inputScaling);
110      this.negativeLogLikelihood = original.negativeLogLikelihood;
111      this.targetVariable = original.targetVariable;
112      this.sqrSigmaNoise = original.sqrSigmaNoise;
113      if (original.meanParameter != null) {
114        this.meanParameter = (double[])original.meanParameter.Clone();
115      }
116      if (original.covarianceParameter != null) {
117        this.covarianceParameter = (double[])original.covarianceParameter.Clone();
118      }
119
120      // shallow copies of arrays because they cannot be modified
121      this.allowedInputVariables = original.allowedInputVariables;
122      this.alpha = original.alpha;
123      this.x = original.x;
124    }
125    public ToeplitzGaussianProcessModel(Dataset ds, string targetVariable, IEnumerable<string> allowedInputVariables, IEnumerable<int> rows,
126      IEnumerable<double> hyp, IMeanFunction meanFunction, ICovarianceFunction covarianceFunction)
127      : base() {
128      this.name = ItemName;
129      this.description = ItemDescription;
130      this.meanFunction = (IMeanFunction)meanFunction.Clone();
131      this.covarianceFunction = (ICovarianceFunction)covarianceFunction.Clone();
132      this.targetVariable = targetVariable;
133      this.allowedInputVariables = allowedInputVariables.ToArray();
134
135
136      int nVariables = this.allowedInputVariables.Length;
137      meanParameter = hyp
138        .Take(this.meanFunction.GetNumberOfParameters(nVariables))
139        .ToArray();
140
141      covarianceParameter = hyp.Skip(this.meanFunction.GetNumberOfParameters(nVariables))
142                                             .Take(this.covarianceFunction.GetNumberOfParameters(nVariables))
143                                             .ToArray();
144      sqrSigmaNoise = Math.Exp(2.0 * hyp.Last());
145
146      CalculateModel(ds, rows);
147    }
148
149    private void CalculateModel(Dataset ds, IEnumerable<int> rows) {
150      inputScaling = new Scaling(ds, allowedInputVariables, rows);
151      x = AlglibUtil.PrepareAndScaleInputMatrix(ds, allowedInputVariables, rows, inputScaling);
152      var y = ds.GetDoubleValues(targetVariable, rows);
153
154      int n = x.GetLength(0);
155      var l = new float[2 * n - 1];
156
157      // calculate means and covariances
158      var mean = meanFunction.GetParameterizedMeanFunction(meanParameter, Enumerable.Range(0, x.GetLength(1)));
159      var cov = covarianceFunction.GetParameterizedCovarianceFunction(covarianceParameter, Enumerable.Range(0, x.GetLength(1)));
160      var l0 = (float)(cov.Covariance(x, 0, 0) / sqrSigmaNoise + 1.0);
161      l[0] = 1.0f;
162      for (int i = 1; i < n; i++) {
163        l[i] = (float)((cov.Covariance(x, 0, i) / sqrSigmaNoise)/ l0);
164      }
165      for (int i = n; i < 2 * n - 1; i++) {
166        l[i] = (float)((cov.Covariance(x, i - n + 1, 0) / sqrSigmaNoise) / l0);
167      }
168
169
170      int info = 0;
171      alpha = new float[n];
172
173      // solve for alpha
174      float[] ym = y.Zip(Enumerable.Range(0, x.GetLength(0)).Select(r => mean.Mean(x, r)), (a, b) => a - b)
175        .Select(e => (float)e)
176        .ToArray();
177      double nll;
178
179      //unsafe {
180      //  fixed (double* ap = &alpha[0])
181      //  fixed (double* ymp = &ym[0])
182      //  fixed (double* invlP = &invL[0])
183      //  fixed (double* lp = &l[0]) {
184      //    myEigen.Solve(lp, ymp, ap, invlP, sqrSigmaNoise, n, &nll, &info);
185      //  }
186      //}
187      int job = 0;
188      r4to_sl_(ref n, l, ym, alpha, ref job);
189      alpha = alpha.Select(a => (float)(a / sqrSigmaNoise / l0)).ToArray();
190
191
192      var yDotAlpha = ym.Zip(alpha, (f, f1) => f * f1).Sum();
193
194      var lambda = toeplitz_cholesky_diag(n, l);
195      var logDetK = 2 * lambda.Sum(f => Math.Log(f * Math.Sqrt(l0)));
196
197
198      this.negativeLogLikelihood = 0.5 * yDotAlpha + 0.5 * logDetK + n / 2.0 * Math.Log(2.0 * Math.PI * sqrSigmaNoise);
199
200      //double noiseGradient = sqrSigmaNoise * Enumerable.Range(0, n).Select(i => invL[i + i * n]).Sum();
201
202      // derivatives
203      int nAllowedVariables = x.GetLength(1);
204      //
205      //double[] meanGradients = new double[meanFunction.GetNumberOfParameters(nAllowedVariables)];
206      //for (int k = 0; k < meanGradients.Length; k++) {
207      //  var meanGrad = Enumerable.Range(0, alpha.Length)
208      //  .Select(r => mean.Gradient(x, r, k));
209      //  meanGradients[k] = -meanGrad.Zip(alpha, (d1, f) => d1 * f).Sum();
210      //}
211      //
212      //double[] covGradients = new double[covarianceFunction.GetNumberOfParameters(nAllowedVariables)];
213      //if (covGradients.Length > 0) {
214      //  for (int i = 0; i < n; i++) {
215      //    for (int j = 0; j < i; j++) {
216      //      var g = cov.CovarianceGradient(x, i, j).ToArray();
217      //      for (int k = 0; k < covGradients.Length; k++) {
218      //        covGradients[k] += invL[j + i * n] * g[k];
219      //      }
220      //    }
221      //
222      //    var gDiag = cov.CovarianceGradient(x, i, i).ToArray();
223      //    for (int k = 0; k < covGradients.Length; k++) {
224      //      // diag
225      //      covGradients[k] += 0.5 * invL[i + i * n] * gDiag[k];
226      //    }
227      //  }
228      //}
229      //
230      hyperparameterGradients =
231        Enumerable.Repeat(0.0,
232                          meanFunction.GetNumberOfParameters(nAllowedVariables) +
233                          covarianceFunction.GetNumberOfParameters(nAllowedVariables) + 1).ToArray();
234      //hyperparameterGradients =
235      //  meanGradients
236      //  .Concat(covGradients)
237      //  .Concat(new double[] { noiseGradient }).ToArray();
238
239    }
240
241    public static double[] toeplitz_cholesky_diag(int n, float[] a) {
242      double div;
243      double[] g;
244      double g1j;
245      double g2j;
246      int i;
247      int j;
248      double[] l;
249      double rho;
250
251      l = new double[n];
252
253
254      g = new double[2 * n];
255
256      for (j = 0; j < n; j++) {
257        g[0 + j * 2] = a[j];
258      }
259      g[1 + 0 * 2] = 0.0;
260      for (j = 1; j < n; j++) {
261        g[1 + j * 2] = a[j + n - 1];
262      }
263
264      l[0] = g[0];
265      //for (i = 0; i < n; i++) {
266      //  l[i, 0] = g[0 + i * 2];
267      //}
268      for (j = n - 1; 1 <= j; j--) {
269        g[0 + j * 2] = g[0 + (j - 1) * 2];
270      }
271      g[0 + 0 * 2] = 0.0;
272
273      for (i = 1; i < n; i++) {
274        rho = -g[1 + i * 2] / g[0 + i * 2];
275        div = Math.Sqrt((1.0 - rho) * (1.0 + rho));
276
277        for (j = i; j < n; j++) {
278          g1j = g[0 + j * 2];
279          g2j = g[1 + j * 2];
280          g[0 + j * 2] = (g1j + rho * g2j) / div;
281          g[1 + j * 2] = (rho * g1j + g2j) / div;
282        }
283
284        l[i] = g[i * 2];
285        //for (j = i; j < n; j++) {
286        //  l[j, i] = g[0 + j * 2];
287        //}
288        for (j = n - 1; i < j; j--) {
289          g[0 + j * 2] = g[0 + (j - 1) * 2];
290        }
291        g[0 + i * 2] = 0.0;
292      }
293
294
295      return l;
296    }
297
298    public override IDeepCloneable Clone(Cloner cloner) {
299      return new ToeplitzGaussianProcessModel(this, cloner);
300    }
301
302    // is called by the solution creator to set all parameter values of the covariance and mean function
303    // to the optimized values (necessary to make the values visible in the GUI)
304    public void FixParameters() {
305      covarianceFunction.SetParameter(covarianceParameter);
306      meanFunction.SetParameter(meanParameter);
307      covarianceParameter = new double[0];
308      meanParameter = new double[0];
309    }
310
311    #region IRegressionModel Members
312    public IEnumerable<double> GetEstimatedValues(Dataset dataset, IEnumerable<int> rows) {
313      return GetEstimatedValuesHelper(dataset, rows);
314    }
315    public GaussianProcessRegressionSolution CreateRegressionSolution(IRegressionProblemData problemData) {
316      return new GaussianProcessRegressionSolution(this, new RegressionProblemData(problemData));
317    }
318    IRegressionSolution IRegressionModel.CreateRegressionSolution(IRegressionProblemData problemData) {
319      return CreateRegressionSolution(problemData);
320    }
321    #endregion
322
323
324    private IEnumerable<double> GetEstimatedValuesHelper(Dataset dataset, IEnumerable<int> rows) {
325
326      var newX = AlglibUtil.PrepareAndScaleInputMatrix(dataset, allowedInputVariables, rows, inputScaling);
327      int newN = newX.GetLength(0);
328      int n = x.GetLength(0);
329      var Ks = new double[newN, n];
330      var mean = meanFunction.GetParameterizedMeanFunction(meanParameter, Enumerable.Range(0, newX.GetLength(1)));
331      var ms = Enumerable.Range(0, newX.GetLength(0))
332      .Select(r => mean.Mean(newX, r))
333      .ToArray();
334      var cov = covarianceFunction.GetParameterizedCovarianceFunction(covarianceParameter, Enumerable.Range(0, x.GetLength(1)));
335      for (int i = 0; i < newN; i++) {
336        for (int j = 0; j < n; j++) {
337          Ks[i, j] = cov.CrossCovariance(x, newX, j, i);
338        }
339      }
340
341      return Enumerable.Range(0, newN)
342        .Select(i => ms[i] + Util.ScalarProd(Util.GetRow(Ks, i), alpha.Select(a=>(double)a)));
343    }
344
345    public IEnumerable<double> GetEstimatedVariance(Dataset dataset, IEnumerable<int> rows) {
346      return rows.Select(r => sqrSigmaNoise);
347    }
348  }
349}
Note: See TracBrowser for help on using the repository browser.