Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2952_RF-ModelStorage/HeuristicLab.Algorithms.DataAnalysis/3.4/GaussianProcess/CovarianceFunctions/CovarianceSpectralMixture.cs @ 17187

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

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

File size: 10.3 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2019 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.Data;
28using HeuristicLab.Parameters;
29using HEAL.Attic;
30
31namespace HeuristicLab.Algorithms.DataAnalysis {
32  [StorableType("FF180FAF-851D-425E-AC0B-25930CE9604C")]
33  [Item(Name = "CovarianceSpectralMixture",
34    Description = "The spectral mixture kernel described in Wilson A. G. and Adams R.P., Gaussian Process Kernels for Pattern Discovery and Exptrapolation, ICML 2013.")]
35  public sealed class CovarianceSpectralMixture : ParameterizedNamedItem, ICovarianceFunction {
36    public const string QParameterName = "Number of components (Q)";
37    public const string WeightParameterName = "Weight";
38    public const string FrequencyParameterName = "Component frequency (mu)";
39    public const string LengthScaleParameterName = "Length scale (nu)";
40    public IValueParameter<IntValue> QParameter {
41      get { return (IValueParameter<IntValue>)Parameters[QParameterName]; }
42    }
43
44    public IValueParameter<DoubleArray> WeightParameter {
45      get { return (IValueParameter<DoubleArray>)Parameters[WeightParameterName]; }
46    }
47    public IValueParameter<DoubleArray> FrequencyParameter {
48      get { return (IValueParameter<DoubleArray>)Parameters[FrequencyParameterName]; }
49    }
50
51    public IValueParameter<DoubleArray> LengthScaleParameter {
52      get { return (IValueParameter<DoubleArray>)Parameters[LengthScaleParameterName]; }
53    }
54
55    private bool HasFixedWeightParameter {
56      get { return WeightParameter.Value != null; }
57    }
58    private bool HasFixedFrequencyParameter {
59      get { return FrequencyParameter.Value != null; }
60    }
61    private bool HasFixedLengthScaleParameter {
62      get { return LengthScaleParameter.Value != null; }
63    }
64
65    [StorableConstructor]
66    private CovarianceSpectralMixture(StorableConstructorFlag _) : base(_) {
67    }
68
69    private CovarianceSpectralMixture(CovarianceSpectralMixture original, Cloner cloner)
70      : base(original, cloner) {
71    }
72
73    public CovarianceSpectralMixture()
74      : base() {
75      Name = ItemName;
76      Description = ItemDescription;
77      Parameters.Add(new ValueParameter<IntValue>(QParameterName, "The number of Gaussians (Q) to use for the spectral mixture.", new IntValue(10)));
78      Parameters.Add(new OptionalValueParameter<DoubleArray>(WeightParameterName, "The weight of the component w (peak height of the Gaussian in spectrum)."));
79      Parameters.Add(new OptionalValueParameter<DoubleArray>(FrequencyParameterName, "The inverse component period parameter mu_q (location of the Gaussian in spectrum)."));
80      Parameters.Add(new OptionalValueParameter<DoubleArray>(LengthScaleParameterName, "The length scale parameter (nu_q) (variance of the Gaussian in the spectrum)."));
81    }
82
83    public override IDeepCloneable Clone(Cloner cloner) {
84      return new CovarianceSpectralMixture(this, cloner);
85    }
86
87    public int GetNumberOfParameters(int numberOfVariables) {
88      var q = QParameter.Value.Value;
89      return
90        (HasFixedWeightParameter ? 0 : q) +
91        (HasFixedFrequencyParameter ? 0 : q * numberOfVariables) +
92        (HasFixedLengthScaleParameter ? 0 : q * numberOfVariables);
93    }
94
95    public void SetParameter(double[] p) {
96      double[] weight, frequency, lengthScale;
97      GetParameterValues(p, out weight, out frequency, out lengthScale);
98      WeightParameter.Value = new DoubleArray(weight);
99      FrequencyParameter.Value = new DoubleArray(frequency);
100      LengthScaleParameter.Value = new DoubleArray(lengthScale);
101    }
102
103
104    private void GetParameterValues(double[] p, out double[] weight, out double[] frequency, out double[] lengthScale) {
105      // gather parameter values
106      int c = 0;
107      int q = QParameter.Value.Value;
108      // guess number of elements for frequency and length (=q * numberOfVariables)
109      int n = WeightParameter.Value == null ? ((p.Length - q) / 2) : (p.Length / 2);
110      if (HasFixedWeightParameter) {
111        weight = WeightParameter.Value.ToArray();
112      } else {
113        weight = p.Skip(c).Select(Math.Exp).Take(q).ToArray();
114        c += q;
115      }
116      if (HasFixedFrequencyParameter) {
117        frequency = FrequencyParameter.Value.ToArray();
118      } else {
119        frequency = p.Skip(c).Select(Math.Exp).Take(n).ToArray();
120        c += n;
121      }
122      if (HasFixedLengthScaleParameter) {
123        lengthScale = LengthScaleParameter.Value.ToArray();
124      } else {
125        lengthScale = p.Skip(c).Select(Math.Exp).Take(n).ToArray();
126        c += n;
127      }
128      if (p.Length != c) throw new ArgumentException("The length of the parameter vector does not match the number of free parameters for CovarianceSpectralMixture", "p");
129    }
130
131    public ParameterizedCovarianceFunction GetParameterizedCovarianceFunction(double[] p, int[] columnIndices) {
132      double[] weight, frequency, lengthScale;
133      GetParameterValues(p, out weight, out frequency, out lengthScale);
134      var fixedWeight = HasFixedWeightParameter;
135      var fixedFrequency = HasFixedFrequencyParameter;
136      var fixedLengthScale = HasFixedLengthScaleParameter;
137      // create functions
138      var cov = new ParameterizedCovarianceFunction();
139      cov.Covariance = (x, i, j) => {
140        return GetCovariance(x, x, i, j, QParameter.Value.Value, weight, frequency,
141                             lengthScale, columnIndices);
142      };
143      cov.CrossCovariance = (x, xt, i, j) => {
144        return GetCovariance(x, xt, i, j, QParameter.Value.Value, weight, frequency,
145                             lengthScale, columnIndices);
146      };
147      cov.CovarianceGradient = (x, i, j) => GetGradient(x, i, j, QParameter.Value.Value, weight, frequency,
148                             lengthScale, columnIndices, fixedWeight, fixedFrequency, fixedLengthScale);
149      return cov;
150    }
151
152    private static double GetCovariance(double[,] x, double[,] xt, int i, int j, int maxQ, double[] weight, double[] frequency, double[] lengthScale, int[] columnIndices) {
153      // tau = x - x' (only for selected variables)
154      double[] tau =
155        Util.GetRow(x, i, columnIndices).Zip(Util.GetRow(xt, j, columnIndices), (xi, xj) => xi - xj).ToArray();
156      int numberOfVariables = lengthScale.Length / maxQ;
157      double k = 0;
158      // for each component
159      for (int q = 0; q < maxQ; q++) {
160        double kc = weight[q]; // weighted kernel component
161
162        int idx = 0; // helper index for tau
163        // for each selected variable
164        for (int c = 0; c < columnIndices.Length; c++) {
165          var col = columnIndices[c];
166          kc *= f1(tau[idx], lengthScale[q * numberOfVariables + col]) * f2(tau[idx], frequency[q * numberOfVariables + col]);
167          idx++;
168        }
169        k += kc;
170      }
171      return k;
172    }
173
174    public static double f1(double tau, double lengthScale) {
175      return Math.Exp(-2 * Math.PI * Math.PI * tau * tau * lengthScale);
176    }
177    public static double f2(double tau, double frequency) {
178      return Math.Cos(2 * Math.PI * tau * frequency);
179    }
180
181    // order of returned gradients must match the order in GetParameterValues!
182    private static IList<double> GetGradient(double[,] x, int i, int j, int maxQ, double[] weight, double[] frequency, double[] lengthScale, int[] columnIndices,
183      bool fixedWeight, bool fixedFrequency, bool fixedLengthScale) {
184      double[] tau = Util.GetRow(x, i, columnIndices).Zip(Util.GetRow(x, j, columnIndices), (xi, xj) => xi - xj).ToArray();
185      int numberOfVariables = lengthScale.Length / maxQ;
186
187      var g = new List<double>((!fixedWeight ? maxQ : 0) + (!fixedFrequency ? maxQ * columnIndices.Length : 0) + (!fixedLengthScale ? maxQ * columnIndices.Length : 0));
188      if (!fixedWeight) {
189        // weight
190        // for each component
191        for (int q = 0; q < maxQ; q++) {
192          double k = weight[q];
193          int idx = 0; // helper index for tau
194          // for each selected variable
195          for (int c = 0; c < columnIndices.Length; c++) {
196            var col = columnIndices[c];
197            k *= f1(tau[idx], lengthScale[q * numberOfVariables + col]) * f2(tau[idx], frequency[q * numberOfVariables + col]);
198            idx++;
199          }
200          g.Add(k);
201        }
202      }
203
204      if (!fixedFrequency) {
205        // frequency
206        // for each component
207        for (int q = 0; q < maxQ; q++) {
208          int idx = 0; // helper index for tau
209          // for each selected variable
210          foreach (var c in columnIndices) {
211            double k = f1(tau[idx], lengthScale[q * numberOfVariables + c]) *
212                       -2 * Math.PI * tau[idx] * frequency[q * numberOfVariables + c] *
213                       Math.Sin(2 * Math.PI * tau[idx] * frequency[q * numberOfVariables + c]);
214            idx++;
215            g.Add(weight[q] * k);
216          }
217        }
218      }
219
220      if (!fixedLengthScale) {
221        // length scale
222        // for each component
223        for (int q = 0; q < maxQ; q++) {
224          int idx = 0; // helper index for tau
225          // for each selected variable
226          foreach (var c in columnIndices) {
227            double k = -2 * Math.PI * Math.PI * tau[idx] * tau[idx] * lengthScale[q * numberOfVariables + c] *
228                       f1(tau[idx], lengthScale[q * numberOfVariables + c]) *
229                       f2(tau[idx], frequency[q * numberOfVariables + c]);
230            idx++;
231            g.Add(weight[q] * k);
232          }
233        }
234      }
235
236      return g;
237    }
238  }
239}
Note: See TracBrowser for help on using the repository browser.