sgptools 1.2.0__py3-none-any.whl → 2.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
sgptools/models/bo.py DELETED
@@ -1,118 +0,0 @@
1
- # Copyright 2024 The SGP-Tools Contributors. All Rights Reserved.
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License");
4
- # you may not use this file except in compliance with the License.
5
- # You may obtain a copy of the License at
6
- #
7
- # http://www.apache.org/licenses/LICENSE-2.0
8
- #
9
- # Unless required by applicable law or agreed to in writing, software
10
- # distributed under the License is distributed on an "AS IS" BASIS,
11
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- # See the License for the specific language governing permissions and
13
- # limitations under the License.
14
-
15
- import numpy as np
16
- from ..utils.metrics import get_mi
17
- from ..utils.data import get_inducing_pts
18
- from bayes_opt import BayesianOptimization
19
-
20
-
21
- class BayesianOpt:
22
- """Class for optimizing sensor placements using Bayesian Optimization
23
-
24
- Refer to the following papers for more details:
25
- - UAV route planning for active disease classification [Vivaldini et al., 2019]
26
- - Occupancy map building through Bayesian exploration [Francis et al., 2019]
27
-
28
- Args:
29
- X_train (ndarray): (n, d); Locations in the environment used to approximate the monitoring regions
30
- noise_variance (float): data variance
31
- kernel (gpflow.kernels.Kernel): gpflow kernel function
32
- transform (Transform): Transform object
33
- """
34
- def __init__(self, X_train, noise_variance, kernel,
35
- transform=None):
36
- self.X_train = X_train
37
- self.noise_variance = noise_variance
38
- self.kernel = kernel
39
- self.num_dim = X_train.shape[-1]
40
- self.transform = transform
41
-
42
- # use the boundaries of the region as the search space
43
- self.pbounds_dim = []
44
- for i in range(self.num_dim):
45
- self.pbounds_dim.append((np.min(X_train[:, i]), np.max(X_train[:, i])))
46
-
47
- def objective(self, **kwargs):
48
- """Objective function (GP-based Mutual Information)
49
-
50
- Args:
51
- x<i> (ndarray): (1, d); Current solution sensor placement location i
52
- """
53
- # MI does not depend on waypoint order (reshape to -1, num_dim)
54
- X = []
55
- for i in range(len(kwargs)):
56
- X.append(kwargs['x{}'.format(i)])
57
- X = np.array(X).reshape(-1, self.num_dim)
58
- if self.transform is not None:
59
- X = self.transform.expand(X)
60
- constraints_loss = self.transform.constraints(X)
61
-
62
- try:
63
- mi = get_mi(X, self.X_train, self.noise_variance, self.kernel)
64
- mi += constraints_loss
65
- mi = mi.numpy()
66
- except:
67
- mi = -1e4 # if the cholskey decomposition fails
68
- return mi
69
-
70
- def optimize(self,
71
- num_sensors=10,
72
- max_steps=100,
73
- X_init=None,
74
- init_points=10,
75
- verbose=0,
76
- seed=1234):
77
- """Optimizes the sensor placements using Bayesian Optimization without any constraints
78
-
79
- Args:
80
- num_sensors (int): Number of sensor locations to optimize.
81
- max_steps (int): Maximum number of optimization steps.
82
- X_init (ndarray): (m, d); Initial inducing points.
83
- init_points (int): Number of random solutions used for initial exploration.
84
- Random exploration can help by diversifying the exploration space.
85
- verbose (int): The level of verbosity.
86
- seed (int): The algorithm will use it to seed the randomnumber generator, ensuring replicability.
87
-
88
- Returns:
89
- Xu (ndarray): (m, d); Solution sensor placement locations
90
- """
91
- if X_init is None:
92
- X_init = get_inducing_pts(self.X_train, num_sensors, random=True)
93
- else:
94
- num_sensors = len(X_init.reshape(-1, self.num_dim))
95
- X_init = X_init.reshape(-1)
96
-
97
- pbounds = {}
98
- for i in range(self.num_dim*num_sensors):
99
- pbounds['x{}'.format(i)] = self.pbounds_dim[i%self.num_dim]
100
-
101
- optimizer = BayesianOptimization(f=self.objective,
102
- pbounds=pbounds,
103
- verbose=verbose,
104
- random_state=seed,
105
- allow_duplicate_points=True)
106
- optimizer.maximize(init_points=init_points,
107
- n_iter=max_steps)
108
-
109
- sol = []
110
- for i in range(self.num_dim*num_sensors):
111
- sol.append(optimizer.max['params']['x{}'.format(i)])
112
- sol = np.array(sol).reshape(-1, self.num_dim)
113
- if self.transform is not None:
114
- sol = self.transform.expand(sol,
115
- expand_sensor_model=False)
116
- if not isinstance(sol, np.ndarray):
117
- sol = sol.numpy()
118
- return sol.reshape(-1, self.num_dim)
sgptools/models/cma_es.py DELETED
@@ -1,121 +0,0 @@
1
- # Copyright 2024 The SGP-Tools Contributors. All Rights Reserved.
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License");
4
- # you may not use this file except in compliance with the License.
5
- # You may obtain a copy of the License at
6
- #
7
- # http://www.apache.org/licenses/LICENSE-2.0
8
- #
9
- # Unless required by applicable law or agreed to in writing, software
10
- # distributed under the License is distributed on an "AS IS" BASIS,
11
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- # See the License for the specific language governing permissions and
13
- # limitations under the License.
14
-
15
- import cma
16
- import numpy as np
17
- from shapely import geometry
18
- from ..utils.metrics import get_mi
19
- from ..utils.data import get_inducing_pts
20
-
21
-
22
- class CMA_ES:
23
- """Class for optimizing sensor placements using CMA-ES (a genetic algorithm)
24
-
25
- Refer to the following paper for more details:
26
- - Adaptive Continuous-Space Informative Path Planning for Online Environmental Monitoring [Hitz et al., 2017]
27
-
28
- Args:
29
- X_train (ndarray): (n, d); Locations in the environment used to approximate the monitoring regions
30
- noise_variance (float): data variance
31
- kernel (gpflow.kernels.Kernel): gpflow kernel function
32
- distance_budget (float): Distance budget for when treating the inducing points
33
- as waypoints of a path
34
- num_robots (int): Number of robots, used when modeling
35
- multi-robot IPP with a distance budget
36
- transform (Transform): Transform object
37
- """
38
- def __init__(self, X_train, noise_variance, kernel,
39
- distance_budget=None,
40
- num_robots=1,
41
- transform=None):
42
- self.boundaries = geometry.MultiPoint([[p[0], p[1]] for p in X_train]).convex_hull
43
- self.X_train = X_train
44
- self.noise_variance = noise_variance
45
- self.kernel = kernel
46
- self.num_dim = X_train.shape[-1]
47
- self.distance_budget = distance_budget
48
- self.num_robots = num_robots
49
- self.transform = transform
50
-
51
- def update(self, noise_variance, kernel):
52
- """Update GP noise variance and kernel function parameters
53
-
54
- Args:
55
- noise_variance (float): data variance
56
- kernel (gpflow.kernels.Kernel): gpflow kernel function
57
- """
58
- self.noise_variance = noise_variance
59
- self.kernel = kernel
60
-
61
- def objective(self, X):
62
- """Objective function (GP-based Mutual Information)
63
-
64
- Args:
65
- X (ndarray): (n, d); Current solution sensor placement locations
66
- """
67
- # MI does not depend on waypoint order (reshape to -1, num_dim)
68
- X = np.array(X).reshape(-1, self.num_dim)
69
- constraints_loss = 0.0
70
- if self.transform is not None:
71
- X = self.transform.expand(X)
72
- constraints_loss = self.transform.constraints(X)
73
-
74
- try:
75
- mi = -get_mi(X, self.X_train, self.noise_variance, self.kernel)
76
- mi -= constraints_loss
77
- mi = mi.numpy()
78
- except:
79
- mi = 0.0 # if the cholskey decomposition fails
80
- return mi
81
-
82
- def optimize(self,
83
- num_sensors=10,
84
- max_steps=5000,
85
- tol=1e-6,
86
- X_init=None,
87
- verbose=0,
88
- seed=1234):
89
- """Optimizes the sensor placements using CMA-ES without any constraints
90
-
91
- Args:
92
- num_sensors (int): Number of sensor locations to optimize
93
- max_steps (int): Maximum number of optimization steps
94
- tol (float): Convergence tolerance to decide when to stop optimization
95
- X_init (ndarray): (m, d); Initial inducing points
96
- verbose (int): The level of verbosity.
97
- seed (int): The algorithm will use it to seed the randomnumber generator, ensuring replicability.
98
-
99
- Returns:
100
- Xu (ndarray): (m, d); Solution sensor placement locations
101
- """
102
- sigma0 = 1.0
103
-
104
- if X_init is None:
105
- X_init = get_inducing_pts(self.X_train, num_sensors, random=True)
106
- X_init = X_init.reshape(-1)
107
-
108
- xopt, _ = cma.fmin2(self.objective, X_init, sigma0,
109
- options={'maxfevals': max_steps,
110
- 'verb_disp': verbose,
111
- 'tolfun': tol,
112
- 'seed': seed},
113
- restarts=5)
114
-
115
- xopt = np.array(xopt).reshape(-1, self.num_dim)
116
- if self.transform is not None:
117
- xopt = self.transform.expand(xopt,
118
- expand_sensor_model=False)
119
- if not isinstance(xopt, np.ndarray):
120
- xopt = xopt.numpy()
121
- return xopt.reshape(-1, self.num_dim)
@@ -1,68 +0,0 @@
1
- # Copyright 2024 The SGP-Tools Contributors. All Rights Reserved.
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License");
4
- # you may not use this file except in compliance with the License.
5
- # You may obtain a copy of the License at
6
- #
7
- # http://www.apache.org/licenses/LICENSE-2.0
8
- #
9
- # Unless required by applicable law or agreed to in writing, software
10
- # distributed under the License is distributed on an "AS IS" BASIS,
11
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- # See the License for the specific language governing permissions and
13
- # limitations under the License.
14
-
15
- import numpy as np
16
-
17
- from ..utils.data import get_inducing_pts
18
- from ..utils.gpflow import optimize_model
19
-
20
- from .core.augmented_sgpr import AugmentedSGPR
21
-
22
-
23
- def continuous_sgp(num_inducing, X_train, noise_variance, kernel,
24
- transform=None,
25
- Xu_init=None,
26
- Xu_time=None,
27
- orientation=False,
28
- **kwargs):
29
- """Get sensor placement solutions using the Continuous-SGP method
30
-
31
- Refer to the following papers for more details:
32
- - Efficient Sensor Placement from Regression with Sparse Gaussian Processes in Continuous and Discrete Spaces [[Jakkala and Akella, 2023](https://www.itskalvik.com/publication/sgp-sp/)]
33
- - Multi-Robot Informative Path Planning from Regression with Sparse Gaussian Processes [[Jakkala and Akella, 2024](https://www.itskalvik.com/publication/sgp-ipp/)]
34
-
35
- Args:
36
- num_inducing (int): Number of inducing points
37
- X_train (ndarray): (n, d); Unlabeled random sampled training points
38
- noise_variance (float): data variance
39
- kernel (gpflow.kernels.Kernel): gpflow kernel function
40
- transform (Transform): Transform object
41
- Xu_init (ndarray): (m, d); Initial inducing points
42
- Xu_time (ndarray): (t, d); Temporal inducing points used in spatio-temporal models
43
- orientation (bool): If True, a additionl dimension is added to the
44
- inducing points to represent the FoV orientation
45
-
46
- Returns:
47
- sgpr (AugmentedSGPR): Optimized sparse Gaussian process model
48
- loss (ndarray): Loss values computed during training
49
- """
50
- # Generate init inducing points
51
- if Xu_init is None:
52
- Xu_init = get_inducing_pts(X_train, num_inducing,
53
- orientation=orientation)
54
-
55
- # Fit spare GP
56
- sgpr = AugmentedSGPR((X_train, np.zeros((len(X_train), 1)).astype(X_train.dtype)),
57
- noise_variance=noise_variance,
58
- kernel=kernel,
59
- inducing_variable=Xu_init,
60
- inducing_variable_time=Xu_time,
61
- transform=transform)
62
-
63
- # Train the mode
64
- loss = optimize_model(sgpr,
65
- kernel_grad=False,
66
- **kwargs)
67
-
68
- return sgpr, loss
@@ -1,9 +0,0 @@
1
- # sgptools/models/core/__init__.py
2
-
3
- """Core modules in this package:
4
-
5
- - `augmented_gpr`: Provides a Gaussian process model with expand and aggregate functions
6
- - `augmented_sgpr`: Provides a sparse Gaussian process model with update, expand, and aggregate functions
7
- - `osgpr`: Provides a streaming sparse Gaussian process model along with initialization function
8
- - `transformations`: Provides transforms to model complex sensor field of views and handle informative path planning
9
- """
@@ -1,291 +0,0 @@
1
- # Copyright 2024 The streaming_sparse_gp Contributors. All Rights Reserved.
2
- # https://github.com/thangbui/streaming_sparse_gp/tree/master
3
- #
4
- # Licensed under the Apache License, Version 2.0 (the "License");
5
- # you may not use this file except in compliance with the License.
6
- # You may obtain a copy of the License at
7
- #
8
- # http://www.apache.org/licenses/LICENSE-2.0
9
- #
10
- # Unless required by applicable law or agreed to in writing, software
11
- # distributed under the License is distributed on an "AS IS" BASIS,
12
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- # See the License for the specific language governing permissions and
14
- # limitations under the License.
15
-
16
- """Provides a streaming sparse Gaussian process model along with initialization function
17
- """
18
-
19
- import tensorflow as tf
20
- import numpy as np
21
-
22
- import gpflow
23
- from gpflow.inducing_variables import InducingPoints
24
- from gpflow.models import GPModel, InternalDataTrainingLossMixin
25
- from gpflow import covariances
26
- from ...utils.data import get_inducing_pts
27
-
28
-
29
- class OSGPR_VFE(GPModel, InternalDataTrainingLossMixin):
30
- """Online Sparse Variational GP regression model from [streaming_sparse_gp](https://github.com/thangbui/streaming_sparse_gp/tree/master)
31
-
32
- Refer to the following paper for more details:
33
- - Streaming Gaussian process approximations [Bui et al., 2017]
34
-
35
- Args:
36
- data (tuple): (X, y) ndarrays with inputs (n, d) and labels (n, 1)
37
- kernel (gpflow.kernels.Kernel): gpflow kernel function
38
- mu_old (ndarray): mean of old `q(u)`; here `u` are the latents corresponding to the inducing points `Z_old`
39
- Su_old (ndarray): posterior covariance of old `q(u)`
40
- Kaa_old (ndarray): prior covariance of old `q(u)`
41
- Z_old (ndarray): (m_old, d): Old initial inducing points
42
- Z (ndarray): (m_new, d): New initial inducing points
43
- mean_function (function): GP mean function
44
- """
45
- def __init__(self, data, kernel, mu_old, Su_old, Kaa_old, Z_old, Z, mean_function=None):
46
- self.X, self.Y = self.data = gpflow.models.util.data_input_to_tensor(data)
47
- likelihood = gpflow.likelihoods.Gaussian()
48
- num_latent_gps = GPModel.calc_num_latent_gps_from_data(data, kernel, likelihood)
49
- super().__init__(kernel, likelihood, mean_function, num_latent_gps)
50
-
51
- self.inducing_variable = InducingPoints(Z)
52
- self.num_data = self.X.shape[0]
53
-
54
- self.mu_old = tf.Variable(mu_old, shape=tf.TensorShape(None), trainable=False)
55
- self.M_old = Z_old.shape[0]
56
- self.Su_old = tf.Variable(Su_old, shape=tf.TensorShape(None), trainable=False)
57
- self.Kaa_old = tf.Variable(Kaa_old, shape=tf.TensorShape(None), trainable=False)
58
- self.Z_old = tf.Variable(Z_old, shape=tf.TensorShape(None), trainable=False)
59
-
60
- def init_Z(self):
61
- M = self.inducing_variable.Z.shape[0]
62
- M_old = int(0.7 * M)
63
- M_new = M - M_old
64
- old_Z = self.Z_old.numpy()[np.random.permutation(M)[0:M_old], :]
65
- new_Z = self.X.numpy()[np.random.permutation(self.X.shape[0])[0:M_new], :]
66
- Z = np.vstack((old_Z, new_Z))
67
- return Z
68
-
69
- def update(self, data, inducing_variable=None, update_inducing=True):
70
- """Configure the OSGPR to adapt to a new batch of data.
71
- Note: The OSGPR needs to be trained using gradient-based approaches after update.
72
-
73
- Args:
74
- data (tuple): (X, y) ndarrays with new batch of inputs (n, d) and labels (n, ndim)
75
- inducing_variable (ndarray): (m_new, d): New initial inducing points
76
- update_inducing (bool): Whether to update the inducing points
77
- """
78
- self.X, self.Y = self.data = gpflow.models.util.data_input_to_tensor(data)
79
- self.num_data = self.X.shape[0]
80
-
81
- # Update the inducing points
82
- self.Z_old.assign(self.inducing_variable.Z.numpy())
83
- if inducing_variable is None and update_inducing:
84
- inducing_variable = self.init_Z()
85
- if inducing_variable is not None:
86
- self.inducing_variable.Z.assign(inducing_variable)
87
-
88
- # Get posterior mean and covariance for the old inducing points
89
- mu_old, Su_old = self.predict_f(self.Z_old, full_cov=True)
90
- self.mu_old.assign(mu_old.numpy())
91
- self.Su_old.assign(Su_old.numpy())
92
-
93
- # Get the prior covariance matrix for the old inducing points
94
- Kaa_old = self.kernel(self.Z_old)
95
- self.Kaa_old.assign(Kaa_old.numpy())
96
-
97
- def _common_terms(self):
98
- Mb = self.inducing_variable.num_inducing
99
- Ma = self.M_old
100
- # jitter = gpflow.default_jitter()
101
- jitter = gpflow.utilities.to_default_float(1e-4)
102
- sigma2 = self.likelihood.variance
103
- sigma = tf.sqrt(sigma2)
104
-
105
- Saa = self.Su_old
106
- ma = self.mu_old
107
-
108
- # a is old inducing points, b is new
109
- # f is training points
110
- # s is test points
111
- Kbf = covariances.Kuf(self.inducing_variable, self.kernel, self.X)
112
- Kbb = covariances.Kuu(self.inducing_variable, self.kernel, jitter=jitter)
113
- Kba = covariances.Kuf(self.inducing_variable, self.kernel, self.Z_old)
114
- Kaa_cur = gpflow.utilities.add_noise_cov(self.kernel(self.Z_old), jitter)
115
- Kaa = gpflow.utilities.add_noise_cov(self.Kaa_old, jitter)
116
-
117
- err = self.Y - self.mean_function(self.X)
118
-
119
- Sainv_ma = tf.linalg.solve(Saa, ma)
120
- Sinv_y = self.Y / sigma2
121
- c1 = tf.matmul(Kbf, Sinv_y)
122
- c2 = tf.matmul(Kba, Sainv_ma)
123
- c = c1 + c2
124
-
125
- Lb = tf.linalg.cholesky(Kbb)
126
- Lbinv_c = tf.linalg.triangular_solve(Lb, c, lower=True)
127
- Lbinv_Kba = tf.linalg.triangular_solve(Lb, Kba, lower=True)
128
- Lbinv_Kbf = tf.linalg.triangular_solve(Lb, Kbf, lower=True) / sigma
129
- d1 = tf.matmul(Lbinv_Kbf, Lbinv_Kbf, transpose_b=True)
130
-
131
- LSa = tf.linalg.cholesky(Saa)
132
- Kab_Lbinv = tf.linalg.matrix_transpose(Lbinv_Kba)
133
- LSainv_Kab_Lbinv = tf.linalg.triangular_solve(
134
- LSa, Kab_Lbinv, lower=True)
135
- d2 = tf.matmul(LSainv_Kab_Lbinv, LSainv_Kab_Lbinv, transpose_a=True)
136
-
137
- La = tf.linalg.cholesky(Kaa)
138
- Lainv_Kab_Lbinv = tf.linalg.triangular_solve(
139
- La, Kab_Lbinv, lower=True)
140
- d3 = tf.matmul(Lainv_Kab_Lbinv, Lainv_Kab_Lbinv, transpose_a=True)
141
-
142
- D = tf.eye(Mb, dtype=gpflow.default_float()) + d1 + d2 - d3
143
- D = gpflow.utilities.add_noise_cov(D, jitter)
144
- LD = tf.linalg.cholesky(D)
145
-
146
- LDinv_Lbinv_c = tf.linalg.triangular_solve(LD, Lbinv_c, lower=True)
147
-
148
- return (Kbf, Kba, Kaa, Kaa_cur, La, Kbb, Lb, D, LD,
149
- Lbinv_Kba, LDinv_Lbinv_c, err, d1)
150
-
151
- def maximum_log_likelihood_objective(self):
152
- """
153
- Construct a tensorflow function to compute the bound on the marginal
154
- likelihood.
155
- """
156
-
157
- Mb = self.inducing_variable.num_inducing
158
- Ma = self.M_old
159
- jitter = gpflow.default_jitter()
160
- # jitter = gpflow.utilities.to_default_float(1e-4)
161
- sigma2 = self.likelihood.variance
162
- sigma = tf.sqrt(sigma2)
163
- N = self.num_data
164
-
165
- Saa = self.Su_old
166
- ma = self.mu_old
167
-
168
- # a is old inducing points, b is new
169
- # f is training points
170
- Kfdiag = self.kernel(self.X, full_cov=False)
171
- (Kbf, Kba, Kaa, Kaa_cur, La, Kbb, Lb, D, LD,
172
- Lbinv_Kba, LDinv_Lbinv_c, err, Qff) = self._common_terms()
173
-
174
- LSa = tf.linalg.cholesky(Saa)
175
- Lainv_ma = tf.linalg.triangular_solve(LSa, ma, lower=True)
176
-
177
- # constant term
178
- bound = -0.5 * N * np.log(2 * np.pi)
179
- # quadratic term
180
- bound += -0.5 * tf.reduce_sum(tf.square(err)) / sigma2
181
- # bound += -0.5 * tf.reduce_sum(ma * Sainv_ma)
182
- bound += -0.5 * tf.reduce_sum(tf.square(Lainv_ma))
183
- bound += 0.5 * tf.reduce_sum(tf.square(LDinv_Lbinv_c))
184
- # log det term
185
- bound += -0.5 * N * tf.reduce_sum(tf.math.log(sigma2))
186
- bound += - tf.reduce_sum(tf.math.log(tf.linalg.diag_part(LD)))
187
-
188
- # delta 1: trace term
189
- bound += -0.5 * tf.reduce_sum(Kfdiag) / sigma2
190
- bound += 0.5 * tf.reduce_sum(tf.linalg.diag_part(Qff))
191
-
192
- # delta 2: a and b difference
193
- bound += tf.reduce_sum(tf.math.log(tf.linalg.diag_part(La)))
194
- bound += - tf.reduce_sum(tf.math.log(tf.linalg.diag_part(LSa)))
195
-
196
- Kaadiff = Kaa_cur - tf.matmul(Lbinv_Kba, Lbinv_Kba, transpose_a=True)
197
- Sainv_Kaadiff = tf.linalg.solve(Saa, Kaadiff)
198
- Kainv_Kaadiff = tf.linalg.solve(Kaa, Kaadiff)
199
-
200
- bound += -0.5 * tf.reduce_sum(
201
- tf.linalg.diag_part(Sainv_Kaadiff) - tf.linalg.diag_part(Kainv_Kaadiff))
202
-
203
- return bound
204
-
205
- def predict_f(self, Xnew, full_cov=False):
206
- """
207
- Compute the mean and variance of the latent function at some new points
208
- Xnew.
209
- """
210
-
211
- # jitter = gpflow.default_jitter()
212
- jitter = gpflow.utilities.to_default_float(1e-4)
213
-
214
- # a is old inducing points, b is new
215
- # f is training points
216
- # s is test points
217
- Kbs = covariances.Kuf(self.inducing_variable, self.kernel, Xnew)
218
- (Kbf, Kba, Kaa, Kaa_cur, La, Kbb, Lb, D, LD,
219
- Lbinv_Kba, LDinv_Lbinv_c, err, Qff) = self._common_terms()
220
-
221
- Lbinv_Kbs = tf.linalg.triangular_solve(Lb, Kbs, lower=True)
222
- LDinv_Lbinv_Kbs = tf.linalg.triangular_solve(LD, Lbinv_Kbs, lower=True)
223
- mean = tf.matmul(LDinv_Lbinv_Kbs, LDinv_Lbinv_c, transpose_a=True)
224
-
225
- if full_cov:
226
- Kss = self.kernel(Xnew) + jitter * tf.eye(tf.shape(Xnew)[0], dtype=gpflow.default_float())
227
- var1 = Kss
228
- var2 = - tf.matmul(Lbinv_Kbs, Lbinv_Kbs, transpose_a=True)
229
- var3 = tf.matmul(LDinv_Lbinv_Kbs, LDinv_Lbinv_Kbs, transpose_a=True)
230
- var = var1 + var2 + var3
231
- else:
232
- var1 = self.kernel(Xnew, full_cov=False)
233
- var2 = -tf.reduce_sum(tf.square(Lbinv_Kbs), axis=0)
234
- var3 = tf.reduce_sum(tf.square(LDinv_Lbinv_Kbs), axis=0)
235
- var = var1 + var2 + var3
236
-
237
- return mean + self.mean_function(Xnew), var
238
-
239
-
240
- def init_osgpr(X_train,
241
- num_inducing=10,
242
- lengthscales=1.0,
243
- variance=1.0,
244
- noise_variance=0.001,
245
- kernel=None,
246
- ndim=1):
247
- """Initialize a VFE OSGPR model with an RBF kernel with
248
- unit variance and lengthcales, and 0.001 noise variance.
249
- Used in the Online Continuous SGP approach.
250
-
251
- Args:
252
- X_train (ndarray): (n, d); Unlabeled random sampled training points.
253
- They only effect the initial inducing point locations,
254
- i.e., limits them to the bounds of the data
255
- num_inducing (int): Number of inducing points
256
- lengthscales (float or list): Kernel lengthscale(s), if passed as a list,
257
- each element corresponds to each data dimension
258
- variance (float): Kernel variance
259
- noise_variance (float): Data noise variance
260
- kernel (gpflow.kernels.Kernel): gpflow kernel function
261
- ndim (int): Number of output dimensions
262
-
263
- Returns:
264
- online_param (OSGPR_VFE): Initialized online sparse Gaussian process model
265
- """
266
-
267
- if kernel is None:
268
- kernel = gpflow.kernels.SquaredExponential(lengthscales=lengthscales,
269
- variance=variance)
270
-
271
- y_train = np.zeros((len(X_train), ndim), dtype=X_train.dtype)
272
- Z_init = get_inducing_pts(X_train, num_inducing)
273
- init_param = gpflow.models.SGPR((X_train, y_train),
274
- kernel,
275
- inducing_variable=Z_init,
276
- noise_variance=noise_variance)
277
-
278
- # Initialize the OSGPR model using the parameters from the SGPR model
279
- # The X_train and y_train here will be overwritten in the online phase
280
- X_train = np.zeros([2, X_train.shape[-1]], dtype=X_train.dtype)
281
- y_train = np.zeros([2, ndim], dtype=X_train.dtype)
282
- Zopt = init_param.inducing_variable.Z.numpy()
283
- mu, Su = init_param.predict_f(Zopt, full_cov=True)
284
- Kaa = init_param.kernel(Zopt)
285
- online_param = OSGPR_VFE((X_train[:2], y_train[:2]),
286
- init_param.kernel,
287
- mu, Su[0], Kaa,
288
- Zopt, Zopt)
289
- online_param.likelihood.variance.assign(init_param.likelihood.variance)
290
-
291
- return online_param