From 37e31aa57a3d907a139d5c61e29dea3571cb3d95 Mon Sep 17 00:00:00 2001 From: SebastianPopescu Date: Fri, 26 Aug 2022 08:23:04 +0100 Subject: [PATCH 01/25] initial iteration of generalized framework for RFF --- docs/notebooks/efficient_sampling.py | 7 +- .../multi_output_efficient_sampling.py | 169 +++++++ ...multi_output_weight_space_approximation.py | 428 ++++++++++++++++++ docs/notebooks/weight_space_approximation.py | 4 +- .../constant_input_dim_deep_gp.py | 2 +- .../feature_decomposition_kernels/__init__.py | 19 + .../kernel_with_feature_decomposition.py | 27 +- .../multioutput/__init__.py | 12 + .../kernel_with_feature_decomposition.py | 377 +++++++++++++++ .../fourier_features/__init__.py | 9 +- .../basis_functions/fourier_features/base.py | 12 +- .../fourier_features/multioutput/__init__.py | 0 .../fourier_features/multioutput/base.py | 128 ++++++ .../multioutput/random/__init__.py | 26 ++ .../multioutput/random/base.py | 284 ++++++++++++ .../basis_functions/fourier_features/utils.py | 10 +- gpflux/layers/gp_layer.py | 4 + gpflux/sampling/__init__.py | 11 +- gpflux/sampling/dispatch.py | 6 + gpflux/sampling/multioutput/__init__.py | 5 + gpflux/sampling/multioutput/sample.py | 157 +++++++ gpflux/sampling/sample.py | 42 +- .../fourier_features/test_multioutput_rff.py | 313 +++++++++++++ .../test_multioutput_rff_cosine.py | 307 +++++++++++++ .../sampling/test_multioutput_sample.py | 169 +++++++ 25 files changed, 2483 insertions(+), 45 deletions(-) create mode 100644 docs/notebooks/multi_output_efficient_sampling.py create mode 100644 docs/notebooks/multi_output_weight_space_approximation.py create mode 100644 gpflux/feature_decomposition_kernels/__init__.py rename gpflux/{sampling => feature_decomposition_kernels}/kernel_with_feature_decomposition.py (92%) create mode 100644 gpflux/feature_decomposition_kernels/multioutput/__init__.py create mode 100644 gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py create mode 100644 gpflux/layers/basis_functions/fourier_features/multioutput/__init__.py create mode 100644 gpflux/layers/basis_functions/fourier_features/multioutput/base.py create mode 100644 gpflux/layers/basis_functions/fourier_features/multioutput/random/__init__.py create mode 100644 gpflux/layers/basis_functions/fourier_features/multioutput/random/base.py create mode 100644 gpflux/sampling/dispatch.py create mode 100644 gpflux/sampling/multioutput/__init__.py create mode 100644 gpflux/sampling/multioutput/sample.py create mode 100644 tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff.py create mode 100644 tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff_cosine.py create mode 100644 tests/gpflux/sampling/test_multioutput_sample.py diff --git a/docs/notebooks/efficient_sampling.py b/docs/notebooks/efficient_sampling.py index 990a1cf4..fe85598c 100644 --- a/docs/notebooks/efficient_sampling.py +++ b/docs/notebooks/efficient_sampling.py @@ -37,7 +37,7 @@ from gpflow.config import default_float from gpflux.layers.basis_functions.fourier_features import RandomFourierFeaturesCosine -from gpflux.sampling import KernelWithFeatureDecomposition +from gpflux.feature_decomposition_kernels import KernelWithFeatureDecomposition from gpflux.models.deep_gp import sample_dgp tf.keras.backend.set_floatx("float64") @@ -48,7 +48,7 @@ """ # %% -d = np.load("../../tests/snelson1d.npz") +d = np.load("./tests/snelson1d.npz") X, Y = data = d["X"], d["Y"] num_data, input_dim = X.shape @@ -68,13 +68,16 @@ Z = np.linspace(X.min(), X.max(), 10).reshape(-1, 1).astype(np.float64) inducing_variable = gpflow.inducing_variables.InducingPoints(Z) + gpflow.utilities.set_trainable(inducing_variable, False) num_rff = 1000 eigenfunctions = RandomFourierFeaturesCosine(kernel, num_rff, dtype=default_float()) eigenvalues = np.ones((num_rff, 1), dtype=default_float()) + kernel_with_features = KernelWithFeatureDecomposition(kernel, eigenfunctions, eigenvalues) + # %% [markdown] """ ## Building and training the single-layer GP diff --git a/docs/notebooks/multi_output_efficient_sampling.py b/docs/notebooks/multi_output_efficient_sampling.py new file mode 100644 index 00000000..c2dce513 --- /dev/null +++ b/docs/notebooks/multi_output_efficient_sampling.py @@ -0,0 +1,169 @@ +# -*- coding: utf-8 -*- +# --- +# jupyter: +# jupytext: +# cell_markers: '"""' +# formats: ipynb,py:percent +# text_representation: +# extension: .py +# format_name: percent +# format_version: '1.3' +# jupytext_version: 1.4.2 +# kernelspec: +# display_name: Python 3 +# language: python +# name: python3 +# --- + +# %% [markdown] +""" +# Efficient sampling with Gaussian processes and Random Fourier Features + +Gaussian processes (GPs) provide a mathematically elegant framework for learning unknown functions from data. They are robust to overfitting, allow to incorporate prior assumptions into the model and provide calibrated uncertainty estimates for their predictions. This makes them prime candidates in settings where data is scarce, noisy or very costly to obtain, and are natural tools in applications such as Bayesian optimisation (BO). + +Despite their favorable properties, the use of GPs still has practical limitations. One of them is the computational complexity to draw predictive samples from the model, which quickly becomes prohibitive as the sample size grows, and creates a well-known bottleneck for GP-based Thompson sampling (GP-TS) for instance. +Recent work proposes to combine GP’s weight-space and function-space views to draw samples more efficiently from (approximate) posterior GPs with encouraging results in low-dimensional regimes. + +In GPflux, this functionality is unlocked by grouping a kernel (e.g., `gpflow.kernels.Matern52`) with its feature decomposition using `gpflux.sampling.KernelWithFeatureDecomposition`. See the notebooks on [weight space approximation](weight_space_approximation.ipynb) and [efficient posterior sampling](efficient_posterior_sampling.ipynb) for a thorough explanation. +""" +# %% +import numpy as np +import tensorflow as tf +import matplotlib.pyplot as plt + +import gpflow +import gpflux + +from gpflow.config import default_float + +from gpflux.layers.basis_functions.fourier_features import MultiOutputRandomFourierFeaturesCosine +from gpflux.feature_decomposition_kernels import KernelWithFeatureDecomposition, SharedMultiOutputKernelWithFeatureDecomposition, SeparateMultiOutputKernelWithFeatureDecomposition +from gpflux.models.deep_gp import sample_dgp + +tf.keras.backend.set_floatx("float64") + +# %% [markdown] +""" +## Load Snelson dataset +""" + +# %% +d = np.load("./tests/snelson1d.npz") +X, Y = data = d["X"], d["Y"] +num_data, input_dim = X.shape + +# %% [markdown] +r""" +## Setting up the kernel and its feature decomposition + +The `KernelWithFeatureDecomposition` instance represents a kernel together with its finite feature decomposition, +$$ +k(x, x') = \sum_{i=0}^L \lambda_i \phi_i(x) \phi_i(x'), +$$ +where $\lambda_i$ and $\phi_i(\cdot)$ are the coefficients (eigenvalues) and features (eigenfunctions), respectively, and $L$ is the finite cutoff. See [the notebook on weight space approximation](weight_space_approximation.ipynb) for a detailed explanation of how to construct this decomposition using Random Fourier Features (RFF). +""" + +# %% +#kernel = gpflow.kernels.Matern52() +kernel1 = gpflow.kernels.Matern52() +kernel2 = gpflow.kernels.SquaredExponential() +#kernel = gpflow.kernels.SeparateIndependent( kernels = [kernel1, kernel2]) +kernel = gpflow.kernels.SharedIndependent( kernel = kernel1, output_dim = 2) + +Z_1 = np.linspace(X.min(), X.max(), 10).reshape(-1, 1).astype(np.float64) +Z_2 = np.linspace(X.min(), X.max(), 10).reshape(-1, 1).astype(np.float64) + +inducing_variable_1 = gpflow.inducing_variables.InducingPoints(Z_1) +inducing_variable_2 = gpflow.inducing_variables.InducingPoints(Z_2) +#inducing_variable = gpflow.inducing_variables.SeparateIndependentInducingVariables(inducing_variable_list= [inducing_variable_1, inducing_variable_2]) +inducing_variable = gpflow.inducing_variables.SharedIndependentInducingVariables(inducing_variable = inducing_variable_1) + +gpflow.utilities.set_trainable(inducing_variable, False) +P = 2 +num_rff = 1000 +eigenfunctions = MultiOutputRandomFourierFeaturesCosine(kernel, num_rff, dtype=default_float()) +eigenvalues = np.ones((P, num_rff, 1), dtype=default_float()) +#kernel_with_features = SeparateMultiOutputKernelWithFeatureDecomposition(kernel, eigenfunctions, eigenvalues) +kernel_with_features = SharedMultiOutputKernelWithFeatureDecomposition(kernel, eigenfunctions, eigenvalues) +# %% [markdown] +""" +## Building and training the single-layer GP + +### Initialise the single-layer GP +Because `KernelWithFeatureDecomposition` is just a `gpflow.kernels.Kernel`, we can construct a GP layer with it. +""" +# %% +layer = gpflux.layers.GPLayer( + kernel_with_features, + inducing_variable, + num_data, + whiten=True, + num_latent_gps=2, + mean_function=gpflow.mean_functions.Zero(), +) +likelihood_layer = gpflux.layers.LikelihoodLayer(gpflow.likelihoods.Gaussian()) # noqa: E231 +dgp = gpflux.models.DeepGP([layer], likelihood_layer) +model = dgp.as_training_model() +# %% [markdown] +""" +### Fit model to data +""" + +# %% +model.compile(tf.optimizers.Adam(learning_rate=0.1)) + +callbacks = [ + tf.keras.callbacks.ReduceLROnPlateau( + monitor="loss", + patience=5, + factor=0.95, + verbose=0, + min_lr=1e-6, + ) +] + +history = model.fit( + {"inputs": X, "targets": tf.tile(Y,[1,2])}, + batch_size=num_data, + epochs=100, + callbacks=callbacks, + verbose=0, +) +# %% [markdown] +""" +## Drawing samples + +Now that the model is trained we can draw efficient and consistent samples from the posterior GP. By "consistent" we mean that the `sample_dgp` function returns a function object that can be evaluated multiple times at different locations, but importantly, the returned function values will come from the same GP sample. This functionality is implemented by the `gpflux.sampling.efficient_sample` function. +""" + +# %% +from typing import Callable + +x_margin = 5 +n_x = 1000 +X_test = np.linspace(X.min() - x_margin, X.max() + x_margin, n_x).reshape(-1, 1) + +f_mean, f_var = dgp.predict_f(X_test) +f_scale = np.sqrt(f_var) + + +fig, axs = plt.subplots(1, 2) + + +for dim in range(2): + + # Plot samples + n_sim = 10 + for _ in range(n_sim): + # `sample_dgp` returns a callable - which we subsequently evaluate + f_sample: Callable[[tf.Tensor], tf.Tensor] = sample_dgp(dgp) + axs[dim].plot(X_test, f_sample(X_test).numpy()[..., dim]) + + # Plot GP mean and uncertainty intervals and data + axs[dim].plot(X_test, f_mean[..., dim], "C0") + axs[dim].plot(X_test, f_mean[..., dim] + f_scale[..., dim], "C0--") + axs[dim].plot(X_test, f_mean[..., dim] - f_scale[..., dim], "C0--") + axs[dim].plot(X, Y, "kx", alpha=0.2) + axs[dim].set_xlim(X.min() - x_margin, X.max() + x_margin) + axs[dim].set_ylim(Y.min() - x_margin, Y.max() + x_margin) +plt.show() diff --git a/docs/notebooks/multi_output_weight_space_approximation.py b/docs/notebooks/multi_output_weight_space_approximation.py new file mode 100644 index 00000000..a2a194b2 --- /dev/null +++ b/docs/notebooks/multi_output_weight_space_approximation.py @@ -0,0 +1,428 @@ +# --- +# jupyter: +# jupytext: +# text_representation: +# extension: .py +# format_name: percent +# format_version: '1.3' +# jupytext_version: 1.10.0 +# kernelspec: +# display_name: Python 3 +# language: python +# name: python3 +# --- + +# %% [markdown] +""" +# Weight Space Approximation with Random Fourier Features +""" + +# %% [markdown] +r""" +This notebook demonstrates how to approximate an exact Gaussian process regression model (GPR) with random Fourier features in weight space. The end result is Figure 1 from from Wilson et al. "Efficiently sampling functions from Gaussian process posteriors" . This figure demonstrates that approximating an exact GPR model in weight space becomes increasingly more difficult as the training data grows. While the approximation remains accurate in areas within the training data and far away from the training data, predictions close to the training data points (but outside the training data interval) become less reliable. Note that Wilson et al. provide a method to alleviate exactly this problem; however, this is outside the scope of this notebook, where the emphasis is on how to build a weight space approximated Gaussian process model with random Fourier features in `gpflux`. + +The basic idea is to approximate a stationary kernel $k(X,X^\prime)$ for one-dimensional inputs $X \in \mathbb{R}$ and $X^\prime \in \mathbb{R}$ according to Bochner's theorem: + +$$ +k(X, X^\prime) \approx \sum_{i=1}^I \phi_i(X) \phi_i(X^\prime), +$$ +with $I$ Fourier features $\phi_i$ following Rahimi and Recht "Random features for large-scale kernel machines" (NeurIPS, 2007) defined as + +$$ +\phi_i(X) = \sqrt{\frac{2 \sigma^2}{l}} \cos(\theta_i X + \tau_i), +$$ +where $\sigma^2$ refers to the kernel variance and $l$ to the kernel lengthscale. $\theta_i$ and $\tau_i$ are randomly drawn hyperparameters that determine each feature function $\phi_i$. The hyperparameter $\theta_i$ is randomly drawn from the kernel's spectral density. The spectral density of a stationary kernel is obtained by interpreting the kernel as a function of one argument only (i.e. the distance between $X$ and $X^\prime$) and performing a Fourier transform on that function, resulting in an unnormalised probability density (from which samples can be obtained). The hyperparameter $\tau_i$ is obtained by sampling from a uniform distribution $\tau_i \sim \mathcal{U}(0,2\pi)$. Note that both $\theta_i$ and $\tau_i$ are fixed and not optimised over. An interesting direction of future research is how to automatically identify those (but this is outside the scope of this notebook). If we drew infinitely many samples, i.e. $I \rightarrow \infty$, we would recover the true kernel perfectly. + +The kernel approximation specified above enables you to express a supervised inference problem with training data $\mathcal{D} = \{(X_n,y_n)\}_{n=1,...,N}$ in weight space view as + +$$ +p(\textbf{w} | \mathcal{D}) = \frac{\prod_{n=1}^N p(y_n| \textbf{w}^\intercal \boldsymbol{\phi}(X_n), \sigma_\epsilon^2) p(\textbf{w})}{p(\mathcal{D})}, +$$ +where we assume $p(\textbf{w})$ to be a standard normal multivariate prior and $p(y_n| \textbf{w}^\intercal \boldsymbol{\phi}(X_n), \sigma_\epsilon^2)$ to be a univariate Gaussian observation model of the i.i.d. likelihood with mean $\textbf{w}^\intercal \boldsymbol{\phi}(X_n)$ and noise variance $\sigma_\epsilon^2$. The boldface notation $\boldsymbol{\phi}(X_n)$ refers to the vector-valued feature function that evaluates all features from $1$ up to $I$ for one particular input $X_n$. Under these assumptions, the posterior $p(\textbf{w} | \mathcal{D})$ enjoys a closed form and is Gaussian. Predictions can readily be obtained by sampling $\textbf{w}$ and evaluating the function sample $\textbf{w}$ at new locations $\{X_{n^\star}^\star\}_{n^\star=1,...,N^\star}$ as $\{\textbf{w}^\intercal \boldsymbol{\phi}(X_{n^\star}^\star)\}_{n^\star=1,...,N^\star}$. + +The advantage of expressing a Gaussian process in weight space is that functions are represented as weight vectors $\textbf{w}$ (rather than actual functions $f(\cdot)$) from which samples can be obtained a priori without knowing where the function should be evaluated. When expressing a Gaussian process in function space view the latter is not possible, i.e. a function $f(\cdot)$ cannot be sampled without knowing where to evaluate the function, namely at $\{X_{n^\star}^\star\}_{n^\star=1,...,N^\star}$. Weight space approximated Gaussian processes therefore hold the potential to sample efficiently from Gaussian process posteriors, which is desirable in vanilla supervised learning but also in domains such as Bayesian optimisation or model-based reinforcement learning. + +In the following example, we compare a weight space approximated GPR model (WSA model) with both a proper GPR model and a sparse variational Gaussian Process model (SVGP). GPR models and SVGP models are implemented in `gpflow`, but the two necessary ingredients for building the WSA model are part of `gpflux`: these are random Fourier feature functions via the `RandomFourierFeaturesCosine` class, and approximate kernels based on Bochner's theorem (or any other theorem that approximates a kernel with a finite number of feature functions, e.g. Mercer) via the `KernelWithFeatureDecomposition` class. +""" + +# %% +import numpy as np +import matplotlib.pyplot as plt + +plt.rcParams["figure.figsize"] = (20, 7) +plt.rc("text") +plt.rcParams.update({"font.size": 20}) +import tensorflow as tf + +import gpflow +from gpflow.config import default_float +from gpflow.models import GPR, SVGP +from gpflow.kernels import SquaredExponential, Matern52 +from gpflow.likelihoods import Gaussian +from gpflow.inducing_variables import InducingPoints + +from gpflux.layers.basis_functions.fourier_features import MultiOutputRandomFourierFeaturesCosine +from gpflux.feature_decomposition_kernels import KernelWithFeatureDecomposition, SeparateMultiOutputKernelWithFeatureDecomposition, SharedMultiOutputKernelWithFeatureDecomposition + + + + +# Copyright 2016-2020 The GPflow Contributors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from typing import Optional + +import tensorflow as tf + +import gpflow + + + + +#from gpflow import posteriors +from gpflow.base import InputData, MeanAndVariance, RegressionData +from gpflow.experimental.check_shapes import check_shapes, inherit_check_shapes +from gpflow.kernels import Kernel +from gpflow.likelihoods import Gaussian +from gpflow.logdensities import multivariate_normal +from gpflow.mean_functions import MeanFunction +from gpflow.utilities.model_utils import add_likelihood_noise_cov +from gpflow.utilities import assert_params_false +from gpflow.models.model import GPModel +from gpflow.models.training_mixins import InternalDataTrainingLossMixin +from gpflow.models.util import data_input_to_tensor + +class GPR_deprecated(GPModel, InternalDataTrainingLossMixin): + r""" + Gaussian Process Regression. + + This is a vanilla implementation of GP regression with a Gaussian + likelihood. Multiple columns of Y are treated independently. + + The log likelihood of this model is given by + + .. math:: + \log p(Y \,|\, \mathbf f) = + \mathcal N(Y \,|\, 0, \sigma_n^2 \mathbf{I}) + + To train the model, we maximise the log _marginal_ likelihood + w.r.t. the likelihood variance and kernel hyperparameters theta. + The marginal likelihood is found by integrating the likelihood + over the prior, and has the form + + .. math:: + \log p(Y \,|\, \sigma_n, \theta) = + \mathcal N(Y \,|\, 0, \mathbf{K} + \sigma_n^2 \mathbf{I}) + """ + + @check_shapes( + "data[0]: [N, D]", + "data[1]: [N, P]", + ) + def __init__( + self, + data: RegressionData, + kernel: Kernel, + mean_function: Optional[MeanFunction] = None, + noise_variance: Optional[float] = None, + likelihood: Optional[Gaussian] = None, + ): + assert (noise_variance is None) or ( + likelihood is None + ), "Cannot set both `noise_variance` and `likelihood`." + if likelihood is None: + if noise_variance is None: + noise_variance = 1.0 + likelihood = gpflow.likelihoods.Gaussian(noise_variance) + _, Y_data = data + super().__init__(kernel, likelihood, mean_function, num_latent_gps=Y_data.shape[-1]) + self.data = data_input_to_tensor(data) + + # type-ignore is because of changed method signature: + @inherit_check_shapes + def maximum_log_likelihood_objective(self) -> tf.Tensor: # type: ignore[override] + return self.log_marginal_likelihood() + + @check_shapes( + "return: []", + ) + def log_marginal_likelihood(self) -> tf.Tensor: + r""" + Computes the log marginal likelihood. + + .. math:: + \log p(Y | \theta). + + """ + X, Y = self.data + K = self.kernel(X) + ks = add_likelihood_noise_cov(K, self.likelihood, tf.tile(X[None,...], [2,1,1])) + L = tf.linalg.cholesky(ks) + m = self.mean_function(X) + + # [R,] log-likelihoods for each independent dimension of Y + log_prob = multivariate_normal(Y, m, L) + return tf.reduce_sum(log_prob) + + @inherit_check_shapes + def predict_f( + self, Xnew: InputData, full_cov: bool = False, full_output_cov: bool = False + ) -> MeanAndVariance: + r""" + This method computes predictions at X \in R^{N \x D} input points + + .. math:: + p(F* | Y) + + where F* are points on the GP at new data points, Y are noisy observations at training data + points. + """ + assert_params_false(self.predict_f, full_output_cov=full_output_cov) + + X, Y = self.data + err = Y - self.mean_function(X) + + kmm = self.kernel(X) + knn = self.kernel(Xnew, full_cov=full_cov) + kmn = self.kernel(X, Xnew) + #kmm_plus_s = add_likelihood_noise_cov(kmm, self.likelihood, X) + kmm_plus_s = add_likelihood_noise_cov(kmm, self.likelihood, tf.tile(X[None,...], [2,1,1])) + + #NOTE -- this onlty works for a single latent Full GP + #conditional = gpflow.conditionals.base_conditional + + conditional = gpflow.conditionals.util.separate_independent_conditional_implementation + + f_mean_zero, f_var = conditional( + kmn, kmm_plus_s, knn, err, full_cov=full_cov, white=False + ) # [N, P], [N, P] or [P, N, N] + f_mean = f_mean_zero + self.mean_function(Xnew) + return f_mean, f_var + + + + + +# %% [markdown] +""" +Our aim is to demonstrate the decrease in predictive quality of a WSA model when increasing the number of training points. To that end, we perform two sets of experiments: one with few and one with many training data points. Each experiment compares a WSA model to an exact GPR and to an approximate SVGP model, resulting in six plots all in all. + +We first define settings that remain the same across the two sets of experiments, like the interval of the training points, aspects of the generative model (i.e. kernel variance and lengthscale, and the variance of the observation model), and the number of feature functions of the WSA model. + +The only aspect that is different across both experimental settings is the number of training data points. We increase the number of inducing points for the SVGP model to cope with this. +""" + +# %% +# experiment parameters that are the same for both sets of experiments +X_interval = [0.14, 0.5] # interval where training points live +lengthscale = [0.1] # lengthscale for the kernel (which is not learned in all experiments, the kernel variance is 1) +number_of_features = 2000 # number of basis functions for weight-space approximated kernels +noise_variance = 1e-3 # noise variance of the likelihood (which is not learned in all experiments) +number_of_test_samples = 1024 # number of evaluation points for prediction +number_of_function_samples = ( + 20 # number of function samples to be drawn from (approximate) posteriors +) + +# experiment parameters that differ across both sets of experiments +number_of_train_samples = [4, 1000] # number of training points +number_of_inducing_points = [4, 8] # number of inducing points for SVGP models + +# kernel class +#kernel_class = Matern52 # set altern experiment = 2*j + nvmatively kernel_class = RBF + +# plotting configuration +x_lim = [0.0, 1.0] +y_lim = [-3.5, 3.5] + +# %% [markdown] +""" +We proceed by generating the training data for both experimental settings from a ground truth function which is a sample from a prior zero-mean GP with a predefined kernel (in our case, we use a `Matern52` kernel but we could have chosen an `RBF` kernel -- both of which are defined in `gpflow`). +""" + +# %% +# generate training data and evaluation points for both sets of experiments + + +list_kernels = [ Matern52(lengthscales=lengthscale), SquaredExponential(lengthscales=lengthscale) ] +#kernel = kernel_class(lengthscales=lengthscale) # kernel object to draw training dataset from + +X, y, X_star = [], [], [] # training points, training observations, and test points for evaluation + +# 1st iteration: experiments with few training points -- 2nd iteration: experiments with many training points + +for i in range(len(number_of_train_samples)): + + X_temp, y_temp, X_star_temp = [], [], [] + + # training pointsnumber_of_train_samples + X.append(np.linspace(start=X_interval[0], stop=X_interval[1], num=number_of_train_samples[i])[...,None]) + + for j in range(len(list_kernels)): + + # training observations generated from a zero-mean GP corrupted with Gaussian noise + kXX = list_kernels[j].K(X[-1]) + kXX_plus_noise_var = kXX + tf.eye(tf.shape(kXX)[0], dtype=kXX.dtype) * noise_variance + lXX = tf.linalg.cholesky(kXX_plus_noise_var) + y_temp.append( + tf.matmul(lXX, tf.random.normal([number_of_train_samples[i], 1], dtype=X[-1].dtype))[..., 0][...,None] + ) + + # test points for evaluation + X_star.append(np.linspace(start=x_lim[0], stop=x_lim[1], num=number_of_test_samples)[...,None]) + y.append(np.concatenate(y_temp, axis = -1)) + + + + + +# %% [markdown] +""" +The `for` loop below iterates through both experimental settings with few and many training examples respectively. In each iteration, the GPR model is built first (and its prediction is used as "ground truth" to compare with the remaining models) followed by the SVGP model (which requires optimisation to identify internal parameters) and the WSA model. +""" + +# %% +# create subplot frame +# 1st row: experiments with few training examples, 2nd row: experiments with many training examples :: Matern52 kernel +# 3rd row: experiments with few training examples, 4th row: experiments with many training examples :: SqExp kernel +# 1st col: exact Gaussian process regression (GPR), 2nd col: sparse variational Gaussian process model (SVGP), +# 3rd col: weight space approximation (WSA) of the exact GPR posterior with random Fourier features +fig, axs = plt.subplots(2, 2) + + +# 1st iteration: experiments with few training points -- 2nd iteration: experiments with many training points + +for experiment in range(len(number_of_train_samples)): + + # subplot titles and axis labels + axs[experiment, 0].set_title( + "Weight Space GP Matern52 $N=" + str(number_of_train_samples[experiment]) + "$" + ) + axs[experiment, 1].set_title( + "Weight Space GP SqExp $N=" + str(number_of_train_samples[experiment]) + "$" + ) + axs[experiment, 0].set_ylabel("$f(X)$") + if experiment == 1: + axs[experiment, 0].set_xlabel("$X$") + axs[experiment, 1].set_xlabel("$X$") + + # plot training point locations X and set axis limits + if ( + experiment == 0 + ): # as vertical lines for the first set of experiments with few training samples + axs[experiment, i].vlines( + X[experiment], ymin=y_lim[0], ymax=y_lim[1], colors="lightgrey" + ) + else: # as fill plots for the second set of experiments with many training samples + axs[experiment, 1].fill_between( + X[experiment].ravel(), y_lim[0], y_lim[1], color="gray", alpha=0.2 + ) + axs[experiment, 0].set_xlim(x_lim) + axs[experiment, 0].set_ylim(y_lim) + axs[experiment, 1].set_xlim(x_lim) + axs[experiment, 1].set_ylim(y_lim) + + # create exact GPR model with weight-space approximated kernel (WSA model) + + kernel1 = gpflow.kernels.Matern52(lengthscales=lengthscale) + kernel2 = gpflow.kernels.SquaredExponential(lengthscales=lengthscale) + #kernel = gpflow.kernels.SeparateIndependent( kernels = [kernel1, kernel2]) + kernel = gpflow.kernels.SharedIndependent( kernel = kernel1, output_dim = 2) + + feature_functions = MultiOutputRandomFourierFeaturesCosine(kernel, + number_of_features, + dtype=default_float()) + + feature_coefficients = np.ones((2, number_of_features, 1), dtype=default_float()) + #kernel = SeparateMultiOutputKernelWithFeatureDecomposition( + # kernel=None, feature_functions=feature_functions, feature_coefficients=feature_coefficients, + # output_dim = 2 + #) + kernel = SharedMultiOutputKernelWithFeatureDecomposition( + kernel=None, feature_functions=feature_functions, feature_coefficients=feature_coefficients, + output_dim = 2 + ) + + + print('***************************************') + print('-- shape of data for current experiment') + print(X[experiment].shape) + print(y[experiment].shape) + print(X_star[experiment].shape) + + gpr_model = GPR_deprecated( + data=(X[experiment], y[experiment]), + kernel=kernel, + noise_variance=noise_variance, + ) + + # predict function mean and variance, and draw function samples (without observation noise)# + + f_mean, f_var = gpr_model.predict_f(X_star[experiment]) + f_samples = gpr_model.predict_f_samples( + X_star[experiment], num_samples=number_of_function_samples + ) + f_mean_plus_2std = f_mean + 2 * f_var ** 0.5 + f_mean_minus_2std = f_mean - 2 * f_var ** 0.5 + + print('***************************************') + print('-- shape of current predictions') + print(f_mean.shape) + print(f_mean_minus_2std.shape) + + + # visualise WSA model predictions (mean +/- 2 * std and function samples) in the third column + + ### Matern52 ### + + axs[experiment, 0].fill_between( + X_star[experiment][...,0], + f_mean_minus_2std[..., 0], + f_mean_plus_2std[..., 0], + color="orange", + alpha=0.2, + ) + for i in range(f_samples.shape[0]): + axs[experiment, 0].plot( + X_star[experiment][...,0], f_samples[i, ..., 0], color="orange", linewidth=0.2 + ) + axs[experiment, 0].plot(X_star[experiment][...,0], f_mean[..., 0], color="orange") + + ### SquaredExponential ### + + axs[experiment, 1].fill_between( + X_star[experiment][...,0], + f_mean_minus_2std[..., 1], + f_mean_plus_2std[..., 1], + color="orange", + alpha=0.2, + ) + for i in range(f_samples.shape[0]): + axs[experiment, 1].plot( + X_star[experiment][...,0], f_samples[i, ..., 1], color="orange", linewidth=0.2 + ) + axs[experiment, 1].plot(X_star[experiment][...,0], f_mean[..., 1], color="orange") + + +# show the plot +fig.tight_layout() +plt.show() + +# %% [markdown] +""" +The results are visualised in a 2 $\times$ 3 plot with 6 subplots. The first row refers to experiments with few training data points and the second row to experiments with many training data points. The first column depicts the exact GPR model in green, the second column the SVGP model in purple and the third column the WSA model in orange. In each plot, training data points are marked in grey (as vertical bars in the first row and fill plots in the second row). We also assume the GPR model's prediction as ground truth, which is therefore plotted in all plots as black dashed lines (indicating mean +/- 2 * std). + +In each plot, the model's prediction in terms of mean +/- 2 * std is plotted through fill plots, and function samples from the (approximate) posterior through thin solid lines (thick solid lines depict mean functions in the second and third column). Note that the coloured purple circles in the second column refer to predictions at the inducing point locations of the SVGP model. + +It can be seen that, as training data points increase from the first to the second row, the predictions of the WSA model decrease drastically in areas relevant to extrapolation (i.e. close to but not inside the training data interval) because a lot of Fourier features would be required to accurately approximate a function sample drawn from a Matern kernel (because of its non-smooth nature). The same effect would be less severe for a function sample drawn from an RBF kernel that is smoother than a Matern kernel (and can hence be reliably approximated with fewer Fourier features). Note that the experiment is stochastic because the ground truth function sample from the prior kernel is random. There might be outcomes of the experiment in which the explained effect is less prominent than in other random outcomes -- so the last code block might require execution more than once to obtain a clear result. +""" diff --git a/docs/notebooks/weight_space_approximation.py b/docs/notebooks/weight_space_approximation.py index ef4b4fe4..7e8dab12 100644 --- a/docs/notebooks/weight_space_approximation.py +++ b/docs/notebooks/weight_space_approximation.py @@ -62,7 +62,7 @@ from gpflow.inducing_variables import InducingPoints from gpflux.layers.basis_functions.fourier_features import RandomFourierFeaturesCosine -from gpflux.sampling.kernel_with_feature_decomposition import KernelWithFeatureDecomposition +from gpflux.feature_decomposition_kernels import KernelWithFeatureDecomposition # %% [markdown] """ @@ -108,7 +108,7 @@ # 1st iteration: experiments with few training points -- 2nd iteration: experiments with many training points for i in range(len(number_of_train_samples)): - # training points + # training pointsnumber_of_train_samples X.append(np.linspace(start=X_interval[0], stop=X_interval[1], num=number_of_train_samples[i])) # training observations generated from a zero-mean GP corrupted with Gaussian noise diff --git a/gpflux/architectures/constant_input_dim_deep_gp.py b/gpflux/architectures/constant_input_dim_deep_gp.py index f028941c..8d5df380 100644 --- a/gpflux/architectures/constant_input_dim_deep_gp.py +++ b/gpflux/architectures/constant_input_dim_deep_gp.py @@ -88,7 +88,7 @@ def _construct_kernel(input_dim: int, is_last_layer: bool) -> SquaredExponential # something where the value scaled with the number of dimensions before lengthscales = [2.0] * input_dim return SquaredExponential(lengthscales=lengthscales, variance=variance) - +construct_kernel def build_constant_input_dim_deep_gp(X: np.ndarray, num_layers: int, config: Config) -> DeepGP: r""" diff --git a/gpflux/feature_decomposition_kernels/__init__.py b/gpflux/feature_decomposition_kernels/__init__.py new file mode 100644 index 00000000..19a6bf10 --- /dev/null +++ b/gpflux/feature_decomposition_kernels/__init__.py @@ -0,0 +1,19 @@ +from .kernel_with_feature_decomposition import ( + _ApproximateKernel, + KernelWithFeatureDecomposition, +) +from .multioutput import ( + _MultiOutputApproximateKernel, + SharedMultiOutputKernelWithFeatureDecomposition, + SeparateMultiOutputKernelWithFeatureDecomposition, +) + +__all__ = [ + "_ApproximateKernel", + "KernelWithFeatureDecomposition", + "_MultiOutputApproximateKernel", + "SharedMultiOutputKernelWithFeatureDecomposition", + "SeparateMultiOutputKernelWithFeatureDecomposition", +] + + diff --git a/gpflux/sampling/kernel_with_feature_decomposition.py b/gpflux/feature_decomposition_kernels/kernel_with_feature_decomposition.py similarity index 92% rename from gpflux/sampling/kernel_with_feature_decomposition.py rename to gpflux/feature_decomposition_kernels/kernel_with_feature_decomposition.py index bad1f80c..33b1a972 100644 --- a/gpflux/sampling/kernel_with_feature_decomposition.py +++ b/gpflux/feature_decomposition_kernels/kernel_with_feature_decomposition.py @@ -28,15 +28,15 @@ <../../../../notebooks/weight_space_approximation.ipynb>`_ for an in-depth overview. """ -from typing import Optional, Union +from typing import List, Optional, Union, Tuple import tensorflow as tf import gpflow from gpflow.base import TensorType -NoneType = type(None) +NoneType = type(None) class _ApproximateKernel(gpflow.kernels.Kernel): r""" @@ -58,37 +58,38 @@ def __init__( :param feature_functions: A Keras layer for which the call evaluates the ``L`` features of the kernel :math:`\phi_i(\cdot)`. For ``X`` with the shape ``[N, D]``, ``feature_functions(X)`` returns a tensor with the shape ``[N, L]``. - :param feature_coefficients: A tensor with the shape ``[L, 1]`` with coefficients + :param feature_coefficients: A tensor with the shape ``[L, 1]`' with coefficients associated with the features, :math:`\lambda_i`. """ - self._feature_functions = feature_functions + self._feature_functions = feature_functions # [N, L] self._feature_coefficients = feature_coefficients # [L, 1] def K(self, X: TensorType, X2: Optional[TensorType] = None) -> tf.Tensor: """Approximate the true kernel by an inner product between feature functions.""" - phi = self._feature_functions(X) # [N, L] + phi = self._feature_functions(X) # [N, L] if X2 is None: phi2 = phi else: phi2 = self._feature_functions(X2) # [N2, L] - r = tf.matmul( - phi, tf.transpose(self._feature_coefficients) * phi2, transpose_b=True + r = tf.linalg.matmul( + phi, tf.linalg.matrix_transpose(self._feature_coefficients) * phi2, transpose_b=True ) # [N, N2] N1, N2 = tf.shape(phi)[0], tf.shape(phi2)[0] + tf.debugging.assert_equal(tf.shape(r), [N1, N2]) return r def K_diag(self, X: TensorType) -> tf.Tensor: """Approximate the true kernel by an inner product between feature functions.""" - phi_squared = self._feature_functions(X) ** 2 # [N, L] - r = tf.reduce_sum(phi_squared * tf.transpose(self._feature_coefficients), axis=1) # [N,] - N = tf.shape(X)[0] + phi_squared = self._feature_functions(X) ** 2 # [N, L] + r = tf.reduce_sum(phi_squared * tf.transpose(self._feature_coefficients), axis=-1) # [N,] + N = tf.shape(X)[0] if tf.experimental.numpy.ndim(X)==1 else tf.shape(X)[0] + tf.debugging.assert_equal(tf.shape(r), [N]) # noqa: E231 return r - class KernelWithFeatureDecomposition(gpflow.kernels.Kernel): r""" This class represents a kernel together with its finite feature decomposition: @@ -156,8 +157,9 @@ def __init__( else: self._kernel = kernel - self._feature_functions = feature_functions + self._feature_functions = feature_functions # [N, L] self._feature_coefficients = feature_coefficients # [L, 1] + tf.ensure_shape(self._feature_coefficients, tf.TensorShape([None, 1])) @property @@ -175,3 +177,4 @@ def K(self, X: TensorType, X2: Optional[TensorType] = None) -> tf.Tensor: def K_diag(self, X: TensorType) -> tf.Tensor: return self._kernel.K_diag(X) + diff --git a/gpflux/feature_decomposition_kernels/multioutput/__init__.py b/gpflux/feature_decomposition_kernels/multioutput/__init__.py new file mode 100644 index 00000000..eed15c5f --- /dev/null +++ b/gpflux/feature_decomposition_kernels/multioutput/__init__.py @@ -0,0 +1,12 @@ +from .kernel_with_feature_decomposition import ( + _MultiOutputApproximateKernel, + SharedMultiOutputKernelWithFeatureDecomposition, + SeparateMultiOutputKernelWithFeatureDecomposition +) + +__all__ = [ + "_MultiOutputApproximateKernel", + "SharedMultiOutputKernelWithFeatureDecomposition", + "SeparateMultiOutputKernelWithFeatureDecomposition", +] + diff --git a/gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py b/gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py new file mode 100644 index 00000000..663aff6b --- /dev/null +++ b/gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py @@ -0,0 +1,377 @@ +# +# Copyright (c) 2021 The GPflux Contributors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +r""" +The classes in this module encapsulate kernels :math:`k(\cdot, \cdot)` with +their features :math:`\phi_i(\cdot)` and coefficients :math:`\lambda_i` so +that: + +.. math:: + + k(x, x') = \sum_{i=0}^\infty \lambda_i \phi_i(x) \phi_i(x'). + +The kernels are used for efficient sampling. See the tutorial notebooks +`Efficient sampling <../../../../notebooks/efficient_sampling.ipynb>`_ +and `Weight Space Approximation with Random Fourier Features +<../../../../notebooks/weight_space_approximation.ipynb>`_ +for an in-depth overview. +""" +from typing import Any, List, Optional, Union, Tuple + +import tensorflow as tf + +import gpflow +from gpflow.base import TensorType +from gpflow.kernels import SquaredExponential + +NoneType = type(None) + +class _MultiOutputApproximateKernel(gpflow.kernels.MultioutputKernel): + r""" + This class approximates a kernel by the finite feature decomposition: + + .. math:: k(x, x') = \sum_{i=0}^L \lambda_i \phi_i(x) \phi_i(x'), + + where :math:`\lambda_i` and :math:`\phi_i(\cdot)` are the coefficients + and features, respectively. + + """ + + def __init__( + self, + feature_functions: tf.keras.layers.Layer, + feature_coefficients: TensorType, + ): + r""" + :param feature_functions: A Keras layer for which the call evaluates the + ``L`` features of the kernel :math:`\phi_i(\cdot)`. For ``X`` with the shape ``[N, D]``, + ``feature_functions(X)`` returns a tensor with the shape ``[P, N, L]``. + :param feature_coefficients: A tensor with the shape ``[P, L, 1]`` with coefficients + associated with the features, :math:`\lambda_i`. + """ + self._feature_functions = feature_functions # [P, N, L] + self._feature_coefficients = feature_coefficients # [P, L, 1] + + @property + def num_latent_gps(self) -> int: + # In this case number of latent GPs (L) == output_dim (P) + return tf.shape(self._feature_coefficients)[0] + + @property + def latent_kernels(self) -> Any: + """In this scenario we do not have access to the underlying kernels, so we are just returning the feature_functions""" + return self._feature_functions + + def K(self, X: TensorType, X2: Optional[TensorType] = None, full_output_cov: bool = True) -> tf.Tensor: + """Approximate the true kernel by an inner product between feature functions.""" + phi = self._feature_functions(X) # [P, N, L] + + L = tf.shape(phi)[-1] + #NOTE - there are some differences between using FourierFeatures and FourierFeaturesCosine, extra check to ensure right shape and to guide debugging in notebooks + tf.debugging.assert_equal(tf.shape(self._feature_coefficients), [self.num_latent_gps, L, 1]) + + if X2 is None: + phi2 = phi + else: + phi2 = self._feature_functions(X2) # [P, N2, L] + + r = tf.linalg.matmul( + phi, tf.linalg.matrix_transpose(self._feature_coefficients) * phi2, transpose_b=True + ) # [P, N, N2] + + N1, N2 = tf.shape(phi)[1], tf.shape(phi2)[1] + tf.debugging.assert_equal(tf.shape(r), [self.num_latent_gps, N1, N2]) + return r + + def K_diag(self, X: TensorType, full_output_cov: bool = False) -> tf.Tensor: + """Approximate the true kernel by an inner product between feature functions.""" + + phi_squared = self._feature_functions(X) ** 2 # [P, N, L] + r = tf.reduce_sum(phi_squared * tf.linalg.matrix_transpose(self._feature_coefficients), axis=-1) # [P,N,] + N = tf.shape(X)[0] + + tf.debugging.assert_equal(tf.shape(r), [self.num_latent_gps, N]) # noqa: E231 + return r + + +class SharedMultiOutputKernelWithFeatureDecompositionBase(gpflow.kernels.SharedIndependent): + + """ + 'Wrapper' class to solve the issue with full_cov:bool = False inherited from gpflow.kernels.MultiOutputKernel + which doesn't work well with GPRPosterior, as it does not use dispatchers from gpflow.covariances. + #NOTE -- I think in general GPR in GPflow is only meant to be used in univariate regression settings or multivariate case but with common covariance + """ + # Overriding __call__ from gpflow.kernels.MultioutputKernel + def __call__( + self, + X: TensorType, + X2: Optional[TensorType] = None, + *, + full_cov: bool = True, #NOTE -- this needs to be set to True as not to throw errors later on + full_output_cov: bool = True, + presliced: bool = False, + ) -> tf.Tensor: + if not presliced: + X, X2 = self.slice(X, X2) + if not full_cov and X2 is not None: + raise ValueError( + "Ambiguous inputs: passing in `X2` is not compatible with `full_cov=False`." + ) + if not full_cov: + return self.K_diag(X, full_output_cov=full_output_cov) + return self.K(X, X2, full_output_cov=full_output_cov) + + +class SharedMultiOutputKernelWithFeatureDecomposition(SharedMultiOutputKernelWithFeatureDecompositionBase): + r""" + This class represents a gpflow.kernels.SharedIndependent kernel together with its finite feature decomposition: + + .. math:: k(x, x') = \sum_{i=0}^L \lambda_i \phi_i(x) \phi_i(x'), + + where :math:`\lambda_i` and :math:`\phi_i(\cdot)` are the coefficients and + features, respectively. + + The decomposition can be derived from Mercer or Bochner's theorem. For example, + feature-coefficient pairs could be eigenfunction-eigenvalue pairs (Mercer) or + Fourier features with constant coefficients (Bochner). + + In some cases (e.g., [1]_ and [2]_) the left-hand side (that is, the + covariance function :math:`k(\cdot, \cdot)`) is unknown and the kernel + can only be approximated using its feature decomposition. + In other cases (e.g., [3]_ and [4]_), both the covariance function and feature + decomposition are available in closed form. + + .. [1] + Solin, Arno, and Simo Särkkä. "Hilbert space methods for + reduced-rank Gaussian process regression." Statistics and Computing + (2020). + .. [2] + Borovitskiy, Viacheslav, et al. "Matérn Gaussian processes on + Riemannian manifolds." In Advances in Neural Information Processing + Systems (2020). + .. [3] + Ali Rahimi and Benjamin Recht. Random features for large-scale kernel + machines. In Advances in Neural Information Processing Systems (2007). + .. [4] + Dutordoir, Vincent, Nicolas Durrande, and James Hensman. "Sparse + Gaussian processes with spherical harmonic features." In International + Conference on Machine Learning (2020). + """ + + def __init__( + self, + kernel: Union[gpflow.kernels.Kernel, NoneType], + feature_functions: tf.keras.layers.Layer, + feature_coefficients: TensorType, + *, + output_dim: Optional[int] = None + ): + r""" + :param kernel: The kernel corresponding to the feature decomposition. + If ``None``, there is no analytical expression associated with the infinite + sum and we approximate the kernel based on the feature decomposition. + + .. note:: + + In certain cases, the analytical expression for the kernel is + not available. In this case, passing `None` is allowed, and + :meth:`K` and :meth:`K_diag` will be computed using the + approximation provided by the feature decomposition. + + :param feature_functions: A Keras layer for which the call evaluates the + ``L`` features of the kernel :math:`\phi_i(\cdot)`. For ``X`` with the shape ``[N, D]``, + ``feature_functions(X)`` returns a tensor with the shape ``[P, N, L]``. + :param feature_coefficients: A tensor with the shape ``[P, L, 1]`` with coefficients + associated with the features, :math:`\lambda_i`. + """ + + if kernel is None: + #NOTE -- this is a subclass of gpflow.kernels.SharedIndependent (needed to be used with dispatchers from gpflow.covariances) + # so it needs to be initialized somehow. Not sure if this is the best approach though + _dummy_kernel = SquaredExponential() + super().__init__(_dummy_kernel, output_dim) + self._kernel = _MultiOutputApproximateKernel(feature_functions, feature_coefficients) + else: + super().__init__(kernel.kernel, kernel.output_dim) + self._kernel = kernel + + self._feature_functions = feature_functions # [P, N, L] + self._feature_coefficients = feature_coefficients # [P, L, 1] + + tf.ensure_shape(self._feature_coefficients, tf.TensorShape([None, None, 1])) + + @property + def num_latent_gps(self) -> int: + return self.output_dim + + @property + def latent_kernels(self) -> Tuple[gpflow.kernels.Kernel, ...]: + """The underlying kernels in the multioutput kernel""" + if isinstance(self._kernel, _MultiOutputApproximateKernel): + return self._kernel.latent_kernels #NOTE -- this will return self._feature_functions from ApproximateKernel + else: + return (self._kernel,) + + @property + def feature_functions(self) -> tf.keras.layers.Layer: + r"""Return the kernel's features :math:`\phi_i(\cdot)`.""" + return self._feature_functions + + @property + def feature_coefficients(self) -> tf.Tensor: + r"""Return the kernel's coefficients :math:`\lambda_i`.""" + return self._feature_coefficients + + def K(self, X: TensorType, X2: Optional[TensorType] = None, full_output_cov: bool = True) -> tf.Tensor: + return self._kernel.K(X, X2, full_output_cov) + + def K_diag(self, X: TensorType, full_output_cov: bool = True) -> tf.Tensor: + return self._kernel.K_diag(X, full_output_cov) + + +class SeparateMultiOutputKernelWithFeatureDecompositionBase(gpflow.kernels.SeparateIndependent): + + """ + 'Wrapper' class to solve the issue with full_cov:bool = False inherited from gpflow.kernels.MultiOutputKernel + which doesn't work well with GPRPosterior, as it does not use dispatchers from gpflow.covariances. + #NOTE -- I think in general GPR in GPflow is only meant to be used in univariate regression settings or multivariate case but with common covariance + """ + + # Overriding __call__ from gpflow.kernels.MultioutputKernel + def __call__( + self, + X: TensorType, + X2: Optional[TensorType] = None, + *, + full_cov: bool = True, #NOTE -- this needs to be set to True as not to throw errors later on + full_output_cov: bool = True, + presliced: bool = False, + ) -> tf.Tensor: + if not presliced: + X, X2 = self.slice(X, X2) + if not full_cov and X2 is not None: + raise ValueError( + "Ambiguous inputs: passing in `X2` is not compatible with `full_cov=False`." + ) + if not full_cov: + return self.K_diag(X, full_output_cov=full_output_cov) + return self.K(X, X2, full_output_cov=full_output_cov) + + +class SeparateMultiOutputKernelWithFeatureDecomposition(SeparateMultiOutputKernelWithFeatureDecompositionBase): + r""" + This class represents a gpflow.kernel.SeparateIndependent together with its finite feature decomposition: + + .. math:: k(x, x') = \sum_{i=0}^L \lambda_i \phi_i(x) \phi_i(x'), + + where :math:`\lambda_i` and :math:`\phi_i(\cdot)` are the coefficients and + features, respectively. + + The decomposition can be derived from Mercer or Bochner's theorem. For example, + feature-coefficient pairs could be eigenfunction-eigenvalue pairs (Mercer) or + Fourier features with constant coefficients (Bochner). + + In some cases (e.g., [1]_ and [2]_) the left-hand side (that is, the + covariance function :math:`k(\cdot, \cdot)`) is unknown and the kernel + can only be approximated using its feature decomposition. + In other cases (e.g., [3]_ and [4]_), both the covariance function and feature + decomposition are available in closed form. + + .. [1] + Solin, Arno, and Simo Särkkä. "Hilbert space methods for + reduced-rank Gaussian process regression." Statistics and Computing + (2020). + .. [2] + Borovitskiy, Viacheslav, et al. "Matérn Gaussian processes on + Riemannian manifolds." In Advances in Neural Information Processing + Systems (2020). + .. [3] + Ali Rahimi and Benjamin Recht. Random features for large-scale kernel + machines. In Advances in Neural Information Processing Systems (2007). + .. [4] + Dutordoir, Vincent, Nicolas Durrande, and James Hensman. "Sparse + Gaussian processes with spherical harmonic features." In International + Conference on Machine Learning (2020). + """ + + def __init__( + self, + kernel: Union[gpflow.kernels.Kernel, NoneType], + feature_functions: tf.keras.layers.Layer, + feature_coefficients: TensorType, + *, + output_dim: Optional[int] = None + ): + r""" + :param kernel: The kernel corresponding to the feature decomposition. + If ``None``, there is no analytical expression associated with the infinite + sum and we approximate the kernel based on the feature decomposition. + + .. note:: + + In certain cases, the analytical expression for the kernel is + not available. In this case, passing `None` is allowed, and + :meth:`K` and :meth:`K_diag` will be computed using thekernel + approximation provided by the feature decomposition. + + :param feature_functions: A Keras layer for which the call evaluates the + ``L`` features of the kernel :math:`\phi_i(\cdot)`. For ``X`` with the shape ``[N, D]``, + ``feature_functions(X)`` returns a tensor with the shape ``[P, N, L]``. + :param feature_coefficients: A tensor with the shape ``[P, L, 1]`` with coefficients + associated with the features, :math:`\lambda_i`. + """ + + if kernel is None: + #NOTE -- this is a subclass of gpflow.kernels.SeparateIndependent (needed to be used with dispatchers from gpflow.covariances) + # so it needs to be initialized somehow. Not sure if this is the best approach though + _dummy_kernels = [SquaredExponential() for _ in range(output_dim)] + super().__init__(_dummy_kernels) + self._kernel = _MultiOutputApproximateKernel(feature_functions, feature_coefficients) + else: + + super().__init__(kernel.kernels) + self._kernel = kernel + + self._feature_functions = feature_functions # [P, N, L] + self._feature_coefficients = feature_coefficients # [P, L, 1] + + tf.ensure_shape(self._feature_coefficients, tf.TensorShape([None, None, 1])) + + @property + def num_latent_gps(self) -> int: + + return len(self._kernel.kernels) + + @property + def latent_kernels(self) -> Tuple[gpflow.kernels.Kernel, ...]: + """The underlying kernels in the multioutput kernel""" + return tuple(self._kernel.kernels) + + @property + def feature_functions(self) -> tf.keras.layers.Layer: + r"""Return the kernel's features :math:`\phi_i(\cdot)`.""" + return self._feature_functions + + @property + def feature_coefficients(self) -> tf.Tensor: + r"""Return the kernel's coefficients :math:`\lambda_i`.""" + return self._feature_coefficients + + def K(self, X: TensorType, X2: Optional[TensorType] = None, full_output_cov: bool = True) -> tf.Tensor: + return self._kernel.K(X, X2, full_output_cov) + + def K_diag(self, X: TensorType, full_output_cov: bool = False) -> tf.Tensor: + return self._kernel.K_diag(X, full_output_cov) + diff --git a/gpflux/layers/basis_functions/fourier_features/__init__.py b/gpflux/layers/basis_functions/fourier_features/__init__.py index 42c09d47..ea293c9b 100644 --- a/gpflux/layers/basis_functions/fourier_features/__init__.py +++ b/gpflux/layers/basis_functions/fourier_features/__init__.py @@ -25,9 +25,16 @@ RandomFourierFeaturesCosine, ) +from gpflux.layers.basis_functions.fourier_features.multioutput.random import ( + MultiOutputRandomFourierFeatures, + MultiOutputRandomFourierFeaturesCosine, +) + __all__ = [ - "QuadratureFourierFeatures", + "QuadratureFourierFeatures", "OrthogonalRandomFeatures", "RandomFourierFeatures", "RandomFourierFeaturesCosine", + "MultiOutputRandomFourierFeatures", + "MultiOutputRandomFourierFeaturesCosine", ] diff --git a/gpflux/layers/basis_functions/fourier_features/base.py b/gpflux/layers/basis_functions/fourier_features/base.py index 80461c80..272fca92 100644 --- a/gpflux/layers/basis_functions/fourier_features/base.py +++ b/gpflux/layers/basis_functions/fourier_features/base.py @@ -22,10 +22,8 @@ import gpflow from gpflow.base import TensorType - from gpflux.types import ShapeType - class FourierFeaturesBase(ABC, tf.keras.layers.Layer): def __init__(self, kernel: gpflow.kernels.Kernel, n_components: int, **kwargs: Mapping): """ @@ -48,11 +46,12 @@ def call(self, inputs: TensorType) -> tf.Tensor: :param inputs: The evaluation points, a tensor with the shape ``[N, D]``. - :return: A tensor with the shape ``[N, M]``. + :return: A tensor with the shape ``[N, M]``.mypy """ - X = tf.divide(inputs, self.kernel.lengthscales) # [N, D] - const = self._compute_constant() - bases = self._compute_bases(X) + + X = tf.divide(inputs, self.kernel.lengthscales) # [N, D] + const = self._compute_constant() + bases = self._compute_bases(X) output = const * bases tf.ensure_shape(output, self.compute_output_shape(inputs.shape)) return output @@ -65,6 +64,7 @@ def compute_output_shape(self, input_shape: ShapeType) -> tf.TensorShape: """ # TODO: Keras docs say "If the layer has not been built, this method # will call `build` on the layer." -- do we need to do so? + tensor_shape = tf.TensorShape(input_shape).with_rank(2) output_dim = self._compute_output_dim(input_shape) return tensor_shape[:-1].concatenate(output_dim) diff --git a/gpflux/layers/basis_functions/fourier_features/multioutput/__init__.py b/gpflux/layers/basis_functions/fourier_features/multioutput/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/gpflux/layers/basis_functions/fourier_features/multioutput/base.py b/gpflux/layers/basis_functions/fourier_features/multioutput/base.py new file mode 100644 index 00000000..b5fb9b04 --- /dev/null +++ b/gpflux/layers/basis_functions/fourier_features/multioutput/base.py @@ -0,0 +1,128 @@ +# +# Copyright (c) 2021 The GPflux Contributors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +""" Shared functionality for stationary kernel basis functions. """ + +from abc import ABC, abstractmethod +from typing import Mapping +from warnings import WarningMessage + +import tensorflow as tf + +import gpflow +from gpflow.base import TensorType +from gpflux.types import ShapeType + +class MultiOutputFourierFeaturesBase(ABC, tf.keras.layers.Layer): + def __init__(self, kernel: gpflow.kernels.MultioutputKernel, n_components: int, **kwargs: Mapping): + """ + :param kernel: kernel to approximate using a set of Fourier bases. Expects a Multioutput Kernel + :param n_components: number of components (e.g. Monte Carlo samples, + quadrature nodes, etc.) used to numerically approximate the kernel. + """ + super(MultiOutputFourierFeaturesBase, self).__init__(**kwargs) + self.kernel = kernel + self.n_components = n_components + if kwargs.get("input_dim", None): + self._input_dim = kwargs["input_dim"] + self.build(tf.TensorShape([self._input_dim])) + else: + self._input_dim = None + + def call(self, inputs: TensorType) -> tf.Tensor: + """ + Evaluate the basis functions at ``inputs``. + + :param inputs: The evaluation points, a tensor with the shape ``[N, D]``. + + :return: A tensor with the shape ``[P, N, M]``.mypy + """ + + P = self.kernel.num_latent_gps + D = tf.shape(inputs)[-1] + + if isinstance(self.kernel, gpflow.kernels.SeparateIndependent): + + for kernel in self.kernel.kernels: + print(kernel.lengthscales.unconstrained_variable.value()) + + _lengthscales = tf.concat([ kernel.lengthscales[None, None, ...] if tf.rank(kernel.lengthscales.unconstrained_variable.value()) == 1 + else kernel.lengthscales[None, None, None, ...] for kernel in self.kernel.kernels], axis = 0) # [P, 1, D] + print('size -f _lengthscales') + print(_lengthscales) + tf.debugging.assert_equal(tf.shape(_lengthscales), [P, 1, D]) + + elif isinstance(self.kernel, gpflow.kernels.SharedIndependent): + #NOTE -- each kernel.kernel.lengthscales has to be of the shape [D,] + _lengthscales = tf.tile(self.kernel.kernel.lengthscales[None, None, ...] if tf.rank(self.kernel.kernel.lengthscales.unconstrained_variable.value()) == 1 + else self.kernel.kernel.lengthscales[None, None, None, ...] , + [P, 1, 1]) # [P, 1, D] + tf.debugging.assert_equal(tf.shape(_lengthscales), [P, 1, D]) + else: + raise ValueError("kernel is not supported. Must be either gpflow.kernels.SharedIndependent or gpflow.kernels.SeparateIndependent") + + X = tf.divide(inputs, # [N, D] in the case that we predict at X*, in case we want to get the Fourier Features for Z, this would correspond to [P, M, D] + _lengthscales # [P, 1, D] + ) # [P, N, D] or [P, M, D] + const = self._compute_constant()[...,None,None] # [P,1,1] + bases = self._compute_bases(X) # [P, N, L] for X*, or [P,M,L] in the case of Z + output = const * bases # [P, N, L] for X*, or [P,M,L] in the case of Z + + tf.ensure_shape(output, self.compute_output_shape(X.shape)) + return output + + def compute_output_shape(self, input_shape: ShapeType) -> tf.TensorShape: + """ + Computes the output shape of the layer. + See `tf.keras.layers.Layer.compute_output_shape() + `_. + """ + # TODO: Keras docs say "If the layer has not been built, this method + # will call `build` on the layer." -- do we need to do so? + + tensor_shape = tf.TensorShape(input_shape).with_rank(3) + output_dim = self._compute_output_dim(input_shape) + return tensor_shape[:-1].concatenate(output_dim) + + def get_config(self) -> Mapping: + """ + Returns the config of the layer. + See `tf.keras.layers.Layer.get_config() + `_. + """ + config = super(MultiOutputFourierFeaturesBase, self).get_config() + config.update( + {"kernel": self.kernel, "n_components": self.n_components, "input_dim": self._input_dim} + ) + + return config + + @abstractmethod + def _compute_output_dim(self, input_shape: ShapeType) -> int: + pass + + @abstractmethod + def _compute_constant(self) -> tf.Tensor: + """ + Compute normalizing constant for basis functions. + """ + pass + + @abstractmethod + def _compute_bases(self, inputs: TensorType) -> tf.Tensor: + """ + Compute basis functions. + """ + pass diff --git a/gpflux/layers/basis_functions/fourier_features/multioutput/random/__init__.py b/gpflux/layers/basis_functions/fourier_features/multioutput/random/__init__.py new file mode 100644 index 00000000..eeb21834 --- /dev/null +++ b/gpflux/layers/basis_functions/fourier_features/multioutput/random/__init__.py @@ -0,0 +1,26 @@ +# +# Copyright (c) 2021 The GPflux Contributors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +""" A kernel's features and coefficients using Random Fourier Features (RFF). """ + +from gpflux.layers.basis_functions.fourier_features.multioutput.random.base import ( + MultiOutputRandomFourierFeatures, + MultiOutputRandomFourierFeaturesCosine, +) + +__all__ = [ + "MultiOutputRandomFourierFeatures", + "MultiOutputRandomFourierFeaturesCosine", +] diff --git a/gpflux/layers/basis_functions/fourier_features/multioutput/random/base.py b/gpflux/layers/basis_functions/fourier_features/multioutput/random/base.py new file mode 100644 index 00000000..586cfd1d --- /dev/null +++ b/gpflux/layers/basis_functions/fourier_features/multioutput/random/base.py @@ -0,0 +1,284 @@ +# +# Copyright (c) 2021 The GPflux Contributors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from multiprocessing.sharedctypes import Value +from typing import Mapping, Optional, Tuple, Type + +import numpy as np +import tensorflow as tf + +import gpflow +from gpflow.base import DType, TensorType + +from gpflux.layers.basis_functions.fourier_features.multioutput.base import MultiOutputFourierFeaturesBase +from gpflux.layers.basis_functions.fourier_features.utils import ( + _bases_concat, + _bases_cosine, + _matern_number, +) +from gpflux.types import ShapeType + +""" +Kernels supported by :class:`RandomFourierFeatures`. + +You can build RFF for shift-invariant stationary kernels from which you can +sample frequencies from their power spectrum, following Bochner's theorem. +""" +RFF_SUPPORTED_KERNELS: Tuple[Type[gpflow.kernels.Stationary], ...] = ( + gpflow.kernels.SquaredExponential, + gpflow.kernels.Matern12, + gpflow.kernels.Matern32, + gpflow.kernels.Matern52, +) + +def _sample_students_t(nu: float, shape: ShapeType, dtype: DType) -> TensorType: + """ + Draw samples from a (central) Student's t-distribution using the following: + BETA ~ Gamma(nu/2, nu/2) (shape-rate parameterization) + X ~ Normal(0, 1/BETA) + then: + X ~ StudentsT(nu) + + Note this is equivalent to the more commonly used parameterization + Z ~ Chi2(nu) = Gamma(nu/2, 1/2) + EPSILON ~ Normal(0, 1) + X = EPSILON * sqrt(nu/Z) + + To see this, note + Z/nu ~ Gamma(nu/2, nu/2) + and + X ~ Normal(0, nu/Z) + The equivalence becomes obvious when we set BETA = Z/nu + """ + # Normal(0, 1) + normal_rvs = tf.random.normal(shape=shape, dtype=dtype) + shape = tf.concat([shape[:-1], [1]], axis=0) + # Gamma(nu/2, nu/2) + gamma_rvs = tf.random.gamma(shape, alpha=0.5 * nu, beta=0.5 * nu, dtype=dtype) + # StudentsT(nu) + students_t_rvs = tf.math.rsqrt(gamma_rvs) * normal_rvs + return students_t_rvs + + +class MultiOutputRandomFourierFeaturesBase(MultiOutputFourierFeaturesBase): + def __init__(self, kernel: gpflow.kernels.MultioutputKernel, n_components: int, **kwargs: Mapping): + + if isinstance(kernel, gpflow.kernels.SeparateIndependent): + for ker in kernel.kernels: + assert isinstance(ker, RFF_SUPPORTED_KERNELS), "Unsupported Kernel" + elif isinstance(kernel, gpflow.kernels.SharedIndependent): + assert isinstance(kernel.kernel, RFF_SUPPORTED_KERNELS), "Unsupported Kernel" + else: + raise ValueError("kernel specified is not supported.") + super(MultiOutputRandomFourierFeaturesBase, self).__init__(kernel, n_components, **kwargs) + + def build(self, input_shape: ShapeType) -> None: + """ + Creates the variables of the layer. + See `tf.keras.layers.Layer.build() + `_. + """ + input_dim = input_shape[-1] + self._weights_build(input_dim, n_components=self.n_components) + super(MultiOutputRandomFourierFeaturesBase, self).build(input_shape) + + def _weights_build(self, input_dim: int, n_components: int) -> None: + + shape = (self.kernel.num_latent_gps, n_components, input_dim) + + self.W = self.add_weight( + name="weights", + trainable=False, + shape=shape, + dtype=self.dtype, + initializer=self._weights_init, + ) + tf.ensure_shape(self.W, shape) + + def _weights_init(self, shape: TensorType, dtype: Optional[DType] = None) -> TensorType: + + if isinstance(self.kernel, gpflow.kernels.SeparateIndependent): + + list_inits = [] + for ker in self.kernel.kernels: + if isinstance(ker, gpflow.kernels.SquaredExponential): + list_inits.append(tf.random.normal(shape[1:], dtype=dtype)) + else: + p = _matern_number(ker) + nu = 2.0 * p + 1.0 # degrees of freedom + list_inits.append(_sample_students_t(nu, shape[1:], dtype)) + return tf.stack(list_inits, axis=0) + + elif isinstance(self.kernel, gpflow.kernels.SharedIndependent): + + if isinstance(self.kernel.kernel, gpflow.kernels.SquaredExponential): + return tf.random.normal(shape, dtype=dtype) + else: + p = _matern_number(self.kernel.kernel) + nu = 2.0 * p + 1.0 # degrees of freedom + return _sample_students_t(nu, shape, dtype) + else: + raise ValueError("kernel is not supported. Must be either gpflow.kernels.SharedIndependent or gpflow.kernels.SeparateIndependent") + + @staticmethod + def rff_constant(variance: TensorType, output_dim: int) -> tf.Tensor: + """ + Normalizing constant for random Fourier features. + """ + return tf.sqrt(tf.math.truediv(2.0 * variance, output_dim)) + + +class MultiOutputRandomFourierFeatures(MultiOutputRandomFourierFeaturesBase): + r""" + Random Fourier features (RFF) is a method for approximating kernels. The essential + element of the RFF approach :cite:p:`rahimi2007random` is the realization that Bochner's theorem + for stationary kernels can be approximated by a Monte Carlo sum. + + We will approximate the kernel :math:`k(\mathbf{x}, \mathbf{x}')` + by :math:`\Phi(\mathbf{x})^\top \Phi(\mathbf{x}')` + where :math:`\Phi: \mathbb{R}^{D} \to \mathbb{R}^{M}` is a finite-dimensional feature map. + + The feature map is defined as: + + .. math:: + + \Phi(\mathbf{x}) = \sqrt{\frac{2 \sigma^2}{\ell}} + \begin{bmatrix} + \cos(\boldsymbol{\theta}_1^\top \mathbf{x}) \\ + \sin(\boldsymbol{\theta}_1^\top \mathbf{x}) \\ + \vdots \\ + \cos(\boldsymbol{\theta}_{\frac{M}{2}}^\top \mathbf{x}) \\ + \sin(\boldsymbol{\theta}_{\frac{M}{2}}^\top \mathbf{x}) + \end{bmatrix} + + where :math:`\sigma^2` is the kernel variance. + The features are parameterised by random weights: + + - :math:`\boldsymbol{\theta} \sim p(\boldsymbol{\theta})` + where :math:`p(\boldsymbol{\theta})` is the spectral density of the kernel. + + At least for the squared exponential kernel, this variant of the feature + mapping has more desirable theoretical properties than its counterpart form + from phase-shifted cosines :class:`RandomFourierFeaturesCosine` :cite:p:`sutherland2015error`. + """ + + def _compute_output_dim(self, input_shape: ShapeType) -> int: + return 2 * self.n_components + + def _compute_bases(self, inputs: TensorType) -> tf.Tensor: + """ + Compute basis functions. + + :return: A tensor with the shape ``[P, N, 2M]`` . + """ + return _bases_concat(inputs, self.W) + + def _compute_constant(self) -> tf.Tensor: + """ + Compute normalizing constant for basis functions. + + :return: A tensor with the shape ``[]`` (i.e. a scalar). + """ + + if hasattr(self.kernel, "kernels"): + _kernel_variance = tf.stack([ker.variance for ker in self.kernel.kernels], axis = 0) + tf.ensure_shape(_kernel_variance, [self.kernel.num_latent_gps,]) + + else: + _kernel_variance = self.kernel.kernel.variance + + return self.rff_constant(_kernel_variance, output_dim=2 * self.n_components) + + +class MultiOutputRandomFourierFeaturesCosine(MultiOutputRandomFourierFeaturesBase): + r""" + Random Fourier Features (RFF) is a method for approximating kernels. The essential + element of the RFF approach :cite:p:`rahimi2007random` is the realization that Bochner's theorem + for stationary kernels can be approximated by a Monte Carlo sum. + + We will approximate the kernel :math:`k(\mathbf{x}, \mathbf{x}')` + by :math:`\Phi(\mathbf{x})^\top \Phi(\mathbf{x}')` where + :math:`\Phi: \mathbb{R}^{D} \to \mathbb{R}^{M}` is a finite-dimensional feature map. + + The feature map is defined as: + + .. math:: + \Phi(\mathbf{x}) = \sqrt{\frac{2 \sigma^2}{\ell}} + \begin{bmatrix} + \cos(\boldsymbol{\theta}_1^\top \mathbf{x} + \tau) \\ + \vdots \\ + \cos(\boldsymbol{\theta}_M^\top \mathbf{x} + \tau) + \end{bmatrix} + + where :math:`\sigma^2` is the kernel variance. + The features are parameterised by random weights: + + - :math:`\boldsymbol{\theta} \sim p(\boldsymbol{\theta})` + where :math:`p(\boldsymbol{\theta})` is the spectral density of the kernel + - :math:`\tau \sim \mathcal{U}(0, 2\pi)` + + Equivalent to :class:`RandomFourierFeatures` by elementary trigonometric identities. + """ + + def build(self, input_shape: ShapeType) -> None: + """ + Creates the variables of the layer. + See `tf.keras.layers.Layer.build() + `_. + """ + self._bias_build(n_components=self.n_components) + super(MultiOutputRandomFourierFeaturesCosine, self).build(input_shape) + + def _bias_build(self, n_components: int) -> None: + + shape = (self.kernel.num_latent_gps, 1, n_components) + + self.b = self.add_weight( + name="bias", + trainable=False, + shape=shape, + dtype=self.dtype, + initializer=self._bias_init, + ) + + def _bias_init(self, shape: TensorType, dtype: Optional[DType] = None) -> TensorType: + return tf.random.uniform(shape=shape, maxval=2.0 * np.pi, dtype=dtype) + + def _compute_output_dim(self, input_shape: ShapeType) -> int: + return self.n_components + + def _compute_bases(self, inputs: TensorType) -> tf.Tensor: + """ + Compute basis functions. + + :return: A tensor with the shape ``[N, M]``. + """ + return _bases_cosine(inputs, self.W, self.b) + + def _compute_constant(self) -> tf.Tensor: + """ + Compute normalizing constant for basis functions. + + :return: A tensor with the shape ``[]`` (i.e. a scalar). + """ + + if hasattr(self.kernel, "kernels"): + _kernel_variance = tf.stack([ker.variance for ker in self.kernel.kernels], axis = 0) + tf.ensure_shape(_kernel_variance, [self.kernel.num_latent_gps,]) + else: + _kernel_variance = self.kernel.kernel.variance + + return self.rff_constant(_kernel_variance, output_dim=self.n_components) + diff --git a/gpflux/layers/basis_functions/fourier_features/utils.py b/gpflux/layers/basis_functions/fourier_features/utils.py index 71372e9e..7866974d 100644 --- a/gpflux/layers/basis_functions/fourier_features/utils.py +++ b/gpflux/layers/basis_functions/fourier_features/utils.py @@ -21,7 +21,6 @@ import gpflow from gpflow.base import TensorType - def _matern_number(kernel: gpflow.kernels.Kernel) -> int: if isinstance(kernel, gpflow.kernels.Matern52): p = 2 @@ -33,15 +32,14 @@ def _matern_number(kernel: gpflow.kernels.Kernel) -> int: raise NotImplementedError("Not a recognized Matern kernel") return p - def _bases_cosine(X: TensorType, W: TensorType, b: TensorType) -> TensorType: """ Feature map for random Fourier features (RFF) as originally prescribed by Rahimi & Recht, 2007 :cite:p:`rahimi2007random`. See also :cite:p:`sutherland2015error` for additional details. """ - proj = tf.matmul(X, W, transpose_b=True) + b # [N, M] - return tf.cos(proj) # [N, M] + proj = tf.matmul(X, W, transpose_b=True) + b # [N, M] or [P, N, M] + return tf.cos(proj) # [N, M] or [P, N, M] def _bases_concat(X: TensorType, W: TensorType) -> TensorType: @@ -50,5 +48,5 @@ def _bases_concat(X: TensorType, W: TensorType) -> TensorType: by Rahimi & Recht, 2007 :cite:p:`rahimi2007random`. See also :cite:p:`sutherland2015error` for additional details. """ - proj = tf.matmul(X, W, transpose_b=True) # [N, M] - return tf.concat([tf.sin(proj), tf.cos(proj)], axis=-1) # [N, 2M] + proj = tf.matmul(X, W, transpose_b=True) # [N, M] or [P, N, M] + return tf.concat([tf.sin(proj), tf.cos(proj)], axis=-1) # [N, 2M] or [P, N, 2M] \ No newline at end of file diff --git a/gpflux/layers/gp_layer.py b/gpflux/layers/gp_layer.py index a9324555..16e03aa5 100644 --- a/gpflux/layers/gp_layer.py +++ b/gpflux/layers/gp_layer.py @@ -208,6 +208,10 @@ def __init__( num_latent_gps, ) + print('**************888') + print(num_inducing) + print(self.num_latent_gps) + self.q_mu = Parameter( np.zeros((num_inducing, self.num_latent_gps)), dtype=default_float(), diff --git a/gpflux/sampling/__init__.py b/gpflux/sampling/__init__.py index 2c19c792..a62d6c2c 100644 --- a/gpflux/sampling/__init__.py +++ b/gpflux/sampling/__init__.py @@ -16,5 +16,12 @@ """ This module enables you to sample from (Deep) GPs efficiently and consistently. """ -from gpflux.sampling.kernel_with_feature_decomposition import KernelWithFeatureDecomposition -from gpflux.sampling.sample import efficient_sample + +from . import sample, multioutput +from .dispatch import efficient_sample + +__all__ = [ + "efficient_sample", + "sample", + "multioutput", +] \ No newline at end of file diff --git a/gpflux/sampling/dispatch.py b/gpflux/sampling/dispatch.py new file mode 100644 index 00000000..116daab3 --- /dev/null +++ b/gpflux/sampling/dispatch.py @@ -0,0 +1,6 @@ +from gpflow.utilities import Dispatcher + +efficient_sample = Dispatcher("efficient_sample") + + + diff --git a/gpflux/sampling/multioutput/__init__.py b/gpflux/sampling/multioutput/__init__.py new file mode 100644 index 00000000..8cf871f2 --- /dev/null +++ b/gpflux/sampling/multioutput/__init__.py @@ -0,0 +1,5 @@ +from . import sample + +__all__ = [ + "sample", +] diff --git a/gpflux/sampling/multioutput/sample.py b/gpflux/sampling/multioutput/sample.py new file mode 100644 index 00000000..3b963f04 --- /dev/null +++ b/gpflux/sampling/multioutput/sample.py @@ -0,0 +1,157 @@ +# +# Copyright (c) 2021 The GPflux Contributors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +""" This module enables you to sample from (Deep) GPs using different approaches. """ + +import abc +from multiprocessing.sharedctypes import Value +from pickle import TRUE +from typing import Callable, Optional, Union + +import tensorflow as tf + +from gpflow.base import TensorType +from gpflow.conditionals import conditional +from gpflow.config import default_float, default_jitter +from gpflow.covariances import Kuf, Kuu +from gpflow.inducing_variables import MultioutputInducingVariables, SharedIndependentInducingVariables, SeparateIndependentInducingVariables +from gpflow.kernels import Kernel, SeparateIndependent, SharedIndependent, MultioutputKernel +from gpflow.utilities import Dispatcher + +from gpflux.math import compute_A_inv_b +from gpflux.feature_decomposition_kernels import SharedMultiOutputKernelWithFeatureDecomposition, SeparateMultiOutputKernelWithFeatureDecomposition +from ..sample import Sample +from ..dispatch import efficient_sample + + + +@efficient_sample.register(MultioutputInducingVariables, (SharedMultiOutputKernelWithFeatureDecomposition, SeparateMultiOutputKernelWithFeatureDecomposition), object) +def _efficient_multi_output_sample_matheron_rule( + inducing_variable: MultioutputInducingVariables, + kernel: Union[SharedMultiOutputKernelWithFeatureDecomposition, SeparateMultiOutputKernelWithFeatureDecomposition], + q_mu: tf.Tensor, + *, + q_sqrt: Optional[TensorType] = None, + whiten: bool = False, +) -> Sample: + """ + Implements the efficient sampling rule from :cite:t:`wilson2020efficiently` using + the Matheron rule. To use this sampling scheme, the GP has to have a + ``kernel`` of the :class:`KernelWithFeatureDecomposition` type . + + :param kernel: A kernel of the :class:`KernelWithFeatureDecomposition` type, which + holds the covariance function and the kernel's features and + coefficients. + :param q_mu: A tensor with the shape ``[M, P]``. + :param q_sqrt: A tensor with the shape ``[P, M, M]``. + :param whiten: Determines the parameterisation of the inducing variables. + """ + + # Reshape kernel.feature_coefficients + _feature_coefficients = tf.transpose(kernel.feature_coefficients[...,0]) # [L,P] + + L = tf.shape(_feature_coefficients)[0] # num eigenfunctions # noqa: F841 + M, P = tf.shape(q_mu)[0], tf.shape(q_mu)[1] # num inducing, num output heads + + + prior_weights = tf.sqrt(_feature_coefficients) * tf.random.normal( + (L, P), dtype=default_float() # [L, P], [L,P] + ) # [L, P] + + u_sample_noise = tf.matmul( + q_sqrt, + tf.random.normal((P, M, 1), dtype=default_float()), # [P, M, M] # [P, M, 1] + ) # [P, M, 1] + tf.debugging.assert_equal(tf.shape(u_sample_noise), [P, M, 1]) + + if isinstance(kernel, SharedIndependent): + Kmm = tf.tile(Kuu(inducing_variable, kernel, jitter=default_jitter())[None,...] ,[P, 1, 1]) # [P,M,M] + tf.debugging.assert_equal(tf.shape(Kmm), [P, M, M]) + elif isinstance(kernel, SeparateIndependent): + Kmm = Kuu(inducing_variable, kernel, jitter=default_jitter()) # [P,M,M] + tf.debugging.assert_equal(tf.shape(Kmm), [P, M, M]) + else: + raise ValueError("kernel not supported. Must be either SharedIndependent or SeparateIndependent") + + tf.debugging.assert_equal(tf.shape(Kmm), [P, M, M]) + + u_sample = q_mu + tf.linalg.matrix_transpose(u_sample_noise[..., 0]) # [M, P] + tf.debugging.assert_equal(tf.shape(u_sample), [M, P]) + + if whiten: + Luu = tf.linalg.cholesky(Kmm) # [P,M,M] + tf.debugging.assert_equal(tf.shape(Kmm), [P,M,M]) + + u_sample = tf.transpose(tf.matmul(Luu, # [P, M, M] + tf.transpose(u_sample)[...,None] # [P, M, 1] + )[...,0]) # [M, P] + tf.debugging.assert_equal(tf.shape(u_sample), [M, P]) + + if isinstance(inducing_variable, SeparateIndependentInducingVariables): + + _inducing_variable_list = [] + for ind_var in inducing_variable.inducing_variable_list: + _inducing_variable_list.append(ind_var.Z) + _inducing_variable_list = tf.stack(_inducing_variable_list, axis=0) + + phi_Z = kernel.feature_functions(_inducing_variable_list) # [P, M, L] + tf.debugging.assert_equal(tf.shape(phi_Z), [P, M, L]) + + elif isinstance(inducing_variable, SharedIndependentInducingVariables): + + phi_Z = kernel.feature_functions(inducing_variable.inducing_variable.Z) # [P, M, L] + tf.debugging.assert_equal(tf.shape(phi_Z), [P, M, L]) + else: + raise ValueError("inducing variable is not supported. Must be either SharedIndependentInducingVariables or SeparateIndependentInducingVariables") + + weight_space_prior_Z = tf.matmul( phi_Z, # [P, M, L] + tf.transpose(prior_weights)[...,None] # [P, L, 1] + ) # [P, M, 1] + weight_space_prior_Z = tf.transpose(weight_space_prior_Z[...,0]) # [M, P] + + diff = tf.transpose(u_sample - weight_space_prior_Z)[..., None] # [P, M, 1] + v = tf.transpose(compute_A_inv_b(Kmm, #[P, M, M] + diff # [P, M, 1] + )[...,0]) # [M, P] + + tf.debugging.assert_equal(tf.shape(v), [M, P]) + + class WilsonSample(Sample): + def __call__(self, X: TensorType) -> tf.Tensor: + """ + :param X: evaluation points [N, D] + :return: function value of sample [N, P] + """ + N = tf.shape(X)[0] + phi_X = kernel.feature_functions(X) # [P, N, L] + + weight_space_prior_X = tf.transpose(tf.matmul(phi_X, # [P, N, L] + tf.transpose(prior_weights)[..., None] # [P, L, 1] + )[...,0]) # [N, P] + + Knm = tf.linalg.matrix_transpose(Kuf(inducing_variable, kernel, X)) # [P, N, M] or [N,M] + if isinstance(inducing_variable, SharedIndependentInducingVariables): + Knm = tf.tile(Knm[None,...], [P,1,1]) + tf.debugging.assert_equal(tf.shape(Knm), [P, N, M]) + function_space_update_X = tf.transpose(tf.matmul(Knm, # [P, N, M] + tf.transpose(v)[..., None] # [P, M, 1] + )[...,0]) # [N, P] + + tf.debugging.assert_equal(tf.shape(weight_space_prior_X), [N, P]) + tf.debugging.assert_equal(tf.shape(function_space_update_X), [N, P]) + + return weight_space_prior_X + function_space_update_X # [N, P] + + return WilsonSample() diff --git a/gpflux/sampling/sample.py b/gpflux/sampling/sample.py index 5b7b8c36..15d3e11e 100644 --- a/gpflux/sampling/sample.py +++ b/gpflux/sampling/sample.py @@ -16,6 +16,7 @@ """ This module enables you to sample from (Deep) GPs using different approaches. """ import abc +from pickle import TRUE from typing import Callable, Optional, Union import tensorflow as tf @@ -25,14 +26,15 @@ from gpflow.config import default_float, default_jitter from gpflow.covariances import Kuf, Kuu from gpflow.inducing_variables import InducingVariables -from gpflow.kernels import Kernel +from gpflow.kernels import Kernel, SeparateIndependent, SharedIndependent from gpflow.utilities import Dispatcher from gpflux.math import compute_A_inv_b -from gpflux.sampling.kernel_with_feature_decomposition import KernelWithFeatureDecomposition +from gpflux.feature_decomposition_kernels import KernelWithFeatureDecomposition, _ApproximateKernel from gpflux.sampling.utils import draw_conditional_sample -efficient_sample = Dispatcher("efficient_sample") +from .dispatch import efficient_sample + """ A function that returns a :class:`Sample` of a GP posterior. """ @@ -133,7 +135,6 @@ def __call__(self, X_new: TensorType) -> tf.Tensor: return SampleConditional() - @efficient_sample.register(InducingVariables, KernelWithFeatureDecomposition, object) def _efficient_sample_matheron_rule( inducing_variable: InducingVariables, @@ -155,29 +156,36 @@ def _efficient_sample_matheron_rule( :param q_sqrt: A tensor with the shape ``[P, M, M]``. :param whiten: Determines the parameterisation of the inducing variables. """ + L = tf.shape(kernel.feature_coefficients)[0] # num eigenfunctions # noqa: F841 M, P = tf.shape(q_mu)[0], tf.shape(q_mu)[1] # num inducing, num output heads prior_weights = tf.sqrt(kernel.feature_coefficients) * tf.random.normal( - (L, P), dtype=default_float() + (L, P), dtype=default_float() # [L, 1], [L,P] ) # [L, P] u_sample_noise = tf.matmul( - q_sqrt, + q_sqrt, tf.random.normal((P, M, 1), dtype=default_float()), # [P, M, M] # [P, M, 1] ) # [P, M, 1] - Kmm = Kuu(inducing_variable, kernel, jitter=default_jitter()) # [M, M] + Kmm = Kuu(inducing_variable, kernel, jitter=default_jitter()) # [M, M] + tf.debugging.assert_equal(tf.shape(Kmm), [M, M]) u_sample = q_mu + tf.linalg.matrix_transpose(u_sample_noise[..., 0]) # [M, P] if whiten: - Luu = tf.linalg.cholesky(Kmm) # [M, M] + Luu = tf.linalg.cholesky(Kmm) # [M, M] u_sample = tf.matmul(Luu, u_sample) # [M, P] - phi_Z = kernel.feature_functions(inducing_variable.Z) # [M, L] - weight_space_prior_Z = phi_Z @ prior_weights # [M, P] + phi_Z = kernel.feature_functions(inducing_variable.Z) # [M, L] + + weight_space_prior_Z = tf.matmul( phi_Z, # [M, L] + prior_weights # [L, P] + ) # [M, P] + diff = u_sample - weight_space_prior_Z # [M, P] v = compute_A_inv_b(Kmm, diff) # [M, P] + tf.debugging.assert_equal(tf.shape(v), [M, P]) class WilsonSample(Sample): @@ -187,10 +195,18 @@ def __call__(self, X: TensorType) -> tf.Tensor: :return: function value of sample [N, P] """ N = tf.shape(X)[0] - phi_X = kernel.feature_functions(X) # [N, L] - weight_space_prior_X = phi_X @ prior_weights # [N, P] + phi_X = kernel.feature_functions(X) # [N, L] + + + weight_space_prior_X = tf.matmul(phi_X, # [N, L] + prior_weights # [L, P] + ) # [N, P] + Knm = tf.linalg.matrix_transpose(Kuf(inducing_variable, kernel, X)) # [N, M] - function_space_update_X = Knm @ v # [N, P] + + function_space_update_X = tf.matmul(Knm, # [N, M] + v # [M, P] + ) # [N, P] tf.debugging.assert_equal(tf.shape(weight_space_prior_X), [N, P]) tf.debugging.assert_equal(tf.shape(function_space_update_X), [N, P]) diff --git a/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff.py b/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff.py new file mode 100644 index 00000000..111d006c --- /dev/null +++ b/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff.py @@ -0,0 +1,313 @@ +# +# Copyright (c) 2021 The GPflux Contributors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import numpy as np +import pytest +import tensorflow as tf +from tensorflow.python.keras.testing_utils import layer_test +from tensorflow.python.keras.utils.kernelized_utils import inner_product + +import gpflow + +from gpflow.kernels import SharedIndependent, SeparateIndependent +from gpflux import feature_decomposition_kernels +from gpflux.layers.basis_functions.fourier_features import ( + MultiOutputRandomFourierFeatures, + MultiOutputRandomFourierFeaturesCosine, +) +from gpflux.layers.basis_functions.fourier_features.random.base import RFF_SUPPORTED_KERNELS +from gpflux.layers.basis_functions.fourier_features.multioutput.random import MultiOutputRandomFourierFeatures +from gpflux.feature_decomposition_kernels.multioutput import SharedMultiOutputKernelWithFeatureDecomposition, SeparateMultiOutputKernelWithFeatureDecomposition +from tests.conftest import skip_serialization_tests + + + +@pytest.fixture(name="n_dims", params=[1, 2, 3, 5, 10, 20]) +def _n_dims_fixture(request): + return request.param + + +@pytest.fixture(name="variance", params=[0.5, 1.0, 2.0]) +def _variance_fixture(request): + return request.param + + +@pytest.fixture(name="lengthscale", params=[0.1, 1.0, 5.0]) +def _lengthscale_fixture(request): + return request.param + + +@pytest.fixture(name="batch_size", params=[1, 10]) +def _batch_size_fixture(request): + return request.param + + +@pytest.fixture(name="n_components", params=[1, 2, 4, 20, 100]) +def _n_features_fixture(request): + return request.param + + +@pytest.fixture(name="base_kernel_cls", params=list(RFF_SUPPORTED_KERNELS)) +def _base_kernel_cls_fixture(request): + return request.param + + +#@pytest.fixture(name="kernel_cls", params=[SeparateIndependent]) #, SharedIndependent]) +#def _kernel_cls_fixture(request): +# return request.param + + +@pytest.fixture( + name="random_basis_func_cls", + params=[MultiOutputRandomFourierFeatures], +) +def _random_basis_func_cls_fixture(request): + return request.param + + +@pytest.fixture( + name="basis_func_cls", + params=[MultiOutputRandomFourierFeatures ], +) +def _basis_func_cls_fixture(request): + return request.param + + + +def test_throw_for_unsupported_separate_kernel(basis_func_cls): + base_kernel = gpflow.kernels.Constant() + kernel = gpflow.kernels.SeparateIndependent(kernels = [base_kernel]) + with pytest.raises(AssertionError) as excinfo: + basis_func_cls(kernel, n_components=1) + assert "Unsupported Kernel" in str(excinfo.value) + +def test_throw_for_unsupported_shared_kernel(basis_func_cls): + base_kernel = gpflow.kernels.Constant() + kernel = SharedIndependent(kernel = base_kernel, output_dim=1) + with pytest.raises(AssertionError) as excinfo: + basis_func_cls(kernel, n_components=1) + assert "Unsupported Kernel" in str(excinfo.value) + + +def test_random_fourier_features_can_approximate_multi_output_separate_kernel_multidim( + random_basis_func_cls, base_kernel_cls, variance, lengthscale, n_dims +): + n_components = 40000 + + x_rows = 20 + y_rows = 30 + # ARD + lengthscales = np.random.rand((n_dims)) * lengthscale + + print('size of sampled lengthscales') + print(lengthscales.shape) + + base_kernel = base_kernel_cls(variance=variance, lengthscales=lengthscales) + + kernel = SeparateIndependent(kernels = [base_kernel, base_kernel]) + + x = tf.random.uniform((x_rows, n_dims), dtype=tf.float64) + y = tf.random.uniform((y_rows, n_dims), dtype=tf.float64) + + actual_kernel_matrix = kernel.K(x, y, full_output_cov = False).numpy() + + fourier_features = random_basis_func_cls(kernel, n_components, dtype=tf.float64) + + feature_coefficients = np.ones((2, 2*n_components, 1), dtype=np.float64) + + kernel = SeparateMultiOutputKernelWithFeatureDecomposition( + kernel=None, feature_functions=fourier_features, feature_coefficients=feature_coefficients, + output_dim = 2 + ) + + approx_kernel_matrix = kernel(x,y).numpy() + + + np.testing.assert_allclose(approx_kernel_matrix, actual_kernel_matrix, atol=5e-2) + + + +def test_random_fourier_features_can_approximate_multi_output_shared_kernel_multidim( + random_basis_func_cls, base_kernel_cls, variance, lengthscale, n_dims +): + n_components = 40000 + + x_rows = 20 + y_rows = 30 + # ARD + lengthscales = np.random.rand((n_dims)) * lengthscale + + print('size of sampled lengthscales') + print(lengthscales.shape) + + base_kernel = base_kernel_cls(variance=variance, lengthscales=lengthscales) + + kernel = SharedIndependent(kernel = base_kernel, output_dim = 2) + + x = tf.random.uniform((x_rows, n_dims), dtype=tf.float64) + y = tf.random.uniform((y_rows, n_dims), dtype=tf.float64) + + actual_kernel_matrix = kernel.K(x, y, full_output_cov = False).numpy() + + fourier_features = random_basis_func_cls(kernel, n_components, dtype=tf.float64) + + feature_coefficients = np.ones((2, 2*n_components, 1), dtype=np.float64) + + kernel = SharedMultiOutputKernelWithFeatureDecomposition( + kernel=None, feature_functions=fourier_features, feature_coefficients=feature_coefficients, + output_dim = 2 + ) + + + approx_kernel_matrix = kernel(x,y).numpy() + + + np.testing.assert_allclose(approx_kernel_matrix, actual_kernel_matrix, atol=5e-2) + + + + +""" +#TODO -- still need to implement the orthogonal version +def test_orthogonal_random_features_can_approximate_kernel_multidim(variance, lengthscale, n_dims): + n_components = 20000 + + x_rows = 20 + y_rows = 30 + # ARD + lengthscales = np.random.rand((n_dims)) * lengthscale + + kernel = gpflow.kernels.SquaredExponential(variance=variance, lengthscales=lengthscales) + fourier_features = OrthogonalRandomFeatures(kernel, n_components, dtype=tf.float64) + + x = tf.random.uniform((x_rows, n_dims), dtype=tf.float64) + y = tf.random.uniform((y_rows, n_dims), dtype=tf.float64) + + u = fourier_features(x) + v = fourier_features(y) + approx_kernel_matrix = inner_product(u, v) + + actual_kernel_matrix = kernel.K(x, y) + + np.testing.assert_allclose(approx_kernel_matrix, actual_kernel_matrix, atol=5e-2) + +""" + +def test_random_multi_output_fourier_feature_layer_compute_covariance_of_shared_inducing_variables( + basis_func_cls, batch_size +): + """ + Ensure that the random fourier feature map can be used to approximate the covariance matrix + between the inducing point vectors of a sparse GP, with the condition that the number of latent + GP models is greater than one. + """ + n_components = 10000 + + base_kernel = gpflow.kernels.SquaredExponential() + kernel = SharedIndependent(kernel = base_kernel, output_dim = 2) + fourier_features = basis_func_cls(kernel, n_components, dtype=tf.float64) + feature_coefficients = np.ones((2, 2*n_components, 1), dtype=np.float64) + + feature_decomposition_kernel = SharedMultiOutputKernelWithFeatureDecomposition( + kernel=None, feature_functions=fourier_features, feature_coefficients=feature_coefficients, + output_dim = 2 + ) + x_new = tf.ones(shape=(2 * batch_size + 1, 1), dtype=tf.float64) + + approx_kernel_matrix = feature_decomposition_kernel(x_new, x_new) + actual_kernel_matrix = kernel.K(x_new, x_new, full_output_cov=False) + + np.testing.assert_allclose(approx_kernel_matrix, actual_kernel_matrix, atol=5e-2) + + +def test_random_multi_output_fourier_feature_layer_compute_covariance_of_separate_inducing_variables( + basis_func_cls, batch_size +): + """ + Ensure that the random fourier feature map can be used to approximate the covariance matrix + between the inducing point vectors of a sparse GP, with the condition that the number of latent + GP models is greater than one. + """ + n_components = 10000 + + base_kernel = gpflow.kernels.SquaredExponential() + kernel = SeparateIndependent(kernels = [base_kernel, base_kernel]) + fourier_features = basis_func_cls(kernel, n_components, dtype=tf.float64) + feature_coefficients = np.ones((2, 2*n_components, 1), dtype=np.float64) + + feature_decomposition_kernel = SharedMultiOutputKernelWithFeatureDecomposition( + kernel=None, feature_functions=fourier_features, feature_coefficients=feature_coefficients, + output_dim = 2 + ) + x_new = tf.ones(shape=(2 * batch_size + 1, 1), dtype=tf.float64) + + approx_kernel_matrix = feature_decomposition_kernel(x_new, x_new) + actual_kernel_matrix = kernel.K(x_new, x_new, full_output_cov=False) + + np.testing.assert_allclose(approx_kernel_matrix, actual_kernel_matrix, atol=5e-2) + + +def test_multi_output_fourier_features_shapes(basis_func_cls, n_components, n_dims, batch_size): + input_shape = (2, batch_size, n_dims) + base_kernel = gpflow.kernels.SquaredExponential(lengthscales= [1.0] * n_dims) + kernel = SeparateIndependent(kernels = [base_kernel, base_kernel]) + feature_functions = basis_func_cls(kernel, n_components, dtype=tf.float64) + output_shape = feature_functions.compute_output_shape(input_shape) + features = feature_functions(tf.ones(shape=(batch_size, n_dims))) + np.testing.assert_equal(features.shape, output_shape) + + + + +""" +#TODO -- have a look at what layer_test actually does +@skip_serialization_tests +def test_keras_testing_util_layer_test_1D(kernel_cls, batch_size, n_components): + kernel = kernel_cls() + + tf.keras.utils.get_custom_objects()["RandomFourierFeatures"] = RandomFourierFeatures + layer_test( + RandomFourierFeatures, + kwargs={ + "kernel": kernel, + "n_components": n_components, + "input_dim": 1, + "dtype": "float64", + "dynamic": True, + }, + input_shape=(batch_size, 1), + input_dtype="float64", + ) + + +@skip_serialization_tests +def test_keras_testing_util_layer_test_multidim(kernel_cls, batch_size, n_dims, n_components): + kernel = kernel_cls() + + tf.keras.utils.get_custom_objects()["RandomFourierFeatures"] = RandomFourierFeatures + layer_test( + RandomFourierFeatures, + kwargs={ + "kernel": kernel, + "n_components": n_components, + "input_dim": n_dims, + "dtype": "float64", + "dynamic": True, + }, + input_shape=(batch_size, n_dims), + input_dtype="float64", + ) + +""" \ No newline at end of file diff --git a/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff_cosine.py b/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff_cosine.py new file mode 100644 index 00000000..07b85381 --- /dev/null +++ b/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff_cosine.py @@ -0,0 +1,307 @@ +# +# Copyright (c) 2021 The GPflux Contributors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import numpy as np +import pytest +import tensorflow as tf +from tensorflow.python.keras.testing_utils import layer_test +from tensorflow.python.keras.utils.kernelized_utils import inner_product + +import gpflow + +from gpflow.kernels import SharedIndependent, SeparateIndependent +from gpflux import feature_decomposition_kernels +from gpflux.layers.basis_functions.fourier_features import ( + MultiOutputRandomFourierFeatures, + MultiOutputRandomFourierFeaturesCosine, +) +from gpflux.layers.basis_functions.fourier_features.random.base import RFF_SUPPORTED_KERNELS +from gpflux.layers.basis_functions.fourier_features.multioutput.random import MultiOutputRandomFourierFeatures +from gpflux.feature_decomposition_kernels.multioutput import SharedMultiOutputKernelWithFeatureDecomposition, SeparateMultiOutputKernelWithFeatureDecomposition +from tests.conftest import skip_serialization_tests + + + +@pytest.fixture(name="n_dims", params=[1, 2, 3, 5, 10, 20]) +def _n_dims_fixture(request): + return request.param + + +@pytest.fixture(name="variance", params=[0.5, 1.0, 2.0]) +def _variance_fixture(request): + return request.param + + +@pytest.fixture(name="lengthscale", params=[0.1, 1.0, 5.0]) +def _lengthscale_fixture(request): + return request.param + + +@pytest.fixture(name="batch_size", params=[1, 10]) +def _batch_size_fixture(request): + return request.param + + +@pytest.fixture(name="n_components", params=[1, 2, 4, 20, 100]) +def _n_features_fixture(request): + return request.param + + +@pytest.fixture(name="base_kernel_cls", params=list(RFF_SUPPORTED_KERNELS)) +def _base_kernel_cls_fixture(request): + return request.param + +@pytest.fixture( + name="random_basis_func_cls", + params=[MultiOutputRandomFourierFeaturesCosine], +) +def _random_basis_func_cls_fixture(request): + return request.param + + +@pytest.fixture( + name="basis_func_cls", + params=[MultiOutputRandomFourierFeaturesCosine], +) +def _basis_func_cls_fixture(request): + return request.param + + + +def test_throw_for_unsupported_separate_kernel(basis_func_cls): + base_kernel = gpflow.kernels.Constant() + kernel = gpflow.kernels.SeparateIndependent(kernels = [base_kernel]) + with pytest.raises(AssertionError) as excinfo: + basis_func_cls(kernel, n_components=1) + assert "Unsupported Kernel" in str(excinfo.value) + +def test_throw_for_unsupported_shared_kernel(basis_func_cls): + base_kernel = gpflow.kernels.Constant() + kernel = SharedIndependent(kernel = base_kernel, output_dim=1) + with pytest.raises(AssertionError) as excinfo: + basis_func_cls(kernel, n_components=1) + assert "Unsupported Kernel" in str(excinfo.value) + + +def test_random_fourier_features_can_approximate_multi_output_separate_kernel_multidim( + random_basis_func_cls, base_kernel_cls, variance, lengthscale, n_dims +): + n_components = 40000 + + x_rows = 20 + y_rows = 30 + # ARD + lengthscales = np.random.rand((n_dims)) * lengthscale + + print('size of sampled lengthscales') + print(lengthscales.shape) + + base_kernel = base_kernel_cls(variance=variance, lengthscales=lengthscales) + + kernel = SeparateIndependent(kernels = [base_kernel, base_kernel]) + + x = tf.random.uniform((x_rows, n_dims), dtype=tf.float64) + y = tf.random.uniform((y_rows, n_dims), dtype=tf.float64) + + actual_kernel_matrix = kernel.K(x, y, full_output_cov = False).numpy() + + fourier_features = random_basis_func_cls(kernel, n_components, dtype=tf.float64) + + feature_coefficients = np.ones((2, n_components, 1), dtype=np.float64) + + kernel = SeparateMultiOutputKernelWithFeatureDecomposition( + kernel=None, feature_functions=fourier_features, feature_coefficients=feature_coefficients, + output_dim = 2 + ) + + approx_kernel_matrix = kernel(x,y).numpy() + + + np.testing.assert_allclose(approx_kernel_matrix, actual_kernel_matrix, atol=5e-2) + + + +def test_random_fourier_features_can_approximate_multi_output_shared_kernel_multidim( + random_basis_func_cls, base_kernel_cls, variance, lengthscale, n_dims +): + n_components = 40000 + + x_rows = 20 + y_rows = 30 + # ARD + lengthscales = np.random.rand((n_dims)) * lengthscale + + print('size of sampled lengthscales') + print(lengthscales.shape) + + base_kernel = base_kernel_cls(variance=variance, lengthscales=lengthscales) + + kernel = SharedIndependent(kernel = base_kernel, output_dim = 2) + + x = tf.random.uniform((x_rows, n_dims), dtype=tf.float64) + y = tf.random.uniform((y_rows, n_dims), dtype=tf.float64) + + actual_kernel_matrix = kernel.K(x, y, full_output_cov = False).numpy() + + fourier_features = random_basis_func_cls(kernel, n_components, dtype=tf.float64) + + feature_coefficients = np.ones((2, n_components, 1), dtype=np.float64) + + kernel = SharedMultiOutputKernelWithFeatureDecomposition( + kernel=None, feature_functions=fourier_features, feature_coefficients=feature_coefficients, + output_dim = 2 + ) + + + approx_kernel_matrix = kernel(x,y).numpy() + + + np.testing.assert_allclose(approx_kernel_matrix, actual_kernel_matrix, atol=5e-2) + + + + +""" +#TODO -- still need to implement the orthogonal version +def test_orthogonal_random_features_can_approximate_kernel_multidim(variance, lengthscale, n_dims): + n_components = 20000 + + x_rows = 20 + y_rows = 30 + # ARD + lengthscales = np.random.rand((n_dims)) * lengthscale + + kernel = gpflow.kernels.SquaredExponential(variance=variance, lengthscales=lengthscales) + fourier_features = OrthogonalRandomFeatures(kernel, n_components, dtype=tf.float64) + + x = tf.random.uniform((x_rows, n_dims), dtype=tf.float64) + y = tf.random.uniform((y_rows, n_dims), dtype=tf.float64) + + u = fourier_features(x) + v = fourier_features(y) + approx_kernel_matrix = inner_product(u, v) + + actual_kernel_matrix = kernel.K(x, y) + + np.testing.assert_allclose(approx_kernel_matrix, actual_kernel_matrix, atol=5e-2) + +""" + +def test_random_multi_output_fourier_feature_layer_compute_covariance_of_shared_inducing_variables( + basis_func_cls, batch_size +): + """ + Ensure that the random fourier feature map can be used to approximate the covariance matrix + between the inducing point vectors of a sparse GP, with the condition that the number of latent + GP models is greater than one. + """ + n_components = 10000 + + base_kernel = gpflow.kernels.SquaredExponential() + kernel = SharedIndependent(kernel = base_kernel, output_dim = 2) + fourier_features = basis_func_cls(kernel, n_components, dtype=tf.float64) + feature_coefficients = np.ones((2, n_components, 1), dtype=np.float64) + + feature_decomposition_kernel = SharedMultiOutputKernelWithFeatureDecomposition( + kernel=None, feature_functions=fourier_features, feature_coefficients=feature_coefficients, + output_dim = 2 + ) + x_new = tf.ones(shape=(2 * batch_size + 1, 1), dtype=tf.float64) + + approx_kernel_matrix = feature_decomposition_kernel(x_new, x_new) + actual_kernel_matrix = kernel.K(x_new, x_new, full_output_cov=False) + + np.testing.assert_allclose(approx_kernel_matrix, actual_kernel_matrix, atol=5e-2) + + +def test_random_multi_output_fourier_feature_layer_compute_covariance_of_separate_inducing_variables( + basis_func_cls, batch_size +): + """ + Ensure that the random fourier feature map can be used to approximate the covariance matrix + between the inducing point vectors of a sparse GP, with the condition that the number of latent + GP models is greater than one. + """ + n_components = 10000 + + base_kernel = gpflow.kernels.SquaredExponential() + kernel = SeparateIndependent(kernels = [base_kernel, base_kernel]) + fourier_features = basis_func_cls(kernel, n_components, dtype=tf.float64) + feature_coefficients = np.ones((2, n_components, 1), dtype=np.float64) + + feature_decomposition_kernel = SharedMultiOutputKernelWithFeatureDecomposition( + kernel=None, feature_functions=fourier_features, feature_coefficients=feature_coefficients, + output_dim = 2 + ) + x_new = tf.ones(shape=(2 * batch_size + 1, 1), dtype=tf.float64) + + approx_kernel_matrix = feature_decomposition_kernel(x_new, x_new) + actual_kernel_matrix = kernel.K(x_new, x_new, full_output_cov=False) + + np.testing.assert_allclose(approx_kernel_matrix, actual_kernel_matrix, atol=5e-2) + + +def test_multi_output_fourier_features_shapes(basis_func_cls, n_components, n_dims, batch_size): + input_shape = (2, batch_size, n_dims) + base_kernel = gpflow.kernels.SquaredExponential(lengthscales= [1.0] * n_dims) + kernel = SeparateIndependent(kernels = [base_kernel, base_kernel]) + feature_functions = basis_func_cls(kernel, n_components, dtype=tf.float64) + output_shape = feature_functions.compute_output_shape(input_shape) + features = feature_functions(tf.ones(shape=(batch_size, n_dims))) + np.testing.assert_equal(features.shape, output_shape) + + + + +""" +#TODO -- have a look at what layer_test actually does +@skip_serialization_tests +def test_keras_testing_util_layer_test_1D(kernel_cls, batch_size, n_components): + kernel = kernel_cls() + + tf.keras.utils.get_custom_objects()["RandomFourierFeatures"] = RandomFourierFeatures + layer_test( + RandomFourierFeatures, + kwargs={ + "kernel": kernel, + "n_components": n_components, + "input_dim": 1, + "dtype": "float64", + "dynamic": True, + }, + input_shape=(batch_size, 1), + input_dtype="float64", + ) + + +@skip_serialization_tests +def test_keras_testing_util_layer_test_multidim(kernel_cls, batch_size, n_dims, n_components): + kernel = kernel_cls() + + tf.keras.utils.get_custom_objects()["RandomFourierFeatures"] = RandomFourierFeatures + layer_test( + RandomFourierFeatures, + kwargs={ + "kernel": kernel, + "n_components": n_components, + "input_dim": n_dims, + "dtype": "float64", + "dynamic": True, + }, + input_shape=(batch_size, n_dims), + input_dtype="float64", + ) + +""" \ No newline at end of file diff --git a/tests/gpflux/sampling/test_multioutput_sample.py b/tests/gpflux/sampling/test_multioutput_sample.py new file mode 100644 index 00000000..1f979d31 --- /dev/null +++ b/tests/gpflux/sampling/test_multioutput_sample.py @@ -0,0 +1,169 @@ +# +# Copyright (c) 2021 The GPflux Contributors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import numpy as np +import pytest +import tensorflow as tf + +import gpflow +from gpflow.config import default_float, default_jitter + +from gpflux.layers.basis_functions.fourier_features import MultiOutputRandomFourierFeaturesCosine +from gpflux.feature_decomposition_kernels import SharedMultiOutputKernelWithFeatureDecomposition, SeparateMultiOutputKernelWithFeatureDecomposition +from gpflux.sampling.sample import Sample, efficient_sample + +@pytest.fixture(name="base_kernel") +def _base_kernel_fixture(): + + return gpflow.kernels.SquaredExponential() + +def _get_shared_kernel(base_kernel): + + return gpflow.kernels.SharedIndependent(kernel=base_kernel, output_dim = 2) + +def _get_separate_kernel(base_kernel): + + return gpflow.kernels.SeparateIndependent(kernels=[base_kernel, base_kernel]) + + +@pytest.fixture(name="shared_inducing_variable") +def _shared_inducing_variable_fixture(): + Z = np.linspace(-1, 1, 10).reshape(-1, 1) + + ind_var = gpflow.inducing_variables.InducingPoints(Z) + + return gpflow.inducing_variables.SharedIndependentInducingVariables(inducing_variable=ind_var) + +@pytest.fixture(name="separate_inducing_variable") +def _separate_inducing_variable_fixture(): + Z = np.linspace(-1, 1, 10).reshape(-1, 1) + + ind_var = gpflow.inducing_variables.InducingPoints(Z) + + return gpflow.inducing_variables.SeparateIndependentInducingVariables(inducing_variable_list=[ind_var, ind_var]) + +@pytest.fixture(name="whiten", params=[True]) +def _whiten_fixture(request): + return request.param + + +def _get_shared_qmu_qsqrt(kernel, inducing_variable): + """Returns q_mu and q_sqrt for a kernel and inducing_variable""" + Z = inducing_variable.inducing_variable.Z.numpy() + Kzz = kernel(Z, full_cov=True, full_output_cov = False).numpy() + + q_sqrt = np.linalg.cholesky(Kzz) + default_jitter() * np.eye(Z.shape[0])[None, ...] + q_mu = q_sqrt @ np.random.randn(2, Z.shape[0], 1) + + return np.transpose(q_mu[...,0]), q_sqrt + +def _get_separate_qmu_qsqrt(kernel, inducing_variable): + """Returns q_mu and q_sqrt for a kernel and inducing_variable""" + Z = inducing_variable.inducing_variable_list[0].Z.numpy() + Kzz = kernel(Z, full_cov=True, full_output_cov = False).numpy() + + q_sqrt = np.linalg.cholesky(Kzz) + default_jitter() * np.eye(Z.shape[0])[None, ...] + q_mu = q_sqrt @ np.random.randn(2, Z.shape[0], 1) + + return np.transpose(q_mu[...,0]), q_sqrt + +def test_shared_wilson_efficient_sample(base_kernel, shared_inducing_variable, whiten): + """Smoke and consistency test for efficient sampling using Wilson""" + kernel = _get_shared_kernel(base_kernel) + + eigenfunctions = MultiOutputRandomFourierFeaturesCosine(kernel, 100, dtype=default_float()) + eigenvalues = np.ones((2,100, 1), dtype=default_float()) + # To apply Wilson sampling we require the features and eigenvalues of the kernel + kernel2 = SharedMultiOutputKernelWithFeatureDecomposition(kernel, eigenfunctions, eigenvalues) + q_mu, q_sqrt = _get_shared_qmu_qsqrt(kernel, shared_inducing_variable) + + + sample_func = efficient_sample( + shared_inducing_variable, + kernel2, + tf.convert_to_tensor(q_mu), + q_sqrt=1e-3 * tf.convert_to_tensor(q_sqrt), + whiten=whiten, + ) + + X = np.linspace(-1, 0, 100).reshape(-1, 1) + # Check for consistency - i.e. evaluating the sample at the + # same locations (X) returns the same value + np.testing.assert_array_almost_equal( + sample_func(X), + sample_func(X), + ) + + + + + +def test_separate_wilson_efficient_sample(base_kernel, separate_inducing_variable, whiten): + """Smoke and consistency test for efficient sampling using Wilson""" + kernel = _get_separate_kernel(base_kernel) + + eigenfunctions = MultiOutputRandomFourierFeaturesCosine(kernel, 100, dtype=default_float()) + eigenvalues = np.ones((2,100, 1), dtype=default_float()) + # To apply Wilson sampling we require the features and eigenvalues of the kernel + kernel2 = SeparateMultiOutputKernelWithFeatureDecomposition(kernel, eigenfunctions, eigenvalues) + q_mu, q_sqrt = _get_separate_qmu_qsqrt(kernel, separate_inducing_variable) + + sample_func = efficient_sample( + separate_inducing_variable, + kernel2, + tf.convert_to_tensor(q_mu), + q_sqrt=1e-3 * tf.convert_to_tensor(q_sqrt), + whiten=whiten, + ) + + X = np.linspace(-1, 0, 100).reshape(-1, 1) + # Check for consistency - i.e. evaluating the sample at the + # same locations (X) returns the same value + np.testing.assert_array_almost_equal( + sample_func(X), + sample_func(X), + ) + + + + +""" +class SampleMock(Sample): + def __init__(self, a): + self.a = a + + def __call__(self, X): + return self.a * X + + +def test_adding_samples(): + X = np.random.randn(100, 2) + + sample1 = SampleMock(1.0) + sample2 = SampleMock(2.0) + sample3 = sample1 + sample2 + np.testing.assert_array_almost_equal(sample3(X), sample1(X) + sample2(X)) + + +def test_adding_sample_and_mean_function(): + X = np.random.randn(100, 2) + + mean_function = gpflow.mean_functions.Identity() + sample = SampleMock(3.0) + + sample_and_mean_function = sample + mean_function + + np.testing.assert_array_almost_equal(sample_and_mean_function(X), sample(X) + mean_function(X)) +""" \ No newline at end of file From f3bcfee016cac9ff89e441ed53abc090ee28c948 Mon Sep 17 00:00:00 2001 From: SebastianPopescu Date: Wed, 14 Sep 2022 11:21:05 +0100 Subject: [PATCH 02/25] fixed formating --- gpflux/__init__.py | 11 +- gpflux/architectures/__init__.py | 5 +- .../constant_input_dim_deep_gp.py | 12 +- gpflux/callbacks.py | 10 +- gpflux/encoders/__init__.py | 4 +- .../directly_parameterized_encoder.py | 14 ++- gpflux/experiment_support/plotting.py | 5 +- gpflux/experiment_support/tensorboard.py | 4 +- .../feature_decomposition_kernels/__init__.py | 6 +- .../kernel_with_feature_decomposition.py | 25 ++-- .../multioutput/__init__.py | 11 +- .../kernel_with_feature_decomposition.py | 97 ++++++++++----- gpflux/helpers.py | 20 ++- gpflux/layers/__init__.py | 5 +- .../fourier_features/__init__.py | 6 +- .../basis_functions/fourier_features/base.py | 17 ++- .../fourier_features/multioutput/base.py | 68 ++++++---- .../multioutput/random/__init__.py | 2 +- .../multioutput/random/base.py | 99 +++++++++------ .../multioutput/random/orthogonal.py | 101 +++++++++++++++ .../fourier_features/quadrature/gaussian.py | 12 +- .../fourier_features/random/base.py | 12 +- .../fourier_features/random/orthogonal.py | 24 +++- .../basis_functions/fourier_features/utils.py | 4 +- gpflux/layers/bayesian_dense_layer.py | 26 ++-- gpflux/layers/gp_layer.py | 24 +++- gpflux/layers/latent_variable_layer.py | 21 ++-- gpflux/losses.py | 4 +- gpflux/math.py | 4 +- gpflux/models/deep_gp.py | 12 +- gpflux/optimization/keras_natgrad.py | 24 +++- gpflux/runtime_checks.py | 4 +- gpflux/sampling/__init__.py | 2 +- gpflux/sampling/dispatch.py | 3 - gpflux/sampling/multioutput/sample.py | 116 ++++++++++++------ gpflux/sampling/sample.py | 43 ++++--- gpflux/sampling/utils.py | 4 +- 37 files changed, 607 insertions(+), 254 deletions(-) create mode 100644 gpflux/layers/basis_functions/fourier_features/multioutput/random/orthogonal.py diff --git a/gpflux/__init__.py b/gpflux/__init__.py index 9e3d558b..ccf2d234 100644 --- a/gpflux/__init__.py +++ b/gpflux/__init__.py @@ -17,5 +17,14 @@ The library root. See :mod:`~gpflux.models.deep_gp.DeepGP` for the core Deep GP model, which is built out of different GP :mod:`~gpflux.layers`. """ -from gpflux import callbacks, encoders, helpers, layers, losses, models, optimization, sampling +from gpflux import ( + callbacks, + encoders, + helpers, + layers, + losses, + models, + optimization, + sampling, +) from gpflux.version import __version__ diff --git a/gpflux/architectures/__init__.py b/gpflux/architectures/__init__.py index d2ab53fe..bb81d50a 100644 --- a/gpflux/architectures/__init__.py +++ b/gpflux/architectures/__init__.py @@ -1,4 +1,7 @@ """ Pre-specified architectures """ -from gpflux.architectures.constant_input_dim_deep_gp import Config, build_constant_input_dim_deep_gp +from gpflux.architectures.constant_input_dim_deep_gp import ( + Config, + build_constant_input_dim_deep_gp, +) diff --git a/gpflux/architectures/constant_input_dim_deep_gp.py b/gpflux/architectures/constant_input_dim_deep_gp.py index 8d5df380..3c184341 100644 --- a/gpflux/architectures/constant_input_dim_deep_gp.py +++ b/gpflux/architectures/constant_input_dim_deep_gp.py @@ -88,9 +88,14 @@ def _construct_kernel(input_dim: int, is_last_layer: bool) -> SquaredExponential # something where the value scaled with the number of dimensions before lengthscales = [2.0] * input_dim return SquaredExponential(lengthscales=lengthscales, variance=variance) + + construct_kernel -def build_constant_input_dim_deep_gp(X: np.ndarray, num_layers: int, config: Config) -> DeepGP: + +def build_constant_input_dim_deep_gp( + X: np.ndarray, num_layers: int, config: Config +) -> DeepGP: r""" Build a Deep GP consisting of ``num_layers`` :class:`GPLayer`\ s. All the hidden layers have the same input dimension as the data, that is, ``X.shape[1]``. @@ -127,7 +132,10 @@ def build_constant_input_dim_deep_gp(X: np.ndarray, num_layers: int, config: Con # Pass in kernels, specify output dim (shared hyperparams/variables) inducing_var = construct_basic_inducing_variables( - num_inducing=config.num_inducing, input_dim=D_in, share_variables=True, z_init=centroids + num_inducing=config.num_inducing, + input_dim=D_in, + share_variables=True, + z_init=centroids, ) kernel = construct_basic_kernel( diff --git a/gpflux/callbacks.py b/gpflux/callbacks.py index 1ce31776..7e529188 100644 --- a/gpflux/callbacks.py +++ b/gpflux/callbacks.py @@ -60,11 +60,7 @@ def __init__( self, log_dir: str = "logs", *, - keywords_to_monitor: List[str] = [ - "kernel", - "mean_function", - "likelihood", - ], + keywords_to_monitor: List[str] = ["kernel", "mean_function", "likelihood",], max_size: int = 3, histogram_freq: int = 0, write_graph: bool = True, @@ -163,7 +159,9 @@ def run(self, **unused_kwargs: Any) -> None: # skip parameters continue # check if the parameter name matches any of the specified keywords - if self.summarize_all or any((keyword in name) for keyword in self.keywords_to_monitor): + if self.summarize_all or any( + (keyword in name) for keyword in self.keywords_to_monitor + ): # keys are sometimes prepended with a character, which we strip name = name.lstrip(self.left_strip_character) self._summarize_parameter(name, parameter) diff --git a/gpflux/encoders/__init__.py b/gpflux/encoders/__init__.py index cb6fdd82..78e8c293 100644 --- a/gpflux/encoders/__init__.py +++ b/gpflux/encoders/__init__.py @@ -17,4 +17,6 @@ Encoders are used by :class:`~gpflux.layers.LatentVariableLayer`\ s to parametrize the approximate posterior distribution over latent variables. """ -from gpflux.encoders.directly_parameterized_encoder import DirectlyParameterizedNormalDiag +from gpflux.encoders.directly_parameterized_encoder import ( + DirectlyParameterizedNormalDiag, +) diff --git a/gpflux/encoders/directly_parameterized_encoder.py b/gpflux/encoders/directly_parameterized_encoder.py index 9823dd4e..6d1fcd1b 100644 --- a/gpflux/encoders/directly_parameterized_encoder.py +++ b/gpflux/encoders/directly_parameterized_encoder.py @@ -66,7 +66,9 @@ class DirectlyParameterizedNormalDiag(TrackableLayer): Initialised to ``1e-5 * np.ones((N, W))``. """ - def __init__(self, num_data: int, latent_dim: int, means: Optional[np.ndarray] = None): + def __init__( + self, num_data: int, latent_dim: int, means: Optional[np.ndarray] = None + ): """ Directly parameterise the posterior of the latent variables associated with each datapoint with a diagonal multivariate Normal distribution. Note that across @@ -99,7 +101,9 @@ def __init__(self, num_data: int, latent_dim: int, means: Optional[np.ndarray] = # TODO: Rename to `scale` and `loc` to match tfp.distributions self.means = Parameter(means, dtype=default_float(), name="w_means") - self.stds = Parameter(stds, transform=positive(), dtype=default_float(), name="w_stds") + self.stds = Parameter( + stds, transform=positive(), dtype=default_float(), name="w_stds" + ) def call( self, inputs: Optional[TensorType] = None, *args: Any, **kwargs: Any @@ -109,6 +113,10 @@ def call( """ if inputs is not None: tf.debugging.assert_shapes( - [(self.means, ["N", "W"]), (self.stds, ["N", "W"]), (inputs, ["N", "D"])] + [ + (self.means, ["N", "W"]), + (self.stds, ["N", "W"]), + (inputs, ["N", "D"]), + ] ) return self.means, self.stds diff --git a/gpflux/experiment_support/plotting.py b/gpflux/experiment_support/plotting.py index bf656b5e..87d7bff9 100644 --- a/gpflux/experiment_support/plotting.py +++ b/gpflux/experiment_support/plotting.py @@ -63,7 +63,10 @@ def plot_layer( def plot_layers( - X: TensorType, means: List[TensorType], covs: List[TensorType], samples: List[TensorType] + X: TensorType, + means: List[TensorType], + covs: List[TensorType], + samples: List[TensorType], ) -> None: # pragma: no cover L = len(means) fig, axes = plt.subplots(3, L, figsize=(L * 3.33, 10)) diff --git a/gpflux/experiment_support/tensorboard.py b/gpflux/experiment_support/tensorboard.py index 106efbd2..0bb72810 100644 --- a/gpflux/experiment_support/tensorboard.py +++ b/gpflux/experiment_support/tensorboard.py @@ -34,7 +34,9 @@ class Event: dtype: Type -def tensorboard_event_iterator(file_pattern: Union[str, List[str], tf.Tensor]) -> Iterator[Event]: +def tensorboard_event_iterator( + file_pattern: Union[str, List[str], tf.Tensor] +) -> Iterator[Event]: """ Iterator yielding preprocessed tensorboard Events. diff --git a/gpflux/feature_decomposition_kernels/__init__.py b/gpflux/feature_decomposition_kernels/__init__.py index 19a6bf10..ffbab0aa 100644 --- a/gpflux/feature_decomposition_kernels/__init__.py +++ b/gpflux/feature_decomposition_kernels/__init__.py @@ -1,5 +1,5 @@ from .kernel_with_feature_decomposition import ( - _ApproximateKernel, + _ApproximateKernel, KernelWithFeatureDecomposition, ) from .multioutput import ( @@ -9,11 +9,9 @@ ) __all__ = [ - "_ApproximateKernel", + "_ApproximateKernel", "KernelWithFeatureDecomposition", "_MultiOutputApproximateKernel", "SharedMultiOutputKernelWithFeatureDecomposition", "SeparateMultiOutputKernelWithFeatureDecomposition", ] - - diff --git a/gpflux/feature_decomposition_kernels/kernel_with_feature_decomposition.py b/gpflux/feature_decomposition_kernels/kernel_with_feature_decomposition.py index 33b1a972..faae572e 100644 --- a/gpflux/feature_decomposition_kernels/kernel_with_feature_decomposition.py +++ b/gpflux/feature_decomposition_kernels/kernel_with_feature_decomposition.py @@ -38,6 +38,7 @@ NoneType = type(None) + class _ApproximateKernel(gpflow.kernels.Kernel): r""" This class approximates a kernel by the finite feature decomposition: @@ -61,19 +62,21 @@ def __init__( :param feature_coefficients: A tensor with the shape ``[L, 1]`' with coefficients associated with the features, :math:`\lambda_i`. """ - self._feature_functions = feature_functions # [N, L] + self._feature_functions = feature_functions # [N, L] self._feature_coefficients = feature_coefficients # [L, 1] def K(self, X: TensorType, X2: Optional[TensorType] = None) -> tf.Tensor: """Approximate the true kernel by an inner product between feature functions.""" - phi = self._feature_functions(X) # [N, L] + phi = self._feature_functions(X) # [N, L] if X2 is None: phi2 = phi else: phi2 = self._feature_functions(X2) # [N2, L] r = tf.linalg.matmul( - phi, tf.linalg.matrix_transpose(self._feature_coefficients) * phi2, transpose_b=True + phi, + tf.linalg.matrix_transpose(self._feature_coefficients) * phi2, + transpose_b=True, ) # [N, N2] N1, N2 = tf.shape(phi)[0], tf.shape(phi2)[0] @@ -83,13 +86,16 @@ def K(self, X: TensorType, X2: Optional[TensorType] = None) -> tf.Tensor: def K_diag(self, X: TensorType) -> tf.Tensor: """Approximate the true kernel by an inner product between feature functions.""" - phi_squared = self._feature_functions(X) ** 2 # [N, L] - r = tf.reduce_sum(phi_squared * tf.transpose(self._feature_coefficients), axis=-1) # [N,] - N = tf.shape(X)[0] if tf.experimental.numpy.ndim(X)==1 else tf.shape(X)[0] - + phi_squared = self._feature_functions(X) ** 2 # [N, L] + r = tf.reduce_sum( + phi_squared * tf.transpose(self._feature_coefficients), axis=-1 + ) # [N,] + N = tf.shape(X)[0] if tf.experimental.numpy.ndim(X) == 1 else tf.shape(X)[0] + tf.debugging.assert_equal(tf.shape(r), [N]) # noqa: E231 return r + class KernelWithFeatureDecomposition(gpflow.kernels.Kernel): r""" This class represents a kernel together with its finite feature decomposition: @@ -157,9 +163,9 @@ def __init__( else: self._kernel = kernel - self._feature_functions = feature_functions # [N, L] + self._feature_functions = feature_functions # [N, L] self._feature_coefficients = feature_coefficients # [L, 1] - + tf.ensure_shape(self._feature_coefficients, tf.TensorShape([None, 1])) @property @@ -177,4 +183,3 @@ def K(self, X: TensorType, X2: Optional[TensorType] = None) -> tf.Tensor: def K_diag(self, X: TensorType) -> tf.Tensor: return self._kernel.K_diag(X) - diff --git a/gpflux/feature_decomposition_kernels/multioutput/__init__.py b/gpflux/feature_decomposition_kernels/multioutput/__init__.py index eed15c5f..8c362f4d 100644 --- a/gpflux/feature_decomposition_kernels/multioutput/__init__.py +++ b/gpflux/feature_decomposition_kernels/multioutput/__init__.py @@ -1,12 +1,11 @@ from .kernel_with_feature_decomposition import ( - _MultiOutputApproximateKernel, - SharedMultiOutputKernelWithFeatureDecomposition, - SeparateMultiOutputKernelWithFeatureDecomposition + _MultiOutputApproximateKernel, + SharedMultiOutputKernelWithFeatureDecomposition, + SeparateMultiOutputKernelWithFeatureDecomposition, ) __all__ = [ - "_MultiOutputApproximateKernel", - "SharedMultiOutputKernelWithFeatureDecomposition", + "_MultiOutputApproximateKernel", + "SharedMultiOutputKernelWithFeatureDecomposition", "SeparateMultiOutputKernelWithFeatureDecomposition", ] - diff --git a/gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py b/gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py index 663aff6b..1cd42c6b 100644 --- a/gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py +++ b/gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py @@ -38,6 +38,7 @@ NoneType = type(None) + class _MultiOutputApproximateKernel(gpflow.kernels.MultioutputKernel): r""" This class approximates a kernel by the finite feature decomposition: @@ -61,7 +62,7 @@ def __init__( :param feature_coefficients: A tensor with the shape ``[P, L, 1]`` with coefficients associated with the features, :math:`\lambda_i`. """ - self._feature_functions = feature_functions # [P, N, L] + self._feature_functions = feature_functions # [P, N, L] self._feature_coefficients = feature_coefficients # [P, L, 1] @property @@ -74,13 +75,20 @@ def latent_kernels(self) -> Any: """In this scenario we do not have access to the underlying kernels, so we are just returning the feature_functions""" return self._feature_functions - def K(self, X: TensorType, X2: Optional[TensorType] = None, full_output_cov: bool = True) -> tf.Tensor: + def K( + self, + X: TensorType, + X2: Optional[TensorType] = None, + full_output_cov: bool = True, + ) -> tf.Tensor: """Approximate the true kernel by an inner product between feature functions.""" phi = self._feature_functions(X) # [P, N, L] - + L = tf.shape(phi)[-1] - #NOTE - there are some differences between using FourierFeatures and FourierFeaturesCosine, extra check to ensure right shape and to guide debugging in notebooks - tf.debugging.assert_equal(tf.shape(self._feature_coefficients), [self.num_latent_gps, L, 1]) + # NOTE - there are some differences between using FourierFeatures and FourierFeaturesCosine, extra check to ensure right shape and to guide debugging in notebooks + tf.debugging.assert_equal( + tf.shape(self._feature_coefficients), [self.num_latent_gps, L, 1] + ) if X2 is None: phi2 = phi @@ -88,7 +96,9 @@ def K(self, X: TensorType, X2: Optional[TensorType] = None, full_output_cov: boo phi2 = self._feature_functions(X2) # [P, N2, L] r = tf.linalg.matmul( - phi, tf.linalg.matrix_transpose(self._feature_coefficients) * phi2, transpose_b=True + phi, + tf.linalg.matrix_transpose(self._feature_coefficients) * phi2, + transpose_b=True, ) # [P, N, N2] N1, N2 = tf.shape(phi)[1], tf.shape(phi2)[1] @@ -99,27 +109,33 @@ def K_diag(self, X: TensorType, full_output_cov: bool = False) -> tf.Tensor: """Approximate the true kernel by an inner product between feature functions.""" phi_squared = self._feature_functions(X) ** 2 # [P, N, L] - r = tf.reduce_sum(phi_squared * tf.linalg.matrix_transpose(self._feature_coefficients), axis=-1) # [P,N,] - N = tf.shape(X)[0] + r = tf.reduce_sum( + phi_squared * tf.linalg.matrix_transpose(self._feature_coefficients), + axis=-1, + ) # [P,N,] + N = tf.shape(X)[0] tf.debugging.assert_equal(tf.shape(r), [self.num_latent_gps, N]) # noqa: E231 return r -class SharedMultiOutputKernelWithFeatureDecompositionBase(gpflow.kernels.SharedIndependent): +class SharedMultiOutputKernelWithFeatureDecompositionBase( + gpflow.kernels.SharedIndependent +): """ 'Wrapper' class to solve the issue with full_cov:bool = False inherited from gpflow.kernels.MultiOutputKernel which doesn't work well with GPRPosterior, as it does not use dispatchers from gpflow.covariances. #NOTE -- I think in general GPR in GPflow is only meant to be used in univariate regression settings or multivariate case but with common covariance """ + # Overriding __call__ from gpflow.kernels.MultioutputKernel def __call__( self, X: TensorType, X2: Optional[TensorType] = None, *, - full_cov: bool = True, #NOTE -- this needs to be set to True as not to throw errors later on + full_cov: bool = True, # NOTE -- this needs to be set to True as not to throw errors later on full_output_cov: bool = True, presliced: bool = False, ) -> tf.Tensor: @@ -134,7 +150,9 @@ def __call__( return self.K(X, X2, full_output_cov=full_output_cov) -class SharedMultiOutputKernelWithFeatureDecomposition(SharedMultiOutputKernelWithFeatureDecompositionBase): +class SharedMultiOutputKernelWithFeatureDecomposition( + SharedMultiOutputKernelWithFeatureDecompositionBase +): r""" This class represents a gpflow.kernels.SharedIndependent kernel together with its finite feature decomposition: @@ -176,7 +194,7 @@ def __init__( feature_functions: tf.keras.layers.Layer, feature_coefficients: TensorType, *, - output_dim: Optional[int] = None + output_dim: Optional[int] = None, ): r""" :param kernel: The kernel corresponding to the feature decomposition. @@ -198,16 +216,18 @@ def __init__( """ if kernel is None: - #NOTE -- this is a subclass of gpflow.kernels.SharedIndependent (needed to be used with dispatchers from gpflow.covariances) - # so it needs to be initialized somehow. Not sure if this is the best approach though + # NOTE -- this is a subclass of gpflow.kernels.SharedIndependent (needed to be used with dispatchers from gpflow.covariances) + # so it needs to be initialized somehow. Not sure if this is the best approach though _dummy_kernel = SquaredExponential() super().__init__(_dummy_kernel, output_dim) - self._kernel = _MultiOutputApproximateKernel(feature_functions, feature_coefficients) + self._kernel = _MultiOutputApproximateKernel( + feature_functions, feature_coefficients + ) else: super().__init__(kernel.kernel, kernel.output_dim) self._kernel = kernel - self._feature_functions = feature_functions # [P, N, L] + self._feature_functions = feature_functions # [P, N, L] self._feature_coefficients = feature_coefficients # [P, L, 1] tf.ensure_shape(self._feature_coefficients, tf.TensorShape([None, None, 1])) @@ -220,7 +240,9 @@ def num_latent_gps(self) -> int: def latent_kernels(self) -> Tuple[gpflow.kernels.Kernel, ...]: """The underlying kernels in the multioutput kernel""" if isinstance(self._kernel, _MultiOutputApproximateKernel): - return self._kernel.latent_kernels #NOTE -- this will return self._feature_functions from ApproximateKernel + return ( + self._kernel.latent_kernels + ) # NOTE -- this will return self._feature_functions from ApproximateKernel else: return (self._kernel,) @@ -234,14 +256,21 @@ def feature_coefficients(self) -> tf.Tensor: r"""Return the kernel's coefficients :math:`\lambda_i`.""" return self._feature_coefficients - def K(self, X: TensorType, X2: Optional[TensorType] = None, full_output_cov: bool = True) -> tf.Tensor: + def K( + self, + X: TensorType, + X2: Optional[TensorType] = None, + full_output_cov: bool = True, + ) -> tf.Tensor: return self._kernel.K(X, X2, full_output_cov) def K_diag(self, X: TensorType, full_output_cov: bool = True) -> tf.Tensor: return self._kernel.K_diag(X, full_output_cov) -class SeparateMultiOutputKernelWithFeatureDecompositionBase(gpflow.kernels.SeparateIndependent): +class SeparateMultiOutputKernelWithFeatureDecompositionBase( + gpflow.kernels.SeparateIndependent +): """ 'Wrapper' class to solve the issue with full_cov:bool = False inherited from gpflow.kernels.MultiOutputKernel @@ -255,7 +284,7 @@ def __call__( X: TensorType, X2: Optional[TensorType] = None, *, - full_cov: bool = True, #NOTE -- this needs to be set to True as not to throw errors later on + full_cov: bool = True, # NOTE -- this needs to be set to True as not to throw errors later on full_output_cov: bool = True, presliced: bool = False, ) -> tf.Tensor: @@ -270,7 +299,9 @@ def __call__( return self.K(X, X2, full_output_cov=full_output_cov) -class SeparateMultiOutputKernelWithFeatureDecomposition(SeparateMultiOutputKernelWithFeatureDecompositionBase): +class SeparateMultiOutputKernelWithFeatureDecomposition( + SeparateMultiOutputKernelWithFeatureDecompositionBase +): r""" This class represents a gpflow.kernel.SeparateIndependent together with its finite feature decomposition: @@ -312,7 +343,7 @@ def __init__( feature_functions: tf.keras.layers.Layer, feature_coefficients: TensorType, *, - output_dim: Optional[int] = None + output_dim: Optional[int] = None, ): r""" :param kernel: The kernel corresponding to the feature decomposition. @@ -334,19 +365,21 @@ def __init__( """ if kernel is None: - #NOTE -- this is a subclass of gpflow.kernels.SeparateIndependent (needed to be used with dispatchers from gpflow.covariances) - # so it needs to be initialized somehow. Not sure if this is the best approach though + # NOTE -- this is a subclass of gpflow.kernels.SeparateIndependent (needed to be used with dispatchers from gpflow.covariances) + # so it needs to be initialized somehow. Not sure if this is the best approach though _dummy_kernels = [SquaredExponential() for _ in range(output_dim)] - super().__init__(_dummy_kernels) - self._kernel = _MultiOutputApproximateKernel(feature_functions, feature_coefficients) + super().__init__(_dummy_kernels) + self._kernel = _MultiOutputApproximateKernel( + feature_functions, feature_coefficients + ) else: super().__init__(kernel.kernels) self._kernel = kernel - self._feature_functions = feature_functions # [P, N, L] + self._feature_functions = feature_functions # [P, N, L] self._feature_coefficients = feature_coefficients # [P, L, 1] - + tf.ensure_shape(self._feature_coefficients, tf.TensorShape([None, None, 1])) @property @@ -369,9 +402,13 @@ def feature_coefficients(self) -> tf.Tensor: r"""Return the kernel's coefficients :math:`\lambda_i`.""" return self._feature_coefficients - def K(self, X: TensorType, X2: Optional[TensorType] = None, full_output_cov: bool = True) -> tf.Tensor: + def K( + self, + X: TensorType, + X2: Optional[TensorType] = None, + full_output_cov: bool = True, + ) -> tf.Tensor: return self._kernel.K(X, X2, full_output_cov) def K_diag(self, X: TensorType, full_output_cov: bool = False) -> tf.Tensor: return self._kernel.K_diag(X, full_output_cov) - diff --git a/gpflux/helpers.py b/gpflux/helpers.py index 45bfc6b6..0afb647c 100644 --- a/gpflux/helpers.py +++ b/gpflux/helpers.py @@ -139,7 +139,9 @@ def construct_basic_inducing_variables( assert len(z_init[i]) == num_ind_var z_init_i = z_init[i] else: - z_init_i = np.random.randn(num_ind_var, input_dim).astype(dtype=default_float()) + z_init_i = np.random.randn(num_ind_var, input_dim).astype( + dtype=default_float() + ) assert z_init_i.shape == (num_ind_var, input_dim) inducing_variables.append(InducingPoints(z_init_i)) return SeparateIndependentInducingVariables(inducing_variables) @@ -155,7 +157,9 @@ def construct_basic_inducing_variables( ) z_init_o = z_init[o] else: - z_init_o = np.random.randn(num_inducing, input_dim).astype(dtype=default_float()) + z_init_o = np.random.randn(num_inducing, input_dim).astype( + dtype=default_float() + ) inducing_variables.append(InducingPoints(z_init_o)) return SeparateIndependentInducingVariables(inducing_variables) @@ -240,7 +244,9 @@ def construct_gp_layer( """ lengthscale = float(input_dim) ** 0.5 base_kernel = kernel_class(lengthscales=np.full(input_dim, lengthscale)) - kernel = construct_basic_kernel(base_kernel, output_dim=output_dim, share_hyperparams=True) + kernel = construct_basic_kernel( + base_kernel, output_dim=output_dim, share_hyperparams=True + ) inducing_variable = construct_basic_inducing_variables( num_inducing, input_dim, @@ -261,7 +267,9 @@ def construct_gp_layer( T = TypeVar("T") -def make_dataclass_from_class(dataclass: Type[T], instance: object, **updates: object) -> T: +def make_dataclass_from_class( + dataclass: Type[T], instance: object, **updates: object +) -> T: """ Take a regular object ``instance`` with a superset of fields for a :class:`dataclasses.dataclass` (``@dataclass``-decorated class), and return an @@ -287,4 +295,6 @@ def xavier_initialization_numpy(input_dim: int, output_dim: int) -> np.ndarray: Draw samples from a normal distribution centred on :math:`0` with standard deviation :math:`\sqrt(2 / (\text{input_dim} + \text{output_dim}))`. """ - return np.random.randn(input_dim, output_dim) * (2.0 / (input_dim + output_dim)) ** 0.5 + return ( + np.random.randn(input_dim, output_dim) * (2.0 / (input_dim + output_dim)) ** 0.5 + ) diff --git a/gpflux/layers/__init__.py b/gpflux/layers/__init__.py index 34f7e073..2c99783f 100644 --- a/gpflux/layers/__init__.py +++ b/gpflux/layers/__init__.py @@ -19,6 +19,9 @@ from gpflux.layers import basis_functions from gpflux.layers.bayesian_dense_layer import BayesianDenseLayer from gpflux.layers.gp_layer import GPLayer -from gpflux.layers.latent_variable_layer import LatentVariableLayer, LayerWithObservations +from gpflux.layers.latent_variable_layer import ( + LatentVariableLayer, + LayerWithObservations, +) from gpflux.layers.likelihood_layer import LikelihoodLayer from gpflux.layers.trackable_layer import TrackableLayer diff --git a/gpflux/layers/basis_functions/fourier_features/__init__.py b/gpflux/layers/basis_functions/fourier_features/__init__.py index ea293c9b..9f0ac7d5 100644 --- a/gpflux/layers/basis_functions/fourier_features/__init__.py +++ b/gpflux/layers/basis_functions/fourier_features/__init__.py @@ -18,7 +18,9 @@ :class:`gpflux.sampling.KernelWithFeatureDecomposition` """ -from gpflux.layers.basis_functions.fourier_features.quadrature import QuadratureFourierFeatures +from gpflux.layers.basis_functions.fourier_features.quadrature import ( + QuadratureFourierFeatures, +) from gpflux.layers.basis_functions.fourier_features.random import ( OrthogonalRandomFeatures, RandomFourierFeatures, @@ -31,7 +33,7 @@ ) __all__ = [ - "QuadratureFourierFeatures", + "QuadratureFourierFeatures", "OrthogonalRandomFeatures", "RandomFourierFeatures", "RandomFourierFeaturesCosine", diff --git a/gpflux/layers/basis_functions/fourier_features/base.py b/gpflux/layers/basis_functions/fourier_features/base.py index 272fca92..c1ea8074 100644 --- a/gpflux/layers/basis_functions/fourier_features/base.py +++ b/gpflux/layers/basis_functions/fourier_features/base.py @@ -24,8 +24,11 @@ from gpflow.base import TensorType from gpflux.types import ShapeType + class FourierFeaturesBase(ABC, tf.keras.layers.Layer): - def __init__(self, kernel: gpflow.kernels.Kernel, n_components: int, **kwargs: Mapping): + def __init__( + self, kernel: gpflow.kernels.Kernel, n_components: int, **kwargs: Mapping + ): """ :param kernel: kernel to approximate using a set of Fourier bases. :param n_components: number of components (e.g. Monte Carlo samples, @@ -49,9 +52,9 @@ def call(self, inputs: TensorType) -> tf.Tensor: :return: A tensor with the shape ``[N, M]``.mypy """ - X = tf.divide(inputs, self.kernel.lengthscales) # [N, D] - const = self._compute_constant() - bases = self._compute_bases(X) + X = tf.divide(inputs, self.kernel.lengthscales) # [N, D] + const = self._compute_constant() + bases = self._compute_bases(X) output = const * bases tf.ensure_shape(output, self.compute_output_shape(inputs.shape)) return output @@ -77,7 +80,11 @@ def get_config(self) -> Mapping: """ config = super(FourierFeaturesBase, self).get_config() config.update( - {"kernel": self.kernel, "n_components": self.n_components, "input_dim": self._input_dim} + { + "kernel": self.kernel, + "n_components": self.n_components, + "input_dim": self._input_dim, + } ) return config diff --git a/gpflux/layers/basis_functions/fourier_features/multioutput/base.py b/gpflux/layers/basis_functions/fourier_features/multioutput/base.py index b5fb9b04..be9cf6e5 100644 --- a/gpflux/layers/basis_functions/fourier_features/multioutput/base.py +++ b/gpflux/layers/basis_functions/fourier_features/multioutput/base.py @@ -25,8 +25,14 @@ from gpflow.base import TensorType from gpflux.types import ShapeType + class MultiOutputFourierFeaturesBase(ABC, tf.keras.layers.Layer): - def __init__(self, kernel: gpflow.kernels.MultioutputKernel, n_components: int, **kwargs: Mapping): + def __init__( + self, + kernel: gpflow.kernels.MultioutputKernel, + n_components: int, + **kwargs: Mapping + ): """ :param kernel: kernel to approximate using a set of Fourier bases. Expects a Multioutput Kernel :param n_components: number of components (e.g. Monte Carlo samples, @@ -54,31 +60,47 @@ def call(self, inputs: TensorType) -> tf.Tensor: D = tf.shape(inputs)[-1] if isinstance(self.kernel, gpflow.kernels.SeparateIndependent): - - for kernel in self.kernel.kernels: - print(kernel.lengthscales.unconstrained_variable.value()) - _lengthscales = tf.concat([ kernel.lengthscales[None, None, ...] if tf.rank(kernel.lengthscales.unconstrained_variable.value()) == 1 - else kernel.lengthscales[None, None, None, ...] for kernel in self.kernel.kernels], axis = 0) # [P, 1, D] - print('size -f _lengthscales') + for kernel in self.kernel.kernels: + print(kernel.lengthscales.unconstrained_variable.value()) + + _lengthscales = tf.concat( + [ + kernel.lengthscales[None, None, ...] + if tf.rank(kernel.lengthscales.unconstrained_variable.value()) == 1 + else kernel.lengthscales[None, None, None, ...] + for kernel in self.kernel.kernels + ], + axis=0, + ) # [P, 1, D] + print("size -f _lengthscales") print(_lengthscales) tf.debugging.assert_equal(tf.shape(_lengthscales), [P, 1, D]) elif isinstance(self.kernel, gpflow.kernels.SharedIndependent): - #NOTE -- each kernel.kernel.lengthscales has to be of the shape [D,] - _lengthscales = tf.tile(self.kernel.kernel.lengthscales[None, None, ...] if tf.rank(self.kernel.kernel.lengthscales.unconstrained_variable.value()) == 1 - else self.kernel.kernel.lengthscales[None, None, None, ...] , - [P, 1, 1]) # [P, 1, D] + # NOTE -- each kernel.kernel.lengthscales has to be of the shape [D,] + _lengthscales = tf.tile( + self.kernel.kernel.lengthscales[None, None, ...] + if tf.rank( + self.kernel.kernel.lengthscales.unconstrained_variable.value() + ) + == 1 + else self.kernel.kernel.lengthscales[None, None, None, ...], + [P, 1, 1], + ) # [P, 1, D] tf.debugging.assert_equal(tf.shape(_lengthscales), [P, 1, D]) else: - raise ValueError("kernel is not supported. Must be either gpflow.kernels.SharedIndependent or gpflow.kernels.SeparateIndependent") - - X = tf.divide(inputs, # [N, D] in the case that we predict at X*, in case we want to get the Fourier Features for Z, this would correspond to [P, M, D] - _lengthscales # [P, 1, D] - ) # [P, N, D] or [P, M, D] - const = self._compute_constant()[...,None,None] # [P,1,1] - bases = self._compute_bases(X) # [P, N, L] for X*, or [P,M,L] in the case of Z - output = const * bases # [P, N, L] for X*, or [P,M,L] in the case of Z + raise ValueError( + "kernel is not supported. Must be either gpflow.kernels.SharedIndependent or gpflow.kernels.SeparateIndependent" + ) + + X = tf.divide( + inputs, # [N, D] in the case that we predict at X*, in case we want to get the Fourier Features for Z, this would correspond to [P, M, D] + _lengthscales, # [P, 1, D] + ) # [P, N, D] or [P, M, D] + const = self._compute_constant()[..., None, None] # [P,1,1] + bases = self._compute_bases(X) # [P, N, L] for X*, or [P,M,L] in the case of Z + output = const * bases # [P, N, L] for X*, or [P,M,L] in the case of Z tf.ensure_shape(output, self.compute_output_shape(X.shape)) return output @@ -91,7 +113,7 @@ def compute_output_shape(self, input_shape: ShapeType) -> tf.TensorShape: """ # TODO: Keras docs say "If the layer has not been built, this method # will call `build` on the layer." -- do we need to do so? - + tensor_shape = tf.TensorShape(input_shape).with_rank(3) output_dim = self._compute_output_dim(input_shape) return tensor_shape[:-1].concatenate(output_dim) @@ -104,7 +126,11 @@ def get_config(self) -> Mapping: """ config = super(MultiOutputFourierFeaturesBase, self).get_config() config.update( - {"kernel": self.kernel, "n_components": self.n_components, "input_dim": self._input_dim} + { + "kernel": self.kernel, + "n_components": self.n_components, + "input_dim": self._input_dim, + } ) return config diff --git a/gpflux/layers/basis_functions/fourier_features/multioutput/random/__init__.py b/gpflux/layers/basis_functions/fourier_features/multioutput/random/__init__.py index eeb21834..e96f8f35 100644 --- a/gpflux/layers/basis_functions/fourier_features/multioutput/random/__init__.py +++ b/gpflux/layers/basis_functions/fourier_features/multioutput/random/__init__.py @@ -22,5 +22,5 @@ __all__ = [ "MultiOutputRandomFourierFeatures", - "MultiOutputRandomFourierFeaturesCosine", + "MultiOutputRandomFourierFeaturesCosine", ] diff --git a/gpflux/layers/basis_functions/fourier_features/multioutput/random/base.py b/gpflux/layers/basis_functions/fourier_features/multioutput/random/base.py index 586cfd1d..e3742bed 100644 --- a/gpflux/layers/basis_functions/fourier_features/multioutput/random/base.py +++ b/gpflux/layers/basis_functions/fourier_features/multioutput/random/base.py @@ -22,7 +22,9 @@ import gpflow from gpflow.base import DType, TensorType -from gpflux.layers.basis_functions.fourier_features.multioutput.base import MultiOutputFourierFeaturesBase +from gpflux.layers.basis_functions.fourier_features.multioutput.base import ( + MultiOutputFourierFeaturesBase, +) from gpflux.layers.basis_functions.fourier_features.utils import ( _bases_concat, _bases_cosine, @@ -43,6 +45,7 @@ gpflow.kernels.Matern52, ) + def _sample_students_t(nu: float, shape: ShapeType, dtype: DType) -> TensorType: """ Draw samples from a (central) Student's t-distribution using the following: @@ -73,16 +76,25 @@ def _sample_students_t(nu: float, shape: ShapeType, dtype: DType) -> TensorType: class MultiOutputRandomFourierFeaturesBase(MultiOutputFourierFeaturesBase): - def __init__(self, kernel: gpflow.kernels.MultioutputKernel, n_components: int, **kwargs: Mapping): - + def __init__( + self, + kernel: gpflow.kernels.MultioutputKernel, + n_components: int, + **kwargs: Mapping + ): + if isinstance(kernel, gpflow.kernels.SeparateIndependent): - for ker in kernel.kernels: - assert isinstance(ker, RFF_SUPPORTED_KERNELS), "Unsupported Kernel" + for ker in kernel.kernels: + assert isinstance(ker, RFF_SUPPORTED_KERNELS), "Unsupported Kernel" elif isinstance(kernel, gpflow.kernels.SharedIndependent): - assert isinstance(kernel.kernel, RFF_SUPPORTED_KERNELS), "Unsupported Kernel" + assert isinstance( + kernel.kernel, RFF_SUPPORTED_KERNELS + ), "Unsupported Kernel" else: - raise ValueError("kernel specified is not supported.") - super(MultiOutputRandomFourierFeaturesBase, self).__init__(kernel, n_components, **kwargs) + raise ValueError("kernel specified is not supported.") + super(MultiOutputRandomFourierFeaturesBase, self).__init__( + kernel, n_components, **kwargs + ) def build(self, input_shape: ShapeType) -> None: """ @@ -95,9 +107,9 @@ def build(self, input_shape: ShapeType) -> None: super(MultiOutputRandomFourierFeaturesBase, self).build(input_shape) def _weights_build(self, input_dim: int, n_components: int) -> None: - + shape = (self.kernel.num_latent_gps, n_components, input_dim) - + self.W = self.add_weight( name="weights", trainable=False, @@ -107,30 +119,34 @@ def _weights_build(self, input_dim: int, n_components: int) -> None: ) tf.ensure_shape(self.W, shape) - def _weights_init(self, shape: TensorType, dtype: Optional[DType] = None) -> TensorType: - + def _weights_init( + self, shape: TensorType, dtype: Optional[DType] = None + ) -> TensorType: + if isinstance(self.kernel, gpflow.kernels.SeparateIndependent): - list_inits = [] - for ker in self.kernel.kernels: - if isinstance(ker, gpflow.kernels.SquaredExponential): - list_inits.append(tf.random.normal(shape[1:], dtype=dtype)) - else: - p = _matern_number(ker) - nu = 2.0 * p + 1.0 # degrees of freedom - list_inits.append(_sample_students_t(nu, shape[1:], dtype)) - return tf.stack(list_inits, axis=0) + list_inits = [] + for ker in self.kernel.kernels: + if isinstance(ker, gpflow.kernels.SquaredExponential): + list_inits.append(tf.random.normal(shape[1:], dtype=dtype)) + else: + p = _matern_number(ker) + nu = 2.0 * p + 1.0 # degrees of freedom + list_inits.append(_sample_students_t(nu, shape[1:], dtype)) + return tf.stack(list_inits, axis=0) elif isinstance(self.kernel, gpflow.kernels.SharedIndependent): - if isinstance(self.kernel.kernel, gpflow.kernels.SquaredExponential): - return tf.random.normal(shape, dtype=dtype) - else: - p = _matern_number(self.kernel.kernel) - nu = 2.0 * p + 1.0 # degrees of freedom - return _sample_students_t(nu, shape, dtype) + if isinstance(self.kernel.kernel, gpflow.kernels.SquaredExponential): + return tf.random.normal(shape, dtype=dtype) + else: + p = _matern_number(self.kernel.kernel) + nu = 2.0 * p + 1.0 # degrees of freedom + return _sample_students_t(nu, shape, dtype) else: - raise ValueError("kernel is not supported. Must be either gpflow.kernels.SharedIndependent or gpflow.kernels.SeparateIndependent") + raise ValueError( + "kernel is not supported. Must be either gpflow.kernels.SharedIndependent or gpflow.kernels.SeparateIndependent" + ) @staticmethod def rff_constant(variance: TensorType, output_dim: int) -> tf.Tensor: @@ -193,12 +209,14 @@ def _compute_constant(self) -> tf.Tensor: """ if hasattr(self.kernel, "kernels"): - _kernel_variance = tf.stack([ker.variance for ker in self.kernel.kernels], axis = 0) - tf.ensure_shape(_kernel_variance, [self.kernel.num_latent_gps,]) + _kernel_variance = tf.stack( + [ker.variance for ker in self.kernel.kernels], axis=0 + ) + tf.ensure_shape(_kernel_variance, [self.kernel.num_latent_gps,]) else: - _kernel_variance = self.kernel.kernel.variance - + _kernel_variance = self.kernel.kernel.variance + return self.rff_constant(_kernel_variance, output_dim=2 * self.n_components) @@ -242,7 +260,7 @@ def build(self, input_shape: ShapeType) -> None: super(MultiOutputRandomFourierFeaturesCosine, self).build(input_shape) def _bias_build(self, n_components: int) -> None: - + shape = (self.kernel.num_latent_gps, 1, n_components) self.b = self.add_weight( @@ -253,7 +271,9 @@ def _bias_build(self, n_components: int) -> None: initializer=self._bias_init, ) - def _bias_init(self, shape: TensorType, dtype: Optional[DType] = None) -> TensorType: + def _bias_init( + self, shape: TensorType, dtype: Optional[DType] = None + ) -> TensorType: return tf.random.uniform(shape=shape, maxval=2.0 * np.pi, dtype=dtype) def _compute_output_dim(self, input_shape: ShapeType) -> int: @@ -275,10 +295,11 @@ def _compute_constant(self) -> tf.Tensor: """ if hasattr(self.kernel, "kernels"): - _kernel_variance = tf.stack([ker.variance for ker in self.kernel.kernels], axis = 0) - tf.ensure_shape(_kernel_variance, [self.kernel.num_latent_gps,]) + _kernel_variance = tf.stack( + [ker.variance for ker in self.kernel.kernels], axis=0 + ) + tf.ensure_shape(_kernel_variance, [self.kernel.num_latent_gps,]) else: - _kernel_variance = self.kernel.kernel.variance - - return self.rff_constant(_kernel_variance, output_dim=self.n_components) + _kernel_variance = self.kernel.kernel.variance + return self.rff_constant(_kernel_variance, output_dim=self.n_components) diff --git a/gpflux/layers/basis_functions/fourier_features/multioutput/random/orthogonal.py b/gpflux/layers/basis_functions/fourier_features/multioutput/random/orthogonal.py new file mode 100644 index 00000000..92c5857b --- /dev/null +++ b/gpflux/layers/basis_functions/fourier_features/multioutput/random/orthogonal.py @@ -0,0 +1,101 @@ +# +# Copyright (c) 2021 The GPflux Contributors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +from typing import Mapping, Optional, Tuple, Type + +import numpy as np +import tensorflow as tf + +import gpflow +from gpflow.base import DType, TensorType + +from gpflux.layers.basis_functions.fourier_features.random.base import ( + RandomFourierFeatures, +) +from gpflux.types import ShapeType + +""" +Kernels supported by :class:`OrthogonalRandomFeatures`. + +This random matrix sampling scheme only applies to the :class:`gpflow.kernels.SquaredExponential` +kernel. +For Matern kernels please use :class:`RandomFourierFeatures` +or :class:`RandomFourierFeaturesCosine`. +""" +ORF_SUPPORTED_KERNELS: Tuple[Type[gpflow.kernels.Stationary], ...] = ( + gpflow.kernels.SquaredExponential, +) + + +def _sample_chi_squared(nu: float, shape: ShapeType, dtype: DType) -> TensorType: + """ + Draw samples from Chi-squared distribution with `nu` degrees of freedom. + + See https://mathworld.wolfram.com/Chi-SquaredDistribution.html for further + details regarding relationship to Gamma distribution. + """ + return tf.random.gamma(shape=shape, alpha=0.5 * nu, beta=0.5, dtype=dtype) + + +def _sample_chi(nu: float, shape: ShapeType, dtype: DType) -> TensorType: + """ + Draw samples from Chi-distribution with `nu` degrees of freedom. + """ + s = _sample_chi_squared(nu, shape, dtype) + return tf.sqrt(s) + + +def _ceil_divide(a: float, b: float) -> int: + """ + Ceiling division. Returns the smallest integer `m` s.t. `m*b >= a`. + """ + return -np.floor_divide(-a, b) + + +# TODO -- this class has to be updated +# NOTE -- I am not sure if the shapes are fine here, check the actual paper +class OrthogonalRandomFeatures(RandomFourierFeatures): + r""" + Orthogonal random Fourier features (ORF) :cite:p:`yu2016orthogonal` for more + efficient and accurate kernel approximations than :class:`RandomFourierFeatures`. + """ + + def __init__( + self, kernel: gpflow.kernels.Kernel, n_components: int, **kwargs: Mapping + ): + assert isinstance(kernel, ORF_SUPPORTED_KERNELS), "Unsupported Kernel" + super(OrthogonalRandomFeatures, self).__init__(kernel, n_components, **kwargs) + + def _weights_init( + self, shape: TensorType, dtype: Optional[DType] = None + ) -> TensorType: + n_out, n_components, input_dim = shape # P, M, D + n_reps = _ceil_divide( + n_components, input_dim + ) # K, smallest integer s.t. K*D >= M + + W = tf.random.normal(shape=(n_out, n_reps, input_dim, input_dim), dtype=dtype) + Q, _ = tf.linalg.qr(W) # throw away R; shape [P, K, D, D] + + s = _sample_chi( + nu=input_dim, shape=(n_out, n_reps, input_dim), dtype=dtype + ) # shape [P, K, D] + U = ( + tf.expand_dims(s, axis=-1) * Q + ) # equiv: S @ Q where S = diag(s); shape [P, K, D, D] + V = tf.reshape(U, shape=(n_out, -1, input_dim)) # shape [P, K*D, D] + + return V[: self.n_components] # shape [M, D] (throw away K*D - M rows) diff --git a/gpflux/layers/basis_functions/fourier_features/quadrature/gaussian.py b/gpflux/layers/basis_functions/fourier_features/quadrature/gaussian.py index 2391bb13..4f4f5969 100644 --- a/gpflux/layers/basis_functions/fourier_features/quadrature/gaussian.py +++ b/gpflux/layers/basis_functions/fourier_features/quadrature/gaussian.py @@ -44,7 +44,9 @@ class QuadratureFourierFeatures(FourierFeaturesBase): - def __init__(self, kernel: gpflow.kernels.Kernel, n_components: int, **kwargs: Mapping): + def __init__( + self, kernel: gpflow.kernels.Kernel, n_components: int, **kwargs: Mapping + ): assert isinstance(kernel, QFF_SUPPORTED_KERNELS), "Unsupported Kernel" if tf.reduce_any(tf.less(kernel.lengthscales, 1e-1)): warnings.warn( @@ -66,9 +68,13 @@ def build(self, input_shape: ShapeType) -> None: omegas_value = tf.squeeze(omegas_value, axis=-1) # Quadrature node points - self.abscissa = tf.Variable(initial_value=abscissa_value, trainable=False) # (M^D, D) + self.abscissa = tf.Variable( + initial_value=abscissa_value, trainable=False + ) # (M^D, D) # Gauss-Hermite weights - self.factors = tf.Variable(initial_value=omegas_value, trainable=False) # (M^D,) + self.factors = tf.Variable( + initial_value=omegas_value, trainable=False + ) # (M^D,) super(QuadratureFourierFeatures, self).build(input_shape) def _compute_output_dim(self, input_shape: ShapeType) -> int: diff --git a/gpflux/layers/basis_functions/fourier_features/random/base.py b/gpflux/layers/basis_functions/fourier_features/random/base.py index 82ae4aa9..ed242a34 100644 --- a/gpflux/layers/basis_functions/fourier_features/random/base.py +++ b/gpflux/layers/basis_functions/fourier_features/random/base.py @@ -73,7 +73,9 @@ def _sample_students_t(nu: float, shape: ShapeType, dtype: DType) -> TensorType: class RandomFourierFeaturesBase(FourierFeaturesBase): - def __init__(self, kernel: gpflow.kernels.Kernel, n_components: int, **kwargs: Mapping): + def __init__( + self, kernel: gpflow.kernels.Kernel, n_components: int, **kwargs: Mapping + ): assert isinstance(kernel, RFF_SUPPORTED_KERNELS), "Unsupported Kernel" super(RandomFourierFeaturesBase, self).__init__(kernel, n_components, **kwargs) @@ -97,7 +99,9 @@ def _weights_build(self, input_dim: int, n_components: int) -> None: initializer=self._weights_init, ) - def _weights_init(self, shape: TensorType, dtype: Optional[DType] = None) -> TensorType: + def _weights_init( + self, shape: TensorType, dtype: Optional[DType] = None + ) -> TensorType: if isinstance(self.kernel, gpflow.kernels.SquaredExponential): return tf.random.normal(shape, dtype=dtype) else: @@ -216,7 +220,9 @@ def _bias_build(self, n_components: int) -> None: initializer=self._bias_init, ) - def _bias_init(self, shape: TensorType, dtype: Optional[DType] = None) -> TensorType: + def _bias_init( + self, shape: TensorType, dtype: Optional[DType] = None + ) -> TensorType: return tf.random.uniform(shape=shape, maxval=2.0 * np.pi, dtype=dtype) def _compute_output_dim(self, input_shape: ShapeType) -> int: diff --git a/gpflux/layers/basis_functions/fourier_features/random/orthogonal.py b/gpflux/layers/basis_functions/fourier_features/random/orthogonal.py index 395da743..9b99773e 100644 --- a/gpflux/layers/basis_functions/fourier_features/random/orthogonal.py +++ b/gpflux/layers/basis_functions/fourier_features/random/orthogonal.py @@ -22,7 +22,9 @@ import gpflow from gpflow.base import DType, TensorType -from gpflux.layers.basis_functions.fourier_features.random.base import RandomFourierFeatures +from gpflux.layers.basis_functions.fourier_features.random.base import ( + RandomFourierFeatures, +) from gpflux.types import ShapeType """ @@ -69,19 +71,29 @@ class OrthogonalRandomFeatures(RandomFourierFeatures): efficient and accurate kernel approximations than :class:`RandomFourierFeatures`. """ - def __init__(self, kernel: gpflow.kernels.Kernel, n_components: int, **kwargs: Mapping): + def __init__( + self, kernel: gpflow.kernels.Kernel, n_components: int, **kwargs: Mapping + ): assert isinstance(kernel, ORF_SUPPORTED_KERNELS), "Unsupported Kernel" super(OrthogonalRandomFeatures, self).__init__(kernel, n_components, **kwargs) - def _weights_init(self, shape: TensorType, dtype: Optional[DType] = None) -> TensorType: + def _weights_init( + self, shape: TensorType, dtype: Optional[DType] = None + ) -> TensorType: n_components, input_dim = shape # M, D - n_reps = _ceil_divide(n_components, input_dim) # K, smallest integer s.t. K*D >= M + n_reps = _ceil_divide( + n_components, input_dim + ) # K, smallest integer s.t. K*D >= M W = tf.random.normal(shape=(n_reps, input_dim, input_dim), dtype=dtype) Q, _ = tf.linalg.qr(W) # throw away R; shape [K, D, D] - s = _sample_chi(nu=input_dim, shape=(n_reps, input_dim), dtype=dtype) # shape [K, D] - U = tf.expand_dims(s, axis=-1) * Q # equiv: S @ Q where S = diag(s); shape [K, D, D] + s = _sample_chi( + nu=input_dim, shape=(n_reps, input_dim), dtype=dtype + ) # shape [K, D] + U = ( + tf.expand_dims(s, axis=-1) * Q + ) # equiv: S @ Q where S = diag(s); shape [K, D, D] V = tf.reshape(U, shape=(-1, input_dim)) # shape [K*D, D] return V[: self.n_components] # shape [M, D] (throw away K*D - M rows) diff --git a/gpflux/layers/basis_functions/fourier_features/utils.py b/gpflux/layers/basis_functions/fourier_features/utils.py index 7866974d..fc4ee205 100644 --- a/gpflux/layers/basis_functions/fourier_features/utils.py +++ b/gpflux/layers/basis_functions/fourier_features/utils.py @@ -21,6 +21,7 @@ import gpflow from gpflow.base import TensorType + def _matern_number(kernel: gpflow.kernels.Kernel) -> int: if isinstance(kernel, gpflow.kernels.Matern52): p = 2 @@ -32,6 +33,7 @@ def _matern_number(kernel: gpflow.kernels.Kernel) -> int: raise NotImplementedError("Not a recognized Matern kernel") return p + def _bases_cosine(X: TensorType, W: TensorType, b: TensorType) -> TensorType: """ Feature map for random Fourier features (RFF) as originally prescribed @@ -49,4 +51,4 @@ def _bases_concat(X: TensorType, W: TensorType) -> TensorType: See also :cite:p:`sutherland2015error` for additional details. """ proj = tf.matmul(X, W, transpose_b=True) # [N, M] or [P, N, M] - return tf.concat([tf.sin(proj), tf.cos(proj)], axis=-1) # [N, 2M] or [P, N, 2M] \ No newline at end of file + return tf.concat([tf.sin(proj), tf.cos(proj)], axis=-1) # [N, 2M] or [P, N, 2M] diff --git a/gpflux/layers/bayesian_dense_layer.py b/gpflux/layers/bayesian_dense_layer.py index 36c316a5..b15466bd 100644 --- a/gpflux/layers/bayesian_dense_layer.py +++ b/gpflux/layers/bayesian_dense_layer.py @@ -111,10 +111,14 @@ def __init__( self.full_output_cov = False self.full_cov = False - self.w_mu = Parameter(np.zeros((self.dim,)), dtype=default_float(), name="w_mu") # [dim] + self.w_mu = Parameter( + np.zeros((self.dim,)), dtype=default_float(), name="w_mu" + ) # [dim] self.w_sqrt = Parameter( - np.zeros((self.dim, self.dim)) if not self.is_mean_field else np.ones((self.dim,)), + np.zeros((self.dim, self.dim)) + if not self.is_mean_field + else np.ones((self.dim,)), transform=triangular() if not self.is_mean_field else positive(), dtype=default_float(), name="w_sqrt", @@ -140,10 +144,7 @@ def build(self, input_shape: ShapeType) -> None: self.initialize_variational_distribution() def predict_samples( - self, - inputs: TensorType, - *, - num_samples: Optional[int] = None, + self, inputs: TensorType, *, num_samples: Optional[int] = None, ) -> tf.Tensor: """ Samples from the approximate posterior at N test inputs, with input_dim = D, output_dim = Q. @@ -153,7 +154,9 @@ def predict_samples( :returns: Samples, shape ``[S, N, Q]`` if S is not None else ``[N, Q]``. """ _num_samples = num_samples or 1 - z = tf.random.normal((self.dim, _num_samples), dtype=default_float()) # [dim, S] + z = tf.random.normal( + (self.dim, _num_samples), dtype=default_float() + ) # [dim, S] if not self.is_mean_field: w = self.w_mu[:, None] + tf.matmul(self.w_sqrt, z) # [dim, S] else: @@ -165,7 +168,9 @@ def predict_samples( ) # [N, D+1] samples = tf.tensordot( inputs_concat_1, - tf.reshape(tf.transpose(w), (_num_samples, self.input_dim + 1, self.output_dim)), + tf.reshape( + tf.transpose(w), (_num_samples, self.input_dim + 1, self.output_dim) + ), [[-1], [1]], ) # [N, S, Q] if num_samples is None: @@ -184,10 +189,7 @@ def call( """ The default behaviour upon calling this layer. """ - sample = self.predict_samples( - inputs, - num_samples=None, - ) + sample = self.predict_samples(inputs, num_samples=None,) # TF quirk: add_loss must add a tensor to compile if training: diff --git a/gpflux/layers/gp_layer.py b/gpflux/layers/gp_layer.py index 16e03aa5..0a61efa5 100644 --- a/gpflux/layers/gp_layer.py +++ b/gpflux/layers/gp_layer.py @@ -208,7 +208,7 @@ def __init__( num_latent_gps, ) - print('**************888') + print("**************888") print(num_inducing) print(self.num_latent_gps) @@ -271,7 +271,9 @@ def predict( return mean_cond + mean_function, cov - def call(self, inputs: TensorType, *args: List[Any], **kwargs: Dict[str, Any]) -> tf.Tensor: + def call( + self, inputs: TensorType, *args: List[Any], **kwargs: Dict[str, Any] + ) -> tf.Tensor: """ The default behaviour upon calling this layer. @@ -288,7 +290,9 @@ def call(self, inputs: TensorType, *args: List[Any], **kwargs: Dict[str, Any]) - outputs = super().call(inputs, *args, **kwargs) if kwargs.get("training"): - log_prior = tf.add_n([p.log_prior_density() for p in self.kernel.trainable_parameters]) + log_prior = tf.add_n( + [p.log_prior_density() for p in self.kernel.trainable_parameters] + ) loss = self.prior_kl() - log_prior loss_per_datapoint = loss / self.num_data @@ -311,7 +315,11 @@ def prior_kl(self) -> tf.Tensor: :attr:`whiten`\ ed representation, returns ``KL[q(v)∥p(v)]``. """ return prior_kl( - self.inducing_variable, self.kernel, self.q_mu, self.q_sqrt, whiten=self.whiten + self.inducing_variable, + self.kernel, + self.q_mu, + self.q_sqrt, + whiten=self.whiten, ) def _make_distribution_fn( @@ -342,13 +350,17 @@ def _make_distribution_fn( ) # loc: [N, Q], scale: [N, Q, Q] elif not self.full_cov and not self.full_output_cov: # mean: [N, Q], cov: [N, Q] - return tfp.distributions.MultivariateNormalDiag(loc=mean, scale_diag=tf.sqrt(cov)) + return tfp.distributions.MultivariateNormalDiag( + loc=mean, scale_diag=tf.sqrt(cov) + ) else: raise NotImplementedError( "The combination of both `full_cov` and `full_output_cov` is not permitted." ) - def _convert_to_tensor_fn(self, distribution: tfp.distributions.Distribution) -> tf.Tensor: + def _convert_to_tensor_fn( + self, distribution: tfp.distributions.Distribution + ) -> tf.Tensor: """ Convert the predictive distributions at the input points (see :meth:`_make_distribution_fn`) to a tensor of :attr:`num_samples` diff --git a/gpflux/layers/latent_variable_layer.py b/gpflux/layers/latent_variable_layer.py index ea5a55e8..34c30adb 100644 --- a/gpflux/layers/latent_variable_layer.py +++ b/gpflux/layers/latent_variable_layer.py @@ -103,7 +103,9 @@ def __init__( self.distribution_class = prior.__class__ self.encoder = encoder self.compositor = ( - compositor if compositor is not None else tf.keras.layers.Concatenate(axis=-1) + compositor + if compositor is not None + else tf.keras.layers.Concatenate(axis=-1) ) def call( @@ -133,7 +135,9 @@ def call( """ if training: if observations is None: - raise ValueError("LatentVariableLayer requires observations when training") + raise ValueError( + "LatentVariableLayer requires observations when training" + ) samples, loss_per_datapoint = self._inference_latent_samples_and_loss( layer_inputs, observations, seed=seed @@ -152,9 +156,7 @@ def call( return self.compositor([layer_inputs, samples]) def _inference_posteriors( - self, - observations: ObservationType, - training: Optional[bool] = None, + self, observations: ObservationType, training: Optional[bool] = None, ) -> tfp.distributions.Distribution: """ Return the posterior distributions parametrised by the :attr:`encoder`, which gets called @@ -173,12 +175,17 @@ def _inference_posteriors( encoder_inputs = tf.concat(observations, axis=-1) distribution_params = self.encoder(encoder_inputs, training=training) - posteriors = self.distribution_class(*distribution_params, allow_nan_stats=False) + posteriors = self.distribution_class( + *distribution_params, allow_nan_stats=False + ) return posteriors def _inference_latent_samples_and_loss( - self, layer_inputs: TensorType, observations: ObservationType, seed: Optional[int] = None + self, + layer_inputs: TensorType, + observations: ObservationType, + seed: Optional[int] = None, ) -> Tuple[tf.Tensor, tf.Tensor]: r""" Sample latent variables during the *training* forward pass, hence requiring diff --git a/gpflux/losses.py b/gpflux/losses.py index 66bb83ca..2395b0db 100644 --- a/gpflux/losses.py +++ b/gpflux/losses.py @@ -79,7 +79,9 @@ def call( Note that we deviate from the Keras Loss interface by calling the second argument *f_prediction* rather than *y_pred*. """ - if isinstance(unwrap_dist(f_prediction), tfp.distributions.MultivariateNormalDiag): + if isinstance( + unwrap_dist(f_prediction), tfp.distributions.MultivariateNormalDiag + ): F_mu = f_prediction.loc F_var = f_prediction.scale.diag ** 2 diff --git a/gpflux/math.py b/gpflux/math.py index 53c2556d..d3d4457a 100644 --- a/gpflux/math.py +++ b/gpflux/math.py @@ -58,5 +58,7 @@ def compute_A_inv_b(A: TensorType, b: TensorType) -> tf.Tensor: L = tf.linalg.cholesky(A) # A⁻¹ = L⁻ᵀ L⁻¹ L_inv_b = tf.linalg.triangular_solve(L, b) - A_inv_b = tf.linalg.triangular_solve(L, L_inv_b, adjoint=True) # adjoint = transpose + A_inv_b = tf.linalg.triangular_solve( + L, L_inv_b, adjoint=True + ) # adjoint = transpose return A_inv_b diff --git a/gpflux/models/deep_gp.py b/gpflux/models/deep_gp.py index 22092e75..be1ac0fa 100644 --- a/gpflux/models/deep_gp.py +++ b/gpflux/models/deep_gp.py @@ -181,7 +181,9 @@ def call( training: Optional[bool] = None, ) -> tf.Tensor: f_outputs = self._evaluate_deep_gp(inputs, targets=targets, training=training) - y_outputs = self._evaluate_likelihood(f_outputs, targets=targets, training=training) + y_outputs = self._evaluate_likelihood( + f_outputs, targets=targets, training=training + ) return y_outputs def predict_f(self, inputs: TensorType) -> Tuple[tf.Tensor, tf.Tensor]: @@ -207,7 +209,9 @@ def elbo(self, data: Tuple[TensorType, TensorType]) -> tf.Tensor: ] return -tf.reduce_sum(all_losses) * self.num_data - def _get_model_class(self, model_class: Optional[Type[tf.keras.Model]]) -> Type[tf.keras.Model]: + def _get_model_class( + self, model_class: Optional[Type[tf.keras.Model]] + ) -> Type[tf.keras.Model]: if model_class is not None: return model_class else: @@ -269,7 +273,9 @@ def as_prediction_model( return model_class(self.inputs, outputs) -def sample_dgp(model: DeepGP) -> Sample: # TODO: should this be part of a [Vanilla]DeepGP class? +def sample_dgp( + model: DeepGP, +) -> Sample: # TODO: should this be part of a [Vanilla]DeepGP class? function_draws = [layer.sample() for layer in model.f_layers] # TODO: error check that all layers implement .sample()? diff --git a/gpflux/optimization/keras_natgrad.py b/gpflux/optimization/keras_natgrad.py index b009922f..cc48436c 100644 --- a/gpflux/optimization/keras_natgrad.py +++ b/gpflux/optimization/keras_natgrad.py @@ -108,7 +108,9 @@ def optimizer(self) -> tf.optimizers.Optimizer: return self._all_optimizers[-1] @optimizer.setter - def optimizer(self, optimizers: List[Union[NaturalGradient, tf.optimizers.Optimizer]]) -> None: + def optimizer( + self, optimizers: List[Union[NaturalGradient, tf.optimizers.Optimizer]] + ) -> None: if optimizers is None: # tf.keras.Model.__init__() sets self.optimizer = None self._all_optimizers = None @@ -144,7 +146,9 @@ def _split_natgrad_params_and_other_vars( ) -> Tuple[List[Tuple[Parameter, Parameter]], List[tf.Variable]]: # NOTE the structure of variational_params is directly linked to the _natgrad_step, # do not change out of sync - variational_params = [(layer.q_mu, layer.q_sqrt) for layer in self.natgrad_layers] + variational_params = [ + (layer.q_mu, layer.q_sqrt) for layer in self.natgrad_layers + ] # NOTE could use a natgrad_parameters attribute on a layer or a # singledispatch function to make this more flexible for other layers @@ -152,7 +156,9 @@ def _split_natgrad_params_and_other_vars( variational_vars_set = ObjectIdentitySet( p.unconstrained_variable for vp in variational_params for p in vp ) - other_vars = [v for v in self.trainable_variables if v not in variational_vars_set] + other_vars = [ + v for v in self.trainable_variables if v not in variational_vars_set + ] return variational_params, other_vars @@ -185,7 +191,9 @@ def _apply_backwards_pass(self, loss: tf.Tensor, tape: tf.GradientTape) -> None: for (natgrad_optimizer, (q_mu_grad, q_sqrt_grad), (q_mu, q_sqrt)) in zip( self.natgrad_optimizers, variational_params_grads, variational_params ): - natgrad_optimizer._natgrad_apply_gradients(q_mu_grad, q_sqrt_grad, q_mu, q_sqrt) + natgrad_optimizer._natgrad_apply_gradients( + q_mu_grad, q_sqrt_grad, q_mu, q_sqrt + ) self.optimizer.apply_gradients(zip(other_grads, other_vars)) @@ -203,7 +211,9 @@ def train_step(self, data: Any) -> Mapping[str, Any]: with tf.GradientTape() as tape: y_pred = self.__call__(x, training=True) - loss = self.compiled_loss(y, y_pred, sample_weight, regularization_losses=self.losses) + loss = self.compiled_loss( + y, y_pred, sample_weight, regularization_losses=self.losses + ) self._apply_backwards_pass(loss, tape=tape) @@ -243,7 +253,9 @@ def layers(self) -> List[tf.keras.layers.Layer]: else: return self.base_model.layers - def call(self, data: Any, training: Optional[bool] = None) -> Union[tf.Tensor, MeanAndVariance]: + def call( + self, data: Any, training: Optional[bool] = None + ) -> Union[tf.Tensor, MeanAndVariance]: """ Calls the model on new inputs. Simply passes through to the ``base_model``. """ diff --git a/gpflux/runtime_checks.py b/gpflux/runtime_checks.py index c8bb3ce5..445d9dbb 100644 --- a/gpflux/runtime_checks.py +++ b/gpflux/runtime_checks.py @@ -70,5 +70,7 @@ def verify_compatibility( f"the number of separate independent inducing_variables ({latent_inducing_points})" ) - num_inducing_points = inducing_variable.num_inducing # currently the same for each dim + num_inducing_points = ( + inducing_variable.num_inducing + ) # currently the same for each dim return num_inducing_points, num_latent_gps diff --git a/gpflux/sampling/__init__.py b/gpflux/sampling/__init__.py index a62d6c2c..c6772317 100644 --- a/gpflux/sampling/__init__.py +++ b/gpflux/sampling/__init__.py @@ -24,4 +24,4 @@ "efficient_sample", "sample", "multioutput", -] \ No newline at end of file +] diff --git a/gpflux/sampling/dispatch.py b/gpflux/sampling/dispatch.py index 116daab3..02146ead 100644 --- a/gpflux/sampling/dispatch.py +++ b/gpflux/sampling/dispatch.py @@ -1,6 +1,3 @@ from gpflow.utilities import Dispatcher efficient_sample = Dispatcher("efficient_sample") - - - diff --git a/gpflux/sampling/multioutput/sample.py b/gpflux/sampling/multioutput/sample.py index 3b963f04..adacb71b 100644 --- a/gpflux/sampling/multioutput/sample.py +++ b/gpflux/sampling/multioutput/sample.py @@ -26,21 +26,42 @@ from gpflow.conditionals import conditional from gpflow.config import default_float, default_jitter from gpflow.covariances import Kuf, Kuu -from gpflow.inducing_variables import MultioutputInducingVariables, SharedIndependentInducingVariables, SeparateIndependentInducingVariables -from gpflow.kernels import Kernel, SeparateIndependent, SharedIndependent, MultioutputKernel +from gpflow.inducing_variables import ( + MultioutputInducingVariables, + SharedIndependentInducingVariables, + SeparateIndependentInducingVariables, +) +from gpflow.kernels import ( + Kernel, + SeparateIndependent, + SharedIndependent, + MultioutputKernel, +) from gpflow.utilities import Dispatcher from gpflux.math import compute_A_inv_b -from gpflux.feature_decomposition_kernels import SharedMultiOutputKernelWithFeatureDecomposition, SeparateMultiOutputKernelWithFeatureDecomposition +from gpflux.feature_decomposition_kernels import ( + SharedMultiOutputKernelWithFeatureDecomposition, + SeparateMultiOutputKernelWithFeatureDecomposition, +) from ..sample import Sample from ..dispatch import efficient_sample - -@efficient_sample.register(MultioutputInducingVariables, (SharedMultiOutputKernelWithFeatureDecomposition, SeparateMultiOutputKernelWithFeatureDecomposition), object) +@efficient_sample.register( + MultioutputInducingVariables, + ( + SharedMultiOutputKernelWithFeatureDecomposition, + SeparateMultiOutputKernelWithFeatureDecomposition, + ), + object, +) def _efficient_multi_output_sample_matheron_rule( inducing_variable: MultioutputInducingVariables, - kernel: Union[SharedMultiOutputKernelWithFeatureDecomposition, SeparateMultiOutputKernelWithFeatureDecomposition], + kernel: Union[ + SharedMultiOutputKernelWithFeatureDecomposition, + SeparateMultiOutputKernelWithFeatureDecomposition, + ], q_mu: tf.Tensor, *, q_sqrt: Optional[TensorType] = None, @@ -60,14 +81,13 @@ def _efficient_multi_output_sample_matheron_rule( """ # Reshape kernel.feature_coefficients - _feature_coefficients = tf.transpose(kernel.feature_coefficients[...,0]) # [L,P] + _feature_coefficients = tf.transpose(kernel.feature_coefficients[..., 0]) # [L,P] L = tf.shape(_feature_coefficients)[0] # num eigenfunctions # noqa: F841 M, P = tf.shape(q_mu)[0], tf.shape(q_mu)[1] # num inducing, num output heads - prior_weights = tf.sqrt(_feature_coefficients) * tf.random.normal( - (L, P), dtype=default_float() # [L, P], [L,P] + (L, P), dtype=default_float() # [L, P], [L,P] ) # [L, P] u_sample_noise = tf.matmul( @@ -77,13 +97,18 @@ def _efficient_multi_output_sample_matheron_rule( tf.debugging.assert_equal(tf.shape(u_sample_noise), [P, M, 1]) if isinstance(kernel, SharedIndependent): - Kmm = tf.tile(Kuu(inducing_variable, kernel, jitter=default_jitter())[None,...] ,[P, 1, 1]) # [P,M,M] + Kmm = tf.tile( + Kuu(inducing_variable, kernel, jitter=default_jitter())[None, ...], + [P, 1, 1], + ) # [P,M,M] tf.debugging.assert_equal(tf.shape(Kmm), [P, M, M]) elif isinstance(kernel, SeparateIndependent): - Kmm = Kuu(inducing_variable, kernel, jitter=default_jitter()) # [P,M,M] + Kmm = Kuu(inducing_variable, kernel, jitter=default_jitter()) # [P,M,M] tf.debugging.assert_equal(tf.shape(Kmm), [P, M, M]) else: - raise ValueError("kernel not supported. Must be either SharedIndependent or SeparateIndependent") + raise ValueError( + "kernel not supported. Must be either SharedIndependent or SeparateIndependent" + ) tf.debugging.assert_equal(tf.shape(Kmm), [P, M, M]) @@ -91,13 +116,15 @@ def _efficient_multi_output_sample_matheron_rule( tf.debugging.assert_equal(tf.shape(u_sample), [M, P]) if whiten: - Luu = tf.linalg.cholesky(Kmm) # [P,M,M] - tf.debugging.assert_equal(tf.shape(Kmm), [P,M,M]) + Luu = tf.linalg.cholesky(Kmm) # [P,M,M] + tf.debugging.assert_equal(tf.shape(Kmm), [P, M, M]) - u_sample = tf.transpose(tf.matmul(Luu, # [P, M, M] - tf.transpose(u_sample)[...,None] # [P, M, 1] - )[...,0]) # [M, P] - tf.debugging.assert_equal(tf.shape(u_sample), [M, P]) + u_sample = tf.transpose( + tf.matmul(Luu, tf.transpose(u_sample)[..., None])[ # [P, M, M] # [P, M, 1] + ..., 0 + ] + ) # [M, P] + tf.debugging.assert_equal(tf.shape(u_sample), [M, P]) if isinstance(inducing_variable, SeparateIndependentInducingVariables): @@ -107,24 +134,28 @@ def _efficient_multi_output_sample_matheron_rule( _inducing_variable_list = tf.stack(_inducing_variable_list, axis=0) phi_Z = kernel.feature_functions(_inducing_variable_list) # [P, M, L] - tf.debugging.assert_equal(tf.shape(phi_Z), [P, M, L]) + tf.debugging.assert_equal(tf.shape(phi_Z), [P, M, L]) elif isinstance(inducing_variable, SharedIndependentInducingVariables): - phi_Z = kernel.feature_functions(inducing_variable.inducing_variable.Z) # [P, M, L] - tf.debugging.assert_equal(tf.shape(phi_Z), [P, M, L]) + phi_Z = kernel.feature_functions( + inducing_variable.inducing_variable.Z + ) # [P, M, L] + tf.debugging.assert_equal(tf.shape(phi_Z), [P, M, L]) else: - raise ValueError("inducing variable is not supported. Must be either SharedIndependentInducingVariables or SeparateIndependentInducingVariables") + raise ValueError( + "inducing variable is not supported. Must be either SharedIndependentInducingVariables or SeparateIndependentInducingVariables" + ) - weight_space_prior_Z = tf.matmul( phi_Z, # [P, M, L] - tf.transpose(prior_weights)[...,None] # [P, L, 1] - ) # [P, M, 1] - weight_space_prior_Z = tf.transpose(weight_space_prior_Z[...,0]) # [M, P] + weight_space_prior_Z = tf.matmul( + phi_Z, tf.transpose(prior_weights)[..., None] # [P, M, L] # [P, L, 1] + ) # [P, M, 1] + weight_space_prior_Z = tf.transpose(weight_space_prior_Z[..., 0]) # [M, P] diff = tf.transpose(u_sample - weight_space_prior_Z)[..., None] # [P, M, 1] - v = tf.transpose(compute_A_inv_b(Kmm, #[P, M, M] - diff # [P, M, 1] - )[...,0]) # [M, P] + v = tf.transpose( + compute_A_inv_b(Kmm, diff)[..., 0] # [P, M, M] # [P, M, 1] + ) # [M, P] tf.debugging.assert_equal(tf.shape(v), [M, P]) @@ -136,18 +167,25 @@ def __call__(self, X: TensorType) -> tf.Tensor: """ N = tf.shape(X)[0] phi_X = kernel.feature_functions(X) # [P, N, L] - - weight_space_prior_X = tf.transpose(tf.matmul(phi_X, # [P, N, L] - tf.transpose(prior_weights)[..., None] # [P, L, 1] - )[...,0]) # [N, P] - Knm = tf.linalg.matrix_transpose(Kuf(inducing_variable, kernel, X)) # [P, N, M] or [N,M] + weight_space_prior_X = tf.transpose( + tf.matmul( + phi_X, # [P, N, L] + tf.transpose(prior_weights)[..., None], # [P, L, 1] + )[..., 0] + ) # [N, P] + + Knm = tf.linalg.matrix_transpose( + Kuf(inducing_variable, kernel, X) + ) # [P, N, M] or [N,M] if isinstance(inducing_variable, SharedIndependentInducingVariables): - Knm = tf.tile(Knm[None,...], [P,1,1]) - tf.debugging.assert_equal(tf.shape(Knm), [P, N, M]) - function_space_update_X = tf.transpose(tf.matmul(Knm, # [P, N, M] - tf.transpose(v)[..., None] # [P, M, 1] - )[...,0]) # [N, P] + Knm = tf.tile(Knm[None, ...], [P, 1, 1]) + tf.debugging.assert_equal(tf.shape(Knm), [P, N, M]) + function_space_update_X = tf.transpose( + tf.matmul(Knm, tf.transpose(v)[..., None])[ # [P, N, M] # [P, M, 1] + ..., 0 + ] + ) # [N, P] tf.debugging.assert_equal(tf.shape(weight_space_prior_X), [N, P]) tf.debugging.assert_equal(tf.shape(function_space_update_X), [N, P]) diff --git a/gpflux/sampling/sample.py b/gpflux/sampling/sample.py index 15d3e11e..f72b221b 100644 --- a/gpflux/sampling/sample.py +++ b/gpflux/sampling/sample.py @@ -30,7 +30,10 @@ from gpflow.utilities import Dispatcher from gpflux.math import compute_A_inv_b -from gpflux.feature_decomposition_kernels import KernelWithFeatureDecomposition, _ApproximateKernel +from gpflux.feature_decomposition_kernels import ( + KernelWithFeatureDecomposition, + _ApproximateKernel, +) from gpflux.sampling.utils import draw_conditional_sample from .dispatch import efficient_sample @@ -71,7 +74,9 @@ def __call__(self, X: TensorType) -> tf.Tensor: """ raise NotImplementedError - def __add__(self, other: Union["Sample", Callable[[TensorType], TensorType]]) -> "Sample": + def __add__( + self, other: Union["Sample", Callable[[TensorType], TensorType]] + ) -> "Sample": """ Allow for the summation of two instances that implement the ``__call__`` method. """ @@ -135,6 +140,7 @@ def __call__(self, X_new: TensorType) -> tf.Tensor: return SampleConditional() + @efficient_sample.register(InducingVariables, KernelWithFeatureDecomposition, object) def _efficient_sample_matheron_rule( inducing_variable: InducingVariables, @@ -161,27 +167,25 @@ def _efficient_sample_matheron_rule( M, P = tf.shape(q_mu)[0], tf.shape(q_mu)[1] # num inducing, num output heads prior_weights = tf.sqrt(kernel.feature_coefficients) * tf.random.normal( - (L, P), dtype=default_float() # [L, 1], [L,P] + (L, P), dtype=default_float() # [L, 1], [L,P] ) # [L, P] u_sample_noise = tf.matmul( - q_sqrt, + q_sqrt, tf.random.normal((P, M, 1), dtype=default_float()), # [P, M, M] # [P, M, 1] ) # [P, M, 1] - Kmm = Kuu(inducing_variable, kernel, jitter=default_jitter()) # [M, M] + Kmm = Kuu(inducing_variable, kernel, jitter=default_jitter()) # [M, M] tf.debugging.assert_equal(tf.shape(Kmm), [M, M]) u_sample = q_mu + tf.linalg.matrix_transpose(u_sample_noise[..., 0]) # [M, P] if whiten: - Luu = tf.linalg.cholesky(Kmm) # [M, M] + Luu = tf.linalg.cholesky(Kmm) # [M, M] u_sample = tf.matmul(Luu, u_sample) # [M, P] - phi_Z = kernel.feature_functions(inducing_variable.Z) # [M, L] - - weight_space_prior_Z = tf.matmul( phi_Z, # [M, L] - prior_weights # [L, P] - ) # [M, P] + phi_Z = kernel.feature_functions(inducing_variable.Z) # [M, L] + + weight_space_prior_Z = tf.matmul(phi_Z, prior_weights) # [M, L] # [L, P] # [M, P] diff = u_sample - weight_space_prior_Z # [M, P] v = compute_A_inv_b(Kmm, diff) # [M, P] @@ -195,18 +199,17 @@ def __call__(self, X: TensorType) -> tf.Tensor: :return: function value of sample [N, P] """ N = tf.shape(X)[0] - phi_X = kernel.feature_functions(X) # [N, L] - + phi_X = kernel.feature_functions(X) # [N, L] - weight_space_prior_X = tf.matmul(phi_X, # [N, L] - prior_weights # [L, P] - ) # [N, P] + weight_space_prior_X = tf.matmul( + phi_X, prior_weights # [N, L] # [L, P] + ) # [N, P] - Knm = tf.linalg.matrix_transpose(Kuf(inducing_variable, kernel, X)) # [N, M] + Knm = tf.linalg.matrix_transpose( + Kuf(inducing_variable, kernel, X) + ) # [N, M] - function_space_update_X = tf.matmul(Knm, # [N, M] - v # [M, P] - ) # [N, P] + function_space_update_X = tf.matmul(Knm, v) # [N, M] # [M, P] # [N, P] tf.debugging.assert_equal(tf.shape(weight_space_prior_X), [N, P]) tf.debugging.assert_equal(tf.shape(function_space_update_X), [N, P]) diff --git a/gpflux/sampling/utils.py b/gpflux/sampling/utils.py index 3ab63103..15836da0 100644 --- a/gpflux/sampling/utils.py +++ b/gpflux/sampling/utils.py @@ -24,7 +24,9 @@ from gpflux.math import _cholesky_with_jitter -def draw_conditional_sample(mean: TensorType, cov: TensorType, f_old: TensorType) -> tf.Tensor: +def draw_conditional_sample( + mean: TensorType, cov: TensorType, f_old: TensorType +) -> tf.Tensor: r""" Draw a sample :math:`\tilde{f}_\text{new}` from the conditional multivariate Gaussian :math:`p(f_\text{new} | f_\text{old})`, where the From 45aac95405ed9e8420607436a7fa8a8c9fa53eb0 Mon Sep 17 00:00:00 2001 From: SebastianPopescu Date: Wed, 14 Sep 2022 11:27:08 +0100 Subject: [PATCH 03/25] hopefully formating is okay now --- docs/conf.py | 8 +- docs/notebooks/benchmarks.py | 5 +- docs/notebooks/deep_gp_samples.py | 20 ++- .../notebooks/efficient_posterior_sampling.py | 104 ++++++++--- docs/notebooks/efficient_sampling.py | 14 +- docs/notebooks/gpflux_features.py | 13 +- docs/notebooks/gpflux_with_keras_layers.py | 5 +- docs/notebooks/keras_integration.py | 30 ++-- .../multi_output_efficient_sampling.py | 44 +++-- ...multi_output_weight_space_approximation.py | 166 +++++++++++------- docs/notebooks/weight_space_approximation.py | 66 +++++-- tests/conftest.py | 4 +- .../fourier_features/test_multioutput_rff.py | 107 +++++------ .../test_multioutput_rff_cosine.py | 96 +++++----- .../fourier_features/test_quadrature.py | 28 ++- .../fourier_features/test_random.py | 22 ++- .../layers/test_bayesian_dense_layer.py | 13 +- .../layers/test_dedup_trackable_layer.py | 28 ++- tests/gpflux/layers/test_gp_layer.py | 21 ++- .../layers/test_latent_variable_layer.py | 16 +- tests/gpflux/layers/test_likelihood_layer.py | 22 ++- tests/gpflux/layers/test_trackable_layer.py | 19 +- tests/gpflux/models/test_bayesian_model.py | 4 +- tests/gpflux/models/test_deep_gp.py | 12 +- .../sampling/test_multioutput_sample.py | 86 +++++---- tests/gpflux/sampling/test_sample.py | 11 +- tests/gpflux/test_callbacks.py | 14 +- tests/gpflux/test_ci_utils.py | 6 +- tests/gpflux/test_helpers.py | 14 +- tests/gpflux/test_math.py | 4 +- tests/gpflux/test_runtime_checks.py | 8 +- tests/integration/test_compilation.py | 12 +- tests/integration/test_svgp_equivalence.py | 51 +++--- tests/test_notebooks.py | 8 +- 34 files changed, 695 insertions(+), 386 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 02eb90f6..d30e482f 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -69,11 +69,11 @@ "python": ("https://docs.python.org/3/", None), "tensorflow": ( "https://www.tensorflow.org/api_docs/python", - "https://github.com/GPflow/tensorflow-intersphinx/raw/master/tf2_py_objects.inv" + "https://github.com/GPflow/tensorflow-intersphinx/raw/master/tf2_py_objects.inv", ), "tensorflow_probability": ( "https://www.tensorflow.org/probability/api_docs/python", - "https://github.com/GPflow/tensorflow-intersphinx/raw/master/tfp_py_objects.inv" + "https://github.com/GPflow/tensorflow-intersphinx/raw/master/tfp_py_objects.inv", ), "gpflow": ("https://gpflow.readthedocs.io/en/master/", None), } @@ -116,7 +116,9 @@ } # If True, show link to rst source on rendered HTML pages -html_show_sourcelink = False # Remove 'view source code' from top of page (for html, not python) +html_show_sourcelink = ( + False # Remove 'view source code' from top of page (for html, not python) +) # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, diff --git a/docs/notebooks/benchmarks.py b/docs/notebooks/benchmarks.py index 471ea6bd..a845f1e0 100644 --- a/docs/notebooks/benchmarks.py +++ b/docs/notebooks/benchmarks.py @@ -41,10 +41,7 @@ # %% {"nbsphinx": "hidden"} table = df.groupby(["dataset", "model"]).agg( - { - "split": "count", - **{metric: ["mean", "std"] for metric in ["mse", "nlpd"]}, - } + {"split": "count", **{metric: ["mean", "std"] for metric in ["mse", "nlpd"]},} ) # %% [markdown] """ diff --git a/docs/notebooks/deep_gp_samples.py b/docs/notebooks/deep_gp_samples.py index 635c527a..d7ca4af5 100644 --- a/docs/notebooks/deep_gp_samples.py +++ b/docs/notebooks/deep_gp_samples.py @@ -53,25 +53,35 @@ M = Z.shape[0] # Layer 1 -inducing_var1 = construct_basic_inducing_variables(M, D, D, share_variables=True, z_init=Z.copy()) +inducing_var1 = construct_basic_inducing_variables( + M, D, D, share_variables=True, z_init=Z.copy() +) kernel1 = construct_basic_kernel( gpflow.kernels.SquaredExponential(lengthscales=0.15), output_dim=D, share_hyperparams=True, ) -layer1 = GPLayer(kernel1, inducing_var1, num_data, full_cov=True, num_samples=num_samples) +layer1 = GPLayer( + kernel1, inducing_var1, num_data, full_cov=True, num_samples=num_samples +) # Layer 2 -inducing_var2 = construct_basic_inducing_variables(M, D, D, share_variables=True, z_init=Z.copy()) +inducing_var2 = construct_basic_inducing_variables( + M, D, D, share_variables=True, z_init=Z.copy() +) kernel2 = construct_basic_kernel( gpflow.kernels.SquaredExponential(lengthscales=0.8, variance=0.1), output_dim=D, share_hyperparams=True, ) -layer2 = GPLayer(kernel2, inducing_var2, num_data, full_cov=True, num_samples=num_samples) +layer2 = GPLayer( + kernel2, inducing_var2, num_data, full_cov=True, num_samples=num_samples +) # Layer 3 -inducing_var3 = construct_basic_inducing_variables(M, D, D, share_variables=True, z_init=Z.copy()) +inducing_var3 = construct_basic_inducing_variables( + M, D, D, share_variables=True, z_init=Z.copy() +) kernel3 = construct_basic_kernel( gpflow.kernels.SquaredExponential(lengthscales=0.3, variance=0.1), output_dim=D, diff --git a/docs/notebooks/efficient_posterior_sampling.py b/docs/notebooks/efficient_posterior_sampling.py index cb9a561b..aba88341 100644 --- a/docs/notebooks/efficient_posterior_sampling.py +++ b/docs/notebooks/efficient_posterior_sampling.py @@ -80,7 +80,9 @@ from gpflow.models import GPR from gpflux.layers.basis_functions.fourier_features import RandomFourierFeaturesCosine -from gpflux.sampling.kernel_with_feature_decomposition import KernelWithFeatureDecomposition +from gpflux.sampling.kernel_with_feature_decomposition import ( + KernelWithFeatureDecomposition, +) # %% [markdown] """ @@ -96,8 +98,16 @@ # settings that vary across experiments num_input_dimensions = [2, 4, 8] # number of input dimensions -train_sample_exponents = [2, 4, 6, 8, 10] # num_train_samples = 2 ** train_sample_exponents -num_train_samples = [2 ** train_sample_exponent for train_sample_exponent in train_sample_exponents] +train_sample_exponents = [ + 2, + 4, + 6, + 8, + 10, +] # num_train_samples = 2 ** train_sample_exponents +num_train_samples = [ + 2 ** train_sample_exponent for train_sample_exponent in train_sample_exponents +] num_features = [ 1024, 4096, @@ -140,7 +150,9 @@ def compute_analytic_GP_predictions(X, y, kernel, noise_variance, X_star): """ # %% -def compute_hybrid_rule_predictions(X, y, exact_kernel, approximate_kernel, noise_variance, X_star): +def compute_hybrid_rule_predictions( + X, y, exact_kernel, approximate_kernel, noise_variance, X_star +): """ Identify the mean and covariance using the hybrid Matheron approximation of the exact posterior. @@ -164,7 +176,9 @@ def compute_hybrid_rule_predictions(X, y, exact_kernel, approximate_kernel, nois assert kXstarX.shape == (X_star.shape[0], X.shape[0]) KXX = exact_kernel.K(X) - kXX_plus_noise_var = tf.linalg.set_diag(KXX, tf.linalg.diag_part(KXX) + noise_variance) + kXX_plus_noise_var = tf.linalg.set_diag( + KXX, tf.linalg.diag_part(KXX) + noise_variance + ) assert kXX_plus_noise_var.shape == (X.shape[0], X.shape[0]) kXX_inv_mul_phi = tf.linalg.solve(kXX_plus_noise_var, phi) @@ -214,9 +228,12 @@ def log10_Wasserstein_distance( square_root_covariance = tf.linalg.sqrtm( covariance + tf.eye(tf.shape(covariance)[0], dtype=covariance.dtype) * jitter ) - matrix_product = square_root_covariance @ approximate_covariance @ square_root_covariance + matrix_product = ( + square_root_covariance @ approximate_covariance @ square_root_covariance + ) square_root_matrix_product = tf.linalg.sqrtm( - matrix_product + tf.eye(tf.shape(matrix_product)[0], dtype=matrix_product.dtype) * jitter + matrix_product + + tf.eye(tf.shape(matrix_product)[0], dtype=matrix_product.dtype) * jitter ) term = covariance + approximate_covariance - 2 * square_root_matrix_product trace = tf.linalg.trace(term) @@ -260,18 +277,24 @@ def conduct_experiment(num_input_dimensions, num_train_samples, num_features): ) feature_coefficients = np.ones((num_features, 1), dtype=default_float()) approximate_kernel = KernelWithFeatureDecomposition( - kernel=None, feature_functions=feature_functions, feature_coefficients=feature_coefficients + kernel=None, + feature_functions=feature_functions, + feature_coefficients=feature_coefficients, ) # create training data set and test points for evaluation X = [] for i in range(num_input_dimensions): - random_samples = np.random.uniform(low=0.15, high=0.85, size=(num_train_samples,)) + random_samples = np.random.uniform( + low=0.15, high=0.85, size=(num_train_samples,) + ) X.append(random_samples) X = np.array(X).transpose() kXX = exact_kernel.K(X) - kXX_plus_noise_var = tf.linalg.set_diag(kXX, tf.linalg.diag_part(kXX) + noise_variance) + kXX_plus_noise_var = tf.linalg.set_diag( + kXX, tf.linalg.diag_part(kXX) + noise_variance + ) lXX = tf.linalg.cholesky(kXX_plus_noise_var) y = tf.matmul(lXX, tf.random.normal([num_train_samples, 1], dtype=X.dtype)) @@ -281,9 +304,9 @@ def conduct_experiment(num_input_dimensions, num_train_samples, num_features): for i in range(num_input_dimensions): random_samples = np.random.uniform(low=0.0, high=0.3, size=(num_test_samples,)) indices = np.random.uniform(size=(num_test_samples,)) < 0.5 - random_samples[indices] = np.random.uniform(low=0.7, high=1.0, size=(num_test_samples,))[ - indices - ] + random_samples[indices] = np.random.uniform( + low=0.7, high=1.0, size=(num_test_samples,) + )[indices] X_star.append(random_samples) X_star = np.array(X_star).transpose() @@ -294,7 +317,11 @@ def conduct_experiment(num_input_dimensions, num_train_samples, num_features): # identify mean and covariance of the analytic GPR posterior when using the weight space approximated kernel f_mean_weight, f_var_weight = compute_analytic_GP_predictions( - X=X, y=y, kernel=approximate_kernel, noise_variance=noise_variance, X_star=X_star + X=X, + y=y, + kernel=approximate_kernel, + noise_variance=noise_variance, + X_star=X_star, ) # identify mean and covariance using the hybrid approximation @@ -327,7 +354,9 @@ def conduct_experiment(num_input_dimensions, num_train_samples, num_features): """ # %% -def conduct_experiment_for_multiple_runs(num_input_dimensions, num_train_samples, num_features): +def conduct_experiment_for_multiple_runs( + num_input_dimensions, num_train_samples, num_features +): """ Conduct the experiment as specified above `num_experiment_runs` times and identify the quartiles for the log10 Wassertein distance between the weight space approximated GP and the exact GP, @@ -352,8 +381,12 @@ def conduct_experiment_for_multiple_runs(num_input_dimensions, num_train_samples list_of_log10_ws_dist_weight.append(log10_ws_dist_weight) list_of_log10_ws_dist_hybrid.append(log10_ws_dist_hybrid) - log10_ws_dist_weight_quarts = np.quantile(list_of_log10_ws_dist_weight, q=(0.25, 0.5, 0.75)) - log10_ws_dist_hybrid_quarts = np.quantile(list_of_log10_ws_dist_hybrid, q=(0.25, 0.5, 0.75)) + log10_ws_dist_weight_quarts = np.quantile( + list_of_log10_ws_dist_weight, q=(0.25, 0.5, 0.75) + ) + log10_ws_dist_hybrid_quarts = np.quantile( + list_of_log10_ws_dist_hybrid, q=(0.25, 0.5, 0.75) + ) return log10_ws_dist_weight_quarts, log10_ws_dist_hybrid_quarts @@ -363,7 +396,9 @@ def conduct_experiment_for_multiple_runs(num_input_dimensions, num_train_samples """ # %% -def conduct_experiment_for_different_train_data_sizes(num_input_dimensions, num_features): +def conduct_experiment_for_different_train_data_sizes( + num_input_dimensions, num_features +): """ Conduct the experiment as specified above for different training dataset sizes and store the results in lists. @@ -396,8 +431,12 @@ def conduct_experiment_for_different_train_data_sizes(num_input_dimensions, num_ list_log10_ws_dist_weight_quarts.append(log10_ws_dist_weight_quarts) list_log10_ws_dist_hybrid_quarts.append(log10_ws_dist_hybrid_quarts) - list_log10_ws_dist_weight_quarts = np.array(list_log10_ws_dist_weight_quarts).transpose() - list_log10_ws_dist_hybrid_quarts = np.array(list_log10_ws_dist_hybrid_quarts).transpose() + list_log10_ws_dist_weight_quarts = np.array( + list_log10_ws_dist_weight_quarts + ).transpose() + list_log10_ws_dist_hybrid_quarts = np.array( + list_log10_ws_dist_hybrid_quarts + ).transpose() return list_log10_ws_dist_weight_quarts, list_log10_ws_dist_hybrid_quarts @@ -421,7 +460,10 @@ def conduct_experiment_for_different_num_features(num_input_dimensions): ) # for the analytic solution using the weight space approximated kernel list_of_hybrid_results = [] # for the hybrid-rule approximation for nf in num_features: - weight_results, hybrid_results = conduct_experiment_for_different_train_data_sizes( + ( + weight_results, + hybrid_results, + ) = conduct_experiment_for_different_train_data_sizes( num_input_dimensions=num_input_dimensions, num_features=nf ) print() @@ -454,22 +496,34 @@ def conduct_experiment_for_different_num_features(num_input_dimensions): # plot the results for the analytic solution using the weight space approximated kernel colors = ["bisque", "orange", "peru"] - assert len(colors) == len(num_features), "Number of colors must equal the number of features!" + assert len(colors) == len( + num_features + ), "Number of colors must equal the number of features!" for j in range(len(weight_results)): weight_result = weight_results[j] axs[i].fill_between( - num_train_samples, weight_result[0], weight_result[2], color=colors[j], alpha=0.1 + num_train_samples, + weight_result[0], + weight_result[2], + color=colors[j], + alpha=0.1, ) axs[i].plot(num_train_samples, weight_result[1], "o", color=colors[j]) axs[i].plot(num_train_samples, weight_result[1], color=colors[j], linewidth=0.5) # plot the results for the hybrid-rule approximation colors = ["lightblue", "blue", "darkblue"] - assert len(colors) == len(num_features), "Number of colors must equal the number of features!" + assert len(colors) == len( + num_features + ), "Number of colors must equal the number of features!" for j in range(len(hybrid_results)): hybrid_result = hybrid_results[j] axs[i].fill_between( - num_train_samples, hybrid_result[0], hybrid_result[2], color=colors[j], alpha=0.1 + num_train_samples, + hybrid_result[0], + hybrid_result[2], + color=colors[j], + alpha=0.1, ) axs[i].plot(num_train_samples, hybrid_result[1], "o", color=colors[j]) axs[i].plot(num_train_samples, hybrid_result[1], color=colors[j], linewidth=0.5) diff --git a/docs/notebooks/efficient_sampling.py b/docs/notebooks/efficient_sampling.py index fe85598c..e9483f91 100644 --- a/docs/notebooks/efficient_sampling.py +++ b/docs/notebooks/efficient_sampling.py @@ -75,7 +75,9 @@ eigenfunctions = RandomFourierFeaturesCosine(kernel, num_rff, dtype=default_float()) eigenvalues = np.ones((num_rff, 1), dtype=default_float()) -kernel_with_features = KernelWithFeatureDecomposition(kernel, eigenfunctions, eigenvalues) +kernel_with_features = KernelWithFeatureDecomposition( + kernel, eigenfunctions, eigenvalues +) # %% [markdown] @@ -94,7 +96,9 @@ num_latent_gps=1, mean_function=gpflow.mean_functions.Zero(), ) -likelihood_layer = gpflux.layers.LikelihoodLayer(gpflow.likelihoods.Gaussian()) # noqa: E231 +likelihood_layer = gpflux.layers.LikelihoodLayer( + gpflow.likelihoods.Gaussian() +) # noqa: E231 dgp = gpflux.models.DeepGP([layer], likelihood_layer) model = dgp.as_training_model() # %% [markdown] @@ -107,11 +111,7 @@ callbacks = [ tf.keras.callbacks.ReduceLROnPlateau( - monitor="loss", - patience=5, - factor=0.95, - verbose=0, - min_lr=1e-6, + monitor="loss", patience=5, factor=0.95, verbose=0, min_lr=1e-6, ) ] diff --git a/docs/notebooks/gpflux_features.py b/docs/notebooks/gpflux_features.py index bd09db82..0155140c 100644 --- a/docs/notebooks/gpflux_features.py +++ b/docs/notebooks/gpflux_features.py @@ -68,7 +68,10 @@ def motorcycle_data(): from gpflux.models import DeepGP config = Config( - num_inducing=25, inner_layer_qsqrt_factor=1e-5, likelihood_noise_variance=1e-2, whiten=True + num_inducing=25, + inner_layer_qsqrt_factor=1e-5, + likelihood_noise_variance=1e-2, + whiten=True, ) deep_gp: DeepGP = build_constant_input_dim_deep_gp(X, num_layers=2, config=config) @@ -89,11 +92,15 @@ def motorcycle_data(): callbacks = [ # Create callback that reduces the learning rate every time the ELBO plateaus - tf.keras.callbacks.ReduceLROnPlateau("loss", factor=0.95, patience=3, min_lr=1e-6, verbose=0), + tf.keras.callbacks.ReduceLROnPlateau( + "loss", factor=0.95, patience=3, min_lr=1e-6, verbose=0 + ), # Create a callback that writes logs (e.g., hyperparameters, KLs, etc.) to TensorBoard gpflux.callbacks.TensorBoard(), # Create a callback that saves the model's weights - tf.keras.callbacks.ModelCheckpoint(filepath="ckpts/", save_weights_only=True, verbose=0), + tf.keras.callbacks.ModelCheckpoint( + filepath="ckpts/", save_weights_only=True, verbose=0 + ), ] history = training_model.fit( diff --git a/docs/notebooks/gpflux_with_keras_layers.py b/docs/notebooks/gpflux_with_keras_layers.py index 4bb5c6ef..ba051517 100644 --- a/docs/notebooks/gpflux_with_keras_layers.py +++ b/docs/notebooks/gpflux_with_keras_layers.py @@ -117,7 +117,10 @@ def plot(model, X, Y, ax=None): f_distribution = model(X_test) mean = f_distribution.mean().numpy().squeeze() - var = f_distribution.variance().numpy().squeeze() + model.layers[-1].likelihood.variance.numpy() + var = ( + f_distribution.variance().numpy().squeeze() + + model.layers[-1].likelihood.variance.numpy() + ) X_test = X_test.squeeze() lower = mean - 2 * np.sqrt(var) upper = mean + 2 * np.sqrt(var) diff --git a/docs/notebooks/keras_integration.py b/docs/notebooks/keras_integration.py index 4626c178..4335034e 100644 --- a/docs/notebooks/keras_integration.py +++ b/docs/notebooks/keras_integration.py @@ -55,7 +55,9 @@ def create_layers(): layer1 = gpflux.helpers.construct_gp_layer( num_data, num_inducing, input_dim, hidden_dim, z_init=Z.copy() ) - layer1.mean_function = gpflow.mean_functions.Identity() # TODO: pass layer_type instead + layer1.mean_function = ( + gpflow.mean_functions.Identity() + ) # TODO: pass layer_type instead layer1.q_sqrt.assign(layer1.q_sqrt * 0.01) layer2 = gpflux.helpers.construct_gp_layer( @@ -76,7 +78,9 @@ def create_model(model_class): a constructor that has the same semantics as `tf.keras.Model.__init__`. """ layer1, layer2, likelihood_layer = create_layers() - dgp = gpflux.models.DeepGP([layer1, layer2], likelihood_layer, default_model_class=model_class) + dgp = gpflux.models.DeepGP( + [layer1, layer2], likelihood_layer, default_model_class=model_class + ) return dgp @@ -89,11 +93,7 @@ def create_model(model_class): callbacks = [ tf.keras.callbacks.ReduceLROnPlateau( - monitor="loss", - patience=5, - factor=0.95, - verbose=1, - min_lr=1e-6, + monitor="loss", patience=5, factor=0.95, verbose=1, min_lr=1e-6, ) ] @@ -101,7 +101,10 @@ def create_model(model_class): dgp_train.compile(tf.optimizers.Adam(learning_rate=0.1)) history = dgp_train.fit( - {"inputs": X, "targets": Y}, batch_size=batch_size, epochs=num_epochs, callbacks=callbacks + {"inputs": X, "targets": Y}, + batch_size=batch_size, + epochs=num_epochs, + callbacks=callbacks, ) # %% @@ -109,11 +112,7 @@ def create_model(model_class): callbacks = [ tf.keras.callbacks.ReduceLROnPlateau( - monitor="loss", - patience=5, - factor=0.95, - verbose=1, - min_lr=1e-6, + monitor="loss", patience=5, factor=0.95, verbose=1, min_lr=1e-6, ) ] @@ -131,7 +130,10 @@ def create_model(model_class): ) history_natgrad = dgp_natgrad_train.fit( - {"inputs": X, "targets": Y}, batch_size=batch_size, epochs=num_epochs, callbacks=callbacks + {"inputs": X, "targets": Y}, + batch_size=batch_size, + epochs=num_epochs, + callbacks=callbacks, ) # %% diff --git a/docs/notebooks/multi_output_efficient_sampling.py b/docs/notebooks/multi_output_efficient_sampling.py index c2dce513..a3375a55 100644 --- a/docs/notebooks/multi_output_efficient_sampling.py +++ b/docs/notebooks/multi_output_efficient_sampling.py @@ -36,8 +36,14 @@ from gpflow.config import default_float -from gpflux.layers.basis_functions.fourier_features import MultiOutputRandomFourierFeaturesCosine -from gpflux.feature_decomposition_kernels import KernelWithFeatureDecomposition, SharedMultiOutputKernelWithFeatureDecomposition, SeparateMultiOutputKernelWithFeatureDecomposition +from gpflux.layers.basis_functions.fourier_features import ( + MultiOutputRandomFourierFeaturesCosine, +) +from gpflux.feature_decomposition_kernels import ( + KernelWithFeatureDecomposition, + SharedMultiOutputKernelWithFeatureDecomposition, + SeparateMultiOutputKernelWithFeatureDecomposition, +) from gpflux.models.deep_gp import sample_dgp tf.keras.backend.set_floatx("float64") @@ -64,27 +70,33 @@ """ # %% -#kernel = gpflow.kernels.Matern52() +# kernel = gpflow.kernels.Matern52() kernel1 = gpflow.kernels.Matern52() kernel2 = gpflow.kernels.SquaredExponential() -#kernel = gpflow.kernels.SeparateIndependent( kernels = [kernel1, kernel2]) -kernel = gpflow.kernels.SharedIndependent( kernel = kernel1, output_dim = 2) +# kernel = gpflow.kernels.SeparateIndependent( kernels = [kernel1, kernel2]) +kernel = gpflow.kernels.SharedIndependent(kernel=kernel1, output_dim=2) Z_1 = np.linspace(X.min(), X.max(), 10).reshape(-1, 1).astype(np.float64) Z_2 = np.linspace(X.min(), X.max(), 10).reshape(-1, 1).astype(np.float64) inducing_variable_1 = gpflow.inducing_variables.InducingPoints(Z_1) inducing_variable_2 = gpflow.inducing_variables.InducingPoints(Z_2) -#inducing_variable = gpflow.inducing_variables.SeparateIndependentInducingVariables(inducing_variable_list= [inducing_variable_1, inducing_variable_2]) -inducing_variable = gpflow.inducing_variables.SharedIndependentInducingVariables(inducing_variable = inducing_variable_1) +# inducing_variable = gpflow.inducing_variables.SeparateIndependentInducingVariables(inducing_variable_list= [inducing_variable_1, inducing_variable_2]) +inducing_variable = gpflow.inducing_variables.SharedIndependentInducingVariables( + inducing_variable=inducing_variable_1 +) gpflow.utilities.set_trainable(inducing_variable, False) P = 2 num_rff = 1000 -eigenfunctions = MultiOutputRandomFourierFeaturesCosine(kernel, num_rff, dtype=default_float()) +eigenfunctions = MultiOutputRandomFourierFeaturesCosine( + kernel, num_rff, dtype=default_float() +) eigenvalues = np.ones((P, num_rff, 1), dtype=default_float()) -#kernel_with_features = SeparateMultiOutputKernelWithFeatureDecomposition(kernel, eigenfunctions, eigenvalues) -kernel_with_features = SharedMultiOutputKernelWithFeatureDecomposition(kernel, eigenfunctions, eigenvalues) +# kernel_with_features = SeparateMultiOutputKernelWithFeatureDecomposition(kernel, eigenfunctions, eigenvalues) +kernel_with_features = SharedMultiOutputKernelWithFeatureDecomposition( + kernel, eigenfunctions, eigenvalues +) # %% [markdown] """ ## Building and training the single-layer GP @@ -101,7 +113,9 @@ num_latent_gps=2, mean_function=gpflow.mean_functions.Zero(), ) -likelihood_layer = gpflux.layers.LikelihoodLayer(gpflow.likelihoods.Gaussian()) # noqa: E231 +likelihood_layer = gpflux.layers.LikelihoodLayer( + gpflow.likelihoods.Gaussian() +) # noqa: E231 dgp = gpflux.models.DeepGP([layer], likelihood_layer) model = dgp.as_training_model() # %% [markdown] @@ -114,16 +128,12 @@ callbacks = [ tf.keras.callbacks.ReduceLROnPlateau( - monitor="loss", - patience=5, - factor=0.95, - verbose=0, - min_lr=1e-6, + monitor="loss", patience=5, factor=0.95, verbose=0, min_lr=1e-6, ) ] history = model.fit( - {"inputs": X, "targets": tf.tile(Y,[1,2])}, + {"inputs": X, "targets": tf.tile(Y, [1, 2])}, batch_size=num_data, epochs=100, callbacks=callbacks, diff --git a/docs/notebooks/multi_output_weight_space_approximation.py b/docs/notebooks/multi_output_weight_space_approximation.py index a2a194b2..602903f6 100644 --- a/docs/notebooks/multi_output_weight_space_approximation.py +++ b/docs/notebooks/multi_output_weight_space_approximation.py @@ -54,17 +54,21 @@ plt.rcParams.update({"font.size": 20}) import tensorflow as tf -import gpflow +import gpflow from gpflow.config import default_float from gpflow.models import GPR, SVGP from gpflow.kernels import SquaredExponential, Matern52 from gpflow.likelihoods import Gaussian from gpflow.inducing_variables import InducingPoints -from gpflux.layers.basis_functions.fourier_features import MultiOutputRandomFourierFeaturesCosine -from gpflux.feature_decomposition_kernels import KernelWithFeatureDecomposition, SeparateMultiOutputKernelWithFeatureDecomposition, SharedMultiOutputKernelWithFeatureDecomposition - - +from gpflux.layers.basis_functions.fourier_features import ( + MultiOutputRandomFourierFeaturesCosine, +) +from gpflux.feature_decomposition_kernels import ( + KernelWithFeatureDecomposition, + SeparateMultiOutputKernelWithFeatureDecomposition, + SharedMultiOutputKernelWithFeatureDecomposition, +) # Copyright 2016-2020 The GPflow Contributors. All Rights Reserved. @@ -88,9 +92,7 @@ import gpflow - - -#from gpflow import posteriors +# from gpflow import posteriors from gpflow.base import InputData, MeanAndVariance, RegressionData from gpflow.experimental.check_shapes import check_shapes, inherit_check_shapes from gpflow.kernels import Kernel @@ -103,6 +105,7 @@ from gpflow.models.training_mixins import InternalDataTrainingLossMixin from gpflow.models.util import data_input_to_tensor + class GPR_deprecated(GPModel, InternalDataTrainingLossMixin): r""" Gaussian Process Regression. @@ -127,8 +130,7 @@ class GPR_deprecated(GPModel, InternalDataTrainingLossMixin): """ @check_shapes( - "data[0]: [N, D]", - "data[1]: [N, P]", + "data[0]: [N, D]", "data[1]: [N, P]", ) def __init__( self, @@ -146,7 +148,9 @@ def __init__( noise_variance = 1.0 likelihood = gpflow.likelihoods.Gaussian(noise_variance) _, Y_data = data - super().__init__(kernel, likelihood, mean_function, num_latent_gps=Y_data.shape[-1]) + super().__init__( + kernel, likelihood, mean_function, num_latent_gps=Y_data.shape[-1] + ) self.data = data_input_to_tensor(data) # type-ignore is because of changed method signature: @@ -154,9 +158,7 @@ def __init__( def maximum_log_likelihood_objective(self) -> tf.Tensor: # type: ignore[override] return self.log_marginal_likelihood() - @check_shapes( - "return: []", - ) + @check_shapes("return: []",) def log_marginal_likelihood(self) -> tf.Tensor: r""" Computes the log marginal likelihood. @@ -167,7 +169,9 @@ def log_marginal_likelihood(self) -> tf.Tensor: """ X, Y = self.data K = self.kernel(X) - ks = add_likelihood_noise_cov(K, self.likelihood, tf.tile(X[None,...], [2,1,1])) + ks = add_likelihood_noise_cov( + K, self.likelihood, tf.tile(X[None, ...], [2, 1, 1]) + ) L = tf.linalg.cholesky(ks) m = self.mean_function(X) @@ -196,14 +200,18 @@ def predict_f( kmm = self.kernel(X) knn = self.kernel(Xnew, full_cov=full_cov) kmn = self.kernel(X, Xnew) - #kmm_plus_s = add_likelihood_noise_cov(kmm, self.likelihood, X) - kmm_plus_s = add_likelihood_noise_cov(kmm, self.likelihood, tf.tile(X[None,...], [2,1,1])) - - #NOTE -- this onlty works for a single latent Full GP - #conditional = gpflow.conditionals.base_conditional - - conditional = gpflow.conditionals.util.separate_independent_conditional_implementation - + # kmm_plus_s = add_likelihood_noise_cov(kmm, self.likelihood, X) + kmm_plus_s = add_likelihood_noise_cov( + kmm, self.likelihood, tf.tile(X[None, ...], [2, 1, 1]) + ) + + # NOTE -- this onlty works for a single latent Full GP + # conditional = gpflow.conditionals.base_conditional + + conditional = ( + gpflow.conditionals.util.separate_independent_conditional_implementation + ) + f_mean_zero, f_var = conditional( kmn, kmm_plus_s, knn, err, full_cov=full_cov, white=False ) # [N, P], [N, P] or [P, N, N] @@ -211,9 +219,6 @@ def predict_f( return f_mean, f_var - - - # %% [markdown] """ Our aim is to demonstrate the decrease in predictive quality of a WSA model when increasing the number of training points. To that end, we perform two sets of experiments: one with few and one with many training data points. Each experiment compares a WSA model to an exact GPR and to an approximate SVGP model, resulting in six plots all in all. @@ -226,9 +231,15 @@ def predict_f( # %% # experiment parameters that are the same for both sets of experiments X_interval = [0.14, 0.5] # interval where training points live -lengthscale = [0.1] # lengthscale for the kernel (which is not learned in all experiments, the kernel variance is 1) -number_of_features = 2000 # number of basis functions for weight-space approximated kernels -noise_variance = 1e-3 # noise variance of the likelihood (which is not learned in all experiments) +lengthscale = [ + 0.1 +] # lengthscale for the kernel (which is not learned in all experiments, the kernel variance is 1) +number_of_features = ( + 2000 # number of basis functions for weight-space approximated kernels +) +noise_variance = ( + 1e-3 # noise variance of the likelihood (which is not learned in all experiments) +) number_of_test_samples = 1024 # number of evaluation points for prediction number_of_function_samples = ( 20 # number of function samples to be drawn from (approximate) posteriors @@ -239,7 +250,7 @@ def predict_f( number_of_inducing_points = [4, 8] # number of inducing points for SVGP models # kernel class -#kernel_class = Matern52 # set altern experiment = 2*j + nvmatively kernel_class = RBF +# kernel_class = Matern52 # set altern experiment = 2*j + nvmatively kernel_class = RBF # plotting configuration x_lim = [0.0, 1.0] @@ -254,36 +265,53 @@ def predict_f( # generate training data and evaluation points for both sets of experiments -list_kernels = [ Matern52(lengthscales=lengthscale), SquaredExponential(lengthscales=lengthscale) ] -#kernel = kernel_class(lengthscales=lengthscale) # kernel object to draw training dataset from +list_kernels = [ + Matern52(lengthscales=lengthscale), + SquaredExponential(lengthscales=lengthscale), +] +# kernel = kernel_class(lengthscales=lengthscale) # kernel object to draw training dataset from -X, y, X_star = [], [], [] # training points, training observations, and test points for evaluation +X, y, X_star = ( + [], + [], + [], +) # training points, training observations, and test points for evaluation # 1st iteration: experiments with few training points -- 2nd iteration: experiments with many training points for i in range(len(number_of_train_samples)): - - X_temp, y_temp, X_star_temp = [], [], [] + + X_temp, y_temp, X_star_temp = [], [], [] # training pointsnumber_of_train_samples - X.append(np.linspace(start=X_interval[0], stop=X_interval[1], num=number_of_train_samples[i])[...,None]) + X.append( + np.linspace( + start=X_interval[0], stop=X_interval[1], num=number_of_train_samples[i] + )[..., None] + ) for j in range(len(list_kernels)): # training observations generated from a zero-mean GP corrupted with Gaussian noise kXX = list_kernels[j].K(X[-1]) - kXX_plus_noise_var = kXX + tf.eye(tf.shape(kXX)[0], dtype=kXX.dtype) * noise_variance + kXX_plus_noise_var = ( + kXX + tf.eye(tf.shape(kXX)[0], dtype=kXX.dtype) * noise_variance + ) lXX = tf.linalg.cholesky(kXX_plus_noise_var) y_temp.append( - tf.matmul(lXX, tf.random.normal([number_of_train_samples[i], 1], dtype=X[-1].dtype))[..., 0][...,None] + tf.matmul( + lXX, + tf.random.normal([number_of_train_samples[i], 1], dtype=X[-1].dtype), + )[..., 0][..., None] ) # test points for evaluation - X_star.append(np.linspace(start=x_lim[0], stop=x_lim[1], num=number_of_test_samples)[...,None]) - y.append(np.concatenate(y_temp, axis = -1)) - - - + X_star.append( + np.linspace(start=x_lim[0], stop=x_lim[1], num=number_of_test_samples)[ + ..., None + ] + ) + y.append(np.concatenate(y_temp, axis=-1)) # %% [markdown] @@ -333,29 +361,30 @@ def predict_f( axs[experiment, 1].set_ylim(y_lim) # create exact GPR model with weight-space approximated kernel (WSA model) - + kernel1 = gpflow.kernels.Matern52(lengthscales=lengthscale) kernel2 = gpflow.kernels.SquaredExponential(lengthscales=lengthscale) - #kernel = gpflow.kernels.SeparateIndependent( kernels = [kernel1, kernel2]) - kernel = gpflow.kernels.SharedIndependent( kernel = kernel1, output_dim = 2) + # kernel = gpflow.kernels.SeparateIndependent( kernels = [kernel1, kernel2]) + kernel = gpflow.kernels.SharedIndependent(kernel=kernel1, output_dim=2) - feature_functions = MultiOutputRandomFourierFeaturesCosine(kernel, - number_of_features, - dtype=default_float()) + feature_functions = MultiOutputRandomFourierFeaturesCosine( + kernel, number_of_features, dtype=default_float() + ) feature_coefficients = np.ones((2, number_of_features, 1), dtype=default_float()) - #kernel = SeparateMultiOutputKernelWithFeatureDecomposition( - # kernel=None, feature_functions=feature_functions, feature_coefficients=feature_coefficients, + # kernel = SeparateMultiOutputKernelWithFeatureDecomposition( + # kernel=None, feature_functions=feature_functions, feature_coefficients=feature_coefficients, # output_dim = 2 - #) + # ) kernel = SharedMultiOutputKernelWithFeatureDecomposition( - kernel=None, feature_functions=feature_functions, feature_coefficients=feature_coefficients, - output_dim = 2 + kernel=None, + feature_functions=feature_functions, + feature_coefficients=feature_coefficients, + output_dim=2, ) - - print('***************************************') - print('-- shape of data for current experiment') + print("***************************************") + print("-- shape of data for current experiment") print(X[experiment].shape) print(y[experiment].shape) print(X_star[experiment].shape) @@ -375,18 +404,17 @@ def predict_f( f_mean_plus_2std = f_mean + 2 * f_var ** 0.5 f_mean_minus_2std = f_mean - 2 * f_var ** 0.5 - print('***************************************') - print('-- shape of current predictions') + print("***************************************") + print("-- shape of current predictions") print(f_mean.shape) print(f_mean_minus_2std.shape) - # visualise WSA model predictions (mean +/- 2 * std and function samples) in the third column ### Matern52 ### axs[experiment, 0].fill_between( - X_star[experiment][...,0], + X_star[experiment][..., 0], f_mean_minus_2std[..., 0], f_mean_plus_2std[..., 0], color="orange", @@ -394,14 +422,17 @@ def predict_f( ) for i in range(f_samples.shape[0]): axs[experiment, 0].plot( - X_star[experiment][...,0], f_samples[i, ..., 0], color="orange", linewidth=0.2 + X_star[experiment][..., 0], + f_samples[i, ..., 0], + color="orange", + linewidth=0.2, ) - axs[experiment, 0].plot(X_star[experiment][...,0], f_mean[..., 0], color="orange") + axs[experiment, 0].plot(X_star[experiment][..., 0], f_mean[..., 0], color="orange") ### SquaredExponential ### axs[experiment, 1].fill_between( - X_star[experiment][...,0], + X_star[experiment][..., 0], f_mean_minus_2std[..., 1], f_mean_plus_2std[..., 1], color="orange", @@ -409,9 +440,12 @@ def predict_f( ) for i in range(f_samples.shape[0]): axs[experiment, 1].plot( - X_star[experiment][...,0], f_samples[i, ..., 1], color="orange", linewidth=0.2 + X_star[experiment][..., 0], + f_samples[i, ..., 1], + color="orange", + linewidth=0.2, ) - axs[experiment, 1].plot(X_star[experiment][...,0], f_mean[..., 1], color="orange") + axs[experiment, 1].plot(X_star[experiment][..., 0], f_mean[..., 1], color="orange") # show the plot diff --git a/docs/notebooks/weight_space_approximation.py b/docs/notebooks/weight_space_approximation.py index 7e8dab12..d8b1b2ac 100644 --- a/docs/notebooks/weight_space_approximation.py +++ b/docs/notebooks/weight_space_approximation.py @@ -77,8 +77,12 @@ # experiment parameters that are the same for both sets of experiments X_interval = [0.14, 0.5] # interval where training points live lengthscale = 0.1 # lengthscale for the kernel (which is not learned in all experiments, the kernel variance is 1) -number_of_features = 2000 # number of basis functions for weight-space approximated kernels -noise_variance = 1e-3 # noise variance of the likelihood (which is not learned in all experiments) +number_of_features = ( + 2000 # number of basis functions for weight-space approximated kernels +) +noise_variance = ( + 1e-3 # noise variance of the likelihood (which is not learned in all experiments) +) number_of_test_samples = 1024 # number of evaluation points for prediction number_of_function_samples = ( 20 # number of function samples to be drawn from (approximate) posteriors @@ -102,25 +106,41 @@ # %% # generate training data and evaluation points for both sets of experiments -kernel = kernel_class(lengthscales=lengthscale) # kernel object to draw training dataset from -X, y, X_star = [], [], [] # training points, training observations, and test points for evaluation +kernel = kernel_class( + lengthscales=lengthscale +) # kernel object to draw training dataset from +X, y, X_star = ( + [], + [], + [], +) # training points, training observations, and test points for evaluation # 1st iteration: experiments with few training points -- 2nd iteration: experiments with many training points for i in range(len(number_of_train_samples)): # training pointsnumber_of_train_samples - X.append(np.linspace(start=X_interval[0], stop=X_interval[1], num=number_of_train_samples[i])) + X.append( + np.linspace( + start=X_interval[0], stop=X_interval[1], num=number_of_train_samples[i] + ) + ) # training observations generated from a zero-mean GP corrupted with Gaussian noise kXX = kernel.K(X[i][..., None]) - kXX_plus_noise_var = kXX + tf.eye(tf.shape(kXX)[0], dtype=kXX.dtype) * noise_variance + kXX_plus_noise_var = ( + kXX + tf.eye(tf.shape(kXX)[0], dtype=kXX.dtype) * noise_variance + ) lXX = tf.linalg.cholesky(kXX_plus_noise_var) y.append( - tf.matmul(lXX, tf.random.normal([number_of_train_samples[i], 1], dtype=X[i].dtype))[..., 0] + tf.matmul( + lXX, tf.random.normal([number_of_train_samples[i], 1], dtype=X[i].dtype) + )[..., 0] ) # test points for evaluation - X_star.append(np.linspace(start=x_lim[0], stop=x_lim[1], num=number_of_test_samples)) + X_star.append( + np.linspace(start=x_lim[0], stop=x_lim[1], num=number_of_test_samples) + ) # %% [markdown] """ @@ -139,8 +159,12 @@ for experiment in range(len(number_of_train_samples)): # subplot titles and axis labels - axs[experiment, 0].set_title("Exact GP $N=" + str(number_of_train_samples[experiment]) + "$") - axs[experiment, 1].set_title("Sparse GP $N=" + str(number_of_train_samples[experiment]) + "$") + axs[experiment, 0].set_title( + "Exact GP $N=" + str(number_of_train_samples[experiment]) + "$" + ) + axs[experiment, 1].set_title( + "Sparse GP $N=" + str(number_of_train_samples[experiment]) + "$" + ) axs[experiment, 2].set_title( "Weight Space GP $N=" + str(number_of_train_samples[experiment]) + "$" ) @@ -182,7 +206,9 @@ # plot mean and std lines from the GPR model as "ground truth" in all three plots for i in range(3): - axs[experiment, i].plot(X_star[experiment], f_mean[..., 0], linestyle="--", color="black") + axs[experiment, i].plot( + X_star[experiment], f_mean[..., 0], linestyle="--", color="black" + ) axs[experiment, i].plot( X_star[experiment], f_mean_minus_2std[..., 0], linestyle="--", color="black" ) @@ -209,9 +235,9 @@ ): # inducing points equal the training data for the first experiment with few training points Z = X[experiment].copy()[..., None] else: # inducing points are randomly chosen for the second experiment with many training points - Z = np.linspace(X_interval[0], X_interval[1], number_of_inducing_points[experiment])[ - ..., None - ] + Z = np.linspace( + X_interval[0], X_interval[1], number_of_inducing_points[experiment] + )[..., None] svgp_model = SVGP( kernel=kernel_class(lengthscales=lengthscale), likelihood=Gaussian(variance=noise_variance), @@ -221,12 +247,16 @@ svgp_model.kernel, False ) # the training data has been sampled from a known kernel! gpf.set_trainable(svgp_model.likelihood, False) # the likelihood variance is known! - gpf.set_trainable(svgp_model.inducing_variable, False) # inducing point locations are fixed! + gpf.set_trainable( + svgp_model.inducing_variable, False + ) # inducing point locations are fixed! def optimize_model_with_scipy(model): optimizer = gpf.optimizers.Scipy() optimizer.minimize( - model.training_loss_closure((X[experiment][..., None], y[experiment][..., None])), + model.training_loss_closure( + (X[experiment][..., None], y[experiment][..., None]) + ), variables=model.trainable_variables, method="l-bfgs-b", options={"disp": False, "maxiter": 10000}, @@ -271,7 +301,9 @@ def optimize_model_with_scipy(model): ) feature_coefficients = np.ones((number_of_features, 1), dtype=default_float()) kernel = KernelWithFeatureDecomposition( - kernel=None, feature_functions=feature_functions, feature_coefficients=feature_coefficients + kernel=None, + feature_functions=feature_functions, + feature_coefficients=feature_coefficients, ) gpr_model = GPR( data=(X[experiment][..., None], y[experiment][..., None]), diff --git a/tests/conftest.py b/tests/conftest.py index 69b39d72..7b42b147 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -24,7 +24,9 @@ def test_data(): input_data = np.concatenate([x_data, w_data], axis=1) assert input_data.shape == (num_data, x_dim + w_dim) y_data = np.random.multivariate_normal( - mean=np.zeros(num_data), cov=SquaredExponential(variance=0.1)(input_data), size=y_dim + mean=np.zeros(num_data), + cov=SquaredExponential(variance=0.1)(input_data), + size=y_dim, ).T assert y_data.shape == (num_data, y_dim) return x_data, y_data diff --git a/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff.py b/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff.py index 111d006c..3a4bfd88 100644 --- a/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff.py +++ b/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff.py @@ -27,13 +27,19 @@ MultiOutputRandomFourierFeatures, MultiOutputRandomFourierFeaturesCosine, ) -from gpflux.layers.basis_functions.fourier_features.random.base import RFF_SUPPORTED_KERNELS -from gpflux.layers.basis_functions.fourier_features.multioutput.random import MultiOutputRandomFourierFeatures -from gpflux.feature_decomposition_kernels.multioutput import SharedMultiOutputKernelWithFeatureDecomposition, SeparateMultiOutputKernelWithFeatureDecomposition +from gpflux.layers.basis_functions.fourier_features.random.base import ( + RFF_SUPPORTED_KERNELS, +) +from gpflux.layers.basis_functions.fourier_features.multioutput.random import ( + MultiOutputRandomFourierFeatures, +) +from gpflux.feature_decomposition_kernels.multioutput import ( + SharedMultiOutputKernelWithFeatureDecomposition, + SeparateMultiOutputKernelWithFeatureDecomposition, +) from tests.conftest import skip_serialization_tests - @pytest.fixture(name="n_dims", params=[1, 2, 3, 5, 10, 20]) def _n_dims_fixture(request): return request.param @@ -64,45 +70,43 @@ def _base_kernel_cls_fixture(request): return request.param -#@pytest.fixture(name="kernel_cls", params=[SeparateIndependent]) #, SharedIndependent]) -#def _kernel_cls_fixture(request): +# @pytest.fixture(name="kernel_cls", params=[SeparateIndependent]) #, SharedIndependent]) +# def _kernel_cls_fixture(request): # return request.param @pytest.fixture( - name="random_basis_func_cls", - params=[MultiOutputRandomFourierFeatures], + name="random_basis_func_cls", params=[MultiOutputRandomFourierFeatures], ) def _random_basis_func_cls_fixture(request): return request.param @pytest.fixture( - name="basis_func_cls", - params=[MultiOutputRandomFourierFeatures ], + name="basis_func_cls", params=[MultiOutputRandomFourierFeatures], ) def _basis_func_cls_fixture(request): return request.param - def test_throw_for_unsupported_separate_kernel(basis_func_cls): base_kernel = gpflow.kernels.Constant() - kernel = gpflow.kernels.SeparateIndependent(kernels = [base_kernel]) + kernel = gpflow.kernels.SeparateIndependent(kernels=[base_kernel]) with pytest.raises(AssertionError) as excinfo: basis_func_cls(kernel, n_components=1) assert "Unsupported Kernel" in str(excinfo.value) + def test_throw_for_unsupported_shared_kernel(basis_func_cls): base_kernel = gpflow.kernels.Constant() - kernel = SharedIndependent(kernel = base_kernel, output_dim=1) + kernel = SharedIndependent(kernel=base_kernel, output_dim=1) with pytest.raises(AssertionError) as excinfo: basis_func_cls(kernel, n_components=1) assert "Unsupported Kernel" in str(excinfo.value) def test_random_fourier_features_can_approximate_multi_output_separate_kernel_multidim( - random_basis_func_cls, base_kernel_cls, variance, lengthscale, n_dims + random_basis_func_cls, base_kernel_cls, variance, lengthscale, n_dims ): n_components = 40000 @@ -111,36 +115,36 @@ def test_random_fourier_features_can_approximate_multi_output_separate_kernel_mu # ARD lengthscales = np.random.rand((n_dims)) * lengthscale - print('size of sampled lengthscales') + print("size of sampled lengthscales") print(lengthscales.shape) base_kernel = base_kernel_cls(variance=variance, lengthscales=lengthscales) - kernel = SeparateIndependent(kernels = [base_kernel, base_kernel]) + kernel = SeparateIndependent(kernels=[base_kernel, base_kernel]) x = tf.random.uniform((x_rows, n_dims), dtype=tf.float64) y = tf.random.uniform((y_rows, n_dims), dtype=tf.float64) - actual_kernel_matrix = kernel.K(x, y, full_output_cov = False).numpy() + actual_kernel_matrix = kernel.K(x, y, full_output_cov=False).numpy() fourier_features = random_basis_func_cls(kernel, n_components, dtype=tf.float64) - feature_coefficients = np.ones((2, 2*n_components, 1), dtype=np.float64) + feature_coefficients = np.ones((2, 2 * n_components, 1), dtype=np.float64) kernel = SeparateMultiOutputKernelWithFeatureDecomposition( - kernel=None, feature_functions=fourier_features, feature_coefficients=feature_coefficients, - output_dim = 2 + kernel=None, + feature_functions=fourier_features, + feature_coefficients=feature_coefficients, + output_dim=2, ) - approx_kernel_matrix = kernel(x,y).numpy() - + approx_kernel_matrix = kernel(x, y).numpy() np.testing.assert_allclose(approx_kernel_matrix, actual_kernel_matrix, atol=5e-2) - def test_random_fourier_features_can_approximate_multi_output_shared_kernel_multidim( - random_basis_func_cls, base_kernel_cls, variance, lengthscale, n_dims + random_basis_func_cls, base_kernel_cls, variance, lengthscale, n_dims ): n_components = 40000 @@ -149,36 +153,34 @@ def test_random_fourier_features_can_approximate_multi_output_shared_kernel_mult # ARD lengthscales = np.random.rand((n_dims)) * lengthscale - print('size of sampled lengthscales') + print("size of sampled lengthscales") print(lengthscales.shape) base_kernel = base_kernel_cls(variance=variance, lengthscales=lengthscales) - kernel = SharedIndependent(kernel = base_kernel, output_dim = 2) + kernel = SharedIndependent(kernel=base_kernel, output_dim=2) x = tf.random.uniform((x_rows, n_dims), dtype=tf.float64) y = tf.random.uniform((y_rows, n_dims), dtype=tf.float64) - actual_kernel_matrix = kernel.K(x, y, full_output_cov = False).numpy() + actual_kernel_matrix = kernel.K(x, y, full_output_cov=False).numpy() fourier_features = random_basis_func_cls(kernel, n_components, dtype=tf.float64) - feature_coefficients = np.ones((2, 2*n_components, 1), dtype=np.float64) + feature_coefficients = np.ones((2, 2 * n_components, 1), dtype=np.float64) kernel = SharedMultiOutputKernelWithFeatureDecomposition( - kernel=None, feature_functions=fourier_features, feature_coefficients=feature_coefficients, - output_dim = 2 + kernel=None, + feature_functions=fourier_features, + feature_coefficients=feature_coefficients, + output_dim=2, ) - - - approx_kernel_matrix = kernel(x,y).numpy() + approx_kernel_matrix = kernel(x, y).numpy() np.testing.assert_allclose(approx_kernel_matrix, actual_kernel_matrix, atol=5e-2) - - """ #TODO -- still need to implement the orthogonal version def test_orthogonal_random_features_can_approximate_kernel_multidim(variance, lengthscale, n_dims): @@ -205,6 +207,7 @@ def test_orthogonal_random_features_can_approximate_kernel_multidim(variance, le """ + def test_random_multi_output_fourier_feature_layer_compute_covariance_of_shared_inducing_variables( basis_func_cls, batch_size ): @@ -216,13 +219,15 @@ def test_random_multi_output_fourier_feature_layer_compute_covariance_of_shared_ n_components = 10000 base_kernel = gpflow.kernels.SquaredExponential() - kernel = SharedIndependent(kernel = base_kernel, output_dim = 2) + kernel = SharedIndependent(kernel=base_kernel, output_dim=2) fourier_features = basis_func_cls(kernel, n_components, dtype=tf.float64) - feature_coefficients = np.ones((2, 2*n_components, 1), dtype=np.float64) + feature_coefficients = np.ones((2, 2 * n_components, 1), dtype=np.float64) feature_decomposition_kernel = SharedMultiOutputKernelWithFeatureDecomposition( - kernel=None, feature_functions=fourier_features, feature_coefficients=feature_coefficients, - output_dim = 2 + kernel=None, + feature_functions=fourier_features, + feature_coefficients=feature_coefficients, + output_dim=2, ) x_new = tf.ones(shape=(2 * batch_size + 1, 1), dtype=tf.float64) @@ -243,13 +248,15 @@ def test_random_multi_output_fourier_feature_layer_compute_covariance_of_separat n_components = 10000 base_kernel = gpflow.kernels.SquaredExponential() - kernel = SeparateIndependent(kernels = [base_kernel, base_kernel]) + kernel = SeparateIndependent(kernels=[base_kernel, base_kernel]) fourier_features = basis_func_cls(kernel, n_components, dtype=tf.float64) - feature_coefficients = np.ones((2, 2*n_components, 1), dtype=np.float64) + feature_coefficients = np.ones((2, 2 * n_components, 1), dtype=np.float64) feature_decomposition_kernel = SharedMultiOutputKernelWithFeatureDecomposition( - kernel=None, feature_functions=fourier_features, feature_coefficients=feature_coefficients, - output_dim = 2 + kernel=None, + feature_functions=fourier_features, + feature_coefficients=feature_coefficients, + output_dim=2, ) x_new = tf.ones(shape=(2 * batch_size + 1, 1), dtype=tf.float64) @@ -259,18 +266,18 @@ def test_random_multi_output_fourier_feature_layer_compute_covariance_of_separat np.testing.assert_allclose(approx_kernel_matrix, actual_kernel_matrix, atol=5e-2) -def test_multi_output_fourier_features_shapes(basis_func_cls, n_components, n_dims, batch_size): +def test_multi_output_fourier_features_shapes( + basis_func_cls, n_components, n_dims, batch_size +): input_shape = (2, batch_size, n_dims) - base_kernel = gpflow.kernels.SquaredExponential(lengthscales= [1.0] * n_dims) - kernel = SeparateIndependent(kernels = [base_kernel, base_kernel]) + base_kernel = gpflow.kernels.SquaredExponential(lengthscales=[1.0] * n_dims) + kernel = SeparateIndependent(kernels=[base_kernel, base_kernel]) feature_functions = basis_func_cls(kernel, n_components, dtype=tf.float64) - output_shape = feature_functions.compute_output_shape(input_shape) + output_shape = feature_functions.compute_output_shape(input_shape) features = feature_functions(tf.ones(shape=(batch_size, n_dims))) np.testing.assert_equal(features.shape, output_shape) - - """ #TODO -- have a look at what layer_test actually does @skip_serialization_tests @@ -310,4 +317,4 @@ def test_keras_testing_util_layer_test_multidim(kernel_cls, batch_size, n_dims, input_dtype="float64", ) -""" \ No newline at end of file +""" diff --git a/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff_cosine.py b/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff_cosine.py index 07b85381..939dc663 100644 --- a/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff_cosine.py +++ b/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff_cosine.py @@ -27,13 +27,19 @@ MultiOutputRandomFourierFeatures, MultiOutputRandomFourierFeaturesCosine, ) -from gpflux.layers.basis_functions.fourier_features.random.base import RFF_SUPPORTED_KERNELS -from gpflux.layers.basis_functions.fourier_features.multioutput.random import MultiOutputRandomFourierFeatures -from gpflux.feature_decomposition_kernels.multioutput import SharedMultiOutputKernelWithFeatureDecomposition, SeparateMultiOutputKernelWithFeatureDecomposition +from gpflux.layers.basis_functions.fourier_features.random.base import ( + RFF_SUPPORTED_KERNELS, +) +from gpflux.layers.basis_functions.fourier_features.multioutput.random import ( + MultiOutputRandomFourierFeatures, +) +from gpflux.feature_decomposition_kernels.multioutput import ( + SharedMultiOutputKernelWithFeatureDecomposition, + SeparateMultiOutputKernelWithFeatureDecomposition, +) from tests.conftest import skip_serialization_tests - @pytest.fixture(name="n_dims", params=[1, 2, 3, 5, 10, 20]) def _n_dims_fixture(request): return request.param @@ -63,40 +69,39 @@ def _n_features_fixture(request): def _base_kernel_cls_fixture(request): return request.param + @pytest.fixture( - name="random_basis_func_cls", - params=[MultiOutputRandomFourierFeaturesCosine], + name="random_basis_func_cls", params=[MultiOutputRandomFourierFeaturesCosine], ) def _random_basis_func_cls_fixture(request): return request.param @pytest.fixture( - name="basis_func_cls", - params=[MultiOutputRandomFourierFeaturesCosine], + name="basis_func_cls", params=[MultiOutputRandomFourierFeaturesCosine], ) def _basis_func_cls_fixture(request): return request.param - def test_throw_for_unsupported_separate_kernel(basis_func_cls): base_kernel = gpflow.kernels.Constant() - kernel = gpflow.kernels.SeparateIndependent(kernels = [base_kernel]) + kernel = gpflow.kernels.SeparateIndependent(kernels=[base_kernel]) with pytest.raises(AssertionError) as excinfo: basis_func_cls(kernel, n_components=1) assert "Unsupported Kernel" in str(excinfo.value) + def test_throw_for_unsupported_shared_kernel(basis_func_cls): base_kernel = gpflow.kernels.Constant() - kernel = SharedIndependent(kernel = base_kernel, output_dim=1) + kernel = SharedIndependent(kernel=base_kernel, output_dim=1) with pytest.raises(AssertionError) as excinfo: basis_func_cls(kernel, n_components=1) assert "Unsupported Kernel" in str(excinfo.value) def test_random_fourier_features_can_approximate_multi_output_separate_kernel_multidim( - random_basis_func_cls, base_kernel_cls, variance, lengthscale, n_dims + random_basis_func_cls, base_kernel_cls, variance, lengthscale, n_dims ): n_components = 40000 @@ -105,36 +110,36 @@ def test_random_fourier_features_can_approximate_multi_output_separate_kernel_mu # ARD lengthscales = np.random.rand((n_dims)) * lengthscale - print('size of sampled lengthscales') + print("size of sampled lengthscales") print(lengthscales.shape) base_kernel = base_kernel_cls(variance=variance, lengthscales=lengthscales) - kernel = SeparateIndependent(kernels = [base_kernel, base_kernel]) + kernel = SeparateIndependent(kernels=[base_kernel, base_kernel]) x = tf.random.uniform((x_rows, n_dims), dtype=tf.float64) y = tf.random.uniform((y_rows, n_dims), dtype=tf.float64) - actual_kernel_matrix = kernel.K(x, y, full_output_cov = False).numpy() + actual_kernel_matrix = kernel.K(x, y, full_output_cov=False).numpy() fourier_features = random_basis_func_cls(kernel, n_components, dtype=tf.float64) feature_coefficients = np.ones((2, n_components, 1), dtype=np.float64) kernel = SeparateMultiOutputKernelWithFeatureDecomposition( - kernel=None, feature_functions=fourier_features, feature_coefficients=feature_coefficients, - output_dim = 2 + kernel=None, + feature_functions=fourier_features, + feature_coefficients=feature_coefficients, + output_dim=2, ) - approx_kernel_matrix = kernel(x,y).numpy() - + approx_kernel_matrix = kernel(x, y).numpy() np.testing.assert_allclose(approx_kernel_matrix, actual_kernel_matrix, atol=5e-2) - def test_random_fourier_features_can_approximate_multi_output_shared_kernel_multidim( - random_basis_func_cls, base_kernel_cls, variance, lengthscale, n_dims + random_basis_func_cls, base_kernel_cls, variance, lengthscale, n_dims ): n_components = 40000 @@ -143,36 +148,34 @@ def test_random_fourier_features_can_approximate_multi_output_shared_kernel_mult # ARD lengthscales = np.random.rand((n_dims)) * lengthscale - print('size of sampled lengthscales') + print("size of sampled lengthscales") print(lengthscales.shape) base_kernel = base_kernel_cls(variance=variance, lengthscales=lengthscales) - kernel = SharedIndependent(kernel = base_kernel, output_dim = 2) + kernel = SharedIndependent(kernel=base_kernel, output_dim=2) x = tf.random.uniform((x_rows, n_dims), dtype=tf.float64) y = tf.random.uniform((y_rows, n_dims), dtype=tf.float64) - actual_kernel_matrix = kernel.K(x, y, full_output_cov = False).numpy() + actual_kernel_matrix = kernel.K(x, y, full_output_cov=False).numpy() fourier_features = random_basis_func_cls(kernel, n_components, dtype=tf.float64) feature_coefficients = np.ones((2, n_components, 1), dtype=np.float64) kernel = SharedMultiOutputKernelWithFeatureDecomposition( - kernel=None, feature_functions=fourier_features, feature_coefficients=feature_coefficients, - output_dim = 2 + kernel=None, + feature_functions=fourier_features, + feature_coefficients=feature_coefficients, + output_dim=2, ) - - - approx_kernel_matrix = kernel(x,y).numpy() + approx_kernel_matrix = kernel(x, y).numpy() np.testing.assert_allclose(approx_kernel_matrix, actual_kernel_matrix, atol=5e-2) - - """ #TODO -- still need to implement the orthogonal version def test_orthogonal_random_features_can_approximate_kernel_multidim(variance, lengthscale, n_dims): @@ -199,6 +202,7 @@ def test_orthogonal_random_features_can_approximate_kernel_multidim(variance, le """ + def test_random_multi_output_fourier_feature_layer_compute_covariance_of_shared_inducing_variables( basis_func_cls, batch_size ): @@ -210,13 +214,15 @@ def test_random_multi_output_fourier_feature_layer_compute_covariance_of_shared_ n_components = 10000 base_kernel = gpflow.kernels.SquaredExponential() - kernel = SharedIndependent(kernel = base_kernel, output_dim = 2) + kernel = SharedIndependent(kernel=base_kernel, output_dim=2) fourier_features = basis_func_cls(kernel, n_components, dtype=tf.float64) feature_coefficients = np.ones((2, n_components, 1), dtype=np.float64) feature_decomposition_kernel = SharedMultiOutputKernelWithFeatureDecomposition( - kernel=None, feature_functions=fourier_features, feature_coefficients=feature_coefficients, - output_dim = 2 + kernel=None, + feature_functions=fourier_features, + feature_coefficients=feature_coefficients, + output_dim=2, ) x_new = tf.ones(shape=(2 * batch_size + 1, 1), dtype=tf.float64) @@ -237,13 +243,15 @@ def test_random_multi_output_fourier_feature_layer_compute_covariance_of_separat n_components = 10000 base_kernel = gpflow.kernels.SquaredExponential() - kernel = SeparateIndependent(kernels = [base_kernel, base_kernel]) + kernel = SeparateIndependent(kernels=[base_kernel, base_kernel]) fourier_features = basis_func_cls(kernel, n_components, dtype=tf.float64) feature_coefficients = np.ones((2, n_components, 1), dtype=np.float64) feature_decomposition_kernel = SharedMultiOutputKernelWithFeatureDecomposition( - kernel=None, feature_functions=fourier_features, feature_coefficients=feature_coefficients, - output_dim = 2 + kernel=None, + feature_functions=fourier_features, + feature_coefficients=feature_coefficients, + output_dim=2, ) x_new = tf.ones(shape=(2 * batch_size + 1, 1), dtype=tf.float64) @@ -253,18 +261,18 @@ def test_random_multi_output_fourier_feature_layer_compute_covariance_of_separat np.testing.assert_allclose(approx_kernel_matrix, actual_kernel_matrix, atol=5e-2) -def test_multi_output_fourier_features_shapes(basis_func_cls, n_components, n_dims, batch_size): +def test_multi_output_fourier_features_shapes( + basis_func_cls, n_components, n_dims, batch_size +): input_shape = (2, batch_size, n_dims) - base_kernel = gpflow.kernels.SquaredExponential(lengthscales= [1.0] * n_dims) - kernel = SeparateIndependent(kernels = [base_kernel, base_kernel]) + base_kernel = gpflow.kernels.SquaredExponential(lengthscales=[1.0] * n_dims) + kernel = SeparateIndependent(kernels=[base_kernel, base_kernel]) feature_functions = basis_func_cls(kernel, n_components, dtype=tf.float64) - output_shape = feature_functions.compute_output_shape(input_shape) + output_shape = feature_functions.compute_output_shape(input_shape) features = feature_functions(tf.ones(shape=(batch_size, n_dims))) np.testing.assert_equal(features.shape, output_shape) - - """ #TODO -- have a look at what layer_test actually does @skip_serialization_tests @@ -304,4 +312,4 @@ def test_keras_testing_util_layer_test_multidim(kernel_cls, batch_size, n_dims, input_dtype="float64", ) -""" \ No newline at end of file +""" diff --git a/tests/gpflux/layers/basis_functions/fourier_features/test_quadrature.py b/tests/gpflux/layers/basis_functions/fourier_features/test_quadrature.py index f563b2f6..b972c1a6 100644 --- a/tests/gpflux/layers/basis_functions/fourier_features/test_quadrature.py +++ b/tests/gpflux/layers/basis_functions/fourier_features/test_quadrature.py @@ -23,8 +23,12 @@ from gpflow.quadrature.gauss_hermite import NDiagGHQuadrature from gpflow.utilities.ops import difference_matrix -from gpflux.layers.basis_functions.fourier_features.quadrature import QuadratureFourierFeatures -from gpflux.layers.basis_functions.fourier_features.quadrature.gaussian import QFF_SUPPORTED_KERNELS +from gpflux.layers.basis_functions.fourier_features.quadrature import ( + QuadratureFourierFeatures, +) +from gpflux.layers.basis_functions.fourier_features.quadrature.gaussian import ( + QFF_SUPPORTED_KERNELS, +) from tests.conftest import skip_serialization_tests @@ -97,7 +101,9 @@ def test_quadrature_fourier_features_can_approximate_kernel_multidim( np.testing.assert_allclose(approx_kernel_matrix, actual_kernel_matrix) -def test_feature_map_decomposition(kernel_cls, variance, lengthscale, n_dims, n_components): +def test_feature_map_decomposition( + kernel_cls, variance, lengthscale, n_dims, n_components +): """ Verify that the inner product of the feature map yields exactly the same result as that of the direct Gauss-Hermite quadrature scheme. @@ -138,7 +144,9 @@ def eigen_func(w): def test_fourier_features_shapes(n_components, n_dims, batch_size): input_shape = (batch_size, n_dims) kernel = gpflow.kernels.SquaredExponential() - feature_functions = QuadratureFourierFeatures(kernel, n_components, dtype=tf.float64) + feature_functions = QuadratureFourierFeatures( + kernel, n_components, dtype=tf.float64 + ) output_shape = feature_functions.compute_output_shape(input_shape) output_dim = output_shape[-1] assert output_dim == 2 * n_components ** n_dims @@ -150,7 +158,9 @@ def test_fourier_features_shapes(n_components, n_dims, batch_size): def test_keras_testing_util_layer_test_1D(kernel_cls, batch_size, n_components): kernel = kernel_cls() - tf.keras.utils.get_custom_objects()["QuadratureFourierFeatures"] = QuadratureFourierFeatures + tf.keras.utils.get_custom_objects()[ + "QuadratureFourierFeatures" + ] = QuadratureFourierFeatures layer_test( QuadratureFourierFeatures, kwargs={ @@ -166,10 +176,14 @@ def test_keras_testing_util_layer_test_1D(kernel_cls, batch_size, n_components): @skip_serialization_tests -def test_keras_testing_util_layer_test_multidim(kernel_cls, batch_size, n_dims, n_components): +def test_keras_testing_util_layer_test_multidim( + kernel_cls, batch_size, n_dims, n_components +): kernel = kernel_cls() - tf.keras.utils.get_custom_objects()["QuadratureFourierFeatures"] = QuadratureFourierFeatures + tf.keras.utils.get_custom_objects()[ + "QuadratureFourierFeatures" + ] = QuadratureFourierFeatures layer_test( QuadratureFourierFeatures, kwargs={ diff --git a/tests/gpflux/layers/basis_functions/fourier_features/test_random.py b/tests/gpflux/layers/basis_functions/fourier_features/test_random.py index 774a6997..4d482a4f 100644 --- a/tests/gpflux/layers/basis_functions/fourier_features/test_random.py +++ b/tests/gpflux/layers/basis_functions/fourier_features/test_random.py @@ -26,7 +26,9 @@ RandomFourierFeatures, RandomFourierFeaturesCosine, ) -from gpflux.layers.basis_functions.fourier_features.random.base import RFF_SUPPORTED_KERNELS +from gpflux.layers.basis_functions.fourier_features.random.base import ( + RFF_SUPPORTED_KERNELS, +) from tests.conftest import skip_serialization_tests @@ -70,7 +72,11 @@ def _random_basis_func_cls_fixture(request): @pytest.fixture( name="basis_func_cls", - params=[RandomFourierFeatures, RandomFourierFeaturesCosine, OrthogonalRandomFeatures], + params=[ + RandomFourierFeatures, + RandomFourierFeaturesCosine, + OrthogonalRandomFeatures, + ], ) def _basis_func_cls_fixture(request): return request.param @@ -108,7 +114,9 @@ def test_random_fourier_features_can_approximate_kernel_multidim( np.testing.assert_allclose(approx_kernel_matrix, actual_kernel_matrix, atol=5e-2) -def test_orthogonal_random_features_can_approximate_kernel_multidim(variance, lengthscale, n_dims): +def test_orthogonal_random_features_can_approximate_kernel_multidim( + variance, lengthscale, n_dims +): n_components = 20000 x_rows = 20 @@ -116,7 +124,9 @@ def test_orthogonal_random_features_can_approximate_kernel_multidim(variance, le # ARD lengthscales = np.random.rand((n_dims)) * lengthscale - kernel = gpflow.kernels.SquaredExponential(variance=variance, lengthscales=lengthscales) + kernel = gpflow.kernels.SquaredExponential( + variance=variance, lengthscales=lengthscales + ) fourier_features = OrthogonalRandomFeatures(kernel, n_components, dtype=tf.float64) x = tf.random.uniform((x_rows, n_dims), dtype=tf.float64) @@ -183,7 +193,9 @@ def test_keras_testing_util_layer_test_1D(kernel_cls, batch_size, n_components): @skip_serialization_tests -def test_keras_testing_util_layer_test_multidim(kernel_cls, batch_size, n_dims, n_components): +def test_keras_testing_util_layer_test_multidim( + kernel_cls, batch_size, n_dims, n_components +): kernel = kernel_cls() tf.keras.utils.get_custom_objects()["RandomFourierFeatures"] = RandomFourierFeatures diff --git a/tests/gpflux/layers/test_bayesian_dense_layer.py b/tests/gpflux/layers/test_bayesian_dense_layer.py index da97d5dc..62d69e9a 100644 --- a/tests/gpflux/layers/test_bayesian_dense_layer.py +++ b/tests/gpflux/layers/test_bayesian_dense_layer.py @@ -56,7 +56,10 @@ def make_data(input_dim: int, output_dim: int, num_data: int): X = np.random.random(size=(num_data, input_dim)) * lim[1] cov = RBF().K(X) + np.eye(num_data) * sigma ** 2 - Y = [np.random.multivariate_normal(np.zeros(num_data), cov)[:, None] for _ in range(output_dim)] + Y = [ + np.random.multivariate_normal(np.zeros(num_data), cov)[:, None] + for _ in range(output_dim) + ] Y = np.hstack(Y) return X, Y @@ -146,7 +149,9 @@ def test_losses_are_added(is_mean_field): assert len(bnn_layer.losses) == 0 _ = bnn_layer(X, training=True) - assert bnn_layer.losses == [bnn_layer.temperature * bnn_layer.prior_kl() / bnn_layer.num_data] + assert bnn_layer.losses == [ + bnn_layer.temperature * bnn_layer.prior_kl() / bnn_layer.num_data + ] # Check loss is 0 when training is False _ = bnn_layer(X, training=False) @@ -156,4 +161,6 @@ def test_losses_are_added(is_mean_field): _ = bnn_layer(X, training=True) _ = bnn_layer(X, training=True) assert len(bnn_layer.losses) == 1 - assert bnn_layer.losses == [bnn_layer.temperature * bnn_layer.prior_kl() / bnn_layer.num_data] + assert bnn_layer.losses == [ + bnn_layer.temperature * bnn_layer.prior_kl() / bnn_layer.num_data + ] diff --git a/tests/gpflux/layers/test_dedup_trackable_layer.py b/tests/gpflux/layers/test_dedup_trackable_layer.py index 93d4efc4..e600c7d1 100644 --- a/tests/gpflux/layers/test_dedup_trackable_layer.py +++ b/tests/gpflux/layers/test_dedup_trackable_layer.py @@ -63,10 +63,14 @@ def model(data) -> tf.keras.models.Model: num_data = len(X) input_dim = X.shape[-1] - layer1 = construct_gp_layer(num_data, CONFIG.num_inducing, input_dim, CONFIG.hidden_dim) + layer1 = construct_gp_layer( + num_data, CONFIG.num_inducing, input_dim, CONFIG.hidden_dim + ) output_dim = Y.shape[-1] - layer2 = construct_gp_layer(num_data, CONFIG.num_inducing, CONFIG.hidden_dim, output_dim) + layer2 = construct_gp_layer( + num_data, CONFIG.num_inducing, CONFIG.hidden_dim, output_dim + ) likelihood_layer = gpflux.layers.LikelihoodLayer(gpflow.likelihoods.Gaussian(0.01)) @@ -91,15 +95,23 @@ def _size_q_mu(num_inducing, output_dim): "._self_tracked_trackables[1].inducing_variable.inducing_variable.Z": ( CONFIG.num_inducing * CONFIG.input_dim ), - "._self_tracked_trackables[1].q_mu": _size_q_mu(CONFIG.num_inducing, CONFIG.hidden_dim), - "._self_tracked_trackables[1].q_sqrt": _size_q_sqrt(CONFIG.num_inducing, CONFIG.hidden_dim), + "._self_tracked_trackables[1].q_mu": _size_q_mu( + CONFIG.num_inducing, CONFIG.hidden_dim + ), + "._self_tracked_trackables[1].q_sqrt": _size_q_sqrt( + CONFIG.num_inducing, CONFIG.hidden_dim + ), "._self_tracked_trackables[2].kernel.kernel.variance": 1, "._self_tracked_trackables[2].kernel.kernel.lengthscales": CONFIG.hidden_dim, "._self_tracked_trackables[2].inducing_variable.inducing_variable.Z": ( CONFIG.num_inducing * CONFIG.hidden_dim ), - "._self_tracked_trackables[2].q_mu": _size_q_mu(CONFIG.num_inducing, CONFIG.output_dim), - "._self_tracked_trackables[2].q_sqrt": _size_q_sqrt(CONFIG.num_inducing, CONFIG.output_dim), + "._self_tracked_trackables[2].q_mu": _size_q_mu( + CONFIG.num_inducing, CONFIG.output_dim + ), + "._self_tracked_trackables[2].q_sqrt": _size_q_sqrt( + CONFIG.num_inducing, CONFIG.output_dim + ), "._self_tracked_trackables[3].likelihood.variance": 1, } @@ -140,7 +152,9 @@ def test_weights_equals_deduplicated_parameter_dict(model): """ # We filter out the parameters of type ResourceVariable. # They have been added to the model by the `add_metric` call in the layer. - parameters = [p for p in parameter_dict(model).values() if not isinstance(p, ResourceVariable)] + parameters = [ + p for p in parameter_dict(model).values() if not isinstance(p, ResourceVariable) + ] variables = map(lambda p: p.unconstrained_variable, parameters) deduplicate_variables = object_identity.ObjectIdentitySet(variables) diff --git a/tests/gpflux/layers/test_gp_layer.py b/tests/gpflux/layers/test_gp_layer.py index 7e5f7317..b69a2d5e 100644 --- a/tests/gpflux/layers/test_gp_layer.py +++ b/tests/gpflux/layers/test_gp_layer.py @@ -33,7 +33,9 @@ def setup_gp_layer_and_data(num_inducing: int, **gp_layer_kwargs): data = make_data(input_dim, output_dim, num_data=num_data) kernel = construct_basic_kernel(RBF(), output_dim) - inducing_vars = construct_basic_inducing_variables(num_inducing, input_dim, output_dim) + inducing_vars = construct_basic_inducing_variables( + num_inducing, input_dim, output_dim + ) mean_function = Zero(output_dim) gp_layer = GPLayer( @@ -48,7 +50,10 @@ def make_data(input_dim: int, output_dim: int, num_data: int): X = np.random.random(size=(num_data, input_dim)) * lim[1] cov = RBF().K(X) + np.eye(num_data) * sigma ** 2 - Y = [np.random.multivariate_normal(np.zeros(num_data), cov)[:, None] for _ in range(output_dim)] + Y = [ + np.random.multivariate_normal(np.zeros(num_data), cov)[:, None] + for _ in range(output_dim) + ] Y = np.hstack(Y) return X, Y @@ -98,19 +103,25 @@ def test_call_shapes(): assert not gp_layer.full_cov and not gp_layer.full_output_cov distribution = gp_layer(X, training=False) - assert isinstance(unwrap_dist(distribution), tfp.distributions.MultivariateNormalDiag) + assert isinstance( + unwrap_dist(distribution), tfp.distributions.MultivariateNormalDiag + ) assert distribution.shape == (batch_size, output_dim) gp_layer.full_cov = True distribution = gp_layer(X, training=False) - assert isinstance(unwrap_dist(distribution), tfp.distributions.MultivariateNormalTriL) + assert isinstance( + unwrap_dist(distribution), tfp.distributions.MultivariateNormalTriL + ) assert distribution.shape == (batch_size, output_dim) assert distribution.covariance().shape == (output_dim, batch_size, batch_size) gp_layer.full_output_cov = True gp_layer.full_cov = False distribution = gp_layer(X, training=False) - assert isinstance(unwrap_dist(distribution), tfp.distributions.MultivariateNormalTriL) + assert isinstance( + unwrap_dist(distribution), tfp.distributions.MultivariateNormalTriL + ) assert distribution.shape == (batch_size, output_dim) assert distribution.covariance().shape == (batch_size, output_dim, output_dim) diff --git a/tests/gpflux/layers/test_latent_variable_layer.py b/tests/gpflux/layers/test_latent_variable_layer.py index ac985613..30aba081 100644 --- a/tests/gpflux/layers/test_latent_variable_layer.py +++ b/tests/gpflux/layers/test_latent_variable_layer.py @@ -35,7 +35,9 @@ def _zero_one_normal_prior(w_dim): """N(0, I) prior""" - return tfp.distributions.MultivariateNormalDiag(loc=np.zeros(w_dim), scale_diag=np.ones(w_dim)) + return tfp.distributions.MultivariateNormalDiag( + loc=np.zeros(w_dim), scale_diag=np.ones(w_dim) + ) def get_distributions_with_w_dim(): @@ -174,13 +176,19 @@ def test_latent_variable_layer_samples(mocker, test_data, w_dim, seed2): tf.random.set_seed(seed) sample_prior = lv(inputs, seed=seed2) tf.random.set_seed(seed) - prior_expected = np.concatenate([inputs, prior.sample(num_data, seed=seed2)], axis=-1) + prior_expected = np.concatenate( + [inputs, prior.sample(num_data, seed=seed2)], axis=-1 + ) np.testing.assert_array_equal(sample_prior, prior_expected) tf.random.set_seed(seed) - sample_posterior = lv(inputs, observations=[inputs, targets], training=True, seed=seed2) + sample_posterior = lv( + inputs, observations=[inputs, targets], training=True, seed=seed2 + ) tf.random.set_seed(seed) - posterior_expected = np.concatenate([inputs, posteriors.sample(seed=seed2)], axis=-1) + posterior_expected = np.concatenate( + [inputs, posteriors.sample(seed=seed2)], axis=-1 + ) np.testing.assert_array_equal(sample_posterior, posterior_expected) diff --git a/tests/gpflux/layers/test_likelihood_layer.py b/tests/gpflux/layers/test_likelihood_layer.py index 1972d096..3a47baee 100644 --- a/tests/gpflux/layers/test_likelihood_layer.py +++ b/tests/gpflux/layers/test_likelihood_layer.py @@ -36,7 +36,9 @@ def setup_gp_layer_and_data(num_inducing: int, **gp_layer_kwargs): data = make_data(input_dim, output_dim, num_data=num_data) kernel = construct_basic_kernel(Matern52(), output_dim) - inducing_vars = construct_basic_inducing_variables(num_inducing, input_dim, output_dim) + inducing_vars = construct_basic_inducing_variables( + num_inducing, input_dim, output_dim + ) mean_function = Zero(output_dim) gp_layer = GPLayer( @@ -51,9 +53,15 @@ def make_data(input_dim: int, output_dim: int, num_data: int): X = np.random.random(size=(num_data, input_dim)) * lim[1] cov = Matern52()(X) + np.eye(num_data) * sigma ** 2 - Y = [np.random.multivariate_normal(np.zeros(num_data), cov)[:, None] for _ in range(output_dim)] + Y = [ + np.random.multivariate_normal(np.zeros(num_data), cov)[:, None] + for _ in range(output_dim) + ] Y = np.hstack(Y) - return X, Y # TODO: improve this test; for most of the likelihoods, Y won't actually be valid + return ( + X, + Y, + ) # TODO: improve this test; for most of the likelihoods, Y won't actually be valid @pytest.mark.parametrize("GPflowLikelihood", TEST_GPFLOW_LIKELIHOODS) @@ -110,13 +118,17 @@ def test_likelihood_loss(GPflowLikelihood): f_var = f_distribution.scale.diag expected_loss = np.mean(-likelihood.variational_expectations(f_mean, f_var, Y)) - np.testing.assert_almost_equal(likelihood_loss(Y, f_distribution), expected_loss, decimal=5) + np.testing.assert_almost_equal( + likelihood_loss(Y, f_distribution), expected_loss, decimal=5 + ) # 2. Run tests with gp_layer output coerced to sample f_sample = tf.convert_to_tensor(gp_layer(X)) expected_loss = np.mean(-likelihood.log_prob(f_sample, Y)) - np.testing.assert_almost_equal(likelihood_loss(Y, f_sample), expected_loss, decimal=5) + np.testing.assert_almost_equal( + likelihood_loss(Y, f_sample), expected_loss, decimal=5 + ) def test_tensor_coercible(): diff --git a/tests/gpflux/layers/test_trackable_layer.py b/tests/gpflux/layers/test_trackable_layer.py index 80174ff6..483134a0 100644 --- a/tests/gpflux/layers/test_trackable_layer.py +++ b/tests/gpflux/layers/test_trackable_layer.py @@ -99,7 +99,9 @@ def test_submodule_variables(): modules, module_variables, ) = setup_layer_modules_variables() - assert to_tensor_set(trackable_layer.variables) == to_tensor_set(variables + module_variables) + assert to_tensor_set(trackable_layer.variables) == to_tensor_set( + variables + module_variables + ) def test_submodule_trainable_variables(): @@ -120,7 +122,9 @@ def test_submodule_non_trainable_variables(): modules, module_variables, ) = setup_layer_modules_variables() - non_trainable_attributes = [v for v in variables + module_variables if not v.trainable] + non_trainable_attributes = [ + v for v in variables + module_variables if not v.trainable + ] assert trackable_layer.non_trainable_variables == non_trainable_attributes @@ -133,7 +137,9 @@ def test_trainable_weights(): ) = setup_layer_modules_variables() all_vars = variables + module_variables trainable_weights = [v for v in all_vars if v.trainable] - assert to_tensor_set(trackable_layer.trainable_weights) == to_tensor_set(trainable_weights) + assert to_tensor_set(trackable_layer.trainable_weights) == to_tensor_set( + trainable_weights + ) def test_non_trainable_weights(): @@ -159,7 +165,9 @@ def test_trainable_variables(): ) = setup_layer_modules_variables() all_vars = variables + module_variables trainable_variables = [v for v in all_vars if v.trainable] - assert to_tensor_set(trackable_layer.trainable_variables) == to_tensor_set(trainable_variables) + assert to_tensor_set(trackable_layer.trainable_variables) == to_tensor_set( + trainable_variables + ) def test_variables(): @@ -174,8 +182,7 @@ def test_variables(): @pytest.mark.parametrize( - "composite_class", - [CompositeModule, UntrackableCompositeLayer], + "composite_class", [CompositeModule, UntrackableCompositeLayer], ) def test_tensorflow_classes_trackable(composite_class): composite_object = composite_class([Matern52()]) diff --git a/tests/gpflux/models/test_bayesian_model.py b/tests/gpflux/models/test_bayesian_model.py index 368f8550..60634ceb 100644 --- a/tests/gpflux/models/test_bayesian_model.py +++ b/tests/gpflux/models/test_bayesian_model.py @@ -22,7 +22,9 @@ from gpflow.likelihoods import Gaussian from gpflux.layers import LatentVariableLayer, LikelihoodLayer -from tests.integration.test_latent_variable_integration import build_gp_layers # noqa: F401 +from tests.integration.test_latent_variable_integration import ( + build_gp_layers, +) # noqa: F401 tf.keras.backend.set_floatx("float64") diff --git a/tests/gpflux/models/test_deep_gp.py b/tests/gpflux/models/test_deep_gp.py index 0ff5bd42..e5723cdf 100644 --- a/tests/gpflux/models/test_deep_gp.py +++ b/tests/gpflux/models/test_deep_gp.py @@ -37,10 +37,14 @@ def build_deep_gp(input_dim, num_data): kernel_list = [RBF(), Matern12()] num_inducing = [25, 25] l1_kernel = construct_basic_kernel(kernels=kernel_list) - l1_inducing = construct_basic_inducing_variables(num_inducing=num_inducing, input_dim=layers[0]) + l1_inducing = construct_basic_inducing_variables( + num_inducing=num_inducing, input_dim=layers[0] + ) # 2. Pass in kernels, specificy output dims (shared hyperparams/variables) - l2_kernel = construct_basic_kernel(kernels=RBF(), output_dim=layers[2], share_hyperparams=True) + l2_kernel = construct_basic_kernel( + kernels=RBF(), output_dim=layers[2], share_hyperparams=True + ) l2_inducing = construct_basic_inducing_variables( num_inducing=25, input_dim=layers[1], share_variables=True ) @@ -61,7 +65,9 @@ def build_deep_gp(input_dim, num_data): return DeepGP(gp_layers, Gaussian(0.1)) -def train_deep_gp(deep_gp, data, maxiter=MAXITER, plotter=None, plotter_interval=PLOTTER_INTERVAL): +def train_deep_gp( + deep_gp, data, maxiter=MAXITER, plotter=None, plotter_interval=PLOTTER_INTERVAL +): optimizer = tf.optimizers.Adam() @tf.function(autograph=False) diff --git a/tests/gpflux/sampling/test_multioutput_sample.py b/tests/gpflux/sampling/test_multioutput_sample.py index 1f979d31..008aa96f 100644 --- a/tests/gpflux/sampling/test_multioutput_sample.py +++ b/tests/gpflux/sampling/test_multioutput_sample.py @@ -20,18 +20,26 @@ import gpflow from gpflow.config import default_float, default_jitter -from gpflux.layers.basis_functions.fourier_features import MultiOutputRandomFourierFeaturesCosine -from gpflux.feature_decomposition_kernels import SharedMultiOutputKernelWithFeatureDecomposition, SeparateMultiOutputKernelWithFeatureDecomposition +from gpflux.layers.basis_functions.fourier_features import ( + MultiOutputRandomFourierFeaturesCosine, +) +from gpflux.feature_decomposition_kernels import ( + SharedMultiOutputKernelWithFeatureDecomposition, + SeparateMultiOutputKernelWithFeatureDecomposition, +) from gpflux.sampling.sample import Sample, efficient_sample + @pytest.fixture(name="base_kernel") def _base_kernel_fixture(): - + return gpflow.kernels.SquaredExponential() + def _get_shared_kernel(base_kernel): - return gpflow.kernels.SharedIndependent(kernel=base_kernel, output_dim = 2) + return gpflow.kernels.SharedIndependent(kernel=base_kernel, output_dim=2) + def _get_separate_kernel(base_kernel): @@ -41,18 +49,24 @@ def _get_separate_kernel(base_kernel): @pytest.fixture(name="shared_inducing_variable") def _shared_inducing_variable_fixture(): Z = np.linspace(-1, 1, 10).reshape(-1, 1) - + ind_var = gpflow.inducing_variables.InducingPoints(Z) - return gpflow.inducing_variables.SharedIndependentInducingVariables(inducing_variable=ind_var) + return gpflow.inducing_variables.SharedIndependentInducingVariables( + inducing_variable=ind_var + ) + @pytest.fixture(name="separate_inducing_variable") def _separate_inducing_variable_fixture(): Z = np.linspace(-1, 1, 10).reshape(-1, 1) - + ind_var = gpflow.inducing_variables.InducingPoints(Z) - return gpflow.inducing_variables.SeparateIndependentInducingVariables(inducing_variable_list=[ind_var, ind_var]) + return gpflow.inducing_variables.SeparateIndependentInducingVariables( + inducing_variable_list=[ind_var, ind_var] + ) + @pytest.fixture(name="whiten", params=[True]) def _whiten_fixture(request): @@ -62,34 +76,39 @@ def _whiten_fixture(request): def _get_shared_qmu_qsqrt(kernel, inducing_variable): """Returns q_mu and q_sqrt for a kernel and inducing_variable""" Z = inducing_variable.inducing_variable.Z.numpy() - Kzz = kernel(Z, full_cov=True, full_output_cov = False).numpy() + Kzz = kernel(Z, full_cov=True, full_output_cov=False).numpy() q_sqrt = np.linalg.cholesky(Kzz) + default_jitter() * np.eye(Z.shape[0])[None, ...] - q_mu = q_sqrt @ np.random.randn(2, Z.shape[0], 1) + q_mu = q_sqrt @ np.random.randn(2, Z.shape[0], 1) + + return np.transpose(q_mu[..., 0]), q_sqrt - return np.transpose(q_mu[...,0]), q_sqrt def _get_separate_qmu_qsqrt(kernel, inducing_variable): """Returns q_mu and q_sqrt for a kernel and inducing_variable""" Z = inducing_variable.inducing_variable_list[0].Z.numpy() - Kzz = kernel(Z, full_cov=True, full_output_cov = False).numpy() + Kzz = kernel(Z, full_cov=True, full_output_cov=False).numpy() q_sqrt = np.linalg.cholesky(Kzz) + default_jitter() * np.eye(Z.shape[0])[None, ...] - q_mu = q_sqrt @ np.random.randn(2, Z.shape[0], 1) + q_mu = q_sqrt @ np.random.randn(2, Z.shape[0], 1) + + return np.transpose(q_mu[..., 0]), q_sqrt - return np.transpose(q_mu[...,0]), q_sqrt def test_shared_wilson_efficient_sample(base_kernel, shared_inducing_variable, whiten): """Smoke and consistency test for efficient sampling using Wilson""" kernel = _get_shared_kernel(base_kernel) - - eigenfunctions = MultiOutputRandomFourierFeaturesCosine(kernel, 100, dtype=default_float()) - eigenvalues = np.ones((2,100, 1), dtype=default_float()) + + eigenfunctions = MultiOutputRandomFourierFeaturesCosine( + kernel, 100, dtype=default_float() + ) + eigenvalues = np.ones((2, 100, 1), dtype=default_float()) # To apply Wilson sampling we require the features and eigenvalues of the kernel - kernel2 = SharedMultiOutputKernelWithFeatureDecomposition(kernel, eigenfunctions, eigenvalues) + kernel2 = SharedMultiOutputKernelWithFeatureDecomposition( + kernel, eigenfunctions, eigenvalues + ) q_mu, q_sqrt = _get_shared_qmu_qsqrt(kernel, shared_inducing_variable) - sample_func = efficient_sample( shared_inducing_variable, kernel2, @@ -102,22 +121,24 @@ def test_shared_wilson_efficient_sample(base_kernel, shared_inducing_variable, w # Check for consistency - i.e. evaluating the sample at the # same locations (X) returns the same value np.testing.assert_array_almost_equal( - sample_func(X), - sample_func(X), + sample_func(X), sample_func(X), ) - - - -def test_separate_wilson_efficient_sample(base_kernel, separate_inducing_variable, whiten): +def test_separate_wilson_efficient_sample( + base_kernel, separate_inducing_variable, whiten +): """Smoke and consistency test for efficient sampling using Wilson""" kernel = _get_separate_kernel(base_kernel) - - eigenfunctions = MultiOutputRandomFourierFeaturesCosine(kernel, 100, dtype=default_float()) - eigenvalues = np.ones((2,100, 1), dtype=default_float()) + + eigenfunctions = MultiOutputRandomFourierFeaturesCosine( + kernel, 100, dtype=default_float() + ) + eigenvalues = np.ones((2, 100, 1), dtype=default_float()) # To apply Wilson sampling we require the features and eigenvalues of the kernel - kernel2 = SeparateMultiOutputKernelWithFeatureDecomposition(kernel, eigenfunctions, eigenvalues) + kernel2 = SeparateMultiOutputKernelWithFeatureDecomposition( + kernel, eigenfunctions, eigenvalues + ) q_mu, q_sqrt = _get_separate_qmu_qsqrt(kernel, separate_inducing_variable) sample_func = efficient_sample( @@ -132,13 +153,10 @@ def test_separate_wilson_efficient_sample(base_kernel, separate_inducing_variabl # Check for consistency - i.e. evaluating the sample at the # same locations (X) returns the same value np.testing.assert_array_almost_equal( - sample_func(X), - sample_func(X), + sample_func(X), sample_func(X), ) - - """ class SampleMock(Sample): def __init__(self, a): @@ -166,4 +184,4 @@ def test_adding_sample_and_mean_function(): sample_and_mean_function = sample + mean_function np.testing.assert_array_almost_equal(sample_and_mean_function(X), sample(X) + mean_function(X)) -""" \ No newline at end of file +""" diff --git a/tests/gpflux/sampling/test_sample.py b/tests/gpflux/sampling/test_sample.py index 70b27588..bafc3e09 100644 --- a/tests/gpflux/sampling/test_sample.py +++ b/tests/gpflux/sampling/test_sample.py @@ -21,7 +21,9 @@ from gpflow.config import default_float, default_jitter from gpflux.layers.basis_functions.fourier_features import RandomFourierFeaturesCosine -from gpflux.sampling.kernel_with_feature_decomposition import KernelWithFeatureDecomposition +from gpflux.sampling.kernel_with_feature_decomposition import ( + KernelWithFeatureDecomposition, +) from gpflux.sampling.sample import Sample, efficient_sample @@ -95,8 +97,7 @@ def test_wilson_efficient_sample(kernel, inducing_variable, whiten): # Check for consistency - i.e. evaluating the sample at the # same locations (X) returns the same value np.testing.assert_array_almost_equal( - sample_func(X), - sample_func(X), + sample_func(X), sample_func(X), ) @@ -125,4 +126,6 @@ def test_adding_sample_and_mean_function(): sample_and_mean_function = sample + mean_function - np.testing.assert_array_almost_equal(sample_and_mean_function(X), sample(X) + mean_function(X)) + np.testing.assert_array_almost_equal( + sample_and_mean_function(X), sample(X) + mean_function(X) + ) diff --git a/tests/gpflux/test_callbacks.py b/tests/gpflux/test_callbacks.py index 2d2998f2..7dc9eaaa 100644 --- a/tests/gpflux/test_callbacks.py +++ b/tests/gpflux/test_callbacks.py @@ -90,11 +90,7 @@ def test_tensorboard_callback(tmp_path, model_and_loss, data, update_freq): model.compile(optimizer=optimizer, loss=loss) callbacks = [ tf.keras.callbacks.ReduceLROnPlateau( - monitor="loss", - patience=1, - factor=0.95, - verbose=1, - min_lr=1e-6, + monitor="loss", patience=1, factor=0.95, verbose=1, min_lr=1e-6, ), # To write the LR to TensorBoard the `TensorBoard` callback needs to be # instantiated after the `ReduceLROnPlateau` callback. @@ -102,7 +98,9 @@ def test_tensorboard_callback(tmp_path, model_and_loss, data, update_freq): ] history = model.fit(dataset, epochs=CONFIG.num_epochs, callbacks=callbacks) - tb_files_pattern = f"{tmp_path}/train/events.out.tfevents*" # notice the glob pattern + tb_files_pattern = ( + f"{tmp_path}/train/events.out.tfevents*" # notice the glob pattern + ) # Maps tensorboard tags (e.g. kernel.variance) to list containing # their successive values during optimisation. @@ -152,7 +150,9 @@ def test_tensorboard_callback(tmp_path, model_and_loss, data, update_freq): assert len(record) == CONFIG.num_epochs # Check that recorded TensorBoard loss matches Keras history - np.testing.assert_array_almost_equal(records["epoch_loss"], history.history["loss"], decimal=5) + np.testing.assert_array_almost_equal( + records["epoch_loss"], history.history["loss"], decimal=5 + ) # Check correctness of fixed likelihood variance tag = ("layers[3].likelihood.variance",) diff --git a/tests/gpflux/test_ci_utils.py b/tests/gpflux/test_ci_utils.py index 5c97c78e..f3cb66a9 100644 --- a/tests/gpflux/test_ci_utils.py +++ b/tests/gpflux/test_ci_utils.py @@ -33,11 +33,7 @@ def test_is_continuous_integration(os_environ, is_ci): @pytest.mark.parametrize( "is_ci, args, expected_result", - [ - (True, (13,), 2), - (True, (13, 5), 5), - (False, (13,), 13), - ], + [(True, (13,), 2), (True, (13, 5), 5), (False, (13,), 13),], ) def test_notebook_niter(is_ci, args, expected_result): with mock_ci_state(is_ci): diff --git a/tests/gpflux/test_helpers.py b/tests/gpflux/test_helpers.py index 04517deb..a503f0b0 100644 --- a/tests/gpflux/test_helpers.py +++ b/tests/gpflux/test_helpers.py @@ -131,7 +131,11 @@ def test_construct_inducing_shared_independent_duplicates(z_init): z_init = None moiv = construct_basic_inducing_variables( - num_inducing, input_dim, output_dim=output_dim, share_variables=True, z_init=z_init + num_inducing, + input_dim, + output_dim=output_dim, + share_variables=True, + z_init=z_init, ) assert isinstance(moiv, SharedIndependentInducingVariables) @@ -165,7 +169,9 @@ def test_construct_gp_layer(): # kernel assert isinstance(layer.kernel, SharedIndependent) assert isinstance(layer.kernel.kernel, SquaredExponential) - assert len(layer.kernel.kernel.lengthscales.numpy()) == input_dim, "expected ARD kernel" + assert ( + len(layer.kernel.kernel.lengthscales.numpy()) == input_dim + ), "expected ARD kernel" # inducing variable assert isinstance(layer.inducing_variable, SharedIndependentInducingVariables) @@ -194,7 +200,9 @@ class PopulatedClass: overwritten = "overwritten" assert PopulatedClass.bar != overwritten - result = make_dataclass_from_class(BlankDataclass, PopulatedClass(), bar=overwritten) + result = make_dataclass_from_class( + BlankDataclass, PopulatedClass(), bar=overwritten + ) assert isinstance(result, BlankDataclass) assert result.foo == PopulatedClass.foo assert result.bar == overwritten diff --git a/tests/gpflux/test_math.py b/tests/gpflux/test_math.py index a5f7166f..5e69892a 100644 --- a/tests/gpflux/test_math.py +++ b/tests/gpflux/test_math.py @@ -32,7 +32,5 @@ def test_compute_A_inv_x(): A = _get_psd_matrix(N) b = np.random.randn(N, 2) / 100 np.testing.assert_array_almost_equal( - np.linalg.inv(A) @ b, - compute_A_inv_b(A, b).numpy(), - decimal=3, + np.linalg.inv(A) @ b, compute_A_inv_b(A, b).numpy(), decimal=3, ) diff --git a/tests/gpflux/test_runtime_checks.py b/tests/gpflux/test_runtime_checks.py index 6c28d12f..a1bc8e0a 100644 --- a/tests/gpflux/test_runtime_checks.py +++ b/tests/gpflux/test_runtime_checks.py @@ -31,8 +31,12 @@ def make_kernels(num_latent_k): return [ construct_basic_kernel([Matern52() for _ in range(num_latent_k)]), - construct_basic_kernel(Matern52(), output_dim=num_latent_k, share_hyperparams=False), - construct_basic_kernel(Matern52(), output_dim=num_latent_k, share_hyperparams=True), + construct_basic_kernel( + Matern52(), output_dim=num_latent_k, share_hyperparams=False + ), + construct_basic_kernel( + Matern52(), output_dim=num_latent_k, share_hyperparams=True + ), ] diff --git a/tests/integration/test_compilation.py b/tests/integration/test_compilation.py index 04abf9f2..844eca43 100644 --- a/tests/integration/test_compilation.py +++ b/tests/integration/test_compilation.py @@ -153,7 +153,9 @@ def test_model_compilation(deep_gp_model_builder): if loss is None: # build_gpflux_deep_gp test_batch_dict = next(iter(train_dataset)) - test_batch_dict["targets"] = np.full_like(test_batch_dict["targets"].shape, np.nan) + test_batch_dict["targets"] = np.full_like( + test_batch_dict["targets"].shape, np.nan + ) output = deep_gp_model(test_batch_dict) mean, var = output.f_mean, output.f_var else: @@ -209,7 +211,9 @@ def objective(data_minibatch): objective = tf.function(objective) def optimization_step(data_minibatch): - optimizer.minimize(lambda: objective(data_minibatch), deep_gp_model.trainable_weights) + optimizer.minimize( + lambda: objective(data_minibatch), deep_gp_model.trainable_weights + ) if use_tf_function: optimization_step = tf.function(optimization_step) @@ -225,7 +229,9 @@ def optimization_step(data_minibatch): # Check outputs if loss is None: # build_gpflux_deep_gp test_batch_dict = next(iter(train_dataset)) - test_batch_dict["targets"] = np.full_like(test_batch_dict["targets"].shape, np.nan) + test_batch_dict["targets"] = np.full_like( + test_batch_dict["targets"].shape, np.nan + ) output = deep_gp_model(test_batch_dict) mean, var = output.f_mean, output.f_var else: diff --git a/tests/integration/test_svgp_equivalence.py b/tests/integration/test_svgp_equivalence.py index c58ee05b..f92d1618 100644 --- a/tests/integration/test_svgp_equivalence.py +++ b/tests/integration/test_svgp_equivalence.py @@ -37,7 +37,9 @@ class LogPrior_ELBO_SVGP(gpflow.models.SVGP): """ def elbo(self, data: RegressionData) -> tf.Tensor: - loss_prior = tf.add_n([p.log_prior_density() for p in self.trainable_parameters]) + loss_prior = tf.add_n( + [p.log_prior_density() for p in self.trainable_parameters] + ) return super().elbo(data) + loss_prior @@ -78,8 +80,12 @@ def create_gpflow_svgp(kernel, likelihood, inducing_variable): def create_gp_layer(kernel, inducing_variable, num_data): mok = gpflow.kernels.SharedIndependent(kernel, output_dim=1) - moiv = gpflow.inducing_variables.SharedIndependentInducingVariables(inducing_variable) - return gpflux.layers.GPLayer(mok, moiv, num_data, mean_function=gpflow.mean_functions.Zero()) + moiv = gpflow.inducing_variables.SharedIndependentInducingVariables( + inducing_variable + ) + return gpflux.layers.GPLayer( + mok, moiv, num_data, mean_function=gpflow.mean_functions.Zero() + ) def create_gpflux_sldgp(kernel, likelihood, inducing_variable, num_data): @@ -93,7 +99,9 @@ def create_gpflux_sequential_and_loss(kernel, likelihood, inducing_variable, num gp_layer = create_gp_layer(kernel, inducing_variable, num_data) loss = gpflux.losses.LikelihoodLoss(likelihood) likelihood_container = gpflux.layers.TrackableLayer() - likelihood_container.likelihood = likelihood # for likelihood to be discovered as trainable + likelihood_container.likelihood = ( + likelihood # for likelihood to be discovered as trainable + ) model = tf.keras.Sequential([gp_layer, likelihood_container]) return model, loss @@ -115,7 +123,9 @@ def training_loss(): return -model.elbo(data) opt = gpflow.optimizers.Scipy() - opt.minimize(training_loss, model.trainable_variables, options=dict(maxiter=maxiter)) + opt.minimize( + training_loss, model.trainable_variables, options=dict(maxiter=maxiter) + ) def assert_equivalence(svgp, sldgp, data, **tol_kws): @@ -134,7 +144,10 @@ def test_svgp_equivalence_after_assign(): def fit_adam( - model: Union[gpflow.models.SVGP, gpflux.models.DeepGP], data, maxiter, adam_learning_rate=0.01 + model: Union[gpflow.models.SVGP, gpflux.models.DeepGP], + data, + maxiter, + adam_learning_rate=0.01, ): X, Y = data num_data = len(X) @@ -186,20 +199,13 @@ def _keras_fit_natgrad( natgrad = gpflow.optimizers.NaturalGradient(gamma=gamma) adam = tf.optimizers.Adam(adam_learning_rate) model.compile( - optimizer=[natgrad, adam], - loss=loss, - run_eagerly=run_eagerly, + optimizer=[natgrad, adam], loss=loss, run_eagerly=run_eagerly, ) model.fit(dataset, epochs=maxiter) def keras_fit_natgrad( - sldgp, - data, - maxiter, - adam_learning_rate=0.01, - gamma=1.0, - run_eagerly=None, + sldgp, data, maxiter, adam_learning_rate=0.01, gamma=1.0, run_eagerly=None, ): base_model = sldgp.as_training_model() dataset = make_dataset(data) @@ -255,7 +261,9 @@ def optimization_step(): variational_grads, other_grads = tape.gradient( loss, (variational_params_vars, hyperparam_variables) ) - for (q_mu_grad, q_sqrt_grad), (q_mu, q_sqrt) in zip(variational_grads, variational_params): + for (q_mu_grad, q_sqrt_grad), (q_mu, q_sqrt) in zip( + variational_grads, variational_params + ): natgrad._natgrad_apply_gradients(q_mu_grad, q_sqrt_grad, q_mu, q_sqrt) adam.apply_gradients(zip(other_grads, hyperparam_variables)) @@ -291,7 +299,9 @@ def test_svgp_equivalence_with_sldgp(svgp_fitter, sldgp_fitter, maxiter=20): (fit_natgrad, _keras_fit_natgrad, dict(atol=1e-8)), ], ) -def test_svgp_equivalence_with_keras_sequential(svgp_fitter, keras_fitter, tol_kw, maxiter=10): +def test_svgp_equivalence_with_keras_sequential( + svgp_fitter, keras_fitter, tol_kw, maxiter=10 +): X, Y = data = load_data() svgp = create_gpflow_svgp(*make_kernel_likelihood_iv()) @@ -303,7 +313,9 @@ def test_svgp_equivalence_with_keras_sequential(svgp_fitter, keras_fitter, tol_k keras_fitter(keras_model, make_dataset(data, as_dict=False), maxiter, loss=loss) f_dist = keras_model(X) - np.testing.assert_allclose((f_dist.loc, f_dist.scale.diag ** 2), svgp.predict_f(X), **tol_kw) + np.testing.assert_allclose( + (f_dist.loc, f_dist.scale.diag ** 2), svgp.predict_f(X), **tol_kw + ) def run_gpflux_sldgp(data, optimizer, maxiter): @@ -343,8 +355,7 @@ def run_gpflow_svgp(data, optimizer, maxiter): @pytest.mark.parametrize( - "optimizer", - ["natgrad", "adam", "scipy", "keras_adam", "keras_natgrad"], + "optimizer", ["natgrad", "adam", "scipy", "keras_adam", "keras_natgrad"], ) def test_run_gpflux_sldgp(optimizer): data = load_data() diff --git a/tests/test_notebooks.py b/tests/test_notebooks.py index a3acab13..bfee5f68 100644 --- a/tests/test_notebooks.py +++ b/tests/test_notebooks.py @@ -62,7 +62,9 @@ def notebook_blacklisted(nb): def _preproc(): pythonkernel = "python" + str(sys.version_info[0]) - return ExecutePreprocessor(timeout=300, kernel_name=pythonkernel, interrupt_on_timeout=True) + return ExecutePreprocessor( + timeout=300, kernel_name=pythonkernel, interrupt_on_timeout=True + ) def _exec_notebook(notebook_filename): @@ -84,4 +86,6 @@ def test_notebook(notebook_file): def test_has_notebooks(): - assert len(get_notebooks()) >= 2, "there are probably some notebooks that were not discovered" + assert ( + len(get_notebooks()) >= 2 + ), "there are probably some notebooks that were not discovered" From 49ec51e441b4c7db1a60e38e1a220cdbe819569a Mon Sep 17 00:00:00 2001 From: SebastianPopescu Date: Wed, 14 Sep 2022 13:47:33 +0100 Subject: [PATCH 04/25] support for multioutput orthogonal random features --- .../multioutput/random/__init__.py | 4 + .../multioutput/random/orthogonal.py | 27 ++- .../test_multioutput_orthogonal_ff.py | 193 ++++++++++++++++++ 3 files changed, 215 insertions(+), 9 deletions(-) create mode 100644 tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_orthogonal_ff.py diff --git a/gpflux/layers/basis_functions/fourier_features/multioutput/random/__init__.py b/gpflux/layers/basis_functions/fourier_features/multioutput/random/__init__.py index e96f8f35..5001d3f4 100644 --- a/gpflux/layers/basis_functions/fourier_features/multioutput/random/__init__.py +++ b/gpflux/layers/basis_functions/fourier_features/multioutput/random/__init__.py @@ -19,8 +19,12 @@ MultiOutputRandomFourierFeatures, MultiOutputRandomFourierFeaturesCosine, ) +from gpflux.layers.basis_functions.fourier_features.multioutput.random.orthogonal import ( + MultiOutputOrthogonalRandomFeatures +) __all__ = [ "MultiOutputRandomFourierFeatures", "MultiOutputRandomFourierFeaturesCosine", + "MultiOutputOrthogonalRandomFeatures" ] diff --git a/gpflux/layers/basis_functions/fourier_features/multioutput/random/orthogonal.py b/gpflux/layers/basis_functions/fourier_features/multioutput/random/orthogonal.py index 92c5857b..13ab6604 100644 --- a/gpflux/layers/basis_functions/fourier_features/multioutput/random/orthogonal.py +++ b/gpflux/layers/basis_functions/fourier_features/multioutput/random/orthogonal.py @@ -22,8 +22,8 @@ import gpflow from gpflow.base import DType, TensorType -from gpflux.layers.basis_functions.fourier_features.random.base import ( - RandomFourierFeatures, +from gpflux.layers.basis_functions.fourier_features.multioutput.random.base import ( + MultiOutputRandomFourierFeatures, ) from gpflux.types import ShapeType @@ -39,7 +39,6 @@ gpflow.kernels.SquaredExponential, ) - def _sample_chi_squared(nu: float, shape: ShapeType, dtype: DType) -> TensorType: """ Draw samples from Chi-squared distribution with `nu` degrees of freedom. @@ -65,9 +64,7 @@ def _ceil_divide(a: float, b: float) -> int: return -np.floor_divide(-a, b) -# TODO -- this class has to be updated -# NOTE -- I am not sure if the shapes are fine here, check the actual paper -class OrthogonalRandomFeatures(RandomFourierFeatures): +class MultiOutputOrthogonalRandomFeatures(MultiOutputRandomFourierFeatures): r""" Orthogonal random Fourier features (ORF) :cite:p:`yu2016orthogonal` for more efficient and accurate kernel approximations than :class:`RandomFourierFeatures`. @@ -76,8 +73,20 @@ class OrthogonalRandomFeatures(RandomFourierFeatures): def __init__( self, kernel: gpflow.kernels.Kernel, n_components: int, **kwargs: Mapping ): - assert isinstance(kernel, ORF_SUPPORTED_KERNELS), "Unsupported Kernel" - super(OrthogonalRandomFeatures, self).__init__(kernel, n_components, **kwargs) + + + + if isinstance(kernel, gpflow.kernels.SeparateIndependent): + for ker in kernel.kernels: + assert isinstance(ker, ORF_SUPPORTED_KERNELS), "Unsupported Kernel" + elif isinstance(kernel, gpflow.kernels.SharedIndependent): + assert isinstance( + kernel.kernel, ORF_SUPPORTED_KERNELS + ), "Unsupported Kernel" + else: + raise ValueError("kernel specified is not supported.") + + super(MultiOutputOrthogonalRandomFeatures, self).__init__(kernel, n_components, **kwargs) def _weights_init( self, shape: TensorType, dtype: Optional[DType] = None @@ -98,4 +107,4 @@ def _weights_init( ) # equiv: S @ Q where S = diag(s); shape [P, K, D, D] V = tf.reshape(U, shape=(n_out, -1, input_dim)) # shape [P, K*D, D] - return V[: self.n_components] # shape [M, D] (throw away K*D - M rows) + return V[:, : self.n_components, :] # shape [P, M, D] (throw away K*D - M rows) diff --git a/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_orthogonal_ff.py b/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_orthogonal_ff.py new file mode 100644 index 00000000..dd5ec30c --- /dev/null +++ b/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_orthogonal_ff.py @@ -0,0 +1,193 @@ +# +# Copyright (c) 2021 The GPflux Contributors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import numpy as np +import pytest +import tensorflow as tf +from tensorflow.python.keras.testing_utils import layer_test +from tensorflow.python.keras.utils.kernelized_utils import inner_product + +import gpflow + +from gpflow.kernels import SharedIndependent, SeparateIndependent +from gpflux import feature_decomposition_kernels +from gpflux.layers.basis_functions.fourier_features import ( + MultiOutputRandomFourierFeatures, + MultiOutputRandomFourierFeaturesCosine, +) +from gpflux.layers.basis_functions.fourier_features.random.orthogonal import ( + ORF_SUPPORTED_KERNELS, +) +from gpflux.layers.basis_functions.fourier_features.multioutput.random import ( + MultiOutputRandomFourierFeatures, + MultiOutputOrthogonalRandomFeatures +) + +from gpflux.feature_decomposition_kernels.multioutput import ( + SharedMultiOutputKernelWithFeatureDecomposition, + SeparateMultiOutputKernelWithFeatureDecomposition, +) +from tests.conftest import skip_serialization_tests + + +@pytest.fixture(name="n_dims", params=[1, 2, 3, 5, 10, 20]) +def _n_dims_fixture(request): + return request.param + + +@pytest.fixture(name="variance", params=[0.5, 1.0, 2.0]) +def _variance_fixture(request): + return request.param + + +@pytest.fixture(name="lengthscale", params=[0.1, 1.0, 5.0]) +def _lengthscale_fixture(request): + return request.param + + +@pytest.fixture(name="batch_size", params=[1, 10]) +def _batch_size_fixture(request): + return request.param + + +@pytest.fixture(name="n_components", params=[1, 2, 4, 20, 100]) +def _n_features_fixture(request): + return request.param + +@pytest.fixture(name="base_kernel_cls", params=list(ORF_SUPPORTED_KERNELS)) +def _base_kernel_cls_fixture(request): + return request.param + +def test_orthogonal_fourier_features_can_approximate_multi_output_separate_kernel_multidim( + base_kernel_cls, variance, lengthscale, n_dims +): + n_components = 40000 + + x_rows = 20 + y_rows = 30 + # ARD + lengthscales = np.random.rand((n_dims)) * lengthscale + + print("size of sampled lengthscales") + print(lengthscales.shape) + + base_kernel = base_kernel_cls(variance=variance, lengthscales=lengthscales) + + kernel = SeparateIndependent(kernels=[base_kernel, base_kernel]) + + x = tf.random.uniform((x_rows, n_dims), dtype=tf.float64) + y = tf.random.uniform((y_rows, n_dims), dtype=tf.float64) + + actual_kernel_matrix = kernel.K(x, y, full_output_cov=False).numpy() + + #fourier_features = random_basis_func_cls(kernel, n_components, dtype=tf.float64) + fourier_features = MultiOutputOrthogonalRandomFeatures(kernel, n_components, dtype=tf.float64) + + feature_coefficients = np.ones((2, 2 * n_components, 1), dtype=np.float64) + + kernel = SeparateMultiOutputKernelWithFeatureDecomposition( + kernel=None, + feature_functions=fourier_features, + feature_coefficients=feature_coefficients, + output_dim=2, + ) + + approx_kernel_matrix = kernel(x, y).numpy() + + np.testing.assert_allclose(approx_kernel_matrix, actual_kernel_matrix, atol=5e-2) + + +def test_orthogonal_fourier_features_can_approximate_multi_output_shared_kernel_multidim( + base_kernel_cls, variance, lengthscale, n_dims +): + n_components = 40000 + + x_rows = 20 + y_rows = 30 + # ARD + lengthscales = np.random.rand((n_dims)) * lengthscale + + print("size of sampled lengthscales") + print(lengthscales.shape) + + base_kernel = base_kernel_cls(variance=variance, lengthscales=lengthscales) + + kernel = SharedIndependent(kernel=base_kernel, output_dim=2) + + x = tf.random.uniform((x_rows, n_dims), dtype=tf.float64) + y = tf.random.uniform((y_rows, n_dims), dtype=tf.float64) + + actual_kernel_matrix = kernel.K(x, y, full_output_cov=False).numpy() + + #fourier_features = random_basis_func_cls(kernel, n_components, dtype=tf.float64) + fourier_features = MultiOutputOrthogonalRandomFeatures(kernel, n_components, dtype=tf.float64) + + feature_coefficients = np.ones((2, 2 * n_components, 1), dtype=np.float64) + + kernel = SharedMultiOutputKernelWithFeatureDecomposition( + kernel=None, + feature_functions=fourier_features, + feature_coefficients=feature_coefficients, + output_dim=2, + ) + + approx_kernel_matrix = kernel(x, y).numpy() + + np.testing.assert_allclose(approx_kernel_matrix, actual_kernel_matrix, atol=5e-2) + + + + + +""" +#TODO -- have a look at what layer_test actually does +@skip_serialization_tests +def test_keras_testing_util_layer_test_1D(kernel_cls, batch_size, n_components): + kernel = kernel_cls() + + tf.keras.utils.get_custom_objects()["RandomFourierFeatures"] = RandomFourierFeatures + layer_test( + RandomFourierFeatures, + kwargs={ + "kernel": kernel, + "n_components": n_components, + "input_dim": 1, + "dtype": "float64", + "dynamic": True, + }, + input_shape=(batch_size, 1), + input_dtype="float64", + ) + + +@skip_serialization_tests +def test_keras_testing_util_layer_test_multidim(kernel_cls, batch_size, n_dims, n_components): + kernel = kernel_cls() + + tf.keras.utils.get_custom_objects()["RandomFourierFeatures"] = RandomFourierFeatures + layer_test( + RandomFourierFeatures, + kwargs={ + "kernel": kernel, + "n_components": n_components, + "input_dim": n_dims, + "dtype": "float64", + "dynamic": True, + }, + input_shape=(batch_size, n_dims), + input_dtype="float64", + ) + +""" From 4a541b67e5ef47cbfff46c905ea8a9e24247dd1c Mon Sep 17 00:00:00 2001 From: SebastianPopescu Date: Wed, 14 Sep 2022 14:14:58 +0100 Subject: [PATCH 05/25] formating done properly --- docs/notebooks/deep_gp_samples.py | 24 ++--- .../notebooks/efficient_posterior_sampling.py | 96 +++++-------------- docs/notebooks/efficient_sampling.py | 14 +-- docs/notebooks/gpflux_features.py | 19 +--- docs/notebooks/gpflux_with_keras_layers.py | 5 +- docs/notebooks/keras_integration.py | 18 +--- .../multi_output_efficient_sampling.py | 12 +-- ...multi_output_weight_space_approximation.py | 65 ++++--------- docs/notebooks/weight_space_approximation.py | 60 ++++-------- .../constant_input_dim_deep_gp.py | 10 +- gpflux/callbacks.py | 4 +- gpflux/encoders/__init__.py | 4 +- .../directly_parameterized_encoder.py | 14 +-- gpflux/experiment_support/plotting.py | 5 +- gpflux/experiment_support/tensorboard.py | 4 +- .../kernel_with_feature_decomposition.py | 12 +-- .../kernel_with_feature_decomposition.py | 46 +++------ gpflux/helpers.py | 26 ++--- .../fourier_features/__init__.py | 4 +- .../basis_functions/fourier_features/base.py | 4 +- .../fourier_features/multioutput/base.py | 10 +- .../multioutput/random/__init__.py | 4 +- .../multioutput/random/base.py | 29 ++---- .../multioutput/random/orthogonal.py | 25 ++--- .../fourier_features/quadrature/gaussian.py | 12 +-- .../fourier_features/random/base.py | 12 +-- .../fourier_features/random/orthogonal.py | 24 ++--- gpflux/layers/bayesian_dense_layer.py | 21 +--- gpflux/layers/gp_layer.py | 32 ++----- gpflux/layers/latent_variable_layer.py | 17 +--- gpflux/losses.py | 4 +- gpflux/math.py | 4 +- gpflux/models/deep_gp.py | 22 +---- gpflux/optimization/keras_natgrad.py | 24 ++--- gpflux/runtime_checks.py | 4 +- gpflux/sampling/multioutput/sample.py | 29 ++---- gpflux/sampling/sample.py | 23 +---- gpflux/sampling/utils.py | 4 +- tests/conftest.py | 4 +- .../test_multioutput_orthogonal_ff.py | 15 ++- .../fourier_features/test_multioutput_rff.py | 8 +- .../test_multioutput_rff_cosine.py | 8 +- .../fourier_features/test_quadrature.py | 28 ++---- .../fourier_features/test_random.py | 25 ++--- .../layers/test_bayesian_dense_layer.py | 13 +-- .../layers/test_dedup_trackable_layer.py | 28 ++---- tests/gpflux/layers/test_gp_layer.py | 21 +--- .../layers/test_latent_variable_layer.py | 28 ++---- tests/gpflux/layers/test_likelihood_layer.py | 17 +--- tests/gpflux/layers/test_trackable_layer.py | 70 +++----------- tests/gpflux/models/test_bayesian_model.py | 4 +- tests/gpflux/models/test_deep_gp.py | 18 +--- .../sampling/test_multioutput_sample.py | 28 ++---- tests/gpflux/sampling/test_sample.py | 8 +- tests/gpflux/test_callbacks.py | 8 +- tests/gpflux/test_ci_utils.py | 3 +- tests/gpflux/test_helpers.py | 14 +-- tests/gpflux/test_runtime_checks.py | 11 +-- tests/integration/test_compilation.py | 12 +-- tests/integration/test_svgp_equivalence.py | 50 +++------- tests/test_notebooks.py | 8 +- 61 files changed, 287 insertions(+), 888 deletions(-) diff --git a/docs/notebooks/deep_gp_samples.py b/docs/notebooks/deep_gp_samples.py index d7ca4af5..7a49790a 100644 --- a/docs/notebooks/deep_gp_samples.py +++ b/docs/notebooks/deep_gp_samples.py @@ -53,35 +53,23 @@ M = Z.shape[0] # Layer 1 -inducing_var1 = construct_basic_inducing_variables( - M, D, D, share_variables=True, z_init=Z.copy() -) +inducing_var1 = construct_basic_inducing_variables(M, D, D, share_variables=True, z_init=Z.copy()) kernel1 = construct_basic_kernel( - gpflow.kernels.SquaredExponential(lengthscales=0.15), - output_dim=D, - share_hyperparams=True, -) -layer1 = GPLayer( - kernel1, inducing_var1, num_data, full_cov=True, num_samples=num_samples + gpflow.kernels.SquaredExponential(lengthscales=0.15), output_dim=D, share_hyperparams=True, ) +layer1 = GPLayer(kernel1, inducing_var1, num_data, full_cov=True, num_samples=num_samples) # Layer 2 -inducing_var2 = construct_basic_inducing_variables( - M, D, D, share_variables=True, z_init=Z.copy() -) +inducing_var2 = construct_basic_inducing_variables(M, D, D, share_variables=True, z_init=Z.copy()) kernel2 = construct_basic_kernel( gpflow.kernels.SquaredExponential(lengthscales=0.8, variance=0.1), output_dim=D, share_hyperparams=True, ) -layer2 = GPLayer( - kernel2, inducing_var2, num_data, full_cov=True, num_samples=num_samples -) +layer2 = GPLayer(kernel2, inducing_var2, num_data, full_cov=True, num_samples=num_samples) # Layer 3 -inducing_var3 = construct_basic_inducing_variables( - M, D, D, share_variables=True, z_init=Z.copy() -) +inducing_var3 = construct_basic_inducing_variables(M, D, D, share_variables=True, z_init=Z.copy()) kernel3 = construct_basic_kernel( gpflow.kernels.SquaredExponential(lengthscales=0.3, variance=0.1), output_dim=D, diff --git a/docs/notebooks/efficient_posterior_sampling.py b/docs/notebooks/efficient_posterior_sampling.py index aba88341..eaa4a373 100644 --- a/docs/notebooks/efficient_posterior_sampling.py +++ b/docs/notebooks/efficient_posterior_sampling.py @@ -80,9 +80,7 @@ from gpflow.models import GPR from gpflux.layers.basis_functions.fourier_features import RandomFourierFeaturesCosine -from gpflux.sampling.kernel_with_feature_decomposition import ( - KernelWithFeatureDecomposition, -) +from gpflux.sampling.kernel_with_feature_decomposition import KernelWithFeatureDecomposition # %% [markdown] """ @@ -105,9 +103,7 @@ 8, 10, ] # num_train_samples = 2 ** train_sample_exponents -num_train_samples = [ - 2 ** train_sample_exponent for train_sample_exponent in train_sample_exponents -] +num_train_samples = [2 ** train_sample_exponent for train_sample_exponent in train_sample_exponents] num_features = [ 1024, 4096, @@ -150,9 +146,7 @@ def compute_analytic_GP_predictions(X, y, kernel, noise_variance, X_star): """ # %% -def compute_hybrid_rule_predictions( - X, y, exact_kernel, approximate_kernel, noise_variance, X_star -): +def compute_hybrid_rule_predictions(X, y, exact_kernel, approximate_kernel, noise_variance, X_star): """ Identify the mean and covariance using the hybrid Matheron approximation of the exact posterior. @@ -176,9 +170,7 @@ def compute_hybrid_rule_predictions( assert kXstarX.shape == (X_star.shape[0], X.shape[0]) KXX = exact_kernel.K(X) - kXX_plus_noise_var = tf.linalg.set_diag( - KXX, tf.linalg.diag_part(KXX) + noise_variance - ) + kXX_plus_noise_var = tf.linalg.set_diag(KXX, tf.linalg.diag_part(KXX) + noise_variance) assert kXX_plus_noise_var.shape == (X.shape[0], X.shape[0]) kXX_inv_mul_phi = tf.linalg.solve(kXX_plus_noise_var, phi) @@ -228,12 +220,9 @@ def log10_Wasserstein_distance( square_root_covariance = tf.linalg.sqrtm( covariance + tf.eye(tf.shape(covariance)[0], dtype=covariance.dtype) * jitter ) - matrix_product = ( - square_root_covariance @ approximate_covariance @ square_root_covariance - ) + matrix_product = square_root_covariance @ approximate_covariance @ square_root_covariance square_root_matrix_product = tf.linalg.sqrtm( - matrix_product - + tf.eye(tf.shape(matrix_product)[0], dtype=matrix_product.dtype) * jitter + matrix_product + tf.eye(tf.shape(matrix_product)[0], dtype=matrix_product.dtype) * jitter ) term = covariance + approximate_covariance - 2 * square_root_matrix_product trace = tf.linalg.trace(term) @@ -277,24 +266,18 @@ def conduct_experiment(num_input_dimensions, num_train_samples, num_features): ) feature_coefficients = np.ones((num_features, 1), dtype=default_float()) approximate_kernel = KernelWithFeatureDecomposition( - kernel=None, - feature_functions=feature_functions, - feature_coefficients=feature_coefficients, + kernel=None, feature_functions=feature_functions, feature_coefficients=feature_coefficients, ) # create training data set and test points for evaluation X = [] for i in range(num_input_dimensions): - random_samples = np.random.uniform( - low=0.15, high=0.85, size=(num_train_samples,) - ) + random_samples = np.random.uniform(low=0.15, high=0.85, size=(num_train_samples,)) X.append(random_samples) X = np.array(X).transpose() kXX = exact_kernel.K(X) - kXX_plus_noise_var = tf.linalg.set_diag( - kXX, tf.linalg.diag_part(kXX) + noise_variance - ) + kXX_plus_noise_var = tf.linalg.set_diag(kXX, tf.linalg.diag_part(kXX) + noise_variance) lXX = tf.linalg.cholesky(kXX_plus_noise_var) y = tf.matmul(lXX, tf.random.normal([num_train_samples, 1], dtype=X.dtype)) @@ -304,9 +287,9 @@ def conduct_experiment(num_input_dimensions, num_train_samples, num_features): for i in range(num_input_dimensions): random_samples = np.random.uniform(low=0.0, high=0.3, size=(num_test_samples,)) indices = np.random.uniform(size=(num_test_samples,)) < 0.5 - random_samples[indices] = np.random.uniform( - low=0.7, high=1.0, size=(num_test_samples,) - )[indices] + random_samples[indices] = np.random.uniform(low=0.7, high=1.0, size=(num_test_samples,))[ + indices + ] X_star.append(random_samples) X_star = np.array(X_star).transpose() @@ -317,11 +300,7 @@ def conduct_experiment(num_input_dimensions, num_train_samples, num_features): # identify mean and covariance of the analytic GPR posterior when using the weight space approximated kernel f_mean_weight, f_var_weight = compute_analytic_GP_predictions( - X=X, - y=y, - kernel=approximate_kernel, - noise_variance=noise_variance, - X_star=X_star, + X=X, y=y, kernel=approximate_kernel, noise_variance=noise_variance, X_star=X_star, ) # identify mean and covariance using the hybrid approximation @@ -354,9 +333,7 @@ def conduct_experiment(num_input_dimensions, num_train_samples, num_features): """ # %% -def conduct_experiment_for_multiple_runs( - num_input_dimensions, num_train_samples, num_features -): +def conduct_experiment_for_multiple_runs(num_input_dimensions, num_train_samples, num_features): """ Conduct the experiment as specified above `num_experiment_runs` times and identify the quartiles for the log10 Wassertein distance between the weight space approximated GP and the exact GP, @@ -381,12 +358,8 @@ def conduct_experiment_for_multiple_runs( list_of_log10_ws_dist_weight.append(log10_ws_dist_weight) list_of_log10_ws_dist_hybrid.append(log10_ws_dist_hybrid) - log10_ws_dist_weight_quarts = np.quantile( - list_of_log10_ws_dist_weight, q=(0.25, 0.5, 0.75) - ) - log10_ws_dist_hybrid_quarts = np.quantile( - list_of_log10_ws_dist_hybrid, q=(0.25, 0.5, 0.75) - ) + log10_ws_dist_weight_quarts = np.quantile(list_of_log10_ws_dist_weight, q=(0.25, 0.5, 0.75)) + log10_ws_dist_hybrid_quarts = np.quantile(list_of_log10_ws_dist_hybrid, q=(0.25, 0.5, 0.75)) return log10_ws_dist_weight_quarts, log10_ws_dist_hybrid_quarts @@ -396,9 +369,7 @@ def conduct_experiment_for_multiple_runs( """ # %% -def conduct_experiment_for_different_train_data_sizes( - num_input_dimensions, num_features -): +def conduct_experiment_for_different_train_data_sizes(num_input_dimensions, num_features): """ Conduct the experiment as specified above for different training dataset sizes and store the results in lists. @@ -431,12 +402,8 @@ def conduct_experiment_for_different_train_data_sizes( list_log10_ws_dist_weight_quarts.append(log10_ws_dist_weight_quarts) list_log10_ws_dist_hybrid_quarts.append(log10_ws_dist_hybrid_quarts) - list_log10_ws_dist_weight_quarts = np.array( - list_log10_ws_dist_weight_quarts - ).transpose() - list_log10_ws_dist_hybrid_quarts = np.array( - list_log10_ws_dist_hybrid_quarts - ).transpose() + list_log10_ws_dist_weight_quarts = np.array(list_log10_ws_dist_weight_quarts).transpose() + list_log10_ws_dist_hybrid_quarts = np.array(list_log10_ws_dist_hybrid_quarts).transpose() return list_log10_ws_dist_weight_quarts, list_log10_ws_dist_hybrid_quarts @@ -460,10 +427,7 @@ def conduct_experiment_for_different_num_features(num_input_dimensions): ) # for the analytic solution using the weight space approximated kernel list_of_hybrid_results = [] # for the hybrid-rule approximation for nf in num_features: - ( - weight_results, - hybrid_results, - ) = conduct_experiment_for_different_train_data_sizes( + (weight_results, hybrid_results,) = conduct_experiment_for_different_train_data_sizes( num_input_dimensions=num_input_dimensions, num_features=nf ) print() @@ -496,34 +460,22 @@ def conduct_experiment_for_different_num_features(num_input_dimensions): # plot the results for the analytic solution using the weight space approximated kernel colors = ["bisque", "orange", "peru"] - assert len(colors) == len( - num_features - ), "Number of colors must equal the number of features!" + assert len(colors) == len(num_features), "Number of colors must equal the number of features!" for j in range(len(weight_results)): weight_result = weight_results[j] axs[i].fill_between( - num_train_samples, - weight_result[0], - weight_result[2], - color=colors[j], - alpha=0.1, + num_train_samples, weight_result[0], weight_result[2], color=colors[j], alpha=0.1, ) axs[i].plot(num_train_samples, weight_result[1], "o", color=colors[j]) axs[i].plot(num_train_samples, weight_result[1], color=colors[j], linewidth=0.5) # plot the results for the hybrid-rule approximation colors = ["lightblue", "blue", "darkblue"] - assert len(colors) == len( - num_features - ), "Number of colors must equal the number of features!" + assert len(colors) == len(num_features), "Number of colors must equal the number of features!" for j in range(len(hybrid_results)): hybrid_result = hybrid_results[j] axs[i].fill_between( - num_train_samples, - hybrid_result[0], - hybrid_result[2], - color=colors[j], - alpha=0.1, + num_train_samples, hybrid_result[0], hybrid_result[2], color=colors[j], alpha=0.1, ) axs[i].plot(num_train_samples, hybrid_result[1], "o", color=colors[j]) axs[i].plot(num_train_samples, hybrid_result[1], color=colors[j], linewidth=0.5) diff --git a/docs/notebooks/efficient_sampling.py b/docs/notebooks/efficient_sampling.py index e9483f91..e8c3e781 100644 --- a/docs/notebooks/efficient_sampling.py +++ b/docs/notebooks/efficient_sampling.py @@ -75,9 +75,7 @@ eigenfunctions = RandomFourierFeaturesCosine(kernel, num_rff, dtype=default_float()) eigenvalues = np.ones((num_rff, 1), dtype=default_float()) -kernel_with_features = KernelWithFeatureDecomposition( - kernel, eigenfunctions, eigenvalues -) +kernel_with_features = KernelWithFeatureDecomposition(kernel, eigenfunctions, eigenvalues) # %% [markdown] @@ -96,9 +94,7 @@ num_latent_gps=1, mean_function=gpflow.mean_functions.Zero(), ) -likelihood_layer = gpflux.layers.LikelihoodLayer( - gpflow.likelihoods.Gaussian() -) # noqa: E231 +likelihood_layer = gpflux.layers.LikelihoodLayer(gpflow.likelihoods.Gaussian()) # noqa: E231 dgp = gpflux.models.DeepGP([layer], likelihood_layer) model = dgp.as_training_model() # %% [markdown] @@ -116,11 +112,7 @@ ] history = model.fit( - {"inputs": X, "targets": Y}, - batch_size=num_data, - epochs=100, - callbacks=callbacks, - verbose=0, + {"inputs": X, "targets": Y}, batch_size=num_data, epochs=100, callbacks=callbacks, verbose=0, ) # %% [markdown] """ diff --git a/docs/notebooks/gpflux_features.py b/docs/notebooks/gpflux_features.py index 0155140c..106faa88 100644 --- a/docs/notebooks/gpflux_features.py +++ b/docs/notebooks/gpflux_features.py @@ -68,10 +68,7 @@ def motorcycle_data(): from gpflux.models import DeepGP config = Config( - num_inducing=25, - inner_layer_qsqrt_factor=1e-5, - likelihood_noise_variance=1e-2, - whiten=True, + num_inducing=25, inner_layer_qsqrt_factor=1e-5, likelihood_noise_variance=1e-2, whiten=True, ) deep_gp: DeepGP = build_constant_input_dim_deep_gp(X, num_layers=2, config=config) @@ -92,23 +89,15 @@ def motorcycle_data(): callbacks = [ # Create callback that reduces the learning rate every time the ELBO plateaus - tf.keras.callbacks.ReduceLROnPlateau( - "loss", factor=0.95, patience=3, min_lr=1e-6, verbose=0 - ), + tf.keras.callbacks.ReduceLROnPlateau("loss", factor=0.95, patience=3, min_lr=1e-6, verbose=0), # Create a callback that writes logs (e.g., hyperparameters, KLs, etc.) to TensorBoard gpflux.callbacks.TensorBoard(), # Create a callback that saves the model's weights - tf.keras.callbacks.ModelCheckpoint( - filepath="ckpts/", save_weights_only=True, verbose=0 - ), + tf.keras.callbacks.ModelCheckpoint(filepath="ckpts/", save_weights_only=True, verbose=0), ] history = training_model.fit( - {"inputs": X, "targets": Y}, - batch_size=12, - epochs=200, - callbacks=callbacks, - verbose=0, + {"inputs": X, "targets": Y}, batch_size=12, epochs=200, callbacks=callbacks, verbose=0, ) # %% [markdown] diff --git a/docs/notebooks/gpflux_with_keras_layers.py b/docs/notebooks/gpflux_with_keras_layers.py index ba051517..4bb5c6ef 100644 --- a/docs/notebooks/gpflux_with_keras_layers.py +++ b/docs/notebooks/gpflux_with_keras_layers.py @@ -117,10 +117,7 @@ def plot(model, X, Y, ax=None): f_distribution = model(X_test) mean = f_distribution.mean().numpy().squeeze() - var = ( - f_distribution.variance().numpy().squeeze() - + model.layers[-1].likelihood.variance.numpy() - ) + var = f_distribution.variance().numpy().squeeze() + model.layers[-1].likelihood.variance.numpy() X_test = X_test.squeeze() lower = mean - 2 * np.sqrt(var) upper = mean + 2 * np.sqrt(var) diff --git a/docs/notebooks/keras_integration.py b/docs/notebooks/keras_integration.py index 4335034e..f4befd9a 100644 --- a/docs/notebooks/keras_integration.py +++ b/docs/notebooks/keras_integration.py @@ -55,9 +55,7 @@ def create_layers(): layer1 = gpflux.helpers.construct_gp_layer( num_data, num_inducing, input_dim, hidden_dim, z_init=Z.copy() ) - layer1.mean_function = ( - gpflow.mean_functions.Identity() - ) # TODO: pass layer_type instead + layer1.mean_function = gpflow.mean_functions.Identity() # TODO: pass layer_type instead layer1.q_sqrt.assign(layer1.q_sqrt * 0.01) layer2 = gpflux.helpers.construct_gp_layer( @@ -78,9 +76,7 @@ def create_model(model_class): a constructor that has the same semantics as `tf.keras.Model.__init__`. """ layer1, layer2, likelihood_layer = create_layers() - dgp = gpflux.models.DeepGP( - [layer1, layer2], likelihood_layer, default_model_class=model_class - ) + dgp = gpflux.models.DeepGP([layer1, layer2], likelihood_layer, default_model_class=model_class) return dgp @@ -101,10 +97,7 @@ def create_model(model_class): dgp_train.compile(tf.optimizers.Adam(learning_rate=0.1)) history = dgp_train.fit( - {"inputs": X, "targets": Y}, - batch_size=batch_size, - epochs=num_epochs, - callbacks=callbacks, + {"inputs": X, "targets": Y}, batch_size=batch_size, epochs=num_epochs, callbacks=callbacks, ) # %% @@ -130,10 +123,7 @@ def create_model(model_class): ) history_natgrad = dgp_natgrad_train.fit( - {"inputs": X, "targets": Y}, - batch_size=batch_size, - epochs=num_epochs, - callbacks=callbacks, + {"inputs": X, "targets": Y}, batch_size=batch_size, epochs=num_epochs, callbacks=callbacks, ) # %% diff --git a/docs/notebooks/multi_output_efficient_sampling.py b/docs/notebooks/multi_output_efficient_sampling.py index a3375a55..9ac669f6 100644 --- a/docs/notebooks/multi_output_efficient_sampling.py +++ b/docs/notebooks/multi_output_efficient_sampling.py @@ -36,9 +36,7 @@ from gpflow.config import default_float -from gpflux.layers.basis_functions.fourier_features import ( - MultiOutputRandomFourierFeaturesCosine, -) +from gpflux.layers.basis_functions.fourier_features import MultiOutputRandomFourierFeaturesCosine from gpflux.feature_decomposition_kernels import ( KernelWithFeatureDecomposition, SharedMultiOutputKernelWithFeatureDecomposition, @@ -89,9 +87,7 @@ gpflow.utilities.set_trainable(inducing_variable, False) P = 2 num_rff = 1000 -eigenfunctions = MultiOutputRandomFourierFeaturesCosine( - kernel, num_rff, dtype=default_float() -) +eigenfunctions = MultiOutputRandomFourierFeaturesCosine(kernel, num_rff, dtype=default_float()) eigenvalues = np.ones((P, num_rff, 1), dtype=default_float()) # kernel_with_features = SeparateMultiOutputKernelWithFeatureDecomposition(kernel, eigenfunctions, eigenvalues) kernel_with_features = SharedMultiOutputKernelWithFeatureDecomposition( @@ -113,9 +109,7 @@ num_latent_gps=2, mean_function=gpflow.mean_functions.Zero(), ) -likelihood_layer = gpflux.layers.LikelihoodLayer( - gpflow.likelihoods.Gaussian() -) # noqa: E231 +likelihood_layer = gpflux.layers.LikelihoodLayer(gpflow.likelihoods.Gaussian()) # noqa: E231 dgp = gpflux.models.DeepGP([layer], likelihood_layer) model = dgp.as_training_model() # %% [markdown] diff --git a/docs/notebooks/multi_output_weight_space_approximation.py b/docs/notebooks/multi_output_weight_space_approximation.py index 602903f6..1586bd24 100644 --- a/docs/notebooks/multi_output_weight_space_approximation.py +++ b/docs/notebooks/multi_output_weight_space_approximation.py @@ -61,9 +61,7 @@ from gpflow.likelihoods import Gaussian from gpflow.inducing_variables import InducingPoints -from gpflux.layers.basis_functions.fourier_features import ( - MultiOutputRandomFourierFeaturesCosine, -) +from gpflux.layers.basis_functions.fourier_features import MultiOutputRandomFourierFeaturesCosine from gpflux.feature_decomposition_kernels import ( KernelWithFeatureDecomposition, SeparateMultiOutputKernelWithFeatureDecomposition, @@ -148,9 +146,7 @@ def __init__( noise_variance = 1.0 likelihood = gpflow.likelihoods.Gaussian(noise_variance) _, Y_data = data - super().__init__( - kernel, likelihood, mean_function, num_latent_gps=Y_data.shape[-1] - ) + super().__init__(kernel, likelihood, mean_function, num_latent_gps=Y_data.shape[-1]) self.data = data_input_to_tensor(data) # type-ignore is because of changed method signature: @@ -169,9 +165,7 @@ def log_marginal_likelihood(self) -> tf.Tensor: """ X, Y = self.data K = self.kernel(X) - ks = add_likelihood_noise_cov( - K, self.likelihood, tf.tile(X[None, ...], [2, 1, 1]) - ) + ks = add_likelihood_noise_cov(K, self.likelihood, tf.tile(X[None, ...], [2, 1, 1])) L = tf.linalg.cholesky(ks) m = self.mean_function(X) @@ -208,9 +202,7 @@ def predict_f( # NOTE -- this onlty works for a single latent Full GP # conditional = gpflow.conditionals.base_conditional - conditional = ( - gpflow.conditionals.util.separate_independent_conditional_implementation - ) + conditional = gpflow.conditionals.util.separate_independent_conditional_implementation f_mean_zero, f_var = conditional( kmn, kmm_plus_s, knn, err, full_cov=full_cov, white=False @@ -234,12 +226,8 @@ def predict_f( lengthscale = [ 0.1 ] # lengthscale for the kernel (which is not learned in all experiments, the kernel variance is 1) -number_of_features = ( - 2000 # number of basis functions for weight-space approximated kernels -) -noise_variance = ( - 1e-3 # noise variance of the likelihood (which is not learned in all experiments) -) +number_of_features = 2000 # number of basis functions for weight-space approximated kernels +noise_variance = 1e-3 # noise variance of the likelihood (which is not learned in all experiments) number_of_test_samples = 1024 # number of evaluation points for prediction number_of_function_samples = ( 20 # number of function samples to be drawn from (approximate) posteriors @@ -285,32 +273,25 @@ def predict_f( # training pointsnumber_of_train_samples X.append( - np.linspace( - start=X_interval[0], stop=X_interval[1], num=number_of_train_samples[i] - )[..., None] + np.linspace(start=X_interval[0], stop=X_interval[1], num=number_of_train_samples[i])[ + ..., None + ] ) for j in range(len(list_kernels)): # training observations generated from a zero-mean GP corrupted with Gaussian noise kXX = list_kernels[j].K(X[-1]) - kXX_plus_noise_var = ( - kXX + tf.eye(tf.shape(kXX)[0], dtype=kXX.dtype) * noise_variance - ) + kXX_plus_noise_var = kXX + tf.eye(tf.shape(kXX)[0], dtype=kXX.dtype) * noise_variance lXX = tf.linalg.cholesky(kXX_plus_noise_var) y_temp.append( - tf.matmul( - lXX, - tf.random.normal([number_of_train_samples[i], 1], dtype=X[-1].dtype), - )[..., 0][..., None] + tf.matmul(lXX, tf.random.normal([number_of_train_samples[i], 1], dtype=X[-1].dtype),)[ + ..., 0 + ][..., None] ) # test points for evaluation - X_star.append( - np.linspace(start=x_lim[0], stop=x_lim[1], num=number_of_test_samples)[ - ..., None - ] - ) + X_star.append(np.linspace(start=x_lim[0], stop=x_lim[1], num=number_of_test_samples)[..., None]) y.append(np.concatenate(y_temp, axis=-1)) @@ -348,9 +329,7 @@ def predict_f( if ( experiment == 0 ): # as vertical lines for the first set of experiments with few training samples - axs[experiment, i].vlines( - X[experiment], ymin=y_lim[0], ymax=y_lim[1], colors="lightgrey" - ) + axs[experiment, i].vlines(X[experiment], ymin=y_lim[0], ymax=y_lim[1], colors="lightgrey") else: # as fill plots for the second set of experiments with many training samples axs[experiment, 1].fill_between( X[experiment].ravel(), y_lim[0], y_lim[1], color="gray", alpha=0.2 @@ -390,9 +369,7 @@ def predict_f( print(X_star[experiment].shape) gpr_model = GPR_deprecated( - data=(X[experiment], y[experiment]), - kernel=kernel, - noise_variance=noise_variance, + data=(X[experiment], y[experiment]), kernel=kernel, noise_variance=noise_variance, ) # predict function mean and variance, and draw function samples (without observation noise)# @@ -422,10 +399,7 @@ def predict_f( ) for i in range(f_samples.shape[0]): axs[experiment, 0].plot( - X_star[experiment][..., 0], - f_samples[i, ..., 0], - color="orange", - linewidth=0.2, + X_star[experiment][..., 0], f_samples[i, ..., 0], color="orange", linewidth=0.2, ) axs[experiment, 0].plot(X_star[experiment][..., 0], f_mean[..., 0], color="orange") @@ -440,10 +414,7 @@ def predict_f( ) for i in range(f_samples.shape[0]): axs[experiment, 1].plot( - X_star[experiment][..., 0], - f_samples[i, ..., 1], - color="orange", - linewidth=0.2, + X_star[experiment][..., 0], f_samples[i, ..., 1], color="orange", linewidth=0.2, ) axs[experiment, 1].plot(X_star[experiment][..., 0], f_mean[..., 1], color="orange") diff --git a/docs/notebooks/weight_space_approximation.py b/docs/notebooks/weight_space_approximation.py index d8b1b2ac..e53dbf18 100644 --- a/docs/notebooks/weight_space_approximation.py +++ b/docs/notebooks/weight_space_approximation.py @@ -77,12 +77,8 @@ # experiment parameters that are the same for both sets of experiments X_interval = [0.14, 0.5] # interval where training points live lengthscale = 0.1 # lengthscale for the kernel (which is not learned in all experiments, the kernel variance is 1) -number_of_features = ( - 2000 # number of basis functions for weight-space approximated kernels -) -noise_variance = ( - 1e-3 # noise variance of the likelihood (which is not learned in all experiments) -) +number_of_features = 2000 # number of basis functions for weight-space approximated kernels +noise_variance = 1e-3 # noise variance of the likelihood (which is not learned in all experiments) number_of_test_samples = 1024 # number of evaluation points for prediction number_of_function_samples = ( 20 # number of function samples to be drawn from (approximate) posteriors @@ -106,9 +102,7 @@ # %% # generate training data and evaluation points for both sets of experiments -kernel = kernel_class( - lengthscales=lengthscale -) # kernel object to draw training dataset from +kernel = kernel_class(lengthscales=lengthscale) # kernel object to draw training dataset from X, y, X_star = ( [], [], @@ -119,28 +113,18 @@ for i in range(len(number_of_train_samples)): # training pointsnumber_of_train_samples - X.append( - np.linspace( - start=X_interval[0], stop=X_interval[1], num=number_of_train_samples[i] - ) - ) + X.append(np.linspace(start=X_interval[0], stop=X_interval[1], num=number_of_train_samples[i])) # training observations generated from a zero-mean GP corrupted with Gaussian noise kXX = kernel.K(X[i][..., None]) - kXX_plus_noise_var = ( - kXX + tf.eye(tf.shape(kXX)[0], dtype=kXX.dtype) * noise_variance - ) + kXX_plus_noise_var = kXX + tf.eye(tf.shape(kXX)[0], dtype=kXX.dtype) * noise_variance lXX = tf.linalg.cholesky(kXX_plus_noise_var) y.append( - tf.matmul( - lXX, tf.random.normal([number_of_train_samples[i], 1], dtype=X[i].dtype) - )[..., 0] + tf.matmul(lXX, tf.random.normal([number_of_train_samples[i], 1], dtype=X[i].dtype))[..., 0] ) # test points for evaluation - X_star.append( - np.linspace(start=x_lim[0], stop=x_lim[1], num=number_of_test_samples) - ) + X_star.append(np.linspace(start=x_lim[0], stop=x_lim[1], num=number_of_test_samples)) # %% [markdown] """ @@ -159,12 +143,8 @@ for experiment in range(len(number_of_train_samples)): # subplot titles and axis labels - axs[experiment, 0].set_title( - "Exact GP $N=" + str(number_of_train_samples[experiment]) + "$" - ) - axs[experiment, 1].set_title( - "Sparse GP $N=" + str(number_of_train_samples[experiment]) + "$" - ) + axs[experiment, 0].set_title("Exact GP $N=" + str(number_of_train_samples[experiment]) + "$") + axs[experiment, 1].set_title("Sparse GP $N=" + str(number_of_train_samples[experiment]) + "$") axs[experiment, 2].set_title( "Weight Space GP $N=" + str(number_of_train_samples[experiment]) + "$" ) @@ -206,9 +186,7 @@ # plot mean and std lines from the GPR model as "ground truth" in all three plots for i in range(3): - axs[experiment, i].plot( - X_star[experiment], f_mean[..., 0], linestyle="--", color="black" - ) + axs[experiment, i].plot(X_star[experiment], f_mean[..., 0], linestyle="--", color="black") axs[experiment, i].plot( X_star[experiment], f_mean_minus_2std[..., 0], linestyle="--", color="black" ) @@ -235,9 +213,9 @@ ): # inducing points equal the training data for the first experiment with few training points Z = X[experiment].copy()[..., None] else: # inducing points are randomly chosen for the second experiment with many training points - Z = np.linspace( - X_interval[0], X_interval[1], number_of_inducing_points[experiment] - )[..., None] + Z = np.linspace(X_interval[0], X_interval[1], number_of_inducing_points[experiment])[ + ..., None + ] svgp_model = SVGP( kernel=kernel_class(lengthscales=lengthscale), likelihood=Gaussian(variance=noise_variance), @@ -247,16 +225,12 @@ svgp_model.kernel, False ) # the training data has been sampled from a known kernel! gpf.set_trainable(svgp_model.likelihood, False) # the likelihood variance is known! - gpf.set_trainable( - svgp_model.inducing_variable, False - ) # inducing point locations are fixed! + gpf.set_trainable(svgp_model.inducing_variable, False) # inducing point locations are fixed! def optimize_model_with_scipy(model): optimizer = gpf.optimizers.Scipy() optimizer.minimize( - model.training_loss_closure( - (X[experiment][..., None], y[experiment][..., None]) - ), + model.training_loss_closure((X[experiment][..., None], y[experiment][..., None])), variables=model.trainable_variables, method="l-bfgs-b", options={"disp": False, "maxiter": 10000}, @@ -301,9 +275,7 @@ def optimize_model_with_scipy(model): ) feature_coefficients = np.ones((number_of_features, 1), dtype=default_float()) kernel = KernelWithFeatureDecomposition( - kernel=None, - feature_functions=feature_functions, - feature_coefficients=feature_coefficients, + kernel=None, feature_functions=feature_functions, feature_coefficients=feature_coefficients, ) gpr_model = GPR( data=(X[experiment][..., None], y[experiment][..., None]), diff --git a/gpflux/architectures/constant_input_dim_deep_gp.py b/gpflux/architectures/constant_input_dim_deep_gp.py index 3c184341..681a971c 100644 --- a/gpflux/architectures/constant_input_dim_deep_gp.py +++ b/gpflux/architectures/constant_input_dim_deep_gp.py @@ -93,9 +93,7 @@ def _construct_kernel(input_dim: int, is_last_layer: bool) -> SquaredExponential construct_kernel -def build_constant_input_dim_deep_gp( - X: np.ndarray, num_layers: int, config: Config -) -> DeepGP: +def build_constant_input_dim_deep_gp(X: np.ndarray, num_layers: int, config: Config) -> DeepGP: r""" Build a Deep GP consisting of ``num_layers`` :class:`GPLayer`\ s. All the hidden layers have the same input dimension as the data, that is, ``X.shape[1]``. @@ -157,11 +155,7 @@ def build_constant_input_dim_deep_gp( q_sqrt_scaling = config.inner_layer_qsqrt_factor layer = GPLayer( - kernel, - inducing_var, - num_data, - mean_function=mean_function, - name=f"gp_{i_layer}", + kernel, inducing_var, num_data, mean_function=mean_function, name=f"gp_{i_layer}", ) layer.q_sqrt.assign(layer.q_sqrt * q_sqrt_scaling) gp_layers.append(layer) diff --git a/gpflux/callbacks.py b/gpflux/callbacks.py index 7e529188..5005abeb 100644 --- a/gpflux/callbacks.py +++ b/gpflux/callbacks.py @@ -159,9 +159,7 @@ def run(self, **unused_kwargs: Any) -> None: # skip parameters continue # check if the parameter name matches any of the specified keywords - if self.summarize_all or any( - (keyword in name) for keyword in self.keywords_to_monitor - ): + if self.summarize_all or any((keyword in name) for keyword in self.keywords_to_monitor): # keys are sometimes prepended with a character, which we strip name = name.lstrip(self.left_strip_character) self._summarize_parameter(name, parameter) diff --git a/gpflux/encoders/__init__.py b/gpflux/encoders/__init__.py index 78e8c293..cb6fdd82 100644 --- a/gpflux/encoders/__init__.py +++ b/gpflux/encoders/__init__.py @@ -17,6 +17,4 @@ Encoders are used by :class:`~gpflux.layers.LatentVariableLayer`\ s to parametrize the approximate posterior distribution over latent variables. """ -from gpflux.encoders.directly_parameterized_encoder import ( - DirectlyParameterizedNormalDiag, -) +from gpflux.encoders.directly_parameterized_encoder import DirectlyParameterizedNormalDiag diff --git a/gpflux/encoders/directly_parameterized_encoder.py b/gpflux/encoders/directly_parameterized_encoder.py index 6d1fcd1b..8a865b8c 100644 --- a/gpflux/encoders/directly_parameterized_encoder.py +++ b/gpflux/encoders/directly_parameterized_encoder.py @@ -66,9 +66,7 @@ class DirectlyParameterizedNormalDiag(TrackableLayer): Initialised to ``1e-5 * np.ones((N, W))``. """ - def __init__( - self, num_data: int, latent_dim: int, means: Optional[np.ndarray] = None - ): + def __init__(self, num_data: int, latent_dim: int, means: Optional[np.ndarray] = None): """ Directly parameterise the posterior of the latent variables associated with each datapoint with a diagonal multivariate Normal distribution. Note that across @@ -101,9 +99,7 @@ def __init__( # TODO: Rename to `scale` and `loc` to match tfp.distributions self.means = Parameter(means, dtype=default_float(), name="w_means") - self.stds = Parameter( - stds, transform=positive(), dtype=default_float(), name="w_stds" - ) + self.stds = Parameter(stds, transform=positive(), dtype=default_float(), name="w_stds") def call( self, inputs: Optional[TensorType] = None, *args: Any, **kwargs: Any @@ -113,10 +109,6 @@ def call( """ if inputs is not None: tf.debugging.assert_shapes( - [ - (self.means, ["N", "W"]), - (self.stds, ["N", "W"]), - (inputs, ["N", "D"]), - ] + [(self.means, ["N", "W"]), (self.stds, ["N", "W"]), (inputs, ["N", "D"]),] ) return self.means, self.stds diff --git a/gpflux/experiment_support/plotting.py b/gpflux/experiment_support/plotting.py index 87d7bff9..f6ce52a8 100644 --- a/gpflux/experiment_support/plotting.py +++ b/gpflux/experiment_support/plotting.py @@ -63,10 +63,7 @@ def plot_layer( def plot_layers( - X: TensorType, - means: List[TensorType], - covs: List[TensorType], - samples: List[TensorType], + X: TensorType, means: List[TensorType], covs: List[TensorType], samples: List[TensorType], ) -> None: # pragma: no cover L = len(means) fig, axes = plt.subplots(3, L, figsize=(L * 3.33, 10)) diff --git a/gpflux/experiment_support/tensorboard.py b/gpflux/experiment_support/tensorboard.py index 0bb72810..106efbd2 100644 --- a/gpflux/experiment_support/tensorboard.py +++ b/gpflux/experiment_support/tensorboard.py @@ -34,9 +34,7 @@ class Event: dtype: Type -def tensorboard_event_iterator( - file_pattern: Union[str, List[str], tf.Tensor] -) -> Iterator[Event]: +def tensorboard_event_iterator(file_pattern: Union[str, List[str], tf.Tensor]) -> Iterator[Event]: """ Iterator yielding preprocessed tensorboard Events. diff --git a/gpflux/feature_decomposition_kernels/kernel_with_feature_decomposition.py b/gpflux/feature_decomposition_kernels/kernel_with_feature_decomposition.py index faae572e..5486cd76 100644 --- a/gpflux/feature_decomposition_kernels/kernel_with_feature_decomposition.py +++ b/gpflux/feature_decomposition_kernels/kernel_with_feature_decomposition.py @@ -51,9 +51,7 @@ class _ApproximateKernel(gpflow.kernels.Kernel): """ def __init__( - self, - feature_functions: tf.keras.layers.Layer, - feature_coefficients: TensorType, + self, feature_functions: tf.keras.layers.Layer, feature_coefficients: TensorType, ): r""" :param feature_functions: A Keras layer for which the call evaluates the @@ -74,9 +72,7 @@ def K(self, X: TensorType, X2: Optional[TensorType] = None) -> tf.Tensor: phi2 = self._feature_functions(X2) # [N2, L] r = tf.linalg.matmul( - phi, - tf.linalg.matrix_transpose(self._feature_coefficients) * phi2, - transpose_b=True, + phi, tf.linalg.matrix_transpose(self._feature_coefficients) * phi2, transpose_b=True, ) # [N, N2] N1, N2 = tf.shape(phi)[0], tf.shape(phi2)[0] @@ -87,9 +83,7 @@ def K(self, X: TensorType, X2: Optional[TensorType] = None) -> tf.Tensor: def K_diag(self, X: TensorType) -> tf.Tensor: """Approximate the true kernel by an inner product between feature functions.""" phi_squared = self._feature_functions(X) ** 2 # [N, L] - r = tf.reduce_sum( - phi_squared * tf.transpose(self._feature_coefficients), axis=-1 - ) # [N,] + r = tf.reduce_sum(phi_squared * tf.transpose(self._feature_coefficients), axis=-1) # [N,] N = tf.shape(X)[0] if tf.experimental.numpy.ndim(X) == 1 else tf.shape(X)[0] tf.debugging.assert_equal(tf.shape(r), [N]) # noqa: E231 diff --git a/gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py b/gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py index 1cd42c6b..2850c46c 100644 --- a/gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py +++ b/gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py @@ -51,9 +51,7 @@ class _MultiOutputApproximateKernel(gpflow.kernels.MultioutputKernel): """ def __init__( - self, - feature_functions: tf.keras.layers.Layer, - feature_coefficients: TensorType, + self, feature_functions: tf.keras.layers.Layer, feature_coefficients: TensorType, ): r""" :param feature_functions: A Keras layer for which the call evaluates the @@ -76,19 +74,14 @@ def latent_kernels(self) -> Any: return self._feature_functions def K( - self, - X: TensorType, - X2: Optional[TensorType] = None, - full_output_cov: bool = True, + self, X: TensorType, X2: Optional[TensorType] = None, full_output_cov: bool = True, ) -> tf.Tensor: """Approximate the true kernel by an inner product between feature functions.""" phi = self._feature_functions(X) # [P, N, L] L = tf.shape(phi)[-1] # NOTE - there are some differences between using FourierFeatures and FourierFeaturesCosine, extra check to ensure right shape and to guide debugging in notebooks - tf.debugging.assert_equal( - tf.shape(self._feature_coefficients), [self.num_latent_gps, L, 1] - ) + tf.debugging.assert_equal(tf.shape(self._feature_coefficients), [self.num_latent_gps, L, 1]) if X2 is None: phi2 = phi @@ -96,9 +89,7 @@ def K( phi2 = self._feature_functions(X2) # [P, N2, L] r = tf.linalg.matmul( - phi, - tf.linalg.matrix_transpose(self._feature_coefficients) * phi2, - transpose_b=True, + phi, tf.linalg.matrix_transpose(self._feature_coefficients) * phi2, transpose_b=True, ) # [P, N, N2] N1, N2 = tf.shape(phi)[1], tf.shape(phi2)[1] @@ -110,8 +101,7 @@ def K_diag(self, X: TensorType, full_output_cov: bool = False) -> tf.Tensor: phi_squared = self._feature_functions(X) ** 2 # [P, N, L] r = tf.reduce_sum( - phi_squared * tf.linalg.matrix_transpose(self._feature_coefficients), - axis=-1, + phi_squared * tf.linalg.matrix_transpose(self._feature_coefficients), axis=-1, ) # [P,N,] N = tf.shape(X)[0] @@ -119,9 +109,7 @@ def K_diag(self, X: TensorType, full_output_cov: bool = False) -> tf.Tensor: return r -class SharedMultiOutputKernelWithFeatureDecompositionBase( - gpflow.kernels.SharedIndependent -): +class SharedMultiOutputKernelWithFeatureDecompositionBase(gpflow.kernels.SharedIndependent): """ 'Wrapper' class to solve the issue with full_cov:bool = False inherited from gpflow.kernels.MultiOutputKernel @@ -220,9 +208,7 @@ def __init__( # so it needs to be initialized somehow. Not sure if this is the best approach though _dummy_kernel = SquaredExponential() super().__init__(_dummy_kernel, output_dim) - self._kernel = _MultiOutputApproximateKernel( - feature_functions, feature_coefficients - ) + self._kernel = _MultiOutputApproximateKernel(feature_functions, feature_coefficients) else: super().__init__(kernel.kernel, kernel.output_dim) self._kernel = kernel @@ -257,10 +243,7 @@ def feature_coefficients(self) -> tf.Tensor: return self._feature_coefficients def K( - self, - X: TensorType, - X2: Optional[TensorType] = None, - full_output_cov: bool = True, + self, X: TensorType, X2: Optional[TensorType] = None, full_output_cov: bool = True, ) -> tf.Tensor: return self._kernel.K(X, X2, full_output_cov) @@ -268,9 +251,7 @@ def K_diag(self, X: TensorType, full_output_cov: bool = True) -> tf.Tensor: return self._kernel.K_diag(X, full_output_cov) -class SeparateMultiOutputKernelWithFeatureDecompositionBase( - gpflow.kernels.SeparateIndependent -): +class SeparateMultiOutputKernelWithFeatureDecompositionBase(gpflow.kernels.SeparateIndependent): """ 'Wrapper' class to solve the issue with full_cov:bool = False inherited from gpflow.kernels.MultiOutputKernel @@ -369,9 +350,7 @@ def __init__( # so it needs to be initialized somehow. Not sure if this is the best approach though _dummy_kernels = [SquaredExponential() for _ in range(output_dim)] super().__init__(_dummy_kernels) - self._kernel = _MultiOutputApproximateKernel( - feature_functions, feature_coefficients - ) + self._kernel = _MultiOutputApproximateKernel(feature_functions, feature_coefficients) else: super().__init__(kernel.kernels) @@ -403,10 +382,7 @@ def feature_coefficients(self) -> tf.Tensor: return self._feature_coefficients def K( - self, - X: TensorType, - X2: Optional[TensorType] = None, - full_output_cov: bool = True, + self, X: TensorType, X2: Optional[TensorType] = None, full_output_cov: bool = True, ) -> tf.Tensor: return self._kernel.K(X, X2, full_output_cov) diff --git a/gpflux/helpers.py b/gpflux/helpers.py index 0afb647c..e0018408 100644 --- a/gpflux/helpers.py +++ b/gpflux/helpers.py @@ -139,9 +139,7 @@ def construct_basic_inducing_variables( assert len(z_init[i]) == num_ind_var z_init_i = z_init[i] else: - z_init_i = np.random.randn(num_ind_var, input_dim).astype( - dtype=default_float() - ) + z_init_i = np.random.randn(num_ind_var, input_dim).astype(dtype=default_float()) assert z_init_i.shape == (num_ind_var, input_dim) inducing_variables.append(InducingPoints(z_init_i)) return SeparateIndependentInducingVariables(inducing_variables) @@ -157,9 +155,7 @@ def construct_basic_inducing_variables( ) z_init_o = z_init[o] else: - z_init_o = np.random.randn(num_inducing, input_dim).astype( - dtype=default_float() - ) + z_init_o = np.random.randn(num_inducing, input_dim).astype(dtype=default_float()) inducing_variables.append(InducingPoints(z_init_o)) return SeparateIndependentInducingVariables(inducing_variables) @@ -244,15 +240,9 @@ def construct_gp_layer( """ lengthscale = float(input_dim) ** 0.5 base_kernel = kernel_class(lengthscales=np.full(input_dim, lengthscale)) - kernel = construct_basic_kernel( - base_kernel, output_dim=output_dim, share_hyperparams=True - ) + kernel = construct_basic_kernel(base_kernel, output_dim=output_dim, share_hyperparams=True) inducing_variable = construct_basic_inducing_variables( - num_inducing, - input_dim, - output_dim=output_dim, - share_variables=True, - z_init=z_init, + num_inducing, input_dim, output_dim=output_dim, share_variables=True, z_init=z_init, ) gp_layer = GPLayer( kernel=kernel, @@ -267,9 +257,7 @@ def construct_gp_layer( T = TypeVar("T") -def make_dataclass_from_class( - dataclass: Type[T], instance: object, **updates: object -) -> T: +def make_dataclass_from_class(dataclass: Type[T], instance: object, **updates: object) -> T: """ Take a regular object ``instance`` with a superset of fields for a :class:`dataclasses.dataclass` (``@dataclass``-decorated class), and return an @@ -295,6 +283,4 @@ def xavier_initialization_numpy(input_dim: int, output_dim: int) -> np.ndarray: Draw samples from a normal distribution centred on :math:`0` with standard deviation :math:`\sqrt(2 / (\text{input_dim} + \text{output_dim}))`. """ - return ( - np.random.randn(input_dim, output_dim) * (2.0 / (input_dim + output_dim)) ** 0.5 - ) + return np.random.randn(input_dim, output_dim) * (2.0 / (input_dim + output_dim)) ** 0.5 diff --git a/gpflux/layers/basis_functions/fourier_features/__init__.py b/gpflux/layers/basis_functions/fourier_features/__init__.py index 9f0ac7d5..120d7240 100644 --- a/gpflux/layers/basis_functions/fourier_features/__init__.py +++ b/gpflux/layers/basis_functions/fourier_features/__init__.py @@ -18,9 +18,7 @@ :class:`gpflux.sampling.KernelWithFeatureDecomposition` """ -from gpflux.layers.basis_functions.fourier_features.quadrature import ( - QuadratureFourierFeatures, -) +from gpflux.layers.basis_functions.fourier_features.quadrature import QuadratureFourierFeatures from gpflux.layers.basis_functions.fourier_features.random import ( OrthogonalRandomFeatures, RandomFourierFeatures, diff --git a/gpflux/layers/basis_functions/fourier_features/base.py b/gpflux/layers/basis_functions/fourier_features/base.py index c1ea8074..d431d052 100644 --- a/gpflux/layers/basis_functions/fourier_features/base.py +++ b/gpflux/layers/basis_functions/fourier_features/base.py @@ -26,9 +26,7 @@ class FourierFeaturesBase(ABC, tf.keras.layers.Layer): - def __init__( - self, kernel: gpflow.kernels.Kernel, n_components: int, **kwargs: Mapping - ): + def __init__(self, kernel: gpflow.kernels.Kernel, n_components: int, **kwargs: Mapping): """ :param kernel: kernel to approximate using a set of Fourier bases. :param n_components: number of components (e.g. Monte Carlo samples, diff --git a/gpflux/layers/basis_functions/fourier_features/multioutput/base.py b/gpflux/layers/basis_functions/fourier_features/multioutput/base.py index be9cf6e5..f8505315 100644 --- a/gpflux/layers/basis_functions/fourier_features/multioutput/base.py +++ b/gpflux/layers/basis_functions/fourier_features/multioutput/base.py @@ -28,10 +28,7 @@ class MultiOutputFourierFeaturesBase(ABC, tf.keras.layers.Layer): def __init__( - self, - kernel: gpflow.kernels.MultioutputKernel, - n_components: int, - **kwargs: Mapping + self, kernel: gpflow.kernels.MultioutputKernel, n_components: int, **kwargs: Mapping ): """ :param kernel: kernel to approximate using a set of Fourier bases. Expects a Multioutput Kernel @@ -81,10 +78,7 @@ def call(self, inputs: TensorType) -> tf.Tensor: # NOTE -- each kernel.kernel.lengthscales has to be of the shape [D,] _lengthscales = tf.tile( self.kernel.kernel.lengthscales[None, None, ...] - if tf.rank( - self.kernel.kernel.lengthscales.unconstrained_variable.value() - ) - == 1 + if tf.rank(self.kernel.kernel.lengthscales.unconstrained_variable.value()) == 1 else self.kernel.kernel.lengthscales[None, None, None, ...], [P, 1, 1], ) # [P, 1, D] diff --git a/gpflux/layers/basis_functions/fourier_features/multioutput/random/__init__.py b/gpflux/layers/basis_functions/fourier_features/multioutput/random/__init__.py index 5001d3f4..37be97ef 100644 --- a/gpflux/layers/basis_functions/fourier_features/multioutput/random/__init__.py +++ b/gpflux/layers/basis_functions/fourier_features/multioutput/random/__init__.py @@ -20,11 +20,11 @@ MultiOutputRandomFourierFeaturesCosine, ) from gpflux.layers.basis_functions.fourier_features.multioutput.random.orthogonal import ( - MultiOutputOrthogonalRandomFeatures + MultiOutputOrthogonalRandomFeatures, ) __all__ = [ "MultiOutputRandomFourierFeatures", "MultiOutputRandomFourierFeaturesCosine", - "MultiOutputOrthogonalRandomFeatures" + "MultiOutputOrthogonalRandomFeatures", ] diff --git a/gpflux/layers/basis_functions/fourier_features/multioutput/random/base.py b/gpflux/layers/basis_functions/fourier_features/multioutput/random/base.py index e3742bed..f27b41fb 100644 --- a/gpflux/layers/basis_functions/fourier_features/multioutput/random/base.py +++ b/gpflux/layers/basis_functions/fourier_features/multioutput/random/base.py @@ -77,24 +77,17 @@ def _sample_students_t(nu: float, shape: ShapeType, dtype: DType) -> TensorType: class MultiOutputRandomFourierFeaturesBase(MultiOutputFourierFeaturesBase): def __init__( - self, - kernel: gpflow.kernels.MultioutputKernel, - n_components: int, - **kwargs: Mapping + self, kernel: gpflow.kernels.MultioutputKernel, n_components: int, **kwargs: Mapping ): if isinstance(kernel, gpflow.kernels.SeparateIndependent): for ker in kernel.kernels: assert isinstance(ker, RFF_SUPPORTED_KERNELS), "Unsupported Kernel" elif isinstance(kernel, gpflow.kernels.SharedIndependent): - assert isinstance( - kernel.kernel, RFF_SUPPORTED_KERNELS - ), "Unsupported Kernel" + assert isinstance(kernel.kernel, RFF_SUPPORTED_KERNELS), "Unsupported Kernel" else: raise ValueError("kernel specified is not supported.") - super(MultiOutputRandomFourierFeaturesBase, self).__init__( - kernel, n_components, **kwargs - ) + super(MultiOutputRandomFourierFeaturesBase, self).__init__(kernel, n_components, **kwargs) def build(self, input_shape: ShapeType) -> None: """ @@ -119,9 +112,7 @@ def _weights_build(self, input_dim: int, n_components: int) -> None: ) tf.ensure_shape(self.W, shape) - def _weights_init( - self, shape: TensorType, dtype: Optional[DType] = None - ) -> TensorType: + def _weights_init(self, shape: TensorType, dtype: Optional[DType] = None) -> TensorType: if isinstance(self.kernel, gpflow.kernels.SeparateIndependent): @@ -209,9 +200,7 @@ def _compute_constant(self) -> tf.Tensor: """ if hasattr(self.kernel, "kernels"): - _kernel_variance = tf.stack( - [ker.variance for ker in self.kernel.kernels], axis=0 - ) + _kernel_variance = tf.stack([ker.variance for ker in self.kernel.kernels], axis=0) tf.ensure_shape(_kernel_variance, [self.kernel.num_latent_gps,]) else: @@ -271,9 +260,7 @@ def _bias_build(self, n_components: int) -> None: initializer=self._bias_init, ) - def _bias_init( - self, shape: TensorType, dtype: Optional[DType] = None - ) -> TensorType: + def _bias_init(self, shape: TensorType, dtype: Optional[DType] = None) -> TensorType: return tf.random.uniform(shape=shape, maxval=2.0 * np.pi, dtype=dtype) def _compute_output_dim(self, input_shape: ShapeType) -> int: @@ -295,9 +282,7 @@ def _compute_constant(self) -> tf.Tensor: """ if hasattr(self.kernel, "kernels"): - _kernel_variance = tf.stack( - [ker.variance for ker in self.kernel.kernels], axis=0 - ) + _kernel_variance = tf.stack([ker.variance for ker in self.kernel.kernels], axis=0) tf.ensure_shape(_kernel_variance, [self.kernel.num_latent_gps,]) else: _kernel_variance = self.kernel.kernel.variance diff --git a/gpflux/layers/basis_functions/fourier_features/multioutput/random/orthogonal.py b/gpflux/layers/basis_functions/fourier_features/multioutput/random/orthogonal.py index 13ab6604..c5ae8453 100644 --- a/gpflux/layers/basis_functions/fourier_features/multioutput/random/orthogonal.py +++ b/gpflux/layers/basis_functions/fourier_features/multioutput/random/orthogonal.py @@ -39,6 +39,7 @@ gpflow.kernels.SquaredExponential, ) + def _sample_chi_squared(nu: float, shape: ShapeType, dtype: DType) -> TensorType: """ Draw samples from Chi-squared distribution with `nu` degrees of freedom. @@ -70,31 +71,21 @@ class MultiOutputOrthogonalRandomFeatures(MultiOutputRandomFourierFeatures): efficient and accurate kernel approximations than :class:`RandomFourierFeatures`. """ - def __init__( - self, kernel: gpflow.kernels.Kernel, n_components: int, **kwargs: Mapping - ): - - + def __init__(self, kernel: gpflow.kernels.Kernel, n_components: int, **kwargs: Mapping): if isinstance(kernel, gpflow.kernels.SeparateIndependent): for ker in kernel.kernels: assert isinstance(ker, ORF_SUPPORTED_KERNELS), "Unsupported Kernel" elif isinstance(kernel, gpflow.kernels.SharedIndependent): - assert isinstance( - kernel.kernel, ORF_SUPPORTED_KERNELS - ), "Unsupported Kernel" + assert isinstance(kernel.kernel, ORF_SUPPORTED_KERNELS), "Unsupported Kernel" else: raise ValueError("kernel specified is not supported.") - + super(MultiOutputOrthogonalRandomFeatures, self).__init__(kernel, n_components, **kwargs) - def _weights_init( - self, shape: TensorType, dtype: Optional[DType] = None - ) -> TensorType: + def _weights_init(self, shape: TensorType, dtype: Optional[DType] = None) -> TensorType: n_out, n_components, input_dim = shape # P, M, D - n_reps = _ceil_divide( - n_components, input_dim - ) # K, smallest integer s.t. K*D >= M + n_reps = _ceil_divide(n_components, input_dim) # K, smallest integer s.t. K*D >= M W = tf.random.normal(shape=(n_out, n_reps, input_dim, input_dim), dtype=dtype) Q, _ = tf.linalg.qr(W) # throw away R; shape [P, K, D, D] @@ -102,9 +93,7 @@ def _weights_init( s = _sample_chi( nu=input_dim, shape=(n_out, n_reps, input_dim), dtype=dtype ) # shape [P, K, D] - U = ( - tf.expand_dims(s, axis=-1) * Q - ) # equiv: S @ Q where S = diag(s); shape [P, K, D, D] + U = tf.expand_dims(s, axis=-1) * Q # equiv: S @ Q where S = diag(s); shape [P, K, D, D] V = tf.reshape(U, shape=(n_out, -1, input_dim)) # shape [P, K*D, D] return V[:, : self.n_components, :] # shape [P, M, D] (throw away K*D - M rows) diff --git a/gpflux/layers/basis_functions/fourier_features/quadrature/gaussian.py b/gpflux/layers/basis_functions/fourier_features/quadrature/gaussian.py index 4f4f5969..2391bb13 100644 --- a/gpflux/layers/basis_functions/fourier_features/quadrature/gaussian.py +++ b/gpflux/layers/basis_functions/fourier_features/quadrature/gaussian.py @@ -44,9 +44,7 @@ class QuadratureFourierFeatures(FourierFeaturesBase): - def __init__( - self, kernel: gpflow.kernels.Kernel, n_components: int, **kwargs: Mapping - ): + def __init__(self, kernel: gpflow.kernels.Kernel, n_components: int, **kwargs: Mapping): assert isinstance(kernel, QFF_SUPPORTED_KERNELS), "Unsupported Kernel" if tf.reduce_any(tf.less(kernel.lengthscales, 1e-1)): warnings.warn( @@ -68,13 +66,9 @@ def build(self, input_shape: ShapeType) -> None: omegas_value = tf.squeeze(omegas_value, axis=-1) # Quadrature node points - self.abscissa = tf.Variable( - initial_value=abscissa_value, trainable=False - ) # (M^D, D) + self.abscissa = tf.Variable(initial_value=abscissa_value, trainable=False) # (M^D, D) # Gauss-Hermite weights - self.factors = tf.Variable( - initial_value=omegas_value, trainable=False - ) # (M^D,) + self.factors = tf.Variable(initial_value=omegas_value, trainable=False) # (M^D,) super(QuadratureFourierFeatures, self).build(input_shape) def _compute_output_dim(self, input_shape: ShapeType) -> int: diff --git a/gpflux/layers/basis_functions/fourier_features/random/base.py b/gpflux/layers/basis_functions/fourier_features/random/base.py index ed242a34..82ae4aa9 100644 --- a/gpflux/layers/basis_functions/fourier_features/random/base.py +++ b/gpflux/layers/basis_functions/fourier_features/random/base.py @@ -73,9 +73,7 @@ def _sample_students_t(nu: float, shape: ShapeType, dtype: DType) -> TensorType: class RandomFourierFeaturesBase(FourierFeaturesBase): - def __init__( - self, kernel: gpflow.kernels.Kernel, n_components: int, **kwargs: Mapping - ): + def __init__(self, kernel: gpflow.kernels.Kernel, n_components: int, **kwargs: Mapping): assert isinstance(kernel, RFF_SUPPORTED_KERNELS), "Unsupported Kernel" super(RandomFourierFeaturesBase, self).__init__(kernel, n_components, **kwargs) @@ -99,9 +97,7 @@ def _weights_build(self, input_dim: int, n_components: int) -> None: initializer=self._weights_init, ) - def _weights_init( - self, shape: TensorType, dtype: Optional[DType] = None - ) -> TensorType: + def _weights_init(self, shape: TensorType, dtype: Optional[DType] = None) -> TensorType: if isinstance(self.kernel, gpflow.kernels.SquaredExponential): return tf.random.normal(shape, dtype=dtype) else: @@ -220,9 +216,7 @@ def _bias_build(self, n_components: int) -> None: initializer=self._bias_init, ) - def _bias_init( - self, shape: TensorType, dtype: Optional[DType] = None - ) -> TensorType: + def _bias_init(self, shape: TensorType, dtype: Optional[DType] = None) -> TensorType: return tf.random.uniform(shape=shape, maxval=2.0 * np.pi, dtype=dtype) def _compute_output_dim(self, input_shape: ShapeType) -> int: diff --git a/gpflux/layers/basis_functions/fourier_features/random/orthogonal.py b/gpflux/layers/basis_functions/fourier_features/random/orthogonal.py index 9b99773e..395da743 100644 --- a/gpflux/layers/basis_functions/fourier_features/random/orthogonal.py +++ b/gpflux/layers/basis_functions/fourier_features/random/orthogonal.py @@ -22,9 +22,7 @@ import gpflow from gpflow.base import DType, TensorType -from gpflux.layers.basis_functions.fourier_features.random.base import ( - RandomFourierFeatures, -) +from gpflux.layers.basis_functions.fourier_features.random.base import RandomFourierFeatures from gpflux.types import ShapeType """ @@ -71,29 +69,19 @@ class OrthogonalRandomFeatures(RandomFourierFeatures): efficient and accurate kernel approximations than :class:`RandomFourierFeatures`. """ - def __init__( - self, kernel: gpflow.kernels.Kernel, n_components: int, **kwargs: Mapping - ): + def __init__(self, kernel: gpflow.kernels.Kernel, n_components: int, **kwargs: Mapping): assert isinstance(kernel, ORF_SUPPORTED_KERNELS), "Unsupported Kernel" super(OrthogonalRandomFeatures, self).__init__(kernel, n_components, **kwargs) - def _weights_init( - self, shape: TensorType, dtype: Optional[DType] = None - ) -> TensorType: + def _weights_init(self, shape: TensorType, dtype: Optional[DType] = None) -> TensorType: n_components, input_dim = shape # M, D - n_reps = _ceil_divide( - n_components, input_dim - ) # K, smallest integer s.t. K*D >= M + n_reps = _ceil_divide(n_components, input_dim) # K, smallest integer s.t. K*D >= M W = tf.random.normal(shape=(n_reps, input_dim, input_dim), dtype=dtype) Q, _ = tf.linalg.qr(W) # throw away R; shape [K, D, D] - s = _sample_chi( - nu=input_dim, shape=(n_reps, input_dim), dtype=dtype - ) # shape [K, D] - U = ( - tf.expand_dims(s, axis=-1) * Q - ) # equiv: S @ Q where S = diag(s); shape [K, D, D] + s = _sample_chi(nu=input_dim, shape=(n_reps, input_dim), dtype=dtype) # shape [K, D] + U = tf.expand_dims(s, axis=-1) * Q # equiv: S @ Q where S = diag(s); shape [K, D, D] V = tf.reshape(U, shape=(-1, input_dim)) # shape [K*D, D] return V[: self.n_components] # shape [M, D] (throw away K*D - M rows) diff --git a/gpflux/layers/bayesian_dense_layer.py b/gpflux/layers/bayesian_dense_layer.py index b15466bd..9273babc 100644 --- a/gpflux/layers/bayesian_dense_layer.py +++ b/gpflux/layers/bayesian_dense_layer.py @@ -88,10 +88,7 @@ def __init__( assert w_mu.shape == ((input_dim + 1) * output_dim,) if w_sqrt is not None: if not is_mean_field: - assert w_sqrt.shape == ( - (input_dim + 1) * output_dim, - (input_dim + 1) * output_dim, - ) + assert w_sqrt.shape == ((input_dim + 1) * output_dim, (input_dim + 1) * output_dim,) else: assert w_sqrt.shape == ((input_dim + 1) * output_dim,) assert temperature > 0.0 @@ -111,14 +108,10 @@ def __init__( self.full_output_cov = False self.full_cov = False - self.w_mu = Parameter( - np.zeros((self.dim,)), dtype=default_float(), name="w_mu" - ) # [dim] + self.w_mu = Parameter(np.zeros((self.dim,)), dtype=default_float(), name="w_mu") # [dim] self.w_sqrt = Parameter( - np.zeros((self.dim, self.dim)) - if not self.is_mean_field - else np.ones((self.dim,)), + np.zeros((self.dim, self.dim)) if not self.is_mean_field else np.ones((self.dim,)), transform=triangular() if not self.is_mean_field else positive(), dtype=default_float(), name="w_sqrt", @@ -154,9 +147,7 @@ def predict_samples( :returns: Samples, shape ``[S, N, Q]`` if S is not None else ``[N, Q]``. """ _num_samples = num_samples or 1 - z = tf.random.normal( - (self.dim, _num_samples), dtype=default_float() - ) # [dim, S] + z = tf.random.normal((self.dim, _num_samples), dtype=default_float()) # [dim, S] if not self.is_mean_field: w = self.w_mu[:, None] + tf.matmul(self.w_sqrt, z) # [dim, S] else: @@ -168,9 +159,7 @@ def predict_samples( ) # [N, D+1] samples = tf.tensordot( inputs_concat_1, - tf.reshape( - tf.transpose(w), (_num_samples, self.input_dim + 1, self.output_dim) - ), + tf.reshape(tf.transpose(w), (_num_samples, self.input_dim + 1, self.output_dim)), [[-1], [1]], ) # [N, S, Q] if num_samples is None: diff --git a/gpflux/layers/gp_layer.py b/gpflux/layers/gp_layer.py index 0a61efa5..1f26380a 100644 --- a/gpflux/layers/gp_layer.py +++ b/gpflux/layers/gp_layer.py @@ -228,11 +228,7 @@ def __init__( self.num_samples = num_samples def predict( - self, - inputs: TensorType, - *, - full_cov: bool = False, - full_output_cov: bool = False, + self, inputs: TensorType, *, full_cov: bool = False, full_output_cov: bool = False, ) -> Tuple[tf.Tensor, tf.Tensor]: """ Make a prediction at N test inputs for the Q outputs of this layer, @@ -271,9 +267,7 @@ def predict( return mean_cond + mean_function, cov - def call( - self, inputs: TensorType, *args: List[Any], **kwargs: Dict[str, Any] - ) -> tf.Tensor: + def call(self, inputs: TensorType, *args: List[Any], **kwargs: Dict[str, Any]) -> tf.Tensor: """ The default behaviour upon calling this layer. @@ -290,9 +284,7 @@ def call( outputs = super().call(inputs, *args, **kwargs) if kwargs.get("training"): - log_prior = tf.add_n( - [p.log_prior_density() for p in self.kernel.trainable_parameters] - ) + log_prior = tf.add_n([p.log_prior_density() for p in self.kernel.trainable_parameters]) loss = self.prior_kl() - log_prior loss_per_datapoint = loss / self.num_data @@ -315,11 +307,7 @@ def prior_kl(self) -> tf.Tensor: :attr:`whiten`\ ed representation, returns ``KL[q(v)∥p(v)]``. """ return prior_kl( - self.inducing_variable, - self.kernel, - self.q_mu, - self.q_sqrt, - whiten=self.whiten, + self.inducing_variable, self.kernel, self.q_mu, self.q_sqrt, whiten=self.whiten, ) def _make_distribution_fn( @@ -333,9 +321,7 @@ def _make_distribution_fn( which should be coercible to a `tf.Tensor` """ mean, cov = self.predict( - previous_layer_outputs, - full_cov=self.full_cov, - full_output_cov=self.full_output_cov, + previous_layer_outputs, full_cov=self.full_cov, full_output_cov=self.full_output_cov, ) if self.full_cov and not self.full_output_cov: @@ -350,17 +336,13 @@ def _make_distribution_fn( ) # loc: [N, Q], scale: [N, Q, Q] elif not self.full_cov and not self.full_output_cov: # mean: [N, Q], cov: [N, Q] - return tfp.distributions.MultivariateNormalDiag( - loc=mean, scale_diag=tf.sqrt(cov) - ) + return tfp.distributions.MultivariateNormalDiag(loc=mean, scale_diag=tf.sqrt(cov)) else: raise NotImplementedError( "The combination of both `full_cov` and `full_output_cov` is not permitted." ) - def _convert_to_tensor_fn( - self, distribution: tfp.distributions.Distribution - ) -> tf.Tensor: + def _convert_to_tensor_fn(self, distribution: tfp.distributions.Distribution) -> tf.Tensor: """ Convert the predictive distributions at the input points (see :meth:`_make_distribution_fn`) to a tensor of :attr:`num_samples` diff --git a/gpflux/layers/latent_variable_layer.py b/gpflux/layers/latent_variable_layer.py index 34c30adb..b1012639 100644 --- a/gpflux/layers/latent_variable_layer.py +++ b/gpflux/layers/latent_variable_layer.py @@ -103,9 +103,7 @@ def __init__( self.distribution_class = prior.__class__ self.encoder = encoder self.compositor = ( - compositor - if compositor is not None - else tf.keras.layers.Concatenate(axis=-1) + compositor if compositor is not None else tf.keras.layers.Concatenate(axis=-1) ) def call( @@ -135,9 +133,7 @@ def call( """ if training: if observations is None: - raise ValueError( - "LatentVariableLayer requires observations when training" - ) + raise ValueError("LatentVariableLayer requires observations when training") samples, loss_per_datapoint = self._inference_latent_samples_and_loss( layer_inputs, observations, seed=seed @@ -175,17 +171,12 @@ def _inference_posteriors( encoder_inputs = tf.concat(observations, axis=-1) distribution_params = self.encoder(encoder_inputs, training=training) - posteriors = self.distribution_class( - *distribution_params, allow_nan_stats=False - ) + posteriors = self.distribution_class(*distribution_params, allow_nan_stats=False) return posteriors def _inference_latent_samples_and_loss( - self, - layer_inputs: TensorType, - observations: ObservationType, - seed: Optional[int] = None, + self, layer_inputs: TensorType, observations: ObservationType, seed: Optional[int] = None, ) -> Tuple[tf.Tensor, tf.Tensor]: r""" Sample latent variables during the *training* forward pass, hence requiring diff --git a/gpflux/losses.py b/gpflux/losses.py index 2395b0db..66bb83ca 100644 --- a/gpflux/losses.py +++ b/gpflux/losses.py @@ -79,9 +79,7 @@ def call( Note that we deviate from the Keras Loss interface by calling the second argument *f_prediction* rather than *y_pred*. """ - if isinstance( - unwrap_dist(f_prediction), tfp.distributions.MultivariateNormalDiag - ): + if isinstance(unwrap_dist(f_prediction), tfp.distributions.MultivariateNormalDiag): F_mu = f_prediction.loc F_var = f_prediction.scale.diag ** 2 diff --git a/gpflux/math.py b/gpflux/math.py index d3d4457a..53c2556d 100644 --- a/gpflux/math.py +++ b/gpflux/math.py @@ -58,7 +58,5 @@ def compute_A_inv_b(A: TensorType, b: TensorType) -> tf.Tensor: L = tf.linalg.cholesky(A) # A⁻¹ = L⁻ᵀ L⁻¹ L_inv_b = tf.linalg.triangular_solve(L, b) - A_inv_b = tf.linalg.triangular_solve( - L, L_inv_b, adjoint=True - ) # adjoint = transpose + A_inv_b = tf.linalg.triangular_solve(L, L_inv_b, adjoint=True) # adjoint = transpose return A_inv_b diff --git a/gpflux/models/deep_gp.py b/gpflux/models/deep_gp.py index be1ac0fa..b974d59e 100644 --- a/gpflux/models/deep_gp.py +++ b/gpflux/models/deep_gp.py @@ -131,10 +131,7 @@ def _validate_num_data( return num_data def _evaluate_deep_gp( - self, - inputs: TensorType, - targets: Optional[TensorType], - training: Optional[bool] = None, + self, inputs: TensorType, targets: Optional[TensorType], training: Optional[bool] = None, ) -> tf.Tensor: """ Evaluate ``f(x) = fₙ(⋯ (f₂(f₁(x))))`` on the *inputs* argument. @@ -163,10 +160,7 @@ def _evaluate_deep_gp( return features def _evaluate_likelihood( - self, - f_outputs: TensorType, - targets: Optional[TensorType], - training: Optional[bool] = None, + self, f_outputs: TensorType, targets: Optional[TensorType], training: Optional[bool] = None, ) -> tf.Tensor: """ Call the `likelihood_layer` on *f_outputs*, which adds the @@ -181,9 +175,7 @@ def call( training: Optional[bool] = None, ) -> tf.Tensor: f_outputs = self._evaluate_deep_gp(inputs, targets=targets, training=training) - y_outputs = self._evaluate_likelihood( - f_outputs, targets=targets, training=training - ) + y_outputs = self._evaluate_likelihood(f_outputs, targets=targets, training=training) return y_outputs def predict_f(self, inputs: TensorType) -> Tuple[tf.Tensor, tf.Tensor]: @@ -209,9 +201,7 @@ def elbo(self, data: Tuple[TensorType, TensorType]) -> tf.Tensor: ] return -tf.reduce_sum(all_losses) * self.num_data - def _get_model_class( - self, model_class: Optional[Type[tf.keras.Model]] - ) -> Type[tf.keras.Model]: + def _get_model_class(self, model_class: Optional[Type[tf.keras.Model]]) -> Type[tf.keras.Model]: if model_class is not None: return model_class else: @@ -273,9 +263,7 @@ def as_prediction_model( return model_class(self.inputs, outputs) -def sample_dgp( - model: DeepGP, -) -> Sample: # TODO: should this be part of a [Vanilla]DeepGP class? +def sample_dgp(model: DeepGP,) -> Sample: # TODO: should this be part of a [Vanilla]DeepGP class? function_draws = [layer.sample() for layer in model.f_layers] # TODO: error check that all layers implement .sample()? diff --git a/gpflux/optimization/keras_natgrad.py b/gpflux/optimization/keras_natgrad.py index cc48436c..b009922f 100644 --- a/gpflux/optimization/keras_natgrad.py +++ b/gpflux/optimization/keras_natgrad.py @@ -108,9 +108,7 @@ def optimizer(self) -> tf.optimizers.Optimizer: return self._all_optimizers[-1] @optimizer.setter - def optimizer( - self, optimizers: List[Union[NaturalGradient, tf.optimizers.Optimizer]] - ) -> None: + def optimizer(self, optimizers: List[Union[NaturalGradient, tf.optimizers.Optimizer]]) -> None: if optimizers is None: # tf.keras.Model.__init__() sets self.optimizer = None self._all_optimizers = None @@ -146,9 +144,7 @@ def _split_natgrad_params_and_other_vars( ) -> Tuple[List[Tuple[Parameter, Parameter]], List[tf.Variable]]: # NOTE the structure of variational_params is directly linked to the _natgrad_step, # do not change out of sync - variational_params = [ - (layer.q_mu, layer.q_sqrt) for layer in self.natgrad_layers - ] + variational_params = [(layer.q_mu, layer.q_sqrt) for layer in self.natgrad_layers] # NOTE could use a natgrad_parameters attribute on a layer or a # singledispatch function to make this more flexible for other layers @@ -156,9 +152,7 @@ def _split_natgrad_params_and_other_vars( variational_vars_set = ObjectIdentitySet( p.unconstrained_variable for vp in variational_params for p in vp ) - other_vars = [ - v for v in self.trainable_variables if v not in variational_vars_set - ] + other_vars = [v for v in self.trainable_variables if v not in variational_vars_set] return variational_params, other_vars @@ -191,9 +185,7 @@ def _apply_backwards_pass(self, loss: tf.Tensor, tape: tf.GradientTape) -> None: for (natgrad_optimizer, (q_mu_grad, q_sqrt_grad), (q_mu, q_sqrt)) in zip( self.natgrad_optimizers, variational_params_grads, variational_params ): - natgrad_optimizer._natgrad_apply_gradients( - q_mu_grad, q_sqrt_grad, q_mu, q_sqrt - ) + natgrad_optimizer._natgrad_apply_gradients(q_mu_grad, q_sqrt_grad, q_mu, q_sqrt) self.optimizer.apply_gradients(zip(other_grads, other_vars)) @@ -211,9 +203,7 @@ def train_step(self, data: Any) -> Mapping[str, Any]: with tf.GradientTape() as tape: y_pred = self.__call__(x, training=True) - loss = self.compiled_loss( - y, y_pred, sample_weight, regularization_losses=self.losses - ) + loss = self.compiled_loss(y, y_pred, sample_weight, regularization_losses=self.losses) self._apply_backwards_pass(loss, tape=tape) @@ -253,9 +243,7 @@ def layers(self) -> List[tf.keras.layers.Layer]: else: return self.base_model.layers - def call( - self, data: Any, training: Optional[bool] = None - ) -> Union[tf.Tensor, MeanAndVariance]: + def call(self, data: Any, training: Optional[bool] = None) -> Union[tf.Tensor, MeanAndVariance]: """ Calls the model on new inputs. Simply passes through to the ``base_model``. """ diff --git a/gpflux/runtime_checks.py b/gpflux/runtime_checks.py index 445d9dbb..c8bb3ce5 100644 --- a/gpflux/runtime_checks.py +++ b/gpflux/runtime_checks.py @@ -70,7 +70,5 @@ def verify_compatibility( f"the number of separate independent inducing_variables ({latent_inducing_points})" ) - num_inducing_points = ( - inducing_variable.num_inducing - ) # currently the same for each dim + num_inducing_points = inducing_variable.num_inducing # currently the same for each dim return num_inducing_points, num_latent_gps diff --git a/gpflux/sampling/multioutput/sample.py b/gpflux/sampling/multioutput/sample.py index adacb71b..168b11c9 100644 --- a/gpflux/sampling/multioutput/sample.py +++ b/gpflux/sampling/multioutput/sample.py @@ -91,15 +91,13 @@ def _efficient_multi_output_sample_matheron_rule( ) # [L, P] u_sample_noise = tf.matmul( - q_sqrt, - tf.random.normal((P, M, 1), dtype=default_float()), # [P, M, M] # [P, M, 1] + q_sqrt, tf.random.normal((P, M, 1), dtype=default_float()), # [P, M, M] # [P, M, 1] ) # [P, M, 1] tf.debugging.assert_equal(tf.shape(u_sample_noise), [P, M, 1]) if isinstance(kernel, SharedIndependent): Kmm = tf.tile( - Kuu(inducing_variable, kernel, jitter=default_jitter())[None, ...], - [P, 1, 1], + Kuu(inducing_variable, kernel, jitter=default_jitter())[None, ...], [P, 1, 1], ) # [P,M,M] tf.debugging.assert_equal(tf.shape(Kmm), [P, M, M]) elif isinstance(kernel, SeparateIndependent): @@ -120,9 +118,7 @@ def _efficient_multi_output_sample_matheron_rule( tf.debugging.assert_equal(tf.shape(Kmm), [P, M, M]) u_sample = tf.transpose( - tf.matmul(Luu, tf.transpose(u_sample)[..., None])[ # [P, M, M] # [P, M, 1] - ..., 0 - ] + tf.matmul(Luu, tf.transpose(u_sample)[..., None])[..., 0] # [P, M, M] # [P, M, 1] ) # [M, P] tf.debugging.assert_equal(tf.shape(u_sample), [M, P]) @@ -138,9 +134,7 @@ def _efficient_multi_output_sample_matheron_rule( elif isinstance(inducing_variable, SharedIndependentInducingVariables): - phi_Z = kernel.feature_functions( - inducing_variable.inducing_variable.Z - ) # [P, M, L] + phi_Z = kernel.feature_functions(inducing_variable.inducing_variable.Z) # [P, M, L] tf.debugging.assert_equal(tf.shape(phi_Z), [P, M, L]) else: raise ValueError( @@ -153,9 +147,7 @@ def _efficient_multi_output_sample_matheron_rule( weight_space_prior_Z = tf.transpose(weight_space_prior_Z[..., 0]) # [M, P] diff = tf.transpose(u_sample - weight_space_prior_Z)[..., None] # [P, M, 1] - v = tf.transpose( - compute_A_inv_b(Kmm, diff)[..., 0] # [P, M, M] # [P, M, 1] - ) # [M, P] + v = tf.transpose(compute_A_inv_b(Kmm, diff)[..., 0]) # [P, M, M] # [P, M, 1] # [M, P] tf.debugging.assert_equal(tf.shape(v), [M, P]) @@ -169,10 +161,9 @@ def __call__(self, X: TensorType) -> tf.Tensor: phi_X = kernel.feature_functions(X) # [P, N, L] weight_space_prior_X = tf.transpose( - tf.matmul( - phi_X, # [P, N, L] - tf.transpose(prior_weights)[..., None], # [P, L, 1] - )[..., 0] + tf.matmul(phi_X, tf.transpose(prior_weights)[..., None],)[ # [P, N, L] # [P, L, 1] + ..., 0 + ] ) # [N, P] Knm = tf.linalg.matrix_transpose( @@ -182,9 +173,7 @@ def __call__(self, X: TensorType) -> tf.Tensor: Knm = tf.tile(Knm[None, ...], [P, 1, 1]) tf.debugging.assert_equal(tf.shape(Knm), [P, N, M]) function_space_update_X = tf.transpose( - tf.matmul(Knm, tf.transpose(v)[..., None])[ # [P, N, M] # [P, M, 1] - ..., 0 - ] + tf.matmul(Knm, tf.transpose(v)[..., None])[..., 0] # [P, N, M] # [P, M, 1] ) # [N, P] tf.debugging.assert_equal(tf.shape(weight_space_prior_X), [N, P]) diff --git a/gpflux/sampling/sample.py b/gpflux/sampling/sample.py index f72b221b..cfca4545 100644 --- a/gpflux/sampling/sample.py +++ b/gpflux/sampling/sample.py @@ -74,9 +74,7 @@ def __call__(self, X: TensorType) -> tf.Tensor: """ raise NotImplementedError - def __add__( - self, other: Union["Sample", Callable[[TensorType], TensorType]] - ) -> "Sample": + def __add__(self, other: Union["Sample", Callable[[TensorType], TensorType]]) -> "Sample": """ Allow for the summation of two instances that implement the ``__call__`` method. """ @@ -119,13 +117,7 @@ def __call__(self, X_new: TensorType) -> tf.Tensor: self.X = tf.concat([self.X, X_new], axis=0) mean, cov = conditional( - self.X, - inducing_variable, - kernel, - q_mu, - q_sqrt=q_sqrt, - white=whiten, - full_cov=True, + self.X, inducing_variable, kernel, q_mu, q_sqrt=q_sqrt, white=whiten, full_cov=True, ) # mean: [N_old+N_new, P], cov: [P, N_old+N_new, N_old+N_new] mean = tf.linalg.matrix_transpose(mean) # [P, N_old+N_new] f_old = tf.linalg.matrix_transpose(self.f) # [P, N_old] @@ -171,8 +163,7 @@ def _efficient_sample_matheron_rule( ) # [L, P] u_sample_noise = tf.matmul( - q_sqrt, - tf.random.normal((P, M, 1), dtype=default_float()), # [P, M, M] # [P, M, 1] + q_sqrt, tf.random.normal((P, M, 1), dtype=default_float()), # [P, M, M] # [P, M, 1] ) # [P, M, 1] Kmm = Kuu(inducing_variable, kernel, jitter=default_jitter()) # [M, M] @@ -201,13 +192,9 @@ def __call__(self, X: TensorType) -> tf.Tensor: N = tf.shape(X)[0] phi_X = kernel.feature_functions(X) # [N, L] - weight_space_prior_X = tf.matmul( - phi_X, prior_weights # [N, L] # [L, P] - ) # [N, P] + weight_space_prior_X = tf.matmul(phi_X, prior_weights) # [N, L] # [L, P] # [N, P] - Knm = tf.linalg.matrix_transpose( - Kuf(inducing_variable, kernel, X) - ) # [N, M] + Knm = tf.linalg.matrix_transpose(Kuf(inducing_variable, kernel, X)) # [N, M] function_space_update_X = tf.matmul(Knm, v) # [N, M] # [M, P] # [N, P] diff --git a/gpflux/sampling/utils.py b/gpflux/sampling/utils.py index 15836da0..3ab63103 100644 --- a/gpflux/sampling/utils.py +++ b/gpflux/sampling/utils.py @@ -24,9 +24,7 @@ from gpflux.math import _cholesky_with_jitter -def draw_conditional_sample( - mean: TensorType, cov: TensorType, f_old: TensorType -) -> tf.Tensor: +def draw_conditional_sample(mean: TensorType, cov: TensorType, f_old: TensorType) -> tf.Tensor: r""" Draw a sample :math:`\tilde{f}_\text{new}` from the conditional multivariate Gaussian :math:`p(f_\text{new} | f_\text{old})`, where the diff --git a/tests/conftest.py b/tests/conftest.py index 7b42b147..9783f9d6 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -24,9 +24,7 @@ def test_data(): input_data = np.concatenate([x_data, w_data], axis=1) assert input_data.shape == (num_data, x_dim + w_dim) y_data = np.random.multivariate_normal( - mean=np.zeros(num_data), - cov=SquaredExponential(variance=0.1)(input_data), - size=y_dim, + mean=np.zeros(num_data), cov=SquaredExponential(variance=0.1)(input_data), size=y_dim, ).T assert y_data.shape == (num_data, y_dim) return x_data, y_data diff --git a/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_orthogonal_ff.py b/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_orthogonal_ff.py index dd5ec30c..6122b31d 100644 --- a/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_orthogonal_ff.py +++ b/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_orthogonal_ff.py @@ -27,12 +27,10 @@ MultiOutputRandomFourierFeatures, MultiOutputRandomFourierFeaturesCosine, ) -from gpflux.layers.basis_functions.fourier_features.random.orthogonal import ( - ORF_SUPPORTED_KERNELS, -) +from gpflux.layers.basis_functions.fourier_features.random.orthogonal import ORF_SUPPORTED_KERNELS from gpflux.layers.basis_functions.fourier_features.multioutput.random import ( MultiOutputRandomFourierFeatures, - MultiOutputOrthogonalRandomFeatures + MultiOutputOrthogonalRandomFeatures, ) from gpflux.feature_decomposition_kernels.multioutput import ( @@ -66,10 +64,12 @@ def _batch_size_fixture(request): def _n_features_fixture(request): return request.param + @pytest.fixture(name="base_kernel_cls", params=list(ORF_SUPPORTED_KERNELS)) def _base_kernel_cls_fixture(request): return request.param + def test_orthogonal_fourier_features_can_approximate_multi_output_separate_kernel_multidim( base_kernel_cls, variance, lengthscale, n_dims ): @@ -92,7 +92,7 @@ def test_orthogonal_fourier_features_can_approximate_multi_output_separate_kerne actual_kernel_matrix = kernel.K(x, y, full_output_cov=False).numpy() - #fourier_features = random_basis_func_cls(kernel, n_components, dtype=tf.float64) + # fourier_features = random_basis_func_cls(kernel, n_components, dtype=tf.float64) fourier_features = MultiOutputOrthogonalRandomFeatures(kernel, n_components, dtype=tf.float64) feature_coefficients = np.ones((2, 2 * n_components, 1), dtype=np.float64) @@ -131,7 +131,7 @@ def test_orthogonal_fourier_features_can_approximate_multi_output_shared_kernel_ actual_kernel_matrix = kernel.K(x, y, full_output_cov=False).numpy() - #fourier_features = random_basis_func_cls(kernel, n_components, dtype=tf.float64) + # fourier_features = random_basis_func_cls(kernel, n_components, dtype=tf.float64) fourier_features = MultiOutputOrthogonalRandomFeatures(kernel, n_components, dtype=tf.float64) feature_coefficients = np.ones((2, 2 * n_components, 1), dtype=np.float64) @@ -148,9 +148,6 @@ def test_orthogonal_fourier_features_can_approximate_multi_output_shared_kernel_ np.testing.assert_allclose(approx_kernel_matrix, actual_kernel_matrix, atol=5e-2) - - - """ #TODO -- have a look at what layer_test actually does @skip_serialization_tests diff --git a/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff.py b/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff.py index 3a4bfd88..ae85f19e 100644 --- a/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff.py +++ b/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff.py @@ -27,9 +27,7 @@ MultiOutputRandomFourierFeatures, MultiOutputRandomFourierFeaturesCosine, ) -from gpflux.layers.basis_functions.fourier_features.random.base import ( - RFF_SUPPORTED_KERNELS, -) +from gpflux.layers.basis_functions.fourier_features.random.base import RFF_SUPPORTED_KERNELS from gpflux.layers.basis_functions.fourier_features.multioutput.random import ( MultiOutputRandomFourierFeatures, ) @@ -266,9 +264,7 @@ def test_random_multi_output_fourier_feature_layer_compute_covariance_of_separat np.testing.assert_allclose(approx_kernel_matrix, actual_kernel_matrix, atol=5e-2) -def test_multi_output_fourier_features_shapes( - basis_func_cls, n_components, n_dims, batch_size -): +def test_multi_output_fourier_features_shapes(basis_func_cls, n_components, n_dims, batch_size): input_shape = (2, batch_size, n_dims) base_kernel = gpflow.kernels.SquaredExponential(lengthscales=[1.0] * n_dims) kernel = SeparateIndependent(kernels=[base_kernel, base_kernel]) diff --git a/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff_cosine.py b/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff_cosine.py index 939dc663..41f898e0 100644 --- a/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff_cosine.py +++ b/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff_cosine.py @@ -27,9 +27,7 @@ MultiOutputRandomFourierFeatures, MultiOutputRandomFourierFeaturesCosine, ) -from gpflux.layers.basis_functions.fourier_features.random.base import ( - RFF_SUPPORTED_KERNELS, -) +from gpflux.layers.basis_functions.fourier_features.random.base import RFF_SUPPORTED_KERNELS from gpflux.layers.basis_functions.fourier_features.multioutput.random import ( MultiOutputRandomFourierFeatures, ) @@ -261,9 +259,7 @@ def test_random_multi_output_fourier_feature_layer_compute_covariance_of_separat np.testing.assert_allclose(approx_kernel_matrix, actual_kernel_matrix, atol=5e-2) -def test_multi_output_fourier_features_shapes( - basis_func_cls, n_components, n_dims, batch_size -): +def test_multi_output_fourier_features_shapes(basis_func_cls, n_components, n_dims, batch_size): input_shape = (2, batch_size, n_dims) base_kernel = gpflow.kernels.SquaredExponential(lengthscales=[1.0] * n_dims) kernel = SeparateIndependent(kernels=[base_kernel, base_kernel]) diff --git a/tests/gpflux/layers/basis_functions/fourier_features/test_quadrature.py b/tests/gpflux/layers/basis_functions/fourier_features/test_quadrature.py index b972c1a6..f563b2f6 100644 --- a/tests/gpflux/layers/basis_functions/fourier_features/test_quadrature.py +++ b/tests/gpflux/layers/basis_functions/fourier_features/test_quadrature.py @@ -23,12 +23,8 @@ from gpflow.quadrature.gauss_hermite import NDiagGHQuadrature from gpflow.utilities.ops import difference_matrix -from gpflux.layers.basis_functions.fourier_features.quadrature import ( - QuadratureFourierFeatures, -) -from gpflux.layers.basis_functions.fourier_features.quadrature.gaussian import ( - QFF_SUPPORTED_KERNELS, -) +from gpflux.layers.basis_functions.fourier_features.quadrature import QuadratureFourierFeatures +from gpflux.layers.basis_functions.fourier_features.quadrature.gaussian import QFF_SUPPORTED_KERNELS from tests.conftest import skip_serialization_tests @@ -101,9 +97,7 @@ def test_quadrature_fourier_features_can_approximate_kernel_multidim( np.testing.assert_allclose(approx_kernel_matrix, actual_kernel_matrix) -def test_feature_map_decomposition( - kernel_cls, variance, lengthscale, n_dims, n_components -): +def test_feature_map_decomposition(kernel_cls, variance, lengthscale, n_dims, n_components): """ Verify that the inner product of the feature map yields exactly the same result as that of the direct Gauss-Hermite quadrature scheme. @@ -144,9 +138,7 @@ def eigen_func(w): def test_fourier_features_shapes(n_components, n_dims, batch_size): input_shape = (batch_size, n_dims) kernel = gpflow.kernels.SquaredExponential() - feature_functions = QuadratureFourierFeatures( - kernel, n_components, dtype=tf.float64 - ) + feature_functions = QuadratureFourierFeatures(kernel, n_components, dtype=tf.float64) output_shape = feature_functions.compute_output_shape(input_shape) output_dim = output_shape[-1] assert output_dim == 2 * n_components ** n_dims @@ -158,9 +150,7 @@ def test_fourier_features_shapes(n_components, n_dims, batch_size): def test_keras_testing_util_layer_test_1D(kernel_cls, batch_size, n_components): kernel = kernel_cls() - tf.keras.utils.get_custom_objects()[ - "QuadratureFourierFeatures" - ] = QuadratureFourierFeatures + tf.keras.utils.get_custom_objects()["QuadratureFourierFeatures"] = QuadratureFourierFeatures layer_test( QuadratureFourierFeatures, kwargs={ @@ -176,14 +166,10 @@ def test_keras_testing_util_layer_test_1D(kernel_cls, batch_size, n_components): @skip_serialization_tests -def test_keras_testing_util_layer_test_multidim( - kernel_cls, batch_size, n_dims, n_components -): +def test_keras_testing_util_layer_test_multidim(kernel_cls, batch_size, n_dims, n_components): kernel = kernel_cls() - tf.keras.utils.get_custom_objects()[ - "QuadratureFourierFeatures" - ] = QuadratureFourierFeatures + tf.keras.utils.get_custom_objects()["QuadratureFourierFeatures"] = QuadratureFourierFeatures layer_test( QuadratureFourierFeatures, kwargs={ diff --git a/tests/gpflux/layers/basis_functions/fourier_features/test_random.py b/tests/gpflux/layers/basis_functions/fourier_features/test_random.py index 4d482a4f..950df8fb 100644 --- a/tests/gpflux/layers/basis_functions/fourier_features/test_random.py +++ b/tests/gpflux/layers/basis_functions/fourier_features/test_random.py @@ -26,9 +26,7 @@ RandomFourierFeatures, RandomFourierFeaturesCosine, ) -from gpflux.layers.basis_functions.fourier_features.random.base import ( - RFF_SUPPORTED_KERNELS, -) +from gpflux.layers.basis_functions.fourier_features.random.base import RFF_SUPPORTED_KERNELS from tests.conftest import skip_serialization_tests @@ -63,8 +61,7 @@ def _kernel_cls_fixture(request): @pytest.fixture( - name="random_basis_func_cls", - params=[RandomFourierFeatures, RandomFourierFeaturesCosine], + name="random_basis_func_cls", params=[RandomFourierFeatures, RandomFourierFeaturesCosine], ) def _random_basis_func_cls_fixture(request): return request.param @@ -72,11 +69,7 @@ def _random_basis_func_cls_fixture(request): @pytest.fixture( name="basis_func_cls", - params=[ - RandomFourierFeatures, - RandomFourierFeaturesCosine, - OrthogonalRandomFeatures, - ], + params=[RandomFourierFeatures, RandomFourierFeaturesCosine, OrthogonalRandomFeatures,], ) def _basis_func_cls_fixture(request): return request.param @@ -114,9 +107,7 @@ def test_random_fourier_features_can_approximate_kernel_multidim( np.testing.assert_allclose(approx_kernel_matrix, actual_kernel_matrix, atol=5e-2) -def test_orthogonal_random_features_can_approximate_kernel_multidim( - variance, lengthscale, n_dims -): +def test_orthogonal_random_features_can_approximate_kernel_multidim(variance, lengthscale, n_dims): n_components = 20000 x_rows = 20 @@ -124,9 +115,7 @@ def test_orthogonal_random_features_can_approximate_kernel_multidim( # ARD lengthscales = np.random.rand((n_dims)) * lengthscale - kernel = gpflow.kernels.SquaredExponential( - variance=variance, lengthscales=lengthscales - ) + kernel = gpflow.kernels.SquaredExponential(variance=variance, lengthscales=lengthscales) fourier_features = OrthogonalRandomFeatures(kernel, n_components, dtype=tf.float64) x = tf.random.uniform((x_rows, n_dims), dtype=tf.float64) @@ -193,9 +182,7 @@ def test_keras_testing_util_layer_test_1D(kernel_cls, batch_size, n_components): @skip_serialization_tests -def test_keras_testing_util_layer_test_multidim( - kernel_cls, batch_size, n_dims, n_components -): +def test_keras_testing_util_layer_test_multidim(kernel_cls, batch_size, n_dims, n_components): kernel = kernel_cls() tf.keras.utils.get_custom_objects()["RandomFourierFeatures"] = RandomFourierFeatures diff --git a/tests/gpflux/layers/test_bayesian_dense_layer.py b/tests/gpflux/layers/test_bayesian_dense_layer.py index 62d69e9a..da97d5dc 100644 --- a/tests/gpflux/layers/test_bayesian_dense_layer.py +++ b/tests/gpflux/layers/test_bayesian_dense_layer.py @@ -56,10 +56,7 @@ def make_data(input_dim: int, output_dim: int, num_data: int): X = np.random.random(size=(num_data, input_dim)) * lim[1] cov = RBF().K(X) + np.eye(num_data) * sigma ** 2 - Y = [ - np.random.multivariate_normal(np.zeros(num_data), cov)[:, None] - for _ in range(output_dim) - ] + Y = [np.random.multivariate_normal(np.zeros(num_data), cov)[:, None] for _ in range(output_dim)] Y = np.hstack(Y) return X, Y @@ -149,9 +146,7 @@ def test_losses_are_added(is_mean_field): assert len(bnn_layer.losses) == 0 _ = bnn_layer(X, training=True) - assert bnn_layer.losses == [ - bnn_layer.temperature * bnn_layer.prior_kl() / bnn_layer.num_data - ] + assert bnn_layer.losses == [bnn_layer.temperature * bnn_layer.prior_kl() / bnn_layer.num_data] # Check loss is 0 when training is False _ = bnn_layer(X, training=False) @@ -161,6 +156,4 @@ def test_losses_are_added(is_mean_field): _ = bnn_layer(X, training=True) _ = bnn_layer(X, training=True) assert len(bnn_layer.losses) == 1 - assert bnn_layer.losses == [ - bnn_layer.temperature * bnn_layer.prior_kl() / bnn_layer.num_data - ] + assert bnn_layer.losses == [bnn_layer.temperature * bnn_layer.prior_kl() / bnn_layer.num_data] diff --git a/tests/gpflux/layers/test_dedup_trackable_layer.py b/tests/gpflux/layers/test_dedup_trackable_layer.py index e600c7d1..93d4efc4 100644 --- a/tests/gpflux/layers/test_dedup_trackable_layer.py +++ b/tests/gpflux/layers/test_dedup_trackable_layer.py @@ -63,14 +63,10 @@ def model(data) -> tf.keras.models.Model: num_data = len(X) input_dim = X.shape[-1] - layer1 = construct_gp_layer( - num_data, CONFIG.num_inducing, input_dim, CONFIG.hidden_dim - ) + layer1 = construct_gp_layer(num_data, CONFIG.num_inducing, input_dim, CONFIG.hidden_dim) output_dim = Y.shape[-1] - layer2 = construct_gp_layer( - num_data, CONFIG.num_inducing, CONFIG.hidden_dim, output_dim - ) + layer2 = construct_gp_layer(num_data, CONFIG.num_inducing, CONFIG.hidden_dim, output_dim) likelihood_layer = gpflux.layers.LikelihoodLayer(gpflow.likelihoods.Gaussian(0.01)) @@ -95,23 +91,15 @@ def _size_q_mu(num_inducing, output_dim): "._self_tracked_trackables[1].inducing_variable.inducing_variable.Z": ( CONFIG.num_inducing * CONFIG.input_dim ), - "._self_tracked_trackables[1].q_mu": _size_q_mu( - CONFIG.num_inducing, CONFIG.hidden_dim - ), - "._self_tracked_trackables[1].q_sqrt": _size_q_sqrt( - CONFIG.num_inducing, CONFIG.hidden_dim - ), + "._self_tracked_trackables[1].q_mu": _size_q_mu(CONFIG.num_inducing, CONFIG.hidden_dim), + "._self_tracked_trackables[1].q_sqrt": _size_q_sqrt(CONFIG.num_inducing, CONFIG.hidden_dim), "._self_tracked_trackables[2].kernel.kernel.variance": 1, "._self_tracked_trackables[2].kernel.kernel.lengthscales": CONFIG.hidden_dim, "._self_tracked_trackables[2].inducing_variable.inducing_variable.Z": ( CONFIG.num_inducing * CONFIG.hidden_dim ), - "._self_tracked_trackables[2].q_mu": _size_q_mu( - CONFIG.num_inducing, CONFIG.output_dim - ), - "._self_tracked_trackables[2].q_sqrt": _size_q_sqrt( - CONFIG.num_inducing, CONFIG.output_dim - ), + "._self_tracked_trackables[2].q_mu": _size_q_mu(CONFIG.num_inducing, CONFIG.output_dim), + "._self_tracked_trackables[2].q_sqrt": _size_q_sqrt(CONFIG.num_inducing, CONFIG.output_dim), "._self_tracked_trackables[3].likelihood.variance": 1, } @@ -152,9 +140,7 @@ def test_weights_equals_deduplicated_parameter_dict(model): """ # We filter out the parameters of type ResourceVariable. # They have been added to the model by the `add_metric` call in the layer. - parameters = [ - p for p in parameter_dict(model).values() if not isinstance(p, ResourceVariable) - ] + parameters = [p for p in parameter_dict(model).values() if not isinstance(p, ResourceVariable)] variables = map(lambda p: p.unconstrained_variable, parameters) deduplicate_variables = object_identity.ObjectIdentitySet(variables) diff --git a/tests/gpflux/layers/test_gp_layer.py b/tests/gpflux/layers/test_gp_layer.py index b69a2d5e..7e5f7317 100644 --- a/tests/gpflux/layers/test_gp_layer.py +++ b/tests/gpflux/layers/test_gp_layer.py @@ -33,9 +33,7 @@ def setup_gp_layer_and_data(num_inducing: int, **gp_layer_kwargs): data = make_data(input_dim, output_dim, num_data=num_data) kernel = construct_basic_kernel(RBF(), output_dim) - inducing_vars = construct_basic_inducing_variables( - num_inducing, input_dim, output_dim - ) + inducing_vars = construct_basic_inducing_variables(num_inducing, input_dim, output_dim) mean_function = Zero(output_dim) gp_layer = GPLayer( @@ -50,10 +48,7 @@ def make_data(input_dim: int, output_dim: int, num_data: int): X = np.random.random(size=(num_data, input_dim)) * lim[1] cov = RBF().K(X) + np.eye(num_data) * sigma ** 2 - Y = [ - np.random.multivariate_normal(np.zeros(num_data), cov)[:, None] - for _ in range(output_dim) - ] + Y = [np.random.multivariate_normal(np.zeros(num_data), cov)[:, None] for _ in range(output_dim)] Y = np.hstack(Y) return X, Y @@ -103,25 +98,19 @@ def test_call_shapes(): assert not gp_layer.full_cov and not gp_layer.full_output_cov distribution = gp_layer(X, training=False) - assert isinstance( - unwrap_dist(distribution), tfp.distributions.MultivariateNormalDiag - ) + assert isinstance(unwrap_dist(distribution), tfp.distributions.MultivariateNormalDiag) assert distribution.shape == (batch_size, output_dim) gp_layer.full_cov = True distribution = gp_layer(X, training=False) - assert isinstance( - unwrap_dist(distribution), tfp.distributions.MultivariateNormalTriL - ) + assert isinstance(unwrap_dist(distribution), tfp.distributions.MultivariateNormalTriL) assert distribution.shape == (batch_size, output_dim) assert distribution.covariance().shape == (output_dim, batch_size, batch_size) gp_layer.full_output_cov = True gp_layer.full_cov = False distribution = gp_layer(X, training=False) - assert isinstance( - unwrap_dist(distribution), tfp.distributions.MultivariateNormalTriL - ) + assert isinstance(unwrap_dist(distribution), tfp.distributions.MultivariateNormalTriL) assert distribution.shape == (batch_size, output_dim) assert distribution.covariance().shape == (batch_size, output_dim, output_dim) diff --git a/tests/gpflux/layers/test_latent_variable_layer.py b/tests/gpflux/layers/test_latent_variable_layer.py index 30aba081..a5057b7d 100644 --- a/tests/gpflux/layers/test_latent_variable_layer.py +++ b/tests/gpflux/layers/test_latent_variable_layer.py @@ -35,9 +35,7 @@ def _zero_one_normal_prior(w_dim): """N(0, I) prior""" - return tfp.distributions.MultivariateNormalDiag( - loc=np.zeros(w_dim), scale_diag=np.ones(w_dim) - ) + return tfp.distributions.MultivariateNormalDiag(loc=np.zeros(w_dim), scale_diag=np.ones(w_dim)) def get_distributions_with_w_dim(): @@ -119,12 +117,10 @@ def test_latent_variable_layer_losses(mocker, w_dim): posteriors_shape = (num_data, w_dim) prior = tfp.distributions.MultivariateNormalDiag( - loc=np.random.randn(*prior_shape), - scale_diag=np.random.randn(*prior_shape) ** 2, + loc=np.random.randn(*prior_shape), scale_diag=np.random.randn(*prior_shape) ** 2, ) posteriors = tfp.distributions.MultivariateNormalDiag( - loc=np.random.randn(*posteriors_shape), - scale_diag=np.random.randn(*posteriors_shape) ** 2, + loc=np.random.randn(*posteriors_shape), scale_diag=np.random.randn(*posteriors_shape) ** 2, ) encoder = mocker.Mock(return_value=(posteriors.loc, posteriors.scale.diag)) @@ -161,12 +157,10 @@ def test_latent_variable_layer_samples(mocker, test_data, w_dim, seed2): posteriors_shape = (num_data, w_dim) prior = tfp.distributions.MultivariateNormalDiag( - loc=np.random.randn(*prior_shape), - scale_diag=np.random.randn(*prior_shape) ** 2, + loc=np.random.randn(*prior_shape), scale_diag=np.random.randn(*prior_shape) ** 2, ) posteriors = tfp.distributions.MultivariateNormalDiag( - loc=np.random.randn(*posteriors_shape), - scale_diag=np.random.randn(*posteriors_shape) ** 2, + loc=np.random.randn(*posteriors_shape), scale_diag=np.random.randn(*posteriors_shape) ** 2, ) encoder = mocker.Mock(return_value=(posteriors.loc, posteriors.scale.diag)) @@ -176,19 +170,13 @@ def test_latent_variable_layer_samples(mocker, test_data, w_dim, seed2): tf.random.set_seed(seed) sample_prior = lv(inputs, seed=seed2) tf.random.set_seed(seed) - prior_expected = np.concatenate( - [inputs, prior.sample(num_data, seed=seed2)], axis=-1 - ) + prior_expected = np.concatenate([inputs, prior.sample(num_data, seed=seed2)], axis=-1) np.testing.assert_array_equal(sample_prior, prior_expected) tf.random.set_seed(seed) - sample_posterior = lv( - inputs, observations=[inputs, targets], training=True, seed=seed2 - ) + sample_posterior = lv(inputs, observations=[inputs, targets], training=True, seed=seed2) tf.random.set_seed(seed) - posterior_expected = np.concatenate( - [inputs, posteriors.sample(seed=seed2)], axis=-1 - ) + posterior_expected = np.concatenate([inputs, posteriors.sample(seed=seed2)], axis=-1) np.testing.assert_array_equal(sample_posterior, posterior_expected) diff --git a/tests/gpflux/layers/test_likelihood_layer.py b/tests/gpflux/layers/test_likelihood_layer.py index 3a47baee..58f95d04 100644 --- a/tests/gpflux/layers/test_likelihood_layer.py +++ b/tests/gpflux/layers/test_likelihood_layer.py @@ -36,9 +36,7 @@ def setup_gp_layer_and_data(num_inducing: int, **gp_layer_kwargs): data = make_data(input_dim, output_dim, num_data=num_data) kernel = construct_basic_kernel(Matern52(), output_dim) - inducing_vars = construct_basic_inducing_variables( - num_inducing, input_dim, output_dim - ) + inducing_vars = construct_basic_inducing_variables(num_inducing, input_dim, output_dim) mean_function = Zero(output_dim) gp_layer = GPLayer( @@ -53,10 +51,7 @@ def make_data(input_dim: int, output_dim: int, num_data: int): X = np.random.random(size=(num_data, input_dim)) * lim[1] cov = Matern52()(X) + np.eye(num_data) * sigma ** 2 - Y = [ - np.random.multivariate_normal(np.zeros(num_data), cov)[:, None] - for _ in range(output_dim) - ] + Y = [np.random.multivariate_normal(np.zeros(num_data), cov)[:, None] for _ in range(output_dim)] Y = np.hstack(Y) return ( X, @@ -118,17 +113,13 @@ def test_likelihood_loss(GPflowLikelihood): f_var = f_distribution.scale.diag expected_loss = np.mean(-likelihood.variational_expectations(f_mean, f_var, Y)) - np.testing.assert_almost_equal( - likelihood_loss(Y, f_distribution), expected_loss, decimal=5 - ) + np.testing.assert_almost_equal(likelihood_loss(Y, f_distribution), expected_loss, decimal=5) # 2. Run tests with gp_layer output coerced to sample f_sample = tf.convert_to_tensor(gp_layer(X)) expected_loss = np.mean(-likelihood.log_prob(f_sample, Y)) - np.testing.assert_almost_equal( - likelihood_loss(Y, f_sample), expected_loss, decimal=5 - ) + np.testing.assert_almost_equal(likelihood_loss(Y, f_sample), expected_loss, decimal=5) def test_tensor_coercible(): diff --git a/tests/gpflux/layers/test_trackable_layer.py b/tests/gpflux/layers/test_trackable_layer.py index 483134a0..5030e56e 100644 --- a/tests/gpflux/layers/test_trackable_layer.py +++ b/tests/gpflux/layers/test_trackable_layer.py @@ -62,10 +62,7 @@ def setup_layer_modules_variables(): tf.Variable(7.0, dtype=default_float(), trainable=False), ] ), - [ - CompositeModule(attributes=[Matern52()]), - CompositeModule(attributes=[Matern52()]), - ], + [CompositeModule(attributes=[Matern52()]), CompositeModule(attributes=[Matern52()]),], ] modules_variables = [ @@ -93,62 +90,31 @@ def to_tensor_set(tensor_set: List[tf.Tensor]): def test_submodule_variables(): - ( - trackable_layer, - variables, - modules, - module_variables, - ) = setup_layer_modules_variables() - assert to_tensor_set(trackable_layer.variables) == to_tensor_set( - variables + module_variables - ) + (trackable_layer, variables, modules, module_variables,) = setup_layer_modules_variables() + assert to_tensor_set(trackable_layer.variables) == to_tensor_set(variables + module_variables) def test_submodule_trainable_variables(): - ( - trackable_layer, - variables, - modules, - module_variables, - ) = setup_layer_modules_variables() + (trackable_layer, variables, modules, module_variables,) = setup_layer_modules_variables() trainable_attributes = [v for v in variables + module_variables if v.trainable] assert trackable_layer.trainable_variables == trainable_attributes def test_submodule_non_trainable_variables(): - ( - trackable_layer, - variables, - modules, - module_variables, - ) = setup_layer_modules_variables() - non_trainable_attributes = [ - v for v in variables + module_variables if not v.trainable - ] + (trackable_layer, variables, modules, module_variables,) = setup_layer_modules_variables() + non_trainable_attributes = [v for v in variables + module_variables if not v.trainable] assert trackable_layer.non_trainable_variables == non_trainable_attributes def test_trainable_weights(): - ( - trackable_layer, - variables, - modules, - module_variables, - ) = setup_layer_modules_variables() + (trackable_layer, variables, modules, module_variables,) = setup_layer_modules_variables() all_vars = variables + module_variables trainable_weights = [v for v in all_vars if v.trainable] - assert to_tensor_set(trackable_layer.trainable_weights) == to_tensor_set( - trainable_weights - ) + assert to_tensor_set(trackable_layer.trainable_weights) == to_tensor_set(trainable_weights) def test_non_trainable_weights(): - ( - trackable_layer, - variables, - modules, - module_variables, - ) = setup_layer_modules_variables() + (trackable_layer, variables, modules, module_variables,) = setup_layer_modules_variables() all_vars = variables + module_variables non_trainable_weights = [v for v in all_vars if not v.trainable] assert to_tensor_set(trackable_layer.non_trainable_weights) == to_tensor_set( @@ -157,26 +123,14 @@ def test_non_trainable_weights(): def test_trainable_variables(): - ( - trackable_layer, - variables, - modules, - module_variables, - ) = setup_layer_modules_variables() + (trackable_layer, variables, modules, module_variables,) = setup_layer_modules_variables() all_vars = variables + module_variables trainable_variables = [v for v in all_vars if v.trainable] - assert to_tensor_set(trackable_layer.trainable_variables) == to_tensor_set( - trainable_variables - ) + assert to_tensor_set(trackable_layer.trainable_variables) == to_tensor_set(trainable_variables) def test_variables(): - ( - trackable_layer, - variables, - modules, - module_variables, - ) = setup_layer_modules_variables() + (trackable_layer, variables, modules, module_variables,) = setup_layer_modules_variables() all_vars = variables + module_variables assert to_tensor_set(trackable_layer.variables) == to_tensor_set(all_vars) diff --git a/tests/gpflux/models/test_bayesian_model.py b/tests/gpflux/models/test_bayesian_model.py index 60634ceb..368f8550 100644 --- a/tests/gpflux/models/test_bayesian_model.py +++ b/tests/gpflux/models/test_bayesian_model.py @@ -22,9 +22,7 @@ from gpflow.likelihoods import Gaussian from gpflux.layers import LatentVariableLayer, LikelihoodLayer -from tests.integration.test_latent_variable_integration import ( - build_gp_layers, -) # noqa: F401 +from tests.integration.test_latent_variable_integration import build_gp_layers # noqa: F401 tf.keras.backend.set_floatx("float64") diff --git a/tests/gpflux/models/test_deep_gp.py b/tests/gpflux/models/test_deep_gp.py index e5723cdf..f1ab2104 100644 --- a/tests/gpflux/models/test_deep_gp.py +++ b/tests/gpflux/models/test_deep_gp.py @@ -37,14 +37,10 @@ def build_deep_gp(input_dim, num_data): kernel_list = [RBF(), Matern12()] num_inducing = [25, 25] l1_kernel = construct_basic_kernel(kernels=kernel_list) - l1_inducing = construct_basic_inducing_variables( - num_inducing=num_inducing, input_dim=layers[0] - ) + l1_inducing = construct_basic_inducing_variables(num_inducing=num_inducing, input_dim=layers[0]) # 2. Pass in kernels, specificy output dims (shared hyperparams/variables) - l2_kernel = construct_basic_kernel( - kernels=RBF(), output_dim=layers[2], share_hyperparams=True - ) + l2_kernel = construct_basic_kernel(kernels=RBF(), output_dim=layers[2], share_hyperparams=True) l2_inducing = construct_basic_inducing_variables( num_inducing=25, input_dim=layers[1], share_variables=True ) @@ -65,9 +61,7 @@ def build_deep_gp(input_dim, num_data): return DeepGP(gp_layers, Gaussian(0.1)) -def train_deep_gp( - deep_gp, data, maxiter=MAXITER, plotter=None, plotter_interval=PLOTTER_INTERVAL -): +def train_deep_gp(deep_gp, data, maxiter=MAXITER, plotter=None, plotter_interval=PLOTTER_INTERVAL): optimizer = tf.optimizers.Adam() @tf.function(autograph=False) @@ -146,11 +140,7 @@ def run_demo(maxiter=int(80e3), plotter_interval=60): deep_gp = build_deep_gp(input_dim, num_data) fig, plotter = get_live_plotter(data, deep_gp) train_deep_gp( - deep_gp, - data, - maxiter=maxiter, - plotter=plotter, - plotter_interval=plotter_interval, + deep_gp, data, maxiter=maxiter, plotter=plotter, plotter_interval=plotter_interval, ) diff --git a/tests/gpflux/sampling/test_multioutput_sample.py b/tests/gpflux/sampling/test_multioutput_sample.py index 008aa96f..4ac41e9f 100644 --- a/tests/gpflux/sampling/test_multioutput_sample.py +++ b/tests/gpflux/sampling/test_multioutput_sample.py @@ -20,9 +20,7 @@ import gpflow from gpflow.config import default_float, default_jitter -from gpflux.layers.basis_functions.fourier_features import ( - MultiOutputRandomFourierFeaturesCosine, -) +from gpflux.layers.basis_functions.fourier_features import MultiOutputRandomFourierFeaturesCosine from gpflux.feature_decomposition_kernels import ( SharedMultiOutputKernelWithFeatureDecomposition, SeparateMultiOutputKernelWithFeatureDecomposition, @@ -52,9 +50,7 @@ def _shared_inducing_variable_fixture(): ind_var = gpflow.inducing_variables.InducingPoints(Z) - return gpflow.inducing_variables.SharedIndependentInducingVariables( - inducing_variable=ind_var - ) + return gpflow.inducing_variables.SharedIndependentInducingVariables(inducing_variable=ind_var) @pytest.fixture(name="separate_inducing_variable") @@ -99,14 +95,10 @@ def test_shared_wilson_efficient_sample(base_kernel, shared_inducing_variable, w """Smoke and consistency test for efficient sampling using Wilson""" kernel = _get_shared_kernel(base_kernel) - eigenfunctions = MultiOutputRandomFourierFeaturesCosine( - kernel, 100, dtype=default_float() - ) + eigenfunctions = MultiOutputRandomFourierFeaturesCosine(kernel, 100, dtype=default_float()) eigenvalues = np.ones((2, 100, 1), dtype=default_float()) # To apply Wilson sampling we require the features and eigenvalues of the kernel - kernel2 = SharedMultiOutputKernelWithFeatureDecomposition( - kernel, eigenfunctions, eigenvalues - ) + kernel2 = SharedMultiOutputKernelWithFeatureDecomposition(kernel, eigenfunctions, eigenvalues) q_mu, q_sqrt = _get_shared_qmu_qsqrt(kernel, shared_inducing_variable) sample_func = efficient_sample( @@ -125,20 +117,14 @@ def test_shared_wilson_efficient_sample(base_kernel, shared_inducing_variable, w ) -def test_separate_wilson_efficient_sample( - base_kernel, separate_inducing_variable, whiten -): +def test_separate_wilson_efficient_sample(base_kernel, separate_inducing_variable, whiten): """Smoke and consistency test for efficient sampling using Wilson""" kernel = _get_separate_kernel(base_kernel) - eigenfunctions = MultiOutputRandomFourierFeaturesCosine( - kernel, 100, dtype=default_float() - ) + eigenfunctions = MultiOutputRandomFourierFeaturesCosine(kernel, 100, dtype=default_float()) eigenvalues = np.ones((2, 100, 1), dtype=default_float()) # To apply Wilson sampling we require the features and eigenvalues of the kernel - kernel2 = SeparateMultiOutputKernelWithFeatureDecomposition( - kernel, eigenfunctions, eigenvalues - ) + kernel2 = SeparateMultiOutputKernelWithFeatureDecomposition(kernel, eigenfunctions, eigenvalues) q_mu, q_sqrt = _get_separate_qmu_qsqrt(kernel, separate_inducing_variable) sample_func = efficient_sample( diff --git a/tests/gpflux/sampling/test_sample.py b/tests/gpflux/sampling/test_sample.py index bafc3e09..e8e0ef19 100644 --- a/tests/gpflux/sampling/test_sample.py +++ b/tests/gpflux/sampling/test_sample.py @@ -21,9 +21,7 @@ from gpflow.config import default_float, default_jitter from gpflux.layers.basis_functions.fourier_features import RandomFourierFeaturesCosine -from gpflux.sampling.kernel_with_feature_decomposition import ( - KernelWithFeatureDecomposition, -) +from gpflux.sampling.kernel_with_feature_decomposition import KernelWithFeatureDecomposition from gpflux.sampling.sample import Sample, efficient_sample @@ -126,6 +124,4 @@ def test_adding_sample_and_mean_function(): sample_and_mean_function = sample + mean_function - np.testing.assert_array_almost_equal( - sample_and_mean_function(X), sample(X) + mean_function(X) - ) + np.testing.assert_array_almost_equal(sample_and_mean_function(X), sample(X) + mean_function(X)) diff --git a/tests/gpflux/test_callbacks.py b/tests/gpflux/test_callbacks.py index 7dc9eaaa..dafaa1c1 100644 --- a/tests/gpflux/test_callbacks.py +++ b/tests/gpflux/test_callbacks.py @@ -98,9 +98,7 @@ def test_tensorboard_callback(tmp_path, model_and_loss, data, update_freq): ] history = model.fit(dataset, epochs=CONFIG.num_epochs, callbacks=callbacks) - tb_files_pattern = ( - f"{tmp_path}/train/events.out.tfevents*" # notice the glob pattern - ) + tb_files_pattern = f"{tmp_path}/train/events.out.tfevents*" # notice the glob pattern # Maps tensorboard tags (e.g. kernel.variance) to list containing # their successive values during optimisation. @@ -150,9 +148,7 @@ def test_tensorboard_callback(tmp_path, model_and_loss, data, update_freq): assert len(record) == CONFIG.num_epochs # Check that recorded TensorBoard loss matches Keras history - np.testing.assert_array_almost_equal( - records["epoch_loss"], history.history["loss"], decimal=5 - ) + np.testing.assert_array_almost_equal(records["epoch_loss"], history.history["loss"], decimal=5) # Check correctness of fixed likelihood variance tag = ("layers[3].likelihood.variance",) diff --git a/tests/gpflux/test_ci_utils.py b/tests/gpflux/test_ci_utils.py index f3cb66a9..2f200771 100644 --- a/tests/gpflux/test_ci_utils.py +++ b/tests/gpflux/test_ci_utils.py @@ -32,8 +32,7 @@ def test_is_continuous_integration(os_environ, is_ci): @pytest.mark.parametrize( - "is_ci, args, expected_result", - [(True, (13,), 2), (True, (13, 5), 5), (False, (13,), 13),], + "is_ci, args, expected_result", [(True, (13,), 2), (True, (13, 5), 5), (False, (13,), 13),], ) def test_notebook_niter(is_ci, args, expected_result): with mock_ci_state(is_ci): diff --git a/tests/gpflux/test_helpers.py b/tests/gpflux/test_helpers.py index a503f0b0..093234db 100644 --- a/tests/gpflux/test_helpers.py +++ b/tests/gpflux/test_helpers.py @@ -131,11 +131,7 @@ def test_construct_inducing_shared_independent_duplicates(z_init): z_init = None moiv = construct_basic_inducing_variables( - num_inducing, - input_dim, - output_dim=output_dim, - share_variables=True, - z_init=z_init, + num_inducing, input_dim, output_dim=output_dim, share_variables=True, z_init=z_init, ) assert isinstance(moiv, SharedIndependentInducingVariables) @@ -169,9 +165,7 @@ def test_construct_gp_layer(): # kernel assert isinstance(layer.kernel, SharedIndependent) assert isinstance(layer.kernel.kernel, SquaredExponential) - assert ( - len(layer.kernel.kernel.lengthscales.numpy()) == input_dim - ), "expected ARD kernel" + assert len(layer.kernel.kernel.lengthscales.numpy()) == input_dim, "expected ARD kernel" # inducing variable assert isinstance(layer.inducing_variable, SharedIndependentInducingVariables) @@ -200,9 +194,7 @@ class PopulatedClass: overwritten = "overwritten" assert PopulatedClass.bar != overwritten - result = make_dataclass_from_class( - BlankDataclass, PopulatedClass(), bar=overwritten - ) + result = make_dataclass_from_class(BlankDataclass, PopulatedClass(), bar=overwritten) assert isinstance(result, BlankDataclass) assert result.foo == PopulatedClass.foo assert result.bar == overwritten diff --git a/tests/gpflux/test_runtime_checks.py b/tests/gpflux/test_runtime_checks.py index a1bc8e0a..ddfe2fa2 100644 --- a/tests/gpflux/test_runtime_checks.py +++ b/tests/gpflux/test_runtime_checks.py @@ -31,20 +31,15 @@ def make_kernels(num_latent_k): return [ construct_basic_kernel([Matern52() for _ in range(num_latent_k)]), - construct_basic_kernel( - Matern52(), output_dim=num_latent_k, share_hyperparams=False - ), - construct_basic_kernel( - Matern52(), output_dim=num_latent_k, share_hyperparams=True - ), + construct_basic_kernel(Matern52(), output_dim=num_latent_k, share_hyperparams=False), + construct_basic_kernel(Matern52(), output_dim=num_latent_k, share_hyperparams=True), ] def make_inducing_variables(num_latent_iv): return [ construct_basic_inducing_variables( - num_inducing=[num_inducing for _ in range(num_latent_iv)], - input_dim=input_dim, + num_inducing=[num_inducing for _ in range(num_latent_iv)], input_dim=input_dim, ), construct_basic_inducing_variables( num_inducing=num_inducing, input_dim=input_dim, output_dim=num_latent_iv diff --git a/tests/integration/test_compilation.py b/tests/integration/test_compilation.py index 844eca43..04abf9f2 100644 --- a/tests/integration/test_compilation.py +++ b/tests/integration/test_compilation.py @@ -153,9 +153,7 @@ def test_model_compilation(deep_gp_model_builder): if loss is None: # build_gpflux_deep_gp test_batch_dict = next(iter(train_dataset)) - test_batch_dict["targets"] = np.full_like( - test_batch_dict["targets"].shape, np.nan - ) + test_batch_dict["targets"] = np.full_like(test_batch_dict["targets"].shape, np.nan) output = deep_gp_model(test_batch_dict) mean, var = output.f_mean, output.f_var else: @@ -211,9 +209,7 @@ def objective(data_minibatch): objective = tf.function(objective) def optimization_step(data_minibatch): - optimizer.minimize( - lambda: objective(data_minibatch), deep_gp_model.trainable_weights - ) + optimizer.minimize(lambda: objective(data_minibatch), deep_gp_model.trainable_weights) if use_tf_function: optimization_step = tf.function(optimization_step) @@ -229,9 +225,7 @@ def optimization_step(data_minibatch): # Check outputs if loss is None: # build_gpflux_deep_gp test_batch_dict = next(iter(train_dataset)) - test_batch_dict["targets"] = np.full_like( - test_batch_dict["targets"].shape, np.nan - ) + test_batch_dict["targets"] = np.full_like(test_batch_dict["targets"].shape, np.nan) output = deep_gp_model(test_batch_dict) mean, var = output.f_mean, output.f_var else: diff --git a/tests/integration/test_svgp_equivalence.py b/tests/integration/test_svgp_equivalence.py index f92d1618..c7550e4e 100644 --- a/tests/integration/test_svgp_equivalence.py +++ b/tests/integration/test_svgp_equivalence.py @@ -37,9 +37,7 @@ class LogPrior_ELBO_SVGP(gpflow.models.SVGP): """ def elbo(self, data: RegressionData) -> tf.Tensor: - loss_prior = tf.add_n( - [p.log_prior_density() for p in self.trainable_parameters] - ) + loss_prior = tf.add_n([p.log_prior_density() for p in self.trainable_parameters]) return super().elbo(data) + loss_prior @@ -80,12 +78,8 @@ def create_gpflow_svgp(kernel, likelihood, inducing_variable): def create_gp_layer(kernel, inducing_variable, num_data): mok = gpflow.kernels.SharedIndependent(kernel, output_dim=1) - moiv = gpflow.inducing_variables.SharedIndependentInducingVariables( - inducing_variable - ) - return gpflux.layers.GPLayer( - mok, moiv, num_data, mean_function=gpflow.mean_functions.Zero() - ) + moiv = gpflow.inducing_variables.SharedIndependentInducingVariables(inducing_variable) + return gpflux.layers.GPLayer(mok, moiv, num_data, mean_function=gpflow.mean_functions.Zero()) def create_gpflux_sldgp(kernel, likelihood, inducing_variable, num_data): @@ -99,9 +93,7 @@ def create_gpflux_sequential_and_loss(kernel, likelihood, inducing_variable, num gp_layer = create_gp_layer(kernel, inducing_variable, num_data) loss = gpflux.losses.LikelihoodLoss(likelihood) likelihood_container = gpflux.layers.TrackableLayer() - likelihood_container.likelihood = ( - likelihood # for likelihood to be discovered as trainable - ) + likelihood_container.likelihood = likelihood # for likelihood to be discovered as trainable model = tf.keras.Sequential([gp_layer, likelihood_container]) return model, loss @@ -123,9 +115,7 @@ def training_loss(): return -model.elbo(data) opt = gpflow.optimizers.Scipy() - opt.minimize( - training_loss, model.trainable_variables, options=dict(maxiter=maxiter) - ) + opt.minimize(training_loss, model.trainable_variables, options=dict(maxiter=maxiter)) def assert_equivalence(svgp, sldgp, data, **tol_kws): @@ -144,10 +134,7 @@ def test_svgp_equivalence_after_assign(): def fit_adam( - model: Union[gpflow.models.SVGP, gpflux.models.DeepGP], - data, - maxiter, - adam_learning_rate=0.01, + model: Union[gpflow.models.SVGP, gpflux.models.DeepGP], data, maxiter, adam_learning_rate=0.01, ): X, Y = data num_data = len(X) @@ -186,13 +173,7 @@ def keras_fit_adam(sldgp: gpflux.models.DeepGP, data, maxiter, adam_learning_rat def _keras_fit_natgrad( - base_model, - dataset, - maxiter, - adam_learning_rate=0.01, - gamma=1.0, - loss=None, - run_eagerly=None, + base_model, dataset, maxiter, adam_learning_rate=0.01, gamma=1.0, loss=None, run_eagerly=None, ): model = gpflux.optimization.NatGradWrapper(base_model) model.natgrad_layers = True # Shortcut to apply natural gradients to all layers @@ -261,9 +242,7 @@ def optimization_step(): variational_grads, other_grads = tape.gradient( loss, (variational_params_vars, hyperparam_variables) ) - for (q_mu_grad, q_sqrt_grad), (q_mu, q_sqrt) in zip( - variational_grads, variational_params - ): + for (q_mu_grad, q_sqrt_grad), (q_mu, q_sqrt) in zip(variational_grads, variational_params): natgrad._natgrad_apply_gradients(q_mu_grad, q_sqrt_grad, q_mu, q_sqrt) adam.apply_gradients(zip(other_grads, hyperparam_variables)) @@ -294,14 +273,9 @@ def test_svgp_equivalence_with_sldgp(svgp_fitter, sldgp_fitter, maxiter=20): @pytest.mark.parametrize( "svgp_fitter, keras_fitter, tol_kw", - [ - (fit_adam, _keras_fit_adam, {}), - (fit_natgrad, _keras_fit_natgrad, dict(atol=1e-8)), - ], + [(fit_adam, _keras_fit_adam, {}), (fit_natgrad, _keras_fit_natgrad, dict(atol=1e-8)),], ) -def test_svgp_equivalence_with_keras_sequential( - svgp_fitter, keras_fitter, tol_kw, maxiter=10 -): +def test_svgp_equivalence_with_keras_sequential(svgp_fitter, keras_fitter, tol_kw, maxiter=10): X, Y = data = load_data() svgp = create_gpflow_svgp(*make_kernel_likelihood_iv()) @@ -313,9 +287,7 @@ def test_svgp_equivalence_with_keras_sequential( keras_fitter(keras_model, make_dataset(data, as_dict=False), maxiter, loss=loss) f_dist = keras_model(X) - np.testing.assert_allclose( - (f_dist.loc, f_dist.scale.diag ** 2), svgp.predict_f(X), **tol_kw - ) + np.testing.assert_allclose((f_dist.loc, f_dist.scale.diag ** 2), svgp.predict_f(X), **tol_kw) def run_gpflux_sldgp(data, optimizer, maxiter): diff --git a/tests/test_notebooks.py b/tests/test_notebooks.py index bfee5f68..a3acab13 100644 --- a/tests/test_notebooks.py +++ b/tests/test_notebooks.py @@ -62,9 +62,7 @@ def notebook_blacklisted(nb): def _preproc(): pythonkernel = "python" + str(sys.version_info[0]) - return ExecutePreprocessor( - timeout=300, kernel_name=pythonkernel, interrupt_on_timeout=True - ) + return ExecutePreprocessor(timeout=300, kernel_name=pythonkernel, interrupt_on_timeout=True) def _exec_notebook(notebook_filename): @@ -86,6 +84,4 @@ def test_notebook(notebook_file): def test_has_notebooks(): - assert ( - len(get_notebooks()) >= 2 - ), "there are probably some notebooks that were not discovered" + assert len(get_notebooks()) >= 2, "there are probably some notebooks that were not discovered" From 116a4403f3794d61ea74f079ae62d757699fbce6 Mon Sep 17 00:00:00 2001 From: SebastianPopescu Date: Wed, 21 Sep 2022 13:54:25 +0100 Subject: [PATCH 06/25] make format invoked --- gpflux/__init__.py | 11 +---------- gpflux/architectures/__init__.py | 5 +---- gpflux/feature_decomposition_kernels/__init__.py | 9 +++------ .../kernel_with_feature_decomposition.py | 3 +-- .../multioutput/__init__.py | 4 ++-- .../kernel_with_feature_decomposition.py | 2 +- gpflux/layers/__init__.py | 5 +---- .../basis_functions/fourier_features/__init__.py | 9 ++++----- .../basis_functions/fourier_features/base.py | 1 + .../fourier_features/multioutput/base.py | 1 + gpflux/sampling/__init__.py | 2 +- gpflux/sampling/multioutput/sample.py | 16 ++++++---------- gpflux/sampling/sample.py | 5 +---- .../test_multioutput_orthogonal_ff.py | 15 +++++++-------- .../fourier_features/test_multioutput_rff.py | 12 ++++++------ .../test_multioutput_rff_cosine.py | 12 ++++++------ tests/gpflux/sampling/test_multioutput_sample.py | 4 ++-- 17 files changed, 45 insertions(+), 71 deletions(-) diff --git a/gpflux/__init__.py b/gpflux/__init__.py index ccf2d234..9e3d558b 100644 --- a/gpflux/__init__.py +++ b/gpflux/__init__.py @@ -17,14 +17,5 @@ The library root. See :mod:`~gpflux.models.deep_gp.DeepGP` for the core Deep GP model, which is built out of different GP :mod:`~gpflux.layers`. """ -from gpflux import ( - callbacks, - encoders, - helpers, - layers, - losses, - models, - optimization, - sampling, -) +from gpflux import callbacks, encoders, helpers, layers, losses, models, optimization, sampling from gpflux.version import __version__ diff --git a/gpflux/architectures/__init__.py b/gpflux/architectures/__init__.py index bb81d50a..d2ab53fe 100644 --- a/gpflux/architectures/__init__.py +++ b/gpflux/architectures/__init__.py @@ -1,7 +1,4 @@ """ Pre-specified architectures """ -from gpflux.architectures.constant_input_dim_deep_gp import ( - Config, - build_constant_input_dim_deep_gp, -) +from gpflux.architectures.constant_input_dim_deep_gp import Config, build_constant_input_dim_deep_gp diff --git a/gpflux/feature_decomposition_kernels/__init__.py b/gpflux/feature_decomposition_kernels/__init__.py index ffbab0aa..b2dff876 100644 --- a/gpflux/feature_decomposition_kernels/__init__.py +++ b/gpflux/feature_decomposition_kernels/__init__.py @@ -1,11 +1,8 @@ -from .kernel_with_feature_decomposition import ( - _ApproximateKernel, - KernelWithFeatureDecomposition, -) +from .kernel_with_feature_decomposition import KernelWithFeatureDecomposition, _ApproximateKernel from .multioutput import ( - _MultiOutputApproximateKernel, - SharedMultiOutputKernelWithFeatureDecomposition, SeparateMultiOutputKernelWithFeatureDecomposition, + SharedMultiOutputKernelWithFeatureDecomposition, + _MultiOutputApproximateKernel, ) __all__ = [ diff --git a/gpflux/feature_decomposition_kernels/kernel_with_feature_decomposition.py b/gpflux/feature_decomposition_kernels/kernel_with_feature_decomposition.py index 5486cd76..159d5b1a 100644 --- a/gpflux/feature_decomposition_kernels/kernel_with_feature_decomposition.py +++ b/gpflux/feature_decomposition_kernels/kernel_with_feature_decomposition.py @@ -28,14 +28,13 @@ <../../../../notebooks/weight_space_approximation.ipynb>`_ for an in-depth overview. """ -from typing import List, Optional, Union, Tuple +from typing import List, Optional, Tuple, Union import tensorflow as tf import gpflow from gpflow.base import TensorType - NoneType = type(None) diff --git a/gpflux/feature_decomposition_kernels/multioutput/__init__.py b/gpflux/feature_decomposition_kernels/multioutput/__init__.py index 8c362f4d..9b419a1c 100644 --- a/gpflux/feature_decomposition_kernels/multioutput/__init__.py +++ b/gpflux/feature_decomposition_kernels/multioutput/__init__.py @@ -1,7 +1,7 @@ from .kernel_with_feature_decomposition import ( - _MultiOutputApproximateKernel, - SharedMultiOutputKernelWithFeatureDecomposition, SeparateMultiOutputKernelWithFeatureDecomposition, + SharedMultiOutputKernelWithFeatureDecomposition, + _MultiOutputApproximateKernel, ) __all__ = [ diff --git a/gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py b/gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py index 2850c46c..f7d1fcf5 100644 --- a/gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py +++ b/gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py @@ -28,7 +28,7 @@ <../../../../notebooks/weight_space_approximation.ipynb>`_ for an in-depth overview. """ -from typing import Any, List, Optional, Union, Tuple +from typing import Any, List, Optional, Tuple, Union import tensorflow as tf diff --git a/gpflux/layers/__init__.py b/gpflux/layers/__init__.py index 2c99783f..34f7e073 100644 --- a/gpflux/layers/__init__.py +++ b/gpflux/layers/__init__.py @@ -19,9 +19,6 @@ from gpflux.layers import basis_functions from gpflux.layers.bayesian_dense_layer import BayesianDenseLayer from gpflux.layers.gp_layer import GPLayer -from gpflux.layers.latent_variable_layer import ( - LatentVariableLayer, - LayerWithObservations, -) +from gpflux.layers.latent_variable_layer import LatentVariableLayer, LayerWithObservations from gpflux.layers.likelihood_layer import LikelihoodLayer from gpflux.layers.trackable_layer import TrackableLayer diff --git a/gpflux/layers/basis_functions/fourier_features/__init__.py b/gpflux/layers/basis_functions/fourier_features/__init__.py index 120d7240..064fc39a 100644 --- a/gpflux/layers/basis_functions/fourier_features/__init__.py +++ b/gpflux/layers/basis_functions/fourier_features/__init__.py @@ -18,6 +18,10 @@ :class:`gpflux.sampling.KernelWithFeatureDecomposition` """ +from gpflux.layers.basis_functions.fourier_features.multioutput.random import ( + MultiOutputRandomFourierFeatures, + MultiOutputRandomFourierFeaturesCosine, +) from gpflux.layers.basis_functions.fourier_features.quadrature import QuadratureFourierFeatures from gpflux.layers.basis_functions.fourier_features.random import ( OrthogonalRandomFeatures, @@ -25,11 +29,6 @@ RandomFourierFeaturesCosine, ) -from gpflux.layers.basis_functions.fourier_features.multioutput.random import ( - MultiOutputRandomFourierFeatures, - MultiOutputRandomFourierFeaturesCosine, -) - __all__ = [ "QuadratureFourierFeatures", "OrthogonalRandomFeatures", diff --git a/gpflux/layers/basis_functions/fourier_features/base.py b/gpflux/layers/basis_functions/fourier_features/base.py index d431d052..503a6a51 100644 --- a/gpflux/layers/basis_functions/fourier_features/base.py +++ b/gpflux/layers/basis_functions/fourier_features/base.py @@ -22,6 +22,7 @@ import gpflow from gpflow.base import TensorType + from gpflux.types import ShapeType diff --git a/gpflux/layers/basis_functions/fourier_features/multioutput/base.py b/gpflux/layers/basis_functions/fourier_features/multioutput/base.py index f8505315..581760f0 100644 --- a/gpflux/layers/basis_functions/fourier_features/multioutput/base.py +++ b/gpflux/layers/basis_functions/fourier_features/multioutput/base.py @@ -23,6 +23,7 @@ import gpflow from gpflow.base import TensorType + from gpflux.types import ShapeType diff --git a/gpflux/sampling/__init__.py b/gpflux/sampling/__init__.py index c6772317..4c082df2 100644 --- a/gpflux/sampling/__init__.py +++ b/gpflux/sampling/__init__.py @@ -17,7 +17,7 @@ This module enables you to sample from (Deep) GPs efficiently and consistently. """ -from . import sample, multioutput +from . import multioutput, sample from .dispatch import efficient_sample __all__ = [ diff --git a/gpflux/sampling/multioutput/sample.py b/gpflux/sampling/multioutput/sample.py index 168b11c9..613fd31e 100644 --- a/gpflux/sampling/multioutput/sample.py +++ b/gpflux/sampling/multioutput/sample.py @@ -28,24 +28,20 @@ from gpflow.covariances import Kuf, Kuu from gpflow.inducing_variables import ( MultioutputInducingVariables, - SharedIndependentInducingVariables, SeparateIndependentInducingVariables, + SharedIndependentInducingVariables, ) -from gpflow.kernels import ( - Kernel, - SeparateIndependent, - SharedIndependent, - MultioutputKernel, -) +from gpflow.kernels import Kernel, MultioutputKernel, SeparateIndependent, SharedIndependent from gpflow.utilities import Dispatcher -from gpflux.math import compute_A_inv_b from gpflux.feature_decomposition_kernels import ( - SharedMultiOutputKernelWithFeatureDecomposition, SeparateMultiOutputKernelWithFeatureDecomposition, + SharedMultiOutputKernelWithFeatureDecomposition, ) -from ..sample import Sample +from gpflux.math import compute_A_inv_b + from ..dispatch import efficient_sample +from ..sample import Sample @efficient_sample.register( diff --git a/gpflux/sampling/sample.py b/gpflux/sampling/sample.py index cfca4545..060c58e1 100644 --- a/gpflux/sampling/sample.py +++ b/gpflux/sampling/sample.py @@ -29,11 +29,8 @@ from gpflow.kernels import Kernel, SeparateIndependent, SharedIndependent from gpflow.utilities import Dispatcher +from gpflux.feature_decomposition_kernels import KernelWithFeatureDecomposition, _ApproximateKernel from gpflux.math import compute_A_inv_b -from gpflux.feature_decomposition_kernels import ( - KernelWithFeatureDecomposition, - _ApproximateKernel, -) from gpflux.sampling.utils import draw_conditional_sample from .dispatch import efficient_sample diff --git a/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_orthogonal_ff.py b/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_orthogonal_ff.py index 6122b31d..70f49f13 100644 --- a/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_orthogonal_ff.py +++ b/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_orthogonal_ff.py @@ -20,23 +20,22 @@ from tensorflow.python.keras.utils.kernelized_utils import inner_product import gpflow +from gpflow.kernels import SeparateIndependent, SharedIndependent -from gpflow.kernels import SharedIndependent, SeparateIndependent from gpflux import feature_decomposition_kernels +from gpflux.feature_decomposition_kernels.multioutput import ( + SeparateMultiOutputKernelWithFeatureDecomposition, + SharedMultiOutputKernelWithFeatureDecomposition, +) from gpflux.layers.basis_functions.fourier_features import ( MultiOutputRandomFourierFeatures, MultiOutputRandomFourierFeaturesCosine, ) -from gpflux.layers.basis_functions.fourier_features.random.orthogonal import ORF_SUPPORTED_KERNELS from gpflux.layers.basis_functions.fourier_features.multioutput.random import ( - MultiOutputRandomFourierFeatures, MultiOutputOrthogonalRandomFeatures, + MultiOutputRandomFourierFeatures, ) - -from gpflux.feature_decomposition_kernels.multioutput import ( - SharedMultiOutputKernelWithFeatureDecomposition, - SeparateMultiOutputKernelWithFeatureDecomposition, -) +from gpflux.layers.basis_functions.fourier_features.random.orthogonal import ORF_SUPPORTED_KERNELS from tests.conftest import skip_serialization_tests diff --git a/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff.py b/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff.py index ae85f19e..0f28f729 100644 --- a/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff.py +++ b/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff.py @@ -20,21 +20,21 @@ from tensorflow.python.keras.utils.kernelized_utils import inner_product import gpflow +from gpflow.kernels import SeparateIndependent, SharedIndependent -from gpflow.kernels import SharedIndependent, SeparateIndependent from gpflux import feature_decomposition_kernels +from gpflux.feature_decomposition_kernels.multioutput import ( + SeparateMultiOutputKernelWithFeatureDecomposition, + SharedMultiOutputKernelWithFeatureDecomposition, +) from gpflux.layers.basis_functions.fourier_features import ( MultiOutputRandomFourierFeatures, MultiOutputRandomFourierFeaturesCosine, ) -from gpflux.layers.basis_functions.fourier_features.random.base import RFF_SUPPORTED_KERNELS from gpflux.layers.basis_functions.fourier_features.multioutput.random import ( MultiOutputRandomFourierFeatures, ) -from gpflux.feature_decomposition_kernels.multioutput import ( - SharedMultiOutputKernelWithFeatureDecomposition, - SeparateMultiOutputKernelWithFeatureDecomposition, -) +from gpflux.layers.basis_functions.fourier_features.random.base import RFF_SUPPORTED_KERNELS from tests.conftest import skip_serialization_tests diff --git a/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff_cosine.py b/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff_cosine.py index 41f898e0..00bd70d3 100644 --- a/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff_cosine.py +++ b/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff_cosine.py @@ -20,21 +20,21 @@ from tensorflow.python.keras.utils.kernelized_utils import inner_product import gpflow +from gpflow.kernels import SeparateIndependent, SharedIndependent -from gpflow.kernels import SharedIndependent, SeparateIndependent from gpflux import feature_decomposition_kernels +from gpflux.feature_decomposition_kernels.multioutput import ( + SeparateMultiOutputKernelWithFeatureDecomposition, + SharedMultiOutputKernelWithFeatureDecomposition, +) from gpflux.layers.basis_functions.fourier_features import ( MultiOutputRandomFourierFeatures, MultiOutputRandomFourierFeaturesCosine, ) -from gpflux.layers.basis_functions.fourier_features.random.base import RFF_SUPPORTED_KERNELS from gpflux.layers.basis_functions.fourier_features.multioutput.random import ( MultiOutputRandomFourierFeatures, ) -from gpflux.feature_decomposition_kernels.multioutput import ( - SharedMultiOutputKernelWithFeatureDecomposition, - SeparateMultiOutputKernelWithFeatureDecomposition, -) +from gpflux.layers.basis_functions.fourier_features.random.base import RFF_SUPPORTED_KERNELS from tests.conftest import skip_serialization_tests diff --git a/tests/gpflux/sampling/test_multioutput_sample.py b/tests/gpflux/sampling/test_multioutput_sample.py index 4ac41e9f..175ab9ff 100644 --- a/tests/gpflux/sampling/test_multioutput_sample.py +++ b/tests/gpflux/sampling/test_multioutput_sample.py @@ -20,11 +20,11 @@ import gpflow from gpflow.config import default_float, default_jitter -from gpflux.layers.basis_functions.fourier_features import MultiOutputRandomFourierFeaturesCosine from gpflux.feature_decomposition_kernels import ( - SharedMultiOutputKernelWithFeatureDecomposition, SeparateMultiOutputKernelWithFeatureDecomposition, + SharedMultiOutputKernelWithFeatureDecomposition, ) +from gpflux.layers.basis_functions.fourier_features import MultiOutputRandomFourierFeaturesCosine from gpflux.sampling.sample import Sample, efficient_sample From e7a7fc30d0cafae19f453b21f16fd83ddd1e5a2c Mon Sep 17 00:00:00 2001 From: SebastianPopescu Date: Wed, 21 Sep 2022 17:53:42 +0100 Subject: [PATCH 07/25] black should be finally working now --- docs/notebooks/benchmarks.py | 5 +- docs/notebooks/deep_gp_samples.py | 4 +- .../notebooks/efficient_posterior_sampling.py | 22 +++++-- docs/notebooks/efficient_sampling.py | 12 +++- docs/notebooks/gpflux_features.py | 11 +++- docs/notebooks/keras_integration.py | 22 +++++-- .../multi_output_efficient_sampling.py | 6 +- ...multi_output_weight_space_approximation.py | 21 +++++-- docs/notebooks/weight_space_approximation.py | 4 +- .../constant_input_dim_deep_gp.py | 6 +- gpflux/callbacks.py | 6 +- .../directly_parameterized_encoder.py | 6 +- gpflux/experiment_support/plotting.py | 5 +- .../kernel_with_feature_decomposition.py | 8 ++- .../kernel_with_feature_decomposition.py | 26 +++++++-- gpflux/helpers.py | 6 +- .../multioutput/random/base.py | 14 ++++- gpflux/layers/bayesian_dense_layer.py | 15 ++++- gpflux/layers/gp_layer.py | 16 +++++- gpflux/layers/latent_variable_layer.py | 9 ++- gpflux/models/deep_gp.py | 14 ++++- gpflux/sampling/multioutput/sample.py | 6 +- gpflux/sampling/sample.py | 11 +++- tests/conftest.py | 4 +- .../fourier_features/test_multioutput_rff.py | 6 +- .../test_multioutput_rff_cosine.py | 6 +- .../fourier_features/test_random.py | 9 ++- .../layers/test_latent_variable_layer.py | 12 ++-- tests/gpflux/layers/test_trackable_layer.py | 57 ++++++++++++++++--- tests/gpflux/models/test_deep_gp.py | 6 +- .../sampling/test_multioutput_sample.py | 6 +- tests/gpflux/sampling/test_sample.py | 3 +- tests/gpflux/test_callbacks.py | 6 +- tests/gpflux/test_ci_utils.py | 7 ++- tests/gpflux/test_helpers.py | 6 +- tests/gpflux/test_math.py | 4 +- tests/gpflux/test_runtime_checks.py | 3 +- tests/integration/test_svgp_equivalence.py | 32 +++++++++-- 38 files changed, 336 insertions(+), 86 deletions(-) diff --git a/docs/notebooks/benchmarks.py b/docs/notebooks/benchmarks.py index a845f1e0..471ea6bd 100644 --- a/docs/notebooks/benchmarks.py +++ b/docs/notebooks/benchmarks.py @@ -41,7 +41,10 @@ # %% {"nbsphinx": "hidden"} table = df.groupby(["dataset", "model"]).agg( - {"split": "count", **{metric: ["mean", "std"] for metric in ["mse", "nlpd"]},} + { + "split": "count", + **{metric: ["mean", "std"] for metric in ["mse", "nlpd"]}, + } ) # %% [markdown] """ diff --git a/docs/notebooks/deep_gp_samples.py b/docs/notebooks/deep_gp_samples.py index 7a49790a..635c527a 100644 --- a/docs/notebooks/deep_gp_samples.py +++ b/docs/notebooks/deep_gp_samples.py @@ -55,7 +55,9 @@ # Layer 1 inducing_var1 = construct_basic_inducing_variables(M, D, D, share_variables=True, z_init=Z.copy()) kernel1 = construct_basic_kernel( - gpflow.kernels.SquaredExponential(lengthscales=0.15), output_dim=D, share_hyperparams=True, + gpflow.kernels.SquaredExponential(lengthscales=0.15), + output_dim=D, + share_hyperparams=True, ) layer1 = GPLayer(kernel1, inducing_var1, num_data, full_cov=True, num_samples=num_samples) diff --git a/docs/notebooks/efficient_posterior_sampling.py b/docs/notebooks/efficient_posterior_sampling.py index eaa4a373..bae0ba1a 100644 --- a/docs/notebooks/efficient_posterior_sampling.py +++ b/docs/notebooks/efficient_posterior_sampling.py @@ -266,7 +266,9 @@ def conduct_experiment(num_input_dimensions, num_train_samples, num_features): ) feature_coefficients = np.ones((num_features, 1), dtype=default_float()) approximate_kernel = KernelWithFeatureDecomposition( - kernel=None, feature_functions=feature_functions, feature_coefficients=feature_coefficients, + kernel=None, + feature_functions=feature_functions, + feature_coefficients=feature_coefficients, ) # create training data set and test points for evaluation @@ -300,7 +302,11 @@ def conduct_experiment(num_input_dimensions, num_train_samples, num_features): # identify mean and covariance of the analytic GPR posterior when using the weight space approximated kernel f_mean_weight, f_var_weight = compute_analytic_GP_predictions( - X=X, y=y, kernel=approximate_kernel, noise_variance=noise_variance, X_star=X_star, + X=X, + y=y, + kernel=approximate_kernel, + noise_variance=noise_variance, + X_star=X_star, ) # identify mean and covariance using the hybrid approximation @@ -464,7 +470,11 @@ def conduct_experiment_for_different_num_features(num_input_dimensions): for j in range(len(weight_results)): weight_result = weight_results[j] axs[i].fill_between( - num_train_samples, weight_result[0], weight_result[2], color=colors[j], alpha=0.1, + num_train_samples, + weight_result[0], + weight_result[2], + color=colors[j], + alpha=0.1, ) axs[i].plot(num_train_samples, weight_result[1], "o", color=colors[j]) axs[i].plot(num_train_samples, weight_result[1], color=colors[j], linewidth=0.5) @@ -475,7 +485,11 @@ def conduct_experiment_for_different_num_features(num_input_dimensions): for j in range(len(hybrid_results)): hybrid_result = hybrid_results[j] axs[i].fill_between( - num_train_samples, hybrid_result[0], hybrid_result[2], color=colors[j], alpha=0.1, + num_train_samples, + hybrid_result[0], + hybrid_result[2], + color=colors[j], + alpha=0.1, ) axs[i].plot(num_train_samples, hybrid_result[1], "o", color=colors[j]) axs[i].plot(num_train_samples, hybrid_result[1], color=colors[j], linewidth=0.5) diff --git a/docs/notebooks/efficient_sampling.py b/docs/notebooks/efficient_sampling.py index e8c3e781..fe85598c 100644 --- a/docs/notebooks/efficient_sampling.py +++ b/docs/notebooks/efficient_sampling.py @@ -107,12 +107,20 @@ callbacks = [ tf.keras.callbacks.ReduceLROnPlateau( - monitor="loss", patience=5, factor=0.95, verbose=0, min_lr=1e-6, + monitor="loss", + patience=5, + factor=0.95, + verbose=0, + min_lr=1e-6, ) ] history = model.fit( - {"inputs": X, "targets": Y}, batch_size=num_data, epochs=100, callbacks=callbacks, verbose=0, + {"inputs": X, "targets": Y}, + batch_size=num_data, + epochs=100, + callbacks=callbacks, + verbose=0, ) # %% [markdown] """ diff --git a/docs/notebooks/gpflux_features.py b/docs/notebooks/gpflux_features.py index 106faa88..c8ce8ea7 100644 --- a/docs/notebooks/gpflux_features.py +++ b/docs/notebooks/gpflux_features.py @@ -68,7 +68,10 @@ def motorcycle_data(): from gpflux.models import DeepGP config = Config( - num_inducing=25, inner_layer_qsqrt_factor=1e-5, likelihood_noise_variance=1e-2, whiten=True, + num_inducing=25, + inner_layer_qsqrt_factor=1e-5, + likelihood_noise_variance=1e-2, + whiten=True, ) deep_gp: DeepGP = build_constant_input_dim_deep_gp(X, num_layers=2, config=config) @@ -97,7 +100,11 @@ def motorcycle_data(): ] history = training_model.fit( - {"inputs": X, "targets": Y}, batch_size=12, epochs=200, callbacks=callbacks, verbose=0, + {"inputs": X, "targets": Y}, + batch_size=12, + epochs=200, + callbacks=callbacks, + verbose=0, ) # %% [markdown] diff --git a/docs/notebooks/keras_integration.py b/docs/notebooks/keras_integration.py index f4befd9a..47e54886 100644 --- a/docs/notebooks/keras_integration.py +++ b/docs/notebooks/keras_integration.py @@ -89,7 +89,11 @@ def create_model(model_class): callbacks = [ tf.keras.callbacks.ReduceLROnPlateau( - monitor="loss", patience=5, factor=0.95, verbose=1, min_lr=1e-6, + monitor="loss", + patience=5, + factor=0.95, + verbose=1, + min_lr=1e-6, ) ] @@ -97,7 +101,10 @@ def create_model(model_class): dgp_train.compile(tf.optimizers.Adam(learning_rate=0.1)) history = dgp_train.fit( - {"inputs": X, "targets": Y}, batch_size=batch_size, epochs=num_epochs, callbacks=callbacks, + {"inputs": X, "targets": Y}, + batch_size=batch_size, + epochs=num_epochs, + callbacks=callbacks, ) # %% @@ -105,7 +112,11 @@ def create_model(model_class): callbacks = [ tf.keras.callbacks.ReduceLROnPlateau( - monitor="loss", patience=5, factor=0.95, verbose=1, min_lr=1e-6, + monitor="loss", + patience=5, + factor=0.95, + verbose=1, + min_lr=1e-6, ) ] @@ -123,7 +134,10 @@ def create_model(model_class): ) history_natgrad = dgp_natgrad_train.fit( - {"inputs": X, "targets": Y}, batch_size=batch_size, epochs=num_epochs, callbacks=callbacks, + {"inputs": X, "targets": Y}, + batch_size=batch_size, + epochs=num_epochs, + callbacks=callbacks, ) # %% diff --git a/docs/notebooks/multi_output_efficient_sampling.py b/docs/notebooks/multi_output_efficient_sampling.py index 9ac669f6..253d604d 100644 --- a/docs/notebooks/multi_output_efficient_sampling.py +++ b/docs/notebooks/multi_output_efficient_sampling.py @@ -122,7 +122,11 @@ callbacks = [ tf.keras.callbacks.ReduceLROnPlateau( - monitor="loss", patience=5, factor=0.95, verbose=0, min_lr=1e-6, + monitor="loss", + patience=5, + factor=0.95, + verbose=0, + min_lr=1e-6, ) ] diff --git a/docs/notebooks/multi_output_weight_space_approximation.py b/docs/notebooks/multi_output_weight_space_approximation.py index 1586bd24..15dc56d6 100644 --- a/docs/notebooks/multi_output_weight_space_approximation.py +++ b/docs/notebooks/multi_output_weight_space_approximation.py @@ -128,7 +128,8 @@ class GPR_deprecated(GPModel, InternalDataTrainingLossMixin): """ @check_shapes( - "data[0]: [N, D]", "data[1]: [N, P]", + "data[0]: [N, D]", + "data[1]: [N, P]", ) def __init__( self, @@ -154,7 +155,9 @@ def __init__( def maximum_log_likelihood_objective(self) -> tf.Tensor: # type: ignore[override] return self.log_marginal_likelihood() - @check_shapes("return: []",) + @check_shapes( + "return: []", + ) def log_marginal_likelihood(self) -> tf.Tensor: r""" Computes the log marginal likelihood. @@ -369,7 +372,9 @@ def predict_f( print(X_star[experiment].shape) gpr_model = GPR_deprecated( - data=(X[experiment], y[experiment]), kernel=kernel, noise_variance=noise_variance, + data=(X[experiment], y[experiment]), + kernel=kernel, + noise_variance=noise_variance, ) # predict function mean and variance, and draw function samples (without observation noise)# @@ -399,7 +404,10 @@ def predict_f( ) for i in range(f_samples.shape[0]): axs[experiment, 0].plot( - X_star[experiment][..., 0], f_samples[i, ..., 0], color="orange", linewidth=0.2, + X_star[experiment][..., 0], + f_samples[i, ..., 0], + color="orange", + linewidth=0.2, ) axs[experiment, 0].plot(X_star[experiment][..., 0], f_mean[..., 0], color="orange") @@ -414,7 +422,10 @@ def predict_f( ) for i in range(f_samples.shape[0]): axs[experiment, 1].plot( - X_star[experiment][..., 0], f_samples[i, ..., 1], color="orange", linewidth=0.2, + X_star[experiment][..., 0], + f_samples[i, ..., 1], + color="orange", + linewidth=0.2, ) axs[experiment, 1].plot(X_star[experiment][..., 0], f_mean[..., 1], color="orange") diff --git a/docs/notebooks/weight_space_approximation.py b/docs/notebooks/weight_space_approximation.py index e53dbf18..55d8ac8d 100644 --- a/docs/notebooks/weight_space_approximation.py +++ b/docs/notebooks/weight_space_approximation.py @@ -275,7 +275,9 @@ def optimize_model_with_scipy(model): ) feature_coefficients = np.ones((number_of_features, 1), dtype=default_float()) kernel = KernelWithFeatureDecomposition( - kernel=None, feature_functions=feature_functions, feature_coefficients=feature_coefficients, + kernel=None, + feature_functions=feature_functions, + feature_coefficients=feature_coefficients, ) gpr_model = GPR( data=(X[experiment][..., None], y[experiment][..., None]), diff --git a/gpflux/architectures/constant_input_dim_deep_gp.py b/gpflux/architectures/constant_input_dim_deep_gp.py index 681a971c..2af04d83 100644 --- a/gpflux/architectures/constant_input_dim_deep_gp.py +++ b/gpflux/architectures/constant_input_dim_deep_gp.py @@ -155,7 +155,11 @@ def build_constant_input_dim_deep_gp(X: np.ndarray, num_layers: int, config: Con q_sqrt_scaling = config.inner_layer_qsqrt_factor layer = GPLayer( - kernel, inducing_var, num_data, mean_function=mean_function, name=f"gp_{i_layer}", + kernel, + inducing_var, + num_data, + mean_function=mean_function, + name=f"gp_{i_layer}", ) layer.q_sqrt.assign(layer.q_sqrt * q_sqrt_scaling) gp_layers.append(layer) diff --git a/gpflux/callbacks.py b/gpflux/callbacks.py index 5005abeb..1ce31776 100644 --- a/gpflux/callbacks.py +++ b/gpflux/callbacks.py @@ -60,7 +60,11 @@ def __init__( self, log_dir: str = "logs", *, - keywords_to_monitor: List[str] = ["kernel", "mean_function", "likelihood",], + keywords_to_monitor: List[str] = [ + "kernel", + "mean_function", + "likelihood", + ], max_size: int = 3, histogram_freq: int = 0, write_graph: bool = True, diff --git a/gpflux/encoders/directly_parameterized_encoder.py b/gpflux/encoders/directly_parameterized_encoder.py index 8a865b8c..a3418472 100644 --- a/gpflux/encoders/directly_parameterized_encoder.py +++ b/gpflux/encoders/directly_parameterized_encoder.py @@ -109,6 +109,10 @@ def call( """ if inputs is not None: tf.debugging.assert_shapes( - [(self.means, ["N", "W"]), (self.stds, ["N", "W"]), (inputs, ["N", "D"]),] + [ + (self.means, ["N", "W"]), + (self.stds, ["N", "W"]), + (inputs, ["N", "D"]), + ] ) return self.means, self.stds diff --git a/gpflux/experiment_support/plotting.py b/gpflux/experiment_support/plotting.py index f6ce52a8..87d7bff9 100644 --- a/gpflux/experiment_support/plotting.py +++ b/gpflux/experiment_support/plotting.py @@ -63,7 +63,10 @@ def plot_layer( def plot_layers( - X: TensorType, means: List[TensorType], covs: List[TensorType], samples: List[TensorType], + X: TensorType, + means: List[TensorType], + covs: List[TensorType], + samples: List[TensorType], ) -> None: # pragma: no cover L = len(means) fig, axes = plt.subplots(3, L, figsize=(L * 3.33, 10)) diff --git a/gpflux/feature_decomposition_kernels/kernel_with_feature_decomposition.py b/gpflux/feature_decomposition_kernels/kernel_with_feature_decomposition.py index 159d5b1a..0a64b8a8 100644 --- a/gpflux/feature_decomposition_kernels/kernel_with_feature_decomposition.py +++ b/gpflux/feature_decomposition_kernels/kernel_with_feature_decomposition.py @@ -50,7 +50,9 @@ class _ApproximateKernel(gpflow.kernels.Kernel): """ def __init__( - self, feature_functions: tf.keras.layers.Layer, feature_coefficients: TensorType, + self, + feature_functions: tf.keras.layers.Layer, + feature_coefficients: TensorType, ): r""" :param feature_functions: A Keras layer for which the call evaluates the @@ -71,7 +73,9 @@ def K(self, X: TensorType, X2: Optional[TensorType] = None) -> tf.Tensor: phi2 = self._feature_functions(X2) # [N2, L] r = tf.linalg.matmul( - phi, tf.linalg.matrix_transpose(self._feature_coefficients) * phi2, transpose_b=True, + phi, + tf.linalg.matrix_transpose(self._feature_coefficients) * phi2, + transpose_b=True, ) # [N, N2] N1, N2 = tf.shape(phi)[0], tf.shape(phi2)[0] diff --git a/gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py b/gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py index f7d1fcf5..4f4b6bfd 100644 --- a/gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py +++ b/gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py @@ -51,7 +51,9 @@ class _MultiOutputApproximateKernel(gpflow.kernels.MultioutputKernel): """ def __init__( - self, feature_functions: tf.keras.layers.Layer, feature_coefficients: TensorType, + self, + feature_functions: tf.keras.layers.Layer, + feature_coefficients: TensorType, ): r""" :param feature_functions: A Keras layer for which the call evaluates the @@ -74,7 +76,10 @@ def latent_kernels(self) -> Any: return self._feature_functions def K( - self, X: TensorType, X2: Optional[TensorType] = None, full_output_cov: bool = True, + self, + X: TensorType, + X2: Optional[TensorType] = None, + full_output_cov: bool = True, ) -> tf.Tensor: """Approximate the true kernel by an inner product between feature functions.""" phi = self._feature_functions(X) # [P, N, L] @@ -89,7 +94,9 @@ def K( phi2 = self._feature_functions(X2) # [P, N2, L] r = tf.linalg.matmul( - phi, tf.linalg.matrix_transpose(self._feature_coefficients) * phi2, transpose_b=True, + phi, + tf.linalg.matrix_transpose(self._feature_coefficients) * phi2, + transpose_b=True, ) # [P, N, N2] N1, N2 = tf.shape(phi)[1], tf.shape(phi2)[1] @@ -101,7 +108,8 @@ def K_diag(self, X: TensorType, full_output_cov: bool = False) -> tf.Tensor: phi_squared = self._feature_functions(X) ** 2 # [P, N, L] r = tf.reduce_sum( - phi_squared * tf.linalg.matrix_transpose(self._feature_coefficients), axis=-1, + phi_squared * tf.linalg.matrix_transpose(self._feature_coefficients), + axis=-1, ) # [P,N,] N = tf.shape(X)[0] @@ -243,7 +251,10 @@ def feature_coefficients(self) -> tf.Tensor: return self._feature_coefficients def K( - self, X: TensorType, X2: Optional[TensorType] = None, full_output_cov: bool = True, + self, + X: TensorType, + X2: Optional[TensorType] = None, + full_output_cov: bool = True, ) -> tf.Tensor: return self._kernel.K(X, X2, full_output_cov) @@ -382,7 +393,10 @@ def feature_coefficients(self) -> tf.Tensor: return self._feature_coefficients def K( - self, X: TensorType, X2: Optional[TensorType] = None, full_output_cov: bool = True, + self, + X: TensorType, + X2: Optional[TensorType] = None, + full_output_cov: bool = True, ) -> tf.Tensor: return self._kernel.K(X, X2, full_output_cov) diff --git a/gpflux/helpers.py b/gpflux/helpers.py index e0018408..45bfc6b6 100644 --- a/gpflux/helpers.py +++ b/gpflux/helpers.py @@ -242,7 +242,11 @@ def construct_gp_layer( base_kernel = kernel_class(lengthscales=np.full(input_dim, lengthscale)) kernel = construct_basic_kernel(base_kernel, output_dim=output_dim, share_hyperparams=True) inducing_variable = construct_basic_inducing_variables( - num_inducing, input_dim, output_dim=output_dim, share_variables=True, z_init=z_init, + num_inducing, + input_dim, + output_dim=output_dim, + share_variables=True, + z_init=z_init, ) gp_layer = GPLayer( kernel=kernel, diff --git a/gpflux/layers/basis_functions/fourier_features/multioutput/random/base.py b/gpflux/layers/basis_functions/fourier_features/multioutput/random/base.py index f27b41fb..251d6a62 100644 --- a/gpflux/layers/basis_functions/fourier_features/multioutput/random/base.py +++ b/gpflux/layers/basis_functions/fourier_features/multioutput/random/base.py @@ -201,7 +201,12 @@ def _compute_constant(self) -> tf.Tensor: if hasattr(self.kernel, "kernels"): _kernel_variance = tf.stack([ker.variance for ker in self.kernel.kernels], axis=0) - tf.ensure_shape(_kernel_variance, [self.kernel.num_latent_gps,]) + tf.ensure_shape( + _kernel_variance, + [ + self.kernel.num_latent_gps, + ], + ) else: _kernel_variance = self.kernel.kernel.variance @@ -283,7 +288,12 @@ def _compute_constant(self) -> tf.Tensor: if hasattr(self.kernel, "kernels"): _kernel_variance = tf.stack([ker.variance for ker in self.kernel.kernels], axis=0) - tf.ensure_shape(_kernel_variance, [self.kernel.num_latent_gps,]) + tf.ensure_shape( + _kernel_variance, + [ + self.kernel.num_latent_gps, + ], + ) else: _kernel_variance = self.kernel.kernel.variance diff --git a/gpflux/layers/bayesian_dense_layer.py b/gpflux/layers/bayesian_dense_layer.py index 9273babc..36c316a5 100644 --- a/gpflux/layers/bayesian_dense_layer.py +++ b/gpflux/layers/bayesian_dense_layer.py @@ -88,7 +88,10 @@ def __init__( assert w_mu.shape == ((input_dim + 1) * output_dim,) if w_sqrt is not None: if not is_mean_field: - assert w_sqrt.shape == ((input_dim + 1) * output_dim, (input_dim + 1) * output_dim,) + assert w_sqrt.shape == ( + (input_dim + 1) * output_dim, + (input_dim + 1) * output_dim, + ) else: assert w_sqrt.shape == ((input_dim + 1) * output_dim,) assert temperature > 0.0 @@ -137,7 +140,10 @@ def build(self, input_shape: ShapeType) -> None: self.initialize_variational_distribution() def predict_samples( - self, inputs: TensorType, *, num_samples: Optional[int] = None, + self, + inputs: TensorType, + *, + num_samples: Optional[int] = None, ) -> tf.Tensor: """ Samples from the approximate posterior at N test inputs, with input_dim = D, output_dim = Q. @@ -178,7 +184,10 @@ def call( """ The default behaviour upon calling this layer. """ - sample = self.predict_samples(inputs, num_samples=None,) + sample = self.predict_samples( + inputs, + num_samples=None, + ) # TF quirk: add_loss must add a tensor to compile if training: diff --git a/gpflux/layers/gp_layer.py b/gpflux/layers/gp_layer.py index 1f26380a..04ff5f98 100644 --- a/gpflux/layers/gp_layer.py +++ b/gpflux/layers/gp_layer.py @@ -228,7 +228,11 @@ def __init__( self.num_samples = num_samples def predict( - self, inputs: TensorType, *, full_cov: bool = False, full_output_cov: bool = False, + self, + inputs: TensorType, + *, + full_cov: bool = False, + full_output_cov: bool = False, ) -> Tuple[tf.Tensor, tf.Tensor]: """ Make a prediction at N test inputs for the Q outputs of this layer, @@ -307,7 +311,11 @@ def prior_kl(self) -> tf.Tensor: :attr:`whiten`\ ed representation, returns ``KL[q(v)∥p(v)]``. """ return prior_kl( - self.inducing_variable, self.kernel, self.q_mu, self.q_sqrt, whiten=self.whiten, + self.inducing_variable, + self.kernel, + self.q_mu, + self.q_sqrt, + whiten=self.whiten, ) def _make_distribution_fn( @@ -321,7 +329,9 @@ def _make_distribution_fn( which should be coercible to a `tf.Tensor` """ mean, cov = self.predict( - previous_layer_outputs, full_cov=self.full_cov, full_output_cov=self.full_output_cov, + previous_layer_outputs, + full_cov=self.full_cov, + full_output_cov=self.full_output_cov, ) if self.full_cov and not self.full_output_cov: diff --git a/gpflux/layers/latent_variable_layer.py b/gpflux/layers/latent_variable_layer.py index b1012639..d46eb64a 100644 --- a/gpflux/layers/latent_variable_layer.py +++ b/gpflux/layers/latent_variable_layer.py @@ -152,7 +152,9 @@ def call( return self.compositor([layer_inputs, samples]) def _inference_posteriors( - self, observations: ObservationType, training: Optional[bool] = None, + self, + observations: ObservationType, + training: Optional[bool] = None, ) -> tfp.distributions.Distribution: """ Return the posterior distributions parametrised by the :attr:`encoder`, which gets called @@ -176,7 +178,10 @@ def _inference_posteriors( return posteriors def _inference_latent_samples_and_loss( - self, layer_inputs: TensorType, observations: ObservationType, seed: Optional[int] = None, + self, + layer_inputs: TensorType, + observations: ObservationType, + seed: Optional[int] = None, ) -> Tuple[tf.Tensor, tf.Tensor]: r""" Sample latent variables during the *training* forward pass, hence requiring diff --git a/gpflux/models/deep_gp.py b/gpflux/models/deep_gp.py index b974d59e..1fd8c003 100644 --- a/gpflux/models/deep_gp.py +++ b/gpflux/models/deep_gp.py @@ -131,7 +131,10 @@ def _validate_num_data( return num_data def _evaluate_deep_gp( - self, inputs: TensorType, targets: Optional[TensorType], training: Optional[bool] = None, + self, + inputs: TensorType, + targets: Optional[TensorType], + training: Optional[bool] = None, ) -> tf.Tensor: """ Evaluate ``f(x) = fₙ(⋯ (f₂(f₁(x))))`` on the *inputs* argument. @@ -160,7 +163,10 @@ def _evaluate_deep_gp( return features def _evaluate_likelihood( - self, f_outputs: TensorType, targets: Optional[TensorType], training: Optional[bool] = None, + self, + f_outputs: TensorType, + targets: Optional[TensorType], + training: Optional[bool] = None, ) -> tf.Tensor: """ Call the `likelihood_layer` on *f_outputs*, which adds the @@ -263,7 +269,9 @@ def as_prediction_model( return model_class(self.inputs, outputs) -def sample_dgp(model: DeepGP,) -> Sample: # TODO: should this be part of a [Vanilla]DeepGP class? +def sample_dgp( + model: DeepGP, +) -> Sample: # TODO: should this be part of a [Vanilla]DeepGP class? function_draws = [layer.sample() for layer in model.f_layers] # TODO: error check that all layers implement .sample()? diff --git a/gpflux/sampling/multioutput/sample.py b/gpflux/sampling/multioutput/sample.py index 613fd31e..0073f469 100644 --- a/gpflux/sampling/multioutput/sample.py +++ b/gpflux/sampling/multioutput/sample.py @@ -87,13 +87,15 @@ def _efficient_multi_output_sample_matheron_rule( ) # [L, P] u_sample_noise = tf.matmul( - q_sqrt, tf.random.normal((P, M, 1), dtype=default_float()), # [P, M, M] # [P, M, 1] + q_sqrt, + tf.random.normal((P, M, 1), dtype=default_float()), # [P, M, M] # [P, M, 1] ) # [P, M, 1] tf.debugging.assert_equal(tf.shape(u_sample_noise), [P, M, 1]) if isinstance(kernel, SharedIndependent): Kmm = tf.tile( - Kuu(inducing_variable, kernel, jitter=default_jitter())[None, ...], [P, 1, 1], + Kuu(inducing_variable, kernel, jitter=default_jitter())[None, ...], + [P, 1, 1], ) # [P,M,M] tf.debugging.assert_equal(tf.shape(Kmm), [P, M, M]) elif isinstance(kernel, SeparateIndependent): diff --git a/gpflux/sampling/sample.py b/gpflux/sampling/sample.py index 060c58e1..823c0577 100644 --- a/gpflux/sampling/sample.py +++ b/gpflux/sampling/sample.py @@ -114,7 +114,13 @@ def __call__(self, X_new: TensorType) -> tf.Tensor: self.X = tf.concat([self.X, X_new], axis=0) mean, cov = conditional( - self.X, inducing_variable, kernel, q_mu, q_sqrt=q_sqrt, white=whiten, full_cov=True, + self.X, + inducing_variable, + kernel, + q_mu, + q_sqrt=q_sqrt, + white=whiten, + full_cov=True, ) # mean: [N_old+N_new, P], cov: [P, N_old+N_new, N_old+N_new] mean = tf.linalg.matrix_transpose(mean) # [P, N_old+N_new] f_old = tf.linalg.matrix_transpose(self.f) # [P, N_old] @@ -160,7 +166,8 @@ def _efficient_sample_matheron_rule( ) # [L, P] u_sample_noise = tf.matmul( - q_sqrt, tf.random.normal((P, M, 1), dtype=default_float()), # [P, M, M] # [P, M, 1] + q_sqrt, + tf.random.normal((P, M, 1), dtype=default_float()), # [P, M, M] # [P, M, 1] ) # [P, M, 1] Kmm = Kuu(inducing_variable, kernel, jitter=default_jitter()) # [M, M] diff --git a/tests/conftest.py b/tests/conftest.py index 9783f9d6..7b42b147 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -24,7 +24,9 @@ def test_data(): input_data = np.concatenate([x_data, w_data], axis=1) assert input_data.shape == (num_data, x_dim + w_dim) y_data = np.random.multivariate_normal( - mean=np.zeros(num_data), cov=SquaredExponential(variance=0.1)(input_data), size=y_dim, + mean=np.zeros(num_data), + cov=SquaredExponential(variance=0.1)(input_data), + size=y_dim, ).T assert y_data.shape == (num_data, y_dim) return x_data, y_data diff --git a/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff.py b/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff.py index 0f28f729..14145159 100644 --- a/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff.py +++ b/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff.py @@ -74,14 +74,16 @@ def _base_kernel_cls_fixture(request): @pytest.fixture( - name="random_basis_func_cls", params=[MultiOutputRandomFourierFeatures], + name="random_basis_func_cls", + params=[MultiOutputRandomFourierFeatures], ) def _random_basis_func_cls_fixture(request): return request.param @pytest.fixture( - name="basis_func_cls", params=[MultiOutputRandomFourierFeatures], + name="basis_func_cls", + params=[MultiOutputRandomFourierFeatures], ) def _basis_func_cls_fixture(request): return request.param diff --git a/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff_cosine.py b/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff_cosine.py index 00bd70d3..813d0aea 100644 --- a/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff_cosine.py +++ b/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff_cosine.py @@ -69,14 +69,16 @@ def _base_kernel_cls_fixture(request): @pytest.fixture( - name="random_basis_func_cls", params=[MultiOutputRandomFourierFeaturesCosine], + name="random_basis_func_cls", + params=[MultiOutputRandomFourierFeaturesCosine], ) def _random_basis_func_cls_fixture(request): return request.param @pytest.fixture( - name="basis_func_cls", params=[MultiOutputRandomFourierFeaturesCosine], + name="basis_func_cls", + params=[MultiOutputRandomFourierFeaturesCosine], ) def _basis_func_cls_fixture(request): return request.param diff --git a/tests/gpflux/layers/basis_functions/fourier_features/test_random.py b/tests/gpflux/layers/basis_functions/fourier_features/test_random.py index 950df8fb..f897bad4 100644 --- a/tests/gpflux/layers/basis_functions/fourier_features/test_random.py +++ b/tests/gpflux/layers/basis_functions/fourier_features/test_random.py @@ -61,7 +61,8 @@ def _kernel_cls_fixture(request): @pytest.fixture( - name="random_basis_func_cls", params=[RandomFourierFeatures, RandomFourierFeaturesCosine], + name="random_basis_func_cls", + params=[RandomFourierFeatures, RandomFourierFeaturesCosine], ) def _random_basis_func_cls_fixture(request): return request.param @@ -69,7 +70,11 @@ def _random_basis_func_cls_fixture(request): @pytest.fixture( name="basis_func_cls", - params=[RandomFourierFeatures, RandomFourierFeaturesCosine, OrthogonalRandomFeatures,], + params=[ + RandomFourierFeatures, + RandomFourierFeaturesCosine, + OrthogonalRandomFeatures, + ], ) def _basis_func_cls_fixture(request): return request.param diff --git a/tests/gpflux/layers/test_latent_variable_layer.py b/tests/gpflux/layers/test_latent_variable_layer.py index a5057b7d..ac985613 100644 --- a/tests/gpflux/layers/test_latent_variable_layer.py +++ b/tests/gpflux/layers/test_latent_variable_layer.py @@ -117,10 +117,12 @@ def test_latent_variable_layer_losses(mocker, w_dim): posteriors_shape = (num_data, w_dim) prior = tfp.distributions.MultivariateNormalDiag( - loc=np.random.randn(*prior_shape), scale_diag=np.random.randn(*prior_shape) ** 2, + loc=np.random.randn(*prior_shape), + scale_diag=np.random.randn(*prior_shape) ** 2, ) posteriors = tfp.distributions.MultivariateNormalDiag( - loc=np.random.randn(*posteriors_shape), scale_diag=np.random.randn(*posteriors_shape) ** 2, + loc=np.random.randn(*posteriors_shape), + scale_diag=np.random.randn(*posteriors_shape) ** 2, ) encoder = mocker.Mock(return_value=(posteriors.loc, posteriors.scale.diag)) @@ -157,10 +159,12 @@ def test_latent_variable_layer_samples(mocker, test_data, w_dim, seed2): posteriors_shape = (num_data, w_dim) prior = tfp.distributions.MultivariateNormalDiag( - loc=np.random.randn(*prior_shape), scale_diag=np.random.randn(*prior_shape) ** 2, + loc=np.random.randn(*prior_shape), + scale_diag=np.random.randn(*prior_shape) ** 2, ) posteriors = tfp.distributions.MultivariateNormalDiag( - loc=np.random.randn(*posteriors_shape), scale_diag=np.random.randn(*posteriors_shape) ** 2, + loc=np.random.randn(*posteriors_shape), + scale_diag=np.random.randn(*posteriors_shape) ** 2, ) encoder = mocker.Mock(return_value=(posteriors.loc, posteriors.scale.diag)) diff --git a/tests/gpflux/layers/test_trackable_layer.py b/tests/gpflux/layers/test_trackable_layer.py index 5030e56e..80174ff6 100644 --- a/tests/gpflux/layers/test_trackable_layer.py +++ b/tests/gpflux/layers/test_trackable_layer.py @@ -62,7 +62,10 @@ def setup_layer_modules_variables(): tf.Variable(7.0, dtype=default_float(), trainable=False), ] ), - [CompositeModule(attributes=[Matern52()]), CompositeModule(attributes=[Matern52()]),], + [ + CompositeModule(attributes=[Matern52()]), + CompositeModule(attributes=[Matern52()]), + ], ] modules_variables = [ @@ -90,31 +93,56 @@ def to_tensor_set(tensor_set: List[tf.Tensor]): def test_submodule_variables(): - (trackable_layer, variables, modules, module_variables,) = setup_layer_modules_variables() + ( + trackable_layer, + variables, + modules, + module_variables, + ) = setup_layer_modules_variables() assert to_tensor_set(trackable_layer.variables) == to_tensor_set(variables + module_variables) def test_submodule_trainable_variables(): - (trackable_layer, variables, modules, module_variables,) = setup_layer_modules_variables() + ( + trackable_layer, + variables, + modules, + module_variables, + ) = setup_layer_modules_variables() trainable_attributes = [v for v in variables + module_variables if v.trainable] assert trackable_layer.trainable_variables == trainable_attributes def test_submodule_non_trainable_variables(): - (trackable_layer, variables, modules, module_variables,) = setup_layer_modules_variables() + ( + trackable_layer, + variables, + modules, + module_variables, + ) = setup_layer_modules_variables() non_trainable_attributes = [v for v in variables + module_variables if not v.trainable] assert trackable_layer.non_trainable_variables == non_trainable_attributes def test_trainable_weights(): - (trackable_layer, variables, modules, module_variables,) = setup_layer_modules_variables() + ( + trackable_layer, + variables, + modules, + module_variables, + ) = setup_layer_modules_variables() all_vars = variables + module_variables trainable_weights = [v for v in all_vars if v.trainable] assert to_tensor_set(trackable_layer.trainable_weights) == to_tensor_set(trainable_weights) def test_non_trainable_weights(): - (trackable_layer, variables, modules, module_variables,) = setup_layer_modules_variables() + ( + trackable_layer, + variables, + modules, + module_variables, + ) = setup_layer_modules_variables() all_vars = variables + module_variables non_trainable_weights = [v for v in all_vars if not v.trainable] assert to_tensor_set(trackable_layer.non_trainable_weights) == to_tensor_set( @@ -123,20 +151,31 @@ def test_non_trainable_weights(): def test_trainable_variables(): - (trackable_layer, variables, modules, module_variables,) = setup_layer_modules_variables() + ( + trackable_layer, + variables, + modules, + module_variables, + ) = setup_layer_modules_variables() all_vars = variables + module_variables trainable_variables = [v for v in all_vars if v.trainable] assert to_tensor_set(trackable_layer.trainable_variables) == to_tensor_set(trainable_variables) def test_variables(): - (trackable_layer, variables, modules, module_variables,) = setup_layer_modules_variables() + ( + trackable_layer, + variables, + modules, + module_variables, + ) = setup_layer_modules_variables() all_vars = variables + module_variables assert to_tensor_set(trackable_layer.variables) == to_tensor_set(all_vars) @pytest.mark.parametrize( - "composite_class", [CompositeModule, UntrackableCompositeLayer], + "composite_class", + [CompositeModule, UntrackableCompositeLayer], ) def test_tensorflow_classes_trackable(composite_class): composite_object = composite_class([Matern52()]) diff --git a/tests/gpflux/models/test_deep_gp.py b/tests/gpflux/models/test_deep_gp.py index f1ab2104..0ff5bd42 100644 --- a/tests/gpflux/models/test_deep_gp.py +++ b/tests/gpflux/models/test_deep_gp.py @@ -140,7 +140,11 @@ def run_demo(maxiter=int(80e3), plotter_interval=60): deep_gp = build_deep_gp(input_dim, num_data) fig, plotter = get_live_plotter(data, deep_gp) train_deep_gp( - deep_gp, data, maxiter=maxiter, plotter=plotter, plotter_interval=plotter_interval, + deep_gp, + data, + maxiter=maxiter, + plotter=plotter, + plotter_interval=plotter_interval, ) diff --git a/tests/gpflux/sampling/test_multioutput_sample.py b/tests/gpflux/sampling/test_multioutput_sample.py index 175ab9ff..d5b082e4 100644 --- a/tests/gpflux/sampling/test_multioutput_sample.py +++ b/tests/gpflux/sampling/test_multioutput_sample.py @@ -113,7 +113,8 @@ def test_shared_wilson_efficient_sample(base_kernel, shared_inducing_variable, w # Check for consistency - i.e. evaluating the sample at the # same locations (X) returns the same value np.testing.assert_array_almost_equal( - sample_func(X), sample_func(X), + sample_func(X), + sample_func(X), ) @@ -139,7 +140,8 @@ def test_separate_wilson_efficient_sample(base_kernel, separate_inducing_variabl # Check for consistency - i.e. evaluating the sample at the # same locations (X) returns the same value np.testing.assert_array_almost_equal( - sample_func(X), sample_func(X), + sample_func(X), + sample_func(X), ) diff --git a/tests/gpflux/sampling/test_sample.py b/tests/gpflux/sampling/test_sample.py index e8e0ef19..70b27588 100644 --- a/tests/gpflux/sampling/test_sample.py +++ b/tests/gpflux/sampling/test_sample.py @@ -95,7 +95,8 @@ def test_wilson_efficient_sample(kernel, inducing_variable, whiten): # Check for consistency - i.e. evaluating the sample at the # same locations (X) returns the same value np.testing.assert_array_almost_equal( - sample_func(X), sample_func(X), + sample_func(X), + sample_func(X), ) diff --git a/tests/gpflux/test_callbacks.py b/tests/gpflux/test_callbacks.py index dafaa1c1..2d2998f2 100644 --- a/tests/gpflux/test_callbacks.py +++ b/tests/gpflux/test_callbacks.py @@ -90,7 +90,11 @@ def test_tensorboard_callback(tmp_path, model_and_loss, data, update_freq): model.compile(optimizer=optimizer, loss=loss) callbacks = [ tf.keras.callbacks.ReduceLROnPlateau( - monitor="loss", patience=1, factor=0.95, verbose=1, min_lr=1e-6, + monitor="loss", + patience=1, + factor=0.95, + verbose=1, + min_lr=1e-6, ), # To write the LR to TensorBoard the `TensorBoard` callback needs to be # instantiated after the `ReduceLROnPlateau` callback. diff --git a/tests/gpflux/test_ci_utils.py b/tests/gpflux/test_ci_utils.py index 2f200771..5c97c78e 100644 --- a/tests/gpflux/test_ci_utils.py +++ b/tests/gpflux/test_ci_utils.py @@ -32,7 +32,12 @@ def test_is_continuous_integration(os_environ, is_ci): @pytest.mark.parametrize( - "is_ci, args, expected_result", [(True, (13,), 2), (True, (13, 5), 5), (False, (13,), 13),], + "is_ci, args, expected_result", + [ + (True, (13,), 2), + (True, (13, 5), 5), + (False, (13,), 13), + ], ) def test_notebook_niter(is_ci, args, expected_result): with mock_ci_state(is_ci): diff --git a/tests/gpflux/test_helpers.py b/tests/gpflux/test_helpers.py index 093234db..203550c2 100644 --- a/tests/gpflux/test_helpers.py +++ b/tests/gpflux/test_helpers.py @@ -131,7 +131,11 @@ def test_construct_inducing_shared_independent_duplicates(z_init): z_init = None moiv = construct_basic_inducing_variables( - num_inducing, input_dim, output_dim=output_dim, share_variables=True, z_init=z_init, + num_inducing, + input_dim, + output_dim=output_dim, + share_variables=True, + z_init=z_init, ) assert isinstance(moiv, SharedIndependentInducingVariables) diff --git a/tests/gpflux/test_math.py b/tests/gpflux/test_math.py index 5e69892a..a5f7166f 100644 --- a/tests/gpflux/test_math.py +++ b/tests/gpflux/test_math.py @@ -32,5 +32,7 @@ def test_compute_A_inv_x(): A = _get_psd_matrix(N) b = np.random.randn(N, 2) / 100 np.testing.assert_array_almost_equal( - np.linalg.inv(A) @ b, compute_A_inv_b(A, b).numpy(), decimal=3, + np.linalg.inv(A) @ b, + compute_A_inv_b(A, b).numpy(), + decimal=3, ) diff --git a/tests/gpflux/test_runtime_checks.py b/tests/gpflux/test_runtime_checks.py index ddfe2fa2..6c28d12f 100644 --- a/tests/gpflux/test_runtime_checks.py +++ b/tests/gpflux/test_runtime_checks.py @@ -39,7 +39,8 @@ def make_kernels(num_latent_k): def make_inducing_variables(num_latent_iv): return [ construct_basic_inducing_variables( - num_inducing=[num_inducing for _ in range(num_latent_iv)], input_dim=input_dim, + num_inducing=[num_inducing for _ in range(num_latent_iv)], + input_dim=input_dim, ), construct_basic_inducing_variables( num_inducing=num_inducing, input_dim=input_dim, output_dim=num_latent_iv diff --git a/tests/integration/test_svgp_equivalence.py b/tests/integration/test_svgp_equivalence.py index c7550e4e..e3249b7b 100644 --- a/tests/integration/test_svgp_equivalence.py +++ b/tests/integration/test_svgp_equivalence.py @@ -134,7 +134,10 @@ def test_svgp_equivalence_after_assign(): def fit_adam( - model: Union[gpflow.models.SVGP, gpflux.models.DeepGP], data, maxiter, adam_learning_rate=0.01, + model: Union[gpflow.models.SVGP, gpflux.models.DeepGP], + data, + maxiter, + adam_learning_rate=0.01, ): X, Y = data num_data = len(X) @@ -173,20 +176,33 @@ def keras_fit_adam(sldgp: gpflux.models.DeepGP, data, maxiter, adam_learning_rat def _keras_fit_natgrad( - base_model, dataset, maxiter, adam_learning_rate=0.01, gamma=1.0, loss=None, run_eagerly=None, + base_model, + dataset, + maxiter, + adam_learning_rate=0.01, + gamma=1.0, + loss=None, + run_eagerly=None, ): model = gpflux.optimization.NatGradWrapper(base_model) model.natgrad_layers = True # Shortcut to apply natural gradients to all layers natgrad = gpflow.optimizers.NaturalGradient(gamma=gamma) adam = tf.optimizers.Adam(adam_learning_rate) model.compile( - optimizer=[natgrad, adam], loss=loss, run_eagerly=run_eagerly, + optimizer=[natgrad, adam], + loss=loss, + run_eagerly=run_eagerly, ) model.fit(dataset, epochs=maxiter) def keras_fit_natgrad( - sldgp, data, maxiter, adam_learning_rate=0.01, gamma=1.0, run_eagerly=None, + sldgp, + data, + maxiter, + adam_learning_rate=0.01, + gamma=1.0, + run_eagerly=None, ): base_model = sldgp.as_training_model() dataset = make_dataset(data) @@ -273,7 +289,10 @@ def test_svgp_equivalence_with_sldgp(svgp_fitter, sldgp_fitter, maxiter=20): @pytest.mark.parametrize( "svgp_fitter, keras_fitter, tol_kw", - [(fit_adam, _keras_fit_adam, {}), (fit_natgrad, _keras_fit_natgrad, dict(atol=1e-8)),], + [ + (fit_adam, _keras_fit_adam, {}), + (fit_natgrad, _keras_fit_natgrad, dict(atol=1e-8)), + ], ) def test_svgp_equivalence_with_keras_sequential(svgp_fitter, keras_fitter, tol_kw, maxiter=10): X, Y = data = load_data() @@ -327,7 +346,8 @@ def run_gpflow_svgp(data, optimizer, maxiter): @pytest.mark.parametrize( - "optimizer", ["natgrad", "adam", "scipy", "keras_adam", "keras_natgrad"], + "optimizer", + ["natgrad", "adam", "scipy", "keras_adam", "keras_natgrad"], ) def test_run_gpflux_sldgp(optimizer): data = load_data() From afc0f1273233475fd0b43cdd82813d915f1e988f Mon Sep 17 00:00:00 2001 From: SebastianPopescu Date: Thu, 22 Sep 2022 10:57:57 +0100 Subject: [PATCH 08/25] flake8 working --- .../constant_input_dim_deep_gp.py | 3 -- .../kernel_with_feature_decomposition.py | 2 +- .../kernel_with_feature_decomposition.py | 42 +++++++++++-------- .../fourier_features/multioutput/base.py | 10 ++--- .../multioutput/random/base.py | 5 +-- gpflux/sampling/multioutput/sample.py | 17 ++------ gpflux/sampling/sample.py | 6 +-- 7 files changed, 37 insertions(+), 48 deletions(-) diff --git a/gpflux/architectures/constant_input_dim_deep_gp.py b/gpflux/architectures/constant_input_dim_deep_gp.py index 2af04d83..b1797558 100644 --- a/gpflux/architectures/constant_input_dim_deep_gp.py +++ b/gpflux/architectures/constant_input_dim_deep_gp.py @@ -90,9 +90,6 @@ def _construct_kernel(input_dim: int, is_last_layer: bool) -> SquaredExponential return SquaredExponential(lengthscales=lengthscales, variance=variance) -construct_kernel - - def build_constant_input_dim_deep_gp(X: np.ndarray, num_layers: int, config: Config) -> DeepGP: r""" Build a Deep GP consisting of ``num_layers`` :class:`GPLayer`\ s. diff --git a/gpflux/feature_decomposition_kernels/kernel_with_feature_decomposition.py b/gpflux/feature_decomposition_kernels/kernel_with_feature_decomposition.py index 0a64b8a8..54801a2c 100644 --- a/gpflux/feature_decomposition_kernels/kernel_with_feature_decomposition.py +++ b/gpflux/feature_decomposition_kernels/kernel_with_feature_decomposition.py @@ -28,7 +28,7 @@ <../../../../notebooks/weight_space_approximation.ipynb>`_ for an in-depth overview. """ -from typing import List, Optional, Tuple, Union +from typing import Optional, Union import tensorflow as tf diff --git a/gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py b/gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py index 4f4b6bfd..5e1a9289 100644 --- a/gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py +++ b/gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py @@ -28,7 +28,7 @@ <../../../../notebooks/weight_space_approximation.ipynb>`_ for an in-depth overview. """ -from typing import Any, List, Optional, Tuple, Union +from typing import Any, Optional, Tuple, Union import tensorflow as tf @@ -72,7 +72,8 @@ def num_latent_gps(self) -> int: @property def latent_kernels(self) -> Any: - """In this scenario we do not have access to the underlying kernels, so we are just returning the feature_functions""" + """In this scenario we do not have access to the underlying kernels, + so we are just returning the feature_functions""" return self._feature_functions def K( @@ -85,7 +86,8 @@ def K( phi = self._feature_functions(X) # [P, N, L] L = tf.shape(phi)[-1] - # NOTE - there are some differences between using FourierFeatures and FourierFeaturesCosine, extra check to ensure right shape and to guide debugging in notebooks + # NOTE - there are some differences between using FourierFeatures and FourierFeaturesCosine, + # extra check to ensure right shape and to guide debugging in notebooks tf.debugging.assert_equal(tf.shape(self._feature_coefficients), [self.num_latent_gps, L, 1]) if X2 is None: @@ -120,9 +122,10 @@ def K_diag(self, X: TensorType, full_output_cov: bool = False) -> tf.Tensor: class SharedMultiOutputKernelWithFeatureDecompositionBase(gpflow.kernels.SharedIndependent): """ - 'Wrapper' class to solve the issue with full_cov:bool = False inherited from gpflow.kernels.MultiOutputKernel - which doesn't work well with GPRPosterior, as it does not use dispatchers from gpflow.covariances. - #NOTE -- I think in general GPR in GPflow is only meant to be used in univariate regression settings or multivariate case but with common covariance + 'Wrapper' class to solve the issue with full_cov:bool = False + inherited from gpflow.kernels.MultiOutputKernel + which doesn't work well with GPRPosterior, + as it does not use dispatchers from gpflow.covariances. """ # Overriding __call__ from gpflow.kernels.MultioutputKernel @@ -131,7 +134,7 @@ def __call__( X: TensorType, X2: Optional[TensorType] = None, *, - full_cov: bool = True, # NOTE -- this needs to be set to True as not to throw errors later on + full_cov: bool = True, # NOTE -- otherwise will throw errors full_output_cov: bool = True, presliced: bool = False, ) -> tf.Tensor: @@ -150,7 +153,8 @@ class SharedMultiOutputKernelWithFeatureDecomposition( SharedMultiOutputKernelWithFeatureDecompositionBase ): r""" - This class represents a gpflow.kernels.SharedIndependent kernel together with its finite feature decomposition: + This class represents a gpflow.kernels.SharedIndependent kernel together + with its finite feature decomposition: .. math:: k(x, x') = \sum_{i=0}^L \lambda_i \phi_i(x) \phi_i(x'), @@ -212,8 +216,9 @@ def __init__( """ if kernel is None: - # NOTE -- this is a subclass of gpflow.kernels.SharedIndependent (needed to be used with dispatchers from gpflow.covariances) - # so it needs to be initialized somehow. Not sure if this is the best approach though + # NOTE -- this is a subclass of gpflow.kernels.SharedIndependent + # (needed to be used with dispatchers from gpflow.covariances) + # so it needs to be initialized somehow. Not sure if efficient _dummy_kernel = SquaredExponential() super().__init__(_dummy_kernel, output_dim) self._kernel = _MultiOutputApproximateKernel(feature_functions, feature_coefficients) @@ -265,9 +270,10 @@ def K_diag(self, X: TensorType, full_output_cov: bool = True) -> tf.Tensor: class SeparateMultiOutputKernelWithFeatureDecompositionBase(gpflow.kernels.SeparateIndependent): """ - 'Wrapper' class to solve the issue with full_cov:bool = False inherited from gpflow.kernels.MultiOutputKernel - which doesn't work well with GPRPosterior, as it does not use dispatchers from gpflow.covariances. - #NOTE -- I think in general GPR in GPflow is only meant to be used in univariate regression settings or multivariate case but with common covariance + 'Wrapper' class to solve the issue with full_cov:bool = False + inherited from gpflow.kernels.MultiOutputKernel + which doesn't work well with GPRPosterior, + as it does not use dispatchers from gpflow.covariances. """ # Overriding __call__ from gpflow.kernels.MultioutputKernel @@ -276,7 +282,7 @@ def __call__( X: TensorType, X2: Optional[TensorType] = None, *, - full_cov: bool = True, # NOTE -- this needs to be set to True as not to throw errors later on + full_cov: bool = True, # NOTE -- otherwise will throw errors full_output_cov: bool = True, presliced: bool = False, ) -> tf.Tensor: @@ -295,7 +301,8 @@ class SeparateMultiOutputKernelWithFeatureDecomposition( SeparateMultiOutputKernelWithFeatureDecompositionBase ): r""" - This class represents a gpflow.kernel.SeparateIndependent together with its finite feature decomposition: + This class represents a gpflow.kernel.SeparateIndependent + together with its finite feature decomposition: .. math:: k(x, x') = \sum_{i=0}^L \lambda_i \phi_i(x) \phi_i(x'), @@ -357,8 +364,9 @@ def __init__( """ if kernel is None: - # NOTE -- this is a subclass of gpflow.kernels.SeparateIndependent (needed to be used with dispatchers from gpflow.covariances) - # so it needs to be initialized somehow. Not sure if this is the best approach though + # NOTE -- this is a subclass of gpflow.kernels.SeparateIndependent + # (needed to be used with dispatchers from gpflow.covariances) + # so it needs to be initialized somehow. Not sure if efficient _dummy_kernels = [SquaredExponential() for _ in range(output_dim)] super().__init__(_dummy_kernels) self._kernel = _MultiOutputApproximateKernel(feature_functions, feature_coefficients) diff --git a/gpflux/layers/basis_functions/fourier_features/multioutput/base.py b/gpflux/layers/basis_functions/fourier_features/multioutput/base.py index 581760f0..b2eaf6c5 100644 --- a/gpflux/layers/basis_functions/fourier_features/multioutput/base.py +++ b/gpflux/layers/basis_functions/fourier_features/multioutput/base.py @@ -17,7 +17,6 @@ from abc import ABC, abstractmethod from typing import Mapping -from warnings import WarningMessage import tensorflow as tf @@ -32,7 +31,8 @@ def __init__( self, kernel: gpflow.kernels.MultioutputKernel, n_components: int, **kwargs: Mapping ): """ - :param kernel: kernel to approximate using a set of Fourier bases. Expects a Multioutput Kernel + :param kernel: kernel to approximate using a set of Fourier bases. + Expects a Multioutput Kernel :param n_components: number of components (e.g. Monte Carlo samples, quadrature nodes, etc.) used to numerically approximate the kernel. """ @@ -85,12 +85,10 @@ def call(self, inputs: TensorType) -> tf.Tensor: ) # [P, 1, D] tf.debugging.assert_equal(tf.shape(_lengthscales), [P, 1, D]) else: - raise ValueError( - "kernel is not supported. Must be either gpflow.kernels.SharedIndependent or gpflow.kernels.SeparateIndependent" - ) + raise ValueError("kernel is not supported.") X = tf.divide( - inputs, # [N, D] in the case that we predict at X*, in case we want to get the Fourier Features for Z, this would correspond to [P, M, D] + inputs, # [N, D] or [P, M, D] _lengthscales, # [P, 1, D] ) # [P, N, D] or [P, M, D] const = self._compute_constant()[..., None, None] # [P,1,1] diff --git a/gpflux/layers/basis_functions/fourier_features/multioutput/random/base.py b/gpflux/layers/basis_functions/fourier_features/multioutput/random/base.py index 251d6a62..9b225c48 100644 --- a/gpflux/layers/basis_functions/fourier_features/multioutput/random/base.py +++ b/gpflux/layers/basis_functions/fourier_features/multioutput/random/base.py @@ -13,7 +13,6 @@ # See the License for the specific language governing permissions and # limitations under the License. # -from multiprocessing.sharedctypes import Value from typing import Mapping, Optional, Tuple, Type import numpy as np @@ -135,9 +134,7 @@ def _weights_init(self, shape: TensorType, dtype: Optional[DType] = None) -> Ten nu = 2.0 * p + 1.0 # degrees of freedom return _sample_students_t(nu, shape, dtype) else: - raise ValueError( - "kernel is not supported. Must be either gpflow.kernels.SharedIndependent or gpflow.kernels.SeparateIndependent" - ) + raise ValueError("kernel is not supported.") @staticmethod def rff_constant(variance: TensorType, output_dim: int) -> tf.Tensor: diff --git a/gpflux/sampling/multioutput/sample.py b/gpflux/sampling/multioutput/sample.py index 0073f469..bbfaf191 100644 --- a/gpflux/sampling/multioutput/sample.py +++ b/gpflux/sampling/multioutput/sample.py @@ -15,15 +15,11 @@ # """ This module enables you to sample from (Deep) GPs using different approaches. """ -import abc -from multiprocessing.sharedctypes import Value -from pickle import TRUE -from typing import Callable, Optional, Union +from typing import Optional, Union import tensorflow as tf from gpflow.base import TensorType -from gpflow.conditionals import conditional from gpflow.config import default_float, default_jitter from gpflow.covariances import Kuf, Kuu from gpflow.inducing_variables import ( @@ -31,8 +27,7 @@ SeparateIndependentInducingVariables, SharedIndependentInducingVariables, ) -from gpflow.kernels import Kernel, MultioutputKernel, SeparateIndependent, SharedIndependent -from gpflow.utilities import Dispatcher +from gpflow.kernels import SeparateIndependent, SharedIndependent from gpflux.feature_decomposition_kernels import ( SeparateMultiOutputKernelWithFeatureDecomposition, @@ -135,13 +130,9 @@ def _efficient_multi_output_sample_matheron_rule( phi_Z = kernel.feature_functions(inducing_variable.inducing_variable.Z) # [P, M, L] tf.debugging.assert_equal(tf.shape(phi_Z), [P, M, L]) else: - raise ValueError( - "inducing variable is not supported. Must be either SharedIndependentInducingVariables or SeparateIndependentInducingVariables" - ) + raise ValueError("inducing variable is not supported.") - weight_space_prior_Z = tf.matmul( - phi_Z, tf.transpose(prior_weights)[..., None] # [P, M, L] # [P, L, 1] - ) # [P, M, 1] + weight_space_prior_Z = tf.matmul(phi_Z, tf.transpose(prior_weights)[..., None]) # [P, M, 1] weight_space_prior_Z = tf.transpose(weight_space_prior_Z[..., 0]) # [M, P] diff = tf.transpose(u_sample - weight_space_prior_Z)[..., None] # [P, M, 1] diff --git a/gpflux/sampling/sample.py b/gpflux/sampling/sample.py index 823c0577..e09818e5 100644 --- a/gpflux/sampling/sample.py +++ b/gpflux/sampling/sample.py @@ -16,7 +16,6 @@ """ This module enables you to sample from (Deep) GPs using different approaches. """ import abc -from pickle import TRUE from typing import Callable, Optional, Union import tensorflow as tf @@ -26,10 +25,9 @@ from gpflow.config import default_float, default_jitter from gpflow.covariances import Kuf, Kuu from gpflow.inducing_variables import InducingVariables -from gpflow.kernels import Kernel, SeparateIndependent, SharedIndependent -from gpflow.utilities import Dispatcher +from gpflow.kernels import Kernel -from gpflux.feature_decomposition_kernels import KernelWithFeatureDecomposition, _ApproximateKernel +from gpflux.feature_decomposition_kernels import KernelWithFeatureDecomposition from gpflux.math import compute_A_inv_b from gpflux.sampling.utils import draw_conditional_sample From 0e1fcbc0324d0bbf10f310127a5916c3eaf9a1aa Mon Sep 17 00:00:00 2001 From: SebastianPopescu Date: Thu, 22 Sep 2022 11:11:36 +0100 Subject: [PATCH 09/25] mypy fixed now --- gpflux/layers/likelihood_layer.py | 4 ++-- gpflux/losses.py | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/gpflux/layers/likelihood_layer.py b/gpflux/layers/likelihood_layer.py index 7d3fb2ab..b8fc7aee 100644 --- a/gpflux/layers/likelihood_layer.py +++ b/gpflux/layers/likelihood_layer.py @@ -84,12 +84,12 @@ def call( assert targets is not None # TODO: re-use LikelihoodLoss to remove code duplication loss_per_datapoint = tf.reduce_mean( - -self.likelihood.variational_expectations(F_mean, F_var, targets) + -self.likelihood.variational_expectations(inputs, F_mean, F_var, targets) ) Y_mean = Y_var = None else: loss_per_datapoint = tf.constant(0.0, dtype=default_float()) - Y_mean, Y_var = self.likelihood.predict_mean_and_var(F_mean, F_var) + Y_mean, Y_var = self.likelihood.predict_mean_and_var(inputs, F_mean, F_var) self.add_loss(loss_per_datapoint) diff --git a/gpflux/losses.py b/gpflux/losses.py index 66bb83ca..ae6560ab 100644 --- a/gpflux/losses.py +++ b/gpflux/losses.py @@ -72,6 +72,7 @@ def __init__(self, likelihood: gpflow.likelihoods.Likelihood): def call( self, + x: TensorType, y_true: TensorType, f_prediction: Union[TensorType, tfp.distributions.MultivariateNormalDiag], ) -> tf.Tensor: @@ -83,7 +84,7 @@ def call( F_mu = f_prediction.loc F_var = f_prediction.scale.diag ** 2 - return -self.likelihood.variational_expectations(F_mu, F_var, y_true) + return -self.likelihood.variational_expectations(x, F_mu, F_var, y_true) else: # Tensor f_samples = f_prediction - return -self.likelihood.log_prob(f_samples, y_true) + return -self.likelihood.log_prob(x, f_samples, y_true) From 3c23a1226dddd5d60c18a28ebac1e2065cac0c17 Mon Sep 17 00:00:00 2001 From: SebastianPopescu Date: Fri, 23 Sep 2022 16:12:44 +0100 Subject: [PATCH 10/25] tests should be fine now --- docs/notebooks/checkpoint | 2 + docs/notebooks/ckpts/.data-00000-of-00001 | Bin 0 -> 25793 bytes docs/notebooks/ckpts/.index | Bin 0 -> 3035 bytes docs/notebooks/ckpts/checkpoint | 2 + .../notebooks/efficient_posterior_sampling.py | 5 +- docs/notebooks/efficient_sampling.py | 2 +- ...s.1663843333.sebastianp-lptp.profile-empty | Bin 0 -> 40 bytes .../sebastianp-lptp.input_pipeline.pb | Bin 0 -> 2881 bytes .../sebastianp-lptp.kernel_stats.pb | 0 .../sebastianp-lptp.memory_profile.json.gz | Bin 0 -> 73 bytes .../sebastianp-lptp.overview_page.pb | Bin 0 -> 4172 bytes .../sebastianp-lptp.tensorflow_stats.pb | Bin 0 -> 132114 bytes .../sebastianp-lptp.trace.json.gz | Bin 0 -> 20593 bytes .../sebastianp-lptp.xplane.pb | Bin 0 -> 88285 bytes .../sebastianp-lptp.input_pipeline.pb | Bin 0 -> 2881 bytes .../sebastianp-lptp.kernel_stats.pb | 0 .../sebastianp-lptp.memory_profile.json.gz | Bin 0 -> 73 bytes .../sebastianp-lptp.overview_page.pb | Bin 0 -> 4172 bytes .../sebastianp-lptp.tensorflow_stats.pb | Bin 0 -> 131756 bytes .../sebastianp-lptp.trace.json.gz | Bin 0 -> 21513 bytes .../sebastianp-lptp.xplane.pb | Bin 0 -> 92627 bytes .../sebastianp-lptp.input_pipeline.pb | Bin 0 -> 2881 bytes .../sebastianp-lptp.kernel_stats.pb | 0 .../sebastianp-lptp.memory_profile.json.gz | Bin 0 -> 73 bytes .../sebastianp-lptp.overview_page.pb | Bin 0 -> 4172 bytes .../sebastianp-lptp.tensorflow_stats.pb | Bin 0 -> 131384 bytes .../sebastianp-lptp.trace.json.gz | Bin 0 -> 21611 bytes .../sebastianp-lptp.xplane.pb | Bin 0 -> 92216 bytes ...ts.1663843327.sebastianp-lptp.1309091.0.v2 | Bin 0 -> 561295 bytes ...ts.1663843327.sebastianp-lptp.1309091.1.v2 | Bin 0 -> 55142 bytes ...ts.1663844068.sebastianp-lptp.1320413.0.v2 | Bin 0 -> 671910 bytes ...ts.1663844068.sebastianp-lptp.1320413.1.v2 | Bin 0 -> 212670 bytes ...ts.1663944078.sebastianp-lptp.2242101.0.v2 | Bin 0 -> 671910 bytes ...ts.1663944078.sebastianp-lptp.2242101.1.v2 | Bin 0 -> 212670 bytes .../multi_output_efficient_sampling.py | 2 +- ...multi_output_weight_space_approximation.py | 444 ------------------ docs/notebooks/weights.data-00000-of-00001 | Bin 0 -> 9289 bytes docs/notebooks/weights.index | Bin 0 -> 1298 bytes gpflux/layers/likelihood_layer.py | 4 +- gpflux/losses.py | 5 +- .../sampling/test_multioutput_sample.py | 56 ++- tests/gpflux/sampling/test_sample.py | 4 +- 42 files changed, 70 insertions(+), 456 deletions(-) create mode 100644 docs/notebooks/checkpoint create mode 100644 docs/notebooks/ckpts/.data-00000-of-00001 create mode 100644 docs/notebooks/ckpts/.index create mode 100644 docs/notebooks/ckpts/checkpoint create mode 100644 docs/notebooks/logs/events.out.tfevents.1663843333.sebastianp-lptp.profile-empty create mode 100644 docs/notebooks/logs/plugins/profile/2022_09_22_11_42_13/sebastianp-lptp.input_pipeline.pb create mode 100644 docs/notebooks/logs/plugins/profile/2022_09_22_11_42_13/sebastianp-lptp.kernel_stats.pb create mode 100644 docs/notebooks/logs/plugins/profile/2022_09_22_11_42_13/sebastianp-lptp.memory_profile.json.gz create mode 100644 docs/notebooks/logs/plugins/profile/2022_09_22_11_42_13/sebastianp-lptp.overview_page.pb create mode 100644 docs/notebooks/logs/plugins/profile/2022_09_22_11_42_13/sebastianp-lptp.tensorflow_stats.pb create mode 100644 docs/notebooks/logs/plugins/profile/2022_09_22_11_42_13/sebastianp-lptp.trace.json.gz create mode 100644 docs/notebooks/logs/plugins/profile/2022_09_22_11_42_13/sebastianp-lptp.xplane.pb create mode 100644 docs/notebooks/logs/plugins/profile/2022_09_22_11_54_33/sebastianp-lptp.input_pipeline.pb create mode 100644 docs/notebooks/logs/plugins/profile/2022_09_22_11_54_33/sebastianp-lptp.kernel_stats.pb create mode 100644 docs/notebooks/logs/plugins/profile/2022_09_22_11_54_33/sebastianp-lptp.memory_profile.json.gz create mode 100644 docs/notebooks/logs/plugins/profile/2022_09_22_11_54_33/sebastianp-lptp.overview_page.pb create mode 100644 docs/notebooks/logs/plugins/profile/2022_09_22_11_54_33/sebastianp-lptp.tensorflow_stats.pb create mode 100644 docs/notebooks/logs/plugins/profile/2022_09_22_11_54_33/sebastianp-lptp.trace.json.gz create mode 100644 docs/notebooks/logs/plugins/profile/2022_09_22_11_54_33/sebastianp-lptp.xplane.pb create mode 100644 docs/notebooks/logs/plugins/profile/2022_09_23_15_41_22/sebastianp-lptp.input_pipeline.pb create mode 100644 docs/notebooks/logs/plugins/profile/2022_09_23_15_41_22/sebastianp-lptp.kernel_stats.pb create mode 100644 docs/notebooks/logs/plugins/profile/2022_09_23_15_41_22/sebastianp-lptp.memory_profile.json.gz create mode 100644 docs/notebooks/logs/plugins/profile/2022_09_23_15_41_22/sebastianp-lptp.overview_page.pb create mode 100644 docs/notebooks/logs/plugins/profile/2022_09_23_15_41_22/sebastianp-lptp.tensorflow_stats.pb create mode 100644 docs/notebooks/logs/plugins/profile/2022_09_23_15_41_22/sebastianp-lptp.trace.json.gz create mode 100644 docs/notebooks/logs/plugins/profile/2022_09_23_15_41_22/sebastianp-lptp.xplane.pb create mode 100644 docs/notebooks/logs/train/events.out.tfevents.1663843327.sebastianp-lptp.1309091.0.v2 create mode 100644 docs/notebooks/logs/train/events.out.tfevents.1663843327.sebastianp-lptp.1309091.1.v2 create mode 100644 docs/notebooks/logs/train/events.out.tfevents.1663844068.sebastianp-lptp.1320413.0.v2 create mode 100644 docs/notebooks/logs/train/events.out.tfevents.1663844068.sebastianp-lptp.1320413.1.v2 create mode 100644 docs/notebooks/logs/train/events.out.tfevents.1663944078.sebastianp-lptp.2242101.0.v2 create mode 100644 docs/notebooks/logs/train/events.out.tfevents.1663944078.sebastianp-lptp.2242101.1.v2 delete mode 100644 docs/notebooks/multi_output_weight_space_approximation.py create mode 100644 docs/notebooks/weights.data-00000-of-00001 create mode 100644 docs/notebooks/weights.index diff --git a/docs/notebooks/checkpoint b/docs/notebooks/checkpoint new file mode 100644 index 00000000..efd06212 --- /dev/null +++ b/docs/notebooks/checkpoint @@ -0,0 +1,2 @@ +model_checkpoint_path: "weights" +all_model_checkpoint_paths: "weights" diff --git a/docs/notebooks/ckpts/.data-00000-of-00001 b/docs/notebooks/ckpts/.data-00000-of-00001 new file mode 100644 index 0000000000000000000000000000000000000000..0c3c568236d378b8a013601f74c167a5415a4ac3 GIT binary patch literal 25793 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 literal 0 HcmV?d00001 diff --git a/docs/notebooks/ckpts/.index b/docs/notebooks/ckpts/.index new file mode 100644 index 0000000000000000000000000000000000000000..2a961d37709b04724c6ae0d21268be53629a4b27 GIT binary patch literal 3035 zcmZQzVB=tvV&Y(AkP(P?_HcFf4)FK%3vqPvagFzP@^WIYUQ- z!*qvb+%k7lA#!~QF=<0I(4;j{c8m!!!UQ}B(QpFjIS$j6dA@g)E&0F^nU|bOj!zgA zCV+g=IlE8D*_4l5Uoa@F0QsP)<4k;v3_k%MFen@VyPnUbDa%%Tf`Q53xJ;EFb#RWl9S>h?*+&gA1>-OQdHzMfP4^VU|mg2kv9YE`ez)4 zMWUwSlou%-VxaWVHS?-GRmzkNt{~%npPv4olrrT+2}qao%&9fvrV>;rJT8cXa;?4T z=`9Qy*vcqFef(t<70R0*ZXhRoG?Y{zsl1s`2GZ7hz@$ppjn7CwCo?-WCo>~IKSiIi zy14^X51r|jHx|FQT!Qlv!r4_rxIi`#AgM{#d@ZSyHDy8nX0U4rfN&o-= literal 0 HcmV?d00001 diff --git a/docs/notebooks/ckpts/checkpoint b/docs/notebooks/ckpts/checkpoint new file mode 100644 index 00000000..462f6274 --- /dev/null +++ b/docs/notebooks/ckpts/checkpoint @@ -0,0 +1,2 @@ +model_checkpoint_path: "." +all_model_checkpoint_paths: "." diff --git a/docs/notebooks/efficient_posterior_sampling.py b/docs/notebooks/efficient_posterior_sampling.py index bae0ba1a..95821d1a 100644 --- a/docs/notebooks/efficient_posterior_sampling.py +++ b/docs/notebooks/efficient_posterior_sampling.py @@ -80,7 +80,10 @@ from gpflow.models import GPR from gpflux.layers.basis_functions.fourier_features import RandomFourierFeaturesCosine -from gpflux.sampling.kernel_with_feature_decomposition import KernelWithFeatureDecomposition +from gpflux.feature_decomposition_kernels.kernel_with_feature_decomposition import ( + KernelWithFeatureDecomposition, +) + # %% [markdown] """ diff --git a/docs/notebooks/efficient_sampling.py b/docs/notebooks/efficient_sampling.py index fe85598c..75805b19 100644 --- a/docs/notebooks/efficient_sampling.py +++ b/docs/notebooks/efficient_sampling.py @@ -48,7 +48,7 @@ """ # %% -d = np.load("./tests/snelson1d.npz") +d = np.load("../../tests/snelson1d.npz") X, Y = data = d["X"], d["Y"] num_data, input_dim = X.shape diff --git a/docs/notebooks/logs/events.out.tfevents.1663843333.sebastianp-lptp.profile-empty b/docs/notebooks/logs/events.out.tfevents.1663843333.sebastianp-lptp.profile-empty new file mode 100644 index 0000000000000000000000000000000000000000..ebaf76d33b4088b9812cabc31a16c0a86e6a0093 GIT binary patch literal 40 rcmb1OfPlsI-b$Pd3=WL^r*Ak)@g@}|X6EU+mZj#ESQ(vBTe%hhqL2#w literal 0 HcmV?d00001 diff --git a/docs/notebooks/logs/plugins/profile/2022_09_22_11_42_13/sebastianp-lptp.input_pipeline.pb b/docs/notebooks/logs/plugins/profile/2022_09_22_11_42_13/sebastianp-lptp.input_pipeline.pb new file mode 100644 index 0000000000000000000000000000000000000000..61b382b1776ff59a068d3c2adb56d765915d19e8 GIT binary patch literal 2881 zcmc&$e~1)S9N#+)ZOD*=M2+z6igc^TY>oQiL7sDzOy^+?0eIj zH@B`)pix4I)=@z!6j?+;pa~%nQjiEie`J4@{}la^U?35c7)JDcvp4N|TPd8-9|N=R zz5RZEe1E*@iY9eePL zzO1n*FTfMr1mAa9xwoL*^PgZCwd>ma{K1~rGw~lTue$ijXX~=bXeAx3%#J#!-Fbaf z43mQwA6{s@m5EuZ4qdyHTh&G`(E6?q^N&v4r<`!9 zL~}w{HgaZC2@D^EJ(Q>}dgsbiCjR~J`}gelF`Z2g)N{w~+WK53{k3uQ$O$9S2K#)6 zHZnKdor+Tdn9s#F*D)233tt|5cI~nKnfOnqpWOcE;dnL~t)!!s*)EQ2i5t_v(34w# z{q)@KlbQH!AI?9p&CX|&*3`?VPQ3d}CSAC2@6_-gcehEbYuOuzZm%&kTJTy^*y7G* zd%oK7lHId66F+nHqjRZKOS8#nB^|BI)&!b<6TmZ4iu!uv7pLC8{8}bnKXS72(D4Vd z$rZnSv!>@X&!o@H5B4qidC_cr#`!z6U4!hY00Jy>Vo^yA(%=E9(FUngCW++4c7B~Hr*N_#?QqoQ- z9VrFtgIrmoUV=zPN^VFLOD<*AMBnr#>h!vk>r=Fka4~};krila932`O&W#M}+WC27 zK&{9nVq<=Z?YI!~q}C*5CbV?P01Z=mYJejuJflL|+(p_dh_rRZlJw_ur2AILM1yUR zW~E(gv_pJnFDR`&x5QUWI|vu(B(y`e_K4XqT`0Q1%Ca(d@WRj-m|R##1jagxN+BS${+B`>#pmj95^k%xdP;ukgUNh>Fv!i`)q5-?Y7dWaA(S z)CCb%%>SC+xtklA+R9$LldZkE3@j6+hDL*x^*A0tX$J)5wm*AN6F{dmWk~ z8y@Io&db-S2vS+z$@pq~Ch%Fl za(w!7@T(5O;7AkTOTuk@cYK_9WzYvEwCv65*^F9*V{Svz1>`({xvN@A$`TE~_7btx zvEG;w8;EU*jm0KnrP!8*8}pABM@NRoOD8(JKIn`D*QlssN_oi#F$osI#w8U{Vid=g zC&+QyEaeLRQWsr?dLA%>N$O4~i4@dfs(#eJd=ll%VZIbW4RGpNq#Ki^_o#oU%Q8CB zET~8ElhjYD>g(>sXb9iTo(gFN__^xfY(ZokDFP=bo}lb{mO8-?R>h?!49@@&@rtFE f)l|}=5(aw&uayw2d0Z)y0v|pN48-LOuVno%WB?FB literal 0 HcmV?d00001 diff --git a/docs/notebooks/logs/plugins/profile/2022_09_22_11_42_13/sebastianp-lptp.kernel_stats.pb b/docs/notebooks/logs/plugins/profile/2022_09_22_11_42_13/sebastianp-lptp.kernel_stats.pb new file mode 100644 index 00000000..e69de29b diff --git a/docs/notebooks/logs/plugins/profile/2022_09_22_11_42_13/sebastianp-lptp.memory_profile.json.gz b/docs/notebooks/logs/plugins/profile/2022_09_22_11_42_13/sebastianp-lptp.memory_profile.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..854ec4b59a13029728eb3facb30ba1c1b9a2296e GIT binary patch literal 73 zcmb2|=3oE==G9@Re9xZMU&W(w%K!8kPhJn*qBAE?`upje)DPOUYTebqQ`%?0p3v9R b4BKRMrE%3)AI49MlCv4>3(VMTfF=L{6-OOS literal 0 HcmV?d00001 diff --git a/docs/notebooks/logs/plugins/profile/2022_09_22_11_42_13/sebastianp-lptp.overview_page.pb b/docs/notebooks/logs/plugins/profile/2022_09_22_11_42_13/sebastianp-lptp.overview_page.pb new file mode 100644 index 0000000000000000000000000000000000000000..313af2800ebd6060417924e71b5971ba2346aee5 GIT binary patch literal 4172 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 IZP@hx0l2Ix0ssI2 literal 0 HcmV?d00001 diff --git a/docs/notebooks/logs/plugins/profile/2022_09_22_11_42_13/sebastianp-lptp.trace.json.gz b/docs/notebooks/logs/plugins/profile/2022_09_22_11_42_13/sebastianp-lptp.trace.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..53c50a59c658a986357ed1514ea241db8990bd1a GIT binary patch literal 20593 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:h6w22cI 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 Q{MSGJHy+TL=t1)W0LOUL?EnA( literal 0 HcmV?d00001 diff --git a/docs/notebooks/logs/plugins/profile/2022_09_22_11_42_13/sebastianp-lptp.xplane.pb b/docs/notebooks/logs/plugins/profile/2022_09_22_11_42_13/sebastianp-lptp.xplane.pb new file mode 100644 index 0000000000000000000000000000000000000000..2d724fb0ed2f2168697d81de652da518b14aa277 GIT binary patch literal 88285 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%0DGN)y4s)usKpu5obb_bHT2|I$0 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 D)NOSd literal 0 HcmV?d00001 diff --git a/docs/notebooks/logs/plugins/profile/2022_09_22_11_54_33/sebastianp-lptp.input_pipeline.pb b/docs/notebooks/logs/plugins/profile/2022_09_22_11_54_33/sebastianp-lptp.input_pipeline.pb new file mode 100644 index 0000000000000000000000000000000000000000..3f8810d6ad54546933c491bfe6e11ce388b05aec GIT binary patch literal 2881 zcmc&$U1$_n6y9tLZO8uD1#JzL-i;644e4w*v=qmm-6SRwf08t&DJIJHX6DT9u(S7$ z_uk2NwO9~T3KgM0pp>Hc=0m~Sw-zc&Z9%9NDfHD^^hLBq@X1no?rf$Tv#k{(^kHE3 z-n-}fzVn@P?xYf(iS8#>96om^v*Ykv#ons%>aYSq6&IE@&bhLzF)FCNxD8TztlT?cth_H6M*a5m(Sh+LpA^ztG3I9%Un^$gm3+LiFluP5zi-s0 zgjci#pDI)p$r<3xrV1E72z%rDRlaB6$Axs`x!cDs6%n@Q*tJGbKTybP9=A5W)Fx(s zhcU7^+-c2e0+{4toA240$4T=F95}SEkiLHE(23KlR~57INZ+0@-f$3Ez36!N{BUp&&iyt6HI-6;Nd==K^zzXY!}^RqO$V&|E+ zU-zd~A^rXPqcWoQS=eVN~WJyJ+_{`Ag=H!iF$X746< z|8jBvu0sCc?am9;OlqM%>++Mv&Ox>-gb<6II8;%KGuHYdT>LADrZuwM{@wK^W8s|GUU{n&!@1_=p$7}&q0%2jT6wGyR z$wnX@m#n3vBEVhORZ%LCRxVes*G;T^EIZfdb(4#7js{-I;kL{L4OQVRr`(*@k<+je z)T$Z{x`@)G)Vi+Hj89p$YyI3N>I^d3wK=+;a50Y~Q59%v932|kGCVS98kZj#2kOLG zA};z%T+fGyCv|2iv!SI+g_tm{rv^BpqBAd7Y5FMvk7sDf@Z^LBY$iN^8^#u`C z%>Qcd;*%REwdG!WCR=-p$9ouNY8F}JtBz4@FVVC{o1`6yIy%0*ZZ4HW3=mBjtTx%6qWWXz=kyvVCgcGSCAj+!&so`J^ z1vn;|z}$d~A3>xJ#HLJhP=Ld{t~a964M5-lEO;Bp%-nb2i3C?wFuANhNLHub3b}lb+nY_27c{zCAt&62`kZ` z*pwJgOeJO#n;st+d$Tk;vSs_ssbuQ&WGuKwMHMaOGZMrsI0PG)R6vW-99ua-j&sS< zS;1fWqN~s#07lTHOg>ALpdQopqyHsI?3u@;5@8K+>NzBXW|=+uANsP4k2DKvGk%iF ztggOHFGfT7rh7W16XNHphqDEdaij>Gpm>6^ds&(UKUg)Fo+vy6M8qqWI!;qbi%Jx1 Y4PGk|So646qy#>E4j72f8D7ceUpfj88~^|S literal 0 HcmV?d00001 diff --git a/docs/notebooks/logs/plugins/profile/2022_09_22_11_54_33/sebastianp-lptp.kernel_stats.pb b/docs/notebooks/logs/plugins/profile/2022_09_22_11_54_33/sebastianp-lptp.kernel_stats.pb new file mode 100644 index 00000000..e69de29b diff --git a/docs/notebooks/logs/plugins/profile/2022_09_22_11_54_33/sebastianp-lptp.memory_profile.json.gz b/docs/notebooks/logs/plugins/profile/2022_09_22_11_54_33/sebastianp-lptp.memory_profile.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..854ec4b59a13029728eb3facb30ba1c1b9a2296e GIT binary patch literal 73 zcmb2|=3oE==G9@Re9xZMU&W(w%K!8kPhJn*qBAE?`upje)DPOUYTebqQ`%?0p3v9R b4BKRMrE%3)AI49MlCv4>3(VMTfF=L{6-OOS literal 0 HcmV?d00001 diff --git a/docs/notebooks/logs/plugins/profile/2022_09_22_11_54_33/sebastianp-lptp.overview_page.pb b/docs/notebooks/logs/plugins/profile/2022_09_22_11_54_33/sebastianp-lptp.overview_page.pb new file mode 100644 index 0000000000000000000000000000000000000000..69ae79d6961bd28e3c597a559948fd56e5da3532 GIT binary patch literal 4172 zcmeHJU5FD`6i#A6JKEL;+}2R>CO$N?tdl0T6r*dhyY5>5cGsA0ySvJGGjk^yGMPKh z+-%HREC?!sBJ>B8B8qQ56ju9CXrZFi7KB=nLg|~e=!ck!31a7nMKD_!Tzr2#^vlrcQ<&wmmFcaMjF^^wZ-UPIvG9AQP>>aQDQOETru^aieb4_GgkD z$DMUAw~^Tw6b5IPcbsF&6VsvgRzp`fj?>aLvj6bjO!Vf|;ZtWIC=>nSof}h!L)}^N_MS!8KL2KSCVAoFasB+aFSXGb6=DyEd6Wzlp{{x+ncBGYXlF;HEp$!D{&nbfjX}R`TJh?$ zFtm94xgDX`ry#*krx+bMSmsfuS_ou5u_O;ZczsBK(QzO^G`=J(a3kZ-n(^a zWmdc&n*8zdzMYxmfxD4Q<#>2Hzx34w!uEc1XO&bzc#kym1!N6uYwx;nCcv^9Bbpo$J)Na9uSc!NXhXw{Vtsm@{ zgsXFM1gn0PkOuulnr;vmCsrr0sgNcwR)vCbJ{1BMUr5(I*M#+Vw>03T-F0LGT1=PuYBjl)7RN*&t?-m1dtjKae8|wN<~l zih&(RW}5A;@`^&s+wp+LR9BvwMr_%ygD715)231rsicBU)$6HKqE$mhJdUS}^@FHq z?MTmHUq7ny1Hx6zf7;&J7uPRpvwQ88Y`&X)z9-R4jzSbZ3l70}*#EoWqob^mS!eL0 zCWcQ3g*2;ML@H8Rgn_bjM*`1HwD=q(=U!t=y_7MSC8CsjOl;I0-3gb4xnRQ($qeTQ zDRLOG5YsCJRlr!QHc=&%huRPgE`eKr11`3%Yz5GHz}ySHE32GJ zhXA*|SfDeI3Zw(QfenFNU@TAwY?#+K{H8oKxM{R76$*bG@(EY4U51v@fHq9Pbv zR3e-V$Jne1U~CkNR|S6YgRX=viI@saD~-s)M&cX0Q|+929n7^I?<{f(t9h(&dIX z31oyL7OSeqqzT0hwhE3FH<`DcGh#M8w2_z~gPL$8OOfzs!2KJ|?u<=+`s<1xLfP1v zx&O9)3c?Qe(jZ&9MGUw}$e3$)61c~SV-ZD%eObT`)?W^zs0~=VuE794#EorZm#g8;7KnPmgL|v2a2H$ jrl|*1(Lm3Z)ckqDg~8YyXbyPe|2}BKus{`O?1O&*3KP~m literal 0 HcmV?d00001 diff --git a/docs/notebooks/logs/plugins/profile/2022_09_22_11_54_33/sebastianp-lptp.tensorflow_stats.pb b/docs/notebooks/logs/plugins/profile/2022_09_22_11_54_33/sebastianp-lptp.tensorflow_stats.pb new file mode 100644 index 0000000000000000000000000000000000000000..2c61e8e749bd95d85bd3c42dc88109b047a890db GIT binary patch literal 131756 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

RI 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 a;Z=f4i#pUiX>NntJbbRQE620>?Ee8QCX;yp literal 0 HcmV?d00001 diff --git a/docs/notebooks/logs/plugins/profile/2022_09_23_15_41_22/sebastianp-lptp.input_pipeline.pb b/docs/notebooks/logs/plugins/profile/2022_09_23_15_41_22/sebastianp-lptp.input_pipeline.pb new file mode 100644 index 0000000000000000000000000000000000000000..6f2b79d61792e13bb0a9b04cdbab5fc8b9601d57 GIT binary patch literal 2881 zcmc&$UuYaf7{7~xW^J|Pp_-P^xvPJ&ZQSz?5!t5MOWLGOte1FA3r(rV-0tk%a=SB| z+1Z@YCn*ssilBlPeK2i>iWaN12!e{$mPVyQ!567Yk@QVPMIY>gezTYL(j00a1s@jn zX6C-%@Av(_@0;yNtV?Wa?|l80PtnQrWIi{pbPWr_v0z-+i;M|fAHy8GE^!~m{@&c0 zWaovak00vWFlVGj{}_Dv$@xd}YP^z-SM=3mocNrXBnTW@$<>tm|23+vPdNVm>;YXL zVw_A7UL-!j0>I22-;aHC%TXhB_1i7%^YrGty1MhZV*BW8Mz;OqcXi%-Pkt#_sPruZ z>^=$RVgafm;BAbWSP%*iz;6s65?5i0gdw#zC+1d5C zwZP6KmBPw!_e)OWga(Z7b{$jl_~MCIoio25G*Z@;_3zD2uF9+NN;Y0uDt}P9^;#Mb z=7Fx{rJhGWGg9rhKht*ld@--i+ZP6oH%TxF28x?=Sw5$ zyt;nmhrv@_fss9ZZth0hd(~J1qhDO592lgNAqk=Ok%a};(KHK@ho?~;Q-K6SCiBV; zB`ENqw~#~qP(&w@Sq*6|fE74olRDw33|lVd6?koIYRcK zsUss{10pth*iR!NNr|oLQrX3{mhM~F1f71j+MB_Bi19@nk*Jb}#?hgnUBiVzO}ThO zkzgy%60*TxWIHa2cw%b`Q_qERCGp$w3!REWe{O&k|pXN8%EvNLnb8H zCc>Ea+L z37bc&GNWL5D<7yaD=JUhCcG5qK~>KFqp6G{i+Gq?4NrqA3tbDzIE}g(E};JHd;1I9 z22m*Qji_S&S9@2U+&HOC_gXXA+*>)`^)OSiP?h(SqtITwVU09NIudnse6KfK(_}Po zWHmH>TTcJMCqf0<*@JE_RYC|5O&O@RpfyR0np^Ti-HshiRm@?~F|mN`2>4M~JKjht zx|sHfR$;6H4dpw51~WIaXwCt+oHbk#)D0q{g^4}l`sH|(FY!f^a z@T}XoZ{czXY7W4_NaG|Bh}rP&1TgU`L>rh;^2^n;1GI3*+zq71f%5=(SF@y)wF-Rg zr4ySHxrCk=NQ@+kiHSrxF>>>^u|1{H!mfSglWiR*+G4>T<~6XCl>@@3h=rhWQI$wB zl4CO`z;Pj2GAr;)UUXIL`-CDesXMD8!LdVS{m6d>DE7>uf#9J>VCq?@8_d#r;2ZAAkX8tvs}9T-K!%aRVS>U5Os{3BA^5bETzaDLlmH@J ivDmU2N}5!nU|Zl?iNG4ir6R%MVGF3(VMTfF=L{6-OOS literal 0 HcmV?d00001 diff --git a/docs/notebooks/logs/plugins/profile/2022_09_23_15_41_22/sebastianp-lptp.overview_page.pb b/docs/notebooks/logs/plugins/profile/2022_09_23_15_41_22/sebastianp-lptp.overview_page.pb new file mode 100644 index 0000000000000000000000000000000000000000..1a062e13de83f1056443129925e139db930c4d41 GIT binary patch literal 4172 zcmeHJU2GIp6y7Z+*r6!d2ec&(cNc$l3hcV8F=qMMZJ`A!v}IX{Ey4Bf%$?oI&fYt{ zbEix3$q-C17!x&7q7U+8f>9zE(8NRyD1@rPghU?*YKSRsYLw`MJm|TzJ8bFtQ!U09 zn@rNZbLV{DIp;gyy`fVJLxGM!S8MyLFMWiLMMg8poYJ{L5RL`osZ^FRkxC6=jxCE= zo3Ontxggkn{;4B-S1+DOhX;S@eesFO%^B5SN%$+N`9qx8oN2^yOj=Bql?VPbYAQ8i z+S?O5QmH=1$r#~TViPO?Ok4NO&p{4!)93w4Qn^#aG^& znGWVEt7iaqp9Hh8fUG>=HH>Ol5DE{#b}n9i{?04Ur^5@cgbp4!+nG`6>GzWC^F8Ur zxyjb24=lR933g9V8JHdJcF8G6sKfXc%hV)~Pal8TJpJ?TbXdQ#=$!+jZ5h>HN%$+% z)9+PoyO9Qjd9X8hY1yM6r^Bsx>}xrBE}K#J+_U%Y$?tZj6I);SaDBySYf5KWiQE`w znh?B}LFkj0_P0Li98ZTY9{TL3rC&ajQBO=d3NF!yz*Ll8cga!o3f*qj=IDJ?IRrvoI>NwMHM`b zs+bBS7}8j!U{Zpd3d|NVsqG4HC(=qTEjzFRn+#GV92MY|g?SPFt-XvXXM$@XDzc{z zSp&nQ8YkExh`N=$U7y~(20$_{T8UAK6Ju4RB!umx;_+&=8Uy8n>Y&tcM8!vqZFVH^tVtV>+R- zG8b$ZBGFK8fFVZ^8ws;QPz8+DU7K*&0D{*D zDqIIaK&7LFvMzW=;OSU0Tt6I~vI#I?X`DC$F$4ZL9dNuNiS>*qnVIIZ4szk9wgpJ% zfO8M@uB^*c7AkPtiv+p?$v`U56X*|Q10#V#p#Ro2LtFEM0~?16$67*1Tl|D8n3tiY ztl$tnMsx&&i%LW$BRMu|0vzkbl2w6U@}MhW+a?r2lcEU~364!F^&`J>kl!^1+?tmvH`H6hff+$j!vsNiF{fy|7Qi3Y8i3DH z?Wibakb*|?W2SeviCT=65r)YDR193lOku+DU*{o5P9`V060DUxVxTea$e;wvM%P9Q zE)L$jfHq}(B;%`*oRVz}eBKdQ0Bx`tDog{K3ExVD<KeP zBO}Tqvr58`BrjtghX&)WeL-b!a3`uo4MYdX8-iOZ5L!*za&lh3RO)}@~Gtc z&`{kLrO9@UE7gBarkO(z5pp_z7ux3qmp2KW+@!4fn}#QEF>sbpP%PL%s7;aP3QrQA t)MBMG3zs=i46A3Fyq+rR>)xE4cWZD#Ffs?41K#+*4^kKwsN#%$@HeWX-6;S7 literal 0 HcmV?d00001 diff --git a/docs/notebooks/logs/plugins/profile/2022_09_23_15_41_22/sebastianp-lptp.tensorflow_stats.pb b/docs/notebooks/logs/plugins/profile/2022_09_23_15_41_22/sebastianp-lptp.tensorflow_stats.pb new file mode 100644 index 0000000000000000000000000000000000000000..0f824ec2df1048c89237ab34aae61510c2d2afaa GIT binary patch literal 131384 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 H4V(Ud+WQES literal 0 HcmV?d00001 diff --git a/docs/notebooks/logs/plugins/profile/2022_09_23_15_41_22/sebastianp-lptp.trace.json.gz b/docs/notebooks/logs/plugins/profile/2022_09_23_15_41_22/sebastianp-lptp.trace.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..3b9be0eb0c8c6228f66bc38ba712d893b96ac3a4 GIT binary patch literal 21611 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 D-{_*sTBzy8+K$4B|i7gw=;DjagX-$`; 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 literal 0 HcmV?d00001 diff --git a/docs/notebooks/logs/train/events.out.tfevents.1663844068.sebastianp-lptp.1320413.0.v2 b/docs/notebooks/logs/train/events.out.tfevents.1663844068.sebastianp-lptp.1320413.0.v2 new file mode 100644 index 0000000000000000000000000000000000000000..c3a5985d42d0cf81f791b22b4f015c92de59526c GIT binary patch literal 671910 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 literal 0 HcmV?d00001 diff --git a/docs/notebooks/logs/train/events.out.tfevents.1663844068.sebastianp-lptp.1320413.1.v2 b/docs/notebooks/logs/train/events.out.tfevents.1663844068.sebastianp-lptp.1320413.1.v2 new file mode 100644 index 0000000000000000000000000000000000000000..bab3605456b188f7f2cac114e23e88cc3252e211 GIT binary patch literal 212670 zcmcGXbyQVr7w%O=1QlCsQ7jDXPHa$7Q87>{5mZzZyRZurJ5a>#ZjYVV-Q8lN*m}Qv z_hIhwymQ@o7;BGp{yEy_rT7k zfBX4|1crH+>FDAk{D0j8`}7P9ap~{Zr>kGjfWSI-sgq|)Rv@K&rb!jt)7aVC*@Ol7 zh4}RedsS+6ia!6Q7qYH8%65Fqf765P0`1&|ge0Vg1ojN-8~lHh0>ctd@Nx5>T5y6E zIS;mK_wNZNT2@!9K7nEQn0g#N9}KPD-;|VAla{VEe<4?^+R$o`_)GJl z)rb>GY4v|6kXvP=9^bGyKeQTgFDb3Epd?K-YHrovUjHKGQS$Lt+ljW#OuO3H&dtu{ z|A$cdjxHfxy9b7J4er&eGuz3MJ{&=WQDpfe-d)9MB^uIJ5}Rne;l-c z3sX!)smZqO-6_rjM>tNbg^u`>XH5m5=;b~yQ;R8#aKxYbiX+~>T~rAuDtd|XMT(Mk z-JXjQoU z259$;JDovnmo2W^E*p3KmgKFV-DVvrN^F-!X|>BHb5FH)8#rR`NQ$$-5vxD9M@Q7z ze9<2$I)A*A3EGrKIAVzXEObN%hgJ4Kk^L>o7b(*3h(brdBgqRUl;{8ym3U8Q5Gi7d zt5U?qjdfd<1}O5d^GSTTMT%II7Da5bWY=pHgmxPgrZ@u}arQ$qd}PxXNr;7ZH`Szk zv0eR+Xg)9-I%4Lq{dUl9)i!hnv0b*fYP)RQa{K1^K)dC7P?Xp%i_&VBO}2fo%VBUt z=xmC!z!7=R1)(Ei&yK7N6kY2VV1m}#2uEaIH4hz8eUWo|plHr4$`>ip?+B}{Uyt~vdK!mUq1~Tal(V*EO5mAkzweFaeKej2Z{#03Nk%{sf=*M-;l-Vh#9lW^#h9T z{HA=7BK?kNTjC3nT>jkAwLsCCjKPVIfk+WsT$Lg=Zp80aE zgnxy0dsL@50~|5!eM5X?e>m;E2kka$PWfWH`W@lqnGYTD-dE-mJ;^2t+_2~>EMQm|ZirBa*PL(kS?ByA2cX@E@f2r(BOYCxc5Zh&otG3I=_1*LxpKH9nKv815EJ~|gHrch-H9vzRGX9}B3mj3p!5DOe_b{6q zKvBCRp(aP9Ho_783NArMoUXC?2~bq|2IY$s>32klgajnHdcugBK+*F!I)g|NTU?bQ zHm>XH4jI4^g_HG8e7Hr5SdVlomy7vV3+2=0Lld zuTq==ju_BXaYXT7>+tgtx86~{*sgv@BwONwj!3z_?{sK)zs-TeOBCiLTAk3p3CWS&HY*3l#Nk8*X|8(-`51AfL79 zh(ar-76wP0=tcP=Mfx3a@3HcFL{`t$sez&*kz$vr4aq=-dnQN$(-7;o6F^aRm5jPgk zM@O^{NOch?$~tv|$r0&{a72o9>+w3`$T{coK+)+p$^#?3z4?JiLC&tr-bDPmDt6tT(X?>IUR+HH__Vv^cT+K#H@-YKWN_qk`J z%Ts8#N)gHz+f7=&)??6eRz-BgZQt7OpxxZH=nP`JY;pf{+=NGi@beK_+fbC)E{jUi zWNxdkt_Mf_kK@F4EpWu%YEkHj-Sb-C1BwnsPBG=!8{vo|eu^W`o}977cH4iT zI0LRDVy`yB_ceB;tFi>zb;>q1kuI@a{f-E`QyCpmbJpF)&~9`^I)m6QTU@nWHtxqM zsUo4>j?E}aY?no8waX@3XyinG8GKlenVBXax>xeXM(iH5Hfud1QDN3Y> zMQKsQCL0!aXDqZ^;1|Ui;E0Po-SLr~^TRd(+KtOIGm$Q_UHy(&W>pOxF|L-?PG~oK zT{?rBHt3NLCIXGfOAjMhW zh=qAqp(9rMRY?mJrGBx{)M7>>9IPgq)5LbRv%UFA92hz9>4c_ zCjFws$3UcrEv`xt8@EVc!L~rrpCS|`QpBRPC}NY1Oz!s<+WlFL;tX&^?%hq%5gR&` z`v)9xpc&J5%q+nLTFw#yb*ZI_LE@puV*Un6)RMTzaQD6Mwc zWLhvQpBRPC}NXMc<&Mp?Y{A# zI0GEfvy1Y*&(in4he5kPd?{aSSHC05tgVghHrqWnEjS{77@a|Emo2W^E*m$QkLw=z z3-EFrMTzaQD6MwcWC_)?HU>vjTT5{kIKpq!dUV9hsCD?Au0yWNO^(QHgdVNU zY?m#r+AbUSQSk1O(5}s8iW1vpQCjV?$wI0(UI&gCmwZLy?pol83n81(5lesejs}Xt zzppmsWHG`K&PAi}I>Ki0;0{31)68oU^F@mEJEF_Hlt|GjpPW5`qKC!k3?fBraaD@g zxZNi<83h!jaiu7cA{M1Z5u2>a!s&aU-OFASXMiJ|oLizJ>h~Sv3GIf5P`=o%enz4lsU1+%%Z>6yiu5~TR$XhPXxinSVc>|f z9q9}rMQm|ZirBbKyKjC46kYF4Q6fbwN{b>k*+0Ls;Cr7r$5EUCj(D`E6*|H?=*t;s zH(?&-i|y)n#I;QIv0cYJx6lze*3%ipcG=>p?Xq#lc3)5e+HHN1qQrJtlvcZJveRcu zodriMc}j5>I3hTFJ369*$DDTHh)S!rm>iMK2uJh_S%8jMRxw2aP*mw8<%<;Qcf|MF zsgR;qJ?jq!M-+HOXAmi3i>p$^#;ty7L=aFk;2TAW6tO5Rir8drXUE_@X3p4eO;Wo_ z+fjAgkrkAC)lI#dIWx3dun^^o?ItZ>>oIU1*#O&h9sczQw0p5Wok47uE$)AgTXJKu zC}_7!H;NM5Wl>3*tej8w?cj)yizvW(2$u~zO%yp8;fSm^=At7` z-RqkQC`xyX@aN?+fjAgd28F?b%ayufwiFB9XTjpY&U87T91L>&W7lSZR5Vi zLc0zwbOy0qwz&T}?(uPbHbJ`~btp<~mqjIMvP|_Z-33P!=|*uDIKsci9(2UVuNO80 zMK5pdHBpq^2uF;FnuCsL7~H@YC<=K?`65O79q~PPYNTktjn6NjXl}B7iI0Iu5nEi9 zA~tU0?AP(T;qx+6lt>Ya(xQk>_Vj+ylF;t0!W3t~bB+Ga?a&d;M$X;>?cT0J`C_~J z9r5F7BW!or;~R6K-IGn|3}U-%an*L&xPBWt;;T*fd?-q6mqlr{%O=Y;@r-lTnV6e#-e^?+$Vav0%=K5nzo5iRCcUjP)f&T=p@U!+LCBl>+&91+wh zdN)v1zBHXdq=+r9N)a2kkKN|^@R!ETjiN+~SdXMrQ4V*f!$WPI~6D^OHv#WB;4<}|_)`9qcaV&4jxiO)4g?52E? zBK?jiu+0`Jio8|I8z{bjh>d&1rd(}s#Jf0(5-DO)S`@L#u1yF(0qw>o zKc1v^leVMkxP>Qpqa)G;Cm#=vD3y)!#dedHuk{$*{H{2n+`^yu3AuYk=?r4KY;pf{ z+?exU4?(-ls!^2KE{jUiWWh(>ZNL#Zdr+JOj<}cN5ISOCw#nClqRMWkO%&xa!V#;N zMB;TsmE!vk0Y!HMDPN>Wzay5futP^&&bPG+IAYr{I)g|NTU?bQHtw)p75f22&!t4(C&w26lcJ7ME&9&&=CRi!_X1AcTv9Bu6{?POw$D0ty(rV544*y zmd+ry%NAE{myP>v*7!-#?uok;CAQ0=wAy8pxtw>-1CBVCJT`H6EpUW$^&{wrt{ZxE z2Z|<5J7>ztZG=6f@ipUymrWi_RcY#1>bj zh>d&1>tacusN^|{5-DO)S`@L#e*f}G4efS(NO1-@;%)7Y=!k|V>I{N*E5}p5*sgv@ z6mn>aj>zBs3f_n6nDzNY!o_yk;;QYkaoxKW#qWmq$VpLRyDUnpT{c-r@z=e<5p8Nw zoCS_Z=yD7lVQrhT7*Nz>^(E6In8yf5xY{d@@cor-IZ#yU0OgAm>32l&3W_66eLVUU z{?c^6LT3;uVvDO%#Kv7eKL+nZ)%yiSi4?IYEsEG=t8NCqgLeIXP@DmdNV!*WMB8pD zYC^jn=`JVICAO>I5zX^>pd+H@&e;d;)^wsXi0!h)Roi9bUP<#d7yJcSU5TQ^c3G5G zyKJ%=ZAQ!nNBDH2I13!HfAR@*#PG|xasfq7cdwaR%xi=r-Y=Yv&ozE6PlI<(&h?S< zMT+!0V(yMKNKut~NAYTOlJ)h($3UcrEv`xt8~6T^5sQJM(K#qeq=-dnQN$*z`e+#5 zV`ghfiZj3w6MHDX_xWl~or~azPp*_NwyWO}S&BBpb_3J>u?I(FX-8)e+hvQZw#&w? zo2sM@wA;KVMTzaQD6MwcWbvoB@vL6XAoeM--S3X+~&LC367FVT+jeF`v+e|=F^a+X*DPmDt6tT$~dDLD3j;Mc&;tX(vYrNtJ$4~eA zL%V6-P`=o%en;e<*8;C2rcGFYzvjC7FP%Ybmo2W^E*p3C7QY72ZnsQN5|>GAmqlr{ z%OT8ib{EhQzdk!m1B%*Cer_78fDw-H+NM0$$hOw~7*O;jn({@8 z^gE)itMXhUYFG78_)GJ8JDowKh%K&45gYe_&GsHZQP-0cB~rwqv?yYe6@NDw?+)_e zHpLm>h~eJ8cpZ^{jJ*rAd-g5mi|y)n#P4RF=!g*$qq0G}%~HHbBwTElEw0)w8#lAx zx=YaR_be18w#%Zl+GUg7Pak>=t|MAip*Ra1ajx1Wbi~H+sdzWDvkPCF9ziD~95L5( z20quwe0=r@py=mD$`>ip?+CX$iX&X(_umDIG995ah!nBKRViZQ1{L#~QDVC+N~>Kq*`yU8N`oV2hEkjbj`%q23Ob@;<<>iZ zqB?Q!Of42P!V$x>D~_1criKGhl=3g-ixla1g!^~J5x;JA$_^9_$^1U?F%T(Yi>p$^ z#_hduv^_W?$eE%G;V(aCL`HBeN?mGVW3^gE)@cjfaD-RAegZx0vh zKxYssVvDO%#KxUps5ky1Cq%;dO-7?h#wT5&O5$8N_zk;;QYkanpaX#_wyKKTc6%yDUnpT{hV{ z>qT$C5ixHm&H_h_-g^Tbk?mo{1fb|u-LED`6gI*U4-Zd7N93ybd_6eA*NgH+iu60; z!V-I=$Zu=$Pe9RxU^;_H5nEi9A~xPginG8G{R-VhM+CSgWCM!UbpLB|L{TFg zk+ab#bi{}AbMTj((u7mKNRfU=tgf389Wiw4k1IgY?iq9jks`LZDn)GE;oUajeX;v5 zrznvk7NtcIo2=Ny=S!j8m|YZSfFlYXQyeiO|M)KGh*-)O+tu%gX-&Ma-OQU_^oMp2 z+@&*!?XtyH+hyaXf3&y}IKtsQMTzaQD6MwcWN!+3zXeBxWlFX${h6Dt8HyIOz!9lN z-A6}we5u|5D4O7IWy*0j!V%WTN1!9>FTDL5D6;89`65O79nm*lam4HfLrMTeaiMeu zks`LZDn)GEH6>e428s@hrYMmj7NtcIn=EbD!Iz=kEORN&07ul>syHG=;2-?G&y4FR zUu;*uBgQ^g9Fgb6J8Njy?f{)ZY?m#r+AbeA=hv#xZplj&CAQ0=wAy8pm3@0QIXJ@Y z3&mOBhzy4xq9dX{mKy*ReV$-razrsB9FZyiNOXj~%S5~yjafwbB1QTgG5nt5h^mFI zO#q7eZK5-X6tTrsDPrSpoROj#P?Y=#MTr!#C@qTEWZiFf!oL73uTq==j@WTRaYU7b z4fw8Ah8L7CwyWO}Cp)&m>xcpEqn1OvUB1&9#CF-@s_n9IEA4wZ8rrRrCUxR6iS4o| zt#;XDyEdi5-|~xcp*Ra1vE}n)bVNYZ_)p-7t>I}*V-+{T5fvLNj@VY+wk=#o42z_E zks|$$82CnU#AM&B$$_F$E9nd(MQm|ZirBb6KmEjCX_>K`qC|>Vlomy7vT98q41so= zouN1b9I@2BT zBl26NO1U&ADp1q203=Db4^#+)v|=?|m*W?X?0NG3goQi|y)nM1#(4@j4=ZzdGl@5q96` z3}U-%an*L&xEU%P$In?-vCELSOk%q%N~>Kq*}|SZ@i%yGmZUff98t>q1v+B#+HLQF zqDE^no5m_>gdTuG%gecU-9(8=>9LEh$QDmqlr{ z%O<;i^sqZPqU8XJv%nEUW8=^f?LMuU0~C!so67`kDI**);njF_#O}M{*@2>Y4=7)x zNWUY7J1UL{D;|^p6#2)~8AOWM;;Iy}aW{>v=LHlEN|ihD;T9=kQJNH~lLh6r`VQ>| z=AbwO9O0i{am1eQ$?&;GuM(6mwyWO}-|s1oxa?rR1KMp|i_Rdn%NAE{myNsdP^K-= zZZc1b65C}_TJ5sQwzLc10gj05PjMDFVpH~a=!k%)qm~0j(Z}+cpe=2LBW4{MjgB~S zbKxX#M6a8aFH)r65d}9X&ox@jySx%8Y8gjo5Gi7dt5U?qU6wT%?^M+24@HR-u_!Hy z*kq~ScEjKMbj|3Pq;`|Gqw2Va)Yl{C`%KOY?e2D>e6ii6 zdn(cy#CF-@{^z)kz2l<65xLwcN^F-!C26u+bjh>bhk zAz}tl6p*H1;=?Uc#Gkh$-I>9N}G$&LFnS7FTVTjr-|g3w+Hobz6!O+htK&?Xt)Y+aKxN^iX--yxY6)1XEl%hn6Sd1wpb*DM=#r#J%~@ngB-h^Y(5uY-17!zo{ESHB~gip?+B~I%4eu<#5aEiSEHVF=?o%8Y;jeJ*tjdYZ;1qo zW_nSSND+(DqKHklBx@Aj&vHmtiZj3wz1As?c-$lSBed%=l=8)P^*f?qYsC>+t5;qN z?S7p~XAs+Ei>tQF#(gz%Eq;nNYAHpD?XoDXcG+a{+f(fXM^rmOaTYk@nCmZe#HlAQ zUBD5!Z7Q1_QPBuTbn{mnQR&xw`~`+4xhP+xNWUXmMk$Wy)v8BsplG8Dok66CEv`xt z8~5~yL+;>+5Lb#4DPmDt6tT&6hkLbwcAK}NI0GCp;g;fv$e2Puz!3wwP`=o%en&hz zs5qiX4XZ=Y?(Ttf2C-eXxN5s>-1M_r9fWq%MNpL3E{oD?mrZsdO`WIUh{GEw&H_iA zTmJ_g;pLyN3Q%-5U3HTqDjDI3RSlKTVrOjjbq7#XCqLzj6zO-w#zKlC8eb274-}Ov zPiGJ*VvDO%#KxVSw?PC@6xEQTM2c9H7Da5bfC~TMudto-rZ@u}(f_96h$b};Re^Tn zdQ!gFu6{=hO5YKmYgB(zU=Fl=;E0@)lhtrfV`pn;6BghX;@2mvX7aCi|A_g;YMUHU*$79(wpBhKF?n`c zymx+N4ayfO((j0%R?6oi?i`zl-}jHz0!C!#;eJRcWN5rc4kBIn|COtS}&3MWe+tu#~2QS4DPou|O21gWJKxYu!WsA$& zRmbg9a=}Ar_x5^<65C}_TJ5sQQhPTn4~_`9L~#~4!ud#YbVS--4)}eI)s^a*98tvx zM|cD)_o15Wx9c)cRNkHPMT+!0;^RE!bCy4*HERtNo$Ekn5Gi7dt5U?q-8UjCGf-5n z7e$E_u_!Hy*knylZaM*uI5?8x3~&kURUB_PD&~BkwlrOfc-w~yjD2~`&Y}zhp zx93VagV-)xT(w;`Zt15z(nGs3yD3U+mqlr{%O=ZOW94#i#QFOaXMrOkex^W2G|jcK zFHlstRU?xlsv6;l$=S!@`x=!FZo}UMUK2$5B1QTgG1*OVME4_|t^q|g2h$luirC_+ z6tQv3SIw0jC>lSRqC|>Vlomy7vg_g9@i&3}mr$Gmj&N0MU60cl#CF-@s_n9IAGUa05ZZORO;KXIEJ~|gHrb;7FGhkRZ2wZ6 z1&%maDJ44MSBj7;yLqvP?qoq(e7V9FOM((j1g&y;)KzH7Su zIZ$+MFr7i9h%K&45gWH~NGH5k-KZ%PB~rwqv?yYe`FM}p0`2~ep*RB^QR=yJ9Z@Z0 zDt@PH>`uxT+tu#~doRTi-#ZPe1MU7iO=l3>Ws9q}%f?+b^T0iDM7_HdCAQ0=wAy8p z-KbM{H#j2VFU48lh;#j|(GgphA88L1{jJm7lXova(1UPh!nBKRViZQUhG*MKSR}bI7NvRu_!Hy*kp_6&)Ev?Hl9Io z1~{VECdCoyx76{6zW_OxQ@+@)en&iyQXEn2dXx*a+kGdUL2Q>TuG%gecYK4{ZNL$` zPf?WEE{oD?mrZu{y?Z1$BIFIlS>TAy2U4LU-p5_W>xiDsTbUeD!w5&ri&Px3;o2H} z@3TZ_$`>ip?})e66-PWCowGhrWHXS?AX3B@SEY!JyWYE1WuU0qB#II#Vo_QYvB^G_ z>{J095w(cojBvzY#SydCJ|72;IK7eb#dh^O;@dOD5vSK@d_Ae6CU93Pp+SvM8-~*<@$?U%n2Gn3q6t7C0i)I~#Pw?hToD0Y&@jv^6=RrV);4 zkzaAd=s&-Y07c2XC|{&VzavKYDUR4(uKXLIXnHW6L8OQ+u1XObH_L(|^}!J~Lnun5 zh(&2p#3r+wH~%oSdwB}Q8Q=)35sD)kjIU7>+C30W`C_~J9g(Sw556Ap_4J+B(C)ph zbOy0qwzz7$Y}~RA5ApXkE+3;Pv0WCW)h?UtdE~&$;D~jvD9!>$tSxSfj(8FlI|(Qn zR;z=_5w(nPgkvh@z0a#98*c)NI(kyRNRfU=^ysU+_vv!I;cTGjVP`snND*6Hl_ECo z!7UF)fg|z{peT_d7NtcIo9xb_ppDS(yonTNfFrDf6i4*v6rT**J-d+d#dh^O;#IKX zh^N1l`$u%xNM{h+Ws9q}%f_8`yz(??clu$965C}_TJ5sQDi`0F3LG)$8O2%Ph|ghm z=!g@0Zd3+}YM1jhIij`^j(D;{`3zODBa!$UJRj>*zDSXNN1Vy4e1>Xl&h_}a;aS_# z8AOWM;;Iy}aWj_savLZr-i@L}idd8uMQpMI(<_ESyR(NknZvs3_=gCnZUr!$D{vc*-~W#i5%9-aZ(y}yp4#CBPf zR=aGnh$gdhgCjm&pg0R0ao|&0bi~d-2fKnJj^_(DIiijcj&O8T?s;3Tb^grYh(+Zn zU!+LCBP!Kb9I-ci^)R65SpzzQND*6Hl_EB7#Q82yfTCvYDN3Y>MQKsQCR^RL&RuAC zM-PfKz!6q9iX)y^?0gv74I4rEV!Qes;Ze*NUytb4KOz>|b)HFQ5Zh&otG3I=&G5K% z9JG691x1PNvM8-~*<>G9*Lntyh>WE;3mg$v%pM)l-?2(jpvbFeh{+Lkjc~-p9LjZs z*JitHKvAn|lrK`G-x0l5D~>4pXC3}d*OjJp29YARxGF_#+&AZ3egj2+d?`w#h(&2p z#3t+5x^OvYcXt@Y8Q_TdKYa1t`L+EvHGy{bj-!0BUHy(IGeU7h+pf>sgCq9Mr!$D{ zvc*-~W#d*!sJRW=owS~!#CBPfR=aGn#>M}60FF3yk>V_H#Mhwo=!g`1Ug3M6zTTlG zN7OUI5ydkr*AdoJkE8&KriM|zNRfU=l&z;Y;&k+nJU~&AiF5{$BDT0HMQq%D-JYEU zita9^D3Kx-r9}~&Y)$=$ir|Q|+bGTeM^yfxIKm}=#evZ7%+r)FwyWO}Gmj{as2H)L z6SUjsKAk~qmo2W^E*p1dBcGnoZqay(65C}_TJ5sQyh9rf21jJf)jM%_EpSBa?hNRN z8}BCF2a2M?`+*0Gp2SdBL?fNAylh`hc(rTAYR`kX6G2n=7 zWhl-9M-={+5gjqK>&m%6QQE!(O=C4M!Vx{)l;;|I{2iwQMSI6lzDSXNM+}&zIAY7? zXZ+P(gi&LFnS7FTVTjeBBY{2XXE(+`Rg+htK& z?Xt=K_HPjkj%b^AP~z@d;E28zGNU8nQ{9;Y6om{OYRYM7gd+}LP~Q7|())ZUI3jK; z<%<;QcSJ*H<-N~4r9R{95nGqi8AOWM;;Iy}ai@pg>H!p0*g;VuMJ!5-A~sp;mpAZx zpU+QIoB@uwP*Ay!crkj*c4#;DF6E2u>UTuZ)`}xeUU>5p9FhJ5ok47uEw0)w8#ni! zE*{YCX{%w0%OtkTqO{s&lhxg|<~2BCY*C7{z!66$WkE+c4*QWF9MN~-2-8@NjBrG{ z{>pu*oI0;Q1{6)&Nckc~`W^9crs9a~j^FkIMMVzN8AOWM;;Iz!aZ7i94it^JLQx_` zEJ}+aHre(Xwe~@~$(~c30gkw@z8-OR&5J$IZtHK9FSe`S5miGKM@+vl7=K^GChf>X z!o_yk;;QYkaqY97eg*9g%12RRyDUnpT{hX|ah>pY!-v+TI13yx>~>ak#QX4Rmw}@C z3&)rqK{q2D;b5yc;{3~_1AwCU8z^6-NWUYd98w(7Ilb=;a73m?XtyH+hyZcUTOUr+P$5dqQrJtlvcZJvahijJHvIv-&z!Bfg^k} zI-nz>a!!c@imt{_Fg=3qMmS=ki{gm)Q!{=Bib~o{Ow1Q4((j1Z+Z0EH727!-C`y)- z&LC367FVT+jXQDZ>d`>a!x9uFQpBRPC}NYfaPdqA?S867aRxY|??vVHi1@+P>p;7g zJt<#oSHB|;zEvF2XRix>KEkUDok47uEw0)w8~5Z)FZ>j3@F0p3+htK&?Xty%Rx^F@mEJ0e|k z#Syb|ZNtw{Wpbc1h!nBKRViZQMn69|6CB~_Oi?05EJ}+aHrbp>3G<;{-)a$L>$k7j#%5|9sVL@-*?kZJKDquN0k4h{JzG8l377Pl*;dGtWMho?;r6c6P-b%h%K&45gWH~k?SRZqAGyVGY)4UTBgfzBYd%NAE{ zmyMe#?y4KKyQn8ciS4o|t#;XD-y`B|!4d1HQ=A2kxM`IO9kJs2aQyag<@i~q9c^la zBi?-*hWDx)nj*G2Q1se*c4EFrk$y+Swp1KZ$3CYQP_#Nbok66CEv`xt8@JlVM(cp0 zSH&nwq=-dnQN$)2)1wf+_ZeA(;tX)amQ#u&K06k!2klmBPWfWH`Ws}vx!Q~7b(*3h+bcm&rp4K zocIVR%9xAJAX3B@SEY!JyDXwKzW2Gpg`z}?Sd$EDS95~|aaEcP!Wl>t~ zvdN0iyI2q$QEEBGS>TAGsq&#CjyEay1SndVa;a%Yn;YSX!atSkh+@qf_X3KlWv6_R zBK?jC%copNJXq#44Je8#PG=A)VvDO%#Kz6)Y~K+mx?hu`M2c9H7Da5bO0gABLA%Ra zQk(&f_}fl#MBgP2_?qQ_Aj%ip)$fQ;-xNnAU(&1xwA*F~ok47uEw0)w8@HDG?$yw4 zhp7}Lw#%Zl+GUeXZW6Hu9MN|x#aZBpE?$o4h+<8n@i%xD+pRD;qJSt zlMQ}Z(-j<1){Ei{aKwfNiX+;`E}9H~0rGXFe6d~qj%bi30N>YeXxua%wEJfWok47u zEw0)w8`pbFa{QgHf2LBD*e;9GYL`v6zVW1~;D|KaDb4~%JlvQc9nt4Q_KQGK=K5<) zj_@?X5uSyI;B$>0L*pZXqO5HxU!+LCBjRi_BSnMm_89;a9qC4A5Gi7dt5U?qExOmU zE&QdKF^r-_idd8uMQpNOCuc=NyK|>goB@s)TugDqnf#xtLc7+>DPL??zaxHhQ5^Bl z+p4{wU58zC2C-eXxN5s>+zLC6)q-{x#!{5nE{oD?mrXW%(er!Yh*$3@&H_g`rFKF` zv~3)Y@1PfJxxwU!mPR;Y&y_*wi2IEuxdKJGf+%04NWUW%wpJWbVrDbEb8^kWbOw3q%ITB%&bCuD#Tnp;cxS~C^#%>;4ek1DrF^kn z{f=ljTyaFI{2BIxBW50>Gl=c7#Z}v7377fcZwsn7Qb;GC`!JZ&LC367FVT+joZXNGyxppzLTOvidd8uMQpOR#ru4N zc7L6sI0GE9S-p<98^54G`~{eIhw{aC^*f^YQpFMZ7Y=I(?FPK1Gl=c7#Z}v7Kq+3}n^R)Qnu6reZ@9MPd@5p=}s?oK;_qRUhFn8xxl!Vyi% zE7uX@dgjE>Sx#6=`65O79kFAy;)pnxBKqSsJG-`M?qN%21pIj(9eyC_2LJWB4PW zsLalPOk=e%!V#%o4aVz;@h6|90*Y##rhJhi{f_9~S$RETbkq*~ovz<^=nNu7Y;jeJ z*toZ@)#?Nkd3>NKks=nQMG>2jE)wYs4=V%5_pct6YH4wNsp zo3wnb$Dl#(&iG8SYm6hl_qorR&LFnS7WY5LJ^p0CT4*;zb&3+(Wl>3*EaChp{490@ zABwZU5ublMqa)g6zPS)6+WzveiK4bfIO0b(<-JdQGUDG%-1mZLZWt|O|R zR2<>c`&Jof*QY+^i|y)n#NYCYBRZv?u@%}K*M`m@w#yb*ZI_L^v|24!Xt#1ViW1vp zQCjV?$x2SFeGRT7I!vWF3mh@Hb8&RU>w;I70!0g)PMG$ioe_>mH%a*n)d`ojjzCeX zN|Y~Bq~8%f3zg4MJ-W63El?EZPG=A)VvDO%#K!%YZ|F#%D5N7ri4?IYEsEG=ZT1|T z3GKEDr8ol|5o)8nW|^mp{|{)_VKn87?do?#wML2~qMsG~3hiE-O=l3>Ws9q}%f@Z? zv1xN?H+D5eiS4o|t#;XD&+bJn1xKVlM{yQ7!t+51bVSzk34eg195rH1j%aU$BWlMe z_p_|}&bk3m)T|BVixla1#EUb^XR#l9UBNpH^youp5Gi7dt5U?q4M+_P5O@lJ&9c4rcoNoBHTNUWQr2oWl>t~vdKmjdAJ@Nae5QQS>TA} zyGx-X{>k`hGf?!rz!j4tIvC-Ibgz`_h#lt|-2_LBsz~`FMfx4#_(pNW-9cjtfg=vO z(HTUF*y5@bv2mNO*!ch`%H4sYM2c9H7Da5bzh%ofL%W+pDb4^#Jjty%BL7M^{7zSq z(UdQ?tKSh>rYnwU+3e{qXt(8TI)m6QTU@nWHtzSk1@NA?T~|?**e;9GYL`t`JxA^C z;D|OCD9!>$w8~lr9kK22S^Q<`(PeI!9MRDTN8CO=7T?$C;r$dpi|tvD@o031;}n4(0ASdtQF#=YBPI67kDc8U_) zWl>t~vdLl}M&RoaXKqlO1&$~lT^1b?aU^CxP_!`59g`zE8R3ZE87813W^a1x0u*H` zP5B~4`W>;*B|W}7)@kIUc|ehK9Xf+Z5nEi9A~x>s{)JP6BdWEcD3Kx-r9}~&tlPYL z_-&k~K@?|zBa-)09FeZ_M{j6%>LAJ&+tu%g;Oc?cZg?`A4A5@Y8FU7*UADMtyKLNi zhd1NrEI%)!D6w4@rPVH*>_%jnn{XX5?Igun;0R}{^5}@y8Dj8TKg)AIFge1<2uIwC zpNNha@pf7qQ1qt+<%<;QcSMcW_DGTAy_0zF{9(1|3?fBraaD@gxaEF$B1NNHP?Sg! zi_)TqO_nFbAAcF)O8~_g;E13GiX*DDcf;>%>>fz@V!Qesaj~P~i1BSUEk;K~&>6&b z+2X40vT@UWPM8dT0cJ;0l-Mqd(rTAY_VMBf{JqcRM<~t$M|2IYfR0#w2|#M?9}M z0pHgcIGD~Lw#yb*ZI_K36Ow)(w3}=SMTzaQD6MwcWW#s-X$jX6S+-D|1&)~Zts*)i z?$J7Y2R%!{7bZve8R3W%sVCue#L|Q&{yk??!W*(hEY?m#r+AbTnbMwj3&~Djv6eYIHqO{s&lLd@V>kN*laEan9 zaKyS+mC+G%I(iR>>xjl}<4lh5H^LF#?G#7U5An8&KYf9sw2>4gQpBRPC}NW(ysp1oi49{cE_EjGl=c7#Z}v7<1Tq#pbE76@D4?Z?XoDXcG+Y- zqHEO$M?6mUCUJKya75VYD(Hy9xd)^Hik1y}Z^{WU!VzaDE6+8Cjo;lFDB3fb@Ravd@CTjofhC~OIxL8OQ+u1XOb*UdK5C7|f_7K#!nVo_QYvB{bppI#8!jXp+k z1~}qHW5p3C&)>m!w&&lZe6d~qj<|7Gam1{CwTnZ$b>ip@V!Lc{)ppsq#Se7Ed*`oC z_91bZ#CBPfR=aGnKke@0_ci(!q&N#4F`;TTbj0rOsZ#?*p*!MDV|6yd5r^_C*Ae|^ z#We#*47*7AB1QTg5p_Yij@Wr29`7G9D2~n`Qp6TlrHGB&``Ouk;E3^mC`zP=MQKsQ zCaY9z*(+akJNK^Ay@m*Mg$Nc3D)CCd+x}#T&SeDAbSQEO3O&_3G$|vje+t1&Y2O z`f8#m&-O>#xN^F-!C26wgSt;^^BeHd+I13!{ zutiODgmc67&A<^w{`qO5sEZMfC^bfLM9j7Gcvn=bi;oyz0!O4eRSO-Fw&T{PKvA2se@zqx8R3Z3EtJp$^#x0wB_;8?Tkae>C>CfDB%@9;fq=-dnQN$+u zIn4PIw0pyW;tY5_BK$@tyvIzxI!OqQrJtlvcZJvVHH;;`cR<_og@t9PzfXD>`CmgN1K_qGlVdOwa}! z;RvTl<#U$7b004NisqiCe32skj&O@p95K3vKi**=_AZ@4q=+r9N)a3P=c*n}!4Wp^ zDN3Y>MQKsQCR>z{dpES(J9)|^wVSjZRmUB#I%416{UxAXyDXG1wwttkt;e9cui^;D zEGf>xUx0yy=?r4KY;pf{-0$bk7ln5JsX|d=yDTb6lMVa2as*sQjO<8p7C7SM$vWtW zUyGLD)#$a&HYSR?8sUhIOBF{1Y->>pC<;7E`65O79kJ!P;)syYXKR6?5!dJpB1LR* zRf^cSeF}BJJ13ueK~W+_EJ}+aHrWa1h@9Yvi)m9QsokXQs5)-fugZ0V&)jABu2oPm z$`{*BTE5m}5b3Wt;`-qgDWKhj)#(gkyKHg)bKHexZ{w>?ww@Fvw#%ZDG+EfbsguDG zgZfjP1&-+CRSzAprg4Z1P;|XQS`$UxjBrGkpX2c}RF4YH+XIeB=Sle@Mfx4_#YuVZ zvskEA08sQJfX*ON#1>bjh>bh?)6lu_mu6BwiV`VeQCbwS$(qa@x)|CmH-X{|c&<@5 zL2*QM4|n|LfBl7&FSe`S5&q2;N9_E%9zR31eG{EQY?m#r+AbS+`>l`IZn+~ACAQ0= zwAy8pZTmU%J2;}>Q;M^|5%JgRqaz-)OFsiB>R&N~$r0U+a72;MiX+mD>=6x)Na05L zB1QTgaiE0ah<3pbOMxTWc+(j~irC_+6tQvFdGrYbM-=Z#Q6fbwN{b>k+1KaGOF_Hs zM^l^uj(GT8aYW;mlU_r+?sF(#Y*)V{&b3h-VQqEa7TSHWn$94$%NAE{myO$~v2!zM z*I_?JiS4o|t#;XDV?TL_ zFv1ae6BI{84@uD+C~DoD@AdwXcN$t21b+tu%g zr*{=c?60vgH#p+VB07WEE?Zo+T{iC1wde7j?XsIFN^F-!X|>BH%ROv8zOOOi8pT=Q zi0|(jqa%)2PIwFyEiU9}azrm99O1A@aYVv|*x5kQk}8xhQl#Gz8*?j;X#Q*t{@UB# zCUgdoBDT0HMQq&UTfP?oM=bE6D3Kx-r9}~&>_D}H_!~US`%s(#ju^UMam4eBp68(5 zQsXFJY*)V{Ha}Aw@nY7Bb>N6H^XUv?yKHgQcGw?Pl3XQDVC+N~>KqS=f&v zZQ(j%-xZ3pz!5b@HbqCo&Dd-Mj;P$Ipve)TMmWM{nc|40zuJrfil%x~zDSXNN3>KO zai-RxOF)rdPdbB05nEi9A~tTPdX4b+HLi@ND3Kx-r9}~&?0vE8_zO$v=TV#ij_7el zal{6%%DJH3bn7TzY*)V{HWUrQ&slb!Iv@nvee(~UL2Q>TuG%geH}Ly8FL1=Rixefc z%c8W}Ws{A5vicD?V)R#vv%nD^-#pL}Qz{0n21oR7Uex4>-bOg$#IkYt-e<~z88!n& zm3mOVNYVe6#wRQ=q>E4AK7Ik+13R1k?dKm780KwWD6Pl(WIyFPV%GM&HGm@PNpuF0 zB6Cjnz&G|$gfuhf==nNu7Y;jeJ*tl=Y-^>6M_1a5OB1J4piy}7Jx>327fg`ec!qR;O# zTqdzy7NylLn=IFw2)qwf!D19=fg`4t@I*)ad6C`;C^|i(v}vp`BOK9sukwA3BO7+Q z0!3F=P`*f!en(6%ue`7E^zEp3KvB$YI)g|NTU?bQHtvb9RZD{-nw_C2ks=nQMG>29 z@!caK&~A(S6lZ`V?vGX+QOBbs{=UZB50o#qtKSj%!xTqcIsfuCv>TbSOd{c8yKHgQ zcGBH>o?L0e>Z$ob&9jV5u3KPL`M{lY_}IE%DJ+<=@IN} zgd<`jlR;Y;HoJrB+@0etKSimS168Hb^0z| zM~u%#XAs+Ei>tQF#(iIQjWx9ER)V6$c3G5GyKJ&;HyvifbB#XDDb4~%9I4bA9Z|Gm z^{GHnfk%~1E%r0Q5w#{LuScBgH0TyMBIggv7b(*3h>`=8*CX!aJaiEpkv?6O#K%CS zh%K&45gYf)CrA9f&q?_xN~DNIX;H)`3#i@=KSPzbEX5h%h@#~cN5pp7R~p(KTaWU^ zcJ(`=OswLF$&YW0gm#;?p)-i>vc*-~W#i`R`85F?ai%LpiS4o|t#;XDKhB=$3XZ57 zNpTi9qRb92bi|b&K5IO5eT#Sz_x20sIeDx|BCm@iVK-w|z_Dvq%B zJKP&6%Hv395Gi7dt5U?qy*=s#z8+De97Tx~u_!Hy*ktQ-KB)rj`ZuOH101okmg0yP z3mTP#c6W86e6d~qj>vLFaYP&IJF}qOU%lxJV!Lc{)ppsqUKI`x1V?-yLs4S8EJ~|g zHre9P@j1W|5o;*U0!KXP*cKfTwK+Zhmfvn`SJRFTFv1Z}8Y=I7-nd#OA5c^;2jz34)vO2rZRSNmoHiYBo>qr;vk#&(i0!h)Roi9bF0J9XAKJYh zK~ZA6EJ~|gHrbWyTuG%ge zckRUVAEDi1>nTcXmqlr{%O-2GsnSoljwpSd;w*4Pt4MEjM5S7j?BOp>jxaZqBL*4a zh~Wj4*DQap>*fiLcsiEyMT+!0V%$>25yuZk;HPYE&8IVn6tTrsDPrT=zWhB8D7wCZ zqC|>Vlomy7vUT$>=7M&&9HKY_98on~am0X(d$U2iKQ2?g*sgv@lr9{MpP{OM+4d7S zV%ak~gV-)xT(w;`Zn4WV+Csavzf+XhE{oD?mrYip@24){hz@z(6L;4FNBnHq5glQ7 z`N<%lXhTd>Q_f%`9I*76V*ZV!i8Q_SYQaDqT*e;9GYL`vcy?nViaKy_d z6lZ}W^6u?~j#z3xzbR1Ea&rq)i$jcX#OSV*@pG03e%o9Eie?_Ae32skjtEJqIHKg> z-tj=u!|QYgks`LZDn)GEu}5R@HOt4ZC`zP=MQKsQCd+)SCw|Vd=P!ygz!6SPiX(=X z+J|=;duZ>ONSD~Ien%8+t2iR6$f(26?y~%J2C-eXxN5s>+@@RNhrwTfjO8gxY?no8 zwaX^E@;*E{IAVVXinG8G83KIK5pUv~yZ}dZyw}>);!q&jUbF-}!U~ks`LZDn)GE4^gF>07d84QG}U#DmA_+5knz zLpzyrh8y9Cw~Zsw5fy$e3NPmRH?L3P?pol8 z=CuOR5g9_y;V1FFuJbqLgd5?AA<1T-BU+bi=?fI?JwW*)Mfx2vuDWs^QQNsKeiEg^r0ES5e=VElt>Ya(xQk>Hg9K(wBU%S1d21j5$oS8j@b1!&mw5o z*)|}NF0ozxjwpRfaYU8U&R^j#z}#GP2C-eXxN5s>+^Qp8lR>*~r722mmqlr{%O?BU z^2DHoiiUo1c~jg3KARmbN6*y zeE-cVn*YRY+g}gNSt3a+ON%5nTf3rp&p^X}KAH0j5QYC@MHDyg+<6TRpSBJn#Kea6 zo8sDg#T02g;ys|@;W^ER5F2Lut2WFAK3nB+EHqr*#hfKJ%(Ao^X0!DzdAe%5e~Fru zCvd0jTu*bJ1+us`Fc@XgEA6ZYfKr8>-Aql6G(;ASQz`F)=6Qbl0-$vLwD|xcO8RAS z<*V`*M?L@B;eb+~yXHfPD6s`rQDOt9THJOVpp@o=IZH%|WoeKR~5Z3_&Y$ud9#@hAU2$|186-8<1Z_+nCi2>DKvbvsQD0L!)$^7bKvGJ zV+KLPan;OOV#6#eNweLY@Ny)`qK219G`lp(Sh>!W=1 za!RT@o`6zdZu0>|l=REOM*UqL&&LDO07@@Qn-3wP#1>dZi4APM&A$Pl^wHg%C8ET# zv`}KR#ZA6>9~%DK$((1vmBqAs%9X|Lus?aB;aXwl1Bealm&LD)UGY^Y&+Y!3q2UAL z&4&;hW(%w~%mzN~e7HR{Tw|d*OKg~BX*JAdOIF-^9>^lwVRN1ZvZ%1SJIdnL$17I> zrKwI~CRvO&L>4ox6?)wtqOti9B1&w5Rg~Dk zUSo3H0+hTvnX^QcSe6z_Y__PJzv7|cCcVvh2FT)KoFa==A3F{KS$rIAK7iP;epyt? zsmP+n;8$_baLgR@A;gB+0;>(PfvqYHEDH^{U1QD?8)jKr4YS!6PX0U;WKr_GInM%F zoGsM@Wl>?{v!;O3gNg%8vKV8CED8rHH=>zUvwL4asf(NW03u5IWzj1^c^XprZL+C= zQmD825F$!!fmM{)zy<4FLb^co+O z01Zb*nhzj0tX~$t$|$lpZN23dG#tI$d$XxKj5d;qaw{j$i|Op!(Z@&yY)!@0Mb4 z=P`4Z*f7h|YM9No>QuMeAd7b|&3P8c!g^jP%A(BcN$mlpw$;K-vKVKGEbb>$KEl29 z&E&^`Qaumz0YsGa%OaJvB8xhHe!Bss83E=)h$yiIR#9RD58Ccr3{Z;iZ_W}?Vp&=! zvDrGfPAdrw7oKF!Ge8#EE-JDZ6qWA{H0%*&K7iP;ep#IMRb*kEbMsSZxaMZ_A;gB+ z0;>(Pf%kt{)D;?De$<>LHq5fL8fLSdnUS_F$RhrwInM%F)UVP9WpQfYvZH`f=Z>RI zvKViOEHXMx!OvGb>M>*~pwy$c`2ZqH`ejjPqw?12qh}va07?f&n-3wP#1>dZi4EM_ zsiGgCB-QGAd3pa&3P8c;?$e|D2oW+c zvzLzql(Ht9P6rTC(l3j9JCx6PcUw7X2%vNzllc%LN^F5ul-R(@D1{a>XNf4W zEG?ASY(-D|&w+*?R5IroAd9VI6adqHUUQb+S4 z#D>`ds|~Y(7tghdgN6%)nzO`)S(aAAY_^?^nhyY3WS?u!vp^P&dJaTc{AhmJ2~f)W zYo=*eBMgznKOL3tmgZe`XaS(~C;cosfQXWQS(NutWHCGV%UD3^TmkbTM3mS9t0=L7 zn@)-v11O!ZV9pXzVp&=!vDwz8_FDlBpJ`;yGe8#ChbgiMf7<#OG~A|x`2b?W`el(> zy|Q@HZOi~@xO=$y5Msk@fz^iDz+*GS_JxMituSYa4YMq*hS_XhTRZ!LEWF>F^DK~s zcgDdei+3j?908>dKNgsFb+RF{a1K>uF{(lT4uI1AybI|7B1-yY5gnw+;Ht1y&no1GkQ?BIK7fdl zepwW?Q)Cg^GW0s2RI-El5F$!!fmM{)z>k(T7!N2F>ut^wQDRwID6!ezr26LvG<;yJ zInMxDoG-7)!sm67R?zUD`Q`(N4eOW1`BdHTk246m|#ADh?0I;MD|x?k=ZeJ8K87?;s2@atiP&ExF~F)qNAADf*qLHfhcw} z_85bSBdC~+-HL&YVv9I-V9tnxg<|X2V=F3-U4SiqKisuAYoGJ3^SR!;-oIe)&EDtX zUbsOf)G3Jr=2H@Zw_Gk=9H!KIJ87v?5?V%664}O2X^W2?j~^yI3t*9_3WLSe!nG$s z!>ulp0kvWCuy~N4!Qx)=YOSH+jd5f`ZCD&IZ&(CgdL`rnH2m!YX{ikhEu)4-wxUGy+((3)pBAnrjIxPWiDvaJE~}68{UIZxR_$r(_-$ z`!_RKWGi@VDNJc*2$@i)Bo3HQNd!LEr*ajTQs5@iQl})ejHV>A4X?2?6dGRiH|bdb zix%}6EE?td2j3gg=pQnmHf$aiIcqamj0!Jb1{#ihKql0N#R2n%Mc^K*obp1$;}c0s zZCGd-H7v6Ao|`8YU{Nj4rsNy80~U@ICLk=HZhbWurj*Tpt4(O0C9vpljKLxxX{RIn z-Z?v#45(8w4~uuf3>FoSPVEg-8ZeJcs8bRL%%>y*H|t*s{|i5GEorG!5?V%664?fM zUEc}~SNV(dEPzF|R16m7yAQ4i4d*#S2GoYl!y#}zG=V9-Uq)K$ zl!TVilti{aw>A%khVyJEJquv5Xm?lqB)!5B;dh{6-@{};ZP+|4Hf&?CDA9aLLufee z5}8mN76;557J;+(>y!Z+?i5E_YQsXys9}-KwdLiH0E;b-JCkqN4p@9WH4z_K#BQit z0;bf`caKeIfhDlme~Ue`81Xz|KTN6AXfmKq$viA({?1@=W|@0-n9?6}$b>p2alm{^ zBCyYZB7zV zF$Rl@Z;Q8uhA-bB6KccafO*3ra7V|P4$yFx7o?>&EVPUo7TM-B`ZOG1al&bD@(tSo zi#kgtAuRs;dtr8*QqO%hp@o*fB3&!?$YR%lvz1^7)OmO3S&Wi%y`txm_%anNwNZKP)bES^R&SmaGA5)Tcx zJVXZ6hRws`^-TtgCjFz=K*N7uBok`G;(&R>B5=D$9g?8oYY$0FZCGd-H7v3%+?etZ zz+y|f$mAQg0~RfRnT)X5KkHUum{QQdD4S4-C9tTPz+Ud1=17sdFs05D$$&Z~^RTFR zm%+j*gX?gZ(z1nQLYq$$UlF%}mlE{|1@`u~daM4K8vj7$i zRxw!g8(Fa?G#qi345$s8hsB#O3>G~A+k=CB ze4ycaQKV-9EN=eJU=iTfHUb*na-IyR4V#BW!;=2^Ityp-+W6j(6tQGNZCD&IZ&(C= zJf)&5G~6_vwA6-$mQlkZTgJ+l>jNxKJ0D5DVLM>)HO*9n#puFse}XBEo_@?GwAd0@ zG`P<`&tk*a)aPMJyH=0^bxP)8aq~8V#oR&}tHSS{JrQI=osu|UJ|z)2BIm&4Fr|CZ zq@_+tXcDm zd?piW!{UH>!y<5xVeKbF!}&7BB;S`(SahC92Gl8;hsDUX3>Fs`udWQR z*s_pJs8bRL%%>y*=lOi7D!`)M2GUZeB(#jCB(fFn>+}j>v2;J_SpbW^+ZilARxi^O z8umIz2GoYl!{QGPi)@uk;cIkf-6Iof!{UH>!y<6+=2u5U!&lytmfEn;GHO_4tC?a_ z8-T?o=X1$7YzHhl_yr*>Hs85?0H)NY&jp*%QcGabrxyFy>BV*HCc~6&{7wecDVc{w zv9t^pTW^nd0az5ANhZ`Oi38?S5`l|f{$3QObaVx2sZ$bKMpF{mN~hes2pY~2L3$Rz z;=>#Uizr900BE?{5i+1QY#tW(+}IXgjG!rzJgH>7rG!XB8?_Els;osu|UJ|z)&z~-0}Fr`yFNK2iP&@!5m$W|wE z=XPkg;8D`E02cdKGg$14K6nTku5gtMs12Kk#hd^Ji|+Hv;g>zs`HxJf4T}Tj4U52g zUsl7fkqY@lT57{W%cxyW%wUoCY61N7 z*Y~=&ZLnBj2`mbREJj!)O)pdjru4im8BnKW9v0c0(jzP`J`NfSQws1U6Y7-20rM$| zz$e%K{SQoO!3fe)rzEtDrX;dG`jUVz=zlnq^eliy?`aGcUR|GlfQGZLBm-*0=3(*k z1O|&UJN&vs!-FHpgxat;VBW9@Jmk;;e5+vC5zDd8`qWxweEM8Avj_(}k-RY4H7OO0QMfht5i$m_iio=we_>%#3O6Fnlb8hy? zqNmrBc`&68yO3xOMmO3S&Wi%y`?Q>$C8u06&{W{XK02Whb zGFYVB(Af_fp70kLP#ZQ6i4uv9R@;(pLH{DemLg->ikt1W@Wo>2@IU0SVQ4O1Gw zjtr<%G7pQ_?HDY|IgRNDQ#$$=nNX)B4wz3#1P<#kt|m+=<`ikEQxaN6Qxe%mb?8?Y zU~%v^=~)1azos)-%$a)R0yKQ+H5pJFHV=y-2N^7!Gvq%74L48qG!y@qa z9+^`>!%cILmfEn;GHO_4OE<1zQGmscYNTfeEJi(MusC!$=nYKi*YFp%A7Yp#u=pt? z6#r&%`swzgFeRTq$$&Z~^RPH^i#-kb6z_+hcJTTXnNX)B4wz3#1U{R^ITograGSK$ zDG4p3DT!zm&p@T8#WJ%2bucg6V0#;+a>}m z@;Z|VwPA6p8%pi8txl0gL#3v+f~y8opVROsEZu1OC5(*FF5`4-F6TCM~sLq4h)AJVU*Q0W1!W zBt1J|kv?z^!eW+Zs!9Nhn7oO$DTP}Ci)-WA(~wRv@d%4Y?qoonl6hDZZ^NF3fxQxaN6Qxe(2qRZhIRAw4XdKNsgxO0`k!u#{= z&H#(@)5w6@uz6T4Y{FpC&AD$IX!!4CWI}CN958QK1pc1;q#HE6AcC~ihJ}_JWjv_q^ zVDafLgT?CKvP^@9&j*tMwPEwHIM9H>Vq>>g_^;DXtI34gusC4eun7FSbJ#D?@Uxwy zr8X?Ij2af%s?4ai7GUx63hCJai>7(zAuQa_Oj!a`x?Sd*4Hkb`0*i=N3>HQ1?A!`d zn(0Xf)G3*VMWqA=ix!;^4FFg?Y)>ZCDTxE-QxbtYrK~;(ru6nV(o&}+w2Y=CvW0x^ zJ_j0JKbrI`fW@?M28%SQPbWabndXoIwPEwHnC{15@wV{UzR+;bFfySwEDo4AECPRc zeBn1}ICd9lsSOJ)qlQJc!hV690T!LFk)9o}cy^P)BGa{0Q(;Q}B~l)6I&-~VmUWiE zVsm>2i{)iKJHeFB)g%Mzl+44zB@KH8XT;a_H(^QzTagKMO5%X|ltkdN%a%@nDIMxg zTI!U9meG_%Hvbukcc9^ELrKp9SX|n{VDYWl#b?lP(`jTtZP+|4;({40+J4xBpWmKt zIhjx!76;557JD zQt|c1fcca} z;Afe__rsL7&LS;!NXvdhFh*8JquuQ@H~S>Gsg}Kq2c%lGN3kW9v013 zGFT+^_s9wj&pSdU)P}_Y^M*y>8*b&lLBlVvk(S!9&@yURWV`FT^9{fv(^t~70~Vuv z79cEA4P1B`r!>vc28#`rz~XB?_TP|mKkZ!sQ*vEO2Gl8;hehft3>IlWIyHbPZQV*H z)G3Jr=2H@ZD-NxKZzTKWFlnh%5?V%664`Q98*&;N&Ul6NEP%yNhZ!txwA}C*8jg8P z2GoYl!=m>l28*!HJ@KuA13!@owPA6SeqUAAIb=Ycl6hFfR$#Cg z*Jy8XfJKRLGNDdM95A1f2pr^C=o(BZVh?GlQxaN6Qxe&(mhYMb4WB%vMgxat;VBW9@JYf8Y2GH=S6q%E6N^MwZ z88s}j~pYl%5TgqE+M?=FN zmq^b7SorudSd>iF8oxK>$RjeKHf$ai6VnaA7iDdE{SiNd^T~TMp*AcIm^Ul}muYYd zpN8B>pDp>O)P{wYQNtqJ&S4iL0T%1sNY4&fOxYBIk1Q5D3{DAC8gwqFE!bvDV9~rI z`va$6*$dwQ76b2-0d-2|VNpGr!6Gp5NfUs@?RR8Cosu|UJ|z*jYQekN0T%rooRfdz z>Xd|*(Ue5C5qH+(x7mKoMS2#%V$vK2i=xYVw1I|ybt406!{%Y(oR-0&wRelM&~Us5 znNS-R2h1B5fxo2txiK`{!ke_zhJ}_9+`B;rDRHDS$=z zg*>+DZm|RwGnOyF*ID?z>3#yHRNx^QP^V-b76VVR|Arh)7&IBC)HIPys8bRL%%>y* z&r6f{2u$g>^m&ti;_8%ymeG_%wzLBl`$5C6^OBwgu(-5^!D9HeTVBv`QW-L!Hf$ai zM=CN{d_U~*6&n7@lT4@$iv#8ji@>|D?I{Tj|NAp(sSOJ)qlQH`_b9Kk0E@=MNzV>g z6t27&Vd2{97Cy4L{;q&+x?3%Q#eg;JONM?9>e3OWRL7xUvH^8U=3!A`9Q&lK-c!7W zz?AyrA`|MA!~yduiNIS27O4hPDq5Pf)F}xqqbZ4OFH%Q304(Zwke&swIDdk{;##pm z_*DRtTay8`Ve_yEDaT-OaNPC0(D3>mWI}CN958QK1dhpn>0f9#ekf_F4GS%!hDEld znvDtpEGCAMo*l4Q_J+Y?;htvRFr`D83)^mWnp2alm{^BCzj2C11moYBVA(bxK0ZXi6em`&Q+bL&K{(k)8#x zh@8Y=F?iQtcW5}UKN(OPHV=zbZ5S*9D&&7I2MZQSVvjY~@_k`jjiy-$sORbH22(2K zN(R&^nTN%h1oku}^}*mkm{Lo3GNDdM95A1f2s|Rqm0U2ThK)!|os!Tpnv%$NWyI9~ zpy9*aNY4UTM29d~e6KOA5Hy@(5E)P#HV+Gr&I}eY;bBFf;R=(f|=3(*IVg`$?g~z;yhI5`E6Kcca zfO*3raJm#duS3I&u9KG9u+TDUSY*4Lf6fVjMZa&PX9q0u)?SLR$h*k>I!x(s?Q%9) z?63qD-FL8momR^qfG-BVSEHf02U2=7%UzJcY6bmEIc=p0kvWC zuy}QW!D4ye@zdeg!Tu;Rp*AcIm^Ul}cRV%-UuSXWJZY&73oWCDMYb=+I)4XPxP2r& zJ7D3uc^N*kXgDYWpN5QXRn-QIU6#P2yElWy-2CnFZx&U0kO6f{=3&uk9fQTW+M^s{ zN}j{WggPa0z9E(xJQ(#IX_K*p6O5%X|ltkc3XAeZdl#U!HEp+w1~^YXK}a-5@;+ zVDYdagT;=2y;DNN@1K(awPEwHIQE*sqUzLFFQDP#Nn}E8SR62KSOjhx{}MmHy=j(O z$v34oEVPUo7TH{~f7%bQs9Txz?105jrB@&5T-PAY8_j!J(j?tMhJTaXV4rU z7nqXI5;CAp$viAN?&h$l6u1zkG;Ir+P^Tmgm`_OruK%XZRDi`l2T4nvlF%}mlE{`m zrb>2b_|8Srvj7$yYcp6Z*}km`G`#N-8BiNG4-5B{1M%hF9&NX*frj^gAQNiC;(&R> zB5=^sSrwt-*bJV@H>EZ#w2T@S+4`*udJVAnwLIzB0gJf*7%W__t#XAa6`AH`3%1u1 zSj2W>u;}z#3;b4zxTR!3osxN2^t#Akk#=$?{B-YA+sTAFC2_!fN+NKDd8`OWRiBBa4!8 zk0-*E{+!gv7VJ+;V9_Thdm0k$Pz~R8+ItZhP^V-b7L&^|SnTSt2w&et5nSQ$?y)P}_Y^M*y>&Rt95yMN*x8YkbB+OW_vYFK1D?de|@V3Dyj z>Dd8`UO%rwSTubWei5crVL~%ou)i#UMUGSK51h>+S8szUMJ*r$>XgjG;#x5K1Lx6f zOYtr0ZtKW|Iwf(yd`cp4i7TtW11$Xak(N3op=C5Bk!@DYz+a%@XQxTe0$2n-Vvj7! zcU#Z|8vge-8BiNG4~w9V3>Fct9ghMmHYJh?wPA6xX$dTb4qJw> z2&g%uG)yUT4l10AzIxcLw=p*AcI zm^Ul}56#&Z|KIg?3Tdeg3oWCDMYf`q&f!-9cyA;zhkhNJ~Ue#z+#shnNX)B z4wz3#1pXdUbskJ9#)GufDG4p3DT!0lkG2JJ11w68BNJ-F;(&R>B5?JDd8`8&ksZk;UK-J7)tdToQWPU~#|_Sj0YNud_(K@xT|D(!R94k`1U+ zG7pOt?(AKs^?H4J1yg#Mn@p%v5(mtuBmy4}yMs?dT--=Yos!Tpnv%$tt9Tf`k!-aG z=~)1a1&tXj_Gg$e3mRVHO$OA4&BLO?D+Y`DyPl_mhLd`d3AJHyz`S7*_*v3lK>&+F z!%0hRSZEnFEV2b`E#d~S7_@}+?0`jy%4-o8G4K251XvVs=xe*xgOI6Y7-20rM$|z>&Ak;s?cNtVdevl!TVilti|< zh1T|fhHthdJquuQI)K6A+Vx_40T%0g$$;9hd051LWUwfiBRBrPtIJ3-p*AcIm^Ul} z&)rsKCcxt3EYeaN7Fvc4^K93%U-ku9JljEfcEF&56PDvavpOOeX{m%4qFr{Z*NlTrQ z&@!5m$o4YvR3m7(+z`^U02V1KGguUj49p6!$TyV?s12KkMcYyV_;T-@rEc_qM;5V* z$%NXlIAGqe2%Ik>pglA^Ya?l?4GS%!hDElr-QpVoEUum*Jv(3#wek;qWN~AmFgCf0I+bqM0ys$Vs;Y-i}}m9w8VxVlL571^RP%;p1~r` zw{G~p;<}&7gxat;VBW9@>>Idc95npYX;AV_sSOJ)qlQJc-{1AXPxtn&MtXL@;$E9| z2#b^Z#<{?hJR*nMf*r907FlB1hu=7~*n|&KN1i1E>XgjG!o4Vi#l<7F{Qws2?~w_0 zO5%X|ltkcNqkE--DcycYTI!U9meG_%w$V}d6QSXJRJ%l-kd zaLhvn)P{e|fYDDOqBeuYssl|HLBnxwWI}CN9Ps}Q?3^QLE;O9mleE-^h1L&c%T+fB zzc(b&m-Os_MSLQI#r{-vE5MZcpZ(o7rD#iF5q*}y!oS#g{J`GR_sM`dCG)W8+l0X) z>{QrEm{M>&nNX)B4wz3#1U`4AGk$&HVTTdPKXG+RLd$4MB3r|!z3M^34!KFsf=3pW z%P?3xaBv$Au*hDT45$s8hefZp3>KxMr?^1Fc|6F3+ORla-mnOqW^CFi0E=5cla|`B z&@yURWZTo-#S@-}tR7B!cEDo)%JuljqVb`CBQT};S4Z2Xd(;wG^yGiD7<8`aXPDCB zCuBgKl6hFvxy)d3)$@uoOeyR$nNX)B4wz3#1g@UV-vOpHA=8-TpSU_Dp=C5Bku7?A zzVXm-cURK002c8r7%WOPJJt{yUgu5*)P~K&B3DZWi>9w?k%rsVgY45(8w4~rKL?5hC!dB4V|AzK_LB>xoDDTxE-Qxbu%ooL_*Q@WXt zwA3jHEu$%kY&$dM-T)0(E=PJ6z@k|r1`DsFgF>OD34}KlI zX+tK|hQ$H%hDG3yZq+hD!x{RJmfEn;GHO_4>)-K0Yk)<_bkef}79}!lL|7dBuzm$h zY1pO7wlj&b1QzQuvQPK!k$GMcOvy8j45(8w4~z2s7%XOc9>VVp`S$~vP^Tmgm`_Or ze(^9q45k$4I3@Wfu1-m48BIxK8~5th576-7{G?|AET;Bku;{iwsvb1FsT>(l8#WJ% zCjA*KHt*`N0btR(E}2jp76;557J)O}_QwBr?QKI^YQsXys9}-q^M5Xn0Ty3|k)9o} z*zzZXMN(K6e30rF6=a+4aZ6y4bXd|*(Ue5CN}KLK23Xv1nEqo8|Jbeaz`svmut+p2alm{^B5<3sH}b-isy-qubxK0ZXi6g6)7_bW2Uv`L zPkI(Svgp#1!6Me@-C}6?M*867iKz{nhsEf53>GtrommMDr^!bq)P}_Y^M*y>ovEVn oPuTg&l9t-A&@yURWOE)`?li!nQXA5<0~QgfHX|(N_K$J=9~(<#HUIzs literal 0 HcmV?d00001 diff --git a/docs/notebooks/logs/train/events.out.tfevents.1663944078.sebastianp-lptp.2242101.0.v2 b/docs/notebooks/logs/train/events.out.tfevents.1663944078.sebastianp-lptp.2242101.0.v2 new file mode 100644 index 0000000000000000000000000000000000000000..e626493762ab6816cb0f2fb33c786341fd04a317 GIT binary patch literal 671910 zcmd?S3z#HVSui|RJ-a*mX0u5e0@)H_2?}8lW~XO%H(5W$Om0MzO~@`mE1@$?Jr&q4{mM`+Gr(qP!{w2?@Ijn2A@-?i4y)OTFd>kfvC z-wQj=wl=oi`h(Z%3$^+@0$^Xh;B(HLM<7nc+M<&{zyj<%;(Y|}g#G#jk))+B+0ZX( zA(-rckyrIl-fzQYDlqGNj`?Ul#<1)p7%7DyPAdLVpJ*VPT|7A5?{v>JTjx51=4NYf zrfy$0xA-8q(B0VRYz?9xT8kG0oN!Ndy8JPlJ=S&aihXu3EV$iv^w47xTyQBoNXGNK zz&ei7Z!`4X*loM#@S7T(hKmIZ9%I^|zQg;+QKEJ+d=+j6<)s-Y7Co`Gv1&1-HsdhGaZPr2s!b=NkpKHePmwwfF6S=8Ytd;Pmw{r1vrZmWHJ ztKVsz*l=&zTI#!l-gbZ8rAKA`1F1Mwgqds_I*?D)bdt+hxd<@8wDXkRXc}|Sa4mg4Ic}1QhkAcRV>QG z^IYK=02*33A#gX`_2KOegdq6J$uD|N0c_ypge#y-Ium>#FB9C@Mjx>=JYQenU*+9< zKnWG!hA_bgZMZ%c1M?jpt?v%MENJ(|O2Q&s(md5~wL6IGCZ717WqWD;LDy^#hP}-j zg5Ny8abR^B&lohQx#xIU!VJgX9GOEu`d2NeCy`g*6&M^&L6}uiu?~9%zHQTNcQyxg z8|EU)z7TzGVRP4aHa6<>>~BY7S~?PV!dEiGuEX4m$SZhM0ypR)AGwft>hKZ^ZW4CV z3AlY?X4q$_tupF<66RN-KvFyB;R!tN0XVXNF@$|A5TXkTG#k_dD=H2#(0D|_l93~( z320;qjDX3ap&KTLGW!zhlC z!n};r!>C25Y~oJbu)poLJ7*{F#QimO;_~h*p+!U|F7L}j&y{KuwKQ6BM=tvgigo1f zwTUA)+IA$4T=o~md~H$Av%kzol1a$J1~e~4PbT|fQfDsvYbXND_Wrxnq07Fg(xJ=# zDnvu5U39yLk5PL*`%2uEQ#f_mUl>Du=+x;1`Qy~F%f2Xg=M;`z_7{556w$F8;T6ok zC+tFt`w_RMm{aiMaEah; zp)cC%yY-#^zr?=_c4PkLGbGP*YVu+!@{(J{ni+<*sgzlR5K>uVQd=4I}P zGV7uWOugKKy&@djoAnwl=_G+8=CX8GivaV-J8ds7ws;ZjKI6Jufy;bFm|Uba9c=XmZnIUlub87hI)Oj3;Ateyx4FHs zbdD226-A#jjH0g-3gD~jH3ZlZ6HeZGgeE>VQgFF1!~#6ef`&lnR{M@#r#oEQY+;TU zBMlq@OVL+bZhw=5sP^$#W?eLU^(oBvSn&8vyQuFz&bQ{o_|zEzo)8}z#Ic%(eGH`I z9tK#B_ql{Zt#-S<YX6mhZ|r%e{u`RCS*(apb5m@V(@el zWy4ot8Z(v0KmQSt`0B*fNdkcPa-Yk^NLa8Y;d~EPb0BUdlnPDqm@GAy&EFUcV+}^k zZfYISAd;Ei>oz0C^DX#6K?==5D%R=zk_A_dyp6!w6#YYUIH*bE5|8CcEJ9jkwo@qojj9s-W z4=t**b?8vUPuqrn)aS$p?$uss4^c8@?S|$KmsCj}yU{V4}s{^(5hJ3X!(Pi>RZNw9+0Mtq0 zl~{&LG>ikf5)Yi#WCoknB%?Su%LdOhm>ro&7S#}^vT|In@GzdVO4cWORl8~BxO1u# z1MY^02)frj?=Ick>2@|TUa>3qLK7ca(fy8_Mhre_SwB1#9voYH;Me*3HRqRbR$Exx ziBT9Vq!aD%nnGFPV{nd?wKJgBd)@WcaLKD-A0VgC--^ZUjskQYw?$B4REAYgdxg_z zOdZ89EO-WCMPX&{(V()u&H>xKw#y4I#Y>1)2z!SGm&P#W16E%^lp%oVJ4;dOh*jmn zt~fpj9fjYsT}KcHP}*Aj2*D~i0sCUx?RDM3l1E-115t%}zVSqn+G-aVy{-pI7740F zZ}tk<-)B zQbYY)hC(MDZZ2&0;-#>owb41%t?#MBZ8zTVq~pz-uDkwtT5L-aZd!@LO+wMPQlK=b zg-*f-U6F^IaLoi#8Q#;jAA%1wvc?$#Ts0XkbEvYz*FozYhBUz(TF^23t zBxmUZCO2iprZ|FtX#X;URb%d0@T|D$fq(_87h=w0qsK$3B@iwk7_KxtXI1qNygw?RZKIHM_a-JQU z-@xs}oizm0dv)Bz6|5JfPr0Z|-J|^y^Mk~tL?c%r>e{!9?n({Msz)Vw#Dhv|<{Fx_ zN>BPfWW2(biy68xn>Ju5M@8GX+bE)oIUl;;dj_uw4o0+eLr#{MysNriyqA3Sy>I-t zPrmbqMS3Z%VK|d8c~^atH;GDyZ&EYCOi|p5xiOkFdRJsduV)P>jNb61N-G7~2Y*V- z!i*!fNPn8+t5VEXGg_c|kXoWdlc>#7l_kuIGuR((L4UAhWRS{>J^VLOw^d*4q3a^x zi-vY-cHpEP2JkIijP+p5JQZ8lM&~VZz*D0v08?YpazyAXTK-HUML@mab|P%cRE8{U zn~czU0~6wbT%)#fTiY6Qh%$8<{1q%&E>rVGL#CEPDrH=aQDeg&=$QIYjHwfYI+TMr zn!$!O?8!mWu_u3~vG|xo{5;Dj4JDrzIPC-e)`FV_dnYK)#Ped*9BSfZ8Bb@4T0fGM zmJKhZN9HI17F*`?0-MY%7ob zPG*epKk_pMFYOV^kaEM2C`i)q2D1&Gl#{tR45U1%C@7qQEn0Oz8J zN$F4&Ogc~wI)zao;$3}Vlch3dus3-eRmuTAMt=DSZL$huCJTV27&BQnq%mf)yo$y+ zq{d8^*9FE5KW((efWnx`vYghK$?_tK2Hmzp(NY;RS(Z&TX0p7D6g2Aey~3EuvX-GS zljW5$5*V?N!kEdjEN^iXnrCIkOqN$NA&?p~nO@>G(8`X`EN|g-GUI54F_UFMZV03p zGg)5ADP#tN!kEdjAcrBV_KCx_qdZ0aIpF;WbHA zW9I>4kyLmE{M1OGTC%rAlfheBREJoDby8w_-0co}{dRANDgLOPJ9lx8YLSzD7pD?? z<*XQGl@-R*3MQSlhAt@`jv(=>)cNdVnUpp(ueC!=EyiXdV-RGTS z*&F}c8m^xX8tgBdV|Y8x=L4`OE`(jjw_5!c8(D`<%qQXdwD6%GETmZGixxa0WuaWC zWCG(DffB=jhWoPO7I{+aIT2ZMGl=$WQA5`zYM9s_UCIy)P+XddYwhetRj?#Lomeg6Veln)UZV_@CnbiW-ENEr40(}9LWX9ptIzLp zUE%YYV()x&5i3!~S9vvT_N#a!j--n3VAQyx@)4DFllP0hjg5s`qPNKE@(#)yS8z?z zK^Gz^g3lPD4yj5Ha7-)1)u*_s_KaQsk+_To?xiEXg0&*TiqL!hFS$g8Y%Kzm5;84m za)z8m!7Eu7UaW*ySMD&lM4IVq;BY9j$jaerYKR*|S%)9+x2J+xO=^0+;Jq#)hOtel zxylPS#fIZxS;ArAR?Ky9U?tcX(h=W&%xl2MiqUJlE1PmF*AtSrBUs)tr23R`ln}^> zIhs2E0LQ(F<^8@gDaK#=WjgN6f3={fC72_{yFNBoNsq9wKdFjke3WjsVaKYBdA$&# zCoKfI9y5^{W&SR*vkNszVmgu46d&X~D>AdEETtT)E=-Fn_fWnhTK-U^6j#}1EtzD~?$hN>JYlMC_m%=i^ZDRA9@aGFXs*xjig%sYX7~7S8L8} z{b)|UY)RsMRjPO&)`)koS&eveaCG9$pPB5OA?aZXPbQaA-qz}d(@#dsE!uD!aYhE) zC!*06$y6j|Sd|xx!&<~U9q^s3Tb2 zMD(M*7wZ&V_-a{2i3QJ*CPh}{89k3y(u`iPK@DYs7*8#h4tXZ21LE+mE)BhsQZ*CC zTo(oZ$12;R*Zb%U+(4p5bO)QnjL_vqC(+*XCAZ>RE>xOxVkEfCnQ&#bryL zzz+5mfn`pepCIK4eo_$?Qz2D#IN43C!{;v-(yub;SEOmiRq0O;k_raCfL|gb=-vo1 zL26d#?%ROZPKz50E4{>mHIXo$<4Wq_`A&@Ud`#JgwP}32HhkHFCkp}g)?ncFhfR+O z2Q%eQV7{lN1oR}{_>H${b?~s>-e~nFcIoziTJYoJ+GN7X8$UWk1H(oyDL$V4Lb%|_ zZgw?yy|(ZP8-Cw{&ElYs(G<8?AT=2DOWC>vbnhI1yxSJ7sN}BP>bL5ZWQZF zQ+RLp{I5hP-G<+_;Pm+T_cr&e+aI{GzAJ^HZ>l#e_=*kdC2YFBJKVoBK4~ir{i$c7 z=-)?1+dD0A$A@g+v?K<4{_f7t*Wf3|y=B4dFY5qs%3yk@9AZm(jWL~HYN|KizBv!S zXN~jR4T1>NKQ;_x)D|DfyJjz2dk9{IGml1R?eaa$wqO<>`yc+rF494WTc5%9Bfop> z(%_6y1_&`iy+k8ji| zU2dO8*$De60yWxM+<-SCm%IP%Exgv4?>`ySjam8%nBd;|ahezu?e)F%d#6CZQz2ze zxis;3s^m32J}?n6Pbjgk-1YBu4=WG*qCGq!=ufBjybX7)ddo^a59n5$%y!j z&#U}6%bTy@p6Ya)o2|ha@9sRw7-AzoPI;#xmjPO{5gVl~!C=H*@`wkwNKBnC8+xQ1 zPqrlTl`qX=a`t+RdYWX??8HnDW46XXzuzPtBs4U#f~msv$tHM@xWvBW8&TMtl7uTgM_E#ACEKzFc8Xf) zwIhq3k!>RZQikWZyv)L|v)0;Jlz1Q!%>%%5{q&|PNcgq$$g^aSN zk}1V9YEpc2bN#fter6!P92aZ$&IGSL1CKS?JfT_Ak)X6um2tpN!J^S(0i}FaRZB;< zbj#D>n9<@RQRgNyEnP_+cDxx7WfLA}vQ^Zug^1F#HHNmxTFXm@gvqA1o(WGegmxs- z9EIx*UtcV7aKzk5dd@Qt!$BkP)0QE18k9OkYIsu$;dC~?A|RV;Go=vDq%;zr57JRT zR2r|lbGx-s-{Jk^7#m5Bp?9QGeK@J|vQBrsx4DJ#e`3S+YbKg*zu)WE?JKO%J20@$ zu|G#)opX0RZh>p81`A$f!}lu%3Jc>SW`4h3f-UPv(yHnu9R@SQKNUE%Hg za(}FhxLM}&iTfm*gudxsLQ6M)X6UTxnxUyHgl%`J@Jeg)8RPEV+#U?~pKc+i4LWzb zaL#nyuzQXuVD`$3Z*$jOWZi)Oj!@=PZ4F*-!{gJKG7!^tYuIWY;HI?^;L|9y@D?i@ zN|rfFN|x4_XWVBfv$Qy(insq5P7b7KvyQouq{OIoVdnhCtu@FcPA4 zQHRgfGy&E?eEomwJN^{IskwZB#;Q%?(VE39I7{wkmM<3BokT18B?{INP&5&0 z*WEN(H$0i-VA9aHcDeg)($W%#GZu}O(Ai0+iSwvbvSItW!9%LRvb6FqdB>{Jb*gik zt{^;p5+#2%>ClF&_<^MhVP*)WfwU2$pz-U!Zpj)k8bU>u*bo$F5y?Qjt7Lr_{$^!$ zN;Reqj7H*#a{$-+y;gf21K7uV^$Ub=NT)?O4@J^x(va;XZAQmF_@o8P0zV6l2ZP?m zS$D}Vm^dExBOGHttzRnrG3gl;VUTN0ZY|?tGeMhg;9b)KW&bX%peuk1g zxSU}nyow?_l#yCD9%Pfe5@aRIJrybqs|bq7?x|Q&-czwcx|G=fOUd36!`bCrWpbMZ zoKAFWdYhwNYb*#rx^lgZMW{Dg>6hquYYYgj<8i;Tbhfpz?GEr<^LsZnV@*gOAk_(1 z^3Bv3F0#!9m+H9{QqQWOtt3Z93#!;1gAz5cVyfrFsm%$5$uyq7Z6oC-W11Sa8Hz*W zaaI%-!(H3i94uj^iXSk7N2F{6mXyIog2Qet77gZTnL0#Y6OLnTyenibeDomOn+FZs zBb#a-MnTm&AvP%Y6&C3_6!ao8CQWAcw=o+4?qq9 zkt(@iusTkGSiMBeh3&LoB^Mq$BrRpYe`aG+B zrY~u+ToHWRf~N_z@D07NZaG%vnzcK%`i-9-v7lQZ_%VE;SFh~+Bu8I%M+^G~{N@3? zy>Y8t2%^A&+y`V^V}Hb8s=j-50x*O@2ssSddp|$AgA}&s6(lVu#R41S6JV!g;c!Z4 z<)zF5{z_DMj1}^3x6Qv#Zwm#S`rH|#G6_2QhGMUPEhRX8z<&T_n|b1p|<3VT0y^M!-+A9 zR-zYF?1(FxO?{bgN~1@_FLXqdNjE4CfEkPt?=jRS+Cf!OL1VoKIFG7i0E+1ceg6Dd zEe?wKL_=r^vgVXb7QZF5XE>+&E6d zk1kE})$~^pw$mQ+i5^Cw4Ad;`2*!-jg9M%HmtHK(N)C0=1EXVAnwU9AOw42>N-Th( z(9x`bPy{0g*&h^aL2UwB{47TSi39Q%db{OkoKe=N^dR4pZPXMlj4ovJh9r5ZL*{vj!PLcwgD3OL0VM3ZOsjt7o=ZMGLe3g*B--3qF~(xr@>%zE_ULYh8OtQ! z?!gpM!+7DJwP001O;9C-ieCaydhvXEeVc3#)q+Y^@8^8f0monA4?3j|KOrXGO%hg|BUbcMF+E zwlgY(BduPXnEzZ&J^mmGd`!^O*|T9Th#a+!a&Sj-KfZcEanJslDhfQ7{H3E5yWf1_ z%W6zSCx4cKXBp1Frq^^cA;ApRjs(+0__R$SS=0hwJrqohzA;k^nFOYtPgCE@61|e4H| z14m;stB;GwMvfcS7|i;~tXwtXFq{!+>8W#FC-3M|iTy{y5TlW$@;64HvuN%3cmryZ#jf{|;C6CyNX z9_BbRoWSg+I^}pB1oCQ+&~zHoDt9~|xAs_XjLxGZ6Oa1taJ%2#?>D=}#||lx@Fq(= zoG-SU$QCbu#EEi%V0@3E#eSIM>;Nk4i$6FH8)$bzWNZ!?Y3gF>)9sFRpaqLlF>qm@k4<9i@LC-XWB7a zz@HFhZrnA@v6SDqGm5>2Q!WY5`eP?h0@MlRFpLs+;xrLR8(v~!YvHGYbomh_LXkXM#Uvk~tbVPBK767k+Bu}IDchoP_u z0XVgi8izz;x;68z3lurD;xaEEN}kGyC1cmphEcMCN13+}nvzCzOSd=St@GNnb4&n3 zW75FPAkz|znDRjOk1S{ZNF)14R;a2Cm5q(wrV+p@k9H zR93)vn3sQwoeMm|=3I0mj#Y0Bd;J^S;ZgV8FtVUkg`e@dMXV{hNXU;IyR$#6&$GX& zOJ!ocn=Tn{5}s$l)xzRf5RC)kabjz0=pOC$H(MLmc3P+Wn?MK6ll>mM)^WXwldYNq zym-Y`n)K@FR>?ew1?be=kY^Wo(QfeGTx{N(M zJf2{M=E3y^{&f2#$x{P1wZ9qs-t&Zcus+TwAssWhYyV`yt1AE*>FQ?sBdW+zr=Ki3 zZ9W{{%G)cx8>?FTqJ<3!lc%Bt*2wRavucLIzzPEyTGDbLDYY~~2E1xx7rd-$l#G=# zRYqSp6_szNva(p&oi$_wagx)L^ObP(bHuEu9KLMhi9LCx>NkqUnDS3`jzsX?1jW1x3rL7#E6dosoE9)k@k})*9dd z#O?7*l*HcCJ0=;dy+5+xu8BYpS*#?I7uw*exW2}k2b_dBAz+HLOkcbcdLq9+aK3=qP@!H-6yFS-gU^6M$AF-s*R+c4W$Xcu| z*DYM1_wHQDg&9iKY#=Y1T5HczQ0`LkO?h~DVKgWSL9J~E>cC)h|%UM#uJZNoh z;WLWgN^&d5ybt(!tR>0s)xRNTh$-hqL^W@lu;8DqDZvS;-c!|hq_GD4j1BLf3Ko!9 zR-FIkxr~?$XiheGz6~FkRwP8`r5p_zQaV$OhT_cE_btG?rjHw9cJdVIb!Tc7kTb{P*EClDWvgVXu(b5_OMJ@asy@Y!O3u`+UYIXDr zL~o#`zS|YPX2EYw1>~O5Bp#W2o4xJf)^<>>gx6eyePmA3!%tB$r51x<7Z}y`$Snp6 zs?HIG7ufKjsh~Tt9yuCBK9Eh^df*_UIOFM)3)7+l#jDYf6ZRbQe{gK0v+g=msmG`B zNawQXOtl`F>fM)PPFa%m9WA3&@rD{f6$8f)r5 zEO_5kf*u{H1o%v*{ zM1YtUYl>QgW^DD#HTa#W(A7e|rM_@u8yj>w!}C)@8NyA?Wi!hBsYM$UCLE0+>6)~( zj56{1j~2YHLhMG|YT7fDJGSr@3*Jy|P$P3k4s3?h%M<`xT#VqeyJ!>Gge8+OaV!on zb-LZDxO#9ZFVmIZVLAS~CSM+%za;(fw-)?rg%mb18Vd2tKX1WnD-2+C9F6XMzi_@% zs+rI*?g>?!7PN!0N=KY7qZ5iYe8Hw&=@W)P?!J)z)d}yA@TwV(vH3|XQ5`n`Y>ojR zU68Eh4|3Xerr8DWDis3aLz$PnQ9B$yWx=z{%hD6;vS1hK4=s4^L?MZe9G$sf;vK={ zVJXhRdD%|VMK@--CL9*?U&>Z5&SWLanY1`edIJqsv6IZEp4#W-W%6SnLy^s=E%@mY z{V$?dIWW%vbiDHtBNGMZFhp{E? zsrcqvna2nr6LMLs*g_m*F=kYeoj8*_Np-{tDF|<}$=IGT<3=9*D-lP8I9Pz7i+1qd z5G-SZZeEqS#wL`8tCI%Wp#9eWhYnjET}i&*hCj}2VyACf^MpX_aOUbX^bNmqwlFth zsFiwi@HQL%W`@{_c!UMVa(~l?zng7TMMhk1*ZBc}tl}K=f87m#F{_*v^ZRG+>~dyY zeL6F*^JX4GbvY8YS-Tq>ovlG<(A;bd&eZM86aklf-PqEU2fWUPznmqt=iNe3V9)le zZ1|HI!cQz=VqP5(Gg)WZwBWH~o{`bHv2q(NhOD>S@P!%TA!6TiWTly{6eYUQ06ZYj zRh;4ae3&f_PWy{urt1u!RkLdXaUJ120JPu(0LEgcIIBC}d5D-6>nJ9v!s~7Ls~I|E z!)P`e(JJI7)#xJO>|`fBywQfgo?!$<1_(h!rmp%=?U<<;5aFSC(r&hS!I{}uUYK3f z+R&feF;hk%;pAijdX|VyKy_xy-ldkkj(|Ic~-$oZTQ&Kflfj|1*dplZo?;L0U?n=Di0E7sDYjtloS{BdgX2`79D@x zP_ZRAL~LS_tr)&OOYR>T)!h;z(u}*UE1wWAl#hpE{*P z3^pOsBs5cL#xO3DXp0wiV)KqaI`wFXj&A~Crg+l-nV-T#its}`YBURUb*9{KFms&W zQ7d5RxW@bm3ad3w2)?dqjk53&!9AWndJ!2iqt}b)3z%7_p~gt`B5=fYLH=3PMQ`_5 zN(sEcUgXNx@)|SDc;Txy-d$NW=SD!DAe*nN+&&4S~zwd?cjZ>Q26>6Askh@n)qa~HwxGp@VUYbO}oF$un8RU8*YU`Gz{;+*>Y^D)y;%F#(qqEZD1bH8mBFsHs`;3LmZ zu81=PZl@Cb;)1j7^o_3~Au@rD~LTUWqtHS2;6z;jI^F6*^#0_|3 zWq_jlN4{*qn=5Vb#X3TSsBe}LT5~X6M;$Lo<~<(rlb*UEjgA_v6Go%}bGj&<);FHh5v%vDVRx5$hY!*cyFmAh^%UJP);J=N** z46&E6O}5z@U2&`~xzChYhHqH#_DY)qByuWbg4GBhsZmMK!M|AW+fxN{R(#Pa z;98&jHo64F$SjcuDl()bDhyzI%!IX^o+f$>Xor;Qm0ar&AOko~VtL)CI znilwT3tm})vxOY;g8xfg!K9a~xugDb7QCv0fJMg%0WFi4`}JBSR4k!c+!LuL?wyxa zfF+2Lq4Os~rvv`PhL==e=W_R<3OFUaXogd~E~hj8Dn4C~PglAnH#X(XUfpG0eePN1eixr z!y;}R$cuXRD1Kq-j&-c_h0XEHe?VSuYdgH7U2>;gtaL?nIy`T_jFa5oaeV0-Uj^C`1zJps1LkWttF3r^$IG+$r^hV-df9l zeOS7JlEESL$&_G^`10gTl4cRNDO8KdUW!v9iH8Rp_mI6YW4ZLyjFXH;r(TEXnMj;35pU>yN z2`~>7!eLtxL366HkL3cc-^@dpCB|Nn$Y(yQKWo8@C!{%puEDV!-G5nw7gYi*;Uv#} z0c9ROaVkV*Rlp;0u9HKbho<10Rbg50qH})V`C|l&_vY=5VdreC-)Rk9pUbc9v`#JE z?e=@2tlDhoP;YzK9G>5D>-K?~#=N%R|F+=gE5Xm+u^c6QMs8!BMBPB3X{g>InG0G0 zqVWwBh6!~pSWEJ+RDx;}AR`*)wy`P=W>^J6!kXDhYr!w=f>%_Jnz1^NYN&ZnGnQYs zU@G8Fg{88>du!0E6ZnCQy71z`>3*ksrpb&^-Xo#7b!^1035~$wkbU^YY6vE6E8jq73umB}USFTam(o-dlRZ|Zr!9Sgf3Qj!wVm!nbbI~H*2Yr5 z)ou4So56RRZmY}V8vA%P#l>rT7wr06V_`1%!wmLzkcqNY`8oI}3*Jx(*^@##7`EH) z*)&+c@kBFN-&2EkR2SCUJQ^Px;y03w`h#UZb*iK-De4cv-X>;1w=fAhV3E^7 z{o(MiBToH-h41n|7WsyKeBiq6hF3$2=OO!s*V7(nNmO{(JiNBLWZT@{sMjz%>`WPJ zIh7ZCZYJ4_nYjvHI}iW8vOH7Yado?mHO|%MYNw3B{W(s+JnZq3TKRJ~q~=PfJ*vyC z&ZE=IV0v9wsDjBZuHUsQLXTFv&84&S!7M5UakAGTWv9Sr?TS<*d36RX`sf!NRD%l0 z7MkRs9jT&N0a#U&qYYXWl{=MI(d1|VW)#cTL@mwAzbX!Bm>d;+KW!DF0%{B1Sk2^U zBbFSkMg?V{vnrVs4P>B_X~$4LE4{mhaW&MO{BBT#8M4~0QGUGCn6rFix9y(u{9>&0 zuSN#Lk56Lyy^y|`|D1NAdvwWor)!+9hk3?_n{18~?ZPe=!29Gxlom)fzlkaOOw4 z)N-_rr4Y9I?&BOxry9l^m#=D&J>q5~{v~mBWM;+-$36C8k@FAQlj_>{EMo4%Pnzc< zoW|U9jZa^L3ARy^Beq~y9VaPHO70|JMXtF#24Sq+ET|Y@p(`#2EJL00AMb?cP3TA> z6pOju6PhjIX_kq#z7mA^k~y(sOtKd&!>E#QXPqW%R5a{4*MYd~hC~GZ}-9!y!1w<&CweggSI4wF{2=?5^%SadrQy z2G5=h^CW!RNn41{grz95P^k}lWx|JjG<@HY%M)%Z@nP9-p`^{2@NvVkZ-U0=AdjVS00&zCYFKifX9>2(J~jsIhDmaM@CZ1|HB>`%@9 zPek{@1gwO?W>Pwmd}7J3pj(pshB&9$lk4VAB+ho9HQaf8liP0jO&k7hrdUd1i*qE& z{l5&3?b~hm!mJ}JEe??3Sa?97tGMXGf9;09oL%mU#Vls<9CKz~kvb0m?e_qHvDhnj zb(LJ<6dSQzLRG{8Z?NJ2oh=1e^vIfDvf=-kDGYf=Y-Dnb9DbW^Q-jabD9n)kZ5#f6 zruc|h{Ty8pU*)#^A0P+|joI8)t1pFF)8(`gKW5I(^tm<5CK1;a&I3XpJ|LhpuM)OK zt`eThI-UvMXv1I6)R9Z34iqwi>DO%d+nGjDWRP5zNGI)t`6DLL6Z~I0W-LlX z_$WRYXx90`nc;|^Sx)QIJ7&yKB>apL9~*TwTLdS-Ix}VkQ;R=L!|M1N{-K5wlgD4n zQC^Bx$l3~N^x2{`;o|198KwWjg7;4$rHe@$zud-)=%$a&Ntno_oI68u_?0$%YBo?3 znW^%)S%wtw3?U_qjpatlYj?v(rkzt_@voUZ^PCw`bI#1@rkR1HA&)*?3~<6d)#*kB z^afq)b2_7xG^Fy&0Y8%42 zW;p+O8{S+3Bq=>0m}W1!3q+%MIA#*pzyeN7fR&_1q4}X|K72`~$UYN>Vs|&G= z#!GnBS!v@X^now#J(36*yW_s}D*^-?Gisbwn?!@6I|u&Jg11y$9maYA$O)hryRj%~ z7?`@FkC&hpR^5NE4ezZut%>c&5fGU_g!b8Op*fgZ6odwliIt~|oWa``s;}i}g-y%^ znlc?dT}L#RIcG{W#gy*59Fs_0T`V_<{>6gduK0mLB434M_x{y_cTO45(E&MnChueO zmG_GYt>f|e>7$u5RdEO&JJm*A;G^@EH!cVlq2$Esu&YiKvi3$8i-k_Ep~ zRUji{MaO<7Ztg_x?h+(F3fM_#*(}auf8Vb1uaQXyGv<{~k;Zl^s{qQspDLZszG}j` z)z#G~4HCx>4GGmip|a|0;d3}%vJz^T9Q=iN$#@IPFI5t>=y)037yeeQA_|w#E$*pQ z760YmHO~8r*4S01aT8eMDzQDgKgS1n_=B2WX5u;--Pl={NBVj7!EHGik)g@XC4RW6^ z*}FpSq=iwxu(OO~ATZAw6R{W~N|&Jk%2YPo>MiAhZq1o0T&u$SfP^2FXchTFA>N}D zX`aCHnb+7%^YG3ZbjE*{CT>`o>`hN)hy~XGoF4J}fJeVe=?^W~8b8UxD{{&8zu(WV z|9#k+6I}m0fBD7i`d@bSFS`P`hX0Gb<+>F5JiMg_XG(-cyzaL=ws%S=7b8G;?{36_ zqw`#;mdZ-PQZY%8Y1CZFmdXmTR5BPRL~h`-J4&=vRwiPpM3k<)m;9O%;*rx}arn&5 zbP5Zr=(KxHYL>t+mZI_livtrRyZDXjWgavoS{N&ley6uJJ}xm{cON|T$fe2K8rcPn zIHT;;_zz-o)m;hn2)RIWIMgEi#jeuBX)lm_l7L30gHXPto`Of5a-Vzu!-BiUPgV&8 zQD#yOgRzZh!Q@~Ft6E63K^MA|18c!Q>?k8rLg)}HSt(1p^UvNGNn)HyvH7GH_6Db= zHHK>M9nV-t5+BLtU3~6tY;?8;odKWIHdk&;aFtlv$@qLs%P357_?c4T^Fc&lRj{dQ&{h?E$)!T?D zV2txu*5E}G!#Sf+NP$+nUEgtayM24ZnPM(*E*2O7L24deG^IsIJ$M?3Z@GrumCikc zeLNt0@!H-69P8Ow!1$~8M+_#}SRJ~z+1nm&Z4dpUU{Ie2`^X$T9qPgcy;n!3d)}9y z0+IcZmPhOJ>~De;Z%s$Cix7VHg|F0AP~c#PV*(hh!NBcvK%0%FPH^#k^O{?Z9y@;9 zQ?5CF-L=iDk2iy+MZZ<-uyUlI2Z*TQGEv!4ZWvjlIe(xL?7V&)9=E0F)zSMUI zz3u+GO9}Px1fli-99clGeIN7O;X4-mgs_V^s3$uc8%^v(YIRR-Z=hn!3vo-e)>6)u z6yQH10se(>!I9lw(4w~R2^;RGIp^H)$H2e>@IJCjyE)kCth=;R#n2117r&Pa<%8Gi zL6*e6+!M@wD4IA}817V|6}dIGqjVC+J|F`jl4O9;*`(N< z+jhNrM|h7#l0}6R{Wd%%`vVut;l#RKMYzjU04?~24emHqVYu!3?(j=zoRTLNQ;wMk zDXj7dsh?}Z?^-0%U-%|{f1I$%_we(uzIHL5hjT~ZyZnz~1?4~1;KVrj#NV_KnGvf4 z3P%yKF`RM)z!3w$g+n9|T^3#Ow3cte>-F0==i&FQ@t(;+EM&>6D&}s~BRPj&w)T*~ zVyj)ghZz&hVq^cC>a-gCyAA8(ThnLcW`d4)otI}>JOK?+ndde-d%2=vr&FUhuuSEL$JMt0W1!|$T9R6 z(HMH+8iu02zL$RQlp%3W*_82ktMpYpeu$*dK<*Zqq;^7E^iJ5X5yGGbzzh3mqx5no zkLluslLvRf!;oIGXwFhxJt8kCU{>D9&h$O?4#6^r)EZ;=UMOs;}r>oisZ>AJk@v;Bhl$r zc#`n~W|Vrj1rHTod8*&r-a@i&4RErE#~aQK&k}wgKV3vQOIgsl(eOq7a7Z1O!51vJ zN!XP~(B|^;$RXh>#+%#lAPI9lZ6Flh3SDyZf~%M#Tki_%D2S{2Nk zD*MHhdKg0E7Eetf*0YsHl8SZ6glcwHB{$?|nO3YDCSqNboCS-eiFM2jQ{y2;i}2+_ zjE-5X8|h-*(1~@hU!BBqkd{pz3QG?>!zq$6`E{F?T&|PiZ*&Q$%67)vV4f~0M(RM~ zX&+0YrRUvfayW5#S1xsmg|uQPQho%)FeXbp>J0_-2#Qb_$)U)eJ^eIoP#QBo#WdVFMVU10jTx*UfjR-EcFJE34l;cM)eow$83*KbM%c7f0e(ipH(#w zI+{!kr5Co~`*n(N47CWS(pM~o)89-()|6=IeaDmi<24WI@{SqS(;v&7R{wE$h`<1C z>^5p{u__cHF(U2pkc~kjp$a%dvggs8x3FQQ(>>MnX3X-_J#SM8Mxh=ogQI@2kN9g5 zFjif2`-&sxF(_4VLc0PPj#vnw03{SE95oq78Sl2RSjWZUrLd#5(K*$v@2SIWH{S51 zy#x<&ey0UIds>#P5Gu zmozMeku5`CT9w3LK|B@)gXfTjt7BN^b+BH;e;kr73xJmNE;SY}g576a7jxL1%>fQA zos%2t3iAg3#v&Q^W1YL*nMx`@nKXtm@VIs%^=G^5bGKRhL|wI8mCA$Dok!hM^&0*~)?o{) zb{eueJVPd6he839YRT}^X{rm3k!{}8!)@YUG7dgu{!*Frt#I1O>-CDz5^&hy+HNQW7&nBYpc|`$Th!!q#!JruUQage-eJ&e9Zt2*$N_0XnK7U zm=snBYu5~lE}slHnnRINTo=?`o>3L^tpvqs5P*eQ`Tqe8}mEbAY7oC1MV4>i5x803lOTF({xs!@* zUStt3DA;&?2cqSa>nLGzk|>lu>}_&UeSx-MOTlvq2eX6qO5eT^&DW69#J~u)ozuWL z4UZ9Mc=cd_?mEgxG{qsDG*G|b){WM>d%CyLcKafSKUm3rs6Pg$TUemZW@S7Z9M~=lO52a~$dnD^-MJ>mDBh?Jk2V1X(Y}`g=VZWmQM-M)1(!;9TVKGF>uB$2 ztLqq1#xVps{k(oEaXxPhhSmsoqRBU${^Gy11SP%99ShG2cB(V&DS{(5hgI8>bXri# ztWiKYy+vMu8#5HtMSFNvi=a=WD@E$~5xkxFA!`o~+KDZ7)4OibJ5m=7gP)q$;Q6-0 z58_|Ac0sryi=Gki9$PSnVi3lv?;@);U?(R!8e^Xf3f!WWKpr7`Hx_B(!6`*Jy zFsdHbVKE3h(3)mwgA*!}<=|pIKEXaTQB4S-;d2Yb>`%CgIE!OsL-j3|U<2@13!@Ms zb23IbM+3KD=<`>G0~%SV&6~QMX;LGI?#%Mi-EO}(Sn|3^xjC(HXJX+pwL9}dswTY^ z>hss*L@nW*=g<%Uh0SCi@5YMXz2;fJ6%ug+Vh3#u>ArswbwjE7RhQ*pu|)Ayuc3B} z5@(7fBmJh1^d?@cVQSlG(NMq17tLO_{LvZ_SaM__h$06iF~YLHt2@n00&19V^80v5%p4xyrUTzno}4D zwiVl*xUCVyum^{$Ji##6VQOt6OX?knLbjsNxj?(g9Sl-~ zuXC&Sn{DUY7F?ZsJN0?CDW^!1IYl5TQq!ssD0XZ7NG|ZNJGWJ@;a`OUpT2Lryml?u zzA^E=yj9=f{o~|DLHdTVhWxr*8$K53B)pe4_^M=--*4xIAh-%xxLG&9=s5+jfl~}+ z(wX1`d6_^G&C0p=fF|jC|DY|5l^Nxz!-<^Ub`Xu$aL67$ppe_ibXG=vmX2v4+p!WUnBRKg{>1TH#q zA-S#qULsC{8GQhZ!VFWKfyD9>jfMxqXQ-{xDQWIJH?_NA59iq+ifk3L`2IbK-(5`Q)9rzot%H-hFAExV$e9Ri-G` zwkGOmLClfMzJp>NxqEHm$c?rgi6fW&MX{``DCgN<<|8TMe08AO!fSqrGnaiasWX@T zH5376d&ha&q9vbwQKdtd{Z)ttvrXd|718|8z7luk6i!|C7mkAZk5k7k`=ZD6j$QT_ zdeM{u*nzkg*|))|qf>(+qX1s+osSu~884J7hxSE#dwtmHb+JCajVZwa&%GG; zpsT720c((=jt7Ked($tSOae#DW$CVrL5!DMT4HM&ypk3JVAti%c$M8w|6k%d2dI_( zZ1EDfV2IV7gRS1cZMMA5D!qlgkACC?e#8nPBKMyyv%B@80&iu`-!O{4PAGt{_RG7) z`WA0JQUTy&BivsKQ|$vB3)~RmB(3%xy-s(??h3?d@_1WUfT^YEE1bx_$@xs}<7M+^ z@rsye9P;u~`Y!6bkMpewojD$#IwQcNL6hHXi@wou5AdKo#Ba%ZE};P3d=2p$K99pOr(aML!$;sG0RZ=j0C<;Eiki~< z@zOb=2$``6!fFo0t%OpcNgk7>EN_g3u?8b%H?BUwRAC!y+pZi5%#eGF05W}_ueadH zNc$wt zWlFK@69qx6o2tkwc_)~W5{Dt6RqR8ix7wv+(lx;i8+$B8hm=+`uF|xZyeiK)-(_iQ z0E4xne3yJR+ESo_%xtwV(Up5OtO8JnFjiw3F3~U!=t?|rDH$}$s1SJu&t$7ORJ1z8 zJ0iR)-L&#s4jQzF! zYQr5~?LWp1g2L8?wVl}6f>)r6iJ+Q7%i?2jj&u$&p#0&CQSZk5t$6JSDfAaWk9Lmj zuwEmEec2rQA?s?ew4DD8!ivJmh4gd0L+otxG3Em%^mIhcxdKW_509`buXAXC9Xg@_ z3BPB%*1;=O=l_TFCCHEiwp#uG(qD?K6Rbw#6_e3029LA6NKS0|#& zQE!VwVJCYxG>F)Tyc}PujnmGe32r0z@SK8&#c=4om<x@)k(n8OxM?K{Hz`A^M6;@8t&^}pSLER)Tr+`GhW7}(G~<#+wph3d z4F*3nm#~9LWQ#?+R?OFlSG9Yl-b!&J*(zqlrcCrI)`&e=q7fUcRgw|QS1ZYgJ(z05 zu4s(dV6z$nm4lyFiRp_xo?MO{=mi+Kow&1xV0y2Po47(^MCns%?Oo6=RjiS_A>2gC$>2dX7Blxh zWW2(biy68xn>Ju5M@8GX+Zd;e?)RR-`zY$V@Xr$*C?+wdS-K&&N=)9>s25M=7bQ*M zmwffTZ~V7UzVnBP+lf^padQ*LP~MCQ;Up>BofxOP0&je9^+0T01V}aEz&|Gfhh)7y+s@g29og z6Ab=Ln6EG#7ZOiRZe|Zxd&lIG7-N4J15w@u zc~Oy20G0QZyko?Sx&OcxZirdN%5i_Vca{T0I_277wb+j#N1W0^72 zFfnEhOO2Tic zTQ7d?S_CAC#3}X`VN|VU_r-gA$+eTH6N!!1yP-8a?e=ePc;n=Gx5dbX zv*=5Gui(KYm#HuC1xfu+^q>bnsTGcX#|S_;F8URJt3MTA#{#S^+Aqn$srf8=-Wsl- z4u;@i#W}melussLjnfyxuH$$wbc@|Pi=*UE3irz_FD2JUJy=MY&KE6sgcgyg%k!X; z35;+div|>(slk$1Igm-OdWevDO|Ogh%?5>Bxg`x}E{dh+(K5I8d+qu>``ghot%6m( zZ6-#FBrw^6}>M=VO6w?5DbMD@US0kau4i0 z?!T9v9tRSGf*uYJJK~V-l5gN$Dh~Chq=d6$WQbf=$Y%hc27&v?Cg}7Sf8Y$6LBj^h zc+FY1*Ei+OinTtw5ARFsk#d7cf$FwG0UKsXW{KJaFNJWrNA;Z0NxLB}O zMA(F{EL=;h6jcZf(tedTBK6Ani}E; zQP$xH^f0TLm!2=MP529IMe&;Spk!3!uwYrjVc}Lr;IL;%F6jv`xzDX!Pe|T=kUOGr zjvC1cwLrWen71{=)HW#-RTUCT{8Ogy#Fj#?sRU&$(&m`gbGAw}g8#FFL|FK1@@nH3 z$XVD6BziJKN{c;~A^{h^kL+x-NGuX8pA~7zs+y6=xE_w*5`W=oM=9qDq*n_}stG_G%g932(!w?fSSJ7U$fx93FdGXtdb0J4uF;6i_pY-w*^leag#g?Da`FE3$<^v zN8fd_%~yQ)ci29ph_wuDa>~S`Sg-8Vgg!kLSa_nUEWU#HjGhfr!(Ljf$Tj*6TH= zdmHZH%z3n4gRjUU%yP*vZy|OuhHvK{8hPGASb|o+;MR@Sx{Et(yM57EGrZmK^Ymhj zy!+ByJf6W{0MH_w>DTPYhMFDXsSSBNAp1NB%~k5nD`~@0+Qp?JboyYN?uOG~(I|f* z*lpUkDiXAF+F5FRwUj_(hFNOb>1J2Pnv{}m?O}LXw=VF-H^Q!x5;H9ne^*U{HCh z_Gih|2>Gg!To-qMZknuHoP^^Y;bOuk4ri)}Ur8pZ#Xs&7#}Q{w$REMEhXxN-ap2LD z$?cf8wYq1d{I60^$(Xebw-KLYuzez$p^Y@@tzoQE)ZU3aSE?UAGZ2ot{FZoi-Ow`$Sl(L|bQX=VVD)rL z)9OT?w8D!bz4V@6Y9hMR-ixCXSW+mWAL05OX@YM>p5XInB~9=J8`MxHG!kf5AH&@Fnsk4|l&TTJTJDOC%8UY=uGjj$*l0MRadAf*V!Nz07l zG>4=y(ZjaTnuPBg5#JMwL4h^Aqc|wm-MzL8XA#dGu`EdPy;q$q(Qk3S$JHYSRV;~9 z#>5gUjv^ex=ka|}gu?v2ET4TaB2-+q;ssO*tg@!Y?!Oi{78ZVq^=l$wJpWaerEQpJX;Ba)mo$CZ zf+q`c-PT~>_PMt+Q*H&OeOgLDPvQmSc%4@V59{rXR=;`8Ek}E2?`rkiu>@#gVaors;K#?c$%L;resqW-K6~*I32*vBxZuccc9mhh zw(toXejmGiii18zQ#2p@ownO<4mR*EK7Xu?AT=2DOWC>vbnhI1yxS}oY$t~p6Ya) zo2|haJgdEU_K0`O>lNPH!*X{ze+z!sg45&U-`nsU>kr&m8wqF29x?u9(3i0_G{N%W|ESUXe9RN-lOz)IKZ04u< zh5vfR_04%XSN@(g&T}{Lkg0$CNba{^w)PP8+u60)wafP~vw#_A2?I@I`PATF>>?e6 zxb+!qKk~cBE)C8YWq=Ta`?ofA{1-1z*!vg5-XnWFd!Kb_u=`AK#$JDXYQet+X06q2 z--@B*B{p$i&oM_F(_Rlopgg7qbrQy?)1|JpO~Sd+~cL$jZPMWe+6N?pUo?JUZ375p?a&s97fju|aJ5_N7O z!_$@2VaJ;RQ8wXmCR;@fTZkw&0LN6#fs6LZc|oXCrqi3;kX-e#@6#ah@^pIdvqb)q$J@jUCcJHt+|+uFF| zvHM&7Q`?(vcR1Mp^rO9@yMK7PHN?LHm+P{Dw(t0kd^4zRg{C zk#z(9J3^UHN%EK5@c1;Q48*kE8n&7T_y(q49+fD0iQj{QdW%xbWRxVh6pObC%uobo_DgN1cO@K8JU;m%_PXAvr_OC@MEq&u9n^tf# zJ-(dn@kX}CSF%06YHEFDdoAsTr5N@+(B?tsanA}>?*VSydKSq5oiCqG;TJfa5c~S~ z05leM?b=mi|FNl}gYC`DRv!-IZ|5G4~_QVs>sYdW|2;(|N9@FG{uHoug(u3ZqFWJ^@a$t%o!WJlN({Jislj ztJVawHR-A|x+cM*1KZl(z+kb+NF^qaU-)1hfl+!AwY`CS-S8O8otC;^+Z(tX3tda- ztm_R7wySIV;}B_k1NlR$D0H$+(2{rgJ_s)Cx_33%DBGx@5ECtKw;g?dS)xv2C(IvV z&0RdF#E#=I(}dAUvFE|pYs;aHSX6LLIzVrQRD~rYy|F}&!XE&%_CyfSm&CEl%@v`3 zOKcyCrFE7`9|Q+qHcHRmZG^?JzDXCJ7aQuHZ;>{{wSKSFUdMR%@m~D`;Ty7{aEgiy zLcW)@X&(E;3M=@e16_6+T_M!38abF+t{Mf>LJ>Hi4MmO zWPWw&Y-?lNMcWJK!nfAXkk&vd_*ZIvcNNEpd~&$%_?P#mtrnx`@PGFJR-!HXg@q##F6tjVG3*KuI+3NmN2lzUGAjg7_qyV!^Z=cx>*0n0!)B(3%=rq7j8qo%A~GgX_40j_6M$1He0{dfb=rP` z)-Ov1=3rc4G$-W&jl^8Z5Rn+MuM-pwPE9T`2Z_WePJT(FEj1ZHE-?plNKAw=nZ)?p z4q;<158&pDEoa{CTVJiY}@^%ADsS7Sx@W;upi88E2ntnER4Z^oAc$#1l`j%c;=Nzkw z&Dzac{YKG`;H6dtf*->dMp(w)DT+5)ZT_r!;y*8jQ?IGwL42fiZ(I;ys4i zMEmH7!Qn^=0?w~08358hI&uQ%`SWA7I4I&14WuQ=no}}a{1(!Z7tP&6+9h*kDb>c& zZSAJ5N4R_B802eg5(TGlCAe{%h96y;fl0cG2@Xd zk24=4Cg#W*OrC;1B-nzQz`8UAy-ebOK@z~Ecw#~vZ%J(5=9T0YUi!ObUD86I=F?sGph#LAE{2)p zNsGg#%%sJpjH~=@=isW7WC(4PO2eu!A^(JKUzB4eIcI3mz&MXyQU7)i*-W zT@+98y-Fqe2b4u)Y8>KCrHhU=$M@-d%*S1hV_zoPujD)Y&)$fJq*N9=0}zB%vJd+k2!i~5H-#%7Gm&c(#4ClA} zgQ6i+ESoJ%tDM6rtF7)}t2c0$qOZIg)Pp7qb!4BVAZXY~ZEV=^F$)2tJ`^{}c;2D90US~48DC>4eAP@X@#=<^>9O49p_&m3@|B~smVE74@41>|w4)^y zYlrD5`P%d_)CR+K;~nCQ$MQ&G*B2=-$Ip2Tq8{%Me>1Bs#~Q2yqTGlD>+8p7xVit(d3s>*}q8D3mP&i`ar?GTl0~0*-oy{k# z+1TTzY??#GEZs`*!)%i}o(i{Q1v#ZXFBn5~4i05}F~TLzS5ZZuk|AGep+N2yxF{Me4voSJLG8~$t zv6(XnVt9;WFzY9?a@B~_b4H-0r_OcVyrWAcc1LNa9vRZ|H%6f43XO1-V}gx9XKXa| z52>-sEM7ZjG%yKoqS3_#$jBt+1UFAZ2(cct{FURC;?HuqQBIFYo2z8x8skU_jhK&g z@Z!~W%6T*hG-5o?(IEp?XliGo<~VWB=z0lcE7vdZ+DB&DN<^{H(BawezDy| zwz%L4>{7jXv9Q4@fGJAl#KHI;LyP?|$JrCse!#=oqmwg?c#I?a9HXK6jx_U7vStO& znXg*#ER?&=S1x>-(J#gV?J;vb5SZW}I?rf~g7enQy9!Gf3X=@c{ZtAfU}G#f*wXP= zk`UdUbzh+<2?|K9|8-e7cuv-}3l^w*GZUro`9iOrS5JJ7)T%F6;e?^oL*L2BYX`D^ zU^(jt8d*QElJx_t=4MOQS05s|-BwI?J=>(YYCHnSXxRNA>rbIT2~a1LbtxCV_e8=3USeX$;JRLjfTu&oc!a&#QV$Id6#(B) zWc`(Vd|~aAaZxNm+?_(Ue#uXN1EF2-`i`cO8nH zv1qA$TtF)>Gtvr{JREtHc?+Q_sZu(mkUD)3ExdJJn|6)~U}#Jlm>FbTf)P_5$o`S# z>>p`l|Hw-Ak7O|{vvYxgX?f6jtS(LD6E=uh85x(KsF8x*XqYA17ydX)^999Gn_HrBii{vlTBB9Q0S>K39P)c-lgmQTjVX;wpx2F^u7g5=np{b7Bc{Y`x;6Z1U`+#0X_JPWQC7RM5394U`8 zT3bW+Xs^H7+PJpUI_2LTI%uBk_t-^{>rEVP)g0heEiSd`lNrWXfssNlvx<@%^6Uby zX6_FC3kJAlH@5*)SJQY zJy)1V>*IWq<#L{oG2x#qcy$FJBmFB(fkY)a@+qynSK_-duF@2g!51y;NSHhoC9p=0 zr<_$YR0dWU$k3FQ1DS!6FWLn!s~RO^^-Pt~7fwax+o`N9R(5Bq0Xmbssq@P=p4gLD zs(!0zynV8AN`f_^#Ro=Onn-JOGZK8p!r*FU5bXgGbQ>j2z1VrBGWEVQk9B5M0ZC{y zt&Z-lplCT2<3h2oliRgsJ>q~P5VyzAeiD0+J0==y72|QT_6I6i@JANhH4z9Ri&Y1M z+;&%#gs@qN69Oi*Om)D>2|}$_c=1l?l}wPB;aMGx>P$wsoCz_}@}w44nT1{lL42-a zveCf1b|byzPbV5!tCDO)WRaY!^T+}TcZjXxte5z(#%j`BNAoKdsnyRM-)BtCP@T+auw@%q+fKwdXM`pAJr+DY6 zcz2#cTX}g9ni)`dgNysP!F%!A-UYn5sj=YA%Z?4Kuvy4jEH2kAT%Y%@UCD(RO4V#2 zXS?2owfA%bp zpK3IO=4);=yl(+#j8C0N#O&lL((BIDDj;WywZ;_hJvoGBTs})sz*A#}TNGW9Pj{Mw zf3t9==u{{UR=n114T7Q;evXoMC-rTvmvARxVQuF^t&VO2e9eO2nhMB0qbWKv3B)R= zNMc*TbRLy{VPI6(BR?uLgv(xF!-uAV?!?kOpC{WYw+3m zDKSh4U!g?Ba$3_tAOgg+SX0y@G-In@uEFn2g{~IzE%k*P+t{Gf8J?dK$`Ed9E}K#2 zPc7P@FyYKbG3lCrwBU6WVmIPe)1IN+F7;O|ctf>8jm#Z6uo+S>QvhrjBOpODO?85z zeAa@`?xIa#6P8TE#IZQQ)aiDo;_AVvyi8YqhiZS_XsC4owWe~9{ckP!)e0$WVl))u zmw(=Z*H#$7=r~e_7I1b#(9sa)ZirtFFPyKGY9=&{dqUNw1?^z0(h(Q>#5y|~zF^a? z^a(>CcV9^V>V$Vlc-0KY*!(1xsE!)|mi6VM3ks^`e^;pxr1(%Vds~sug-==V?DDeo z#JZ#|Qcgp94*t-B=S~!o=*YFCMa!oia=D(D!UYyBFmNRK_ znDhqJzQJVMJaCTxo#kmNuUwqzChrU9B4K4V$cZ1$Sqj5#c3pIdAjArlk~K(%hus8^ z2%g%PmX~FZ8_mI|E%@mY{V$?dIWWnrBZN%IWwBxlag4>7QAKv*OztE#qtcu3 z%IEUbfjszEB8~`gObZY&HrCCHqct|6G+doD&<5?d{y%isDhbA9Ne00CZTREdCU*L! zHBSh%4ri{G+&64~tztME&W2ac7Uohyt)!M!c{dWg&4$03A$B4jA&uqAy}=loG)^!4 zrVW2L+o+0+IHI34NKsahJOGeYoMZm4yWuZpm9t`g|ID3T&Wx*1XXbU@%tJW&l!Lq+ z>2)^zm@N%X`-@_x>kOY&vugrz9pO9xwBQ2(#s;196WW!Efj@;N50znB zc)bmOHA9DN7|muQS_{cdzR`xio?!$<2FU2f{-<`#R1AplP&{cj+q~e+Y%DL#0qatb z@W~xBWfT%lP9~sdiP!{GXQu33YT4`fH)L}7`x^Y&44qm+-d30|FiTV>{EI~Zp?Rpu zV6ibq@0~g-7nA&bsSO{SI?zc7sNfXu%We3?EFdH@NaX>XZ^O*b0d>;k@IIPCXi; z)Cw3nt}%at!fMSEg0E{@qbz(x zaF3^tUPOk>0v#`&FJNY!h8iQ$i@*`r1^H)D7rotMDJAd%dyy+&$K13cENjLKU$x;i zl{-KMCh=|LAs51nZFo}&5|gF~i@rlp!>Ang#25+ql2vhB z5P?n3mWTQtJgnKNk;9_dDG)vGv&;F~pk=x$L@}&iJeNVmUtI1B{UQg8OQ4di=X)Rfnjl{OZGs zah_8i)pAxG{*w)NjGtB~H+sE(yK}a_a6S9#+Rj<0r0P_sG){~pTH!atJ1jUeeq7&- zS&hx@&82fZcPnw%NfCmIgWzj+8QLeh^(Js5Rl^HvDYazGT31KJuc|(LY~uUpqHC-*7n`;lTNfRS`7eEwY{{ zBU|k7><$dYT(D59&)4k*>xh-1jPBz_TwgjGF#^sgC+|(bB+JSI z(Y!aZx~orDZ$Wp{b-|`-Y#Wj#DkGO#W`M5hrRX6s>;;tL&`B~wuN&hOML-V-~$QTJSX&~1-8oXYR%w$C&k z?+p4wVYK8LSRG6pk>8BSt7n3qnOar}pVG0S-KZN#C5hN`sPYRx0j5v&Up|0Jg0;VB0UPH>uACJaV;1pe)c;J%!C6#kf)^^8LsgnjXZm(c z;mX#`4Ngc|<~S-oXLz7Bl)F+RX%)Rj`Ic7xX;=gKB2Pz+=faB_)}Rx=(?epZVGfOk|Jx4b-pvHN&sXD1*aQ_$@usBsn zf+DZ2RX=ybYOYA>F}u{7e1)bmkusS6R%bZQdwemTk@skCYzXeGd@u_}AW88$q~Zee zcjFnUMq+gaH2TO34rb#OfGnK8Lz)=R6@bwV1~XWg&}xQMMHNV;&1iBo1yjYcH51i2 zVGSu#pCdC4=;V^4@0iWxXfu->osA00RA$X&QZ(g(nM^xM{+#LCjhhsmqqAo7Gj#$6 z&^r5l2-Nw{Mh1h&Cn5blk-nIJnJ2HA3D-@4rNx7Hx88p?qR~d-ajQ8aX-e@}ym=-d z;9IkHypsP@n-M$sq0W$&9@ei+e@JG=5>94|J*8K_u#a4^#*s!lNtbg$$J@zmM{YIZ zjI{UA_zMCB8Q;81(q{xw{^53i*lBEc2Ad-2{ZtX)zvbA?X}e_Y_I)(QAH)A6_`e?f zc3HJG^0zhe4Vp7wVfmJ<&@d%|HAXdB4|Pm_Hr}nS zeP$60AAYxK&f&VthV#7ZzKd;?hKilAs}7SCcZ=^VU@6z!Ud|gV+#)(6a+Uy_oGboY zSCCiil1egOEaQ6b(rgJPS$3`U)j$a6%w1Dsmb*Y1#!T@*u0VJ?zHlsTz_7Aq@+;A< zag^bw2pg|-@6FH7lds<$gHFJqImgwFwV4TVnC#Xq1nRk~Ya5|9ZUha- z>A3%k)jpV%lpxq_l#b*-(MU_~EdRxDPJ@%{up16)*jl5D5R{`{c0i+aOup-K!yTiW zvF(;0jme*0RwQMy#RZb=a;|`5`|g;0=5j}tFAh*ZEqqC!YjV+rFI+`Fb@@_PCT4LN z>apaq7o^FTfb{zkfUyZhRpV^O4cpl3vdSPya{tywCo^dF`(yIy%S!-GdSuO;WAe$% z3Pa3@RVGL2@Z05WYKVCn6EkGr6O+HVtmw$F`UScaU5#z|e~BPW8na`T=SJjp^Y{m&8kz$N(7M%uXaps??ti|8&r zGB?6RA?4f!lEZI^$**1>C{bprJ#JPY1$-GHMaIU)M#|f-A|JZcDJ2vCx@>h`a+!#^ z(-%R=+8C4@7N&Z2Ox{@mB%U4+NV8A63j~|==ORTqHE!0iVFc((7sUPV zh`evcpM9FaxGzNHCoetlm8Cv*jOh|Zz~q8#Z{16N>{6nDOh9ecr4%3ja0!Z--=ClH{_A4hl^8whR8-XoVR3MOX&y=(96OF6T`CSw9!Vlw*D zQqh9vl1o%lT%z~h&72>a2qXVJBJY`Tg<(X#wCtXd(#q%X91DN{XGGq6i2l9hUGTADy3hzu0)|Y<&LGd$Z({ibDkXQ{*G_GjCiNR0N!psl%T2M=`En{Ytx{ z{;FxoDaYGk$&**t$p1Uz5?DinmKvIM%haHq(0b;NN90vA@fwp!fc$wx-ZB&57_RPw zYmRqgsg=eODw1UZQW+~_Co^UmOzE*ZL>&^eFbk>4PhVO68X5m(aFg74O}_g16hj4DbqkpC2s@0tl+V<>*jOV-@Q2zQB1cab^MbPLOy zXA(4}Uh+<^5evrQCI727BLdfWx2&f!tN5>e-;`fagn6&O7n9e|1W{`MY3{{$&cxje znhbO3emWwn(Fw!yY@@7f*xuakbsFpat@ZW@0@&x;y`9dmbwDJ}$_s+`MWkQh z#V4|z?_KlcCDq+o+b*yhPn^sgza~`^jCD&MyLkyMhURZ3~97Z^K-62H3DZPvRqUZfsd?7i6^lW=bQJ=i zN?{|c-bxm9J9MhHRz>syX@6CrRm7RXX%)>o+`)PB-WusnUzg@KEbZ>5rz+S&NPtPL zP!bv?Cchq$?dd<6T#;+6|Gh)3|9$eYBwhbIfBW@x{V!epOIHBb;Qwam2~P>klOL{; zvlYUkulucz?32o$OA^b%p`1w?xU!4Bq1@pMUB?v$HI^=MOJ&KhR1l}YW}Fy&Lw8oQjWDC^%=8uUDcaE^_OMs*9+CKiV*)1~Pt%LEt(x4G(Z1cHqL|Wt!n=v(3EhGLbjR`IrmbN9_XIRu& zoRGY{lK6ZY5m?qN?X3!AGs_qAd_)z2DMJQTaiBme-#;FZ3XJV`>FX=COPiJ2rP2Y$bm1Xrd9WDMZwvcH)b{#g*Y1t$bIrXFq-FmjUrp-T1=&|C(;fdkU9Y0&k~2gn ze|XE2^?CYF11apx#BvKI7Nk%|Vrc{hJDk$MXb*>-fylwPnvHI{_`Y@b11C?dJ@lfx z*Y3Tib#$#Y>TkDtkhtkdqI;;*-gvk@=(eFa;eqY?wdS9bHSG}Q%eGcae|clj8TNMu z>m3u9x8{WAK0=P{1+RTS_1ww-iO5%Jx5$Eey4&lupbx3Nb!Mjrf^A%g+t^u+F;7Ck ze@YJgYsl3{u3|xp+TM@Fhq0g%f^YuM|qcg#+eFB5EZ9U!981=tvZi&&8xOO;ISXUB62H zm`s!N^kT{>KZ3H4+|=cY<2achHr&FK1c}s-T@NHOcZ7UV{4XMZ zRU0P5se(#xId*d@$ZEImqs9ca0qOtAKgMKznzWh%paMu0a7Hp!elVV7 z;r5&ha6P&9$Uf!*a4%@T5`9L>6V@}3(KJziq7B}`g=6iljR)I(`opPO9Lzr0SPpv{m`3j2;w+ zg|H*#!tT~a=K?J}AdivT988$j0C2f$_s^&pr6M&{EXU+Lx!rf9a)JFaJoMli*(A?& z9Gr5&puKgrLH{AREYD3WowhN$2;~ugLM)O;zK%RA@VKd<`D@6F0*_B2rvOnGanyx) zdhcRuqciFZHX&@j(OT~h2GC&BVldC2>_4zgPLlfqzn*_(YyHvA`q`oWt#C@Kf40uQ zuTP#G_I=Pt>3*J?NfC&YB(I3bbAnGaUTBgu*&<&Ve2G%;^dNab@Bv{j^^*~KqV|<% z2K}9Fc-HM{c6 z2^J8AAe)r@K1-geonrV$6ru2@>r!~yV+p~^A_AHHH1A!s3}o>@#IS=o9?ur*H3 zF%nX@nry_$)=MF5Jt;m*5A(5g#tg&p;9+ZVTvcqnz3?yFhD*&0UTf3+qUO$QRReI||O&%2q);T)IGT0 z81VDdbEhAT$Y7$67yyG38g_FBJXQ8T(?`H%M@)7F3Mq>Mvo@Hhm)X;gn+-}+rl*XA znJ ze~9raQet%UE4c0uz(WnA*CH)npMqOa{u3ud>F+c{ z*5;#u_nl4lPuDy&k59s|?*AAkfB>n>m;H+t9Gm-8$3arJHG~)VNI{5QVzY21osRj`({3Fj`&n@KU1ZG0azi3GE0n61@-r z0Y&0;;U==D-Rqv&s_(0lhweZAg07zn<1e=hL{6F&!?*2-m- zA^5Jy%>1P=)~`6leoBnY=eP(^FM^|<_rI)L8kS^a3y;qgD<}DSqv7fllzFYxYw)kc zNSCERTY8shb9R=3*eKA2>&R7SI~~YvcQ=PH@pR5^xBqcuWY|x2AMadNwDoU|#xM$= z@Er^pc2#}up=iIZl&-=MOCB}8^6oaY$j#G#njM&M62POjDD*U8SAdJXXdQK7xv+r@DCdWulnSjJe1hDPi74##eElZ+_%cPPscljCEql-6vklKJ445!g~JcZ zCvhnxiKLJMRyZhs`DMWbb_bf~7^oPdQ}%S8aCJb{NM4j3L`B&_3r3eQTp5xpC)Tbc z5$BeFZ#*XLfITGIdiADOCSw!*fq|zKN^us_zht=c;?^>S?!`ujDLd5o8+zI*3Yfh6 zBe}aDw%wf_oBRHQ{@brR3MH2sMtxY3^_B*4kZngv8VvK|t+KTGt<~M~RKaD)4ttaV zIiLwhvsTM`qDrs@MK}!|K|4hvND7ih_?ZS~%P&m$TJrD0&rH!!tRV8mj$Yp!Cbbh} z?OH(5<-aBOheP2hu1o7K&tk=VOKCCR|Ap7!<-qbBndxAM!3(WJjSE7OYV?G*siW=j zfA)N0N&xode6E8oz0)%d2|#7eVZQ|UYD22fgG@q7dC-X(Ei;Uo!+P|?w$YcOt}*R7>wvJ z%!l;i^*w-=Go1v5DaoVI`eAlSd}Wlb`N=mJ6igNCA#Pvj=Bs>Z!@x+djS?~#-D}+q z)>Du->!gx?l-#Mk;nCp`+f#=nT+PL1YZsm_pdxptHe^ zP<(%@`=t64EXOCI*E6_BPcM(_E)oDc9*G zd#ANAKF^5q&z zsDR$;x3=0_4NrAhFje{PlRVXPVc4CE$RQJyAB)IWgn$BQzt#jUDS+{S+iJ9e>#pyJ z$W7MU*7t(uI@v$j-b#XACJ6-Euj0Paa6a!(ht_C2(d-vSUq_0_4tX*Mwbwn{>2)9N z_cvO-_QlSivE4uKH3#PA0?mP!M1oX76L{A4FiGyT6C^29b4RcWqt10GvPmP zbVuF()@>JVd+u{@yLj71cjLCL{^&MpA>9V+uQoedqi3J*4m(G5Nq;4Fd-6RISuTD- z$|P>Atct5Y``9zt)$h1)+tZPQ7^xmP@QmA@dz*1-^7e99_ ztwqZjuVSCrxGDL?qT zYGkRzgV(R%4=-${0AZGlL0Dt_?xIK8l)u$d;!#w|Gj*Fb<)0z->V}{YIRfPm;K@L& z`YLi|bI+Am)~>8kUvs##xd~$cAuk0x4#<{A%Y%&I`cn@^bE~3&N*CHSCL^+dP=-mVa`)G z+z%rI=xpBOozcn8h0&2k$7yWP5KBDK_=Il8lR)YMu`tQT@X2- zz$-}JLRco8r~f$?K>^>E*zS(QDa{C32%{5snkzqe7lT~os zb-Zg#PHg-{&FAXcu#piVm;yE*m6K9w0`M8gwtGr3<1v99zgu)}!sM2MphZ$@I8ja{ zSTIg$mZRRH;7hS_ISvvkLd76#Mxx2A4rvmRZ;i;mE-p>PH73Z)V_sx(%>45;Us%XS z=zxiRr?{*;MQ3rN8sAD>W!O@@K{D3+jrH5J$kxvgvw3oCt;RH^g&#j2ku8MwpnC#m>Ru*j;gCvRQuOpy$wi?}hDp z4gOIPvL%oh7RWcpWV13_>z`TNuI~Y1w74yn2UUXdAT(@Og@#k9^r-I@KUGBym`)Kk zDuJH*>d*jLx%JV*O+Z8XQ&OqaORA-NF^FaQ1TUz{PxY^lt9x!s4M^prhDkw*De|K* z^0z8EATV;WewF;OLMjnVm(J{;I9-}`QDFH%X6gzu-;CpUVS(JxIx}c*bRjDb3+s4+ z%1!kr+`Tg#^*4{F|K-_Bs|Qw)+ReEmb98P=Iuc^ymuDOHqkd`{rb9QTe{0d=Q9VtIu@KXTF{I-9-FP_{SR=fftg=Uu(gqVp1TS)f`gzq6 zfYiLt{n_)wDDh=zjT;=pdjqfzxQLmV9G` zLdj0z<&sWBpj8m*RTZW~@jzaW^E}9NAsMk-v2)S4hyPllo)do%pe1+^+3GVcV}B?9 zAnYX0+Zc7EmqCFC?3H+q?})`NoSaHXTPh|PQ@b=GR6i#NfKCM^x!}WOqg1dP2s7X( z@u1e*r;(~IqIV{7u4%T4!ID)zkYX;xUneh*Nq>qc$e~_Ft*S%39|;id#?0DD&_NCf zENmsBS5>1QGcY8Y2%uwBB~6^lN3mv!I{tU9VszxAS(Qsiu}8EbVa39@yFzo4>M^z; zZ>g9YL;y$YaHR0a-dxXCj<>v_K4R*dh z4;awIOV+OEM&p@n2te>Y50MQlRCpR%l0NALSivRf>A|Wf%~3iEbJWwyxsXN>=$w5H zVtE?{t}Ste$(5r8m!vl{1!!38htWi98Kqk*K!GLc0{q2-pKnq^>}+kcHrvCq(8T0! z(MYM6Z8=oE8un#9);0F|Wj*%B5#nq6SP?9ikMBCFE+^3Tk*+rqa&XM1qB#=GV{)&O zIJ$Zs6Ia*;9?LGSa`V_qAdjU01@eplKa|JB=bH=D>DvGY&9)^gl<^28?$VhQIs4P- z^8m4)Y5c%`EhE7KTR)Z@92*I}UGvURSQR1xGoZjO5Z@LT(7zG+rN9{qOXds(H;t~M z*vTMY+}YU}GpT6`OXe^Dd!I;wD)-Q73QLV*(-cxvhfPyRfzszuq}F zHPhEN=PFEYegYbO3msZuy{Me4Fy%-8QE!(TpE_f`q@1i!(bNB2;Dm+DWs6N%fM145 zF`h;)2T~4<@wl5d&vxY8Vcj()d-xHiFSUm(h8VghH=JB4bKT=xPBz zHd_BYN}l8)!UkfdV=>uxQa59*;Nk#%dM0U+TPNt$)PJ^Qx?ahWLR30|^TmI-WR=f2%vnUgE!qdeUw?;6{N6q}! zM3k5jz$KzRHx$?B7CeK$$tGC{Jxm$ho-aiTv*9}AFJTHnzxPiT#~?$ZuUbGh=_1v5(E-wHVz^hoP2H2TS%)ZQ&!FTc~-ip7gWvq7oMUM z3(-f*eG+CZmC(q7Y-=vnte;g>HS51So@&;=$*Y?65BpTJ{#olQI{jvWL0n!rRI`3` zs*$OPcdKUomjDr{YBoMciAh~`AGu-_0L(E7gRH17zSF_4%Mt5o^ox7YSw>^p`wtK7X%P!U%!krZB|V#SeM?v!Nr1{ z$!(j5RbZkVG#p#4KkRrV{j8Q`2~a}P&>1s_&cU<#e7RdQ9qr3dgBS|CM0RNDZ@|#{ zptoD=_BwS~m(zneSwX)bR7?RV7hsy@8gSyMyWNAB4%Hiy5<|l6bTnGn*0s+(V`;%LjL0qI1xzOg7u_>!H;1;Gn-zpQrx}q@MJF>{2VoBSvll zH8z|!79HOkjzMMgyNanovN_}vP$Lp_FvT96TO5ncK%6ryI+pRcyi36*Fsg<;CkUJq z?F-#as1%kB&xW^#=~K%dD)RnNu1}AwUzz@p6hVAa5G;ui%r>BtGM*iTs?)uGe*l}C z>U-~_KS9_s2@~1{7%oML|JJacA?$Fvt}0Dw6a!PwW0c8*5NP2I`56qC4k;5g=R`R)gdZskwvR0=2*<0#g`ufr6TUIbdZh0slv}wfG3h7U(V~abO&r~wBe3xOnxFFvcN{KgUN{jT6<#_ z{^#i`8ehZ(JuwW;4bw)fU}*lnE|k?4(WJ{sQJhRr$U|fd8fiNh)Yec;?0+T>jKn`3aM@-Pd<_ut;@zA$frYd-4C z$ij}1_yR_!W#@sil>Zu49mj&S6aTyWQ7@cFLjhlrbsk1?1uG>%l+EIQ$@$*Eyr$7 zH?7ug-xtlz&58e0&)_y2ZL!c=PC5j@>nNNwfXS31+@3RNt|!+X*;kMELWG(BUt*FB z$*t&}jf5zUfc=03`hPRhsJSAHD_M&ZTOW9~O& z#O$EoMbr7Nh<+Cv0rV^3N9i}cd^xg}_@uUcm>UnmSc&2yHg_tB{&k_&RBE1^ zjs+H>r?ggbC-HfE8Y!oOjr*wNnI$-CC==YPfnm7EY|;-s*=mJg>8!BFGk{90`84!8 zJh3ol66;NILG-6(kW>J%?xes=XAG!{$Jt3!FxX=He5f5PUr@MM#U4>$aRQX6cpstp zTRfxRf~{czbIzCwvxdd5Q?H=}n}o+z3H zE2qohQEOid1(ATnEhr3B`Ft@R0F)&66k6j0*Grkk*6f!TJ(N3)I;{ z9%KxSY!m`>qAoi66I0Crz5Wayk?F?WsCePagy(GJ z1{QUo07<-{9>Gh>v|)?)g=6iljR#>EOKZ`KD@}sB-ES5$p*O-qFmNMy#~S=A zaff>nCsaXBu&{v$&i&Hs77Qb(x&VheQ=bq3#K=`UJ0yhS=YH)A-9Z#LeMb)NPh$}9 zglRnxj;A8wzu3k7JbdEiehqq*qUH7TaXo3)ctoa?`^ESBxt{|S%H^1paB=@)!@~XW zm!aG*VJXII4(?|+@^L>$49flNJJef+$Rnu04-0s0!d^m&GlzTCxDc3p2bQG~G<99f zJb6v1B@I^uNyUsHUrL*Q^nyA(JjV{#3A5z1>rj!v?u91&p$4)@xvac63C^$c>sSqB zEHoBot!r=wMhUdv7Hx28nn!wE1$tp#R=FO>p=A+EeNb%3X%T5=Gp-I}77R53jHeW_-! zFV#e?DS3T`85|eXH;D3P7oC~#G}M22sI%VP9`x7Sy*g1pCr{8OVV-(yr#(FqD~KgA64dpTC-fK<2xRytae!lMZ1H1-1w% zv|^61goHL9h8a=dj+l-V=JByD+VX%RE)2a)n1dlN<9DOz+HO~vRcg76zeoN)BG0pF z+8lMz%UBI$%!w+9@W8584JQKorxq4FhuxNsZ ze5we&<(!W~ND8d6m5(T%Fq^Rn^(Se6W&t`=`M5Ig7*=SG@<~`WPVcnHJ~sK&P)Cwp zB7I4a9kOkvAgW5Rq*2EZ>^({{AYVgn%uJ?!yff$zh0BQMKMZ#fAMy7H%-c2xUr%;( z{4Yki$=dXQ>X*CQ!IXH$G$#4sh}1I}n#mRE{~;nbXYP5bduFrW-Kbxg{!ryoTq%Vy zlj&O`^2F?Y^Lw?kv(zZdb zez7*%JUH5MKAd>yWcSH&7_7Yvivv-};AGBUj@W7AV)#RIP~`ieVgPoXhF=m$hjZ3- z(we7M1Q>eZ-vNM@Ais|m5CLp3Udl+}_o8eR{%OF3!fh}qKI&+orpmgp1;MsK|GW&{ zl}2_dcQaRNhA9ZVdjD`n6`nvyIW^k=i0p;S;l~AFSCRJk4gPV?C5c( z$JY1p^1OTC=ZBY2YlAyytHzQe`s>VnX`DrSY!5KwO1@Xf=P0)AbAJ(BE!;%*w0p3h zu)Ys+_V*uu!CLEu_ujWwtcVaN1a2Qn5Ja?a3M8kUG-Z-YPpX>a__2W`ms-gh$?;$J zk(`D_Dk4yl(>~`Ux%6`eu9QqGPkXQcG8<`Q;b@wVV?hht7YYnWe{C)-NMn9b&FM9c zmp`nFPh7l!H*E_B0|@ghyx8ITFJ~>juz#j8PM=*S%#{ri3NY0(Ve;Da8ntQuIRQ`(k;#L0h}ma8CcIs za*}M0hP_9E!Y{Fep^RphgM}zgkqoFv36s2MMG*BW`hI9PC7p;Hv2qAEIm_%n9eeL>sV=1qBow?+*-s z79@lfG?3t`X?~4d;X)CZ!>guK#7?Mc8oE%PYC|=c(cBw74$}ZZ9)n*>e@b%BY8a5z zD=$lOFj_I2mOQG~&*LeI6EpD@iQ)jzSbSn=Nbe4`nBR$D4V)mOm8pKM`RBw2 zOLB*d0c3w4o`E{Dz5e;m!2hwG?d{G$0TloXE4ODuY3ZgW@`k*zMv)C7o-d2X(9I2T z9NpYNRyQkzZm1u^&<*Fh(VaCQI5Zk2v)_Oq9QhbWcwszCM3D33%MnUSRj8@wRgF2j z5To%TwSVg1b7=g;IM}Y-nG;e@x&J3*pdgbt%xEZ9)m59G zBNSp-G}q89_SPsL-o{pgu!jfR>?|lHr~0sV81V~K-32|Iq}Q@-K_8090}cjzNx!=V z&E}0wCPi8!n1wyu?hiW+_0#=Z=Q@MYgPpqKYY}KdzCB2qr9Q z^E8ZxhX?Jpx6bVJ+5>-GOy(DSngvry*{dWwk~Xsc2?#H9=(xAkjD^aN9ozVDyst(5 zP8f4JLk)Z1>{Yb)&Hkr~-nXJ-$9~_BBW)W@g@GN%tQpF7@I(Cy{_o@#$vun8Fj(ui znqHlrY9-hVf3=i=tryqhr$-@zXum0lj4x@!m&}nrL6*PTzyUK#0JNw9q=~0tzjv;a z%A7SRwNBB$4Te;P-S7f1Ua^;lCXb~#*xcsU(W|CyioMk0bPUw=bi08H21aYS+__!@ zbyd;faqx+|P9AThN%I5G`tq3w5R%^B?!HDJv z4xrm3-B#0lsFHG#I0 zUveo1>Nv^A0&bVhBtaMoW-P4mAp17R+Y*3byF%lXIjkZHXm8M`&H0bTW)*E&TZU1>prRc?GQRzcuH5?qz3$RREp0B!K#m$1}c>0)5E0e{jK%(sI`LDEv3*1JeBL_ zg%~w98W6r;7*z|1bY+jPyFZY*u%`2HROo8B@S?EnnwUs8st6Qc;-*o`ThN;%6|)l& zq0f-*$o051WCv~ZN#9pF3O8vU7*r0x$jN)Un{xeJT*Pf4Fb1pOL%}_6vJ$g4KxVO# zQtdL@_9LMh&m{o5#dA8;i-Iy2_?Op=O3A>UEyt<0wKzq(g)tF+x?NUu>p?`oQ;cgw z4!uMSGaQ-hHHal0da^7;SP>Gg(eWnO&{H5XSaU4Q%zQaxZDC0+eSQYHvwjD<^qG+W zyE!z{8N+$8vMZsBM*gO74s zY~)uTBhOlnc=HmIrL;Ci7hwt^t+)7Hm+aM69Aiz)k`*1Zr4)>kyXl0k%qHSect?;$ zU_S*OeKU65W>*&DI+#(NV*)QoRIi3^I_TA0L0k$QvZ}>JkG~gUm8>YM#9DmH)M+L% z=CIKWlnW}zTG-FcMIN3>o^j+(BM*ZAfks^Mh@3Qdv-^ep2HJ}MRTrL_yZV0e#3MJQ z`vfwn9DTx#j2FKzB7MX;n?}|aMC@5yJ;h-b(%;8qtHL{*CQCX!4hV4?_~GtPqkW+} zOsakt!5=lOWSc+-U6pZCZZ^x74?NoYEC~6Uq=O5hcz2)>Gw2=5O71NL#kbFs^A$1y zblpHS>4DRyhn-P);)qqW`KCH6q%wTa;fZu&MYHVwow&`?oea7pMj8$(Ou4CU2UrR#;PFV6nzsqlzli zXu1SEvbYO$(ezNj$6`C-5QoJ#ja-aw@gZ*0Lf&08EkWY2_@;4Z%;KBISs@nRG|r{( zA}FMk#W#&hRd4Z44~i-+zG*t zEWT-+sZ;(g(7~cdv%foI3CdWG!{VC;nwa_TxA>-Uw4e&i;+w{qI#oC})|b2@`Gz0a6I*|H6aoe-XhdqZy)9M!IrB-30iNR+p3iaV2b> zo*5|X*PqI8XfkusVy14ycsrRfPE2NyZ_ujkY3Na=U#O%}rmb*oz(%@$_~@X!b+$!Q zqpi*M@N7N4Wp3dK<1qQA;gIdJ z$yWhL8HHk+eB~`!!;o;AwYvag@@kR zhq8#tSN-j{w7^ZiUAU3Qg& z778)>rf~uGAcn~|jZ-9;+~kv1zR%3ljYBeYl-;t>wFt%W$hJPg@je)lq#nFTVB0l4 zPCJxkMQE$25m2XHIwb?@&fy&VU|DKRLv-bbb7)XF3ahnGsa5XfI!K|Y6c7KW=ZHR1 z{DWym2sY0zBQDw^U1!l+vJWwF%-zt-rgJkm1nJVyPrkg;qpt0@AW4 z!E-2R4+SV>7%kX>vd5=0d!7E_qA|{jd@NujRWrRj5L4jw@s%H-6e0h1s8H&Rx*AqE z<|Jp5--&ZO1EAUSWUHBup`D?ibFwR;Fo`Pq1Fw$u84V~>mwZT_hUt@u9A&~RC{m|! z6={WeBcFM!lb3kY1MKr@9nwf*wuS$by~L`9f^Wn?})(8VLTB|jjE=vSKpAo zj=n0M=s&32nb{E$id)gdy}z3sc0O{eRL|X~-Rz|-#F)G}B2PgrAKJ}MZBm}=13@G^ zF)<*@^nI?_3VF##T(3u4`QTn4v@Hham_r6}g zKR5y9iuflPxXCWT5YX8!N?b5=7@FDhed*;$MJGb?y)NsSHNe71QKPrLM4zgSJTp=V zDNql)-!!`0SIhtJ>hm-l;ZRDv`foJ}gHs8>iS)YTBJl@ehr?qu zUQ>(P_zMTHDd{+5D3i91Z{X-!anLWvd%4$@W~YllQ>U;-{-Z0lA>6@(Dk2cVo z4NR-xOt$O2@T@EXW6E&ZA>C>iQM_2cTKi)_)Zn21ISrFcINj*}o_Md>`yMbQOPZ_r z!`2p_Dooj1j@_J^vbEdy(L@rh1IyKdm6?*&EHEW&)r+@-N*pwEWw5uATQg;_nLiR3 zoQoSXES$+LZ=4!4k%Pi>vYHT@8E-&?K{=UNj+%%~el&zt4=Gml;3eQ?%xF!>E)_xd zussDYR_5~Wknk{`D2q218*1pAE*HY%-?cIXy;Ojp{es}ocm)05d<4DB3EDfbP(_mp zlk^ghv}VF&9ZW@&V-i03$q%ACfyCK}}#y5d+VoE0gci{S174 z<-1+%Lqnp6dG&vZS^r*O6$0^TgBh*=4wv;!uM00+gMT|*83TU~tCRs>;);J6k!PTf z2g*|$p$m3ZcBvYk5D_$dD0!Nu0L(AcmZo?iu;s}AMk88?i*`DXcN)X~>Ctv?XXxJ*6tV&tfWe}D@`0ep-?{=B;>~mg@+2?m zzsq;xi;kOW(eXs@Ba?s3zuQP7?))_ag>x?0rm|c*Zu5;G<9}xnF%`Mpt$(tbM z;kl@ge;O))gs@yZfG;v`Vn|Tb@~Ij+k|~?Nne_gvoMs4DD#=jewTyz8@UAIM;Z%I+ z*b3~|@&b!xW|z|>qSpgv6hO%kj|Wm40!T1`P8TK7(I03Yv=$x<`7aT95M>20IK<*O zzL_ca7o0@a#8P>qNIdb;~xIL-&|hBwsV<(Wp4d~9#Zn`@RyfmKlq?`1c?j2dke)v z709vh8)c-ETo5e$!6%9ET>aSf5T2VmLc~VJFPigbFDXdI0V^<|TVzcC_>aMUr^Lp+zg zRlpkAb+!t8OGFk6UIBc&)cLtllbCXSpX)d!G&6xb@@)}$ZumXS$`nYpuFFZSV^?s1 z`}h2@ZbI?Hix-|Ec>LyLH_B=f@&&=@89v8@`4Khl$Gnv0aM?;+3f$!rHFB^dg6jKD z0b{}d0#>`76ea#-JQ7L9MB(DNU(lp8y^VIy$kr9gT19<5pmTV{P;gm|ni#4<6=_`< zhqid7!vvWR_FNn-Nn7GB(_p_>PvBaUW57SCk;A2tlwrZ*!oM^VhzCl>f8p`JLOSSS zOk!tKD>sk9xa3uF5iu{Fl;Z(i6lFzrQl8Yt+j{hOg&Y7#@bYX}X%#7t1TdStS{_r zy>O&SRUIz*^N1{k%WfI$Q?FdaW}>)Eic9#Cv3^M)bkYf%l&1{4&hX%pRa~@| z3zU;A`Ll70<0(`~-?|HdR=5T&ATUzOEnHTz43acg-lPjq5p-K9Ui$a0piC*Gp~U4q zNC|ltj}AoWoV+3;cn7Eqs5I{1g5f%&2Rnn!ol$$#?Qhj@$o-YEYjB;fQ*DNXVrm4& zpgqf>lG@Slty3En_D$mHntZ-N)z`nK(SYxraACJf;3Z*Fq z$4_`Yq^%Azs(g@SprxWaCZCH*ud*9MBv0!KIjsfuCXE|ToP2FiwJ#z_2#;k$>&$j# zC{IgCM6l4Vr>N;tY-P|cz#u~#cnC8_rZ!Uea&18J} zl#*WMCl(qT|El>ay$F41e04HF*dV(@?UlcO>2dL|#g|4+!8f6_z_MKQhYFD-sG&Ol zPnUf#D84$v=MpGjF_4kM5N<(;11Ob}VSp9aP$H*FzQJK8I}(!ki4iojr@1&IK`8Qr znL+?^fjkFQik1tgM9A1V(V{0y+}lqskZk-X*OpoX=uBe6Tf*B+aIeSsV%p5Rel{tH z`+}b@mXAQvhS_{XU?LH5NGG6*WhfYz6~Gxos(w9|Urf!jDn-H)xq`@TlfFd+vUW zY@eB(PgPruKqCmgkfL+3(>T%H>TW{1>&o;8M@NY9XrZ6;yUCEH$7LtIV(R0wQ7X{Y zUY~!EO3)y%)aeipqyx0s>}U3yx^6s+O61^78x&MDUBn4?TRw0!|Hpv zg#{Bs@VgnW1R0w`xOIH5x`v!x$j1;l#Gsy#lurR$dG16l4|)piQa48zVBK4vd%iC3 z@$RknxSDXpk?A-Bya-ugAPEIP03B0)XQg_r(Z%f!+hdC3Z9nM{_cb=U?K2HorDh>1 z9WQu(ATIQ@MjcBGiZ(e-^iIC>Af?Zd7F4*dnnBaV7`@tuvcNg%4} z3x|G|K8qvcFAq0xsaV06-?$0J#r3*pw(9%pf^f>OrY9_88f z>lN2N2rvWZI{IALYdTC9`L)2fxXG$MWdN?o(V?`wa76-B|a%azTQ!f#6ddN-rAsi(rT)%2|-sbqrp(+ zD0X*>o>jmz2-q<5%-{ zSsNWJu_Je(?pfNJ*w|$A8Cud}Q1u)QRwI$x&3G0X61Bn6w3rr^{HrnUq}P~uU!<9g z4SqQO!4OnMCGT~WRM7#N5S)W{QSkl)fEWi~!S{zC34Rr(cLF9SOwMXZ+uiXJEQUk} z_QaLFd~+p<*1(C6$q%~XYxL_5n#&mO(rRIX$2ve1^Zt#_)~GwWcv8Jhrs)l<6R*z^ z*X{=Gjx++zGHJ%{2AKCyZe~_YoVy$N!PZhotk4k;`Dsu%0+ZUO0HhLQ;RNz)$daBv@1v~<0k)Iaa2bZWxs{E+`cCy6*_i-c`jv71u8S5(=!M{v>rt%~)vb`mu zgX!?Gi~Qi!!Byp#K4@sKLJ%2=rw*N3^$EWq0D=G(Vwb6u zmlU25lrqpA8!8-R-Og439Hld0J7SM_db`Ctrk<0Z3~bK0dXz-ZKT^R5m>R zaYSAn?G{mH-*5{19Y5n(K3_eJGJs_|#K^*w<3q}e-n!7z|BT0fN>mgW3z`s*SYfU5AL`zu;r^$IVzw8)qiA}Uzn%qRo@5>K} zV-qc5%M_bvd9U^cMM54Svn&A&EEgaxZd!|%9gawY8cTeZe$v3}p$vVGs37ucLgds&@4a%XjPelDPcp~r|y%8Nz>ApWZKeN;8 ztdAaU>bpk~%n+zT!*gu(E{o}9f;~w~BuAh>d}QHoB75;x(&>vcW4k50pj#;Ugss9; zgf?;%F3@LQ749yNgw{3T#sBjKEMisHViB3xtTzIio@$T4(x~-{BZ(bL=(5wG{Snwz z`&QU;5!e(855G!S#kI?A&;1TxjB}N)s^kL1@`}EM`BE^C3NT{2jME)|1klA~8Q%xt z?w)uV@^la{lVawU+~$)j$ovsn`I?Kz>P87{bajWdRvQHauMF^Dx(E%5DL{>&8hP9? zQjRil(@yk_Aq-;AMY$pezZ+{9qIwLumX|rEX}Qm)%+F6ZzP3ic)(pEL&kCo%GAawY zJX|w4YfhnKPwt9F4DtonI06SIFwuigj&gh%JSmhwGR(B?@= zHL0M@1BKe5E^#QO4Cy->6*wwWvDg^WV39zf!Ol!d=xB4u7xI{+N6&KLBqYdB`DA~y zsO)EN;b_>g0wR%~8RmnT@37Irov&e30|;Uc#q%_73U*0V4&G-wXhlb!3M1k&N15Gc znxofi7pHhzQFzLjoG#G~3KG}v+NsJM)o1gjG~UvnEONH9D1aYsO($b|0e^N45{K!b zeM;3il#}?s>XLEkIl}(KAAr8AG_V|U&Vj43Q|~|Lk^=nT0v4bI-I01vKSSlFqG`jd z3pU8fZ@7ekybKivpd}onVZOvF8a(A+X{FlyXewh$qXHGN>7We4nZ4#m3ziJZUTX+& zz@C1JZ|+goEcqf>m~&a^NJOqXBAdDnMHlxhPcF;}`*v^2#Fto@6ZT-RFz4NxXb#sY zAwf<60ySKOt4F@c9^{0resp2aBrfN_1I!i2LY&Jg#97Tsj4XLee-LiP9*-z)@o11ZM7#E>aV?&= zxGWxi&I#e;T3*s|Nkg$oT!z~K-dG&anXtv&j_C?@(><{`G=8wW-J54P*x%~1$?Yf>%C>8?-%7_R{>k&tvt%_c|FyFrBzNy4k$1uTkG zOPWfsyTnb8Q2Bzf6!hr%eADId&=CZ%@MM>iiKe)Il4b>|k3i}j?yOK##LC_cF zgKVz@uKT0<)qB-oIr2xYX;(^&ay8K4|B^kD1*CiOWUG1+($Q$wWZjIx_M+Jdnb{ur z`w?lP!5;)Xpgqy;ss~R;gPqPs_Z*lK1;AE39{M6CI20AOaSr6H-#A-Q5gOa3ul;%$ z#+5IO2&_;KU_=NMq|fQ4Uhz4vQKm)7P1TKCk^3R{;{D!Lo8byx1%$@K^>ZX&mwX@y zLn{hHxOtWl9Dc)fRbC^Lad}#L!nGo-NvW?;eum=1N?Vr zeKagbw_?~&;36w1tF|{b?4Guk`M2jgX;!;fzO(E_CY6V$x23lxfA11rC`K^*s~mEZ zQolB4{{3YRp-thoW{BO=uE3~Kh}z>EksiEE#u1BJw4ukX)Ufrg1FW6Cde zcwY3}Q~;aVZd|5fJz-YnB9Ms2jU4TCB@Mm!cIaH~3pqHLICKl32qvK58rJhcu7{&NZl)!F`C+y*^}Vy5}a3 z_V0EL{Sn8e8*lFEo^#CF5+4S;7gtv)-oh~QIKhV@Nw!)wrR1cHT&TLjpFMK(L>CwgrlS4KT$Jtu9*J&*^!1fw-w|h!6+i^y9@}XTI%P}6AiId8>Qwh}_+nhv z#S6>iiq?9sJsj2-$kXdz(d(}txeN6TQ?+o=Faxl(K7j!%?kPjizju_4YPwz1sw^~+ zxBVO`8xEv+hgwOHFggDb7Zh-BK=0oBs8Bu8-$*?0`hh@hF(z>2dt92&x9Y?^>K(&`t1HOo%q$HRwV^B-gknfGi9jLsb1E7I+Si^{T8VmkP zUNPj6$sfAJGrwOtQ{AgP4kclbDq)eIr(TY?F~)dj>_~p!b8)M^*jNXZ*`2D75@LRUdR znN$~X7Cg(;-&!9Y`)civAvW5H9E+#Oq_}+1DFM~q*WL2C3jnGyyS-c5=WAAfli3kB$j3(Q&@{0Oc z>M39_2F}vVzG)p!Eu7@GNAO2uemmYUaF_1cp`%n_7?#85JV6tZu-F{_o!GPbUPu(S zJh2Nph#B{O*-cjYP4G|g5P-u}-~ff+>5VRDi@(*PXrfN;#2-sjp`gXlO$~u>=Eu}Q z{LNg`lm$fLlr3~O`2p|i9rD%w8%Xj!;z9L@!DhqH=UZAJXmPT&nhqBU%D*L((Io2n z(gO7{h%1UGrQ0Dh@@Y6WE=SBB?h{dY^8W-GzK4|Io9!Lqh<1eUvJfZ)nF)(=u*BrU z@@~dDp?fMc)_KT*tSlgO-4+td^w|k?q__344yIgz?`2WS)v#TCtjkJoxYOl%Oi2T< z7Y8?-WsRArCuU*{S(z>R2f= zkHcKoF3e0nIyf`LidlkD=twN8qce%caxKIka;0w7Swk|F-%~v8TBC|mWdYC5|fFKI>cr~-iH`Whf;&7WI)4b zHXWjZkef}R9*-2A!1i5Ql z!G546g^WlmZ%L(a1XxlM;_)`LK#NcacEc>GLsnr7soVbP(ROcV*t+|Hlc&}mdePl$ z_ukVwy4D)?w_Cl=xlXTfx<5GI9&D)LK_y}dpA3=8fHu)>RsinAZ&D$ofQ`lT3>Q=^ z=xpp1;#tl*z6vDl?| zmGnPT47x(LmWGsFh4F{N*xPM%9deWw>&(QdKr^~RbteHSxEliO&WU&u)Yu( zG=cWZAp1*7pFDhw@XN(*)j!7$%=xIO5$U)<|Fu$??HgExK_OaK&_WhXjbZ=V7P zB@1*4;AF2Fb|a|a$7TXTBm1fDnazH8V^?klRRie4kQLvAz!mF+z!h{tpf-X4*W?j_ z35vEoC~3(_SXh-s2VuYj4qVvF{X-ONt7MiOzcP|MaiB3`!}D6}{mx*$3pCz1*Y53f zXocaZdydlmsB^ME*ra|*`%Gil-h`%`#`>e}?pCXRx;1>XdwRrvSZ_mL&SrabuCw0i zb+AOXlTdW~xmp=vehIN1KM{CfH#0rrP< zhAXi@Lcmu^D#9@f6x($(O-^^u*tojU*RjVPgiW(wX^1g&2l2)Ah4G}3M zT!u*CU7$@dYk{-sxx;CG5l;x1WmtIh()b+Q*d4!W9*|T;f1oMInlA!G&iiu&X28er zkZR0Bif`Xryj*MGkJ|EsRf-YG9O`1qWz0n6Ph3^(sgq=%#Dpan@i!J<$2Bni#>VF$ z(cR3=wYrVmnwe{r`J;ID8g2jZpA?o_Je=Got>wjrxMjHis7kav4H_><^0qw`+DuhT?H1nw(beQY3=( zcM(ihnB|wD#vXqgHIVZ_10rUvlC^9foreLhGYYZQ>cA|`+2*KZ*2zlnOS$%kkJn(H z%ZyTyG>Gv{q-K^eA7x7}Efx`P89QqIw1Fi#l}mnPes;xR+Fz$s`YaP(GTTyV>_`aD!~pmq(UtIi+2@l2I6kyOCJ=ph!I%QQsnYXbYBhHxF&OP$myu z981=sIr66PJaqn2mOON5VO;*p`1FI|#I)rLiWSCLzMx2A+VblnF&z?yW?WcFTG|u8 zQd{T~;s=<^5mW}>5VcLNm^}5rI{(*`g{) zLbqTh49!JP@}gmxXqY{PmBhiMJW&!?{k>dy=!3pI^g(ML`XHKz)>@rhZwKR;vTp}L zIr?@`Ko%6>W-`H*g?0tJwBQPiY3YVl=4*S2qhy3wngMEpp;{iil zE;FV~E;}X?O1fM`_>J@AH!d5(2A#zf*UY-}sTfKsm3T5M9vm(Br9GDsRmjA`Wku-8 zWv-7(=0t=vjL8T0Tt)^{E}L@s&@!z7yUdIXNrahVlVJIK9<5GFiwH~)L#>24kZ%8l z0!-ZPb9fm$Xz`J8url4RyMM%+gpPMcCp#BL3iKlN95C_=TZAXhEo8J}MN#6*xMPMD z85y5aGn>j8SRaYeonrDFF<55y6FTS;bpea@nZ}moP!H^Ttek|z)&+{2Qn?dECu3({ zfdrn4dhRqLK>aWX0Hr@A*?_@ikBs04&Nx8#_8sL*e34Y&KlPS{F- zWep)g-x|Kf;oD+zd^`vwEc)^QzbHs1jX0&0F$)C71DI3{c@?!nppR~2gNWudMwWaK z?~OiSuT;j$4RzCKoh^!JEu-s!QfS8OUHMc*o{W->^hFCWe}YZKMo^&_mlR*%lW7o% z^zIQlyBk-lsmN?Csj3erBD~KaWpA-Tyf5<@&#QuFxfO`%h{fzY$smiGoby;J>FLUX z)(eDzJX*^^=VUKOye9N&F~)J5Mky2?AWrqUs_J|1U(OpjLx>++=;o#G>Mt&>evis_{e;DEV7mN?y>o z?-^72NU&|}h>CA50{OZ$wR)Ap76AEim$(%Ky{zPq2N3~JF)k4gy+jO)jJdYgi6z~h zysVHFPQo?vT@m>*oCIKdvM4&ruMMp&EXm!;&mec!?{Mu-78KhwDh08=Ji12#x4J+m zyo|na_M4ZY+ayaMRdXJ zfrf$+leJ0!=C>u6!3X*7*x@`HyLq!Kkv+tj;F1y~s#ild9rQ}kL=oZJYFty;Duo-^ zdxSeW!YYB0hr*)5gT)!k+~LC-C|`JPZlcLE$uo}JX~fO&KM3$M9UN5M;UYsCylZ`P zFLD4X{I9C6^voP+`^giJ+(f5_!v8Y?Zrugi_F7)c!t&DN9K)R#x3q~G;bvD9W}U*s zDM1H*Of7pcrCEq(DC%iByxl;q%S^Q)(D{PPA!Z4{Mo4ZFBzHW5%3O^WP=SQaK$|l+ zeG(XVj7totq7ntby0y%QI6>;f3rsn>qANY!mr6H!2C<7HxX9pJC`9tYK_Np2vofMK zV~ctw@4jxY)U<=h8B){^Ri3)eYSgwb$!gA!B0pFX<#8>vf;sB=!)Z`B#Ig3NakKIt zb!n6I91&9VOORDZw9tX4vD4xoaHYlh!KoMwk%tm&hxwU)h7Dv25q?S(7=ja4y5Lyl zXULgM_y>j7UtK746#|=ayrihYl=%7bqUdC<0}cKeE1OIp0tsO>+|J=g3nT?aAo;Jb z7;RBL%-A(SPeR87;rAB`M-L^=BCp>T!cSFA_sM!HXAWjIKT`l(D(QWETBk7 z?xT^#QhGNgZ^k#gfa400MXKp}2&sfCwX%?RyW_CfB1{U!Ei~#@!M%=dYyflKuH_1t z1!9RVVpBi`jAa5}E7(g4a<9>>4Gsic8-Un*U$5UEoB+=l|0Dw!on$IuNG-=wF;Wy5 z5)fq+E(O#hrF#nZ9=l?1tsa+)D6W_kf<`OJ_quEn7QKS1pW&!I7zr9S!k|b1&O)=L z0;4No_Zv6TXydWKNF%HTz(r1qKM`xhvr7h|y;SNDx8jR<#1Ri3#)hCRBbH#+9=QYc zercEq2!~0%LWEQ1Di&&sXn_STvH0}@qmHXd7@S^NwlI;n;|lqK*kOhlK`;=G*BF1{ zhz6vjHK!_ezTjxcID_*=E9Is*lil}g7hM8#G^2X^ljSGR`uW|;AKJ_NfARddxBtaJ+AJ#{5vE(j3;VFwJN~T z|P(pLHCg-Ln|NLovWWF1U3-eSz;5&6jw zl0Ft5PEENnT8mtyz@xWn=Nu0*xq_QeCCxN+q-I6od%3d{&< zV&)pnw%|O@6F|V@?1$veM^F>k(97sby-cbHz0|v1>_g*Z=@!`%9VcF3!xg^}nlS6o zVSUrl~V#TQ^ z#Fme9)$i{Q5&~Kb+>h?V=(1!{J+i1Rsxc)&FwL}(MV>+)==N#x^_sBQ?rVv4~r zO)7)+>e=-{Y*N{w+@vzV+haSO&f}d4ukQq46hR{aB-`poI;9M9%I1`^@h|DW3rqsT zCX|6$nx9Zs#hqY^8@kc*kZ(HKA?tLqL+Es}Lzr5UxFavK4kk-W0PxB*rSS0uodKtR zsz%NS%JRl(NbExcqin{!`+<|E)*gD%-D~&W(>l7=8uhnZz0SE#PcF{P{6gBdDRe_l zGlVOZWQZ$>%%QC@Z>cGqiVx)qtgzlvl=bUTPUu3?;w05t^YjNtKqhs87t^esBQV8H z5=VKVB-BNDGx`JHb{4EZJ{yq-Q99LVk~awF{(>73Ym#t81~Ys975qDgiY zb&AY|Ysi&pM=nj5hTD8#_cKd|{gyNUUl%(%Mr?q=3&^(ViQ_0KVc58vsP~68j!R-8 zuaC&H!=GN3Q{Zhk2ogOTw)U$VfeJYmek06)6&@j?$QPa@f_n91*F#Wm?g;s!_@9|# zA>TaieVC{b_sM5XGtooj!sKUSa;Pj?a>}6ClP42+k1@Z4i)$b48!m>TsBer&BOGQFsb#q;rB2$rOTM0mKGo!&WS*OVXhfmYY!guxQ7^Qv@&HeC)gHe1sL4uY@F(K*E>m3;!nmS5p<4u=(~>l1x@e^t{*-+=x&{D zwJ&ssu#kRu7WTi+(M%_slrH`zT6hAvrqk4m1FYBLbh1yVXMSXF>Do9zQK-C zCIkHHxR8;nD$^(L)fSK%))&?@{7A;m^VsCiBeE2(;A9jbzoiQ+OTF5v~=W|O1A zVH+5ZwuJ(jag4_f+y%Hrv?S)SIJ_JtCU38i?aCm?aq@1(W|N9v4IHFvTm7BU_Rgp^ zq^Y%G{Tg!hk*ipTLT&Ho=MhRI1AmTAI$@LYlwtA&9$d1Di`H_1f|8~`A16bpTHzYBfWSy8w{T&}GDy!0h5SjM_E<)jIl2ku8F`qMCX8_Zp)c|*OGllXbpSJ|4CjoU!@m8 z1JaP!U~%c{9zqyUyF=}jzyG4g;(xccyTOQ2zjnS#!AyyO3g+FShU)x3UD_R4tehU$ z&_9`p5c)axP|3&Q5C>2yCA(rR+9DIfj%nOXwxj_?zRjKl6gj{z7D&8ZAkRUSqU8e0 zw6LfAf^CY36g^quKF}bDz#>cAc&|BjwM>;p5&0+A%rFD!Ok%@Z#M?{?J!eu7_XR&+ zEFTf&5{7eQBn+|2j({kO9QHUVCJUxCkxde8W+$KmG!D)<9^Wx2O&qNl%+BLw68(=C zzJ%m8I|d5KmsivreX(1P<{}|b*u%*Tty}Yi#}g5o~tNHPg_Co@jac3um`2P z)!l@2*OloHj`nr~Q=y*|Y8ZEuAxn?TPI|@E$3NHZ?a;pV`uu}Xq2rjlq=7|GryfG& zszFg#g!VKVNuWg(FzE&F?$mC@KA#rD82Sm3gO+yrIr7)8D5E;8zL#5AFf#phuxN`yT8iS>iDIqsk8G1WQOkp#Li^Os;RV>JzRx{hk7S@dALKo*HXLze zI*vhj; z)%VrOL-!wl!CLEu_ujYWs|X-4)V4s?BFE*Ltgv)e>+9)`yC3cMI>WOUJr6)RP=REW z@6Y)_p+ZYm?USEyc5AjrdTqY-qPWD88ULpDO2$?)y2vatYwX#gG6^s_?Jz4SYFgXS zxj6v|bkRp4BF@(p|xUejT^$gc&)#SKvPDFg5Y zgs~ioMm^|D97*s^+A_S@xF9f#s1vl!`p--?O}k=o9Pz_=e=_cNiz_)=fhCqCkPZvQ zt#Toj-=beP0fPRt%M=mk)UV@2b*eMEhid~IUnx!DAK<8RC<}3F<19u&p&4oN^^STZ z4wC5HYc*9@oS>`VZWT1;wo~-{$#kuJu|PL_GuNhqQ@MDV1ka4)SS|WXy!qrx67hMT zzBf0zP{@CAku@h#@Z7{^&gY}{f378h!<3-(HTrc2%^~-9X|*uJ{^`+nZ)fOjFNY}R{TrRFQFnClBvu!$ z8glXjKU`}zwL8)XG%F)X^qKf{@Pn)s%zd}Rq>9~ZHu=HUQb(-N5szeQP&fjU+NS`d z5^V&6E^2f?6z&}Gb51}{HKRv70;ej}+4+A5g>(&J{cRpaHNQ?ic@3#sip%DX*8QzWjt=5CA~{i!qWITMRhDx{{RC zdhqah0+NJa@Pn7#RCk5%qYQM%2`|BAg^XJPT$s1~9P#L2?1Vh{g!_LFa`c?AB zDhon+(QVSz-0evlNfItz58>`U{Fu4(L0E$Xn`tR${f?V@MrK+bR&g2Zgyj$GS_DsS ze;+c_@^CuS@?Px?iiA8K>a;f=ZbJh1#l6l0+lh5FCxD?GG9!=bQHwd26S|F{FYH=id*c%<5Bnxq9=1-fJd94TJd9mK zz8#c9XP=1rW$9Suz$gGd#8R6=jS&e{p?OkhOWbu2_9QKl9QiDvAszBtF*1J<%HZhi zz+`5Ow`3QT3#A|40OXav0`+9%iEFG1f0u_s>zeeUB)QtSfW;%m3BjhP+C#83Y`r3R zrO+fa=UP$@k2UI2E(DuG;R%XJSjP*&!m40*v~RU>LWE!~ujnY#pm(fmjUYw$Vrj09E9e}4G35702<%@4zR{T zkcLO=FzJjItKqtg(VQG=TT+@wg!FZ&Z=45OU5cvOnUI%q6__VD_!5lEE` zZJulZ0+bP%&4q1+bjAz?(s$H|b5y1TX~y!5O&PGB9YnN-)d-j54#pYZm1?_7;v_2`eCqz)d#9EGJke;0~2Dsu7uw=V{y&>(Rb1KOulin-i48dy_}%eeF$G1M(kwK?RR16SF(GWL`dCU|a%$j`Z?06(~Z?vq;;L--$jCoNNjiuXX20_ zEm%@pmx4<}4FN^jqV)K*d;sY2&Y%x{RIqo3Yb-1PWTp}D08l#@*kC(N77t7`#+03$ zpPrEhneHy7Rx%-`?4A(`24RY_i+4}!768CbMLgG`gSo;(b@4f%FUP^Wulv)_e1 z&9Ku;#F!>>8N?cpm!x%sNha!cs?+PNj~;H)+w2v8$gM<3v7TfX<#2rFgFF&Kc{Ylm zZ_2+CRpoFU&pIr_P)Zzd`R@Q;fyd>5U3@2;T>|_z@ENE-DD9oN%pZEdifR62J?NEk zaS)gJqn&Cuf7Uu%!~S5SKT=qpnEAsGwdpM5GCi%8E{wv~S#h1lb=`qCo&29|6OmCRGA~WQ!@`?| z)e$-0B#>(yo#*Py8KJ5xmVDWBj(7zlcN3MmyiB1hhe4O_)6TW)KIvx^3I9t}xl6J6 z;a166T=!{^IE0(_sd07RFS{5uJx6Gm5P9VA`yGhFJ^H-osk@~@FVQw&oK^V2Io`qr zl!V*i_ott6`TcIu6p>$Zx%=`C!rc$T{wk`b`1e`KG)%$g!p_=5xP5(owB$jhvT$Et zgFcuK1Th3BK%)B9d)4qS@<*g(2KL%LooX zj#f?Z7oL`zYF$9?v7t0YE$E(W8(!eMyNW7dw!bI?Qc)ZYpfed?zj(u-*k)@t><0 zr>RI>vuUR*7VzTRA!xNPTdUxM6~0Ka&1m$IB^EfEuQq?hu7!n zza3+06doMN$^zm=7Hr*HQ((sjY7%`=De4U~9u)km59T`c*iL)UDQA4f1VZ^Zs!nwu zhc6cL*0u~}nOxCY@3n`+`T}`+{VRI?^&|K^i%oCWiGeA^3+b@yzd+4wCgMk3&fqq+?1v%jj8*G2R(FGEMhf+-h%j*H6J1 zn)OFPN?v39MS?qkDIGe5DHFT?*vLT#5p&c#i8BpLmQ)<{65U|5>HDeEP z<20Ja#u7c*m&S+%`}r!0GXqm;)Ymp?jYb#oc%gA`Ep}b*=C}*HpW!tZpU=RM8Ttwd z{S&Bc4j2u0{}wa_j~;{paXX_n4ZzfI$o*B))NIFq@1*1A#0$BCGckc7jrWdod+Chp z#_Xj4zf_zQE_vEB$JiuRiWwm9IsA;C=j_ z_azq{wzI715cPXZk|9&+ipTv&j)ZLHXj;O@4>tlwcs>p*-G~V6SwDoTe|4-Bo5x|E zT^DA>9vz$+V#Ry7`=P#&1rZ%Noy;f4?ce*bD{H3Cf`*;mJ>7Fuz_1^3%_CftFC{O~ zya@H{B^pi@jrvIQ_gwy{x`V8C#|w|thXt6WNx)%%yK}%2Zt{zvPcvk>V0aq#gCm}( z-~(hh0w3DvSdpUV1>}`YodN4TadSf*ak6u!UW0!miAFlcAWXgG*K-x}JFe8LIy8M> zkQb7o1Mj*U6b{2ga3?DdR8s*}Ur zw#sA3;D)X*P}4gESm9AK^2rdv40sbA9t8kT{8kl03u8BXIGd@2fVPZ#@f!yW6#+I? zN@}J+D-lk4X@GInYy=ornji@lWuFdFA(GIGSy}ATyGr_>DF$63b4x?Y1Yrz)I4K9n z4~Mb0$L?AVu)7q*%@Sk|Vkk&y7BRq@Gy)Z1fFVK%3^1g!CwRj~kO?NmP%#sX2_k2I zjgoW11T)gpK?WIlO+av7L}R>}l;yFb^3Z^RXC_Y2OiDV_)RJg+q|DQp{9?Gr;7t!S z)1epmb$N8rXNw*VztcB3W~ya8ZDD>+HiQQwBcG4@JGmQVX3?7=^}xU$R`@Q$k7T?n z1+H~~dfiNE9PaGI4Mps|_uhMNsHoUj zyW(0A>kR}Z=bdCo5cJ!7pSyqT?gNMS%=|JlNhZmJp5ovaXyO*2PX8ZuYmMpBtUWsS zT#(|EL+&h8bD4MPHMqD6kz>YeMY!Qqa@{CyRxEuTuDmU*vLemRW>qe3-ZyJiuKz{R zxEq4lYgyUIuF+*9y+)S}dyOuQb$Hn0aQa(?L|c(NROa46%}>7OXxcEF)w&dxhS{IV zgBb9b%rEHA8gJ2L-8N!>NZGAE%>K;X{=n?dIhpKH)StNuDeF9}{>;7VlhvPpzOdPi zETp)q?D{iz4xU|q&PCD440Lw=CfokZJ=Y?$=ANx|f3{`!XIo`ttp1$&!dChItZ@#S zO@CHc8tyqJdY8suHg?FIwP(+=;r$Kl83FhlcM{A#$x1&bw6#ueUFp;K`IMhb4U(UD z`!y#~Ve&H}{1@lp#Qoju?hws9>d4u&J$oBx#qn1@*xMLBm)rXv_9>WOQaWMppl&8U zCdH_f~>k`G@G>>vWlT#Lf%&SSaeRo1*fdmt2qlV&y{{d#&2)U z+|3)Zmyt+yG^X8^|B=n_uM~IKBG1hoWoLJPgM<7Ty5OR``EZMdE9er!)ViX2$Y0%) z-eG7iCC0dQ0iH*q7Zpoiy+TPt$QU^^r_>b^$Y0yb+WTfR3NjZ7P(DSQc>yu&Mn^aW z%9k;vp<}9-HO;AcZj${|IysmRi=rD-PqY9Vninl?ce$6s<%6x6u_((MtSz<|a}w z`efe!nZ8ab_npEttjuAHaI^!ns;p^V$w^(wxnI#VuZlUL!!2MTalz>qOz7C<-309# z@!2dtLCf8@pE04+GFK-9il%e8>Ij>UJ)~%-Us{r!p5@-Hm_D78mqpEHWDxd#s@d60 z&T=bLXHDk({(@yYm18G6m18G8m1D=A%CS?n1;>fEV8+yJ=G!rIaO9KCM2^C;aPRDt zp2%^`oX9E9yg-*e?P8zJl80H3A!U?A(W5DZPc@uXtlF8yqPsxG?2|3ySq62{Kmn%%&5NORe4--H|jwnY}spLSJd#tfwp``+#`V%IF#zuUaGDFWUvUU5#`J zvYuy?YHkja&COBrr?o{JE4wor?ew?vNEayUW^t(k*-C!3o#an7UMY~(%vl|R-TbrW zz*%jWyR^%nba{toyknhvu_tvB#%%udpW2E3RB@{(^xVTe(x_Rx07L2>MBG3ji6=G8 zGEV`Lun2yqTD~-z=ilki8W!;miHr!1jPTC*_He`eDy{&kdD<#{QZd8) z>0h1sPH%})nAWiB7t*^fx4@iFP~Q*^BFrz8YY{$mt*s)sJ1@BZ`1(b0tE<*++OAVw z>+~s;j$wT~40Wuv)6Wb%!XktF_(b?+ERw<~Px{}ugh!X7sXl_}3*4J`RL#r~r z$%k7wcyQ)PP7bkPoh^Mstq$7o;061;xtDI~WqowF-F`LNDQgR8w10h-ugXj)OvZi5zhVT5%DlHDqssKRh#Hxa z5^1(I_9()w;HF{C?e8vAXU)}{jBkWYYxI#qFM4BmP>Xtfz58G zY{!xFK?OED{VmyTcKWkqm}9nSjlyZCFWjer#~ozRo1M(^V@B5`0X+ypN?u+=E%=|G1t(gzTftjem^(* z^W%DWWN)kJpWF4YD#^MR>fc71BbAOSDsu~PMMz(Jy?5rGCZj}||DVB=LwngR-!JoU zs^dUzsnh)F|5o$69PXR*`n$N7gcZsd*0^kLUG|@pRw&9E5meE_#!hc->DExH%=&ZM zd0qdZnbps{z%4v_&L16S;FE^vozre6yQ%-kY+~H$1%Ck*k5)4kG7Fd2btio+WAggv z`j~jjx7fHZ_U(-!4WTbFw>-2z+y7Pj`%|O+aW|J?`{PO_8hi74QvieAe}RFUm_-Jz zR5XKa4jEVja#lA{^`wunxEX7*vz0tyx6ye1Q*Lg_lTNpnP1l&Lk)1i}O2<3M#%nx~ zpUqsT%7adJludRbQyt8%C&I2Rm&)C6C}T{%RlF(d$fj$|rO14ZO0+4RWYaZX>Lj}< zyQzv%$NJoxr?YQ}wsy*{9CZ>!Yo13)wsBi~);1KlJw>sa$Enh>4$8NtxYV*e)7DYG z)SC;ciU4#QL;Wn~HjE1!j*OqzX8gPkJVLqfeH26HbzDrH!rX=Hdr$bjaVORv?muT#g?vO@agqFPnPwzQ7qKdP_X z4S5-TCgWd`p}yR7C^spC+CN`aHz*tT zj-sEB!i~VcNhufggm%Kc6^UDaKJ%K_&lk}{v$l|#i`JLJft_2qKQi3Un;X#k2L=al zSJ8xfnk;|Ypl_%ulwJt#r7RJCVIfiJ*YZ>obW~O8agCdg5)ETkx!SKqko{UeRbNAY zdcOu6#mYZ0D9D?;NX@-2Co;$&aHwRad|GPA*IlAH_9;vn=wb%2}81H}0 z=2a_fw+cV^OLl{JHruAIjk>$$V8lIk7#0}q>=W$Uj(fXSZX3S3Cp(+lY`N@K>Ta6p zdAdo}J($tl2%XDv=Ww9@-*iWbkvaXHO1!Yj%d`*c<46cW|rS`Hj?#h+Rv^X zAzZN3xG<^kY(z0Yt_EtEJ@fw(AgzGJ*euZkq{e2=Gm<>3gTyc^Q5-AoX-Y*6_qPnk zws>5fTMKm?&2cO2hdmukB($9}O z*ZSG!K*mey;a>{iSB`$%Yjg9aIzKTP^+am)lK_w#{qn315~G?#aU@4Ssn7kE(a#P? zzua1=T{K6(pKavoWq>JWg>BQKi$tX_YqlfKi_Mm((3$t*)*=rab?S^Yja#w zUS6BCvBC*p#d{%cc-A~hS8H6GqcZ<5xHgyjwj+%AQhPYbt5J@5y@$(o#+%wGxt)v` z>YL-)73nLLQX0A1-NA0{ze^*1ZB9Z%YTqYZoBLIpS7JvfQ8vjPq15Mo%Z|`d^V%Hu zu>CK)Hb-aY?X|f)-lUq>=BVi3er---jLhyTndSea`$`{{*UsxvJICW^_A^^H+{^4D z{d@zXe%0)>6hN*9>by8F$+J4c37bmt+MEP{)Yzdn-MQ$a9V>pTNSbFrU^9x2lVI2;c`sVh!hEQK6 zW3F<5T#bHknEKxWki0f0(E{W~zdYM+5~H6)aU@4Ssn7kE(XS4Uez~>Kyf&AM`w=v* z&E+8FSI#{Dwx%yN)=6HXa?0zmF5AiVpTFNdXTw_h0S*~)r7ucKRXkT?+<&m*lGo-W zDlRp)3D@TGV53QlX%fYd9Mhye_gls^Cu&T~xHgxINnwp^b6GQSxtJ5yxHk9m+eh=- zTn-^Ll7hazF+nmnFCKLP767LEP-M;UHC{ zVYtSf4ncwa{elAfhJ^Tf2l)*43$tn!5@6M*uTNmGcZfgt5K5qbM8^O8QWlpNoWwvkydU^NEP=w z>~caYY7!nE7!b@Y>D$?ddm68IkYC$S!x9odRA;;5W#-~FLgCdV`BLMhV9kAnzG@`5 z&O0|7?HwHA9qbd#HDt}J#-dg6Oe6|L_P6O@C$5O**Xgjp($@esW)_26F{=m`OkG~$ zo45`ZmU(Boy0lbLxOb6h9LTT>6QWWHWiixq35;qJ(#9uP&4yBES9n&Xg#o9Dimbh& zu?mYuA;?ErS*is9C_2s+0anwvfl4 zOc9lC_efPC%`$3id5z60D!V%Sipg&}SCuO3pn-EBEkO;1VQqL4Pq%>d-9xs0S!e+^ zRubD)vIR(fl36s(&ZeST0A0LnTY%)(GFkxRv&xz&wg7H{A=39XTL4{lXaV#uxyHx3 zf|hkQsnTo#nyVUVwg8RQofvuCDq8$oS~3^9QyX{*?TWh%zCe^uP^6!szO$}gPL?V5 zR!I)Fwxof;LL}+VWd2GMo%y_>su%a_6Y+k-+g5rPC{q}9=8I}H+Md43U89F-F6*Sx z@6-jn(hu%PcVcZc$kJS1O~|rUoYg|3T$*dC31fiLQthsw$~ZX9JVY(8akwI3`~MGN z@#$TuqsjluA*{MAzb(^O4W@>4wXyIk?j8{w@8Or}Cjpu}1L-3}=>s^{u@vLyw(4SD zZrrjLJ`o{d&HWC$>Aw~M!C%wAO@BAB z%wdIE{@a`lv?x|-(Z_JI{~xFM8VA1D1N ziTls5T%W;$Sq83oV=1c3f0X=<=DlUsct>&W?=9m7PmM!$c1H(a=Et~xr*VP6`sZ)& z*0_Y4gA~yyf~EOiKWwRaVTXI2NG|Ur)4WxOq;Ud2T}#Qw@_+tT9nBF~@~~cW1eW{& z*P1jIy2`VME;L49`X1BV-ngx~whW!kZJJ!J(W1GOTV6b=pfLhx#O2utOx*!XjeQy` zy>vjM_?N(=FqCShs)+;I0EP3;wpV) zr!fNOAcZ5Nj#V}G2e}xVpfrj{IB{v9$>-$=EZp3fi&|=oz(QUwM&RFd0n0w~7(#TR zEb~Cjk9(*pi1enc9;ocE?5NS>H(o5WG*y{+`}Fbk_UGQ}6%iN`?A<3MI3g@0DDyRA z>FX1k=F_{ad-1h?xh7d}kY0Uct$w+%RlWny-fU7#$I@P9tJ3Z56Va!yx2*PYeZ9FihItS0i}2yr$@NKJg*UXXp|;J}$d~nOGXpD^?fg=ItlQd* zK+9^XDk_yd$SPnP9D|r7FQE1cZ89dxwSvhJ<cii=m7DU;KJ)Lr?2LNq?~UEa zLu<2SdUcwJGBcC!yEe$o=;ik2rM_wr$&j=0OtM8AQ|Hk^5cX*qBTTH5X1t>w)UIaf zMW11-mt8}`l=)P892l=&FdzE}W!W^~-i`{ZM_pR^&4=<~Jm*qczLL)}S+ zoR5KLCG;_i(rOH09efyJVjsQ5N6@EU^Mp&_Q@t+tj#>ef+yx--EEF-56nFpT1GW8bJSA+p2aM@G_jPr{V>c(sf+2cJF$M|q!uET80?3Fwn-dEN-BG_M%Rkn?%miSkkTo?8N8{Yo*y z#6I_ChN6$T?%M?L@l=yAWj?cSgr5SR1;ZA$wuYTkA*MhKW2N_{vpLuPUqfg+$4ST_-)(H}(%;$sAr(@ugIQs(c zqtEgwGieI?4E$@h3skA#0+J!;Q)E8nvp;S^bqKq-h!H0CDX?)5`ZV0RVn6sKFDGHj ze0*EIcnCf^^RMteDwa>no5Rs(dcjX;ph|{INQRt`I)d`?UcNmQ!al8Jgo%C11YAU) zb+vY%5Nv%ct2lU-YTe{QU{2Qv7+6A?NeCHRbc-*ku)j zExE=B6Z@PRmW)0oG3!0S=l*RHrp#x5&4;_er~b!VyiXyPk468s=woL5Dio@8<{Qb7 z^SM)v^4V>qM(n})Z)X(?v5~j>&)#;cy;PbD;J-#@FSw0I^ zIiXM2BImAyPs;`*1FIxHH(jPh`M9r|5es1-n=-=0J|hq2ZwNyK08v3mIcVA_w(pfi>A?MTjrZMins@Pw2gRm*>7-3?cq<4kU z=U`Ozui(?P3kg%^qvd>c4fvGm_=NW<%JT8qUj}_z-`KDPs#LN&$&mAL+(`K}3|WpR zD{Fc&!o)tI?@Oak+>3Tk!6(F@gemix*rJLJ_`I(7g7+!L^10$*fIcPMuDt>unK0LozWBHo*DbDg~9-)Ok z`i`6GgU?GVk|F1Fq$}mqXj*w62-|GW2ow9bHZn(_6%~&gfzN3t5~j>2^s%)ew4b6y z-tj($ET7MMDUD$i9GdWTB~+eET4Vflh7y5tl&AQl4}i;A?I`an;OUGD=iYR{rqdo2owAG zmT^L#-R4^>gU=Nw5~j@O^}RYV;B%|O7v85N%cpzgOX$=0k;{DWxm1;8$oZVOK>1WK zkHh)H-ZdFvVjl;mCg?L@Wy4C~Q_r4+Df4OihhIGSlx*^Y_bJ8lsW|Bv`b?Oa{{Z;J zG$R>uK92E}kLA`q;~~toB_mAiW8T9JeL@a;;{3*^b|g%hPrVnP^uecG*L;2%7eY$2 ze9S8EM4zBaS_`2{J-kVVoKIXZl{aiapVXayVwF7GlMFeZnEI5@flYd!!KYSdMwr;=?z67wlN|m1 z6Zq8ZLBf>z*u}UdfY0bU2E0!hmd~p#%h1QYc0@6#(!+)%L(XTSKIJpG-%V_c2b(g& z#6Ii7d!f(PTF+{L&&d`fOqtIt=Mw*b&kFORyiZw{&)t0S=yU$hkpbXyu_noo^SPE# z7WZF6&i~m5!WP&v!o)rSX9LhDDCzkW@L5%xgemj6z0w1ZfBrHp!TYFLKJ8OyqmOyN zLgk=JCoM>ZoX_yZl+U!;a}PmSxHTh8?BoA57=0SPz1#wPJZh6LWj@>XeLM^8r$JLA z-p82bV{mLb`s7d5eFIgR*n(up`D_oOe4dXRiSrx1TQkDMJ|9ve(I?dQ@(u9u>_Ebl z`OLK#SOt8FcQ)pIOjtfQ?uUzuZp^K6|g2@jm5QK0D5gK%bqay}v+}Zr&sr zaz5oxm%;Hl&~BA6ggs4Sgo%9$|1%POl0GNA1fTrLButr4-=ug;@bO5l#`{!Y`4~I= zjXo6}d!2+T`932Vay}KNQ9e7XMCn6V&x%q^^469?06qjmQU4Q1JLJ~WfKpm(ypf@L(V7ukr9qR z=0h7;K$vq1BTVeGJ8dfZoC%M^`xC4`kT7LF%T6Tjg7$OmMs425jO8Zpz2pjN-5hnIIzi|fo*r%E|f%en!B?(jJv--}U2H@gCL3JE|;?FR`#6B02=c3QB zpppULGwvb@Q|2@C#p>JOQ{-S%-lr@K$oXgur+oTbA6yP$Q>__cVxJ{*;?d`}zkhM?@o^+!%6vAKe7pmE z&NXYt`&h7ij<@wdAD3f~5}``v+mH-7pD<_2r&pmSIGAnnV1$W%TEs3!pFS&+Y{BPL z4-%%#C%*jnj^I$?^#|?utGtgSl70C)$f-$oU-0Px;);R|7k%Qy)f{*r(OB zrRekV*3hfqW7e01Df96eJ17u*d>eG-eX6s3sy=FiKIcb0Ed)LRE+j+FXTgb5I6jYh zv;r@tHF0NziGBL_T#i1kbc@aeAD6ZyOqq|xifbRir`W8XyiX05Pwk+#=+p4ue|CV6 zdo0P2^LaOh@=5$QtsjIL#xugiJ{7fBqR*st!;gSZ`(-3dnNMo*gx=s2GQ1b>QYgcy|+qV7Ja(R+tL?&wjUv3%6#g%PFe~+>mCL1KGrOs9`2Nnc1n*J@HzjSWXSo{ z7*F{`n$-!1uyL;$VPc;*JJ+F4T7^m{!6*DZ2~*~i@Wa9ZeExnA%KO-`d}c(rV*A;< z>H0pX()gz&L(b={8|AZiXL)xBb9&7P6Z?#RupWJM9v-y>ALEZCOqq}MHoKwV)8}Ob z?_&R}`W?xT^Qoav`P}XQR{;nM`@{$n`xw01fIf~3+%JHS-!~Gb z%*W<)_4(ja=6N*lW5@CtU5@f;7^IT|RhsmMWXSp0oGO9i&+e-u@cwZ7PmD0J&#QAA z(PzT!ly~4$>IVr^=2P?3XuN*WGT%_%$DZZmuGbjbPv61anu1R=70HnE(HcYfL|NPC zhp?N)7-3?cv?ZI+$HDS`EAUxnM8cH$G@H5NDYT!nhJW!s4lJL`ry8Kool}+_pi1wJ zNQRuxOjpY1*)rz^5Vqfh5hnKebL3|9Ina8t9r!q!k}zdH1HJb9fzK49QM`{M%jeq; zC-j+QaaIeeRH_2Wkn>5-NBNxH;$#kCCRG_>VxL>Jx1dkKGsmxhk84d5rp%|h zr%S_eyiaYG&k$S6$Iw5p5>#niQ<5R)bNjF%jz67Sn6HB{*A|R0u}|z?%ID&Er&RE< zZ%x9K`4pZ03fqsJ@g&}-4$G(Jdk1VkdXcx!LX~_gk_&&q(NZqR-j{g}%8II(#oQz(DYs|DA*>^LZ0L;V}4o$v2Pp zsmJm;^wb`GKID6B2R@+&Bty>U>Q2h1-_|}jKlY{=BTVd5x%D>eUrW-S$AQnwQY1{7 z&&4eduzwBvx`6ko&+=LG*$#d3&u;J$eB!m^vNGg+9z;++gQwTO24TGlGQz|@6K7C9 zU+NF53qI}!Butr)Pw%6Zq5UKjSj^Y00n2Adf))BCRz8gPKNmG18FD_GY$%^&>s>;? z=VnnxnAm6NMapMo!$D=i=VD0`rp(99*$tonx>9#J@6(Xw6YfL#m>Q2<4^_(NOfuwr zd{TsFH1Wk|F0)HGuM&^K#TU2utx|go%B=7*RfRQVZbvEqD5m zFl9dNt9~p6K3y7Z=6#y5e4NfxK6gzP;v-2hE+j+Fr=J<+V-ul{1s`iSMwr;=NF~ar za*Y{_pnn;*Az{jVeCHnmd}Cv)v*0^YwU{iKZhbohMdpXdqr{lsrPqy zEAS~Xj1eaGiMF78Cf~d|3Vh5)lQ3mIizlgZesz2BUf!oE%je!mbM(1z!RriEDRB_V zkn{OtKIQXO*Jm_@%^J=K6Z^cXMfptZUPc#uqQ;RhWj>o9S?+}PGiK=_-p7UI)3;4k z^l=QUf#Xl9btFU1r)3w)r)h^F&%noh8zW5YV@;1g584Of{To;JlQ3mIEiGoZ10TEZ z$9W%DmXBZGD(LejWOi|=(&+prvNGg+3`$Twb{>1)Ls*205hnI&_nO+jds%zOK>Hb4 zjD#ukdA`ze75EG=KFimw8OvwZGE?+1nYkP9-zZasWXSm(x=;kipI1Gm)&L*ZT8uEU z&-2riPe4=!bMRSLn}jLzDH+|&8hkcBzr_1AXZeiUNcnUPPAdvkn)HTb$oX_1Px;)4 z-cTFDmZvhp#6EkrQa--%0h7w3N#_GE;KeI`z&e0nTdwitZO{YaQHADzv&w4wcUUwE7Mabx-T zPM~}OE85~Mxxp(*hMZ4hZOUh6^|uCq?YM~%CiW@iNBQ&{P!q53cRy2}YRMr*uuq zXX(R@RiORkyGX*6`Ai&dfa{OVcY4J8v}F18Zf$}-3)bIV4pr*gh-Aq5+!;jq?C`39 z4Y*? zhd#}%7uJL-HSA6@IhI2)ovc5hnKO>_hozuT8}Je>Mb=Fl9a?x91xJ zKC`{w@IGx=J~oTWpih%sGfqL3(tJsVoKK(Cl+TG1zLpR+GmsG`_9<1K^3jWUjPt9W z!6ZzXPuR5HMZo8B;}5(~Tb55dOUh@dRlq^0(i>NjA?Gv7m-5;2dN-cTU3F)KiG2!P zrLKRqU0rJ#^sfVLNtiO9Biny$0iS4#G~TBj%ja9=(%61>&x*$DgTdA$L(XSp1)rgCS5iG7xjrhHZn z`S36JXtyO{%6!bXT=)(?SIX-1J{~NeBxgfxKaKXq%!4YOuShcFe3lqcK4HC#@cA$A zYK$4J09B4)HWncna}zV+q&SB+O0V6)0yQ{c}ofO z**&?S544}8UL-@#C+;uGXWaLax)8S5j}a#JIWdCr+5K!0_OGe^NSHF8w42U8;8S{8 zDc+|G%V*s4;^>oH!C?keY13+wA?LH8KIJpw%!L>TYrc^YCibb~Lisq3@~8>zXYDo; zrp#y6cHf%d)8|cD-lr?eXUdqO=ri}_gdtER&rc*n&SzPwKK8GZEoZ!juutC^VPc=F z1t}jh>p8f7)ae51tlBB_d3jvR6nx76D90ysWBDA|Rv3L=-W~A-s#Ga|`K$~%pP5@I zA7hWpc(c_$Jw}+=CwLWg|Eh`k7reeRwlE1(=F_v@z^35iJ=m15TX&YvMt90*W`gk= z@NpYXGUR+#44{1O=pM((k`bdBVPc;sd&)=8BcUtwuOSmim@*%)7ypz6p9LMN@;*IS zK4&f)VEd_8_{(bWxz&Ya$oXtGr+lnF?jHkTDLolsVjt5J)cxVFCTt4=pSM0FOqtKX zrd}c7v&7kw_vy*)6eac_hhwbO68_AIKxsa@fI^Y zdQc^cXp$l4Q@0f5Q~dDJDiGFW7$Z#VW7>uCdD(76LufzsN02aOJ^`QZx^_&1>NEZX*d( z=F{cq_lwZKo(*fr`}nYYUhU9DAGeRqZJ|o{N0AIUpEVOGA5Y8RUJw>Gkr5{L=`xM- zS##(qo}bp8LBf>z?C}Zk0H3AN&b&`=mXH0;g6I?ROpQb8qoE{2&gWAz%BTGfLx1qu z@;4()>~pv}<@2gnVlQYvX=6y3GM}ZZH@*U&6G6>*pFS)fzq19D`_)AxL(XTTJ>|1!(R+M;dG1O^nAm6K zNXjRn?p9nMJ8}aFQ|7bl+bdkZ_wDx1yiWkjr{d*&=reattC_IL@9!fSaz4)g7Qp^> zq|`TDUwzS0Mwr;=yE*0ad1uMC(0(G%kT7LFZ{L?a0qy7gk?y=tUzU%5AoTwE;;na_A}%kk|F2Q&5ZI{^!^22KXrV@2ow95r%~&Zbh4jW z2YgIYNSHF8{mTOJ`KH1r{CS`LET7~1DWB)<_Ev)~5qpkg$oW{^%a7yFKNsgmLRj== zMwr;A=@`oA-!k6Yz$fH72~*~Cv6>^!uYS4EkM{{;`Bb~~4XaeSK>L~5e+cgr%JR{VPQxmx^!`kRDs2iS8FD_8CQv@rcCMHU zVZM=!FtJaCVU*7f>nAGkaUVj$l=*b6=h+;5;=2sveFn08Y>X+N!B(UGgeoQVBpGr( z$;~Mr_eziPV%i!XMwr;grX1z7e4$?_@LA(e!j$EU+kL%y!Z{8=2<@3euBetK5 zZEgF3&-&IRL(az~Kjq`C=UxKBMs#3=iG4ntpw{<`YB~$o?;YHQgemh$J%7O++RwSF zqj{fjmQR&~l+U6QLn}g+UR5U6Z=dKr+iFn#+yO=33Mc3 z%6xn$pIHt*y-SYgeIi&s`JCQil^(@9<1VMT3CWQ2X*rbg@fs6v2tFH48DU}{M@!15 zM#HdH;4{vGgemiR_h8aA@bNO7%=<*Le2RFyN1u0dpQk{T#u$+dIiD0K$|ts2Q=I>4 zZo&u?`*c0K4EJBQzTZcJPs2(iOqtKDqqV+*&uFdbyiXL%r-%AA`qaB~_XGIE79bgN zKI=YeV^|&CqBvRGMa2jc`<(Qqe2R~{g724cDoVnX`J7z7y&U+=c{q#r8N~82-%RDx1F(XXuQ-NN;cl<4TTtA`93lgTx zXM)#BJpTE5DvtLV%<}1J@)Em*#m?Gz|5)rrk|F2wXHClI$Dmaw!6)JxBTVem-Go}- z*rrUkg3x}(-XdYjd@6d@odNB~Ja#efGlb<+<3|em?Dbw?0##}qPcr0u=0DfMunHcF z@&2D8%NSu|AFb_6aC}z9G#>#zUssVZWj@CWq&@(jzveFIeg0tibhz>itCYW|-WBk9 z6h|`Te6Fpee2TSyUIxM@E@6a;eJ1y$eC!Jk#OtS?D@m9#pErj6@%bIy!K-{Owdl+~rtoAQ^H#jSl_5A;W*z27H)o=Qc)| z*k?^c%4hqHLv6rEdp`+N=2PMGkm=y_Zq0Vy=TDZ8^O7gnzqE!f@`FvDx|w9i`E+kc z`K0=!;KLl3b}_=lKGz;BLhR!Uy>R`ys|QJ#q)+m4;JeYq$x8RHt=8#FfuN3fH(S!X>`>81sbjXW9bB_l~)NNM9yfP zGi6lqV6l3TW>tojCN_$!P8lUs?>GjGnwAsNlo_RLQOyS8vvCiNAHR%QU~bHDxq)NzcoWX4apTCN_%Px)8-T_bOBkj5dV|Y08XJy1#V- zqv#!1d85%xqa}A9U^{x%a-25Q>g0YQM9xTc=?m7%)OOrlNIP+il_oZ-(2X+ce?z-B z7+pRqq$xA%|J5@JjO_Q^Mq0KLlb}`}M}-hMBd3m((G9(;iy_V894k$1 zWbvMQJy_%n!v<9$C9FuK=9NK^cjrC1i#{|H-TyNNAufgbX$AqWT;iyC?Q17Xo?SIbjhscSV+?y%1RR(9U4v< ztu;Kq2#o5F6w;I#CGPd{2BRM@-|$8gnMQwaPDG zA#z4L0x2V{_(T6B~scqFxKy)p?Bv8aW7Q%8c&Roqr#U3Tc1gjV3dV2Akc) zb`<;k?KY@YlAaJEXH+yL728qu9%;uRt$Q(6n%JnkFJ*MK>BM(nWLic@Q)blM^HgOp zvYGpXH=4pUntkay8g+QLU?$Y6_d+2=&S+K`WmIVD6CFr_Y1Fnl)s7;j2H<|}i;g}Cku$Q1 zp^UVr4O<6B2UV;zv60aqlu^9#5f^AjS4#+K%8a(J?B@bTe%}i7)tk;VGMq>m*_9~T z6KXZ8KoJrmXVg@iGU|Wv`wmF+F2qU`8@UywjCN|Z3(f%cRF<>-il_6if z8BC)IO(>%daYoKitI3;$5ILim(I2pPwEpmJ2Bclv$x0I&71}rt(~>tm&;z5h2Zc0c zMz-z=$zZhP4UXD% zdPlx>0HeRB3TeuWmd`gI14fHmneaxlm`0!4C!o=zi<_`k^F4$RIipF_-s6@pJbB7v zFiPmbN)sFX^@Dn?e2EuYWx;4oZy`;Y(Yyw|4Z$e9NG0BAHq+?CRI0B{th{0?)M{#J zAwt9yWv-dQ0;&ZuMDJ8VZ*6FT6&Kj|_nO>DHK9c6UHI4%y1%o2q(Wk#D8*fj$q zT^~!{XfD&}ah)q@babUr9WdGxAcV*njW(l<{?OjE0Mbeav(m&y-#^Yl@d6DCUIU}k zkwTg>qbt|<9R;IG>#TUAc}%04?=PcK$8(=?mR@(e5F%%ky!tKH%6W2aoMRigpOq#y z8oZb?iVi6=4~#rc2x-cUZWQm(2#n0DJMc!aOrv%BR6FXU?)40|{23b|M9wJCnliEr zTZ7^~>#)+qMzuXCqYsxxhJ#VdMnal0qy9-Qi@@mc@w&Xxe5O&CN9VB}wKJ>l4n_|y z3L$bvXLrBBcJ!^x3>QdynaD~L8$H*jjCP-E76V3ylZ7-%qq#{X@OuBLM@xr*(M$Wr zywL)t(Y)>#&}f)*;u@$`-v&a6oYBT+lu@mf`Eiad!iAM4Hd?%OHj1yUwC*VwU2G|& zDKlEtB4G{~b>8E`8^tk=T+Pm*(L2}mQ^2UxVIf4$DDmpQSgYQXIvj+w*C$zNVxwmM zl#zGile%DZ`GSz9%xKeJm#2c!++{6zqlHYPQ+`xCN^Z~&&#)e@6++~U416e~zMEd_ zgHf|BtTeIF*5Z`Wze(3?fl=*-47Q^x)#LU;t)_1k zLgb7Fr@Y2?wD3>kR*+`Dhm|HaDtu%Xrk(z`^`Bs5by!GKW>jhUmpCwbmC%kiTEsMp z7)tfE`l%;MLajC@2_bSu@BW~SRu^r19nw}kWTlCXlENsX=Esu1fYGKWLYgw8K}+|Y z1f%AsJb0tUOrwEGXR#f%?04XAsFlS9Aw^|fM?A_AdS@souRIirMX zl#y5SJA)vt%M4bU*r<05W%O^S{{6tH%UmH%(&%|~Av`|ny)nfVjLt{(;*FLujRv2j z+R;fP?b1*yhhaj9oYA_yuW-w+TG+}M((aFBrHPI1)TfN}run*o(cuX~nlhugh1b3V zqn6RWywP%|k?Dz(I37jsDv4XZ$uJ>A&S-pF%BaED9-F|(Yy>M!Y}7%UGHO|EXd5sp zKUPRnW~4i**b*>$(z!2hw1R0gZQUs}+Hh#-ZKzd(rw}4%G$#2awxd(S-tB_43cjo~ zvC-MRGcc`x<)+)f$Ujg>Q)YCfP~sghitHN18?9s-nRTJs(U&?W_CT#7yoC@sqxeCT zkwKd<9Nh}~v(m&y#X~5gmdWlRVDvsnNK8kN3B8Fh6iLom{f71ER$^?T;u9*p86BY30LOrthd z$FZ+X+PB6AYPBRr2$3@~U-SZdM~#$LL6GJ;f|VvV3OGI;)8b4f;yh&S@j{w1qXTcX zg2AZN@o3&?4b!Ok&SPj)vt(PmmOc5L5F%$Z!=5tQx@Sx&Fe-C}l_oaw3#E+yKA>d_ z?P%-`Ax)Xlpn*xAV3edgls8(-G}^Cy6pa>^RQ&<9>QGb&kuxfP`Z;d-7mYrafV66* zS!rS;y9Shz>FN9(!KhI=Ax)W4tpZzifYG?hfAL1^m_{bWDWgxV*7-uMrd1b0L zpYdwXEFU36&S=ovXIQJm&i27z(3uLdhkY?M-wGTP8M z@hBM0wGq;k85#8%jQ6m68cpMkHZhIrj-=YrTkoQHuitSKAw>QN0M3orU!PwQjJl;Q;0v^sY4rBM0o<=$xHxYf7_HNaBOzETv61dz%II{1AY(|I zuFFaj8}0Zo1;rcPO~rGOqeX-?Wky{J+ogh0>$F9D^|mpM9{U|eBdvvBe4tiWz6&98 zM)yllMrMhDpCN5!zQv?Sm?kzlwv95HIb(+_w4+0MLYguo*D2-pf>GStWqg6QGmZ9p z9zvu14$kADR-4m=5UiEB9Ub5B7`OZ>9RpWL>#4Pz6baMBMy^9CqxY=?QoyLKu8^k8 zXuf~{BVeT4bTwa~9ZaKQHv7@&lFx?xP^%*DLI~DMY;@9%GAi;;T@%t4wPU4;jpD5- zqgHO0@Hl&N7a>iVQMXd>%7IaAwe`HwPNtEn4b_fPs<`5wXlgAXM9wJjpGVk^UK&j8 z1V(BHR+`wT@T19?)@9AYIna*2)DzN_87&UK<^e`gX`6VXT}-2(vDBFD=T{Yj|u zOhV+0bcRz#D+>kTJ?xcqS!rUUs_Q5tGjG*%FfuA4q$x8Rb*xEQFdE!oJ72xsOrz;7 z_F-Qeq;p^eZ257{LWrDELu1OQ-SCd{A+14kR+`x8b1-Ez&h?NT7}aSdq$x9MHY|8F z7}YPin>X6SH1bH;i$+y$S$~9D4J#{z$Qe!B@elTnzjt@e2WgGUv(m&yUe=V+jFb+o z!Kkj8kfzM&P~(ZdV3hiJA8)jmY4qobJ!sUS`=NqRtCUwlh@8=v_LR|;B8F8UZR~qi zn%Jn^^GPUP=YUINFpByjq$x8R-z&ipjHVVp%p2`v8Z~)H?bpT|JHCZltu8Hu$Qi}F zO2%3}c{g?{q;)lBrHPG3tfGwOnDqM_j2c!H(v%q;8h-LQ7=6_~&KvD#8abs=M&8;N zam!cH6GG&SN{pk7M$Nxl7>qs_Vx@_V-uP2SMssIx2O}LrAx)XlS*uP4U=-c^G;ef( zY4o%OH69(ld2RsIYDa(&B4>1{GG$b>;=}EbHYJFaCN?^xri`37_Lu}lWy6FtWk!c~ z-)sp+A6?G#MhBTj9^TY=bY{(aT$3f-T?mmg+I!?7_O*n|C-7ds#%)Ek4C z4ZvudX%cUAlxg(w(@tzh^^7{>c(lYq2$3~vMj1s`Ka9^p^sB{66C1U-JpskrmTZFa zke+rznlhsg8+#aokz26`ywNeHkxM7a=v?c`yx^dgWlibxK%0wcF#LYgw8bH0PugHdp)XS~q~rqMq;c3@w7a%b*S z*z)5|gb+ES3l@}7*@MetA?=4LD@|@kS?^ zM)M0$eQo~ZYW`5Gm$iftIisRy?_pnC-?%xh$uh-(l_oa&piLQ79R0oy7>%wkq$xAf JzGyJ_{{Va!gYW$&gWKCXM#ef~LroU_)o_gs(taAp{W99E|PtQ+HA$kxhgY}ddGw`=E0+a<`? zzn^3M!G8S)RxQ8cTukbI|NZ|W!=1a?uGqA-+yDFjmF#NgYv(q=uTS?*1A~0K_V(*$ z`fuMZef$P^Ie9yF68^W|enI{G`Zx~u4f6Nx*VV6%olUY#R)tcux;nW+V|zPWyVL`^ z`u6b+8jx#JweLayr58+rPcDfTD|Ktpe8(~y<1O73$5l)zsZMs|+>{}6KVcI@Nd+pmv*&;I?pv70PZ!l@dxw>)8mZ@_;k3rcLiXdC=!=l`$0 z49SdeLSWc*bi$JlqY?-Hm*1(!fNQq(KU2QQ&%ZfI>ydV!pNIr+i*GmB>%SRtC$pYz zYj3wJ=`j!q`o9@ug4nt?3+|oh^j}nqn#CvE?#fG1B10_dpEgSwm!bl+JHv_MMC1S4 zb*jc66w?DA*)KPa3BBnyS<*U&QV!P~c)ppss8K+*o3GF&Jrzo*q7NylL+suDlmBQeN zzCjdcfg{dGd!i$D^qzGeC@Q?_hzZ&hMmS>f^#$k%tC5%b07U^|lrK`G-w}aVzaz;h zza9My6rG5q8AOWM;i?p|bqkDJz5yuu5kpZTMJ!5-BDPsgn?dWK-N@GzXMiKdgfz!T z)_!sa7ijnMFUl9&)$fRH_F2&pv(mmz0qu@WcQlD`v0Zk!YP)P*t1N%oLA!YiQk2*( zi_&VBZB}~A$Ti>yr@9npfg@6!>yD0STBS_@P}Fxuxakp0X@ny}GAuzyqzudV5h$v^ zit~K|z*t)atwR8lE63$SRND+(DqKIu)X-`Fb z9x>z&#Tnp;9j6=PBYSI9-G|U_WE|y-?do?#hQ>M35$kvP#z4Cb|IiF#yX^h$`(H;3FHfsdsH~M7QmfFSe`S5tTdTMMuOPU9c3| zy%$b1i0!h&Roi9jw%O3XFti(fjiSVMS(H}0Y_q?f)~Ue}#lBIT1&+v&Z!|h$aD??P zpvc?ltjQ6njc`PF*G1@vE4wqd0g9eArF@Yh{f=n+TzNktW?uR{Kv89Xnn9$99j;0d zTle|H!CpX7j}a6lQpBRPC}NxCjf{1GcKgnxI0GC}I75AOMBU(9*`VE~t0-S=SHB~2 zMHWCu6q~tfKD3)7jAjtqWrwS_%hsLzGusnrH)SM6iS4o|t#;XFO#}8V1xLJjNpTi9 z!oJ-^bj0sxHG2a^)v{eMIl{&WM_7+m-j6uyH-8^cRG|drixla1M8%cL&ps#ZZQl?m zigTqIM2gtqsuZzxM?IN$9VqJFjG{z}Sd3u2A07sk(tc#Agu{33G zXm|Ml$`{+!?}%rKh0zfw8zskAlBFio3}UjZlrUYG(#>LSQAwS*>fOZ`{X$G-f zcDQQ0Y~6m$G!2}Gj<}Mc#sr|~T;2{5rcavuQj5ZH}wKXlx$1+B1QTg(KPT6{%bcV?WNg3(T1KhgGdoOT$LiWZoqff zaG>bZNQx3EVo_QYvCYz#@7D*~%`%VT3~)r~V&%2Q$o=)YLA%8^P`=o%en(vEUlJYh z(K}@}XgB*onn7%r9j@9gTer`aig}>j_zM&zw#%Zl+GU%it66RqI3n}|#aZBp%BL5h zBL?jBhz5$1^|@zqL>eO;u_i)!&vM)f`?^5U<#CiRQl#Gzv&t*)M@+0{GaM-Dvw&t0 zDPo7KQpDCxJ+|{vplHP=iV`VeQCbwS&0=;YYY**SK0DuG%hJw@gFtx6tn81d0;dWl>t~vds!zF4Y|z z@ge8^q}#Q?5yNgSLr09Mc=QKQG-}}^Q%+hV9Fe1>^7)9%p#e3)5hp?^U!+LCBjQIW zpT)lMa92v8=+-fsL8OQsu1XPGw?U3Qn}8y(D-Ya(xQlM zcJ$tzSUYH06y?wni(idP1?|o&Kr@K# zvcpx|W$QLM+NBz_TdD#@iS4o|t#;XF_tM?24vr}5NpTi9;?=aZ=!mBm8!iEgrY(DE zYB9YLju`S~B|0MO!)cF!qNCd>U!+LCBPKroiO-0)wy$s!u&| zGc8b*=Nd(c6tO5Rir8k;G6cjzyCt7doB@vTxz!LK*&Gk2R)=;|eWQG_UHy(YHQxyx z5w&9{e$xJm-K!+R#dg`@s_n9M-EPmqXNmI)P?Xp%i_&VBZPqPt?-_8!*LoCZfg`#W z*oclenflW~plIQkIMXAT!3al;ZM_N|@iVp0FQ91NJjxd-((j0izZFL~%$aTrj!0Zj zGl&$i!&NC_>mFP5y%ad2(*cSSDPmDt6tT^!rCpRA+HD?1aRxYIZ%5^`*!_>Lx(e;C zxKH_FyZRmB__#beV$jY}*Pz{j?`a0HU3R!?yKLQ7rwaFjcCD=6CLNR5E{oD?mu;54 zYO;plh)+c*&H_h-cHDxFNGRi&A1E5$FW$6PMk5?ipmzv5V%W8M+kv7X<0xOGNWUYJ zk5t}|*gxub8lY(U0-8ajh#js<5nDHKPbvKVh!&v~B~rwqv?yYm`7H?O1?{FfMsWr> zVq=~r_&j1%!F>ME?!3#CFSe`S5x>*8pd)IPESCW72FKD2V!P~c)ppss>oSt zo6RVMAS=tk0{(>WN6s0%|9C2jfPIN?`_5G&~p(KyF%(C)HplrOfc-x1CYDxxE% zMr~{Y?K(WC8N_zk;i~Pjb*tF!Dgo_g`c6?|yDUnpUA9@;&&3LXBWC6Mo^-nwIHK*K zFm%Kl_d7R%qM0LpnR2oi;RxrcYw)#3{`GfafufGHC|{&Vzat9ORz4r`s9xG1K+%RZ zG=oSHJ6x3_wr+TE|0_Vzz`YbDQpBRPC}Nw%o!Ar(?FOEqI0GCpc6LjA9#JrM*%D~C z_HD`++tu%geT^!iBUBi6h||N?XtsF+hyy%zuB@XwCkTpQDVC+N~>MAS!%EE z=fM#+1%4;pt_6-5QDGlCV#&jKK|s;u`F~A0S&eYSw*!hJc66Av5GXpjgYrd+^gCim zMa2=eZHx8+ie{as8AOWM;i?qzb;s7J0Th*gMo}U~EJ}+awpqIF_D<05?%xz=fFp8k zY>keHoLS@(v^zDOmEZsS{^Sf`_mN7ulo-oQ6DbnwV1345&M6~M{4iwEkO*4oTvBOmO6FEJ~|gw%LIpUvGdTayOzl3mow~{IKGP7ME{TAkyW!}FZ^1b)fg^hLNpD&!rxA|$ymm7>;$gV|F`%f~7|ItZ((j0F zgA_*$p5X5T6s4F)Gl&$i!&NC_>#iu{ehwTFwVt9xidd8uMQpR9w{qg|Ys@`BaRxZz z^IK1JM2o=d_;Zc&QIs#XtKShh`&2_mtY~a|5!(H6pJou-Wrxe!Ro8W>dubxHJ2sx8 z#CBPfR=aGoH_;JGQtrHe7B(^N?y%W z5gc)6H|2{I>32k23*~c`r>noU1B!woX$FxZcDO1It%Xm|Q+iZj3wCDMDLBciV7Eeh?{`c3&_yZRmB(5gB*qFIs9s?hGrbXk%J7u#ir ztG3J5eUNU84>-c6AVrDovM8-~*=7TlUfKPA*KSjIvIpvG(>UTtq4~ioyJ^XtP z+Wqm3W)RzDhpV>B)(!eRIu6>6w9AonOk%q%N~>MAS=^o6pTH5vohZ%%N33~y1|5;2 z!rcgJ0rnT}I;fUJPx8w7Ok1Ok^0Y{wJPWd85`W@kQS8;^Hi+Xi{BIgL2L8OQs zu1XPGH|LHo-+-d%YZN6?#G^CZzF zwyWO}O&`?2=Mn1~TycSR_vNG+#CF-?s_n9MGc9o)2<>KarYNyp7NylL+bq8J`4Di# z?d}w3fg?^dI**PR;dTmtGq8YN0aJ^4jc~-?cDv9K`~Fmq2a0kOqI{7e{f_{!Uk?Fp9Il5yQq`Kt~jD`CJDm`kkkU$r1UCa74k9`_K`!9OkA4iWZck ze32skj;Il={0*L{MpxeeMIm)*29Y9mxGF_#-SrDTZ3jnO?Lbi?MJ!5-BDPuM1xr6d zyPx|~oB@sqpVbK+v8?XmPSCF1ILa5>)$fRB3u~bx?&PY8fAQIE0nH$`%MMp@N zDiqpnvWcR^c3G5GyKJ-gS2iEudBm`2inG8GJuY8FM|`XjRtzX=RJypy5&4a9#N9)O z&=J{Z1mn9}duma>NRfU=bbk5;Nlw3VaeZ(^lQuMiND(_+l_Iw8>y%!3fuhIVDN3Y> zMQKsQHfw+T&TnWp^>B(az!7(Pb;d_FU!DHX!4WxUQoh)(en%7!sEv-OyX$USXt(|< znn7%r9j@9gTld((K`zj)Qy4{w?XoDXcG+fEe>9i|ju?BB;w*5)s1#Sw5rhAxZVME( zFIw8ch6#)L2Q>DuG%hJH_wCKL!jNoTPR9wmqlr{%QmagX60&d#FZ-)XMrQ) z+g(FPylzwfJW!OTU^$Z`3L4>vRs&C=Blb-$iQh1=z=iTfiu60;o5v?4dFP{`YCuuD z1~h|65j$L!BDU^2>pS=_O^yx}B~rwqv?yYm9mw7gzxDi4ABr=;5!Fj|!AG`QwC_1^ zM5i&7FSe`S5tXagMMwOc;+YTHjh{y|i0!h&Roi9jE*;w9AULAZMv4;KWl>t~vd!uo z&2||a5p$m6EO5m0^*7KFm1b1=4vtt@(#7P6LPj`Z)2`F#2#1hURzT6Z8k8?mq~8&j zLO&wOmB$pD0TgX-K{JRHvBOmDaw7aJ~j~I6_cmhyV z&W-X#iu5~T&jaOo#P72nHGrZl9cc!UB6hecMQq&<>zs1}MQ8d^lt>Ya(xQlM_8|Sd zVbJc#aTI5OBfL6vMf+xYoC1FvXX`@B7u(hEi0&8b;q!=#4dd~9sB&$l8N_zk;i~Pj zb+7yylNs6_d6=Tac3G5GyKJ*OwMLx=M>s#CI13z6GRqxw#8jUHRzOj=Le)%;C}M;o zT33q1=MkR!-UNUnPFA3Nks|$$_*+VOKjKaK>qWp3J`HIGks@}uDn)GFX?C?8fTGwA z6eUu`qO>Stn>k)xc@f%8){o*0a73+FiX$4`ujK&khK{9tv0eR+SiQYII-)|mPeY*H z2J>kKv0Zk!YP)RRX5EXnhjvqLq$sgn7NylL+wAl2tYP4YgXbyE0!P@ExrdG@-)BMq zP*gWXEt4aP8sUf>%g&%9CN^>D2^77|PWd85`W=zbUwIxe_jX--ps08$nn9$99j;0d zTX(_qxG;tX&^RKITcJmPe*jQHL8&$?5-*sgv@ z^eOFzj@VxQC;m20j}bJ3*e*LN9aPry@ zj`&)fW)LZ2hpSS=){T$d`Vc7kRh6Pdidd8uMQpR$EvmkRcJno-I0GEv8mc&A=lRb! z;9r2^T_|5{SHC01K2#hro_#aTYkj=HMfA#DvwqRs%(A+#8x4QOpQO?8~G$!adX1(m>HXAIcXg((j0D zR?2&pBaR362a0M2(hMR+>~K|z*t$M-tQ!MGYbH>XND+(DqKIu)BYV%z&~DX56lZ`V z%4hLI`~K;B#tGWZxRvt7cJ(`=@Z<*gJfc`xSNsc0Cy&t#V!P~c)ppssvD07dgm$Z3 zp(wFk7NylL+ib${s@34N#DqR}VizQ6fbwN{b@4 z+0rFba)Tp!T%|Yz9I@J2afIK!V&kCQz?YOSwyWO}rTR2PN7T$U<}I|F@Rw!~+hvEV zw#(MNv10dDaKx>wO_PpEY?no8waYf!y}v>xa74#y6lZ}W9yvclN38ud|0hs1Zb1vv zS|yBdMBQ1+^N8!Oj=BRy-#1adNRfU=+)l5&AMqlS(-WX5{}Gx&q=+4^N)cN(!+@1V zfTGxo6eUu`qO>Stn>CHT^AOt2^@QRKa75$ziX(h$pWO%TzD}Tgv0eR+n3t~vdtdT95lV6}C zvNp)H0w@}}vW@8xENO%z(x$kC&m)3u#-0X>O6;P1ks|$$nDb0|9`R&-yEvd|{YjcZ zq=+4^N)cPPL;QpWKvDD!iV`VeQCbwS%?js^!)J-{FDT9cM`ZY}IAX{BN!HMA&=1NN z+tu%g4f7h|^N6cET~|Z9#qHZB5iYjN4p(iLt$X;aJAQ_$L4Jx7+htK&?Xt~U=B%0k zj)<;9aTYkjea|a&MCGXCVc>{*Q#?$MU@0RU;q9$B;@6o;_`TQ@mr=e*k$y*nu2US* zWopz*plH|*nn9$99j;0dTla=lmb>7H^(QDwq=-dnQN%V&*yO(k+O2$-;tX)a#HQWx z{fNMdo$x2yuisO?*sgv@tSHbJ9pT|p^A@z*#@aK9aIsx>xN5s>-9HH{{Gr{-St&|v zmqlr{%Qm~+#IrXz!lo+4S>T9PDdNx(UD|X`4HUJ!-O=<2mNvo>iKP`s{H)>C68@#> z^Oo{Oiu608;ouKQ^4!cV@Y(3+KQx0#5j$L!BDU_yxOMo7wRcAEq=#Fih(&2p#5N1- zvKc=gQKAUN8Q_TLjTJ|n*}Cp6wEMIo<%{j=cSPt7#SwL1ronaxG@=>AcG=;o?Xq=q zPug@I9Fe*sMTzaQD6MwcW~oO1um(pwA472#IHH`-J9I?jsdI;eBlcYBY=X9o5stWB z`ZB)ONW47u1yB_Cl=4N2^gE*CP~~Tzn+L_OgMVo%f1?>hirC?*6tQ)yep-#+dHcrJ zH|gOPDPmDt6tT?;=6H1o+TEOo;tX)ay|RiU_Fl6+2StoAsD-sy(#3xh2IJ;D~0PiX*C3nG_7|_VA;8 zv0eR+XxOF+I%4(pOFg08)I(_ov0Zk!YP)RRD(OQT9`A3mZZX0QLy94K-t=5M->vPL-K@v7_Sh`aaZZw87ITq$3qNWUXq=X;Be zShu<|{!QTEW;BCH5j$L!BDQYWxRJwvq5{4YB~rwqv?yYm^&J(`4BGuRfZ_~rMC;v( zBVJ#;hkwg&&Sc6L+tu%g#HWfQf^!8=14rapN;8PXGky=%=GHWWND(_+l_Iw8`=_OwfFo}BQItp#i_)TqZRY>{M_F)0 zx1khgfFml0D~>33xFr5%gz>?YFSe`S5w=5`;`4}-0j*rY5q7I+2C-dsxN5s>-NsoD z4uy7a?xHBMT^6O)F57JXl-+*dh$lBF&H_i2TJ{wk@#0+FyDnt>)qI2qxHE$J0U zRQ-GspN*DmMfoB{`Wdn2%K+)yKlrK`G-x1wTD2`}-<(w5z9qK};dbjNUu;*uBLX)z!{-sN zm(A}7?Kay-Gl=c7!&Td5>)suar!us={wzg_?XoDXcG+eNOLZ#-jtF@}aTYjYtKTnl zgjKJ@^MRtB-os3ea5lmbU&9qgOmuN_21lF-pnQ=c{f?+MR&hkKyaD)gjrtR529Y9m zxGF_#-9dAvCj*MIET$-tA{M1Z5!)=y!20i?UDquXXMiIzr&b&>$98c6Xt&%E$`{+! z?})^#&CwA>Qgs~-j;M2yW)RzDhpV>B*0q{+Y7w-X@i9e-?XoDXcG+f|{*-nFM+~zb zo^-nwIO6+(M07;)={HUQMHdH+GUd1!;fOJ(l+R+1^GYZKvDk{G=oSHJ6x3_wr<&qe~$u1Rd-U9ND+(DqKIwwv+)A_-SAu|D9!*!eCVn; zqR_W;-q3F7HOd#;)$fS-C5j`4->#Ai+I4?MGl=c7!&Td5>o#k9>@~D|{VPR@?XoDX zcG+fOl}l#;N36&(I_Y*Ta75iSR@EEZ+u7Qs9?;ddk8jWb&!Edk!4cEE$C+{}7~zOp zWuovs%P%pV&HzP&11MjlNWUZ8{FKi}y!6Sw5-7Snfo2dXVu!0z#MYhl>UmqBC}JT+ zi4?IYEsEG?g_D)v5A8nPL~#ZDN1aYMQOFmHoNZKvH>`vMvC!Cw`+kT`qWK^j;J_s zQEi~8`shifoQg&`;-tq}bVR<7^U8rEcFm=Hks|$$D7rv#MC&KFvH(TLH_!|sMeJ}@ zirBi1SGElRiqapXD3Kx-r9~0jtbtc|{Opta+?do^L z>C1{E0yDY4gLdb}(+py}>~Pg~*}4}Sr=9`r9!oYk>6pZJS(H}0Y_qCG>PCPgUKF7? z3mmb1yfr$adFjpgEhH<)PcyAm$p}YGby2>DYE*o`P@t&wLdq8@((j0%ABrOm*i3W> zifV4A8AOWM;i?qzbu-WG3lv>AOi?05EJ}+aw%P7<)9|mb9gU_q100c1T5*JZiNw6n z?wE&^FSe`S5$!x%;`4|*uKD7j-5Vch2C-dsxN5s>-R4^>;@=JLoP2uHF^TQ6D6Mwc zX0sl4iULQ>EJ|?}IO6s0W zzazdRR~+FGI=?wk)L|mcAX3B*SEY!po7bwxT5v><3?$etP6eX)b$ z3~)_`s&t0b(#CF-?s_n9Mr(7M}4BEZ; zoT9{bS(H}0Y_nze?%0DPoNQ(#-L3_WaDATw9r0}b!s0;Do_cdlIaQ2s#LH&q@wG-3 zziM5<5rf)OzDSXNN0h&#d=}fW-hz_gh-AHJ29Y9mxGF_#-Jzb(n*v3xMpBeW5sT8I zh;0^pWY0)wH*hw^8Q_SJA&Mg&9H=n|+WokO^2K)bJK~;eD|{YdUn9d8Xt&N@nn7%r z9j@9gTld+KHx;4Xv}Y+wY?no8waYe}nr$I|$IPNP6lZ}WsuoFwj@X}bPA{Oy*?FPK z5mk+FM72N4?|p{;Y*Za6s_sVlB1QTgu_p5y{JDlr^nHA-k;a2&5Gi7Zt5U?)t>)Eh zBT!VY7e$E_u_!Hy*k&#h({_h;e~zL!1037 zov+}CDeGwlv0Zk!YP)RRk}=tOK)YA=QH- zz@2;ffTER+mzo^mYJ?-+jZ%K^^L?obyMdya-jpv=q~8&d^IoGPmR0XL1}M7LpJos# zVu!0z#MYe@<`4rEr5aCBB1J4piz2q!%aA9Jh%wA(qFqQrJtlvcZJvl(fo3;{=+ zi>EjX91*?I1|2b>%!f#Dgj3CxCP!2=!V$k)Dvo$+MA zS%tz2a)TqbzN0t`9FgmZEjnV<_`LWTs>DWXOpd5-gd^H5xQOpZ)Z5ksfA%@boAO19 z^gE)*Y{e0=e=oHHifjXD29Y9mxGF_#-KZl)@n4z?6DUfgh(&2p#5UVqp+!OX7hvWh ziZj3w6^|&6c=a+RzS~r33+0RL>UYH3LT&JQ#IK&6mq5F?OX|2wQR?94LCShh`8dVu!0z#MW&+srx9PXxkZz5-DO) zS`@L(#%H{?4chH~m*Na?gu_9_5!J%apM_VFJ>F5i*sgv@MBP*zF{N$c&d_e~Uz$N| zmmRL!E?c*0&K)D6-7Oh6CLNR5E{oD?mu=R z<1wgp2L6!&Td5>&}@N`T^PvEJ#seyDUnpUA9@^x&|KLh{_Eq&H_hl zT$dId5#C|e0idYsvhAivu$B>ysP#qp-SBMdj#dSV9`2xgks|$$=>1%A#GeoD!+@en zCujzdB6hecMQq(?e`mP?MGLP}lt>Ya(xQlMcA$LOQqZpZONukV5$y&m&m$^T3mOmY zZumj@V!Qes@&26Rh~H(p=7n~Pq}h=~xY#Z`T(w=c?)zr}51`#&`6x+Y!f>@&2R z#WpPIn8bEjlvcZJvpKyAEC)xFD@}10IKrt}26V)v_$!ZrqSWv9nbxXfgd=KBQQos0 zT5-iBpvWiv{-k`7BK?l&Qd4<9V(*}zNKyB)G=oSHJ6x3_wrBY|PPi4ucbg6@rhKto{f;=bNpZyIua7u(hEi1??9 zBj#uBir;8FXaUV2w#yDzZI`W^uHDFA;E4A-DN1aYMQOFmHtYB^>q&6L>_-%5fg>(H z%!H0;pZ0AsplDg06Q&!jXM`iB)KMI9Ep^;|plDo2$`>ip?}*ov6-R8%S`WWn{qG=} zL8OQsu1XPG_g>WS0YK59xfCT*#GB8Q=(yx61Q~8;9Hdgmzsc zDPL??zazc}wa3>QZAZLb4gUhPy-zcU?XtsF+hyzS@(xW2?fyxiD6w4@rPVImY{8d< z<-ie>ikwWkT?-shqI?!~L~iFc%YdQ+-e*iX^^I_ZZzbimMw$2tVL(yd!IUpjq~8%s zyS~DI?Z!MQg3luk&7>JbirC?*6tQ*J#ihc}M@-pBQ6fbwN{b@4+2yL?N1$Ej2#Pbn z5z(I&M;uLcb_2A#@;2p*?do^L(I~|c3zja&PukD?NHd7-vcpx|W$Q*Ab*To92)8?% zbWCEqEJ~|gwpp5WlP-cIDpsX93mg$SB`Z3@CG)iDKv9d07ffrp8R3Y7@0IVN>b81f z1)#|B0_BSo>377ieu^V1d#vaL|I$2&rx`?w*x{-av2|OgY_SR`TA4XI>ERYBVo_QY zvCV3R9>Q-B8eECu3~ zZD52W8g5d)hpO%M=)piyUN6cQDbnwVaj%rmS?+9e(gP@JGmvHwDPo7KQpDDM^7wB{ zaKx%P6eUu`qO>StoAu~b3I9^#uN@R;fFs7eR2<=DJ@7rWd+i+Mi|y)nM8Um^Bj#WC zs0Z!#eMU2g?XtsF+hyy%D3E<2wCn$eqQrJtlvcZJvm3EjZ^QG5TIH`L-L3_W2&j|; z9Z|%oW^Zsr=KV3IoQ6g?BI1bhTBDv#bWfnD&t=LNDbnu6rH!emGp3n6tO5Rir8j*?>4~ip=yzr;tX)a`!vdXmgm;(i-mTr zDpJ1Ku6{@CEbNKTBNn*)#D4*vHKQ5CcG=;o?Xq>>T&ed6+D+_EQDVC+N~>MA+57y~ zDZmlk7Eqi8j_4km6CJU7i~S&Q#Py8#P0%(n!V#6bDz7z8$Ata>ii($}e32skjwltU zJddb*u4W!^#A`R2L8OQsu1XPG*Kb7*{C4#lT_{SVh(&2p#5T*ED|{lfdtemB8Q=)J zEQ%w(h77QQb|V&3zSypQMMoi=Y?mFb+AdqyKRnY-a74v(6eYIH zqO{s&o9)~Cb1^t#%~y)Ez!5>#xzQ0G4wdQxMV$*hF*%~K5sp~$SNV>a4!)C|fTEg} zDPN>Wzaut(QNBN7e22JGKvBBpG=oSHJ6x3_w(g>xy{`a8L;NU8q=-dnQN%X$+PMS2 zKf-<_#Tnp;dykdZ8cpmLtcG^$%%^;@UHy)D8Ll{@w#OwqXm@@n%^t?`za=xIY3YDzt@W5Gi7Zt5U?)o!d6+K5)c>qZB1l z#GhPEWT1+Vx8PBI%gKc3G5GyKJ-aDSz02Bce-EoCS_pvnww;VtwM3 z??6%J{jW`HH8H{wn+u-C-}^io(h@(5op7G=MT+!0BCNCG2;X|64+BN@?$Zn+MeJ}@ zirBh?D$F`^yZ?5h>bm#7D9^pQ?1r%l2_0B|5QzIOad`KiZVol7{YVa>j)=0`1DbnwVuS??a z^AUIBM<)Y{cEr#OB1P!`PD_QT*(jW#9<^GcJ zztPy~9mN^oi02=a=Mm?cRK&mc`TGy$i|y)n#GRC0_*x^~PhS^kcVUK4Nra2-vcpx| zW$WgDxz!QcJy@8c#CBPfR=aGo#2S}2f+MEYr#K57QFL!Xbi{>0w}ZhE#U_6-J%Y`R za73j`r_d4ZBfV>aBfc)7e32skjuRzdd7n|f*sgv@JnE}B!Y*6*acFn{ zSDHa=mmRL!E?ak7gWC9w#sh7?CLNR5E{oD?mu3Ria+ z4irTW`(awEg%OUZa87xxaqeM#{5G@sGbvxBNWUZ2x+{)Y`Xev|D5|`MW)LZ2hpSS= z)(za`a337eXAeb*6tO5Rir8izf41Uhu@|4FI0GE<^{nzdqDr1v{B4|aw<%w2SHB}R z9a9`Jdj5#M(C(YpG=tbKJ6yG0wr=nc+c0Q%`!9+T+htK&?Xt}rqBd3sN0cb|GwF6M zaD?^hBIpQ*yax(^BYbBhnsQni;fVEhl%H#K>h}PDGqB4l$`>ip?})d%l%IVr^Qdwb zD9W>sW)LZ2hpSS=)~(ii##W%{_gRV(DPmDt6tT^|q%E8m+P!|4;tX)a>RpN>KKR~0 z3eO`(zN37xUHy(2>D&=tYb=Usho6wU^p|E3+hvEVw#(KXQTk#%Xg5=)KS{?Vw#%Zl z+GU&ld_T+y95K5R#aZBp@rgyz5l*M3j0TFLW+dw#c;R;K46TfCMCN?T-|1>lW5olY z==Lhg7b(*3h%%)WM>rlD^b{Q77Dh9O6tTlqDPrs1N#6{AH{9_wMTr!#C@qTEW|6D5 zrGs`a-=a7J9C0^Pal}-2yXnwwjW?7pwyWO}g*+8U^gUYN724hYn`RK(WrwS_%hqjD zq!zx`_?X^0>6pZJS(H}0Y_kfdFZ=>WBsx=^1&#>pR16()Vc%JNHacQLO4C}cjc~-n z^vcgZzu%hD04VZWMEN2``W@j?KzXeZoqrtu-skcyG=oSHJ6x3_w(cOuYB}Ivn#7|N zB~rwqv?yYm#n%6Z-&ObIGQ}C-i1+OkM>G!1g6+n{Qoh)(en*UtR2(rj{P!7f#E>sE zgV-)RT(w=c?u;oVi$S}SY*Hm1lh`hc(rTA&_Gj0MEZ~Uxr76w=M;yLX939anM@#&i zrN=y5(^_qea72wJ5%`{Ea+mA}z!8qyDPN>Wza!E#RsNQrZM8`Jd!HxH(F`I*>~K|z z*t!GV>rDoVPCle4ks=nQMG@Pq$&&&28LBHED9!*!#7|NjF)D25Y-o3Ja=RqD#CG*N zVqIo$e610C`Wk+JM9Zu+gV-)RT(w=c?!C_4@uyaQ94Ja`mqlr{%Qib4c?`c}=4>O1 zv%nGMYL!Gs46F14zpJj=gtVp>+Zy4BmHCdLBMvOAjo(7Da}ni>6zO+FMjPdC0+;Te z1;5YIb_>lQQp65drHHLtVc0WYaKwTLiV`VeQCbwS&4yhL90jj6=3b{b103;uv*HN9 zZcEOABYr)ne6d~qj&R?iIKt*b&dcyTV#arxL2Q>DuG%hJ_sP?0_&lPMeY&J$65C}_ zTJ5sUdiFc%56>g+m!&uh9I<;!DRji$tV?`>qDHGTn$~J(gd<9MDvsFlaAP7+^f!$1 zMT+!0!YhN~h&Br@F9eG6ou(N?irC?*6tQ(}5`*z)pI>fKlt>Ya(xQlM=Il@v{{>j| zhT;rx#F|HnBdT5+*csYA`J3{^cJ(`=*B8YRd+gl`LAzbjXG$VmY?mFb+Ado+nNO`U z@Gn50f)pjT%c8W}Wt+J-Sg`~g5mKMxEO5lNU!~CzJ3pj#21jK4o7MCPwl~5N+vgs| z=Mg7{*wh1x#^=kHlrK`G-w}ImDvn5WD4P-}+EtBa5Gi7Zt5U?)J-=u){@w5_UKAx# z#G6jhby*QNO3~BX>s}-PfA2Ho1I1b3hzDaF(GlM&+BE`- zKDy;H-Kd8VjtKWs9I^aEcm|*-MF+|kDbnwV+kX{DJnLB;fA6zpADTg=h#js<5nK0I z>oZS)qM@THN~DNIX;H*Bb1R)`8nkVlomy7vx!;Gxj?&7!4zkJBL*B+UTcisyu}&XZ5l%P zV!Qes@npZ^h^b?P@iSCKchd}FyXS_l-Mqd(rTA&*8ESyZ?5h>bkr9 z6i0mMz5F~lVpTrM7u)@}e67dek98+}tx7CD$G@-o5^MY|lv_apjjtBAkT zwQURKixla1M5at1@b^9^XWFt0D9U}5W)LZ2hpSS=*1dG_Za$!B(j|%#DPmDt6tT@( zefo{xd0XiT#ToECqIprp5&a%Vc!MKC6DVJ7SHB~!`6!O?ZV{ao+AWc)SQ6o4yXSNPB64X-(<9i? z2uIv4x*r`e=V8q*KvC>g$`>ip?}&p5AJGvNx2|0Q6m>sNGl&$i!&NC_>xLgFoF6F4 zbA_Tridd8uMQpQPfoU2;yYWvb&HzW)3|Abn-m3aWXt(rd$`{+!?}!gm6i4K>FJ=wx zcCsmzM7Y>4J6yG0wr=v#!)HOepNdhG*e;9GYL{*16F#{WIAXUy#aZBpt*&5&H_io$5ci~>|M0`K2Y@fP(>58os4iq`c8@?zSM2E1t@BNiSk8? z^gF_Pvf_wM`wpB0io9cK29Y9mxGF_#-Ho1YuYx0PeWfUoA{M1Z5!);wa6@%yH`2D! zKehXBH>$4tV7B6jmN`zPhjz2(p?tC3f6Lc;47@xQN37~U1wUu$QjTU2+hvFQKi5q* zr(Y&$H>3_liS4qef7;A@wZlhv9+AHX#aZBpKFzD5BZ^hpodqcR8ei2!QD-9@aj}=; zh=E(IG6O|=b#xxirC?*6tQ(zzBxP{C~_%9Q6fbw zN{b@4SxAJ_0%*5tb&50Kc|?gZiX(2e+Vnv0eR+n7vJL#O0kf!O(8*t~7(# zE<0ScUAAtCg`bi^yXOZ|l-Mqd(rTA&_PKbkYv72GB@}0YBThYYMMtEp_I)r=^zmj5 z(~bHX;RxsViX-fOw|4`ITEC`zks|$$7`sGy&vN*Iwq1cD+ut;UND(_+l_IuoySOtM zfTHT@Y9>A0B1J4piz2q!mip`0Lc2K%Qk(&fSi4PeL;>e)w$Sb&XUZ4b)$fR9FBL~T zdUE|YwEMF@%^l8<{sFdyz zwEH_R<%{k9TfWv~FuR~Hz8?{OBGmMAnPS^N8hLVln|m86zoQq)5Lb zs@f^fBbJVQa}X%Vlomy7v$EIH<2%y%ep8$Q z&m*ixD316W9EgAK^M2X}Npy+r>UV^7fZ~YS`GR7h-Pl4jgV-)RT(w=c?u*CAmO;Dg zT_{Rymqlr{%QkE1GN(B>VwDHQS>T9qLAB5kWjdyD1xK7&*VxozHzOQzwNV&8kLb8+ zMGQFN)PBkrDbnwVV`Y{1Bl1rkdle|kaGqumDPo7KQpDDcY1)1dP~>@!qC|>Vlomy7 zvxyEVGDEx3?MakI3jJMW$&Qf*ktZWbcyZicf`j?#Sz^K$F72Q7i6Uw#CF-? zs_n9M^LMI&?^zx%M^R$CEJ~|gw%MFk^YLe&pL10mTtNoR5tLN33Z|`C_~J9kC)s7ksTz zJ%iODX!o5j%^Vlomy7v!^vW;%kj7J``twBl6tqj*skhw?=88-SL5x zFSe`S5!)OUM@%`IY7Vq}djicMw#yDzZI`WEHl_mp6}HriC`xRXMQOFmHhVYeR15_9jR4Fv1b<6SkovGKXyb2oxPIPx&H6`W=yF(N`q7 z@%J+KfTEf8X$FxZcDO1>e8gjaiZj3wPp&DB zShW4}R%mz82+9}R)$fQsK8hpU#~j6*g!mr2(`%Wi3UC?XoDX zcG+gZ4|3!IM~psAaTYk@N^duGMBZL^0^oVXpj2KaNAxtp5yAJjpd-3H%!{AskIO~* zB1QTgQMk=_bc9Ft6Y0PaU&_!7B1PW1iu)8~ug`w1mt`#U>Y*)V{mfThxQKxNKYH&pU1~h}% zE<0ScUAAs1r@XbG-2@Mc65C}_TJ5sU#viVT-$Ug!isCGAM6X4S&=Di+RO$f#(gYOk zYJ#?x5snxZz8)R%cucE)Kv9dzlrK`G-w~s)|3pW;D^+GJP;{>;%^*_54p*g!t$X~; zhYCQ^jZPFLQpBRPC}Nv=THPE1?Ro@JoB@v5uD;f&ekXnzw3}%n<%{j=cf^#6UGY83 z7q$KH`y(Qk&~Pg~*}8XW(GMufVc)~#h~7px;@Iak=!l5)O>P54Hu)%Dq)5Lb-VOPUj_6ci9eywNh;lT8 zND(_+l_Iw8s0>qWfTGAc6eUu`qO>Stn;i~qgWqRas4c}A;D~pT%KH&f!EFPe-LM{% zFSe`S5%w(=M|fv?egpmm_&bbd5Zh&ktG3J5{b1ud8`^cAK~ZA6EJ~|gw%N7CF?GNZ zTX#~N1&;W>p$R%7P3n#KJR()*-X=%%F~Sk$+pk7P?E5k{5-4(WpnQ=c{f=mJEfF12 zVoRYOKvBmkG=oSHJ6x3_w(g4NsqpV>{BWlzks=nQMG@O9>;6U9Zio-X8Q_S3n~Edu ze}0dje%TvH`C_~J9pO1qaYW-LBkTOi^OHEJ~|g zw%N1Tx3|C%D-Tng1&;7(*bE)fwncOycpee)rk}|XeT{HLV6PB##H|%e%7Y_<5-DG# zNWUW{7W<2i=$LhXA~@oH`u<6efk+WMT$LiWZs{YV76C;)3sICv5sT8Ih;7!OZz}wb znUgLQXMiKxMktQh_vAbN)as)f<%{j=cf^oWiX)Cx{2c`CcJ`zh#CF-?s_n9MKgN`N z1?|r1O;KXIEJ~|gwpoMB<6na#PRyb>3moD0wmCYYc-yywz!4r%L8klYXM`ip?OTD4 zC|;oQT5v?lhmwBFE$dk{)i6 zA{M1Z5!ZAMXIyDUnpUA9?Vz38vti0=UuXMrOcb#94{m@;}hes_NG z$-yRQ`y1hi;;$4(%$z#DEI6V|4CRXy>378c{e}-xw0BVl{2M$8uV@C5B6hecMQq*G z8!LMOMg4wJlt>Ya(xQlMR{Z>dDd32%>4yAMyZ?5h>bj2V`w>S1*NlgDPZywkvE6^m z*Ln;-yDN_PnWwNXIKtVPW)RzDhxDvr3dY0^7rcU4}RL2Q>DuG%hJ*L`lw@z8E2CyEl=Wl>t~vdu~? z>J<%+c-flbEO11fur}z3hPOUH1d84*8*OSa&kbr6h@crnirC?*6tQ)$`FzX^6j@)VD3Kx-r9~0jEHanpJ!rSvbBZ&- z5e<7Qju>Kf2mg9Xz3-GSwyWO}laDEmcoY%z4BBmGHztX2v0Zk!YP)P*p9cMxL%Xhd zC`xRXMQOFmHk(*A8oy)aU`>j%z!80$v_nT^-tDj*C`vJNyy+1PGQtsd&z7Jg`X?5} z@2b1MitGA+YyCW$|q=-dnQN%Xu zkjJS7v^(b(#Tnp;=W`TCWDX540{;TUzNUP!UHy(Y`b2R=$9e~Pg~ z*}CgzZzvA!hNYX3bWCEqEJ~|gwwYsrb#vf(L|JEwv%nD>-nK_a6sy#@A5iqY_hi#r z1B`G){g#UqM_g#U1Skp}P5B~4`W+EnBDvy-r5Ev&crWJA3?fDBa8-)fy32<w2oe6!Q-3R+9&HzW`JfS!uWbGGwXxHW(<%{j=cf`W1e%Nl?^Oy6& zzX0X#(hOp|>~Pg~*}7Tx_FW3?4t+~eV!JF#t6jF)s=~A1gCl-qoRW0A7C0hyxFp=#Su@d{1^i5PK==$#CF-?s_n9MA3mRv8rog-nxe#ZS(H}0Y_sI;<0^q8&ZP-X zx?Kw#QLMBVI^ucGrA2_EHf?8_at0aUhy&#nM=ZbaDmD7vivcis8!v0CPxf5!VwpO6i0X_vmOZ)eQ!(oB1QTg zak`A+h&x$6;a{I`*^_1vDPo7KQpDCBGQaLlplIN5iV`VeQCbwS%_=-Q-XGdMF@xd^ zaKxz9iX&E4a6bU;c34gMV!QesacPO-h$-`~ZG(RSvh1Z9#CF-?s_n9M-``lB2<^I_ zp(wFk7NylL+pNi{mMOpyC0ruW)k$y+Cv{4+fd7%%!Vx85VW)LZ2hpSS=)~#Lm&LyDevOh(M6tO5Rir8lU zZdp@;Bb-K3oB@t#x#4NAG-9XXa{L4&^7;1zg z`sY}Tj(FAF9iNT9El>F(Mfx2Pw@`UMqC}@Ve}STD^=Sr?B6hecMQq)d*+;bkil%!| zlt>Ya(xQlMmM*e!G_;$q55*bah#mD6N4O5?z7qZgSUQ^W#dh^OBKoc3h{EY_9fNk` z=gMASp)Aj>%kG%&QP2Mj@U5E7afr<>Qy$N zsB)GNlOu*1;fM!8%FjN_r9U(ZC@NBn@av=UTPAPwi65C}_TJ5sUzD<4U z2hSsN&Z0OA98oN)8#=;&!Sbr$h&lH+nC@eQ5so->P;o?^rC(M6MOQvhzDSXNM>K4y zI3jWVo9#eR$>bZ89s`jgcDO1d4)yRmZ|nV_8AOWM;i?p|bywEi-xDbMV;7qAaElbNC@qTE zW(N+Ydk5_<&PQBXdt3WNFg%aQFqGmfa75-jJ<$;j4&^Ei6g~a5-309@ zBOKA~j`}-YIaA?x%=AycBPm~`NWUYJ?NokWqhGgIzu;e*iUnx~ks@}uDn)GFkjgXg zbC%!BQ-7Mf&X@6+~A`C_~J9Z@k&4}3pj z^P1g-q1|NuG=tbKJ6yG0w(f=Jp|0>Rz}DduCAQ0=wAy8xJy_&%9~`kTgyJl4M9UTa z=!g^BU1kGCRa1tUZgjK}jz|@xe8)_ob#p%eMQL+TzDSXNNBnVA95E-|u8cs@^O7`! zND(_+l_Iw8%};K(fFj506eUu`qO>Stn*|=3H38bq)STiBa73DHiX-~`-s}(Up6g8c zV!QesQQbpv#LEZyT%q0h184@ZU3R!?yKLQkXQDSlyIm$zl-Mqd(rTA&mg-OrdvHYg ztrTa0BVIS@jgDAv^Pm?{bRo-rlOx6$;fQ;ER^rb-D>)8n4HQKdqkNGf{f>BWOL0V% zS09zf(sza@hIDwbHAZQtLH{|#~e;*Z(3-o4C2h#;}sRY774mu=SW zQ0M=$iWfX{*Y?#!bCyUF%hDo=?bi9>`D@Uy^=fmT0iwuTOnEXfZ05I<(D2H`<^jZp z^_wE^1;rFUyN{>=4Oh8o9ztxG-LKj(Te$wl_y}nDNxV5rY?x(fHOzMFbmQ?y&;N*; zp4V@`?T+F{=!PwjMZ>NAP!?7nq7DE`Pg@-~1&uRA773-4cP5_2PudMA{qQpnAflvS z7WdmLZ(r7OvnmQG#SS$OA)>?%SVf5~oVsD;A3(`F*qkMz#Im$dV!OGG-FFWf9=Xz- zXMili3oEkNKC)t7Xn4~u^8jMQ`eotsMv;Z@-oGKx@U4^PA;gB+0jmwOg+J^bR2Ujg z6=Tj48)jKr4YS?moi20&WU=IjInM%FY%LIgvN)Kw`f@<2i~mWJEXErmi+*dC~w6j_WaUcentI7Moy*ERNJuelF_LJp2=&l;^E^01+kqvRGC_`S3)>c^wA;O71Dn(xV`v#12?R zi7ouF;J#OYQj0w1ED8S?-l zO8R9H9;(P9tzGrbfKry%<{?Cs*a533v4tnutEK3U|w%fz%9lfAo z_q^sj17z`Nw<3#H-i;EV;Y!Zt0mO#&%Ob;BMHYdRhQ5M^?>96LAvVkoSZ$asd|*S! zCuq2ak2y7CmSM*UR{)5 z7tNSHO(8&OSU&RrB1-yYQCa=oi3N4MtpTMyLmeYDJjyERaS07DG`M(Q&;G14^}W z+%d^wiXpNXwq1EwDvF$AflvS7Ohe#vPj(}<^`a1 zDZo60h!Q(s6(zRt;`*no0i~4F%vmBzEK3U|wwwR6mx0jmfVJj417tC2t0IeGlkV(- zhUXkH4-&|P;zbk+Jx?OLu4_+eii;S zWK3AlG(hQdFY^E*O8RAyH>DzrCPntl0+dcpG7ll5#12?Ri7g!J*V+|OYP8avC8ET# zv`}KZH7gvq4H{m%*PLg7EPixUWKlPx%Qa{?A<8^}*sy+C{MoC>B3XrtccI~wPs~Gz z4YLDQ8)ggV2+y|#8b1EboFz8Qva}jzyPYi6Cnw0FYN0oD!xqRQWx6pai)K0MB4NziD9svX&Js~#Sz0Ku-F9>eiG+q%&ot*5@XR8=i}K8( zoA22uXn4dr^8jMQ`eo7Vry`4MVDPI|r%WKr&eInM%FyeK#hWl{N@^-w_RUcav7+ep#%m-V1*ka=wJsc#uW2kLDr7hS>qD4YP%# zJ55{x4ZGQV`~PY?@9&%sFOE|)cI{DunlUOyQG3*^rV_KZgea+qO;Mx~JA>H7iWrH# z8i^f3tQZwDMO7rWsu<<_!*kAa&->obxnJk=oX=nIzBljJedUuU$@AE6N^MwV88s|+ zdmOcPD9EC6Ey{C17VRH1Srj_`OEjX?{he*G`Ig9{;!Y-uaZ3X6<*%%MG=Pedd0EW# zVzQV%=1K)XDJ77GP*D;G%ux~x58SnI0icv?6=kU?i7X?O#BT1{W2!^LTXs>N1+ut$ z+6&(uwCH1t_^Sp#fBs%*(>%9+Sm|-SHlPQrj*xgo=_lV2+YlxcBN7g-{klDN993WEr6( zc3Yiy@*`-t{Zz`cKoM$Rk@$l09FRrw41bix3IDf40HsXvS#7ciwnP?F zW7w}wE4+iG?qfO2@ymc>jU2 zRFp)P5lUjW`<-$XfQFq5W&5;-KkZie!a4q6ve?r)Xe-F#cx4(uZTQm$F#0NZoMf_C z8*}bFG(4se4WTwH4*35rTz=GFE#TWhXE(}H8x~ogw3|zwDz1gZU@`v(Eut+=4BCCkI7V&RytXTO7nH+@A}YQrMSs9~{N^`&=RK^EaX zDbE2}OsOA$vZ(LeCk{~R**TxB$xusV(JPI;X3?tM*PQ{SUw@(jRFuriBI+>vF=SSm zUoHSj6{gYDYC`(02WEr6(b~|-7v48zuaJHi~fZDKmSv;sV3}4`Mo?8L`RWR`?4WTwH4wyGA77l6L={+>O>k(zC4T~(J zhQ)60-)C(IvZzx$zx{?CkVS>OGf);czOC^cptL1NAzRP_OJuQVFOx;1e2WhQN)t=d z04hr6Wf5?d$)e!A)oVZ&jqA`5DoWyjIZ9&Tt4Wi80+epHqbwCAk!6IE*llo=F#H$w zCIczY0$EJh$7Hb~sTIB|)p8;Ypf+q?7L~o3EE)ult_=-G1=A2}!{UH>!(!o4RYOr0 zbv96z+OWtnYFO;{h&sq z&k1A^@{|TpQ8F)!6HnQXAvK1)SO6$_WGim}DyS%l1Li1+g>UtA4+L3c`hv1llth*h zN@BOAKfJ3A4X>y}c^1gx`Cm*HPx7QWL&LSZ(g141=4BB#o5{i{f1^-nc)$o6LTy+a zFmG5aJmzqGZD=?mkh0WzGiW(cR0Q()jd~vJLhV{;(&R>V&Q!*ammnds551$4T~(JhQ)3N2j_1J zvIuKOc@D^8O1D`ki|_8t8UrXr6sctUA}+Q>79Em8Q5K=z-{ZfiySvZ;DoW;Makx)b zL}^;lg zvhdAXdlblG$V3`IZP>gl{&Qur7&`D^Eok`kJQ_l6SR62KSS(!i*&zJY>6_J*r8X?G zj2afZd3x2$53+a~Pk9c=qUATUQ5Jt?`tC8HbpC*gO%_Wmk;Q_GAt(#qGvzV>CHJc| zfQpiNS=jR};cHY~D?8Wy|lZ+4~u$fD|2%5y*#Z*t8+S)7^U5&!(!nJUE7z3hNm~6EVW^gWz?|PZD_?=D2s*Ol;?mf>cq~)CyOFw zXUqYVvNmjFYjU|IvbYh-o-9VxeKQnL%F>SpP*E~3i+}^{$s*IK%8vl0Y!Nhsijp{B zj*?io`)9%30j1B6Q=x0ca#LtH=RL}^Ko$!YFj2fstYK6SB!>GQ4$BtQ4$LWkIsAoP?}nmvQ(5r zmJv!~x0+EW{h{H~jVaFpS$LLbvhXPSJ{)8*)QtvE8#XVCt(AYqSEbx%?rZ=JPZ~%= zs11t)<_(L5pEjA(5E{NcnzGb}MV3*+Vz)MrcLakhE-#@x2V}ACJ(I=y>n)A~O74|9 z*={x55?P#g2}4yev9yV6s>rup$pMd~`Mqp*AcIm^UmI9#!XNerVWp1!buXi!7st#csae6~rGy zvK^s32V_wqBm`yA=bHx40Hr2*y4qy1#u8bCwqj2fRd+lq2PkLx;GcWDx27x=C6Q%>lGv@G|2uql?+4u|&jMMjsLq}& zLT>Ha2n|OMp#ju}&CBA~^Gp^wH)U~yhC_a#A=HM&0rQ5%!Xy7E_7P;!c0OgP4T~(J zhQ)3LU){go=_lV2+Yl_}zsamjIz^E{~n4ac;n0n~=g%OckUCX1HtjrKyr-FwpzYQy4ydBbAi#B$a5 zLBq{_DNAiwWEnLqb}RPk<2aDT?oi5eKo*@{7N9I%g#~m2SvV*6w%zJFOJuQpE|bN| zVj~6tO1aZ%02L+kvbbBCJz0zm*|7{z>iHiHp`s)Xn4=^XZgsQ3IY4Q1{yz4vxQdd< zGD1o0_P*An70~ePa+GI*EJEL~A43+d{-!T9T&FG#pf+q?7E>z?#}_z@=evp@1(3ZR z4WTwH4wyGA7QWE<&6m*dm7bKPHY~D?8Wy{C`s+y}kj2AEl;?mfUf*G|h>Z=!Pr~%S z+24lldP`*ST?O_j>WA)S+y<09pV9y-O6Fy8a1nd5aQd^;7LbKU)&cgff{KzjV2+Yl zIOpZ<%>bomMJY=~Nn{zJBzEhWnlKt<;p;+q7Rch4CrlPOc9u?rh7UKU0n~=g%Ob20 zlg0JvSEfP3PHr@W+ORla-mqBsrPK4G&~Wtul%+N-vWyxQyA}QR(rJ*zbAQTnKo*<# zF2pB`$!V#l0i}VlUbZudutXLkaxz(TJ<=)}P|AOS22fElFN@+!nJirVoazHg)9=y{ zDoWyjIZ9&T_%TNk0i}q4C`(02WEr6(cH2|q;d*FzRgOWQ*6^p@Dqr}{GbW2VNuQmA zhF6rN0n~;+Z2+UMLXo~q7Kt-Pb%Tbp*PtQPhQ$H@--TZ`Iqn7xpK3~3YQrMylXly? zwp~7u#V}9Gb3hi0gThc2S+exSPb90ga)=G34VK8_btm>?NW_1`Hvmdkw$lJAO6FzJ zu^{^~KvYlf@ScT&6+8LGNh*wPEwJ7(ar^BEI+9I?(X2d_UPaR~r@w%o`R9FY6lm2pTR> zma^1_MV3*+Vz<))p}RpAKCLLv0aCG)a~%EkVX?E1>>k$}>|S2To*k~m zlGyF14GBx3;d`Yh&jMK-U&~~%WZnC@(D2F{G=SQ$d0Dhx&tx%Tb@8^)utzf*LTy+a zFmG5ae7#-@ej?c(56V&-7Fk9Oi{0vn-}we)QF{#KIUtMj1s9_%!cQbD1C)wg8ev0s zqb0KNj}5{<%34=5 zVEk9X!!2nDwPA6xB8whd=A$gG-%i8d!pDC$#y)_Gl6hI=>YN>4D=+y?mQf&!&P8Yl z6(w=N93`=E)2TrXKo$X&DN993WEr6(c54!xzc(~I;Ty`cKo-3QFj-W~+k6##I~d-H z22dL|FN+CTeX-%4EA!&p>gDf8L#Pdl1Lh5jg%72?n+XlS_oXbgVUcCju-I*%&%vr7 zi>MIFb3hj5)-S;)i@h(Gw*!=Rem=o=tD7y6h1bG)D2pRMhb#t^?o_4$RFuriqQMg; zi$UXyUjtc`Yf3|?D2W5+D2auy6iqk?DAnpdr+T#R2n%#lruNAAqk)E!ap|YQrMS zs9~{Nj<*#uKo*D3QJw>`IOew$WwGkqnhk)`zY{0hWU<8(SxhRyWYO2FMLj?%V;&8l zqGVncrRwFt?>nWBSHa(g3|vh^s3?g8<|v7U!|#5q1hUAzi?URdM3xasVz)DqJ7+_~ z3*sry0$FtF#AI>4=Gx`ZaH(V(KyBE(ERL6EvbZ>J&jfG$>Pm@fBaO5z(^WGMM)emM@cL^Idipd0i_SWQ^7s(>RTX-cV{Ti0$GGqVY297<{G{intuunpf+q?7FpexEQ%Fw5(Toz|AK~4 z8x{x58x{-ad%md+G#s0Cy8WiqhDDZ9!(z7%Kiv5hWKp3C0S?mrQegYbH`alDy4V#xm!Wbrt zx~Y}@q2ZMUXV^Jc8x{x58x{*ETxwVr8lF~>vebq}mQllEw<*I~o&#ANXh(St$l};( zCX0k7#d`rtZzs*NeG#`>B8x_T?8#!yVV`P%(#0SeKt;*CEHdh|CyV#vL-4mD|E-}R zRFuR4bCkrw{+*fz0ZL`}P?n04$TC7n>=xR)LmOx~=p^M?AdB7ZOcvh#tG0rM4_>1I z)P~K=qS!_zi=tr_Yl1A&(rE~_VR68`VX<)A)T&3I;Xgi5mfEn$GHO`t7Lqj_KfW-w z+-&;|J0OdIxhwF=A~5%jBY;x)xOujqZI;NQ(&O3qW61ASqw!zV|Cvn#s3@72#oah2 ziyxzo-UF1vR?-kEO5%VyN@8KxgTWmErPtdiOGQa!8KES0EA+12P-uAJQOdJG7M^vO zEWGMZ#@8&yU!eiihRw^OXd;tE)qv3pq2Z3HG=$o)IAGqeSU9DUYc^;&76=vrcP{ zpaE2r%**0t@tpVqXP!Z$O9D!Dr_&HBO5%VyN@C%iKVHO#)HVw#OGQa!8KES0YtXwO z{%^>}4U}hrESw$>#P_qPawE1PJXsvuPXnk8o0rA)(j&0pb0fn}L&JZcrXkdZ#R2n% z#lqR&<~|Iv$b5^k)P_ZtQNv=lJvGv{fh^8_q&x>?F`)D+ltrGOjvohERB{iq$zq2k zvZz#$Jy|3^_IeH|?e(GoRFuriqHj8TvY2^ebs0b@X)Fz)q9hKOqa+rt6X@>=D2<#& zSt?2*%Lpa0+nmGR)u7>d%PG$SSsdiDh)lj(2pXOoO#`S6o0rAi7EBiX2lqb*4S#iv zhEN+82h1B53oi>#iGhZ_uTYlSu*foMSnSp<&E*8hqGSf;IUtLOG$xCLr5TL@rRQEt zZL-*Di7c)ZVzTh;;WZvn8b<@DD4CbV==Dq%6>~&H14=7q(GV(1;($3yV&NQ_b`=AZ zl9yAKijv4OLP_j)a`41)(D2i(lxKk~DqLny79Tw>t%ZgQ9-#r$hRw_3xEGVfmbV$- zLBsnl(GY6G;(&R>V&M^M9`=BS)9+K3+OWtnYFO;{XZ^xkKo(naF0oEIg*(Q~ckMe1Vjuq9n46P!hXUdpEfX$m0GI%CkTgPcyUEECv@$ngR`V&MZ#BMX5n>LpQ@+OWtnYFO;nHE;jvAd5f$ zp*#m<(Z_c+%3{msBfbQb7B^mFlf`aJWbx>;nfRK;qpNB7?%t=}XaE%@^Rg&gioIqr z;c4clfYNWCG=z$hIAD&FSop#c^1ebA(cH@ zl+F}i7i3XuB@Li9Y+e@ME@iT~H)_OuXn6k)8bWPY958QKEL{B2#+}gc;&{qZ8x~nc z4U63xo-0}pWN|8$@*I#we8n{=iw_-E;ipQ3w2ZLHVvi-VIJSQV%A)3wLFs^!Uk@5U zMajG@&P6a;xCK?lA4B>Kqajq3!~t`Z#KPH96PE)@pG~1G6(x~ngp$~8OGHup@1JtP zlxKk~vZpXvyeZWQ-`=RfIvPN2*t{$*>}9g}uyx@8kVV5iG=$o)IAGqeSh&)>XVsx$ zmy?vGHY~D?8Wy|FY~!;CWD$@?c@D^;XBv}5nL&H-!|l#2+GLZ(UQ1*Vmd<2xeDPoS z;dXO2(Eut+=4Fu_&15k#`Sw0Qsd_98p`s)Xn4=^XevmY(D4>*fjv~m&J<;e)y}?qQB-^ z4c`u?-=QJYhQ$H%hQ-1|e7y!h!v|hamfEn$GHO`t_HtdNcOZ*Pg}2&o*a2De7`YB* z;nwJUEs#a|kvnWb`z?`$Yj*ZzF+a$64xlt;E)AffWL_4#l9(+1dD9hT(P#q=p`s)X zn4=^X{`%rbe9hwIe#%l&5?MwliQP699{ms+ZkkAW7RbV9Gn2*r5h0bK;T5-N0JUNB zvhZ)qWD(f1(;JXQ-&Zt*+ORla-mqABXGr)QkcC%{o%Wkj8x~nc4U66UuH+j5vS?C` z@*I$bOTG0di*aQV_5w=trtYyV_PZsrcKz2Xfc(BP*D;G%ux~xFMBdP6u$3NT}W9fN+Qb$C9zwZZo%h37V9@q zo&~Z5@_i^BWwtr znt;*|el&oJl6hIQ2x78GSRRBZrTWtlDoWyjIZ9&T-;Z`33n;lQqAV39k!6IE*sWZt zCiOrTahoX50$G%u$Ye3?<@!g^@YVw~fZDKmS*(a=vIugSfln6e&e9NS!{UH>!(!p+ zo)>FF!*fz7OKn(W88s|+3m-afGst2_mV@>ic0d-jf7^hvSX6dvSwJaMmm{{ISW9H_ zRkAe3NrU6ux%*$eI7?VYj7CD!|_nnFpXb2T0aljlUvGB&X-W36*j5(C0 zq9n46P!hX6yK*`e8qU6o@+^?Wl3`31F|MJ1fh=BbqXE>0&C8o7;u*foMSnSq1Uz2Mfi@L8V&jDEssuPK_XmN2Rer||w z`*@oy;w+KHFNo z>NIvm_A!8x-&PtzMM)emM@cNay+~I4tkeGvQ=D3x7&#r8!!Vu>tL zl9?=ewROcm2F|;M22fElFN-hcGFeRXj(Q6yt%;){RFuR4bCkrw$vzn)0i|B&DN993 zWEr6(cAMU_xhFK->JH^uAd4(q78TYOE(Nmq@PYO1*)dq2YVQC`)ZvWEnLqcDwfeN)$X?!vb$pdr9LCB z*}jNJEs;gsZT4fxvbYy-0i|62G=Pedd0B+NWU`olXva1{sly@~LPbd&Fh@x&+&;fY zOF(JRM#@rA5?MwliQRTye%ApS{ws#^ERe;Js{`JKK1 zg=HTHLBkJHXb81oalpJ`v2gndiC;m(pS_?gwPBHE)Uep?NO0HHAd8_zuiJ0f0aSt?2*%Lpa0Ti3;r_(xeUc2J%LvIvf0vIwqqDh(RW zcAN%K8#XVCl6ROa66Van4;lJ!g@#ZY76;5577Kqku;v0Z{PzROQX3XoMh%PI!n}tC zf-L&xyKTQ=2V`-=I|^k{yh{gsqxdz0?%0BkTOx~*-PmtK(#EZH2b3m^rvX%y%*&!o zDw9R&nE9tb7DeXJ5GqRIfH_KH;n(l8gaS&wD=AAwNn{zJBz9{%WKj$FcJO2yvtAEH>AJ= z%2FE^Sw;F{#pZo9gxat;VBWA; zxcjDem7(EsrzuNqSY#PBEOv8CUx07ed;BrwIUtM6*O)9G%q)+;Slb)$&?bu$mdL`j zBKtAqu3LC7kVWyOG=Pedd0C9T%4BiO+j%m`B5O1ap`s)Xn4=^X4s(v$@MN*ih4LJbMV7@|@yX&zru`)W zr6Qvr+ZH=%i7YP9V6wQDG!Xwcq)Z?UprT}67TvEfSp=_IT^3NSQ4$BtQ4$Mh zDo{EQWRWL|vQ(5rmJv!~w`RSwIzz*24pN>4vPg?!vWR?g_yWjcRT2%LHf&xNccw)a{2V~K) N<2IB<^sZk@{|~dt{vZGV literal 0 HcmV?d00001 diff --git a/docs/notebooks/multi_output_efficient_sampling.py b/docs/notebooks/multi_output_efficient_sampling.py index 253d604d..1783965b 100644 --- a/docs/notebooks/multi_output_efficient_sampling.py +++ b/docs/notebooks/multi_output_efficient_sampling.py @@ -52,7 +52,7 @@ """ # %% -d = np.load("./tests/snelson1d.npz") +d = np.load("../../tests/snelson1d.npz") X, Y = data = d["X"], d["Y"] num_data, input_dim = X.shape diff --git a/docs/notebooks/multi_output_weight_space_approximation.py b/docs/notebooks/multi_output_weight_space_approximation.py deleted file mode 100644 index 15dc56d6..00000000 --- a/docs/notebooks/multi_output_weight_space_approximation.py +++ /dev/null @@ -1,444 +0,0 @@ -# --- -# jupyter: -# jupytext: -# text_representation: -# extension: .py -# format_name: percent -# format_version: '1.3' -# jupytext_version: 1.10.0 -# kernelspec: -# display_name: Python 3 -# language: python -# name: python3 -# --- - -# %% [markdown] -""" -# Weight Space Approximation with Random Fourier Features -""" - -# %% [markdown] -r""" -This notebook demonstrates how to approximate an exact Gaussian process regression model (GPR) with random Fourier features in weight space. The end result is Figure 1 from from Wilson et al. "Efficiently sampling functions from Gaussian process posteriors" . This figure demonstrates that approximating an exact GPR model in weight space becomes increasingly more difficult as the training data grows. While the approximation remains accurate in areas within the training data and far away from the training data, predictions close to the training data points (but outside the training data interval) become less reliable. Note that Wilson et al. provide a method to alleviate exactly this problem; however, this is outside the scope of this notebook, where the emphasis is on how to build a weight space approximated Gaussian process model with random Fourier features in `gpflux`. - -The basic idea is to approximate a stationary kernel $k(X,X^\prime)$ for one-dimensional inputs $X \in \mathbb{R}$ and $X^\prime \in \mathbb{R}$ according to Bochner's theorem: - -$$ -k(X, X^\prime) \approx \sum_{i=1}^I \phi_i(X) \phi_i(X^\prime), -$$ -with $I$ Fourier features $\phi_i$ following Rahimi and Recht "Random features for large-scale kernel machines" (NeurIPS, 2007) defined as - -$$ -\phi_i(X) = \sqrt{\frac{2 \sigma^2}{l}} \cos(\theta_i X + \tau_i), -$$ -where $\sigma^2$ refers to the kernel variance and $l$ to the kernel lengthscale. $\theta_i$ and $\tau_i$ are randomly drawn hyperparameters that determine each feature function $\phi_i$. The hyperparameter $\theta_i$ is randomly drawn from the kernel's spectral density. The spectral density of a stationary kernel is obtained by interpreting the kernel as a function of one argument only (i.e. the distance between $X$ and $X^\prime$) and performing a Fourier transform on that function, resulting in an unnormalised probability density (from which samples can be obtained). The hyperparameter $\tau_i$ is obtained by sampling from a uniform distribution $\tau_i \sim \mathcal{U}(0,2\pi)$. Note that both $\theta_i$ and $\tau_i$ are fixed and not optimised over. An interesting direction of future research is how to automatically identify those (but this is outside the scope of this notebook). If we drew infinitely many samples, i.e. $I \rightarrow \infty$, we would recover the true kernel perfectly. - -The kernel approximation specified above enables you to express a supervised inference problem with training data $\mathcal{D} = \{(X_n,y_n)\}_{n=1,...,N}$ in weight space view as - -$$ -p(\textbf{w} | \mathcal{D}) = \frac{\prod_{n=1}^N p(y_n| \textbf{w}^\intercal \boldsymbol{\phi}(X_n), \sigma_\epsilon^2) p(\textbf{w})}{p(\mathcal{D})}, -$$ -where we assume $p(\textbf{w})$ to be a standard normal multivariate prior and $p(y_n| \textbf{w}^\intercal \boldsymbol{\phi}(X_n), \sigma_\epsilon^2)$ to be a univariate Gaussian observation model of the i.i.d. likelihood with mean $\textbf{w}^\intercal \boldsymbol{\phi}(X_n)$ and noise variance $\sigma_\epsilon^2$. The boldface notation $\boldsymbol{\phi}(X_n)$ refers to the vector-valued feature function that evaluates all features from $1$ up to $I$ for one particular input $X_n$. Under these assumptions, the posterior $p(\textbf{w} | \mathcal{D})$ enjoys a closed form and is Gaussian. Predictions can readily be obtained by sampling $\textbf{w}$ and evaluating the function sample $\textbf{w}$ at new locations $\{X_{n^\star}^\star\}_{n^\star=1,...,N^\star}$ as $\{\textbf{w}^\intercal \boldsymbol{\phi}(X_{n^\star}^\star)\}_{n^\star=1,...,N^\star}$. - -The advantage of expressing a Gaussian process in weight space is that functions are represented as weight vectors $\textbf{w}$ (rather than actual functions $f(\cdot)$) from which samples can be obtained a priori without knowing where the function should be evaluated. When expressing a Gaussian process in function space view the latter is not possible, i.e. a function $f(\cdot)$ cannot be sampled without knowing where to evaluate the function, namely at $\{X_{n^\star}^\star\}_{n^\star=1,...,N^\star}$. Weight space approximated Gaussian processes therefore hold the potential to sample efficiently from Gaussian process posteriors, which is desirable in vanilla supervised learning but also in domains such as Bayesian optimisation or model-based reinforcement learning. - -In the following example, we compare a weight space approximated GPR model (WSA model) with both a proper GPR model and a sparse variational Gaussian Process model (SVGP). GPR models and SVGP models are implemented in `gpflow`, but the two necessary ingredients for building the WSA model are part of `gpflux`: these are random Fourier feature functions via the `RandomFourierFeaturesCosine` class, and approximate kernels based on Bochner's theorem (or any other theorem that approximates a kernel with a finite number of feature functions, e.g. Mercer) via the `KernelWithFeatureDecomposition` class. -""" - -# %% -import numpy as np -import matplotlib.pyplot as plt - -plt.rcParams["figure.figsize"] = (20, 7) -plt.rc("text") -plt.rcParams.update({"font.size": 20}) -import tensorflow as tf - -import gpflow -from gpflow.config import default_float -from gpflow.models import GPR, SVGP -from gpflow.kernels import SquaredExponential, Matern52 -from gpflow.likelihoods import Gaussian -from gpflow.inducing_variables import InducingPoints - -from gpflux.layers.basis_functions.fourier_features import MultiOutputRandomFourierFeaturesCosine -from gpflux.feature_decomposition_kernels import ( - KernelWithFeatureDecomposition, - SeparateMultiOutputKernelWithFeatureDecomposition, - SharedMultiOutputKernelWithFeatureDecomposition, -) - - -# Copyright 2016-2020 The GPflow Contributors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from typing import Optional - -import tensorflow as tf - -import gpflow - - -# from gpflow import posteriors -from gpflow.base import InputData, MeanAndVariance, RegressionData -from gpflow.experimental.check_shapes import check_shapes, inherit_check_shapes -from gpflow.kernels import Kernel -from gpflow.likelihoods import Gaussian -from gpflow.logdensities import multivariate_normal -from gpflow.mean_functions import MeanFunction -from gpflow.utilities.model_utils import add_likelihood_noise_cov -from gpflow.utilities import assert_params_false -from gpflow.models.model import GPModel -from gpflow.models.training_mixins import InternalDataTrainingLossMixin -from gpflow.models.util import data_input_to_tensor - - -class GPR_deprecated(GPModel, InternalDataTrainingLossMixin): - r""" - Gaussian Process Regression. - - This is a vanilla implementation of GP regression with a Gaussian - likelihood. Multiple columns of Y are treated independently. - - The log likelihood of this model is given by - - .. math:: - \log p(Y \,|\, \mathbf f) = - \mathcal N(Y \,|\, 0, \sigma_n^2 \mathbf{I}) - - To train the model, we maximise the log _marginal_ likelihood - w.r.t. the likelihood variance and kernel hyperparameters theta. - The marginal likelihood is found by integrating the likelihood - over the prior, and has the form - - .. math:: - \log p(Y \,|\, \sigma_n, \theta) = - \mathcal N(Y \,|\, 0, \mathbf{K} + \sigma_n^2 \mathbf{I}) - """ - - @check_shapes( - "data[0]: [N, D]", - "data[1]: [N, P]", - ) - def __init__( - self, - data: RegressionData, - kernel: Kernel, - mean_function: Optional[MeanFunction] = None, - noise_variance: Optional[float] = None, - likelihood: Optional[Gaussian] = None, - ): - assert (noise_variance is None) or ( - likelihood is None - ), "Cannot set both `noise_variance` and `likelihood`." - if likelihood is None: - if noise_variance is None: - noise_variance = 1.0 - likelihood = gpflow.likelihoods.Gaussian(noise_variance) - _, Y_data = data - super().__init__(kernel, likelihood, mean_function, num_latent_gps=Y_data.shape[-1]) - self.data = data_input_to_tensor(data) - - # type-ignore is because of changed method signature: - @inherit_check_shapes - def maximum_log_likelihood_objective(self) -> tf.Tensor: # type: ignore[override] - return self.log_marginal_likelihood() - - @check_shapes( - "return: []", - ) - def log_marginal_likelihood(self) -> tf.Tensor: - r""" - Computes the log marginal likelihood. - - .. math:: - \log p(Y | \theta). - - """ - X, Y = self.data - K = self.kernel(X) - ks = add_likelihood_noise_cov(K, self.likelihood, tf.tile(X[None, ...], [2, 1, 1])) - L = tf.linalg.cholesky(ks) - m = self.mean_function(X) - - # [R,] log-likelihoods for each independent dimension of Y - log_prob = multivariate_normal(Y, m, L) - return tf.reduce_sum(log_prob) - - @inherit_check_shapes - def predict_f( - self, Xnew: InputData, full_cov: bool = False, full_output_cov: bool = False - ) -> MeanAndVariance: - r""" - This method computes predictions at X \in R^{N \x D} input points - - .. math:: - p(F* | Y) - - where F* are points on the GP at new data points, Y are noisy observations at training data - points. - """ - assert_params_false(self.predict_f, full_output_cov=full_output_cov) - - X, Y = self.data - err = Y - self.mean_function(X) - - kmm = self.kernel(X) - knn = self.kernel(Xnew, full_cov=full_cov) - kmn = self.kernel(X, Xnew) - # kmm_plus_s = add_likelihood_noise_cov(kmm, self.likelihood, X) - kmm_plus_s = add_likelihood_noise_cov( - kmm, self.likelihood, tf.tile(X[None, ...], [2, 1, 1]) - ) - - # NOTE -- this onlty works for a single latent Full GP - # conditional = gpflow.conditionals.base_conditional - - conditional = gpflow.conditionals.util.separate_independent_conditional_implementation - - f_mean_zero, f_var = conditional( - kmn, kmm_plus_s, knn, err, full_cov=full_cov, white=False - ) # [N, P], [N, P] or [P, N, N] - f_mean = f_mean_zero + self.mean_function(Xnew) - return f_mean, f_var - - -# %% [markdown] -""" -Our aim is to demonstrate the decrease in predictive quality of a WSA model when increasing the number of training points. To that end, we perform two sets of experiments: one with few and one with many training data points. Each experiment compares a WSA model to an exact GPR and to an approximate SVGP model, resulting in six plots all in all. - -We first define settings that remain the same across the two sets of experiments, like the interval of the training points, aspects of the generative model (i.e. kernel variance and lengthscale, and the variance of the observation model), and the number of feature functions of the WSA model. - -The only aspect that is different across both experimental settings is the number of training data points. We increase the number of inducing points for the SVGP model to cope with this. -""" - -# %% -# experiment parameters that are the same for both sets of experiments -X_interval = [0.14, 0.5] # interval where training points live -lengthscale = [ - 0.1 -] # lengthscale for the kernel (which is not learned in all experiments, the kernel variance is 1) -number_of_features = 2000 # number of basis functions for weight-space approximated kernels -noise_variance = 1e-3 # noise variance of the likelihood (which is not learned in all experiments) -number_of_test_samples = 1024 # number of evaluation points for prediction -number_of_function_samples = ( - 20 # number of function samples to be drawn from (approximate) posteriors -) - -# experiment parameters that differ across both sets of experiments -number_of_train_samples = [4, 1000] # number of training points -number_of_inducing_points = [4, 8] # number of inducing points for SVGP models - -# kernel class -# kernel_class = Matern52 # set altern experiment = 2*j + nvmatively kernel_class = RBF - -# plotting configuration -x_lim = [0.0, 1.0] -y_lim = [-3.5, 3.5] - -# %% [markdown] -""" -We proceed by generating the training data for both experimental settings from a ground truth function which is a sample from a prior zero-mean GP with a predefined kernel (in our case, we use a `Matern52` kernel but we could have chosen an `RBF` kernel -- both of which are defined in `gpflow`). -""" - -# %% -# generate training data and evaluation points for both sets of experiments - - -list_kernels = [ - Matern52(lengthscales=lengthscale), - SquaredExponential(lengthscales=lengthscale), -] -# kernel = kernel_class(lengthscales=lengthscale) # kernel object to draw training dataset from - -X, y, X_star = ( - [], - [], - [], -) # training points, training observations, and test points for evaluation - -# 1st iteration: experiments with few training points -- 2nd iteration: experiments with many training points - -for i in range(len(number_of_train_samples)): - - X_temp, y_temp, X_star_temp = [], [], [] - - # training pointsnumber_of_train_samples - X.append( - np.linspace(start=X_interval[0], stop=X_interval[1], num=number_of_train_samples[i])[ - ..., None - ] - ) - - for j in range(len(list_kernels)): - - # training observations generated from a zero-mean GP corrupted with Gaussian noise - kXX = list_kernels[j].K(X[-1]) - kXX_plus_noise_var = kXX + tf.eye(tf.shape(kXX)[0], dtype=kXX.dtype) * noise_variance - lXX = tf.linalg.cholesky(kXX_plus_noise_var) - y_temp.append( - tf.matmul(lXX, tf.random.normal([number_of_train_samples[i], 1], dtype=X[-1].dtype),)[ - ..., 0 - ][..., None] - ) - - # test points for evaluation - X_star.append(np.linspace(start=x_lim[0], stop=x_lim[1], num=number_of_test_samples)[..., None]) - y.append(np.concatenate(y_temp, axis=-1)) - - -# %% [markdown] -""" -The `for` loop below iterates through both experimental settings with few and many training examples respectively. In each iteration, the GPR model is built first (and its prediction is used as "ground truth" to compare with the remaining models) followed by the SVGP model (which requires optimisation to identify internal parameters) and the WSA model. -""" - -# %% -# create subplot frame -# 1st row: experiments with few training examples, 2nd row: experiments with many training examples :: Matern52 kernel -# 3rd row: experiments with few training examples, 4th row: experiments with many training examples :: SqExp kernel -# 1st col: exact Gaussian process regression (GPR), 2nd col: sparse variational Gaussian process model (SVGP), -# 3rd col: weight space approximation (WSA) of the exact GPR posterior with random Fourier features -fig, axs = plt.subplots(2, 2) - - -# 1st iteration: experiments with few training points -- 2nd iteration: experiments with many training points - -for experiment in range(len(number_of_train_samples)): - - # subplot titles and axis labels - axs[experiment, 0].set_title( - "Weight Space GP Matern52 $N=" + str(number_of_train_samples[experiment]) + "$" - ) - axs[experiment, 1].set_title( - "Weight Space GP SqExp $N=" + str(number_of_train_samples[experiment]) + "$" - ) - axs[experiment, 0].set_ylabel("$f(X)$") - if experiment == 1: - axs[experiment, 0].set_xlabel("$X$") - axs[experiment, 1].set_xlabel("$X$") - - # plot training point locations X and set axis limits - if ( - experiment == 0 - ): # as vertical lines for the first set of experiments with few training samples - axs[experiment, i].vlines(X[experiment], ymin=y_lim[0], ymax=y_lim[1], colors="lightgrey") - else: # as fill plots for the second set of experiments with many training samples - axs[experiment, 1].fill_between( - X[experiment].ravel(), y_lim[0], y_lim[1], color="gray", alpha=0.2 - ) - axs[experiment, 0].set_xlim(x_lim) - axs[experiment, 0].set_ylim(y_lim) - axs[experiment, 1].set_xlim(x_lim) - axs[experiment, 1].set_ylim(y_lim) - - # create exact GPR model with weight-space approximated kernel (WSA model) - - kernel1 = gpflow.kernels.Matern52(lengthscales=lengthscale) - kernel2 = gpflow.kernels.SquaredExponential(lengthscales=lengthscale) - # kernel = gpflow.kernels.SeparateIndependent( kernels = [kernel1, kernel2]) - kernel = gpflow.kernels.SharedIndependent(kernel=kernel1, output_dim=2) - - feature_functions = MultiOutputRandomFourierFeaturesCosine( - kernel, number_of_features, dtype=default_float() - ) - - feature_coefficients = np.ones((2, number_of_features, 1), dtype=default_float()) - # kernel = SeparateMultiOutputKernelWithFeatureDecomposition( - # kernel=None, feature_functions=feature_functions, feature_coefficients=feature_coefficients, - # output_dim = 2 - # ) - kernel = SharedMultiOutputKernelWithFeatureDecomposition( - kernel=None, - feature_functions=feature_functions, - feature_coefficients=feature_coefficients, - output_dim=2, - ) - - print("***************************************") - print("-- shape of data for current experiment") - print(X[experiment].shape) - print(y[experiment].shape) - print(X_star[experiment].shape) - - gpr_model = GPR_deprecated( - data=(X[experiment], y[experiment]), - kernel=kernel, - noise_variance=noise_variance, - ) - - # predict function mean and variance, and draw function samples (without observation noise)# - - f_mean, f_var = gpr_model.predict_f(X_star[experiment]) - f_samples = gpr_model.predict_f_samples( - X_star[experiment], num_samples=number_of_function_samples - ) - f_mean_plus_2std = f_mean + 2 * f_var ** 0.5 - f_mean_minus_2std = f_mean - 2 * f_var ** 0.5 - - print("***************************************") - print("-- shape of current predictions") - print(f_mean.shape) - print(f_mean_minus_2std.shape) - - # visualise WSA model predictions (mean +/- 2 * std and function samples) in the third column - - ### Matern52 ### - - axs[experiment, 0].fill_between( - X_star[experiment][..., 0], - f_mean_minus_2std[..., 0], - f_mean_plus_2std[..., 0], - color="orange", - alpha=0.2, - ) - for i in range(f_samples.shape[0]): - axs[experiment, 0].plot( - X_star[experiment][..., 0], - f_samples[i, ..., 0], - color="orange", - linewidth=0.2, - ) - axs[experiment, 0].plot(X_star[experiment][..., 0], f_mean[..., 0], color="orange") - - ### SquaredExponential ### - - axs[experiment, 1].fill_between( - X_star[experiment][..., 0], - f_mean_minus_2std[..., 1], - f_mean_plus_2std[..., 1], - color="orange", - alpha=0.2, - ) - for i in range(f_samples.shape[0]): - axs[experiment, 1].plot( - X_star[experiment][..., 0], - f_samples[i, ..., 1], - color="orange", - linewidth=0.2, - ) - axs[experiment, 1].plot(X_star[experiment][..., 0], f_mean[..., 1], color="orange") - - -# show the plot -fig.tight_layout() -plt.show() - -# %% [markdown] -""" -The results are visualised in a 2 $\times$ 3 plot with 6 subplots. The first row refers to experiments with few training data points and the second row to experiments with many training data points. The first column depicts the exact GPR model in green, the second column the SVGP model in purple and the third column the WSA model in orange. In each plot, training data points are marked in grey (as vertical bars in the first row and fill plots in the second row). We also assume the GPR model's prediction as ground truth, which is therefore plotted in all plots as black dashed lines (indicating mean +/- 2 * std). - -In each plot, the model's prediction in terms of mean +/- 2 * std is plotted through fill plots, and function samples from the (approximate) posterior through thin solid lines (thick solid lines depict mean functions in the second and third column). Note that the coloured purple circles in the second column refer to predictions at the inducing point locations of the SVGP model. - -It can be seen that, as training data points increase from the first to the second row, the predictions of the WSA model decrease drastically in areas relevant to extrapolation (i.e. close to but not inside the training data interval) because a lot of Fourier features would be required to accurately approximate a function sample drawn from a Matern kernel (because of its non-smooth nature). The same effect would be less severe for a function sample drawn from an RBF kernel that is smoother than a Matern kernel (and can hence be reliably approximated with fewer Fourier features). Note that the experiment is stochastic because the ground truth function sample from the prior kernel is random. There might be outcomes of the experiment in which the explained effect is less prominent than in other random outcomes -- so the last code block might require execution more than once to obtain a clear result. -""" diff --git a/docs/notebooks/weights.data-00000-of-00001 b/docs/notebooks/weights.data-00000-of-00001 new file mode 100644 index 0000000000000000000000000000000000000000..2f4d3cecb256307cbb22481acca55182e4134409 GIT binary patch literal 9289 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 WQp6EUYz;~{V#%#WA~e(1_x}Lz{dr;l literal 0 HcmV?d00001 diff --git a/docs/notebooks/weights.index b/docs/notebooks/weights.index new file mode 100644 index 0000000000000000000000000000000000000000..690a59bd89b78233cf94aa222dd70a807c824b4d GIT binary patch literal 1298 zcmZQzVB=tvV&Y(Akl~Ma_HcFf4)FK%3vqPvagFzP@^Wrr{x#rrl!Pa<`tBd=<7L#gammyg@(8W>xVf8d4k;#=I9gZ%E2VWA;iQX z3B-&F9Xc8(7)=w-Zu}+cEtH*Fl$V;L52bQa^U_N)ijxy_Qj5v4gavFtgN_D==?=@d zWy+R(U~l9lr;=kDgTfDOph=yx`-DUt#Bx&;^WxJ=^O8$4^Yio_$uSTV28>`QJ^&dU zYwlL6Y$TLKj!_Vwz5p4c$vlHy)KsJ}KDU${li(2pij@ej{fER&C5j7+O2{#b6YN1| zj-yNpCm1zWh?q*MuhkHa5I4knF31N*u3eL&QM$UJ3k+?uCt33;PFEK| zCVjZ5*C=W#PI0^`d=LeBylduFdFn*n4slS_*_)o;BJ9Rzq@RNV8qPWJY2gM2M&?|GJ)Cec+oMb#2RS*;aq@$N@PqK*4c#iG G?zaIvGKNV2 literal 0 HcmV?d00001 diff --git a/gpflux/layers/likelihood_layer.py b/gpflux/layers/likelihood_layer.py index b8fc7aee..7d3fb2ab 100644 --- a/gpflux/layers/likelihood_layer.py +++ b/gpflux/layers/likelihood_layer.py @@ -84,12 +84,12 @@ def call( assert targets is not None # TODO: re-use LikelihoodLoss to remove code duplication loss_per_datapoint = tf.reduce_mean( - -self.likelihood.variational_expectations(inputs, F_mean, F_var, targets) + -self.likelihood.variational_expectations(F_mean, F_var, targets) ) Y_mean = Y_var = None else: loss_per_datapoint = tf.constant(0.0, dtype=default_float()) - Y_mean, Y_var = self.likelihood.predict_mean_and_var(inputs, F_mean, F_var) + Y_mean, Y_var = self.likelihood.predict_mean_and_var(F_mean, F_var) self.add_loss(loss_per_datapoint) diff --git a/gpflux/losses.py b/gpflux/losses.py index ae6560ab..66bb83ca 100644 --- a/gpflux/losses.py +++ b/gpflux/losses.py @@ -72,7 +72,6 @@ def __init__(self, likelihood: gpflow.likelihoods.Likelihood): def call( self, - x: TensorType, y_true: TensorType, f_prediction: Union[TensorType, tfp.distributions.MultivariateNormalDiag], ) -> tf.Tensor: @@ -84,7 +83,7 @@ def call( F_mu = f_prediction.loc F_var = f_prediction.scale.diag ** 2 - return -self.likelihood.variational_expectations(x, F_mu, F_var, y_true) + return -self.likelihood.variational_expectations(F_mu, F_var, y_true) else: # Tensor f_samples = f_prediction - return -self.likelihood.log_prob(x, f_samples, y_true) + return -self.likelihood.log_prob(f_samples, y_true) diff --git a/tests/gpflux/sampling/test_multioutput_sample.py b/tests/gpflux/sampling/test_multioutput_sample.py index d5b082e4..9db16344 100644 --- a/tests/gpflux/sampling/test_multioutput_sample.py +++ b/tests/gpflux/sampling/test_multioutput_sample.py @@ -64,7 +64,7 @@ def _separate_inducing_variable_fixture(): ) -@pytest.fixture(name="whiten", params=[True]) +@pytest.fixture(name="whiten", params=[True, False]) def _whiten_fixture(request): return request.param @@ -91,6 +91,58 @@ def _get_separate_qmu_qsqrt(kernel, inducing_variable): return np.transpose(q_mu[..., 0]), q_sqrt +def test_shared_conditional_sample(base_kernel, shared_inducing_variable, whiten): + """Smoke and consistency test for efficient sampling using MVN Conditioning""" + kernel = _get_shared_kernel(base_kernel) + q_mu, q_sqrt = _get_shared_qmu_qsqrt(kernel, shared_inducing_variable) + + sample_func = efficient_sample( + shared_inducing_variable, + kernel, + q_mu, + q_sqrt=1e-3 * tf.convert_to_tensor(q_sqrt), + whiten=whiten, + ) + + X = np.linspace(-1, 1, 100).reshape(-1, 1) + # Check for consistency - i.e. evaluating the sample at the + # same locations (X) returns the same value + np.testing.assert_array_almost_equal( + sample_func(X), + sample_func(X), + # MVN conditioning is numerically unstable. + # Notice how in the Wilson sampling we can use the default + # of decimal=7. + decimal=2, + ) + + +def test_separate_conditional_sample(base_kernel, separate_inducing_variable, whiten): + """Smoke and consistency test for efficient sampling using MVN Conditioning""" + kernel = _get_separate_kernel(base_kernel) + q_mu, q_sqrt = _get_separate_qmu_qsqrt(kernel, separate_inducing_variable) + + sample_func = efficient_sample( + separate_inducing_variable, + kernel, + q_mu, + q_sqrt=1e-3 * tf.convert_to_tensor(q_sqrt), + whiten=whiten, + ) + + X = np.linspace(-1, 1, 100).reshape(-1, 1) + # Check for consistency - i.e. evaluating the sample at the + # same locations (X) returns the same value + np.testing.assert_array_almost_equal( + sample_func(X), + sample_func(X), + # MVN conditioning is numerically unstable. + # Notice how in the Wilson sampling we can use the default + # of decimal=7. + decimal=2, + ) + + def test_shared_wilson_efficient_sample(base_kernel, shared_inducing_variable, whiten): """Smoke and consistency test for efficient sampling using Wilson""" kernel = _get_shared_kernel(base_kernel) @@ -145,7 +197,6 @@ def test_separate_wilson_efficient_sample(base_kernel, separate_inducing_variabl ) -""" class SampleMock(Sample): def __init__(self, a): self.a = a @@ -172,4 +223,3 @@ def test_adding_sample_and_mean_function(): sample_and_mean_function = sample + mean_function np.testing.assert_array_almost_equal(sample_and_mean_function(X), sample(X) + mean_function(X)) -""" diff --git a/tests/gpflux/sampling/test_sample.py b/tests/gpflux/sampling/test_sample.py index 70b27588..d98e8c81 100644 --- a/tests/gpflux/sampling/test_sample.py +++ b/tests/gpflux/sampling/test_sample.py @@ -20,8 +20,10 @@ import gpflow from gpflow.config import default_float, default_jitter +from gpflux.feature_decomposition_kernels.kernel_with_feature_decomposition import ( + KernelWithFeatureDecomposition, +) from gpflux.layers.basis_functions.fourier_features import RandomFourierFeaturesCosine -from gpflux.sampling.kernel_with_feature_decomposition import KernelWithFeatureDecomposition from gpflux.sampling.sample import Sample, efficient_sample From 1fe532f7eca25a5a1ea7c30366ee0319e47ce330 Mon Sep 17 00:00:00 2001 From: SebastianPopescu Date: Fri, 23 Sep 2022 16:25:23 +0100 Subject: [PATCH 11/25] fixed setup.py --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index eb130d9d..bab45c49 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ requirements = [ "deprecated", - "gpflow>=2.1", + "gpflow>=2.1,<=2.5.2", "numpy", "scipy", "tensorflow>=2.5.0,<2.9.0; platform_system!='Darwin' or platform_machine!='arm64'", From 4117bbd24a0f651df9a70aaee676961a20f1d3ae Mon Sep 17 00:00:00 2001 From: SebastianPopescu Date: Mon, 26 Sep 2022 11:06:16 +0100 Subject: [PATCH 12/25] fixed tests --- .../test_multioutput_orthogonal_ff.py | 5 ---- .../fourier_features/test_multioutput_rff.py | 24 ++++++++++++------- .../test_multioutput_rff_cosine.py | 3 --- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_orthogonal_ff.py b/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_orthogonal_ff.py index 70f49f13..fcfc3970 100644 --- a/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_orthogonal_ff.py +++ b/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_orthogonal_ff.py @@ -27,13 +27,8 @@ SeparateMultiOutputKernelWithFeatureDecomposition, SharedMultiOutputKernelWithFeatureDecomposition, ) -from gpflux.layers.basis_functions.fourier_features import ( - MultiOutputRandomFourierFeatures, - MultiOutputRandomFourierFeaturesCosine, -) from gpflux.layers.basis_functions.fourier_features.multioutput.random import ( MultiOutputOrthogonalRandomFeatures, - MultiOutputRandomFourierFeatures, ) from gpflux.layers.basis_functions.fourier_features.random.orthogonal import ORF_SUPPORTED_KERNELS from tests.conftest import skip_serialization_tests diff --git a/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff.py b/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff.py index 14145159..f11b6f05 100644 --- a/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff.py +++ b/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff.py @@ -31,9 +31,6 @@ MultiOutputRandomFourierFeatures, MultiOutputRandomFourierFeaturesCosine, ) -from gpflux.layers.basis_functions.fourier_features.multioutput.random import ( - MultiOutputRandomFourierFeatures, -) from gpflux.layers.basis_functions.fourier_features.random.base import RFF_SUPPORTED_KERNELS from tests.conftest import skip_serialization_tests @@ -68,11 +65,6 @@ def _base_kernel_cls_fixture(request): return request.param -# @pytest.fixture(name="kernel_cls", params=[SeparateIndependent]) #, SharedIndependent]) -# def _kernel_cls_fixture(request): -# return request.param - - @pytest.fixture( name="random_basis_func_cls", params=[MultiOutputRandomFourierFeatures], @@ -266,7 +258,9 @@ def test_random_multi_output_fourier_feature_layer_compute_covariance_of_separat np.testing.assert_allclose(approx_kernel_matrix, actual_kernel_matrix, atol=5e-2) -def test_multi_output_fourier_features_shapes(basis_func_cls, n_components, n_dims, batch_size): +def test_separate_multi_output_fourier_features_shapes( + basis_func_cls, n_components, n_dims, batch_size +): input_shape = (2, batch_size, n_dims) base_kernel = gpflow.kernels.SquaredExponential(lengthscales=[1.0] * n_dims) kernel = SeparateIndependent(kernels=[base_kernel, base_kernel]) @@ -276,6 +270,18 @@ def test_multi_output_fourier_features_shapes(basis_func_cls, n_components, n_di np.testing.assert_equal(features.shape, output_shape) +def test_shared_multi_output_fourier_features_shapes( + basis_func_cls, n_components, n_dims, batch_size +): + input_shape = (2, batch_size, n_dims) + base_kernel = gpflow.kernels.SquaredExponential(lengthscales=[1.0] * n_dims) + kernel = SharedIndependent(kernel=base_kernel, output_dim=2) + feature_functions = basis_func_cls(kernel, n_components, dtype=tf.float64) + output_shape = feature_functions.compute_output_shape(input_shape) + features = feature_functions(tf.ones(shape=(batch_size, n_dims))) + np.testing.assert_equal(features.shape, output_shape) + + """ #TODO -- have a look at what layer_test actually does @skip_serialization_tests diff --git a/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff_cosine.py b/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff_cosine.py index 813d0aea..d95d260a 100644 --- a/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff_cosine.py +++ b/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff_cosine.py @@ -31,9 +31,6 @@ MultiOutputRandomFourierFeatures, MultiOutputRandomFourierFeaturesCosine, ) -from gpflux.layers.basis_functions.fourier_features.multioutput.random import ( - MultiOutputRandomFourierFeatures, -) from gpflux.layers.basis_functions.fourier_features.random.base import RFF_SUPPORTED_KERNELS from tests.conftest import skip_serialization_tests From 77c1e5ca9466ce36ac71838e31b0bbaabf0877a9 Mon Sep 17 00:00:00 2001 From: SebastianPopescu Date: Tue, 4 Oct 2022 14:58:14 +0100 Subject: [PATCH 13/25] minor changes --- .../fourier_features/multioutput/base.py | 10 ++- .../test_multioutput_rff_cosine.py | 85 ++++++++++++------- 2 files changed, 62 insertions(+), 33 deletions(-) diff --git a/gpflux/layers/basis_functions/fourier_features/multioutput/base.py b/gpflux/layers/basis_functions/fourier_features/multioutput/base.py index b2eaf6c5..c014cb35 100644 --- a/gpflux/layers/basis_functions/fourier_features/multioutput/base.py +++ b/gpflux/layers/basis_functions/fourier_features/multioutput/base.py @@ -71,7 +71,7 @@ def call(self, inputs: TensorType) -> tf.Tensor: ], axis=0, ) # [P, 1, D] - print("size -f _lengthscales") + print("size of _lengthscales") print(_lengthscales) tf.debugging.assert_equal(tf.shape(_lengthscales), [P, 1, D]) @@ -87,10 +87,16 @@ def call(self, inputs: TensorType) -> tf.Tensor: else: raise ValueError("kernel is not supported.") + print('-- size of inputs ---') + print(inputs) + X = tf.divide( - inputs, # [N, D] or [P, M, D] + tf.cast(inputs, tf.float64), # [N, D] or [P, M, D] _lengthscales, # [P, 1, D] ) # [P, N, D] or [P, M, D] + print('--- size of X ---') + print(X) + const = self._compute_constant()[..., None, None] # [P,1,1] bases = self._compute_bases(X) # [P, N, L] for X*, or [P,M,L] in the case of Z output = const * bases # [P, N, L] for X*, or [P,M,L] in the case of Z diff --git a/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff_cosine.py b/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff_cosine.py index d95d260a..0317dea2 100644 --- a/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff_cosine.py +++ b/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff_cosine.py @@ -34,18 +34,22 @@ from gpflux.layers.basis_functions.fourier_features.random.base import RFF_SUPPORTED_KERNELS from tests.conftest import skip_serialization_tests +from gpflux.helpers import construct_basic_kernel @pytest.fixture(name="n_dims", params=[1, 2, 3, 5, 10, 20]) def _n_dims_fixture(request): return request.param -@pytest.fixture(name="variance", params=[0.5, 1.0, 2.0]) + +#@pytest.fixture(name="variance", params=[0.5, 1.0, 2.0]) +@pytest.fixture(name="variance", params=[0.5]) def _variance_fixture(request): return request.param -@pytest.fixture(name="lengthscale", params=[0.1, 1.0, 5.0]) +#@pytest.fixture(name="lengthscale", params=[0.1, 1.0, 5.0]) +@pytest.fixture(name="lengthscale", params=[0.1]) def _lengthscale_fixture(request): return request.param @@ -80,7 +84,7 @@ def _random_basis_func_cls_fixture(request): def _basis_func_cls_fixture(request): return request.param - +@pytest.mark.skip def test_throw_for_unsupported_separate_kernel(basis_func_cls): base_kernel = gpflow.kernels.Constant() kernel = gpflow.kernels.SeparateIndependent(kernels=[base_kernel]) @@ -88,7 +92,7 @@ def test_throw_for_unsupported_separate_kernel(basis_func_cls): basis_func_cls(kernel, n_components=1) assert "Unsupported Kernel" in str(excinfo.value) - +@pytest.mark.skip def test_throw_for_unsupported_shared_kernel(basis_func_cls): base_kernel = gpflow.kernels.Constant() kernel = SharedIndependent(kernel=base_kernel, output_dim=1) @@ -97,6 +101,48 @@ def test_throw_for_unsupported_shared_kernel(basis_func_cls): assert "Unsupported Kernel" in str(excinfo.value) + + + + +@pytest.mark.parametrize("output_dim", [2]) +@pytest.mark.parametrize("n_components", [100]) +@pytest.mark.parametrize("size_dataset", [10]) +def test_separate_kernel_multioutput_rff_cosine(n_components: int, output_dim : int, size_dataset : int, variance, lengthscale) -> None: + + #search_space = Box([0.0], [1.0]) ** output_dim + #x = search_space.sample(size_dataset) + #print('--- shape of samples ----') + #print(x.shape) + + x = tf.random.uniform((size_dataset, output_dim), dtype=tf.float64) + print('----x ----') + print(x) + lengthscales = np.random.rand((output_dim)) * lengthscale + lengthscales = tf.cast(lengthscales, dtype = tf.float64) + + print(lengthscales) + print("size of sampled lengthscales") + print(lengthscales.shape) + + base_kernel = gpflow.kernels.SquaredExponential(variance=variance, lengthscales=lengthscales) + + #kernel = construct_basic_kernel( + # [base_kernel for _ in range(output_dim)], share_hyperparams=False + #) + + kernel = SeparateIndependent(kernels=[base_kernel for _ in range(output_dim)]) + + rff = MultiOutputRandomFourierFeaturesCosine(kernel = kernel, n_components = n_components) + output = rff(inputs = tf.cast(x, tf.float64)) + + print('---- shape of output ----') + print(output) + + tf.debugging.assert_shapes([(output, [output_dim, size_dataset, n_components])]) + + +@pytest.mark.skip def test_random_fourier_features_can_approximate_multi_output_separate_kernel_multidim( random_basis_func_cls, base_kernel_cls, variance, lengthscale, n_dims ): @@ -135,6 +181,7 @@ def test_random_fourier_features_can_approximate_multi_output_separate_kernel_mu np.testing.assert_allclose(approx_kernel_matrix, actual_kernel_matrix, atol=5e-2) +@pytest.mark.skip def test_random_fourier_features_can_approximate_multi_output_shared_kernel_multidim( random_basis_func_cls, base_kernel_cls, variance, lengthscale, n_dims ): @@ -173,33 +220,7 @@ def test_random_fourier_features_can_approximate_multi_output_shared_kernel_mult np.testing.assert_allclose(approx_kernel_matrix, actual_kernel_matrix, atol=5e-2) -""" -#TODO -- still need to implement the orthogonal version -def test_orthogonal_random_features_can_approximate_kernel_multidim(variance, lengthscale, n_dims): - n_components = 20000 - - x_rows = 20 - y_rows = 30 - # ARD - lengthscales = np.random.rand((n_dims)) * lengthscale - - kernel = gpflow.kernels.SquaredExponential(variance=variance, lengthscales=lengthscales) - fourier_features = OrthogonalRandomFeatures(kernel, n_components, dtype=tf.float64) - - x = tf.random.uniform((x_rows, n_dims), dtype=tf.float64) - y = tf.random.uniform((y_rows, n_dims), dtype=tf.float64) - - u = fourier_features(x) - v = fourier_features(y) - approx_kernel_matrix = inner_product(u, v) - - actual_kernel_matrix = kernel.K(x, y) - - np.testing.assert_allclose(approx_kernel_matrix, actual_kernel_matrix, atol=5e-2) - -""" - - +@pytest.mark.skip def test_random_multi_output_fourier_feature_layer_compute_covariance_of_shared_inducing_variables( basis_func_cls, batch_size ): @@ -229,6 +250,7 @@ def test_random_multi_output_fourier_feature_layer_compute_covariance_of_shared_ np.testing.assert_allclose(approx_kernel_matrix, actual_kernel_matrix, atol=5e-2) +@pytest.mark.skip def test_random_multi_output_fourier_feature_layer_compute_covariance_of_separate_inducing_variables( basis_func_cls, batch_size ): @@ -258,6 +280,7 @@ def test_random_multi_output_fourier_feature_layer_compute_covariance_of_separat np.testing.assert_allclose(approx_kernel_matrix, actual_kernel_matrix, atol=5e-2) +@pytest.mark.skip def test_multi_output_fourier_features_shapes(basis_func_cls, n_components, n_dims, batch_size): input_shape = (2, batch_size, n_dims) base_kernel = gpflow.kernels.SquaredExponential(lengthscales=[1.0] * n_dims) From 5f9ebdb7bfe89aaffb5726edccf2b2596ece239e Mon Sep 17 00:00:00 2001 From: hstojic Date: Fri, 25 Nov 2022 10:55:13 +0000 Subject: [PATCH 14/25] removed files accidentally commited to git --- .gitignore | 8 ++++++++ docs/notebooks/checkpoint | 2 -- docs/notebooks/ckpts/.data-00000-of-00001 | Bin 25793 -> 0 bytes docs/notebooks/ckpts/.index | Bin 3035 -> 0 bytes docs/notebooks/ckpts/checkpoint | 2 -- ...ts.1663843333.sebastianp-lptp.profile-empty | Bin 40 -> 0 bytes .../sebastianp-lptp.input_pipeline.pb | Bin 2881 -> 0 bytes .../sebastianp-lptp.kernel_stats.pb | 0 .../sebastianp-lptp.memory_profile.json.gz | Bin 73 -> 0 bytes .../sebastianp-lptp.overview_page.pb | Bin 4172 -> 0 bytes .../sebastianp-lptp.tensorflow_stats.pb | Bin 132114 -> 0 bytes .../sebastianp-lptp.trace.json.gz | Bin 20593 -> 0 bytes .../sebastianp-lptp.xplane.pb | Bin 88285 -> 0 bytes .../sebastianp-lptp.input_pipeline.pb | Bin 2881 -> 0 bytes .../sebastianp-lptp.kernel_stats.pb | 0 .../sebastianp-lptp.memory_profile.json.gz | Bin 73 -> 0 bytes .../sebastianp-lptp.overview_page.pb | Bin 4172 -> 0 bytes .../sebastianp-lptp.tensorflow_stats.pb | Bin 131756 -> 0 bytes .../sebastianp-lptp.trace.json.gz | Bin 21513 -> 0 bytes .../sebastianp-lptp.xplane.pb | Bin 92627 -> 0 bytes .../sebastianp-lptp.input_pipeline.pb | Bin 2881 -> 0 bytes .../sebastianp-lptp.kernel_stats.pb | 0 .../sebastianp-lptp.memory_profile.json.gz | Bin 73 -> 0 bytes .../sebastianp-lptp.overview_page.pb | Bin 4172 -> 0 bytes .../sebastianp-lptp.tensorflow_stats.pb | Bin 131384 -> 0 bytes .../sebastianp-lptp.trace.json.gz | Bin 21611 -> 0 bytes .../sebastianp-lptp.xplane.pb | Bin 92216 -> 0 bytes ...nts.1663843327.sebastianp-lptp.1309091.0.v2 | Bin 561295 -> 0 bytes ...nts.1663843327.sebastianp-lptp.1309091.1.v2 | Bin 55142 -> 0 bytes ...nts.1663844068.sebastianp-lptp.1320413.0.v2 | Bin 671910 -> 0 bytes ...nts.1663844068.sebastianp-lptp.1320413.1.v2 | Bin 212670 -> 0 bytes ...nts.1663944078.sebastianp-lptp.2242101.0.v2 | Bin 671910 -> 0 bytes ...nts.1663944078.sebastianp-lptp.2242101.1.v2 | Bin 212670 -> 0 bytes docs/notebooks/weights.data-00000-of-00001 | Bin 9289 -> 0 bytes docs/notebooks/weights.index | Bin 1298 -> 0 bytes 35 files changed, 8 insertions(+), 4 deletions(-) delete mode 100644 docs/notebooks/checkpoint delete mode 100644 docs/notebooks/ckpts/.data-00000-of-00001 delete mode 100644 docs/notebooks/ckpts/.index delete mode 100644 docs/notebooks/ckpts/checkpoint delete mode 100644 docs/notebooks/logs/events.out.tfevents.1663843333.sebastianp-lptp.profile-empty delete mode 100644 docs/notebooks/logs/plugins/profile/2022_09_22_11_42_13/sebastianp-lptp.input_pipeline.pb delete mode 100644 docs/notebooks/logs/plugins/profile/2022_09_22_11_42_13/sebastianp-lptp.kernel_stats.pb delete mode 100644 docs/notebooks/logs/plugins/profile/2022_09_22_11_42_13/sebastianp-lptp.memory_profile.json.gz delete mode 100644 docs/notebooks/logs/plugins/profile/2022_09_22_11_42_13/sebastianp-lptp.overview_page.pb delete mode 100644 docs/notebooks/logs/plugins/profile/2022_09_22_11_42_13/sebastianp-lptp.tensorflow_stats.pb delete mode 100644 docs/notebooks/logs/plugins/profile/2022_09_22_11_42_13/sebastianp-lptp.trace.json.gz delete mode 100644 docs/notebooks/logs/plugins/profile/2022_09_22_11_42_13/sebastianp-lptp.xplane.pb delete mode 100644 docs/notebooks/logs/plugins/profile/2022_09_22_11_54_33/sebastianp-lptp.input_pipeline.pb delete mode 100644 docs/notebooks/logs/plugins/profile/2022_09_22_11_54_33/sebastianp-lptp.kernel_stats.pb delete mode 100644 docs/notebooks/logs/plugins/profile/2022_09_22_11_54_33/sebastianp-lptp.memory_profile.json.gz delete mode 100644 docs/notebooks/logs/plugins/profile/2022_09_22_11_54_33/sebastianp-lptp.overview_page.pb delete mode 100644 docs/notebooks/logs/plugins/profile/2022_09_22_11_54_33/sebastianp-lptp.tensorflow_stats.pb delete mode 100644 docs/notebooks/logs/plugins/profile/2022_09_22_11_54_33/sebastianp-lptp.trace.json.gz delete mode 100644 docs/notebooks/logs/plugins/profile/2022_09_22_11_54_33/sebastianp-lptp.xplane.pb delete mode 100644 docs/notebooks/logs/plugins/profile/2022_09_23_15_41_22/sebastianp-lptp.input_pipeline.pb delete mode 100644 docs/notebooks/logs/plugins/profile/2022_09_23_15_41_22/sebastianp-lptp.kernel_stats.pb delete mode 100644 docs/notebooks/logs/plugins/profile/2022_09_23_15_41_22/sebastianp-lptp.memory_profile.json.gz delete mode 100644 docs/notebooks/logs/plugins/profile/2022_09_23_15_41_22/sebastianp-lptp.overview_page.pb delete mode 100644 docs/notebooks/logs/plugins/profile/2022_09_23_15_41_22/sebastianp-lptp.tensorflow_stats.pb delete mode 100644 docs/notebooks/logs/plugins/profile/2022_09_23_15_41_22/sebastianp-lptp.trace.json.gz delete mode 100644 docs/notebooks/logs/plugins/profile/2022_09_23_15_41_22/sebastianp-lptp.xplane.pb delete mode 100644 docs/notebooks/logs/train/events.out.tfevents.1663843327.sebastianp-lptp.1309091.0.v2 delete mode 100644 docs/notebooks/logs/train/events.out.tfevents.1663843327.sebastianp-lptp.1309091.1.v2 delete mode 100644 docs/notebooks/logs/train/events.out.tfevents.1663844068.sebastianp-lptp.1320413.0.v2 delete mode 100644 docs/notebooks/logs/train/events.out.tfevents.1663844068.sebastianp-lptp.1320413.1.v2 delete mode 100644 docs/notebooks/logs/train/events.out.tfevents.1663944078.sebastianp-lptp.2242101.0.v2 delete mode 100644 docs/notebooks/logs/train/events.out.tfevents.1663944078.sebastianp-lptp.2242101.1.v2 delete mode 100644 docs/notebooks/weights.data-00000-of-00001 delete mode 100644 docs/notebooks/weights.index diff --git a/.gitignore b/.gitignore index 2aef808d..917cd8eb 100644 --- a/.gitignore +++ b/.gitignore @@ -38,17 +38,25 @@ pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports +reports/ htmlcov/ .tox/ .coverage .coverage.* .cache +.junit.xml nosetests.xml coverage.xml *.cover .hypothesis/ .pytest_cache/ +# notebooks +docs/notebooks/checkpoint +docs/notebooks/ckpts/ +docs/notebooks/logs/ +docs/notebooks/weights* + # Translations *.mo *.pot diff --git a/docs/notebooks/checkpoint b/docs/notebooks/checkpoint deleted file mode 100644 index efd06212..00000000 --- a/docs/notebooks/checkpoint +++ /dev/null @@ -1,2 +0,0 @@ -model_checkpoint_path: "weights" -all_model_checkpoint_paths: "weights" diff --git a/docs/notebooks/ckpts/.data-00000-of-00001 b/docs/notebooks/ckpts/.data-00000-of-00001 deleted file mode 100644 index 0c3c568236d378b8a013601f74c167a5415a4ac3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25793 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 diff --git a/docs/notebooks/ckpts/.index b/docs/notebooks/ckpts/.index deleted file mode 100644 index 2a961d37709b04724c6ae0d21268be53629a4b27..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3035 zcmZQzVB=tvV&Y(AkP(P?_HcFf4)FK%3vqPvagFzP@^WIYUQ- z!*qvb+%k7lA#!~QF=<0I(4;j{c8m!!!UQ}B(QpFjIS$j6dA@g)E&0F^nU|bOj!zgA zCV+g=IlE8D*_4l5Uoa@F0QsP)<4k;v3_k%MFen@VyPnUbDa%%Tf`Q53xJ;EFb#RWl9S>h?*+&gA1>-OQdHzMfP4^VU|mg2kv9YE`ez)4 zMWUwSlou%-VxaWVHS?-GRmzkNt{~%npPv4olrrT+2}qao%&9fvrV>;rJT8cXa;?4T z=`9Qy*vcqFef(t<70R0*ZXhRoG?Y{zsl1s`2GZ7hz@$ppjn7CwCo?-WCo>~IKSiIi zy14^X51r|jHx|FQT!Qlv!r4_rxIi`#AgM{#d@ZSyHDy8nX0U4rfN&o-= diff --git a/docs/notebooks/ckpts/checkpoint b/docs/notebooks/ckpts/checkpoint deleted file mode 100644 index 462f6274..00000000 --- a/docs/notebooks/ckpts/checkpoint +++ /dev/null @@ -1,2 +0,0 @@ -model_checkpoint_path: "." -all_model_checkpoint_paths: "." diff --git a/docs/notebooks/logs/events.out.tfevents.1663843333.sebastianp-lptp.profile-empty b/docs/notebooks/logs/events.out.tfevents.1663843333.sebastianp-lptp.profile-empty deleted file mode 100644 index ebaf76d33b4088b9812cabc31a16c0a86e6a0093..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 40 rcmb1OfPlsI-b$Pd3=WL^r*Ak)@g@}|X6EU+mZj#ESQ(vBTe%hhqL2#w diff --git a/docs/notebooks/logs/plugins/profile/2022_09_22_11_42_13/sebastianp-lptp.input_pipeline.pb b/docs/notebooks/logs/plugins/profile/2022_09_22_11_42_13/sebastianp-lptp.input_pipeline.pb deleted file mode 100644 index 61b382b1776ff59a068d3c2adb56d765915d19e8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2881 zcmc&$e~1)S9N#+)ZOD*=M2+z6igc^TY>oQiL7sDzOy^+?0eIj zH@B`)pix4I)=@z!6j?+;pa~%nQjiEie`J4@{}la^U?35c7)JDcvp4N|TPd8-9|N=R zz5RZEe1E*@iY9eePL zzO1n*FTfMr1mAa9xwoL*^PgZCwd>ma{K1~rGw~lTue$ijXX~=bXeAx3%#J#!-Fbaf z43mQwA6{s@m5EuZ4qdyHTh&G`(E6?q^N&v4r<`!9 zL~}w{HgaZC2@D^EJ(Q>}dgsbiCjR~J`}gelF`Z2g)N{w~+WK53{k3uQ$O$9S2K#)6 zHZnKdor+Tdn9s#F*D)233tt|5cI~nKnfOnqpWOcE;dnL~t)!!s*)EQ2i5t_v(34w# z{q)@KlbQH!AI?9p&CX|&*3`?VPQ3d}CSAC2@6_-gcehEbYuOuzZm%&kTJTy^*y7G* zd%oK7lHId66F+nHqjRZKOS8#nB^|BI)&!b<6TmZ4iu!uv7pLC8{8}bnKXS72(D4Vd z$rZnSv!>@X&!o@H5B4qidC_cr#`!z6U4!hY00Jy>Vo^yA(%=E9(FUngCW++4c7B~Hr*N_#?QqoQ- z9VrFtgIrmoUV=zPN^VFLOD<*AMBnr#>h!vk>r=Fka4~};krila932`O&W#M}+WC27 zK&{9nVq<=Z?YI!~q}C*5CbV?P01Z=mYJejuJflL|+(p_dh_rRZlJw_ur2AILM1yUR zW~E(gv_pJnFDR`&x5QUWI|vu(B(y`e_K4XqT`0Q1%Ca(d@WRj-m|R##1jagxN+BS${+B`>#pmj95^k%xdP;ukgUNh>Fv!i`)q5-?Y7dWaA(S z)CCb%%>SC+xtklA+R9$LldZkE3@j6+hDL*x^*A0tX$J)5wm*AN6F{dmWk~ z8y@Io&db-S2vS+z$@pq~Ch%Fl za(w!7@T(5O;7AkTOTuk@cYK_9WzYvEwCv65*^F9*V{Svz1>`({xvN@A$`TE~_7btx zvEG;w8;EU*jm0KnrP!8*8}pABM@NRoOD8(JKIn`D*QlssN_oi#F$osI#w8U{Vid=g zC&+QyEaeLRQWsr?dLA%>N$O4~i4@dfs(#eJd=ll%VZIbW4RGpNq#Ki^_o#oU%Q8CB zET~8ElhjYD>g(>sXb9iTo(gFN__^xfY(ZokDFP=bo}lb{mO8-?R>h?!49@@&@rtFE f)l|}=5(aw&uayw2d0Z)y0v|pN48-LOuVno%WB?FB diff --git a/docs/notebooks/logs/plugins/profile/2022_09_22_11_42_13/sebastianp-lptp.kernel_stats.pb b/docs/notebooks/logs/plugins/profile/2022_09_22_11_42_13/sebastianp-lptp.kernel_stats.pb deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/notebooks/logs/plugins/profile/2022_09_22_11_42_13/sebastianp-lptp.memory_profile.json.gz b/docs/notebooks/logs/plugins/profile/2022_09_22_11_42_13/sebastianp-lptp.memory_profile.json.gz deleted file mode 100644 index 854ec4b59a13029728eb3facb30ba1c1b9a2296e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 73 zcmb2|=3oE==G9@Re9xZMU&W(w%K!8kPhJn*qBAE?`upje)DPOUYTebqQ`%?0p3v9R b4BKRMrE%3)AI49MlCv4>3(VMTfF=L{6-OOS diff --git a/docs/notebooks/logs/plugins/profile/2022_09_22_11_42_13/sebastianp-lptp.overview_page.pb b/docs/notebooks/logs/plugins/profile/2022_09_22_11_42_13/sebastianp-lptp.overview_page.pb deleted file mode 100644 index 313af2800ebd6060417924e71b5971ba2346aee5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4172 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 IZP@hx0l2Ix0ssI2 diff --git a/docs/notebooks/logs/plugins/profile/2022_09_22_11_42_13/sebastianp-lptp.trace.json.gz b/docs/notebooks/logs/plugins/profile/2022_09_22_11_42_13/sebastianp-lptp.trace.json.gz deleted file mode 100644 index 53c50a59c658a986357ed1514ea241db8990bd1a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20593 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:h6w22cI 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 Q{MSGJHy+TL=t1)W0LOUL?EnA( diff --git a/docs/notebooks/logs/plugins/profile/2022_09_22_11_42_13/sebastianp-lptp.xplane.pb b/docs/notebooks/logs/plugins/profile/2022_09_22_11_42_13/sebastianp-lptp.xplane.pb deleted file mode 100644 index 2d724fb0ed2f2168697d81de652da518b14aa277..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 88285 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%0DGN)y4s)usKpu5obb_bHT2|I$0 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 D)NOSd diff --git a/docs/notebooks/logs/plugins/profile/2022_09_22_11_54_33/sebastianp-lptp.input_pipeline.pb b/docs/notebooks/logs/plugins/profile/2022_09_22_11_54_33/sebastianp-lptp.input_pipeline.pb deleted file mode 100644 index 3f8810d6ad54546933c491bfe6e11ce388b05aec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2881 zcmc&$U1$_n6y9tLZO8uD1#JzL-i;644e4w*v=qmm-6SRwf08t&DJIJHX6DT9u(S7$ z_uk2NwO9~T3KgM0pp>Hc=0m~Sw-zc&Z9%9NDfHD^^hLBq@X1no?rf$Tv#k{(^kHE3 z-n-}fzVn@P?xYf(iS8#>96om^v*Ykv#ons%>aYSq6&IE@&bhLzF)FCNxD8TztlT?cth_H6M*a5m(Sh+LpA^ztG3I9%Un^$gm3+LiFluP5zi-s0 zgjci#pDI)p$r<3xrV1E72z%rDRlaB6$Axs`x!cDs6%n@Q*tJGbKTybP9=A5W)Fx(s zhcU7^+-c2e0+{4toA240$4T=F95}SEkiLHE(23KlR~57INZ+0@-f$3Ez36!N{BUp&&iyt6HI-6;Nd==K^zzXY!}^RqO$V&|E+ zU-zd~A^rXPqcWoQS=eVN~WJyJ+_{`Ag=H!iF$X746< z|8jBvu0sCc?am9;OlqM%>++Mv&Ox>-gb<6II8;%KGuHYdT>LADrZuwM{@wK^W8s|GUU{n&!@1_=p$7}&q0%2jT6wGyR z$wnX@m#n3vBEVhORZ%LCRxVes*G;T^EIZfdb(4#7js{-I;kL{L4OQVRr`(*@k<+je z)T$Z{x`@)G)Vi+Hj89p$YyI3N>I^d3wK=+;a50Y~Q59%v932|kGCVS98kZj#2kOLG zA};z%T+fGyCv|2iv!SI+g_tm{rv^BpqBAd7Y5FMvk7sDf@Z^LBY$iN^8^#u`C z%>Qcd;*%REwdG!WCR=-p$9ouNY8F}JtBz4@FVVC{o1`6yIy%0*ZZ4HW3=mBjtTx%6qWWXz=kyvVCgcGSCAj+!&so`J^ z1vn;|z}$d~A3>xJ#HLJhP=Ld{t~a964M5-lEO;Bp%-nb2i3C?wFuANhNLHub3b}lb+nY_27c{zCAt&62`kZ` z*pwJgOeJO#n;st+d$Tk;vSs_ssbuQ&WGuKwMHMaOGZMrsI0PG)R6vW-99ua-j&sS< zS;1fWqN~s#07lTHOg>ALpdQopqyHsI?3u@;5@8K+>NzBXW|=+uANsP4k2DKvGk%iF ztggOHFGfT7rh7W16XNHphqDEdaij>Gpm>6^ds&(UKUg)Fo+vy6M8qqWI!;qbi%Jx1 Y4PGk|So646qy#>E4j72f8D7ceUpfj88~^|S diff --git a/docs/notebooks/logs/plugins/profile/2022_09_22_11_54_33/sebastianp-lptp.kernel_stats.pb b/docs/notebooks/logs/plugins/profile/2022_09_22_11_54_33/sebastianp-lptp.kernel_stats.pb deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/notebooks/logs/plugins/profile/2022_09_22_11_54_33/sebastianp-lptp.memory_profile.json.gz b/docs/notebooks/logs/plugins/profile/2022_09_22_11_54_33/sebastianp-lptp.memory_profile.json.gz deleted file mode 100644 index 854ec4b59a13029728eb3facb30ba1c1b9a2296e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 73 zcmb2|=3oE==G9@Re9xZMU&W(w%K!8kPhJn*qBAE?`upje)DPOUYTebqQ`%?0p3v9R b4BKRMrE%3)AI49MlCv4>3(VMTfF=L{6-OOS diff --git a/docs/notebooks/logs/plugins/profile/2022_09_22_11_54_33/sebastianp-lptp.overview_page.pb b/docs/notebooks/logs/plugins/profile/2022_09_22_11_54_33/sebastianp-lptp.overview_page.pb deleted file mode 100644 index 69ae79d6961bd28e3c597a559948fd56e5da3532..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4172 zcmeHJU5FD`6i#A6JKEL;+}2R>CO$N?tdl0T6r*dhyY5>5cGsA0ySvJGGjk^yGMPKh z+-%HREC?!sBJ>B8B8qQ56ju9CXrZFi7KB=nLg|~e=!ck!31a7nMKD_!Tzr2#^vlrcQ<&wmmFcaMjF^^wZ-UPIvG9AQP>>aQDQOETru^aieb4_GgkD z$DMUAw~^Tw6b5IPcbsF&6VsvgRzp`fj?>aLvj6bjO!Vf|;ZtWIC=>nSof}h!L)}^N_MS!8KL2KSCVAoFasB+aFSXGb6=DyEd6Wzlp{{x+ncBGYXlF;HEp$!D{&nbfjX}R`TJh?$ zFtm94xgDX`ry#*krx+bMSmsfuS_ou5u_O;ZczsBK(QzO^G`=J(a3kZ-n(^a zWmdc&n*8zdzMYxmfxD4Q<#>2Hzx34w!uEc1XO&bzc#kym1!N6uYwx;nCcv^9Bbpo$J)Na9uSc!NXhXw{Vtsm@{ zgsXFM1gn0PkOuulnr;vmCsrr0sgNcwR)vCbJ{1BMUr5(I*M#+Vw>03T-F0LGT1=PuYBjl)7RN*&t?-m1dtjKae8|wN<~l zih&(RW}5A;@`^&s+wp+LR9BvwMr_%ygD715)231rsicBU)$6HKqE$mhJdUS}^@FHq z?MTmHUq7ny1Hx6zf7;&J7uPRpvwQ88Y`&X)z9-R4jzSbZ3l70}*#EoWqob^mS!eL0 zCWcQ3g*2;ML@H8Rgn_bjM*`1HwD=q(=U!t=y_7MSC8CsjOl;I0-3gb4xnRQ($qeTQ zDRLOG5YsCJRlr!QHc=&%huRPgE`eKr11`3%Yz5GHz}ySHE32GJ zhXA*|SfDeI3Zw(QfenFNU@TAwY?#+K{H8oKxM{R76$*bG@(EY4U51v@fHq9Pbv zR3e-V$Jne1U~CkNR|S6YgRX=viI@saD~-s)M&cX0Q|+929n7^I?<{f(t9h(&dIX z31oyL7OSeqqzT0hwhE3FH<`DcGh#M8w2_z~gPL$8OOfzs!2KJ|?u<=+`s<1xLfP1v zx&O9)3c?Qe(jZ&9MGUw}$e3$)61c~SV-ZD%eObT`)?W^zs0~=VuE794#EorZm#g8;7KnPmgL|v2a2H$ jrl|*1(Lm3Z)ckqDg~8YyXbyPe|2}BKus{`O?1O&*3KP~m diff --git a/docs/notebooks/logs/plugins/profile/2022_09_22_11_54_33/sebastianp-lptp.tensorflow_stats.pb b/docs/notebooks/logs/plugins/profile/2022_09_22_11_54_33/sebastianp-lptp.tensorflow_stats.pb deleted file mode 100644 index 2c61e8e749bd95d85bd3c42dc88109b047a890db..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 131756 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

RI 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 a;Z=f4i#pUiX>NntJbbRQE620>?Ee8QCX;yp diff --git a/docs/notebooks/logs/plugins/profile/2022_09_23_15_41_22/sebastianp-lptp.input_pipeline.pb b/docs/notebooks/logs/plugins/profile/2022_09_23_15_41_22/sebastianp-lptp.input_pipeline.pb deleted file mode 100644 index 6f2b79d61792e13bb0a9b04cdbab5fc8b9601d57..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2881 zcmc&$UuYaf7{7~xW^J|Pp_-P^xvPJ&ZQSz?5!t5MOWLGOte1FA3r(rV-0tk%a=SB| z+1Z@YCn*ssilBlPeK2i>iWaN12!e{$mPVyQ!567Yk@QVPMIY>gezTYL(j00a1s@jn zX6C-%@Av(_@0;yNtV?Wa?|l80PtnQrWIi{pbPWr_v0z-+i;M|fAHy8GE^!~m{@&c0 zWaovak00vWFlVGj{}_Dv$@xd}YP^z-SM=3mocNrXBnTW@$<>tm|23+vPdNVm>;YXL zVw_A7UL-!j0>I22-;aHC%TXhB_1i7%^YrGty1MhZV*BW8Mz;OqcXi%-Pkt#_sPruZ z>^=$RVgafm;BAbWSP%*iz;6s65?5i0gdw#zC+1d5C zwZP6KmBPw!_e)OWga(Z7b{$jl_~MCIoio25G*Z@;_3zD2uF9+NN;Y0uDt}P9^;#Mb z=7Fx{rJhGWGg9rhKht*ld@--i+ZP6oH%TxF28x?=Sw5$ zyt;nmhrv@_fss9ZZth0hd(~J1qhDO592lgNAqk=Ok%a};(KHK@ho?~;Q-K6SCiBV; zB`ENqw~#~qP(&w@Sq*6|fE74olRDw33|lVd6?koIYRcK zsUss{10pth*iR!NNr|oLQrX3{mhM~F1f71j+MB_Bi19@nk*Jb}#?hgnUBiVzO}ThO zkzgy%60*TxWIHa2cw%b`Q_qERCGp$w3!REWe{O&k|pXN8%EvNLnb8H zCc>Ea+L z37bc&GNWL5D<7yaD=JUhCcG5qK~>KFqp6G{i+Gq?4NrqA3tbDzIE}g(E};JHd;1I9 z22m*Qji_S&S9@2U+&HOC_gXXA+*>)`^)OSiP?h(SqtITwVU09NIudnse6KfK(_}Po zWHmH>TTcJMCqf0<*@JE_RYC|5O&O@RpfyR0np^Ti-HshiRm@?~F|mN`2>4M~JKjht zx|sHfR$;6H4dpw51~WIaXwCt+oHbk#)D0q{g^4}l`sH|(FY!f^a z@T}XoZ{czXY7W4_NaG|Bh}rP&1TgU`L>rh;^2^n;1GI3*+zq71f%5=(SF@y)wF-Rg zr4ySHxrCk=NQ@+kiHSrxF>>>^u|1{H!mfSglWiR*+G4>T<~6XCl>@@3h=rhWQI$wB zl4CO`z;Pj2GAr;)UUXIL`-CDesXMD8!LdVS{m6d>DE7>uf#9J>VCq?@8_d#r;2ZAAkX8tvs}9T-K!%aRVS>U5Os{3BA^5bETzaDLlmH@J ivDmU2N}5!nU|Zl?iNG4ir6R%MVGF3(VMTfF=L{6-OOS diff --git a/docs/notebooks/logs/plugins/profile/2022_09_23_15_41_22/sebastianp-lptp.overview_page.pb b/docs/notebooks/logs/plugins/profile/2022_09_23_15_41_22/sebastianp-lptp.overview_page.pb deleted file mode 100644 index 1a062e13de83f1056443129925e139db930c4d41..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4172 zcmeHJU2GIp6y7Z+*r6!d2ec&(cNc$l3hcV8F=qMMZJ`A!v}IX{Ey4Bf%$?oI&fYt{ zbEix3$q-C17!x&7q7U+8f>9zE(8NRyD1@rPghU?*YKSRsYLw`MJm|TzJ8bFtQ!U09 zn@rNZbLV{DIp;gyy`fVJLxGM!S8MyLFMWiLMMg8poYJ{L5RL`osZ^FRkxC6=jxCE= zo3Ontxggkn{;4B-S1+DOhX;S@eesFO%^B5SN%$+N`9qx8oN2^yOj=Bql?VPbYAQ8i z+S?O5QmH=1$r#~TViPO?Ok4NO&p{4!)93w4Qn^#aG^& znGWVEt7iaqp9Hh8fUG>=HH>Ol5DE{#b}n9i{?04Ur^5@cgbp4!+nG`6>GzWC^F8Ur zxyjb24=lR933g9V8JHdJcF8G6sKfXc%hV)~Pal8TJpJ?TbXdQ#=$!+jZ5h>HN%$+% z)9+PoyO9Qjd9X8hY1yM6r^Bsx>}xrBE}K#J+_U%Y$?tZj6I);SaDBySYf5KWiQE`w znh?B}LFkj0_P0Li98ZTY9{TL3rC&ajQBO=d3NF!yz*Ll8cga!o3f*qj=IDJ?IRrvoI>NwMHM`b zs+bBS7}8j!U{Zpd3d|NVsqG4HC(=qTEjzFRn+#GV92MY|g?SPFt-XvXXM$@XDzc{z zSp&nQ8YkExh`N=$U7y~(20$_{T8UAK6Ju4RB!umx;_+&=8Uy8n>Y&tcM8!vqZFVH^tVtV>+R- zG8b$ZBGFK8fFVZ^8ws;QPz8+DU7K*&0D{*D zDqIIaK&7LFvMzW=;OSU0Tt6I~vI#I?X`DC$F$4ZL9dNuNiS>*qnVIIZ4szk9wgpJ% zfO8M@uB^*c7AkPtiv+p?$v`U56X*|Q10#V#p#Ro2LtFEM0~?16$67*1Tl|D8n3tiY ztl$tnMsx&&i%LW$BRMu|0vzkbl2w6U@}MhW+a?r2lcEU~364!F^&`J>kl!^1+?tmvH`H6hff+$j!vsNiF{fy|7Qi3Y8i3DH z?Wibakb*|?W2SeviCT=65r)YDR193lOku+DU*{o5P9`V060DUxVxTea$e;wvM%P9Q zE)L$jfHq}(B;%`*oRVz}eBKdQ0Bx`tDog{K3ExVD<KeP zBO}Tqvr58`BrjtghX&)WeL-b!a3`uo4MYdX8-iOZ5L!*za&lh3RO)}@~Gtc z&`{kLrO9@UE7gBarkO(z5pp_z7ux3qmp2KW+@!4fn}#QEF>sbpP%PL%s7;aP3QrQA t)MBMG3zs=i46A3Fyq+rR>)xE4cWZD#Ffs?41K#+*4^kKwsN#%$@HeWX-6;S7 diff --git a/docs/notebooks/logs/plugins/profile/2022_09_23_15_41_22/sebastianp-lptp.tensorflow_stats.pb b/docs/notebooks/logs/plugins/profile/2022_09_23_15_41_22/sebastianp-lptp.tensorflow_stats.pb deleted file mode 100644 index 0f824ec2df1048c89237ab34aae61510c2d2afaa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 131384 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 H4V(Ud+WQES diff --git a/docs/notebooks/logs/plugins/profile/2022_09_23_15_41_22/sebastianp-lptp.trace.json.gz b/docs/notebooks/logs/plugins/profile/2022_09_23_15_41_22/sebastianp-lptp.trace.json.gz deleted file mode 100644 index 3b9be0eb0c8c6228f66bc38ba712d893b96ac3a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21611 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 D-{_*sTBzy8+K$4B|i7gw=;DjagX-$`; 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 diff --git a/docs/notebooks/logs/train/events.out.tfevents.1663844068.sebastianp-lptp.1320413.0.v2 b/docs/notebooks/logs/train/events.out.tfevents.1663844068.sebastianp-lptp.1320413.0.v2 deleted file mode 100644 index c3a5985d42d0cf81f791b22b4f015c92de59526c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 671910 zcmd?S4VWcYSs>h1w`Zp3&190?5Xh8@Ls%g+LQmiBnMvAJOy`eiG6|U>fPmLKeQRbe z(|vE}-rJLz7y$+OQ3HsetH_Tc3(=q=3Xdp~<=1ujzEwZm)%{!-SU*;M7DZQAS5dzA zRMn|EZ`C=cPW{~Kx;K+2GyPMy&Ut^&`+u&T^Z&g272kQ?e*E&+ulNstc$0Ja>0zhW zfA*~x-2Qm2^{R8f@|iu~&3-#KxBmri`O^MJAO4Pyu;;G(hu`=n*n)-L*d2DpgJJWs zdp0{8?zzEc*Bvfi279{WOWSVKKJtXcC&Iz@U}wC&Gj5O0b++A6a~|xqIrfnEeUp82 z9Xz4EGjfOR(YCwMJJWN!?S5y=Z9+3#0tNtlx%M($(BR|ZrmivC6#StDSKJW*c)L43 z;a(g!<3Di1{VlE~0KFcbwsuwXvW2hlKUULTup~di{Tv8z#PBw1?uGf5ZQF}C!sQfq z=CAxZ*xTON?2JautKf>}<(q?zwQuM6LtH+2YtVH!m(Fgtk1UPG!(JCrKHBVUxcFUX z<9u_^&4d1EEMl#(=p-OqfW2$;2$a3}4Y21zXLHAGK4HDN&}e!;yl%nc9Q+IJhr{{> zk)*+r`ZpQx$Y9Bqen|^A&i*%F@-Z8(Re{+&aMDNfNrq)7!AL0taZ>S@`a}!a?8?!( zVXuF_-MQEswYNH>^G*BOxy7sDa(8pHw>^q}Xf0j|aN0fF>+{EK_E_J2AokgVu;BK) z(L+y9Fv&G=wT$Oc0o>8=x))JPG#2-Pbqc?*;T&8kVDKc<7|lK2KaLW$;ingIGbk_Z zK>27n7G9=i$@Vgpf+uq3zI^?%fVr(T%a}1N*n#T=sEEArwITudM!wn;*Pjrs23&`H z%`)Xj3pNdw4TV4sWQNs#(*{QkWsLt5R93Su$B<)yLxX2p8a-xlR%$RLN9>tFaOM(% zW0?rf9K6+nQv&)<-oN9z5289AoEdL#?u^+|xHe%;qieV}hc5FXT-821>~wobg*Ms( zp3Qqr^Xi*-M&rTO?ZI!J)jG1ejHeG;*MUz7KV?BPiM-~%z~FF7!fYxP7n^WkAbO4%o`I8yu6&Hao_^XYMiqW_Xf|jBH7OCq~(ro zq_K3&i5m}h+-~ne*-o5MOjXn>@W<4NE4r_Q77?AeqAw3USE^0af?>rSx$HYA*O7ar zO&qy=+mSeO*(g65^@$z)$l>da+-4Ml)S=*Na%p$=X4MU@U+ z_E#Yq%r^ZAYR_k1iMw(Nr!M;oW2omLUL82_N$S{TUzEFZ3db({3%zKH=-B0W1@rHT zdy)MeoH{z}g^~#$Ey@hsD^fUjIrg7$?sVGYshVlGQ}WenmX!2GFR*UzL~0sGIp?sni(UvI&i zErQy+I^(-`Hk*6>e`TnZ{cQ0nxNJP^^heu+k=s7qw670SB{uzC2Y)x0LX<=BB9i9Y z+Sy#X$cdneqR$yd(KiSM@YT%*0_=zhCvQDM6CWFC+YTuLud<*e(7Drn*`U`SFKu-& z$BU5$j;W>St8I6<#X(f7K2;)}`FQM)Xc9NzS1ou}rd>4mpW<6{Vtnf4fG5O<263$B z;Sk&QDGvjf?1fhl3U#{O=AN6n-TPXJEoB4FWH&7Ea0pHl?!yf*pFg<;WD~L_d{6_Z z_v&yD@M02W!&hM%Gvsl>H&f_OkgKV_~dO&g`bv0SzLV#l3D(+LUyHS6lEcf)tvARIbzcrxx6pdmDkXDf)-z za8Q%RDT0iMkrZb!yvKqYa)B9gZy7+UQp(}};T;yN<=Q849&>{lZbY?H_$3RzHP;5Y zD{8)hUK?6)i(z!y|c#%1w5`;mf&K?&v9~8140E zZTPla49NFNoV#MXB_$4dHD69w?S^BE$}}HyDB`DW%RlN1;*MB0EXt&J)ec2;ix&j3 z8a*^_dO0&>iKBcMGg2GGX!FVrqjZp9v}r2~6}7O3(0pfRyteRgg{HmaHF?wv&_#r_ z6@bB75rFd5GE@NS>J9m7VWO+>YFGuJP71HYGF+lz9MF|`;It+)*sLZQ#lcxNcqU9( z8C4Z}<%02Y++C;}!dYFEsI?72WT+qG%}B zegQlowzi)O4+_Aq;?b6c^}QHv!9qIG4sR%wB|ZihNm)AsYGcsf=!}=V()1B>`usgu z-0mnqXFETE1<{sHq$2Pz>cYyXSp_w`gs`HpviC#)Sd#;`e|?`9Mv9jZD~?QfzXjLC zFy;f+T);AY1Q2~^DM}r&s$AF=#|NRK@O!pvEfU0tQ((7wMcfR1Hu~3xV%r_`-O-ZQ zQov&%D)06y&k?Du^}4Q>ED}_U$kFAfx5de7v+~_oy@)zoa|m9LpiH;dIlB}#P~@ih zS@`-Gc;1WqJ6rAH;DIn?Ne(3i|19d_m!Mf_W3U-6q-$!m_#=!*Yq%D}JYWIxT*325Qq17d?Y2vmi6=b#Ev$aO- zYK2B@uvSGzEMF}|=VXo8)l?(4r7>cI&1wu(4vx-<<bhBeR9!Ms?|6PekNeTd{N zeZYK+FK)_;O>qPP(f$QHmHjZ)!iDdSn;r;QuzD%xEH-*PiCO~T0)jysGtxP73ByY< z6F-c@moIr{ZOFL+E^Jdn7rO9uiEWo}*#1z$*hc`^GJ$EULY<@A9Os6t=Ix6llso%^A_qJ*$^zVK zEZPwJ2G6wExBxP{K%WBf0^tb@n5ht%1)Pl7dIJ>Vfn9lXxVAOsSoKUDEEzF12|HzH zHecW{7ow9SzG%qQa!HahuEwUb;kR{6eJsY*i9sF8K^*O1!y4A(An6<~{!Gorb?gf! zbPzWX{=|a21bZha&cyQ~Zw@tavg~qa$s6dAnFqjf%Y0sAlbHp1Hxv~7luJBWje90u z2s%vE3MHyKWi{@SviwZTg(X4dq9HWwG+M}l4_R2X&7u>j{ zgs5Z^7_rc2?c$ImON+!}sJ!Col)@TLS#&aEjDJ_0F?eZ@P=-_(240Y4#1d#5Jhvco za~Mc@Qdv+qCCiC88o;=_WO?<*#ni?Xz_}=5QaTg`lMa-lPH9v~agT))MPbZfZ}KFn zlmmR^etC{IS%oo^1;9#-nXDVq7&BR3MPnRNV-inFG9XDLPO&##^Xy!NZuQ}P2wWM4TUrda7ES3F zZUN_QUnh7b44l>^QT?_gsl!IuqQ5ueW$iN!w#E9hu^A& z-oiq~f2D;F^`KZRqbg!ZMdTMP_{Nll3Zaq-jAI0f4jn8jkRQ=lStE9GM8xz&EaF9( zIA@SFoO~!2fJe*RGaPiWH30v1^h~Q@RbLaBXg75=*%?xF746M?ca(T5tZv?Akt(KW zAqGCKp!wNt#ygpPe-BVp$7P!!uFBGmbMAxz}Um6$grgkKz^KYUd- zjL#^sqc^vX_@v5);mZhGLJN1=sUq6-5z_c7z9pmWxYEic8uB8KgbOg&)#rD)uJHLx zv3I_?h?NNUYDAQBk)(?6s6pe(V`8zEx{7Z^yhT=*cU0cEf@_ivx)4dmfP{#^YE!W& zJHRom43}53uq!@THH!$FP7Z8%B^~hOg5`Zds!zQTghus5 zskOL+3NIwR6TUJb{!(tG{S$QDng41*Q72(rA;r4^yrf51*dM2snW-ikd2CLQjCs8f zq9-i`xgIl-8D;)1vMVGi&{%RO@+_+ z=_;O)^_rY>X%MJ#GtPgJb68ifks#A7RyyY=P`+tEAxa|NQUsUSG@x9=ig1ZAn_Ld4 zDnC4g0e;qke=WqhvS5{Djtc-BZbr3R_@D*P$+=0MeH5l=eblimoBy*`$rUi|`zsknPR;DxMz=_odo6AZf)h>sh3R@0VnDi|&{d z&1BgPJ-YDRk8Z3nE=y}I>n3Socq)E8ANS3K!Wbk*g=Y?Ax6i*@?r8^M=~?1#LC=o$uJjc;M3k2R!{_O>6h-%?w|G29 zrUal<&`$D;HpoVbp}~E#=c~#6;_TBHMkHcRo2HJ_b|HZ-y4ZrXn05`RcD7isXo-0X z-E1+wT1tSCP(}+pXlIKZkF^LTUCN`HCbnR+Bz-BRSX7g>F%8EDo7HeU2S>;8 z{FyNPP@`#j(sS&1?(?;xb4)l2?6gBodX62h@*KO7O11oW`WF^YW`8p1dfnyR!J?5= z%a`@n%(krVK;z3+B;GfsiuZAicn6!+h&KmEC*J%SRoiPN6NUI$L{$qsk6cQ5Z>O&r z?`MlKOLe)&y~G(A?VOHAS0qE9)bJyJ*cletHEu};!-X$6&Hp0=G7G5(U`g`7xlA zIPTWV=lQiIB3`{0N3WGsjcCWI!po&ekrjDH&!d$zqZe#2+6c{J$_H$-nXxY=bwC{6 z)upjlQp%YyNv&9xRwX#JvMqYOk4|k3X-w)hc|G`Hd1`4j!lIbsk9Oe$DMcvGePa|? zAyl`UB;U6pzRxYrNxt{WktO;q&iA-_1V%PO;XDzK?{nu?DG^!1UX}wq8WAckTk-^U zurHJ3Ya^Eb`z}(R;3pMPF_ltPhm+mJI(+_eA^j?YenpyQT$TRxD5+rJ3-~26K_EO# z&FWlyn`mmhc3Rw6Sm`Aetcis299L2Y&v(L3|L~?G&UG15i(j(fc|w4_Ga9+Waoc0U z(M5^e&a1#Jv^*;Hao-eF5TwkWy+8wqn|JG_Szi$lLarF)Fu;7-sI6C znx-}e_~Nzwm&0Xi``Ojp&Bnr~Z1^n;w#tJ(MpHB&hrO=bZI3qb3O?%F$-|;-Xb=mH zicn}p93Hb^P$>YBpQr|bfl+4=LZ4H8#OrRUOBArdNB6+lil`9tV<#rNPPKC3RL#Xz zFDM@_tRAfbuYNXk(=ndk`?MvV^U}Q!CzqJse(;6 z_lNs;CMRu`p+EIZ6s^Y4x`SV~z?~ejebbT{=n5xBd(i_qbKvt0_?}5`Sup#nIslw1 znBJ*|*dc$hFZ}i!y~+01^CEk~Z(5T)cY`1T^^b{jueKi=i%;S4x@*^;h*#mvqtV&8 z?f|nLn1#pwhrhAQbP(d!XR!Uq@1D3cI1`isLX3!SXbkMSguQggE+c4^xN02kHH3s_qCUI@%$v8e`;XRT^%($Ab9AR4_DFl^T zA2<8jp*R;_`;`s2-W2edKp$3q&SQyo%T(w%N}bFk$oz?xH$25X+v~TtI-~RK&P%zd zqx`3ZT$GoRmM+)^J&`)WPKGjfQUx0uC2#ghd(%A}Q$}yV7+Ol63A77l#?QAq7~H)L&nKhosn(Wa88s=sxxI1D-8erIUyh5l2j_#= zo`+|cY`z?teJ?B;Ef!G9XH|KwLVC1m^s$Yt{3neT&qbX($+UDOb=dJ{K$I8u0y= zA$3}mI%;dtB)&zoKUN``Q3$8A`4s`#RGTS-{^O&E_8OAII28 zatysARVy48Fkjp2Zw$7!QT|VFx_-?>+Z_%EL!3<$&LU_)x^<5IIi4Jn(n-%cSJOOP zATf;(UT4EMDFx&vkDl~yY=M>cDdGJUi+h^yv)12ZE$nN~t-r%M-5I%fxb?feac|J? zY+nD2!=2&Toh`RN9vy!1iNV-CJU-VM<6pheVejNRjQOYDnVvhspSg!eEYxs#aOQBQ zf4H-W$7LVUdBHtAbhn4@2;YL=4*KkY@7(G?`|wGZz0W<|9c+vapBW6jZ#o-ehY!O$EqJ;SDk3-Gxg5;rtbeNqA&bZS)!cFUG6hSj$yvNFhl4XvPily~U8TVO%%wEifxe_J!p=>Lc zEWa<$wmLQhN*raWfSR%FA2u`r)1B4&aLVPgWWNYBFzYPZZ~?3AD+`WqoyxPHOrk7W;+T4 zL@8!I4svV?DD`P|1GkE$rP4YFG>qgV=761trwHqioKt)GNXfD43*>HQ`C^gXDOeY} zDpOUXeAJ1EgWI2)3S>JxnF@!dAG1kIOB~KvG+IJuC!Hpa0Yu9t4;f~RUIYp(0Cc2#T|a zWFX#+vc3y{vs}8vz6)Ec3xq+YY$VjFi#)1Q+E7#jtwr#+V)A80A1KPmj zer4%GXLH9L;koAbZi>@dsoWnYeSq|LH}K8mms z2$N|%f7^uQ;mHzKX{v*SHm0(~q478?3X9=x>1~acFjB=27===oRQD=m1@NLj(O{02 zX+rch;W*aDyF%u|M-Q^Sar*08+30Xw4@nFvHq87-Ez)%;=tX2qqUz=QCMN)=l#C4K z`%?(as=2`2s1cas+A}cZ8A-dejg!E{0n!1qtCJL%)dB(&AxtJP{FYxEgT&|5c{ZL3u+V4;%7MuNF0#A(AzDy zkBq|0UIyz_uj{v6V*#Nm>bgRsu43MXGKVaBderFL6>{Mm25;VwBrkQ$JTIY3$7)#YA?i>LMkXqSw8aWG@rq(rov=E|k`C+=xl-V3 zZ#`v6$7-UaL$bFJ6lD%5ad&vUl!I`|17w5jHYTiRzNy>QaKe(Mtm)wR=Sg@3FAF5%x9`>AE zP_g}Hn6@jbATQ51R`+uwN}dWD;yKnOiYlk9A&lSYsXs2 z)j=HXqzJ{@S+h~<;VZgn4e`ZeX(X|Ui&U`V=R5{cPiu(3*)L~S&t8x}kJmsc=Q}7q zA;$Ulh5_r=#S&T#ht! z76H#7W*!AQ8{xDDxtJL%W(yut&x(k13tv0JyL|PSHL4~~zSTo9FTDB>HPqt|lEB9V z-GEcf1(BoHQ4a1%?#EXTDDK%m(@IprD_jQ7&-8*D>@mJ_bZ*#VBSbFtMtsDJmp^qk zH+$Qo=!d4$oLI?UI!dwo%@@9`#smi>(QU1(yVFf8O3=e=y4fYc4A$Ny!Q`v&l3=zn z3+74&!3==QAY>dJSp<`RW_NG1LhCr{bqP$>23(*XgxL3pLLl_Pl{`=A^%fizT?Uhd z4NP$Labzo%1V(6-4Rb0S1c=Etc;f|dcUF*7TJwUbLKop!#up=8;<%J#WH)BZD^3u2 zodw6UFC7r_=2EY{J*S>wt)OD`<7{+%k@{Aa=#>n;q0HcqCq_v+_$D_canwa-N`^CV z%C?zv&@$&RoE)_D)VZ#cH@{S3|B*1nC^s$tZ4O$l&mZOfd4#6ZkXHG4ooB8;!yB*jRLPK|p*!9g_7D5bZa8U3jAW{Z{rrrj9?lorO=OE# zKjK6=Krp_?&|*K%arW%>Z}xEZwB$&lASbY#eJs(~9BZ2KCW_`Y)xawZn;PSxQ5^%)8pH2|?HvOAfYl{8c1G4`$t0iK6uK ztZSDnP_N8Pl+woqy>(taz&TQ@zFdU^gHjKDCnK*N$@+oitRHA){lH4r53HJ-Em>cE zjO2DZG1>KOllH3d_#dNLL)gEl3tM`o9kT`e2~p<8UCSIx+*-S`QqKSm6#(B)Wc^`Gjb9?Fv?~`&GZ6u6 zpOlk|le-L$u9MvU`;PVJdiLLX(*8549msAQUdXcF5|6Y8v#eY4arRJ_wL=S$lyVjr zeD_v5y(X?D{Ua>ol_hE;PEf!e$+559vJ&y$D6vS+2!}NgwuiFsxPXiOTI8Dv_55mO$?{*mSEA8BR($V&E)WHBtWbAf?r zdDMA^E=}YUHi%gn8JC}Gkb>Q4kR{p|{wPcH1)XQ6?=95&&ON$^1I{A(i?m3nb8pr+ z;$~8!t2y488kx`W&eSL{-YF&4r?LXZ7oaR*LP?~Dh-+uiXA_u^Ptg&MC= z3{7n;UARKXx}Cg#IBw3fzo|==$$Ec!qGJ0RxO(lXW_%OyDhqBB7RQ2UoC%NPSvzC* z#9+A9*}SFKIqTm9I%=O84%oGh8*Q9y)gIx+D=szZlPQi^eUU;fvx1V_i|hg~TJDei zYXP`>AsF+z_6Buf;eWR9nw%n=x)X1s=?w425?#g~9v)A#Li6DI0)M*wlH{oo8`R$p ze(!n0JXjy+6J142$X|)ctbcC7TWbIr>FQ?sBdW+DW9R)2V`~j~3&q!BT%|4(u;7ap zHYDsm6(z7r{mwkBI#*{PLrc1F1>o!U!5iyF$yhm4ZS;jxQ~7pkD~q+=SvA-5@d`4Q zTaD_<6t$!9B^yud-B+r9qiDQ&vUW;>AH>r6s+Q&mx8Qdzc(^`@W(CCDyi!It;qu@;prEfD-z$Qvodm=tE4|kM?#F%O=&dtu@HyufhflS&Oyhx`mtb-kmFjFhi-D4P?%D z_9FJ)_xfEICwH)$=<%)$qf2M-5@YecWCf^$z8m`DDkOg8Ibx~2tt^*1XR;t8YUIKk zY!7zE+dDzd1uyFZdu=Y=`TtQH9ub{?KgWTW8oR>{cC)h|%UM#uJnC$1<1>oiN^&bF zy$|?#tR>0s)xRNTh$-hqlsE66u;71MQ-Tvxy_Zb&#XMMr#KRBRINM4%5Npc<63Z&$ zf0(h#a$h_1*Xy!OiH5$q@Uq7?}ADBLFh}p?gq}QFPRY1-ZYmF)1 zyV{qDk5{TR2m^m_!3U>9ad;Iiol#KK!q3rb6IDukVSWwW0IawRPS}O@y$g*d`;l1C z1Al43FH8mGp3xK?nYqoT={zd^y1=NeM;_^+wADGH@ERL_V=CxQtVfQ9hz}m`h$zo^ z`t-uI=s@vmG~|Q>C;cCs-0W?*&Q$90X*|-oEIL!IN2YrB*=AUl8!%Ry9Pkeo{OVL3 zEhIR(Gz#wzP=ZFSDJyPGS@4e*d}t~`j}FungK<%b9QcFzDe=Au-Q$^uX{Dbtg^>@P zh00^V4fx#rlo%$2uTY|5Ij!j+5CLLZtSM>{hODFGFZhWD{L)nDY9Zg!T)3l)4LZH? zr758d;ih&tDq7o}0l#n228CVDY?PC(`7;aNUL$rRZZ+*0D(q7Kg$3`dH>i=hQ#kc9 z1;CaUBlz4t+61=Cl1Z3276+I*-R{&}JvgDuqGWp+J;PA8GJqOhV=-d|+u@WY>2 z@KZHX*u-cM{Bq)&CcSTsYx;Q$e!9j0M#quTyQZNBNh0U9^R-gVgobfXsNS@o9gKB4 z;&lE@==8uBY}%E+%Mi%j7t+7F%R3~zYKCKMeiBPmCk+70`ts2QCDrnOpi&4@d??xn zq^z&}j0N9UUBw%*E~$&8JE2Y7C;0akykb`&iH;okeq$8T09*rDLI+2)O|wF}H|`}} zbQ6|q!eKH0rE2x!?5<=vyDbj8y@6JEfSZgCNZv3tp@J#EG5+^gr>VShai*KRFPtlc zmDwOCj-zaCYagr>gw#T%m}*tkckkj6!BhLZyi9&XWT-a!tOeg+q5nnnDhDPy@x%f+ zt+^+M+k#qv6CQesU6MLK9hmU8y>Lkov?>ohBnmCxsb1IYn&Rh->C`|pYOn_{I95qN zW2P7yd=#(ctxh_KFIr0M3tiQRc5nZY)+N!qWB^MOz5BUFl}0(CKs<7_tC%Ds5~|eF z-0ae)ZQtFf@)#jxLN1FHTZm&UCX6bw6KD5MQr#IJQV@Q|CS!Xhj2n6IuR6_L(A<#OUxjGGf!*8A~%%y}{ zV_uue`+T1b|8<7giFkxGmMeFkVrbF?7UAb@_;0g~s>q0wBP$lsc$_0Ebj&q)FpEb2 z?SA;rv&va9zklY=E@#Hor!(_9Z{{JaYd7}WZTO>EQhV~A?fjcw!?U=xU`JSqc(hDhIokB_Z(SiW^0VEH0BySF3?q;;reQrEe%fli(;nh44+lA zYXWf{;XDqs;Nt*B!^(Pfd3C0oAR9<|+CAIrx3@Z@^G*9&dGQUr!-oGdLx*e_&1NH7 zOUX^X%Z5LmVFX16h??m7L;zlMSDm1%yNfDd7!G zk*yg$<(!#NZqAHoq#1!D>nujI5K`fR5$uM9$EHpx5reIiNE6OG{`l0RAv(TOqDGox z`u{UOg@+X3hj`Rz7U=3sx#1Ajm+L%ecz>gWq2n6!Cn&7eJR$hHrZvjKM+EnH`shVu zNJplSmhk%d5@yzEsF90a1dg~aC_an2?CqXRDS;Q*i(L6yU1NqBFMQdCx7F?d6_6*$ z=G$wxPr|dIeCZI6qm<$72{&s53kxo_gQ_ag+ zyaM*0ciruFx3@KF+Sku50?eQ4buW5XDDvTP@Om45rUHpcQ-rm+L-0?nn&W~9ED7Re z3Gm{a`r`93(@)C$Bqvd+l7qQlwMv*%Uor5J=SOIsCvZEJ;FlMqeZxWtw}e(k{a8SD z3iPxyb&92gn-ePI2VWJom#1*gSp%e3!{t>>1A)IP;|9EmGC)m*(?&1nkyP-p4HKtYVzhl8`Yd{H-#%RKx3!Tj!x4D0P-$J7~w`Rq1j*0*P z;I%$)tpPAZpO&1g_@Y(9wLZmdbP0%&SyDJ9QDY#>^Ti+CSHi89B~voyZ%>Vmc4{j2 zC0rdcg6Go>Lvw3RWEcxeYIyJgv@b4hF++??Q9oHulvmy$eo7 z)u~QpoES;8%13^`1?MM^>$^G^ds{nOOBZ?WHn&gzmv$A}C)jUuU+{%fC61g5nO`ZX zVfpWGlyEy*y3?{T=x=n!OJ1C3)IP%5Bu4=wE%Cq+TZONT%DQ`||2rG!tI)Rrdq!f8 z72GIlSj~Oy9Q)x3Z}^x7i&*CiTa%anfV|$;_IO9TlJU|s1H5X!ij&;madQDTi;Q_+ z%c-1=j#R(ovQsTDM0^|Ys;#j+ZLvK8=WW3EPM&W`h5E>A)mrk{mn*2kJu&ZX6u&+! zT|vp<5c*^)ut$7(a(0tuN|j^Q2lGiAez0m^GGI9$dC}?UpD%^4oy*TROcXPnGohrz z?^-oMBi!%OzaDS%ff4jJ-k$=60p|S^YT+UcXD4Gw2$W9o-tMSRwW_ z?F@g^fY;RmEa4vQ=nz0TRC2i@Tyl+`Tvpj+^NTkylR;AihxjuJj3_N$0vN#_*qM%_T5X{g>I znG0G0LV(Mmk^ozhf3g--lK>gf(8P|?8DjMYv%D&hAKwQ*T0d&W>OktD<~_|=ecgho zfIBso${O!YUGGs*!)IjYiiICIWFLO49)d~RintS-zbc|;$9||wbNjLNJP~ICr7J%UX4=s|JAj4^E2k)p6=^B@Z}-(j$Iv4F*zsRWJy^#h zjmttMbEtC5X{~ox@x@JMHU{iQjigldlJYH~{8QP{xk&5;t7$ihBDU~CD){kQ*g0{~ zq63Av%!ZIQ7^Lubjhc8@1h{w!XkGE|)X+1HtaVN71pc;BlY^De9XUGIhFA{-lTA7` zIqj)MqBEmHmVhtVH6gn^e_NmAL5Q-$?)}SPV=&bukk+?`362P4?kUBvTf~bHXE27cBYKAoZ5^1VrEw18sCPW zo`-)^Tb^m|xvAU58s~a*wNu65{sJdp5%zevQT^NvskstrkNR?}^R)Cbm_gqas$eq9 zEqu+c2|YU9E|<>A2eYUc#K~TVl$`>fvujd~4X&!#07Oooy zONa;WZoPj!qS2)AxZSErnvxSMd-F^~>|KC=Zq&pMzSkYG(!=Jy;0vcVmatPV@mxFr zdr$eevX3+tR}=BY>)`O(lSxRCwH1;dgvLE9$awWGX`eAh`A6G>k-N0*4!3yFTWzv7 z7N5d{|JSZRF=&@;Tz7!Q|84x=!vDpFe;$S-UFy6R) z)r0IICz>%biJBuFb02=Uc`k#;-U#u}%&Xn%ydXy`b=B4C zK;^;Gideu&in}Fu60k~i&1(i&d9L_>+zYSTr6Y+@EarOe(rgJ&v+P>yD?x}anY(t3 zN%n$e7c-mCLLEB0wF{1V-_=zc1oNU}%k3J^z+rRB zZ1^t?_`cm?o`i3^+ZLj;%TmOtW5=A?8xqd!)8JpNU6=4*i8IT7Th(O@8gJ0O;P!(W zpSJI5n#}T|)~YuC`TyCKbmV0NQGmJ`U0qVefc$Lxym`z81%w4R4t>+hT%aqAE~w2v!+6lY?1w*^UG9p-EN1W=b7o$V zI*$YG_c(xY_eafOZbWjm&^vATe`iYpmOZlO$8Gq3W(q@|5gVBtxkum3wyDAAX_RKj z{-O>4eWv(`Sp6Jb5nsto*$kHd;{;)$F)MV9HFPeKVqmNVZ-80T<+Kq$X3oy^xi!ls z5!V&Y<3b-kE}&GKxACl|#Y%tO&CTBSNK9ZFWHsj&)$@148Ox%T3-7Ywk7w%0B~u54 z5lq6-VQH|GoW}$|Yr~(+G>RgFgh21jXd>xkHQwO=+B0KOBEm=U!9cUl56%on{CMs~ zYe2$h_sp1~Ncb5gJ~rxVwg^sub!N;8rWU`}4dQ1${Er4sOrCr#M|CM$A!{q7(PxX& zgp1qDW|aO%3qCxBlqPB8-0`+I*?1A%^szY!6VY;R!EDtYSc-_p9K6|v&&&o&A~RJU zH_K2NG($)!FE;km`{85L&MC3@*UX-I&WxxzXJ&NM%s^r|;#*f&!p%+=JctsiPlPK+ z=Z3xh`B-7TS@;WHW5dU%P(2YNPKZaT19c<_BN++)Iva1eoIWEbj)>?uCje)PI(=<^ zDvvCJinu2}8?<$%-jpzNw?5E-k4~X5%H8K_q#2PVv)JCl^OcOW%^D0Lki@mZlrx#L zQ}n=6+^;DxGH)Ugeq_cEe{EMX%sDGR2yh4?u6Nc@+Yrt*)0;nR!@DbhB&7!g)9ht; zfdsa1wyR!oYFyp1QBHvFs}_8q=496dpjQ_^BAY0xTd=)|1PHUhlk zzVa&q1RFDIoK>4dBYEe5VJs^d+JQf_;5{{0hp}FO+@m@c1^guk)i7i)fCkjPgl*}cED;FqTi=;(mVpUL~geC_>WLhE>Ze)?$UOjR5r^4T;Y z82I>n?Trh1k2EA6uStJIP+W1=5!z#}!+zycbC)KJ|mQ^Gq~&&&^c zt-tWuU6`^gpf`$&l#>AYq6I%u3+5uOF0DD%XjoO5F=-Rql}oLpG?M@s87ltADbtYO}5Oo-0ZnL?@}} zNW&jm@RnL2jU4=fmrUHnWTmU7-576S`SDtU79B4HxMb=>1Ki&=YNBun-Qu1~UGZQ2 zeN*X5OlRSS!V7<3!y9YC)B-?)d-0>S*c;)=5O+ER!-p&w6)itpXA_3QwMkjosI#@b z=`L*y`Wu}w2Cy%5Hh0`n`-n7gmL*k+rBX1caO0)i&iB4~cv*FO7H${V4H7%GlUJu| zhG8P;T^FDeLFq*U@R>#xta4&7zV-f{&SrCge^trF^%{jCsMjdGApFp&P=Jgy=;D*% z+FpNSu(jP8_fBuRZNCo09S#S>rhPq2)4=BBh5n?w>28egYc084wVD@W#C+PfR-&c& zhMNogt13u4HEdof%NQ{__VQF{Dzp-&LgDI)N-c&~IrsVg$lfZBfxtX#?TW<^QMw8R zP^GfrR&OO2bZgF3;aU~m2PFKcLaWFZ3T_q6Ypf#q^-J)}4d_k&EKS_7w7WMwRUsB! z11#Q<_tGSOhQw}Rf`4zp_T)(xUXe?#|NSO@#qZazJHZvd^VeO;uJ~ow`?70(8~8uT z&**p(-qV2d6~ZE3_gfv?JC&0wVx9clhr!+G>fTB%m6a*CR94EdR6e(-LQ7?3S1gr? z(zW-J-&R39avCfSpSiikp_>xckjG(utP+(USR9xj*~f2GukxU&(85@Wl>GtNd&&!z zH1WFi#b+iAk3;aJwQG{MHL?pDaYotM$sfdC!yLbdy#jiKT%a*RqC3{(7qjEE7brYQ zKqJ#ZC|^=G!Xr+Fi$?yP1rJP~tP%*K%%nWZU~D5=uzN6sRV{KDXp~RGVix?5JyqmZ z2pwW2D^*E%@!1=>B*xh-Hs7s<>w1}ar7^+PaxCp1s3blgLKS>fb*eR{0tv3T@Fqg*R4em$oXkOG7)TLc4Tz@#zTz^cuK&?W)A>;0gm4 za8lB*7xua~&UJeI_TUUkK<~`h`(mSmNyV+s_=3C9-t6_=&age$c88tuV7PQ@JN=9=g-}@ZG^@Z|QZ;F8Qxr+S=J{HgJfPbA=$`C+{DQoeHhqaP)v}ObU2&175dl zIA;_JDbVS5n|p5RcJFIBQ_Ka!4GNbTbhx0}ibya>d%+|2Gu=N`f#9+16q{osP# zoNFy${MGv-24QWiq(9gm?2NZ}#{N+-YR-ebHU}?;rm#Wp)sg95^yOzkWPhaPiRL`} zn;^wo(~<0g#~75G4>8FGJDe22=!{10kOSIoE%mx?f7}~iYTtbKiIb=9eg4g-ZoQ>_ z)2a4&u-)Fo#LZ^NboaWQ?tPtMuY+|5cW*Zj((j#9!Xln8+di864*zVycL}?QgL9$9ky$zRks(b^NwI{4MgXD*OohNUHP~t=~ z>cV1durS=OLMw7>Y)9!NjD0``LL}2_Aeh#uHxQveE(e08pxFQBKzwEo$$n0jnPLw4 z1f`gm-IE2%mk_6Vey)DW)}mfHJ!*#s663)1QRI?-4Qnwz>S>N$&zCmp$%bFGNV2GO zqTh?hUc3Ipz_e>zcYqla%(Tm5 z-ZkJKY}lA2uLb}_0i+5f!}+EIi$jq6GPKvx7<%a%hN8ZC zkbdt}A#qOCl<|10@>M;4SY*Q2>v!FYUM)coR<{>Tr0{+?tP#SX2Ef<5>Tv<~qTI=2 zx;WwF!2@tz+LDnAT&A+$f@f+L4y0h%>7QR>f2pO+rcSFuk-+!CHybWT&}>*okcM-3 zDLmhB`2h0qrEM>WGVWnKee+Vg>yF*w7KY8c?Tx{3hz&Mv_DFO7#Nh62I03gAzJ4^u z-k^>4#yNN6{78H&uF@Wy58gL`XPLbZ`zZC~X_%4cRTezkctt{?GI_EMFEHLjE;`)< z&oy4aj8Y%8;7P(O&khGW+ep^!QM={S(z*S+h2O_d7g5eq7If|~e33sKQpaWR1q<#J zcI6SYy}X<|BwWXMa~H0bfXEeD1|6-bkFnuAJVjWA_(u$(NYjl_dCG$h#!){Dw&1C$ zi$$k}e7Tt4sy@dImkUFig_rx74PU1LFBXNA5!Xqlg=2z2lZV(e6KQ6OhR_20qk&J$ zuJyB6kj&lO>}`*FBTVg%&NuCA=kmqU<`iN*TWKVzScgogX6G~$ft-_iv2IbZR0dwS^dl2ONq2VnH!d2NF;FSQ;%o??#iuiNm{gsZ%VZ6+4lNBOrz`S>jP|D4;Kw zDY$0CCoCA2N<;$~BBdcWcNi4x57B*Eb7xne2z8MhitO3b&(a2^3G-7-!%b3@NyFZR z!3q+nyTH^=^=k?hX`*UYSan|NGk!EEPLR|LX=?HouL~i)sO8f=%s`UlSYdxe-z^RPzDN2iGP9sLtm3ELwS`H7TjC2~jF z1?h(Jxa4tfj=nMCuj-fev#JK^Q$^+#w&9y}iZD@&P+WA*rmt8Ir@xzqtSQmZ`;I63 zCu<(k9`jyK$am&!abQW5Y_Xf41$- znB}K?(WVfLLOnqSNApS_@wXsgth(mD6-UftP^#dBb_FsVu@FE33Qm}e=Nx#G1-_>V)< zWdYEV-X(Qb3t;|Kuj?1pTmk#fyDsLrds`zMY&sVr0sgB+GVCXN54tmzRDK?53}fJN z?Lu_e{^s1h)*&&hx?kzpo+Gckxq~fo^XzZhfr%@zDIceXJ8XQm>tS7$fJ9Q=G8&)4 z`X{e|`s8qfeZ3!Uhl7H2o^a1L8~7Jlhb=;^YQZ}zBgyfQB)S91 zq%G@O;Fu~m*pxdY7+$)@ayGNEfWYd}(!9apNd;}VRnnqf|bcX$aQChLH`fw%RF zO|71ebwmQAOoiw&eEVqUbbFOScbasVdW({uu+;>vS7-qE?!?}2llO_AaznmM(GZC;)%u z3%*@sbS2{8WyF&U7hs(!oy}W%7YIf?;E2~2eqia6O2LOfqB(Pwz^3;yeYMQtNNNW| zP4!)Ht?*J*f@fV{bcW%8g_7UhbvMTy^}eZAQ(*;1bP)3)*m!dfqUEgXC}DDvD3m_z zZBl(@lxPvaD+mX(gY^dAz7WmVkkZ7!2(}&4SOspNGD zoHWq9?4HfehI?+X*>#7?#ZYC8&ULUR9mivcV()!g`#}nvlL6yp?e44_CfTaXaBWoo zky2)j0?O$v0uSrns4B;ugOQ+5q$@@0_#1gU@e|jd5VR9p>ZW%!c$mIVT{H}S7A_?E zRa-EJVi3lv?;_VdU?(Sq3Qp7#7<;o{0EYqnv?s#iF|Qdb*LaO&OMurokXAf4r{O>g zy5NM0WI4E)k58}s`)or#6Z)CbsWshadwXwKh;6SahMo*^a zK|FBMKSNHk0bn&c9@YAhvxJcPR8r93nU<`XDp_`G8x1DPAr5#@rz&^Y6dd5-2x9E% z+cctHijg;xx-3S9<`l+(ZRK_+?q~!t?7`tGuRKFz(_q<96bsr?7W|g2k->N~Qxt0p zDXkF(-pZs_XCW3f!oZ)YtI_dR3!)kUM9cjM+q)1IG zGD56dxLtXo|4oD$f;DTgvD%!N{jbJz=_P!i25xc7i2;T}~$ zz(;IhtW2JxlJEUQbAR|{QOpOsFIN&SW0AzYFyFFmdvOu2YM&i;x;>nIjq~k&=kl87 z)i>{q#)GZfgWo)>b;I&eMXF~G=Y#*0m}v@;*W4Ez?9Oe4R6~ePOzeCQA6?i%(6|ie3d*tX)oSF@T4~Nig{bz?5c& z{VugtdSwkjkBUA^0Fv4{>UuW6@KYBPS)o3dJW{~oA?%O1Z2p)?uw)byQAcrAGc)|{ z#5SZ2#PCH!M@$ZB_LvCvkg7#yB^DDA4ZOUZrE%Z_AT`bzN5itgGxB?qn3XRZBxBfe zY#94UW9gU^7i7uHcH$HkG!p|wqWh1j6IXO!S|_gP%R`kZinXl`*vA~X>^msek$a_0 z9JzekkvMYMUlhyAigKR)Wj>OklU1!BEoNSdo=o<|q|RLS*H8qQ?H%W7itFt`yofBHi5m6WUSE_#rC_fNkdE*1iLYR z^LbKlfmL{DUvzgi#=Suw>*Kqa5*+c|i^{GtZoCDoL5eya&>7v?@=GV9$~(_PMc|0J zEZvn@lo>CWw9MguGc5+duFJddD!aY@zr=M8P%Hb{;#F|j7^^!++k=tY?s#2RdRzDq z{m5zjNVI8k|JgFTTQ4f`R_6Q-qv#ui0{Cjbyj!eq@zx_106sQMk$MPTWkE}blXSW- z8}#~Pc2^)ylgHb-0!%GMU*SadEzW0ZA1|9Xi&w-%)X4#l z3BLUHTl7p$c^JUrFDx(?Wd!T$c?*vCV-yJ|8*nDOVS$H3aGDg)vBG{#G_wlh7QqU# z3Hcr$G+#r!hR@@0%;|?s3@RS~{Ku%zqfkh2h5&&3L;$?YDMd}`{dno3P=w4_1Yu24 z#)m>6;T}S%&?Jw^QkFNy!dRo6*-fnjS~Nwea6nbWc(n!JBIp8hkjiyB|I~sTb8jPX zHbwu?91d#II7N^VvYs+RjJ0hyB)>V{TBxji`1CzhuF; z=Gq{4MFdB&8kD}v&b#BJQ~~ScQGR+4nshz*oRDSwM%cW(L_0HT?0USm8QMqHRi_oE(?n)uMCWmwc%M(`W zn-8QHhQ_Dn8r>qQ9H8@VCw}tVFeZd!`7a)cn-S4=9XYj>mGWj=@ zzd&d*_Sg2aR>94Eq!d-I8Sz?l3@_~Qr&ukl@5PQB{1IFvokI+$VC1Uz;0QT={vNz` zgcSM}dR@`zCLd(BNKh>j z_0@^!a@5=6P}uB>5!$<|hevV$rS@^L3;~>`Hkf*=lCQh7-MrzEIn8ssbl&?P`tKqZJyl z!CH|KYY3pKDOhhZ^VLElw(x3NBlc*j5xb%>VuQ_U3{(z|&WPpDs0SeK^Sj-RdU(sd z*6ShC-Hdhy#@I8Mu}6vdLrvVHTqCQ^*cZi3Xx6po%^4|d$Ua1JmOfx|Q&w!{B?yT2 zpVg|x5lOMb4gm{RFU6e2Mvv%fNbf`p7Z941qiL}G5f8b9;iZ^~AI9O!v$rc-Vh$GD z!lP+{d{0TkR%L{#ay~JG7k(&V>>~hzX{$n=Fk3gdxolP~=N%jKw8`bzfnI`v+lxDE z2&VVyxQScb^3*O>u93Sb+(gOA;6WudbA{tWX?-oK7-wz{{!zv&Y`K`B8?$KxhH_N2 zjk}F;%IJRY8N5%Wt_%M>!GUTdbD9CXj}KQ#W>{CFUc8)`efZ12_O8GG^e=xK-g6i? zH*pN*U6>F~qLSg8)J!l_6t@yeQJPg6OXo797wxsA(d${m38Qy4?e*b4;P+`+SkJVF z0O?0_e2MhyE}FZ#E`np!5*3(2+a{p6sGL{#YYX~=B_o40yOGV;5d$F&qeVlzR9#_` zZEW`6>0+$MV&A()@H$N^7{vH-Uli#Ei*!86`egtS31c8YX`F+lI0(bOpihJzTi z<3f&C&(y(^5mU?gOUk&K@R@!_312j1>Vo3SduTvAF64NOsp~UMOCuNosx(Z`k*Ra_ z_%o`jUdwHzd3qu{a1C6&b`|NuV`Z>R3r2Dkp8kJg!Ciut5!5c?NtHKyn>f?N!35cB zVCjLWC@E5(4HmqC9@cpPEVsbuH8z=+kat5tsZqJalU3Je;)N`|Em&PIX$Z))Tv&`$ zE*e5pPos1#_>cv+6cim&q*MYj%r^cR3vMsCaY^ygZjj)!c5z6OMNMKER$lRRN?{GB zEIOGn2HrqabU|KJBosgueI@T0(FtP+AN;m0+z_*jmE-Ml`EU)AgGJ`>3%w$=R!;ossWO*rvLTb!pc~MMG(v6v1 zZM-*P8!ujWEHh?WCdSNhsWFoU&X5Wre;Ut!#iB^Dz{>CG#SkLDZc+wST5nnuZiOvU z+Klaj=zveKvlrWF#f*@*Ui{iM-rF0i3Rdhb-qSlLCYvL4s}GYy;L0%E(qgz}Ouujo z5>&U;s4kwaeOnUM*z>>|LM8mvB0*1vYRTS0P>g1O5jwf`z3Wto(QBXn(c zXN>X14qYO#(R#Oc#^>DOeJ!s(gLhlx9)6F$)HetoTymM_0$-5S|3nXZ@RM5M=y!|& zgyW)L@wfVAChSg9K3;&`cyT%GJB61!ci6?S+6yqefcGiC4jmt4%>bS8#<^gK-nDa> zEskz6Szb!6k9x3_GMz74@QqqTqAo9jN+vMEg)ACSyqk$8gG_qWLxjwm2YtM6R#wQB zL+sehMX~feTIQbNpo>ij__w2HS_P|m+f-Ft8yzqW-q(w zc)g-u+$i3;6YU}dL!kvc>_?kC0DDjQ?`0>=kwl*L$?)}S4%sgG20ozTP=88FI6Fp$ z$Yq6m1^{Xhc!+F*PLJ^i&X5^2Y@kduP&P%0g(U=XB}OhJ*Hs3wtAWIRzlcOWqm*^@ zeo|$_@MQ!op;O+iv{S_Z7$eOf)hU36yvQRVwwUYc^SfME_k$U(5$FwG0Ubyo$ z{FALP?3Hx5Sg=+^*o3bvTuaKT2|e=rTZ;fC^hr&coF`{d@Jg127i;j<)|#rth2eqW zgI3?+IB1bd;c9A#TSQrhAJD_BCN(`@V2AJ*){5da=|Rb;$YH^eVrpAe!Jp=mGJPjTD7dB)l(k5kliqlN zRiY96pB*K_!e8V2m6;4SQ7yx3PA-8j6}xu zaQv1?WKTOvIaeUP@uJCU@nh-Q-gF+6kog(!(MfkI`nc|^I!CE*fbR=FHd)A#zb7W``=-jxNbB!gT4U}YqSo3QXf z3!am6lROJ4%brL_ANOP;AMmhk=QAU`*beESs!^9;kh~?>znsgJWraw zUnH$K=skodkG&k>Hm@0leANS3K!Wbk*g=Y@r zIQPGcSg$vq8*I9x^Ow+i4Zb3aFv}&wyoK1s7`~l*Ecd*Humr7n**%+`4HtLVb%&zM z_5`Ia#RJ?kcbhiOSNlA@7^CRE^cIh2@RtCz2xn@866O++K|Ts_?QQAAzfUI zHS&mYXWF)P18rEU=7!T?(Gv3)y6I+owUj_(hFNOb!4NmZnv^62)^rO6n>lf<-Ihc)nUi9Didf#~;^le6U#!$8&IW{c-%6I&!@99J?X+`8qA<*bV#~ zGZZmZ(3c;0FeXFFsK#49QmR=03yU(dKNegdQzPW7Mslr=X{T!ta-w5lmpG|Gv2J-1 zj(3EM37`0SsUm&@nWPr~xKA9%0HS4+htyJjHC&#Y#wi`zng3iveoi#KHsE>WcFcP_ z{qvmvld);9A-y}kwC#EYN2&FscyE*QtQ5-YpR49H0L9w^z z<{m`AS(i*A6@VebnGrLR=e(_n@qLBk$>yS-BIXdj55sGh)Lj+p>O`Kj!iyrk^qya8BD&Mwi=)>{ib%AxT;b)?1mB80!ROIRn&1mI7;S_mNtE+! z;iW`3a(Gvl#$JV~np&|6EEN;dLbvGkK01R!H+cpx#^##i2Yy(dV_J={C>{XOE_@)R z2*pXujN&SU>UNXl`<9OHV{oc4ndEz~I$5IM;(U**M_{O4FDDd^;q&;uEJ9)aUY5^3 z8WAckTk?E%u&+hRJ$jWi>8BO>;3Edu-JNT&6)!oF(=8ywuDTq z4EhymwsBSZQ)!OY-#yXF@qDe$0ki?{zZN$Z7JiBKYa(Gh|5cWy&5>5t&6Hb#X`hY~&@*@eIbP@0!^3)KvombpeD{fyr|y0J&8Kd?rG3+> z_84zr-*hjyn@eW~!v{LUZY%*>TA1>mEO_ChHkt7CCXWu$BC|2-5uX!(Ib623pACO$ zHWof*!*5xzRUY&)nxgqQ>~-C4d$fsn0a6c79vx+4j+nzJLZKJy$1E6B3P9v6szG32 z)ER`(@05eU$2pmU@X!x`jS4p1+#l}WnVhs$hW^wuQD$S>@XHpslS8&& z07$xEiZ^?Hz5(Ae=`9Ope^m#7Qw7sI)exJxY<_Q$-ctMPc{x}9rZvfPHwYq7|M)4~ zC%kt3i9rKyDsZw?-ChdjzwT&>~N%+>CHXB+QV z=KIebH+kj!Buxy8_U1wQy;Gv!sgN?KTAFw~Rq>i0A1oS(m?xCjRPA2$@kf>M~sETAh%VdBH@XbnL*SP0}jnj+p>@4d>UbQa3Dc==Ms^C?1*;Wpn zVfou*p=-_d;D6ijG&7)MPOR9QDq#yJ6A7Jc;4f!CQ z!4A7J%XEdt&{FbRz(JT9Ki}?*F)h*=jhEPW+$c@v>FAlLtjxfq*h;o#CuOH};U(EN z5+H?D;V^wS?rn57H!roj?${k}_4=4~*cc3l?#8(773$2N7~H)L&nJ`ZsbosA?7z9a zan9X1KN4S#i?s*moBnIh!!t}aUk=T_7Z!~c3n+Cn8@FQ|$yeOZ!p}$Sjy!3!crNPP zNrtB@sS}VpjVN32Op~pmhAl;uzE5Lli>wt~e$GX=EVcDgc)lUDxkz&YZZmwnnZ%e9 z2Pe*H^_*9oo?eRg{gxqhTK?7aoH}J{cvA{trGsA)kWICjQV2&>dfGBgd_F=a|4?bX z_5PjCW^<4Ck7H~kIfmYm>bSzW71#Fq8-uNFRQIPhUB70c?GA^7AtU>z{GBGd#Pq<@U#;!!JHD7`unZ=Q?Bjt2a9A9ZH8WwbVP)b4U0y_wa~C5e^T| z9PacFcQ)}P>?5WwxQB=C_Rt;STkzXKpFQxMTm5GrKIyXexre)hjnQGOv+%y@Y>bh( zhuw?YczC*9|DDf%>9Y?X7Eh6VDk8xcE+9d5x#-hmDBfF*-)~~QBtwAzA58AE0EcX z*)Uh401NN*s;u;+ock2=r%?ojm};l{0Jsf^J1^636&J@Wl==jqXc zII)*d-Cr(P)wxyuVDK^KexzB<&h198@nd-ys8E{TrY}mh;hhs^I|`#oDLw%Xfoz5} z3_RHOjXc0Dt*h1ythLp4^m$#AVA+9fZEs+(SY)IU720Udv!wbOM6HIR3f0xDV#Tel zH;}Iz9%F@L=#Oc81D9i=YYCloy@A1Yb!~qfB5iLVe<)jeNm@KO=S}u@&-VK5tW*>{CP4H@qv>~n!2c7N)#=B1qnwJURkPU@XRAdnH zy`)X^I7GJbX$zJGg(vhWj0T$*+$F!h;#AnaaFYGBd5!ePq{UE#L9RD>xd5AM-|4<= z(Cd%AfxM>k_?RB@OKvbE0zW|M9$Xc&5?*AH9m)uyraO|{a5>+qXH#q?~r8J|t=#*a>DQx%&slXhK3ykKZJfe}98#uoIa)wsB8*TTpe>Myo55s)8 zb?@F`M3V#CKQ=$8n73||;wnRurt zUjDdUEd){QK<**3Hc|G6s%drp(S}`sA&f&1i%hdgMF|OSDus{lA%*Zo1xd?EvDn7s z1lXxqIGoB^x$+fTCPACL9iNzDxN>xE*kcuS7keWfC`yKo=GZRcwT>1W7TuemG6_2_ ziG^1<68L2sx>f92Y#E)P%vDDL(VU4ajIO9-Nh^FoN$@1Hh~Q5f zq$jUz_3ZCi@GZo~-?A4YR)tdu>pK+@T+Wf9E2U@6zn*7ZfRn^L=~m=X43Y-+Gbp)R zNB_=-(-Rb}MDM8BL02}L`ZD2EMvq8?(b-Z4t!->z%xHpmkD)fvKAK0R5%ZeOuc{aT z(m$FzO7rUZiCP>K@ree~3S`Zxm@Iw^X~l~c?jh}y+%cuvB)YBLwDrp2?zh<_3Qpll zaN{HmKe{x@Ytvsv*iL(>FwxJEltz$$4eRmBJXWQdnPbGn%&o!XDd=N@EvN~sOH?5OebOW&9P!)Aup;1>caYLCy7Ck){ox27ntq1^fHzkRw!_Me!8hOS6H`OeDb%!IRdm31^Uq@plhH zJR^wNH&6B*yic0IXf-ci?~FIjq2yye1Fu+A?S4i1o7HTa zL+>6dLfW`HY<3C0x#Sgx1leR8Vn+q`=?q=Gz;v%)_(2fl@4GF`GtGi2Nm0jYvT%aC ze&&1~)p1a}9otIcMIEckqK?%>QHNx2T$nQ?u(1;Lyz64EDdy)ryt9mUz%K9r*&w^c z2@9b8%Qsb=u}m`Vtj1$C`>x;zEm##qJ}4SO#j@4Gw8}-CvfAm7wg)43Df$XW+Jw~w z^6Uf)*t0)`47#dL_=E*Z8TX-@zUyJn$puw90!0nvWdKo>qVc?Abptq})HA;Hg|A!| z7qiT1(M&Dz>V}o+vBE)N&4>m0%28TNzBb7m>MR89XbHvIVLD2_Ha!eA+-iYtyhD8P zSRP62`Xc4!_&JY3)Z-oEZ)UaSSc7#$lpC>NUH&{?AC>hJ*$Qhb8Tx=%n_Z`YJMeS( z5hB-8tim?yfQR%&k;{BKUM=h|I4_qY1(QXfsw zP~5YBCab_p@|=ovXnG~R!rWs;f9WX2b~#`8vKkYU7fi45W|ssrSUVC-g}j;CYuN;o zuf9uy*~%=KD;Wec04{@&adc!6O#T`5prr~#ka36P`l}1ngNRumLNAJHmTzUaCcUaQ`+-_F+>;P zSjHD4T>AMcFcwI8;+W8&>XbPIXx!_Ej@Lv>*mcbmDnAnoqA+Q%YU1L zmMb*EQH=?fgU;A!=pRxOmsz}a&S+o~-bAB|3y_gX$_Z|sh7e*sX!$G0E5)DX=C8VI zE@gfa>=;<*I8s6*<{8dgzFnJLZKs?IgFxQo5t@!q5)2OYJepPRkUn$$8Q##Ir%L84 z4c+n1uz%R^iNhgB@H3WrnqO=;ku6^ROcdqB!T26Si~Tr9$FtYJ*+a+Ek~55Wj3fIT zqp>;GH1kjt(SPMckc;N4hOjrapaYkrL`3iv`+a=6WD7 z!9R4Kk-~yo%q1(LtGN%}n|W7Z2}8x=gN?D|U`xkeMMCso)_s*IN-xj4b|_G3vO?HI z$<(jROq6iGkcz1@${W0OUOn+SQmejPg%gHS4}B*iuN}$yf#s|pXl4DtO4bjonwu?I zUww?^b~`cI^=y;&s__UQqj^Kvz^DsbdZrz-1^kgx=Ehyi9826<%5U5m#a_d)n1pBj zDHJFH>Vz`ipPeb|`LKzth3k4D0-g>jepD%S(7P@5(BM!3@crzX^@p`j%F)KjU4}>3 zNpAmr$NFQc25k3Tb<2YdY!ZW-JzrQnc;w41i8`1;a2StUe)4Kn?Bi86077>xcIE1 z$25 zv1)0%8-CY)rEJ2M$`J}?iz}gQ!_3UdvYW3 z!j`SH>Aej$0&!>Z>?g7JxMLzWb~0Fdzhl7zy8=OEvC8dpRoREe^kcIScL|u#GL;h~ zgOBn0y)dYlATh(UJ{r~89pQ3ziHVkXYhjgHs4xQKwxZ!(8XC!s)GnF=k!gsLoSTZs z0tt7Bt>Ubg__)Sc(i9;7q(y4=Gsn0lsmy=QBK7BG>@7`A=Lw_WWem?NLRJY1+vO?X zN9N&<(smb9t;M<7xx2Kz`B5^bbW$vr|H^P61@#><)?+rZ)zeV%k*$W_tVV6YZ`j3n zC7e@!)9~yFXNT~sZP>R?)nKe%8w=UNNi zREpSO3R_vygCT3NxLmhzbKbjlr4VK)RmJN9bu0TIb41$g0;^uX>*DARyxyK&m$7Jc z;md$rkEmF1(051NqfjCDE6))lsA}Y%Gg*)kl`kmq>&2Cn0Ri|?8y*pze?P~8cO|>S z4R#l_AIn)%z&z?~ZR0bF-%4^TC%q5&d8{SL@72E{W{4^0MU*#hps?V7T2q1(Qoffv z{__Ji4!05x#M-ie#AM<8Pk`5`OGRR14qk1;uTLuyBJ;8!8m#F?LukGhM#F~|aK`x5 ziA2m!o+7>OOsxWPrdVrC@!q{lERw!RRY4V%&jf$ZuCSO2#lec#+MQ8Q)WXlvtGHLN zu)Y^(4WVB^%}DiCu77F4FH8mGp3$T@G8NTOk`WuzYBBhQfl*zLJk%bey2hY_*VynI zQ$crPJ#sWeeDHWjM0v*3rx&J02a1=YAtxL->Hpy5W^coFrc#ejPY9+-_0CaieOrUCz8!LLrm(L#cgOQY}tdty!DrI^&3vKEyHfq%5%LsJQQbf6O8 zGntZqFh3>UH=%nx^DwRSbEYuz5$X(0I@*HI%}u*;bZlCH^}vHLR%-d-bi zBW^YA8PbFeRCyQ@ZGykB;GOjbH8OYP@q-LCi&Fq>c`<^|?W0X#yDXW6iDPkqsnhLF z&DDcbdzr5N4%Pm;Gy{@Ml;A|{^cEzY{thlrvjTAO98cOlYKX1WL*BHR) zILhyRzjnS>s+rI*?g`bK7PN!0PDh-X`TPZ&cBSt!1akL<^snyn4hgS@4x$d(tocbS zQJpjZEbGfh7bI)>1ErpA*4zgwg@E`_=IL5$hr?$q_`d40^u)TPE|T19$dG>h_ZGZj zS0Rax962l$^IBQheON*Vr!XvU+)KLXCM?&4!(#qR)#}CBUCDBGTO4+K19fflz&ZZ+ zSEs4Ga&e}cyf2(9gq7JKCygG`w5{QF(G`MFPN9+oyQo%qYM+;v$<=Cx5vR%+vS$j5o z6z}D&PCAG$T1xB-UDbznZ~u|j%^%wOxki;nIiWy2aPQ)WDIhOnLHvG5QMpb0Q$s++7g2j&mWR>Tb|LuMpo;~@4s4AUKgfQm!&)nJN z%((h=W?tvbJcKPa_1?uB2(~(-^G*BOIi2GWc^9PXM>T~CE0vPvOVTQ*L_rh0-G)D! zCAC*}&-Pnv_`MmzPb^`QyTW>wO$#0?E-fSTs10A3As!;81xHqz*_t7N^|(M+d4}t& zVYW0l?JtU%t}}dA&8`W=b%gUc(1MQx7}b^a1q{)Id8};wmK(?L4jcZ<3>~szG@FfR zEhRVkE*t)Mh7lAQAo=6^pV>20F(AT2@ub~s^MW(8u{@)=0epJTOc{lQlamSPSt2$8 z)tM=Kms;_c;95hr)B{mkwHod12kfwnD}79%%G&asMnkKW3lM8rE7`U#3EZWddfL7 zq1>Dq(MU4_N6W|wq9YS0kUWjYtk~56k4>FYA_iM2ktUpX{PC$rLv(!Sk05Y6|n!j>u$HZy{%Ex zzJ5-;_8net!_QP8F=>jh>^lT?K`qt9B=}RS=D3In?7{Y6XS}^L_PfYN&3Ulb=4AKY z&q61$x?l1L%?Xw9gRctP%Tu`LYD)ABPW{;M+rKK~2E2(fK-v8xU$WrcwKn)- z9U&^KHmy?xrt7HVCCR1rc>GHlw^~k=vuX7WS8k7Y1e9m&yknt++dV7ffS9>c{ASXL z?w#u8X*!a*swv?XnTcXpt{Sg&lX_SA z!QWW$i&F)1B$w*W8dG{DTq` z8wXc!f{@KSHMe@`nQX>BuWi74Yb_F|*|fG`6kBx1UcD(nxW;s}-S1fN+8R)Tq%nlE zyn*$`#yJhZYkl5Y17L_grO65cnnuAY%B<($i&hEO`V_a(B_Kv-N#T@4je#uB7k_kL z3Ab97Ov#wPJvBPosj1kPaCKD46y`Ct+U`u97LZPhN)DAOd?z02Xvr=1|H*f9x z`IYe$J_7+ea*E%MmhQA{4Eh_L@sg+GN9`jKo5<9DhH6F}u~qoWsI0qZ`oFVrz6yOC zuqPAq6F8yQGO~(TbvMc*R(fAMhjqTNHF^0D$m^}T$2;1UjF(!q^Q!qOPI7<8%>~>n zGUk0Pr*bwrQvH(4PPM!c9ZvxR+ZqP8Nms(BEco8Z^DU`RA9<}>OCI~`6;uYh^u3MZ z*N3GmC>b0=pG*bzh%ZmhZqh8`HkDNxw?qlYebWB_$$Jwp$+D_IIA26oSM}}cE$D8# z9@z9^+mL`!8M#ze&H!E2OVR&yRrhoz?fm1|VRU9xbx@HR*%6Vov?vNLARr2|DXyqL zzcLEAAZ{Rt%LqD(%OGy3GdQDu!Yr;cFz4R;?)Kh2_uls+;$>99_tBkI9U1qYbI-n# zZz$WBOh}F+PiaT4Uq)U#SDbDXDm7gaq=m?TjHU#Qutk=!vP0xVNZ!RXK*%qRV|{6{ z$4DqcSFA=(38Qq2mLS`+*M7=J4W9o5k83L{EMrBCnYWdS+@_ zC44Np%3wt7srRHfB9Szv+%Ym2W(A17I3kAw0WHaIn~GPn0IA;44yI{GxePJdc|E;g z$|{hN!F=<6@@>=inyEUF=@9cwGL~Pr5X#{3^pflR6yL2eS5{pIn6c|jCmIDF$jm($ zvQOSP9gJzV6$vM{cvZxdseLI+3#%fr3qdrWe!zgKAq~@O=nx=Uerih zMXyo5rImkbG2oo-kAD!6H&2C~lLk#Gl;Wn&|Ef-jcVz&VE&-iZ{Kr%1nYs)I70vsf z)hSV|#=8SWr`iyw1Hr~6<0;YhrbQC=?4PPk$+O$@x6_k6kes5I2GPIt78Q}-j>@m8 zx2i%*CNxL#(+DV&*Y6|WJQYfi1EnQKr-K_)^gJap!jM}q1FiJ>dLLa1jtZ`Fl6*-% z9hEX_+wVkd_xf9{ZoS{y-t28PlRs^>TiYV8afl=(o7Ww`=0K%3(>O4b{7>hx3YxU} zuMzp4so*^;q=Vt+X8W8E*3Y~s4A!5hLjARt()vJ zH~BBrZm|7rJWbM)>aan(y-CYkB?Fo70qzm~M1y_gaHgaD7V^y1xOUZn&x`*>#vjOg zX35*9_t~~~yR|B0hvQ3(wBo5}`?=htBIvI|-abp-I<+)Y+jnep6Kb5No2uh72KSGk z0p(-orxWtJYWZ_FtmcZ89@9&$@t0^S6Dfn~ZMU^5nB06zK3|!V_h@Zy3hpd@FbhT? zac~_{Zp2F-BEM6al4>MYXF#Kmyx?FuUIEBLqAEv`S7l1;Xqt_Xs;C_0LQ|SEOu$sJ zYGKxJ|?f4bXzZSuX-nH+7TlB3g6L7B*`sZ5F{q%oCgM?tppQ+>NeYKv!J z+h<6fQ>OZAX3jck);3j#K%M_|WH5Mq64LK_Urgb8qJN$xubm3lO@O7vgZH-He>$Sk zM&WU@F(qkA@mTqrXR1cq;s2>li5>h%dq7JMYx|QQ;;FHO^a)ht!V9Z(c!OxkoC=c(Ii0y+^Ypm}J?r)>i`|oHO@KjalvjWf;@M z+<83bijdOgLO3W~xNh)7zq5U|NxjSFR%>vU<&o2UOL;u!Uyk;SqYOVq*m#9~<)4`) zU$Zv`oq$7gj>{WsGZo@6-m6;()Js>FmJPa!oMv?oSF#!TgDUyzy&;~AZ@bqPV!X#( zBp#(QXZo-!86Wmb$QQ5Po^e|ZAC~^tvX(J8s-fEF+S|z{>?Zd#LuPs9u#5h4rIe1m zd?0F2*A6_e2`K0cFP1VOKi@s?>1_{&g6v#TgNVGpLVl|R`_pm%$JIWVgp?rIY?O{< zKT%Ig?kxYsa884h>n;Z+X>QI803qLgx#5n{&B%7k4_C;aTvjAyvBd?FTy$gi4O5Qo zyDH>Umpigl9Keo}9BSbU0$t;aE`07v@`=lrx>7NV%TSNSm%Sj3zW}7)7XXaYx?1Ra zD&&)wmjJYntkIg(t8+JJ9Lp=n>?-sRnLB#fz8~`D3i4A~#8kUzhy=*Y181-cYn*-cr~x_4%NzCaK*K4bP<$mJ%>%|`r`IeS^_t;^XY z60#!xf{=$_5K!hFos`aBM&Xsese0rY+?pfbTOogVS*cuO>VP(aDbS$J?&c)lUm<^d zS))i9B*jNLeQe)l79}$1C_NbHa;Jy*GLHC#<+MJ!?=mwK4SEKSPmQ{|ydK;DHonZP zVAJAv`G=C!$)~F@F?sT}9Ob2GwXCg{M!&pX+Mwd*ynId9laqgn$onqAmmW{r_**OF zBbOlXMwlq1oI6K|=nWO}E0+gKl$mOeo8?FWUq(ogu`we^oxi3aB5%KveBe^2lvMod zvekLyThg(8{-Mk{qKmpXUd=55sWho)%+or8S=S^{P?8@K4PioM?iF`B0vV&Mvgqb z^#J*iONjzf0kvtDQhfNsB`9LzOHwXelD8gbfXf=oYInPxoq;}!!Zw~UU8F^K+?T#0 zK(jGb<1B6x4eXr*Ml6d(X3UXeXiSIvWkh~(%Ee)-7ohMcj!RAVixN~(-EUWYIWm!7 zTOmI=?vE!)~0Ojwe^1m||O)$55dL@cGp&;xE)5XRrX2+RO_)ih}_NfrV zhT_+}WHc{e4jIZ;$I>kh87& z&BG#bR$LIgCnCKPFRpLrGfJKEj68eiEO}{pchG;EC%(`We9*W zg^jR!OIgtE(5c#5710Nz{Z)xp5oZeB&QX#lv5;mRN_UpLyGlBf*QJ>aOMAQNsSLId z5!m*9t*;k^avalzX zihAj(_maP}gm~noU~zEbrZR~dkn9&5)yq^gC0ZB@O1_)h z8lRhy_J_#RS8vR2YorSrVMf`R$tz-G)m;hiA*sM&16LLPQr*-r?S+gyNx;F=Nhsea zGzh7UNkyG-`zj*87?Jane^v_wDl_T09&A(I$MP4D?Yk;5C!^KKv>*2n23ggT9|rS{ z$fx&}ky|m|Ayu+c7I%+6d!rD?#Ct{Ndv$Q$0sle6(b(2<-*B|ZAxtYUaG?xJPrU2J z@mSigC?!5G?yOnb+a<_mmM`YXlrjQSh72m>K!H}ie;k+86{|Ta3|T0KDAg`)lxmks zJE%mvbWzz=rd@hh#xA{)JZ<&*?9yMu+f6-;#O;T zuD#LhcDCECezUjJ?ze`$e*JW>f4+P-6(n~yf)OPC7c>ofuYkeWv% zu7h8P{J%v1mV4-~bdi%jBrNFbj$d;C7A7_hK>U^cPY=RYz|y{^+1nlN><+mq7}RD- zWp##pIjLzEWM8dJ_ffz64AIFS-tts!mj2T~3Oh5l+(IEr)_P!2z+i_p4UE=c(C!OB zn~i!WS$yBT=b=+;>yNzTp7s0gZ5~^14tqPzE+lTclIR|3w>BSb^*b#nKzL}Uc8&Sx zcwIY$`LfOB!e3tRw+Fr5{zlt;s9Q1*b&!zN1K_nEqMkeXKN0!2+AY$cp6+zJP3S{v zZJ*igf?yjJ;udyReZ-Rx@Sl|d|7vp8>Xj^LQ9baH3i+UEUycla3JmbS`#>(6%|W-b z(KfyDFA}_V!|__;tyXSl{B{U9PJc#MSd0!9CQo8$1!_&*$p3_?U$B9ocp3+SN{#6T zBETQ7%-I2?=_&eu13>aC`;6@8WQi%|kWY|{4YPZ)KyeO<%ctk^k8Idh;ze`m9*Q6z zx-#b$bnmKALe0!Rr+WOl!4v(?_E~d&Ir)jmNEVI#(H{Xd*&no_98Ry>wa4$w*q0+( z5RuPRNPCi^P+q%srTj6TBsw`V+q>&P{$2bpKUouflEVKQA=7JGgMXwY~Xpt3Rx7?`}1_ zz4Pt9AfwR*9dr+s4Z-dX1h51I*&27#WJUuCuQFrkW0x={>TB1Se~!!GxVY?>VYF5H zsf->J7Y6X%9OcxGSkyzFB)2-4FsT7xVIPNWh&ggp7H1u~^W=8lk;(-gr?B55&vhJ} za6!MdeYQ^jfpZzN_cwj_kk32u@`=F0ff1ZLRdsXtvhO}cZFOr<}I|wJhM>nZ7Dnu-vm?+k@l$tQhM^7*Ob=AmC zjUTs}M5>+;AOCTN#Sxdp261T*Pid1+xyqA5l@v|$VUxwbk+~COI?h<;KUc`+MA&KlWs_02obu+rH+)8swc`*_NJ)TR)KLfv44qjnuf{Jj7et*&`=A=dL4=BvPj zb_5x*UI>7IBAIILMzXKf?VQ=J9juW@9ysyh_2z^3-M>DEH(|hZ@B@c383LI2*>5+O zE~^Z|w?}5?FM+Xk#Txr5HZq^1BEW%h*7hP_jBHpMmOPOy8i31`j5s4(Ut=^}twEXB zQmqRAij8zx0<@)fNru1C#;dt&$(3i@ZAfx=wgxcXbjGNG{G-Uou&;HVYEL_D;Vi=+ zP_yJJ)~gP z3A0~G{!RFq2^#VhL_Y55_03>XJ3-d21r%NWYw|!i6rSR`r0()8R?N4M6!ZN*cnw|# zEYFdt4t5y4&|Ils5Rw$(ygAH?`O_Ea(zBA10PM^8TnAlxCubTGfC&pJNl>!=aznyU zLBb48Q+~1UH|&dJ&_wV5@}}W14*R?9&Ca>zLj9t^4uXZR{j$3aETFf4so}}V188ST zt9x(foPiMroZ+>}U#MU71G7f1*U0n{DzD}R99gMhDnS&0e@kxGz7&MunKoygz8tWC zQIPLUV*l>Vc6Zpq?;R-ZUKJVULvr!jK0wQvc8tOlXHjVVFuSC##T{$2Uv5w^Rje!A zzR=BA`O=1gkz5;l9jA*V35GmD?$X}y*kAzeJn)B_;vgpt)UJBC+uCS9(d%xu`#Oc+ zfL;Mi+9YBQvogM#+~Pi|_B6}!ap?67ZefVj?^q!w2T-TU#Q}ko)HT?O`YrIK+;P&0 zg`cLmPSrxL(@V*7+!zGz>nCF|Mt!Y!M22-`c^QDz`e5OAG#H8_FMgJ;+bpM=kNT?- z`C<(vR6uX{n%k}Ix~IAav|nQa7w5qExNiHc z5xLQN+u8xpT&H@cTHA5Z%fx{|qcUcHQjJ2s%y2#*NQTyEJJIYHmZA_lfwajpIjG&v z*><<{M6b8m?6xkp`}LjPd9OJzGZSbIydokoeon3WaPPcf#jtr;&YLOFLMK^~E(&X6 z^|OB&vX1#)S%qAqB2)+6}!p%QpyH36F`OjUKw#s?u7BM9gHsOCju7 z7lyaNKjJ(H4*f7sqCh+m4ML%8{M`|0ApDhvfKfo*K;XX=-7pKs=MU_!%^ZI&{O8Ti zu+!VV^}?+$c)_g~Z{6%{-n!iz-byW`TVegxR(pH+{PUebdsRo}e)NLh5s}6G7o<$W zv9c_#`26F~WmmlO!mZCnzL1gR>fz_y`hr`-F8B6gmy@}L6>+)x@#nM4-F4A@x#oPH z>-|tfRuNF`k9&;2@n&n-QrjO(c;xRL<)ZSbHH!kJr@4akK)!#JE6Q;8gdhB!RkBdv z!E0CWhZi_9&|Oxw=i8@XvsjJ`F%2as|S;;48`g z#=iagtNW|e?;PxIZNV5o$VB$jEqLVB}coVc$Lf5u@h!VpIfPk|Wb zJazp8FfxG7<~`9Ko@!qhuFliY1I#kzlLP3q1e~Z8laWB`0(=NjZdBu2iK_@(iZ_TydcTo=8*7k7 ztnfm!hfxMrni`&5x(wtwVm41k)2lH}N#VzjMPwVHeW=%~TXu2uP7imwyMw&L7RHt( ze61WnoPlnun5195Eb%IvRQuYpl8s1--Vr875-5YvL%oh7Rc9E$X02z);lx5 zQ`-l^Xnsd54=M%aL1@@13k_?D^r#&WKb1udSOJ)@Q3>?amxl((%54lEZ2%gQpW;%b zUR*BSi$N@tCwM_s7|%;?Ag`~K_uQ5mkkUy_LXM$^{BTw5vzh!m35=YoT`7MokxB&9 zB{TcS4zF1k1(pwFrmi5fjY_35H%G2-p6RzXJCK!!g>^jqePiuu_v{Xay{!|;e|i4G z^5G?xxeX_Jon<8g|8T;Gt z2Vp01-u7Gu1sniW zt+!7iRUJg{jN@F>Y!!ng%X}ckT!`)?uc(N{^yS=3My<+2ykE6KxEnKT$3X{K`qQIV zy$Moa=43#>pC$ku!!j?mmW^VSNF5?#g^>yQ-_?@Qk&R}RE*-@l(QWNr|Cuh!vIE@l$)lNi8IM1HC&<{*|sCIT}?lxt6LBNqQn1a8x8z=Ku=<6w=W zn%iq-1L5M6i}ob&^`dSkcU}qo%Sgkv%`td^$p1w*>cUPypsp zGS3T5aZKb1gI!aJ0pf5SX~d$zBNkZT2R?#&@(G0UsNlZT*6w zFPl(YGZ5uZu34&jj0j&*_tSU?0Z!(#0kG$0*g^|^tQViVBeNIudUEaR)wQb*h#kY9 zj{-*t`1(9xKoc)nyN(-;XLcX}F+!h5Xi0i%0hXia3pAK@=aunvB)B9!Ian2?1=oU& ztt4GsL6)Q0A?!rMO5i>ur`wiL)?2|$57Bft;kG4c6)HQ3f2C)p)e zV`%$;#9cCzB4Y>|eI6jzQ;i?kucahdVC#n*#^|o~_svjP79s&NpujE=LaUPIelZ>$0doTji~4g(ljyoF9vSg7ZlrjVdIY??v>l-s() z;=!TQ6aa#~nWhjru)w^a)mFn>?6Xboo{WuZ0a6?QiF`zfA^XTY(aG z4(r9I+pO@|(fwo=Mp%x%(BdSyiVc^fjh1SZr*C8@hBP9-ZamXF*U3J1J29_QziZ48 z5GQ}d2XWqoexqWelU_EP1y0;^q*h`KX!SnuroJ0=PshJ~(}g%!MANjPByc{RK=R2slrg!Y7h~ zZ#KZ;M(bb4!Pts(fGPw^b*_;SOt+F-Qla1IE~frtnvCKL{FRdW*|`O2WT zkXD~cz8tR8gwc{9NW87}tr2-%z;h=r2;3|un1>*Tnq_JmRZdETFhriKHPqGe{F=Tl zE9V6vxfy~4$kg%*Su3OFxvPJ95&`xN5^XSzoRy1j1ra%b5U&Q1iB;CZSSrlGNZZ+l z5iWRw{9Gs@Fs|h^${9Eq6-A_c#bj0tNQY|H{DjG?=FDMAHREQqM`;s>YSz!Q(nT$& zYSzDSjZQ2?A1(7qeb&;LRkMCpUe&Ds?nR7#qztFLjmaDRo4l%7|FBOr>z}p0B6@9? z@1$UIsAm1>L?crX?^ezFF99M@)ogr@5)%rC5JM)nJ5;m&)fUwZQ}jkw&H52JRI~nT zrfSyzOMsE+P|f-`iK_*uX4|jns#*W<0T*8fB#4rvF+y^wX8jw1YJI9% z|F}yv>z}hSFR11q6^z24ZGv&K5CoAX|go?=lC7lhs4xBjb>~tZfLnp5a8Vjnz zqZ7%(F2|5cEjRXqD;}^}WGCX4BCeY}=;TEL@Hm&0d$DlI$N5x5oiXSy+T(U|p2@|6WLN04%vR|r0?zj&5 z9MnD)0UZkl6~|*-6bXXPie+)WIU=`v5O7iigw?84L6R5jb^{|?S!n@HQUOFT05_sma_CUpCE9@EnI#jS~lSr_E)8JEQdz=EbGR21C zj*;K>l|`!c200CHd$l0xAY`qdkxf4D1vs929R?CI2;) zyOT3TQFIt+5?kxNcw{V#OINVa#?6sV_n9;$`Hg(kmvF0+W?^DbA}Y}6(H>JlXynhZ zAT@bgzQ>a>wA_!UE*2_*2zX>+$4GnuqtmkUKv~LvjjE30LE4FbUJ|6vzL3&JL>5p~ zI(K4_n24s3|BS@2GFAk?hExQKxN;+_kgN!OKK0-RCBpJnJW@qLTdYeW!#~JFsSrg{ zry!Od`6{%0>97cCnHl!mL?h(Q$8Sm&s8(-37{TaL@qaUZf~$rq^$c#c(H0A>Wu!v@ zypF=j>e>kRK-}V=w zr)t@BFFIq-Y#BF91sU#tVD4hn>!Ii>Ul8H{4Jr@ zRAQc+js+H>r@BFIIn6VGq5?y@tZAf-3O4Sel4r#eSTGFtxJ~+@CtIx$ES(khcm_~$ zAw-BLFP6l5Qza+*lQKvufLM1@;H6Ur)YOl&`)sHkEMHK#Sot1NU~vqTXqdPe`&Zb! zxXm1H4GWkv##ER!EPkDO4F%Xl5PUj-6lx@sZ_4|&(l`zjf5A6-V}&f|5<#K}S?kWq zhjZ$AVcW9AyNt4;GBYJpy;d+*-c}SVTJ?EBw3dvUP?Sg{lHbouyP%nQPgd`0#`GY7o{|{(Ah#ssjfV4oJE#v{O zYQT#wrD`$UUUJdVpO|P4==Epth)nkvi7>zo$7@L#pmO_xydi)J4FO<&kqkiSIK)3J zqa*edk{(kKz({5_`-otQ*)`4H?r>*!*knKtY6l5fJs?8>PddUDN!_a-Pk90W74puA zJj=!i3@qwE0g`w@J&qyylrbJA5M{fL;(0fA4v|;8qB{KhMU8rV%VSQU=CBbAGk5E; z6TFogHUvErJplp?T;L}2U>Gh>wqT3*h2yR5&4*za3#={j;i?hjath8Pa3eef12=+q ztir!ycep2ZLZ#^19Vg%+8=U*4*DV;vPt{Zc=uhJ+`FC=^c6LYz#n1iP7rKLhZu*W0 z&izRY0-i9b2g0S~*tnmEPrTf(L61_jyuKqq;*pI`?ib(h=Y9^fxeFZsgSyD?p%9>qtSIZr!|MEzCqqEcRZM3>IqJEB_rcJ_JdvdqcZ#S3Y zTiuS9o)W@uN%M+_$hW&Z7)m*?L57l!&tHv0APYerzgCDFQ$FJIGv8{=a<4SJOEglWEz<);v8Vyx(5JbDKYhZt?x(BR@zqf`1w{Ln8_l845PZw@0k2pa8s19I&-;N zfh__Gt@2HvJU+HXTOFLIG8irs=3vOn_}wVFw%cVVpkCeIMdXDx zO`D+(dKs&Mj5$#`5gu68s^LUnzgS%XEWQh)N_L`fKk|6Mi5(x0h+oWC53V8oL>_v} zI3Kx?6j);`A5lDE;Y>MH1LvSKm5(d(j(3m7Cu49V|0L9rqzF!45@d&Lo5_i)0xX$3 z5Rh^szk=M5noRvvyWblKml4g27{PZuFY*}7+cpPZo15d2nlv;byZAvp=wBhf5M?H7 z(*w$1?rsNDu^R#?`N4?PQW%=b73u#zA~&V(xz;(e)$455_9s7-xfEBbR}8P;5Rs>+ z@0;DLot~veX(zV4M~uMke_xo3lKwt0`?%wpw~~TIQy^1_0Ty%{Uz$<$n0r0>2Fj$N zNmF3nTWlhp=SRW8U*LFpFdJxCs&_Wq+t37hv3bu!r`FaVdC5KN_ubn(w%#1}cADMx zxpr4BAchL5%|~1PPV4b*`=K4wofC1CMTJH@LcyIkZ;o{_C_>Rdi;WLc|Dd_x@R4{x zN3a96yL}G~yChk1JbsqdOJT?d5^awDzA)I%{k}^aJ^D(O%}(n~a|bfw-gjDZV1@ay z@*N3OIJ+;h%rAm}h#|!DOgSzDQUQA=5moT>p$KJQPFN^^QYDH(&Xa{1K9q5X3Gksr zfa85rRPW$J4uFRb1t!r4PS7AJ%6Byv9}4*Ve3%4VLf;Xi13F;R{k|DKoUi-&P{I*{ z6&_e}@FB;rhYu5kc%CT-AHF}-n_WApc@*s&S}64+)^KTksQT z5?l@~)JDCaraMY?pLr3DuZDRx@@&5A-GhWc_eXwdT|*mY2f~=eJXd|VcfMAIf1nG+ zX#Edt#I>0%nFx-&X#Qj$9a5U-d8vL%3cB*#4Sp>bEP$B;u)Hrc@&gD{JQfx)FdT36 z)#w*%#1hP7=fjDIPIgxuhLEF!sZ782`}3d-PUigOh@I9ihCeh1MTvC;7`p2;ELcU+ z52V96>so2eQ!4@tz3}e9kiRK__kWy7Hv#@FVjZQNv_tA0o_L5C+o@uy<$sO!Hi;yDQ5W zMvY1RP{q;XOpmP{>}z#lKVj`4umCb0X=CANnvY{a3sixc)!?XA z3#(hw(K8zJgK7t99Ak156FZiWv@IA6Ak4DxVw>x~jJ5b+?@WD^KD$(y3j-4q#`5{d zJEBZZ07BB#yo7(nFh2D>i#k%-)!4)F4TG~85%q^IS!uZzf`^lg)HG+g(^ zUl>BJZ$Dj~T{)a7Ty~}D$tyw=eA*r0!IBzlwR3U44wg#uNU=-gnp`%YuP7ilh65|B z4SWc&ixmds8h$mehGB$(2EGSKcShXenw4N5HoR&&!G|bY2y?>uFVP0<<3Rxh{&{Or zh|U0Lcd2s*774DJ=GVv+F64nZylOf@Y*IBXncQeB4S!GQLb=U`YA~a@H+ll50fIaR zzm)zIXPnhAAgRO4NiNh&m9$AmE2h(u$JF|HERf5ck$FcuA9YRSDf9<66*R;npe^Qi zAy|WRjaH`GHRhjV8!YjiG6sqd9lfZ)(*m`r~If^g(xBP0Ag`C^2U z5*2Fdc~xW1E_9NHIVGaf9aBzCe-4eG7zf*xJ99#co%^4Vfr3opFry)#LJvZp!@=W6 zvL3NfTcSRW_tZa1YBCV?g&h{!_@2776*vklGW^(`hvnnRd{J=p0D+I98Q1Ka1?{o%vy{?_iWHSF}Z zYu9J~DqfTVoPrqetstkj#4X*u+TTu#S)qXr~#0hwDdy~$3yz0Q` z#sApM_;rdZs-?&uRmnvJ6Bf038b-szgLYcmXLh@-zP~Oe^$R}Df~lnRRpMPq8|nW9 zgqJ#W)LUxCLg~kHT_`Qmkf;~6TBQ}@dS8qB9W&-Kh8p(1>8oh(oBmHFy>Cg!j{LqK zMcOu)3IjWiSu>RF;D_23{NM4-l6y2yf4$dicy)TBl|rP>AyevHPp*lmKX614t83gI@PsJCQl-QfjTyzYT^ob4jh6-c!400?1&7 zjlgaly=>a1*h@{wKuu1!8>rw%F9@xjX;?v0~mHnG)|erDw2R&{hHI4 zK)Us5r~Z?bnHlo^RnjjJhK$>|ch-Ge`rBbL;#rv)cvq9FR?pq zlPa+4W2S+uSstwQR}YhJ^tLxz!{!oNw*-j}noSXa7c;FOMvaXIgzpzd)f^&S+2iZ( z57g9J(|I^5Kn>^K59XSOtp>*sD89r^qlCAhH%TgHCnCJh;B!=DfWfe>$gZP444RPv=f#Gl?6zvy z53~yl7bM^m)b<_Q+z{pCD=vFN@q8Gg7d3$g&;xDLS0ZC0JyZat{MLv0E*_Y z`Ria6VWUAs-s)<}wR z+~(`q)yLU)kBU)o&~yBbOZI9jj`8l;gcTjLr4)=9%_>om-E~~#JqYZlz;njNuG{p= zVq6C^s&h=>1&Qj_&`&ARAkIyqZud{ zubmEcy&w~LcrJO)>Rm=^1pfn7cX&ij8ocTK!hQp7$^WVfqUUB{I7FVldSkLdAeH9P z#145+M0$vGHi@h)h}g42J!K_M#ju1ht|fn0A=@S1*)&;_>2W}alfVymf9kCZok3jo zy9jE+RXlXil^G}HB3`z9;6b?OK_t#39b6Dq$eutUX3#rA(f8$o;+tp5`4X7`x^5tv z^w8!mwd$=I;eHJ{xH=2My~6)VzHPSLBuuxn0p9T% z{a2}|5z&^tqWn^UO~juN%S<^wu)W#7z)F|h@$7e1$eU)%71op(Sgdi+sG`g?nl1rX z=l6gvv_)#*afQ;wM=CChZxXqfNn3oAxHD$)P2#K&i*FL=(s#iuY$0;0E?a35mr7ZD z4lB-KM`f(Ry@8@ki*FKdp-Z?xi*FLwpy3V7;+w>I2?_4Ond7qfCW4g^i*FJK`z*dm zoT*d(9?-!&b!C-8m$|i3EWSygiJAX?i*FJ~3#z~@zDb;^Q-#Cgo5ayvCN<{V6!4LX z(A%b~Kz6*@RTwhK&WQC+cG`rskfXOwtDFeRKrgFUuRj{eWU_mv-CYxdwRp!LYfU1TNz{A438!Mx{P#Tww!5QsZ)IPb!`jphYuB_z*(9=qKqW zz_$d6X^qQ@R`SG-$@lp#wZbnI6cTsT#4z{@-tjjh@-@f{O(JGHfI7F$_GWWHb);ww zU?k(J`f?bsnLr?I$$x#ccOY>9nY=#%-SDB?#4>QW@G)&LKHfgl*%qk^d*~U;hiCHb zRfRnQubZNGY;Qv~38z#eYn$KiqNt$%BYz&jDx)c)R7SdTLY@5`X&o>9e|QSvf9!{? z(^CUw?YgxThsIMUEvD*5jJM+{v!R=IhGZd_xJss83^I1qs1H!EK2n!L42h9xrn zBe1=oKWIPNs9h<4MBUMeJqT1}pM@9<>`|Cd%3H$5vfk?bz0Qta#^5mdCgG4dOg>!2 zjL#e@0i={dDc|JV0~kv;`St)t&EzX?VJ-AQ8H>k-si7RoFZyJm{d(7Qs@=XFC(iRFa`6h7z z_8^AIH;GdunB3&k47qUgj|?1Tw=8rmLUBB@txs^gA4ViOVo@rPosNDJ*Yr5;P?i;; z&6P$#op$LgCmY@4 zOg#LboFn>3@ed{$A=o^>h`4C;be%CI(AEkH1XL<0? zSlI-cF_B)b;AOwi5Q}##@S_Ed2F>!&fDh)w5R|J2GO}dkXI%FeX(chF>gwaI;l>mE zZ=n?tn}D?FN${+w%Y;l#15+Mm3^t+u5e8Ewf4Im-Qhg*~Bvm81JP=dh_3@P-pcEnh zwxVA`$%45&2{rK*3@Gy375f<4MlyzWih|DZo`k{_!N{H?Uz`X<>VglclQ4Z!k)u?Y z1x4y4t|G0lB1nCyH(h>2q?YhFLj*bUeSD|S)yJ?dxvXc_ z01G2UN9}F5(QxX92;#%;XLPqC-(+E0MyQ-HG{E7Z{+)XhM?WIzORVu!S zce&&8zhVsHDI%80+aq!(D)wk=GY}4wdP4YRyH3aO0I1vmza8gxe!bc(4M#YX60iPS zj>F(oLSigE?YKz%zKX-)F&eL_#clkB1K5Og95R$iTgNwWbS*jPm*brx%Gb3n^=&bA zLjHp*wjtcXBPt>g>_Nu(Ck;$Pa3=q7Az5*3dWbNl43{0!t%ecB^R=tAKL$h%j`*L` zF-r*VZWp{z37C>4&DGn47Q6ZQO^Hcbz5O7~1JPQqJoR2xQea9}0}I*drs4*l?Y8X2 zo7_ZIEH(#&b8%yag)_P3jZMkitsR=E{iwj>uTs5$OT+2S0&$M;@<@bdLaiv`vt+uTq9G?eJi;o zRnDFIqkyMM{+o}W7db(D2NtSmQf`u7&_};bkhaN>hmiEqP?Gjn;A`PLLv!Q`h>;C1 zZ66i3TyclvdtAejgkqjQ9EuxPy*=m0qk;z0?2b4JwEExIkN`Z+OxyUb$50bkQ^dgY zfvpFqIr}ab`_Pc+QC|IDVAj7EScO1rms;h3X$lb7@`hXA^t$lERrt5Vl`-(=uu2*5 z1+MrP5qS>!c%VGB5xQVkrI)JV2@yfVEAbtg0x-W&Tbkne(8wz=fSPYZ!Q>nQZ;=GW z@>7pPnMo7Al2K+q86*U>Y>gk?M_v1c`0m2Pib_l=8BEsLa%9AZ58OEU1tp0#PovXWSw)vkE54m zHdb$el!xb{LjDd^0106^e;8k69B}$4s_00jbpB@C`>!&ZAzZ1%1C7^G3S!K=rZk09 z@}XRTQF$xZZb{Ax*&9lJH7l?nX>qE#m?ROs9x$T-N`^j*B!o`2)j~-Ws~Q|2A^#;J z52LIA28UQ2$2T)&{(_Upy8Ikl)l|FD`q%MI8f|H&RA#?9$EA9btI7UkogmHc2g63A z;%sFss|xs*iepB(4K8>dxvpyLD2fZ1HBtb(hr=JTY_T%`if`_EeMFug{_?Wy2Oso~ zAW^-e=ibl_Nsfo#C?%cbf?(kfK0}1=YR9jG(A~@`5gQdh&sHjK4lnMs+4L+-p?&?R z_hEuY+$WoBFbpt!(Be;5$VySPWK==EC%3O4XLDC=udVqfnsguSO`XEpM^RrJk$O1l znCl^)3y+9ZkZx^jM3{U-MCNl|0eri}`ME)pm~t6k+I0!?cgQzIG%z@VuXB7FnWs59hZd;-cc_l9WHwrOOCsI ztV)g)L{RPE8ZagdAYirIabDt&McF#iQ+QOFX6G54i5T%AVQZO zj6b+&xJ7~1KjtIR${Dt0_3c%3Ncs37$Z#??GJO0;n^6jMJpT9(X0PTMWAfQqgc3>L zpP`dZ7;Xh(RABd%Vb>WRT(XJ_2)KrC5nS+R<76bYSb-FzZ{3AJOI(BI5Eu#N<}NE) z1WB5|*3Thfwc@CE24zYi4J9t`K}yKGizc^FC`~aqdcy0GajXvdOoenyyD>!aw62iTT3~P7xZ%Xf*9MjQ zB7*VoST?lI?39M`q?AMi3&&u(&}s5{c8`xv=o|(a+8EbBsaMRB-O}CxVzt=1pi=oS zc$&$$o^8JL6LXD?fAwscUW7h0zC0NqY>>U7_R`NV%Ndy(7zx@1!r$jfaDq5L3_8|QwE+`l2$(wTIRX7()OnzK`# zg9bP|vW>J61fO`;zSypx>}+?oAl2Pf}S39XHjmS$KFXws^j1{Z%5xWLdC*g6m%2H+0Bh^`%!~AC5O`b1 zkGh(0#F5E30=!sWVIU3#KRlKYKyD2L%apUX|X%qJ~Hao2|by=l`DPkWzLUTCY z?n$9#$IxQae($`TD?ECwY4EWdy{oG&idIn#|wvkmOhIk<1Y_4aH&|~ zMwn*T?VQ=J9juW@9ysyh_2z^3-M>EPOa1?DuBt_j%k{8geSN~fJx}zy?ZMfLj!caJ zaLy>!pYcIp)aXlekoP)!HCscyHs5+tTvQ|>faZL|EQ)Wj-U1K8&0nE)^s?r!LQXr( z3Mw_4JFWguNhqHr!mI>x(P6==a|}WgHvFhe3rZPpdz5F_u2Wq5Fu)9)>*#Y~ujw#d z5F0fPfayVi=uHH@xyrI8t!(B zD>-JYNGvJ5xDen{xr6qwNxyCk1pP^uDI(6PUCW7Ttv$S#YXcl#@JWym4x;0zawrRN zYW=LjlutI;DU5uLqaKNabiB2_N%^GNP+b#(u3Xw%H}vq7+iu?T$J4d)`5e9MjZB*g zPUYfd9GP((t9gHkH=pb$(K_V1D_&)0v=q|TIvfm6qTsn*kq~Q+(s>SFN{`3EO`Z)e z9M_YpWT8NlD@Nn5Qi|`70|0GEK>aw$Qz&Z1h2mM`+7uGMMPmF4gOqk#-;KIwNo!(# zi_K?fO2nypjyfxrNbF|AX2*puRysus=;;4wQOUm;;ZAyuiT6bs@yOt-C-I3Q;N1yb8zua9p~-_?T$18%`$1m z?gl#cLDmXpMu|8AY!&zJ27a)$)DbIm#6x}>6pp~8_9+EYvGT|7bU6q7oRiQ~&Bia_ z5jczdbm2a@WctJY+sPIO+{ck%IBM+pXRNR2Y)?>RjLgQpIiiE<@Ue^h;KadI<(EEa zXs<#L8L11J<(P=?Lq6sg1V9kLVvHn476Xp3u7#)+Fu^4BYkqhDmlU25lrqpA8!8-R zYH zilCQuuZS}JhT48dd-(vpHvOL&NpN^2&c*EI(|{gvAf)S_D7gyR!r0_z}rO%lou9$P@AinPmxJVDTbF_)v>?Lkb5p zsIkCjS&rv=@-*x^bm|8--*G`ru`KI0uKAS&zdZ9q)Gvc4 z0?*MK(GivIhf=S+*6y}9hL1L2_b76%d^TEzhUeJmUFMU^1bdQWiRAnSvKMbDnZ7tR zwp+Xhx<$So{ejn@`J^xzItmx)GcOBwmq$Wtn(*TP`GPuid=c2>RC@%LMy;3dQ(Yd6 zb9*j_#~QmU7J*Hm@bIgIRe)410{gAL80RuwRmla2BYTja>Kyv#98%Y8Owe#_~(*2%ppDhj$h+#XoS-+S>n*Ej+PCNR;1 zPmXeY89XVJK;zS@oWClwUd03yn4NAWhfOL%KzU4$MtqH?hroE1wC>AP(vh6_R0s|} z$fWGPNkNNta-eavd~qg-!TYcgC>t5tJSnLL6|`BP6xuL*&?O*A&(WyBQJILv`hW(D z1PY4_lP4WLdX@vnAwhn^C;Jfe<;bSsM zHAoz$hxREb3MepJPzaSO`4yLpOU@DYU!Z~IkaG@PVfM+*Mk7u(K`+VjXI)Z&ADqJi zl%P9O@5yJV+{|xzr-Z?;yM%$f3>5~TB^;zdIZT?m4r`o$rIl)(*7z8**ZgR~l0n&P z4FL|=lTY!@J%Ys3E4+fU*I1ZyQRql5C5c8F@g-g}1POC4sxaqBCoF!D?%TaF6<=au zPS}G%{~h0>iRN&f5)$MDAk+gOh70*Rdyo^h`q70w(kchyF$i!Y$e3 z5tt|JexL*rhiGSpBggWnWsq-iSv>q4pl^E+4qno6Nkg&aw+M(g76*6|wwT*7U7~Kf zL;G_u^J{;Xt0@VME>iYUZVpR~-_>vRNOq7HF-@%C2O&>7D#Vl8I4}ZuuwD0VjzQ2{ zlWKYR4UE@-mPkmtC5Ur0y&F^rktDp@UBD8I83eO*cZr)Gq4EV|Dd^Gj`KB69JtCV9 z6vdNWQYM<>`Wc!Pq&@Q-!xMt0OW@5Xd!-$5&s@9=9L|NT{I%QbV(;#uE741_Bq+;>iUve>O za*oh2A@a!K>N^l6pBb}?JU%~dKgU^xADrPWTtG><9j<=z8RqJnsUEjPk`r4hbSa^i zmsE9n5cZeR+9(J1o$h^@f_E0D8~6tXl`1O;`n-G)?%qeWs}884bL09D`s-t3$M zQz8f0**j^Tj?u!&`&V&TQ}1@xZ=5ZO2o3JxVDt74>Gfk(0xQ%57!d*m$#Z(CSA5QE zlr5!HHx9}nDNaKS*JYdG3dS{r#_=PR6iaJ!^1dJpEh!A)=2=Q`_zlC zXLr~fP}w}FT~DrEz1rY(i5?T91;+#j`0vpANG(UVV$fa< zF0zEOYHM@T?rCe8e|x@@roZ#$JBwb#lZU65pqDXN%Ry}w@^>!bg<=G=zltF@F7#_7 z=HFlD5ZV-OVAO1eSV+5(#~*@P$2lT7p64HMV@lG$V-<+$hICk-37CI{x1f=~q(VqGR7D`CXkVzsShH?extJkguqcMbPc zrgI`mbPuP1#qHp4byNbi0>?yhugy~MgR8SbIswQUTCrhivK{f*py(oAANfpjz zhq0MseaTy0x+{SV2F7wA9rl|s>yZ-PYK7z!`9xljk&YuMT8D$Q)i8MVjrIR+4K!}GBG@Y*c>w}Xll9vsL@ z142j8t}C!AhuP@fkYQgDByGJ;_7R~+^cj_FPwuw*ZKpq6QID8XECjNPII7kGn2O??!#YL@gXK9Vd+*Kw3Db=b{h_#FvFl{XKjktY$Pc^VX1hCVjr)S8 z&4JeO{DaFDNibO32P^WgFM1Jzzq4frC45~HQJ*uyytL-Jh_xf7LFbO1Ea4r>?@ zPm`sBs2Ed)3Bf;biD!PlWTv`Td91`?kQM|dJA57C2PGTdQE?={@4dL)+Ujhq!9=!= zCqPPGZTyA9vP5(XOK+sjrFgPUk)+=kK{4{mmDd11J8N| zy6ME_-UdsY1dn6;5E^z5k1WYPQF>cE%IHo`vF%o_N*K3eSnF` zDxUQEgCuQbCZc#^&0}kuzmgiJ3JDK9g<;%VOQ((D=H@j#*@egifu-0ey_`g4bHJ3; z%*tKc7T$(tI|h6woxJLDo~1+}Ft7N&QEo4TLi%J?oC1x|RyHkH-9Vyhq?}-Kar(3~2cs?sJ}`2}xLN4*!nrS$!`gUV4>6 z9R@LbZnDg8f`5vK034E3t^{i3G#Em=o9-Rrh<1eU(hw*FnYQjISYq;F zaW7+?&^;9z>s)alD-DQGkU3(Z1V(yWAL~fM75H8jrCbf$)yKNa>S=>%|DwZimNjOg zo|uWTJml@NRUj6OCl^ykgVmmlw6N#3Q!yZ%IV18H5m`ZXzdBaR%o8xzwF5KLkM++C zuwoY6_fTKRB8ZN}V(OElwh({7mAX}DLEB=~URupeSO#l|nzJP7sM;q8f*vGYE8 z^SdrzRNVn$;k*bTgqQ@Bg(<*U=c3pTC%{AG7eZfV!0HhKsu&GqID#J9=UC0OurbUU zJfFyeE!ViIp^iA!K2xj0KjK&;9bN-x=7kUuH(n93lLt<1jD%0L{FWF|uUM;Fx zpaDR#BNkJ3wfU0|h7uDKE1W~vk6{9X&8QC%u}sgYmY8%#9hZy|c@JVRtt19h!GMO( zY+A|hmC?6iL2dGi5K@B4HN3Wr{mUT{HRmgp!yeg^O72j$C54PgD{e_8a0FOV5@Nww z#oDu=MaWP0w6#9Ol3K9}V@TchP7imwyMyLE51m?Df8-_itlxKU^VoWG*xPA#+vnQd z`srT(e5=2yh6f3#D#7GSJ{}^K0d3(Xm4rL?n^XuX1e#PxZv5tmPRj{nhZo&u~dLaG2RTyVo;jI5wfSfV0cF2B+Z~4<<5g8 z!R$ztC$V_V-uAf*-n2mDFuw?XT^?8TS)xbP%lPi}a>qo+l$R}x&+$g@U~KY>P-iD| zgUnhDz1PBC5o?W?JI&zHu4HUB!np@)|A6{k_CKBMtK?fE@`B=6n!qZeH$>!E@e3u} zP(&~`KbEXz&g3n#j$y|>TCyzr8I>>{yL5fGsq=L@qdj^&`V$4{ig}@o=AK5bZg;z# zok3^N+-eQZ)+#XU0czbCEaGn}^ke>|G9JODBpf91)pD7e$aRA!`kn2wO=t#@mzW`E z$W5tPc~7&k9XS-?Znn?EdY*s0GxXx@_PFeKqy(D zQvk<%)vy~u4L>#$5E|LnI%l?eoy|SD8JGv?guo@=guo^1guo?qLg12%iX|rL1jY2K z8ZeN7ZCJ@kSXebNRPkYf+R$JZE&Y8IY^$V}9KR}(JaM=_WW)2C8@+aaqXRTvKiBH+ zwrPdouyc;m{jhzi*WaR1nAVy4ptS`}H}#DtTAl4??=(yz=$sz1A2wRhm$TIxo@;M3 zyPfTJtKaNF#anCG>&qYu`?UNMl$|-S?&v$oVUPgiX&cEfNDMhwWpb`^yH(D)yS#E3 zB$g}ftwCbBP|6^&W65fCxL%aJKHMP5Udm#Sd}*M`1z$!D<6!$Edw5R!!}102#=-W7 z<=2xJ39vt;GYmZ&R_$*$L9&)gkX;fQo{%z>YHw+vpoR#HZn5}P<2OW>l_3K6+8kbl zR`tqZwEPhDt6=~!W{5zw7HWv(3DbobA^?s;v`cv)h6q$FVuncZtA^dkVTeG3s>=`= z;bsmL$y*bbA+qc^R`Gzj+GaC!QkNku;$_8!bNQkg`&zFFKCkl<(rm7ii| zS)u4R%eKglW6Y5_ARu+9?b!5OgnTq0@hbA-dcM$)E}AVYotmM>%$rA+;AjcL@L!rA z8&EPK<$EKrR{ZFO(14>1>!{zBS7=c@=(`y#R|yctsst+t41XDdeQ@8%AzAaJah>c}o?xk{~YX9tU28EyK0)`}Zs$6cROhkVTUoN`gr& z48`M2G&${f07nGrZzGtjFwHMRjXnN0Y9Qy~Iz-Hx1#8(pJPQL}rxaqV)q$0=O*coy z(@s{SZBYAY73R52DHTbB7~e!{W*M_lw)oOw5ywb*S5322W#orur&kOn6+KF&Pcz}g z(=CC=I2zGT4hvO20yla+x@3g{fspgwr24gK8 zQ?K?-uO)ZZhJ+W!EePL&Cvdd1iZg}k>3=0TlD=?*bkdhcmTWmCne?@WXI<{ah*#R{ zJhTN%S{^!oc-vMSR3$kI<181NP#*eC;d$unr7U^q(89Rvm+|Qb!HH?h7vw99vwT6G z#I)ttMPfQ649&Rk5-f{@*{P*uqmQU;bYS@#I+yXC*`ypRi-Rc%EF1l=MoMag zhxAlyR_H3&bWs%~p_?!hhUTKjc~NBt$xHvF4$V zpm}I5%;drqjAKf_9R%g*+d(EaD8S8Rf-4Ihc$4p{kdIA?Jv(wxQ&>7w^cfa9CGX#N85vBOY|7{tAF$3#E6?CVVJVy+cnf`%ZB$a{t|7S){qu+4vH+)`36?KUNr-0SBb5*mXXy0R%ZR zSj)59g-*>uuX_%9K3nit7uMxpuhG8^hE#e9+1vWMFU$=NZ2JR&NvjW`M4xP1fbF7C z2?%#?$}#&;q2Jmb?DPihu$2Id8bX4;m2GiIV09)m$v0KViP0dCu;|MJ{GuQpH{wD_ z)?8gryZq!@2hu~gu|Y(05+h6AkM~9&wpS`+<%YUxw80idG#AnJKnXOX)!2O^BF{w0 zM*5;Tm_NoQVk4-4;*#78deS}>vIqxecjIa`5t+>eRrBRUg!dVwL^6vXd=>OB^BB*| zf@ZlDi0KGz5>g%u`kcptPEJ=Av|b<#F2%}_7^G5I~ z`D?tZhTB!_p@8(O)c79TQ(*&e#hKFbqjt6!S`ShZom!WchBL+(JPGbEx=d1zdm$6& z)pL0nixs4~ebWqMg+?0EZ%1~~_L7$B004h z+~Y>;L&g>rzku!tlu(Jg6cb6H^8+KZo2^yVJENSx{%g zvP8bB&&{f$g+s7M0k^t9C}kHX!=cpduq;k?!-ri#aaIw?sS3ma01>3^OvXP4fX1HN zOCPYvEiu^1Tk&mc;&EYjHLpf1bg*T`vQeUoC^cA?49f>_-NQDgnyZqt>uzV}3SHT_ zA2Kg4jEV!q6=mZ*A^op-Xq-65mpI|JQNlc9xP5-<_;g$ zK)C=iZKb?`T+{6B4tI8kFij7plnrXnCC^#C%W#qKKTvgtiwtS-uJ_En$N{MEzp8@h zxfvJ^k*BZTNT-Iv|5MRyEoB4KHGC|#C@e2M&N0}1ys1sp2zMbO5@emi#3?}seoQTT zF{N3EW+>{84BoCM*REb|JU4AK!I8u)0oVx1O@jE&$55H8(E>WgY$kA{CvKb!`ILmX?L8Z|5bVV5>Z&JiI+zXVx! zL<=2w3JWvgVJh-Id{)fiIzKoOgCX)zg6%Lrlh3e$Od-Ng5xgNdVWkU>Repw?$%KDU zXnk$YUC5p2W*jdm(jXiUQ{v~#i=vac#4A|YWDF5V2&3V44!@p2Qcwgkd0tNhGWirG z0^q|Clw)K7&P{$2c-=Jc98hZ3-FsWH-dmff@2ruX!T- z=j>}{XUxbH?qNpc-@9}?RaFhnba>p@=ca26pBEayhmUy0PbKV_!F^4 zTuK^<_EM?C<`!R6IO6Eq%uvy#FwEK`ccR`e4Ko4ZFsUa9CnQujwpSwH4dD`tUoSA~ zxEzPUiR!LVQWs0vcqIA0io*;uf?yyVuQvX|p@9?9amY|6Z5`jh6l-(ILBAaDqe)Zx z+rIc?h5QGX$0&?!=r2!xL?=@Umq7f=yyKGwrj^T^jzH$F_99SUhszG>tU#gceBQ9* z5&v_F*TOfnIzx{BiUnz|-bVJZZ78*ykKc5F4~nVYevt0Hpu=M5|4q9Gw_K}5Di#`8 zAVd$VZSbPRB`@A&AAPZk1t_AzjTvU5amzc{AIn{{&;W;bv|zceF49K3^5p0y2i$2F ze7B-l)q|ISmkIG5g->BtS;63XT-|f|w<0`@r)x&FD!|d@LU>fM5J4~GAn0W;+N392 zjG+IUkDwPhL3=B0m5-jAq!)mswR8whlOqy7`SB2vJ{n5W{)~rwo3yUU6LTONUfMn? zY`NkN$M?7r)q>mS4~OE$mEYj}sI4P4f|{7QMrUZ@JkAq9z~k(P_^!uL6WGwpBd37g zziH|UYO0S3AAe*Rw)C%z!m=@BF{k|55ktv=W-m1 zCLadZ7woEQ%)f~PG**0vrU1-euWv)_tlK-^?)yHpy8|6C3c3)@MX8)sFu-ahHWALz z!oq{XhlR?@Pd(~t;mWK+elkc1Xfbdc ziY~mu7I?0xNoATBjeZS!4cMCn>($figV?09mCU3vz}u6%?e@DV&lIvv6k(4P#s4BRY=^0kuOIb3Ow@?`Xm%1>!E4Dj z%#fe1kd>ln$tZ(-PacoqJx2VFl)vGjAr>4{zQ)%^q#lks=AMh^vhO_38~3e{Z-~fz z&MSa-m(&E@povU53_vkd9uEg5wZ0(y9>%5=nr_`VD-dJQF&^=bz(`7>=T{%UDv6#) ztI-S%XJ7-fVJnu@CCN|<%S|YLShQpAS>lMBj^7}UAfH3{+;LfI-j8@GXc6O=8WBMe z`B;@4Dfm>igKL1n&GzP6x3kfX^AdkN8i}BD%tPOG)GufN(S_~2j%;JdXXsyUx6e0Q z7diu2W+o1X+7fqB z>=#VwK0YO{8N;BJ1bZy1F0JrdTjF0EC#S#x&C4TZ@E4T7h;F)P5kI743 zQ^{rIs><~7d$l>FhV_Nr>ChR4Aw&h=9FaeZ$U?Y+lTj4)%6V)iR_LBz!Yeq;mky0= z(BWv?D3B?~c;vvH;T8p|{0g$piPp|MS(%w3Z?BS_(jdri@?OPe{fICiej)6-TO^){QOYc$aiFiBC1Y(lr-Y z22{c(MOupP=0m0xSIM78C+yI=rTt)p*$lCv!a(!HAF3ZHRKT*tG7@n z$E}kdX>H4Zl&y!wkV#m4_cImJE$zk-$O zUi$mbLrNq)PDVHF-=!^4039jgbL4fiWeR3W1T4$7N7PWB|EEj4)%nutfysk)sJpC~ z;aE47e54ZM0D6>?@aw`A>&qQxvLy{D@@@9yg2(}W-i+-#EcS?8AYY0qMau~!wjHPi4AWNZzION9^;F7(jm@?`<$O|WReLi+n3Eb1f>8G zm%?PS!~v()uq`PWg)o^M_Gq{K@-ta5jf-rOU^6?VnRM*rE^x;2_>Msk;%LQSb{;R1 z=zl8rB_yvIPGx?UkH{;ljy~BG2J&*-LMT57-b)E4Hj*Yh*D0NOG;>se=rB}F4Xd%r_erib9e!^ApSEi(hV-O zBZK^CGL zw^YA(ejs$?=(VQ7$8PkxV?6ePBXumH-GNy(o$WJC-V2{FHo~`Pr;iz7s}Sc>GjVk7 zAP$q`B!{n*=dJaK~dA( zfzHh_NT`br3s#+D5Soxvn9@iwCuX2frHnT|%Cl?NDXyj6s=&GU+($C6b86ReqFQSY@8#M6$5%pA_y;&b9m+zST0e`)V4uv`Pa+m~ zBVXgFN8%uf9+qZf5?w62dCxbxRxrBGCS6VYihMptH+v(~rh-$sc$pZ_jN@3%`%5D= zpZpgWS#uHv&rNLRd=YB@XIdgSd?`I12e)}@iZ8ROGxDiso8p6Ar1*O!fHowc-jB}b zDHOHh!n`E!fb;RIfeNP3rHrKg)_0@Nle8wfHj&bup+ZsE<9IX+P5-C+Ztm@(P*n0S zM!1t+W8!_0Mm#e3Ub+IiQPz?u%)i@JQUz`a%zI5Hh6VsJ3ckGem-60gH8j-h1k4^w zSqG>+=C>MP9xgSn@VYdHM2BI|R3%(F909Q86OXUauRCH6xxZVhg&Fit4|lq|18;jd zL@^)OY;O-c!;7aRxny?9A!Wj_%*ZtpU%MlXK(jKESf7bc2R{VWepS*pqEjI8P4)a> zYpEkv=oo})M_|%`RUooh`6KLy!kq(t&PnL0X7q?h;8ca0{K zAB8a-zE4FkIAmJj<2)(TA-HQr-K%gIKfRxP)3m@?yKXJTnemj#h$*@c$XOCP?HJpI^aYfCoz4(e>+ zJedmSegNf(m&{=LE~6z6q8`trIMdq7y8&A<)Rh z$jdWNME$a4ta4x!03Tu*Z~>SV<4K_{aMwN9le9!~M1UsPA1A+ALFO+)862G*7*CDy z7Vm*_k@QS|;GIBTi97VfHI{|H%R`|xO?pw1T&`ch0$Vi|yUK(@eIeN7RC@@PhOL(r zta&D(c|)+vb!*h6SO_+O!V?scu+9~jrHthu+YlNRlbBEK2?34o zeg{}%AxOg`^&9aungjrYL7nNzveIdY?(|24A|<=*&mYFf=i)>7(}#^fs$^*MWCIYO z6xt9Iz?l>vJx99~W!HuvNHdmaY|4Q3>>#4SL)#o)+-XCfScFS*@}#3Z%5oqT+&n;P z99c~tS#=!w6F#n!K&l{hz{5IvC9Hs$yo9A=<$Ka~0`5>bqZ*O$0U`cIV z3N8&b1mtCl!imFd0O+Z9zXyF(uy=-QtWiTutxRBpg_!0Kk2S`Wo}8bYkp!9UDWq0X zA*OVEMuH(J0@H@%71$7eRkBO$~dMZ;pdzb4zJ}U9hWq; zoVaB8Hd=p31n?vbGu(ocAb3I|OZI41SV%G!H*}hOV@A+l@=Y z0}XY~7~l@fTgjua8Stc|Y&{9PEZWLHk3sBlQN4T0opJdc1T5Kr*0cqMFFdqvP$5XY z+faj0z@n~PaO^DXkZ{u@EH=Ve3VNk{j_P8#qYBY195YfTn&SEynmwdG!uu17Igj9B z;oD)=5gFekkZT;B=jzMZIhKuDC(Wm&- zt^4@lW72&ZBo5)GeF|Lvk@5h)VO*lMgGt=bx4U(t_G65e6m+9hjfphX;m*mIvVX|ydy0%fMj;FvE^;* ziGD944OHF$kUiIX79)S)3+A)tFg~UN#hn&4C62s)H9OgDX zHxagGzSCY6POJL!rHmmJiEB3Pbj1Q*d^-fK_JtfAiG@@e!cBD%j32-g?#WvLA@|#x zyBot!Z@byq-h`rESyOMPJ0oT67Ol?u4|#!b$}0p-7=5`Ylzg=#+pawpovuf%N1>Xu z)Vd2#u6-$#RLRe{Okv}EMSnOWOT0UJ=8P{bN`p{eaNrPmRhXZg#3_X4y2WZx$yPqa z5aD{PLVn-1i$U2-7PA%?-s;y3D>BfKN}yKY80st7tb#ByJ^@04vusi)Ze(BtX_cF_ z-XXw#T2`bP@aaXzM2j>$81j6=(S@`1PPg4$sDq*(c6Pc-BHHx{)g}4#2{^ZS(t{sf zo2CDDjHyw0a3CuU2%WpPuE44st}68T5H|E%o<{`#>Vvt~p4@Hq+r^B}3V~2Qj;giJ zQ}D$?-e%|0ROS}R70r!qYcQzIk!RPwq}$tA#phWh?0Cd<9*_bp0$t_q(FzM^t zG-GynR_8k6qZ~-_PSt`SVNiU?1qIw2(0kziZm-ur+1vDtl5masnk*3C;hI8|yy}V| z6H7(f7^noPt$-XKG=$(TW52b121uBW+3gR-4U1hTOa3WS4I_b|3vRZ%!eXf!P-993v{OKh%FhY_VQc67crC=b(+N<&Y_9PcSYn*G{!@xUIOi~ zvK8?(#jaq%dYBOW1DAN__e%!JdczhgaTufp2@5nI_&4nf&7|5DT~s6`EqO=9k!ia3 z;&yARv#|zaXf~bzDS5T=7cuStCUoc!rcCVm<3~pvM9fhyK`Dqc*+$|b(O(WS0FUG{ z0GAy3F9XlISz#K_hcj`bTgWq4V2g;he|_FixXMY%JE3eMyX1UDFcR_SleS{FjeTh3Fz4FEsA0#jZ!Z zd9G`sVQQe4lc;PC7!CKpHZ%nfABF*OyTcX@z|^kK{8il0Y{!7_q~qosu?$)LT%|)A z?;GXz(izvs$>9`egcRcO;>}Y#z#^rV0dsGP$O};nD92s`n%$dddoX*c!3NudCV0mg z4kDk42%hz`-Amq3e+qoemih|mL&hT_LI9RSc7Y8k-vs8SI3m={zJcafUY{G^`WXIb z%x}l%kl(EvHFyg*)Vkn4=Sdpro9cZ5Q|bSe2UXryk=HG=ALCDq3((P{P6H-=ZXVa zX+RXRJm|@WMaerbzF0{30-r~(^s8aM`nY#lT{oEeFFI^zS<@lv_n0I@UM@fJ4;=~F z)X}trj~{MNDdtFJ!=CjORQ;=CrPw?H^Xxh>EB09b%m6D~$K4P0g)E5Z$l0boIcopj z2VGe+brv-2bnoq)qXLHgkZB&_qI@BKvF1gnUoX&b>NT~c^7~zvKdSB^tKIR!BlTec zW?>R=i1W}wgkK1KngPoN!_%-I9Pva2A0WdK_|QH#N|9pU5hqYboNAw`RpB3TtdWi} z2oqXQqr||1A0NV{ek8x;iW#YIrnxq6Ypwb?KohSPRW49+8&p_} zHo}3(4iYoXu21KwHMW_>BXGiU6A`AvFbw>0Sp*ldlRet{U|K<4W@egAe~?hzgN}p3ll+ zm)=v-|5QHca+zBiQpO0Qv?POH@CU=#+hcbv2H0H+Vy!D6_?{q!f|O<+1FS(KPyq%Q zB80-4n$wNUx?K9d?cH@;7R%y4a6%CtOt5$`FtC+IumcqlP!R(Iq*N3H2@CVsis-Qu zySo!RP_ere8;{*_j zXwKx8dHR^Vm7pMVWg~xkz&d@=3wCk&(M7p)QAg!hF~c)iQ;oXP&N%(d-61?~$;gJx z>m5-EsI};ENL}OhO{OIrs?7fFI!I_)KoAy7=wymp*)mGKdzS3`a z55qKVRpaazh~KW{ArI+$Az7c&JUfrdG24Zbc+)`+T0unWrCKI05|nM({JR8lw$ar& z-$V+okgPJEdlGs=Zch}J+%K*w9MLO0sBa%1-+@69J|VsleT;NUidWj#sb;Jy5EvXB z6c!u)*2=oOWt=D!FbHH!7C8 z4p;6LHnVL*imRHF$*Nr3xNpX)T)A8{aw?vg7B?Y?y_S`g>>6EG(ra{CvDfI*IDyHm zT-@v!dMk3L%G^7s`N7vL4I5^%T9?AoF!yKjAO;*$e#8E(;4PZAhcpl3%o!!APk&4A z&)oC}=Kh?O!5&5XbLu-bGidPqtL|ksLp1%YBWuI<>}{M8$KUy2Z)5nJaQ`TK z3;69r&S$n>0D;OFqn9^LzcrD`YJVA_k`rG@ z!7}NdGN1mS+O2GZq+NOm^WE5U2Q$i>I^#iM+soSG2c*ubuuRr&$S8(_0eOvKQkiz3 zN>p&eDWmmjj>5}xrOtH7t=3FViRG%pP2P~bjYO)WG3>7VkF5TDrMSxwd2a43JG1!> zcJf!~f(vPovWGHm(QpO3gfO(Os2=in_oNRP+^{<90nf~C>5HM@waj}!(-osT(;ht}tIWfsOmxe{bLMEl=S zBp9NVE|S#1Po{&)Ss9|0P|_HpRd{A5H-N0l!Vs-Qfv6!`_O%YH9FoJgs+r1%XvKxf z!4R!DjK6oFc!*XaAZtUk5&_&sS3E>3@#pEANI~zDKL3;JMgQYNv8h8M!q{-e@n6Lp z(BT%akhtOW8wPZ2a&Lfkt@vt|AE4#t?WYasw93)NfTH0Xt~$a2g}wJ`r}kU)KtS5E z{@lA2Q-^bMv#5%WeyUlS49;>ZQ)dk358V@9dNw$gxi!$SK1-mq{IVvCU-3!;Hs}G)j^_GNU7V zIy-_@tlH_tqIZF`(I;!hvkV%8)T9KmFS+C%qm-6$U=$&38;ZyC(|#--7UZ{hX6;vK zOzDNzO&tW3E)(~n;8X$8OJ!5P#X<6?j-u9`RwAikG{(8Sid)1%vNYVZ2);DgzqzYc z`lsTr>x?(VvUY;B6+JWA3COKhpX}@e!x_98PgzRt1L9sQZP&1qeYv^V zE%i_%y@4~HXQST-MluX6FokzMr8I#4O3S=$$)i#np zO?yoPUm!-S7Yf5{{uyK7tTxQu+T}00d?M1`vCh5Nle!3FHh=n0ZA5=c%9lYa-~7WF zs2PU#}iYh-w=kQJ&PVPJgGjL@CPGu;?A?SBG0*&NsMMCK+MMS3lj(y)U zLRBEGXc>dkM*125QVV6yVwt%8H}fy;rYe>8rRdGx#u+abWo}kz2;6muu|&LR^JZEG z%`I!d+_HmJs5i}W>=nft;3 zRiQNfjQ)db4nkj|S@JBFi?!u5dKuj8Hoxn@0h^uvmdrLg{aMn@WoNT8!s`UDE+PPi-q3P96zrig$dd{C6rs0!@=#$mmOqM@7y@_#`7yJ!WJX=jy zNH1I#>n?j>A^TX`;B{{8W6qoQ&wGD;a06xg7_>j@|5W=MuF?Lu$z|C7xKfGw-Yjkk z*>(U7HrZuhZE=MiA$J#7XzJX+EHZGVq8Y4no1rUxu;oUq$-!1~6vWD2Zd^6vY+gsz zjZU|fO|Pwd2uan6j<=JIcThAIs`8|h?PZf4Nwt}WSP^z@xm0e#q0Af@@~tXSx`S-G z##oBX*N8Wzqinjyyd>Fia4%J1>Rg|D^K|A7(OP4)Gm~*WReMpi=5>T*8@JYYkt$;s z=RoKZYo4b{$7;M+OU_$dYS}&0TI0!VR;jn>sR{zLyOBW#vpeI)hCSowwHZHmVEo)s z`sdb`jGtREe$Kc7V{OCuye;GBc8s61>dX51|5=A>)l@}%$ep>+Fn)pZVn)VIqaq?h zLt3P-U{=%C!NHpAwz)AnwW_3baUIG3Rokg88qHj$ty-*IM?dv-JgHAs)iFr@uaU0) zah*D8k6P8y()gvqk7@o%uH>nHauf2>_L;Q*M1=)#!=c=u06%=(I4mr9P}(m-U?e$< z2Wl91?nzz^(oNOH$SdvDAR2Q6+NG_7V`mW*z%3sa6gkMJX>0d(o*wO+dNyPxfvUXx);B65Y7lDA-?7cq zikhOLPxTir@-#25)zlS{XcUC{fpz*Hr(M&isiTY9!&^gv%mGhbsy^H8SM8>m$?pwT zR=FFOgVMQ*OPBq9RV|TLJNs2_31#EnQI!2C+z9-elyXo{XeZoTk+}8e)9-m@zlffi zwS~+aw7x8M?A)seq9Ou)xIVm3P~V>1T{Mjuy??BqH&W$KEd=*cmdL>H(Eh3S@>G*_ zRF&v{jT?^=bz>GeI<7^MLs@TCFQXpxp$s;PMUSB1U?1)#HTSxls9@jl-+Nq3J@}DZ zy~;ImbeQ{J(U_f2e8wZyHl&Vvz8d}g@7cU+h3!`1=YGp!5U&m0>sYBfYj#H5V~62E z1Dp8v4QRu?T`Q*zU)`0R&26?E?pA6q&GcN|r0OorXs(COVYzd$qyEqAw^F_KFYXB( zQLml$&~4gemR!0TkvTA>kB(>INyVI8fM7?h7$8R-^?xzIx4aU4vqTG!>YFvMNOEl> zN_4Xl#j)U?rc~5$|44Uijpx-lwNSfj_G9U3T+f^B#Z@HpvcD)nE_Q`~Y|l{K`=w4- z$knkJnJRK`jSURsuAH*FaV4i~Fo$0h^nOwRzq9xIPXauX>ir}Dhmg}QmRQqnFgzsBo$1-;c3+%xK!Wfs&UnwOFb0GPM=rZHIV2jC0c+~Pbpjj=i(-j z=rJXVBiUn0eeRF+n0A`?=B$J@R&wp$T!ybz4mwVayG$g`CfmD^<}o58F8e#ARGLHf z%cgN}jw@Sk-J9d0a`WDtl?4s}D?SQw-LvLdx?1Dj9F_S$aBnW>ZHIK`+>=-e@6Flg z_7N`AQEh6Y|Z%#r(>ewgToBLgxSK>e@Q8vi~ zq15O8$brya^WGfyu>EhlH%DjZ?!CEO-lUrM=BViZoqKas!E>({lj^l4Ps?lPcCRgS zm66k189C{w6$9j`qy8@jki0i1(E_CUX3gu8T-%5e-LXV*B)em&&;60^xHg_w=hQ;; z-kg<1?%tad^8Wkp&5^R^!i_7%y`MvF_kN7$8sLOccCg~N+`y9_m5~C-QSXm`rIGs{T#6O%c+Ity}2CBN6@%8mxYv^jy#ix zIAsp`IYkoAc_ccvYT_BZD#=?^j=9~}!LFX^NPG4tzYA4Ya$T;x;yLQ${wwMVhZL3M zy*Y_3F4eaQ_vUh8J4y6u62*}0)1*H4NBT5Js!vP1HXn;?!@1VeN3)j$|7XH0_gZlb}_TU~V3F;A<_K$47_bh82CUzpqadOms z{%_*U(Nmc#YB^F}Y+ru*!=KvrYNc&l=?8yHH(Vr*vt{~IqTDkGmg*kqbF6+dl)5+T zdor%(b8m;t#ra@^ey!xb1|hYqW9lI&V@3sYJ;>D8VV4$KQR9e+ zpq_oXC4D>ia!=#=1qZecGcuO=p*qtQFVh#V5ely^%9k2%1w#Q)V%W$eMSJMXTbKk|-28LZ^P6xFVWg$6kqyTLajXSqyH)tb$lDbs33o;&!m`^qJ}E z;!;K7-bJRdaoB|kRjGus80k9&^>+_-_wB1@L#Z<>yl^_m7)?_(R*|(=G*)5JD1>~( z0ss`9=ZXL;YfNC2uoNWAYEBcD_@pw@rCfU#Ohv_$*uqsaFQDeeE+z^e=@MAhJ6g%@&}!s*z?3u$FHD zo+|z=E$Iv0sSUk_cE$W_iIs^ptqfE?D#^~)nlunth(z;mmCfT+b?07vB0g^TSW6!Q zWeTHCe^HG_M{l5V(b&T@mvz$E@6>s{Q%~;5?!@wfEY0QBge>cfEJk-vzC-1#Q7+B3 z)Pz1jX{q*Jq1u=w<@)Y;^J%PFkdgx{8_s|HhDy4qCu6*or& z`+N9h>P3L&!9e=VQ2GRpbuPvDxwX2mcS~;B3*X4l@D_oQ?tud%)oO3yxJs9#6#IAF z`++roD?aj;(fC`@Z|T1l0l{C>zfFBNvCL_OTK>F4bIPw}ZcX|9-(A^2V|KA+F3gkF z7?)0q%h6+^>dKm%+ZR^E;kr<6eVo*@B<}xy=lTp)nPuRbH(XwEIO#2Ljo zpIgRto*Jj>>>V9^nIGf!JB=Fzmf4@)t#J!A3n`*r1WWUue%Mm;#t!#7k?^QM4l>&l zOf;wJkTgyp+qKN)$LKYCV9C>Z%^q0t16*s;Sm-L(9=g!zf$2G>Ii2#TxwZ_Q&25?- zuF;~olv{2*si4sVr^V%34@^%a#lBBtg&g{WIR(<_fvITHn`RsbG@<4dETnK`)VZq0@gN6%6O=}A4<{}SH2K`@ zfysnH?mHEikG9h2frY&6PnP^+H?VBe&mlxN%6$0~u|V#js$jA=W$b~<{>p|rbNYif z%c_-EmGbfR5Af;1z11r+D73GSe`w#x@X+A&*NmmEPgq`8|8~B7l|DK)&UoGRnj`BB zrgdqxx6qjzjSK5kvsGEE^7;8j`uFm&Zlb53&q%9@mP=VxX;n#Xt>Ca;KHM9_d_n>v zeYtgVeN&eY4(ny4ZB@~!ke79OU`3M-{}`CwbW01YR#|1PQU!*Ea&f_-5fM#P+!DZA z<@0oDyRC_fp~^s&FM@kD5D$~NRf5JU}oA{k{Rih6o4q7Fp;_{XV&WqPS*e!AdeaPwt)l)0*c zNLI)R;eA6-`ad3oLjeP*~Ev4<)-2a^mrAM0-A(C3ux!lDpnAHfI{` zqfe2iRl>l>d@u=9=Hq&=|32_Z9OTXWOqoxA-K+V*$4cLy_sPrhsonm4V<<&JndJ|l zN-GPJ3^|{{FG{1&r>8NEAuPHmBTVcQlUy5pmUQ%61wPwLlQ3mITaSd^2cJHRdh$Mc zET4Sl=h3H7;j+DROze}_C=h+zjLbiSPwOotOqq{y z{X9nCQ)5vd-X|Z+C!xd^^chosRUN3(j+G=s&c`986tCQ^uo@ zbJTt{_*m^AVaj~2w61v`e9HC=<9+m5KGQzWMW5lT&b@#tH3}gaaz0TfD4+3H%6@{d zFX4l^rZydh!Ad|n0yJOrNxW`lVj70ai=_7L=` zQ!?fNROwJ9k|F2g9YOi*Iyn6igng>P2owA4xN`!13>-Jcfscg^2~*~CccEJ%_^h}& zjQ25Q`Q$Zdk3QodKKHklD7_Bon#3w>e_`Bwr{EH;25@F}cgxZe;8V?>gemjcc)L?M@NsWEnfEEk@~PTQjXv`x=N}DK zI@5w=$oY)FPWjx9YPSo*qTLu_Vjsr@1N0d`%exBrbZt+wwj@K&XT?U!XJ0e@#}Kx^BO^@g6MM@Defn6p9t%DhMbSiXv(LnYPUZ4Y-r606Z^EeX^K9T+zgh2 zPf$k^rp%|plkE$@$8zy}-lqu5$G_97MzEKk(6Z|URXVqVWXSoH=tTL984!(~z5Y5z znApc*Kt=TVbZpB#@M*o7gemj6S2mzA_?+3li1#sK`Lu6+2Yn93f1U?E8;+0+IiD`o zDW5j(Dr}795*T4(pZOPSppX0e%gw7$C%|azf~gotO#q= z7JNQ_CmC`+d;eAA@vHHvC;kxDPiJ{XfiO($^WDo1eU`jB+y#7GR3uE9PnYWfD)2Fh zS!Xj^%fi3F z=g|rhrp%}D+@#*%^ZnI&-lrJLr`@Ej=yTzve-Kou&j*qr=VKd3`P3PIvk!zte`SP; zeM$y5L!bEtdL95DgI^>}na`4!n@508%a&VspW-YZkK*gl$L;olS5T!kZApflPfQ5q zGw9{WArNNm#RwDoywP_ry`TYuzgaVGDv7VPc<<}?6_)z$FEY++MW=WxRntm_6gYOhd!Ts znN$TIv)v?2q0fZky5RG$$}!$Y&GIR6D;9kkIbYC)DqXiA8FD^dmry>-%6Iz+Vd3_S zFtLxv;2`u_v(erXe3I*vFl9bHOumJK&;8>GypJi%XZ-jH=+pQ6=g&~3*s~-<&c`j7 z^6_%*jVGIlR~TVppG{vw(Wm7kpKIVV;0_5><`ZxBb3XVOw>-=Hlw$deo;ntNI!-h% z2tH2kBty<;x;^FNP~gp32rJNz5hnK8YTX}w);c9QfKPHK5~j>&Y^l4`z-L?6i@Z;1 zmd}#oBhe@R=6GAElBFNXkn?$;QWE>0uPLSCAk3&IBTVdb!+r?*B)6NQ2R;_TButsl zt6%L`flt(wtGrJcmXB$TA?VZV@9TK~J$NR`kn>rQK>3WacEYfk^B7@bpB~yH(Z_FQ z{3!4#v6zG@^BHZN6b(LcuWs@_Wm!HQF7`*CS!YHLgH68k3(1i4Nt{agZ10t?B7`me z#RwDoG`ln)6ok^H79~P{q$MWeD9g05H zLoZr`kF5*Ikn^clmhySlxri%-9cj%76Z;e^JOO=H9$D57dAF6jW*Z zBa$KKbIF$S>9Zgj`=6o7j4-iJlSb3fXP>E4EVQ3rZ%CLjpQl4znt;!>l+V0RC6-Uv zJ8$$ka{00u_!QRrl93_jqyMcq_CI^quS$Wi&niZk*vH3l2KsE(eOL{AEDMt`Wj+%v z&2aw4A^jhG-72$ue1p59kCXaa6jZ5aL6RZoGj%`ZQ@YS$3kZugW`v1-dgh;nK8A(| zii6LNk|a!-kBeUYlF)vJmQUe*s<3=M4D>{wN3q3lO2LJyBty>Uz;MdP)4k_w@EKsq z2ow9Lj0`XqmBu>h*%t|A$7 zJ{_7+KIVD#^FvsPLX0r6&%N-u=o4!C;s*Gri;^&9J~21C?+2fo2KjiOYAl}>(QVMD zZs|uj|K~5(+ zCSl5aPWtxf06vEr7UF$suzac)qC}#dDf4+dW$I+`8C}bm_o>P9nZDQs+fUy@gK_-1l0C_g^LgY<`Alwg z@o(_?QjZZP_Bk4~2z`v7KM4mP4<{0)%*Ux*en;@}A6|m@sm1bHJlYw3tY0k;gDU+y znqcgezbFzL& z3iz~%C1J{ZF1?!g2z+`DtHAqMv3x32Y=S<%iG4z#N(aW03^|_zEh!)Wn_ci^ymTxh zOzfkbv>VwPC$LQ!LJbym8lY}Yr+1BOAHE2KK%c}D}HY}gX)(z38Sgl9+ zeAB75Bty=pSb{P3Kb1f4X6!1!|#(Y zWj@c=o^J;}R+nvfA3K)M!c7k7GilnR9Z;p6w@8MZPmgAlPqizX)etuLAtOxelTdgS z`h08^KN@@{J||(yd^VZX#_Q7sM{4sv_AH-yHk40vYoBjWr8Ws9L(XTbF6GmHfcHKK zOG;#fiG615qkInkU1SXSY`aLpl=*y(tAyjvWscP4eQL9OuGg!L?Wa`uL7Y+WXSo<9ZvboeV14g!hGH`!o)tN`fJeVbiI?4!RON_5~j>&z=NIf z;4}YeQ{Kms<@2ntE&AMiAJ-MCwDc9pkn^#xPx*ZK>Xrau^*%Df#6C`Ol+X2%5jg+Z z;s*&+=F_mu-XGxOQoxz_sl)P#^`?9RV}2z=mAs8ehMdpr??rI`s=Fx|$LGtGV1$W% z9Ez^R_Oq_vW1PQQpcDyH=5w#hjVj=?N#B+CsmtXM~A;YKBriO*dAp2>Vx1X%eQ)XYZV;x4=hBs}1i{kL9zpVlDLf`%p4Y zX)@1CGUR+NMp8cBCl9>^pU(!2FtN|AZIsXHB6)Fs%cp`QOqtK9$ECEuC!e7w?^B=U zGrN@~`W$Sq9v|6iS(s$V`7F1he5#c06bU|Wi!#E*KJLFLpSI)mE<*dcZ9>A7`4nnMr;H3aAE(!avH$6|tN1Sn8>7bv6Z>d;ti%4N z(GWi$@R@8#!j$97LeBBzdeD1keVEeg0+RF;6bnXGkkn=gSmh#E};?6<{ z8~Th9CidAqiSn_HcU}fQU0#zgWj<5A%!)(%@p~2Qvbpci`!r_x z^p32GKA|sTT0xb@J|-D*KDDb*J|BN<_lK}mFBoBBpSWj~k4}6MZSdLlnuICyIeK}1 zMQA^FZuR7Sny`GfmZy9c>TI|HReJW2WXSn!cvcAepK~b&t0Ao2Ge(%$=Wz<jT_>*oXIN%JLa;v@*7zFQ)&lfGVXtB^h!)A68O64-;>`gRny{ z8DU}{TjTZEKW`d*0OybGdP~BT`D`Ba9p@(uHwxo@oLD}7tIg4;YV#-f$W~qxk|F0~ z(S!2wHUD@Be1gg_!o)u68kCRTr7De}{a95bVaj}N>o)_&rE>L2hMbR;IpuTuSxKDV+n@;}Ozcy>G37H&r|k#u`P71hDf9U?&h-iSoU|Co z`!r|y#3WPgr`CRJT+*nn9m$aMsrVxOnYDIc$|1#o=hM*|Y3 z%%{!^=ab;m-(d*v(}Lx5|EL+ZAN_|<@s`!=`Xocn=jT$&#~^NTHSjssgb^n8`RYvh zScTS4g7$N#1qoB;6SecMJ^0vn9KriIvwSA&mO~%&3L_sumAZ5#8FD^5d?}w~KWZ?t zgfAmZ?32GG<&!_msXq7^_aI@)eDeFaZUUbJZASAxEm=Otwo~orXV|6@;IqFY$&mBu zVn+GwOb-1BVI930VPc;ljVK?FdVxQ{XJ!BiQ|43R!i`tp^L6ET-p7UI^XhF`Y(F2Z zo}7Rxb=^oZm{u=)=yaV_wIzz&g`NZC+w-|hWu3f%V*evlISz4q&?p9tbT-K$ob6oqlg<<=BF58VxKyZl+W{f!*TyIyFkK} z`5YVbc{jA5!^fBNK5bb(aiLWEahYp{w`A^}CK+-*n~f-+O7Ue7d)j$MnAm5k6Xo-B z-7*VkKTocZFl9cgzuBDypBvX!^FAIdpS#*r`x$df=Ok?Mk9SFioX^e+hS>i+aM67U zVY?qQ!o)uNs!%@WmAvrz${#ODm@=Q9&4%;^pQD8~@ILKWKL5rP!~H9AnVvUPsdzDx zA?I@}mhvfMR`(i&{WM{OiG4i3Q1>q;jkxm(s1Butr4tH*ky!KX*zExeB>%V&OU zQS?b#@)5_!ZkHe#ay~mro;!1c9u z*WJPUv}gIuURNA_xA>=t_1GAF@)hb{8>(dEPBP?trX{Gb|M|S?`aK9UXvYW> z`}}A{`CPRbRR?^uI*~ACJ`N@B;rgouLgRU#jx3*(qYIDEVp`g#G-N5hnK86+-!R zd{IsdeBS7s&ZwO-pT%1JeZZ&b`g43j7nV=?+6A%wl$bdf$5(%BAsKQ$--l8@%l$^< z#azWbj4-i}jWy+yyujx@_*6bb!j$=V{$+I$e2i{i;(fZZe1;9C+Rudh8}X6#z$B6( z=X1F(km?vOBLKC5;cTZ2!ZcgehuAIqo4 zy?oeyO7HpWAMmmHMl$4lTsBcYH)HSIfv~1pFEa{+VPc=fE|gE38rK$pPi#ICrp#y5 zEwuyqtSk41FOEOU=XC_teimspz*CleRY(R_NxZ&s;}FWHxYI)%AM>_ggo%ARex;so z8nI^WSMc$*Ct=Eb7IvCC34BcIeBgZoSU%>f^|1YT)p%SQHn~eo|I3+yp!?zV%Q`Srp!mX*QVRxb3Ez?@6&_jbI3R^ zwjb}9k|E&JE}CS>`Se~z`P6>W56^#$M=-*~J~5`0&wiJZ+oAoa#*i>&K5h1uTLL~# zV^esao-Cgs6)7LHX_GgB&#*}(L(V5Qkn*Xz=rs=ZTTf+#iG4Qirk+2w_nP+_d}_`l zVaj|?m^k75x;a6*`_tC9>BaI{Q&kt+&zz8;%iy!RFUgSe*;;|}DYm=!PzdW9!3Y!k zj0vE8240zk^P`#%Bw@;YrgwJ0{p(3UKHevY2t> z?!{Nug|Nfnj4-iJU{T7a(c7uBp#7u_Bw@;YMkV!J4*QqM6hq#pH_NBdPw&g1$OzhKU2IaGI=KR^8TgdBW6UQ6vwWgwX`#XgWXSp0-Ohvkk9NHToQ$^Q zGb2pwbKwWI{zmIIU2uNyq#qC5t|`05u{DXh0ou=*k0eZ)k6DxO`QX#?dRg8ll;zXt(s%SJ z`e6s2|2(=!GUR-!ccOfn?ksZv8e_Gmj4-j!bz913m|vU~_)K_3!j$>Ux;+Hn53(+~ z0`C*X@^PA)f<71K+v51f!gnM?&gXD(%BN%t=LGPH{>lgw`z*Rkt^ZRo;>9uWnVmwy zl=)mOR35M2$K9!lm zkn_3fLHSJXpz{>Mu6Z!R#6IJ`QR|Nt-ueaSC-mz?!j$>wHtY8{v>&Ukw!BXy%jebg zPuPCGpVKb}Rod!LGUR;L6rp^&FUg13U*CE&!o)sR)>A%X-2CQ1`+3xlgemhm@86*d z_^b$Y;C-T4J_q8d-F_`pZ+W#ZEdRkv|4Oj3958#8_AIKnJ|U&2|8X6@4qkH%Lo(u z4E{!~e;9ZoybQFT6NgEdG9TB`WA=g1kt2R6j zj9ZzEi!q!{WQ2)*-mam2^z!5S5*IF#Fl9b#Z?~!hJ_SxV@je4tKIO`Nz+J*CPgoJ~ zDSDP<$oU*BK=}-v<(3R#Rjx3?#6H`)Qa;*~?@xsGqrOeTl=*C%HX7eQc6>@f$Qzv$@GmiLKf`FQT2+K=szvwfjTZF`UmIiE4DD4(*fbMa)M zcnBj*?32`+@^Lx4bvpQ%N0KmQK07~r!RMPk{neiL8N%|})9N2=KbH+gjR&8)6G?`g z&nFe-GspElzHH>jR7RNC$GSY_6Z8E-V}zUcApxmQUpIm*^8W zrujwi+5duM$oYhy*21vuZowTP?A2RFnAqp&8ESp(7YF@XfKTPGButr)xvq&Z^gmN; zdheD<`Yd@8Tks}DX~{TX3mpGT&Y z&%_qJ@cGI)y-AodAFbK*Kig^X|GRd)+fxG&+XDWEx$te2PZX%GCV;wffRu2$3_|I4uQhWw!O}Vo19g%}Ns+^$($pdZl=o zg32{HP&=9w3Dd+zT^dtHafvq` zfYD@qAx+X~&Rt_%x9!-HPoKaj^y4tTKx3Ik75Y3xqaE*8PJ&t$|1N}Jt;93$PL`sK z?suu!64K&RSZQJ-a~;aaX@vKDFuJQZoK#Smk$;G#7a09a`HPPj$259X>OLBsbU$ni zwTjF)iiF4+U0n7P+tKW*Wpp8}MnP7Z*y#Iu>h(ouYIbr0qw2+kG-XDKH$D{uBQMKw zeD%gNjc({XKqIyFfUZ!hklI3soKe2&lu-v?12oFtfR!dTy5EU1>V2dB9WeUtB%~=b z^4KxF0vK6`PvVUxFpUyQ+(V<$t&aQyMuP?kA#z4txBkF(RAbzp3y|hGf|VvV>RymC zs#|1OG8j3J6Vj9!O^UmL=SRPWPvMOwGL0^3QSIn)!pbhNKcI#hM9#>rC1rH$OglSBTRxGMCN^@-LmB;b_0dc)N}3_0DKkoRwQd4N zx9>0FjV3dVW-p!o~sUN6W*}W#71EUsn-@>8?)a9 zjK+T!(v%r(n|3h?j4FRy#v8>ljnrdr;l8%|X-6%n)n8i6Nr;?LQ7_79@N+%97O^v6 zrHPHA`cp>7emLX#(YwMznlhtj9nAj)qg~Zj^VOTeG}`5G8;wSe?B5iO-dPACaz>61 zzhXP`zID7Vr0uX}rHPH!TTw<6oz69fcC^P)NK|PI4K#8J zuN)7xdQd|Mku#bQL>Ub!et8b0owj17iH!=porB_^|6YXGBDd{@G-XEGJsci`k$&mT zywTrGqrH`GqS4o({c1q1HkB7b4FdChIJ8v|NY4mq-svYgTR;M4-YKgHBB4@OCFlBV{?*96a)>O?(6B|8m zOc{N#pRNl=*5!mWWk&Y;v*N+%k;!h}XgbrV{$R@JR1t^GP^*x#LWrDEJ6+1it-o$- zNHeR*N)sEk(4vgm*iJeDMjNXNY08X7&2Co|j1sHt=Z$7CjTR(b!F_Gs&)ILGRtGGE z5ILjfF`sc?+j3&!SxEcGmX#(pdc2c*rE_F}fg>0tISOgYjE2SkT?>pll|IB9&14$g zs(KZT)E#P_fm+?ID1^uvbuC62mEU`@45V$X&Po#-%?P56imjOqM%p$)nlhs!W(`+? zQF;4gywNPC(WoG*9o@Co8xFNNW6;G=C#jn%JmO1Qrp##mszcMkXt+fJZ#0`}RKxfZwxh`QMH9hjxvdZ)XY`^nWmI8s%~6on$&r;N zHhO%CdcFL~{U_tWs8s_YO_@>N(uTTVJ&@0qlQn_=b=`2Y6&57M!mOu z#CBx!ET99Vt+8RHiH(9MP)2Vn^}Ys1w;Y5tWkzkRzM6wkve^aRXfD&}zWrrvM)sOs?@zF;&__X=+` zk7;zlnldV$@5p>G8mJONv5Ym(x zy-c)=10y%%8@$ncrjhZI^Vp8&TmBURwF)dLgvc30G-RcTjhrh|MsK&i!hLN;5g|>P(U~9R&p6 zy*Q@P&C8Tg>ppiApjNGPACnL{qi@=j(ZR9J!XYi$fR!dT3b``_Tjj6vs>0BYR7Hd| zWkz2-8;${^?=7D5)my|gia&J@+tIu!OA0`(EZPVmaz@>!y~A2nKQrtaq}g|3rHPG_ z=1@j`7Zw`>M(er>Y08WO&K2GXMpc~t;f)qEjq0cq(Wphr!bqsq&Q?N*oYCF#lu=2q zKvPKb@?fQjjrw{}Mk|I~dILu7yo5AmM$Tmn9Ka}c;9K5k3Dc;r`2{pGZP}(I)GFUF zAwaXtC?Ulef>w?Xera^ z_)V%ERXo%g=hkf6E`-P#)p4SXF8Yl$0HZVUtTeGvt6h|lQz!ivU^MZRkfzM&o9>U} zU{oaOD{r)nX*9DE)o1Ivgzke{1-}qNXv z7!CL$q$xA{{JsSC+0$P9)!5(L@KN@>rd>*LP zKX-%>Iio5mudy8sIX;rQ6ZMFdCN?_%ZW^Y=>XbAFqb|upnlhsf6H4lU(T&1+d83s~ zqrdi^LZgX3V;6!^ff7Q9oYCW%l+laTPOBm9oGB|!Z1i<6Wz@6%rx##!%1lU8W;9}8 zOA|0smoVUsRxyptH=ahL0q?Hk`BA?zLWrEv)*6&ip^4j9fKd~3R+`vo;c&_*@?;Gk zFj`VWNKG$SGad9cJTHEBdbQN zG_jGcGi6jLWJhT*ifbmMDKm=u=O7wwuTz9KTEjG&UY*+4`X2rM5^9yyPzaGTn%9{! zs!=0P0Hnn^vC_mwr3+C;)g5MR0HZZ7LYgw89m6`UgLahMxfpM>mT44tooYw6e{&CD zYR>b2;VXp58Etv@54NMPTMFV8^3-0eG_jGxvA;3Rv(e{4U^FaLNK(&*(D0rF>B4_k$JY^Kt{P_e(>o}X0CN^3+kur+DvtczDg)R`% zlo_2Y{BAfHNt zj*29((!@r4O(>&%0sB3n9sNiY(v%skv^_l%j20g<=Z!WpjS^c@``Vd2i8xlf=cEuK zXY}5kGMYUpZVDKUJjY5C8!fv&6~%AN?u&CGCR`TMlo=hZ{qJHh^0`!%H`>HBs^w1^ zCExR_47F;1QwWhWI`TXjYqernNIghj`PfjPi6V5dubgQmps_ZDAVqtVJ0)TASji*g8FH z5`wi7KMOIiJY}@h>@2pU#syeuVk37G%IMUTHTXM_T1x;T)~{1%wbeqws?-a9^{X8jok~dPb}?u~ESFDVWxKW$YwqM+PN?G-XD* z!EGWG8h@4A*GAl( z`4DPVrKu1iXJl$m8BH?vTmWg_&a5=C(el@^*eV0J%sc`{(QZPTq|x{LZ}He4)-1pX zj6T$H;f;1Njiw!>+R?|;e%+x~?u~^IIV0B_&#+dfbfULInn!b1n%HRL7Rt!!!-%$E zG`f|Lrp##In>IMlzj-%z-e@<|$bUW6jvCeNh0pkf`UxR&M&k!lMklrfM}bk&-&Cyg%CNT=Vd6P zmkx_@6yelKR+`wTqYY(bv+K)aFxsCeq)8f`yz&_LwT5#NsCKly18=mKX{1%}5E>16 zItY!t_Xr_!MoGt?;=cCKzM2uVqxJ__X=0-bg(#y|E!T#Ck>^n%O_|YJowdWD9c?+> znK#g5R`M9%1TFlFS_a0rfSo;t%y6B`x1IvK@#?{Dq_M#&e1 zG-XDg*XM}^qg9)|d87SIqq5Ei(8zwbRb4Q;vr7n(GkR`J8Rb1+^aG?VJitm58%>x> z89g4d>>L>FI4-0qGy3r6M0YSMzt)d8if0-{-=^Bprs;j3L9O&R3n6kw@Ap2zEkD?{ zHy+n&?qH>fjZC^wMr$8E?*K*)dxbP*MmE7q{lLiUP!Hbd0MqE^eSoqwkxDXO<|>pjYj!XMr!@7cwCz}Lr7C*G-BfY1Tb1WIhr>*$~3wX|v8U6dv5TB;Hyi5p@GurG*84d8QG9Qe_t!AZ(jlTbwgst+Eeds@6G-!j6rp%~A z{yQFE6csy)H#*KVs%}XcnN+{k7iu+fx)35~^z=g#)+%B3X?&)}Y7Q$+Y*ZtGGJ5@W zR2?ufT_~g}GaA*r)d(=!5ju`HI>9u05lR^yIeFkY7%l2Agvc3{olhCHuye!fevhH7 zG_jH8G|K3+RRK3J>O5LVQ)XnpC)yQ^N_CyY8=YhtJ+|J1$F)KeJn^_@>Mw-I8Fg+# l8TBsn0L8ZivC_mwe|b?xrQ8F$gVF3TAx)Xl^lrxY{~ueokgNaz diff --git a/docs/notebooks/logs/train/events.out.tfevents.1663844068.sebastianp-lptp.1320413.1.v2 b/docs/notebooks/logs/train/events.out.tfevents.1663844068.sebastianp-lptp.1320413.1.v2 deleted file mode 100644 index bab3605456b188f7f2cac114e23e88cc3252e211..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 212670 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 diff --git a/docs/notebooks/logs/train/events.out.tfevents.1663944078.sebastianp-lptp.2242101.0.v2 b/docs/notebooks/logs/train/events.out.tfevents.1663944078.sebastianp-lptp.2242101.0.v2 deleted file mode 100644 index e626493762ab6816cb0f2fb33c786341fd04a317..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 671910 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 N<2IB<^sZk@{|~dt{vZGV diff --git a/docs/notebooks/weights.data-00000-of-00001 b/docs/notebooks/weights.data-00000-of-00001 deleted file mode 100644 index 2f4d3cecb256307cbb22481acca55182e4134409..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9289 zcmc(h1yoht*7qstJb)4gjfAwM?6pCWG)R%|kS?V}L?o0>6%;86mF6MOUZ4UJl1dw- z3Me3oO6bS&z0Y&+75&EdJ@lea z$$Kl3(1aP2{&4dp;q!uHYXor5RXUo9vGYg(|cR@@-J$G54&NAxs)b6 zLv)=e>V*(V{JUX^|(Y7Uv~nS+(JPJlPvOg?>P)}YCt<-;rm zKdAQ;zuL=#0``5o!kSkP!gK!ffpTeTkk&51m_9-il9M0rbDd!Z8nPW19=tpTADJK9 z)Ycb+Jk{nkG*kR=^I&Hh)m>{4dTr0`G&Ky!h#x8KiMGXO_LB7lWsD=C@j`DRo>yZ{ z{NnkVxx`@ZO^D7A4L7W*(Q;Ddd4SS;&KrGpga#+ND|9LAnJC`ePU<^kpP4Yfu^ zqQH)yOq)EC3To_BzIfttEM_3}G~;f+1Q-x`9#isJ0lRCe*(`PVDLzOsG6b(Gh%PHCq4OkjMth$}-V4(nXMQkZutSlQoF(WIy~UO7-` zzgI-nCUVO|>SGWHQ$FJN#yfdR18Wqms{XRT3RXh&hD)Cp;77y4ZifwfV^Rh=CoTm_ zA-(sHU+cgB0@3kWXCm37hw+s^Jtupo1B*7e!NX>813!05M(b3J4OXP9@z|Z?7QX9I zc-X8$Iku4WWjS?A$7zPW?gTyGxV$y5Zt@{_zWT4ZUu6Vqh9qeocQ&!v*lZDR(>6TX zO{yFI9K*)xYafU+1|gHz&n~K7BL(-grs$md*RU`9%^mkyl_1t7OUt`95u51pqP#`y6*FB>#;)RRRS@9{=R#;l+qlwPxVC0I-h0k+LtWcu} z)t}3*LIk2&$8OwXLppEJ4J|fSBH7i;NAfjAFxPL#ZmYGdV~6coH!R6CV6VJzO)*gu z)@BWS2zuuI8qW~)JarI^Jh~>2E#(SbcriPNh?Ve!YQ1L%dV4&B>`IkLZ_^sh*Qk$J=j#V~+D?;L2X{>HF-B(SpRMNJV*D7d+90t@ zoO}ttdUc`4pywtsNH=+3%G?mhc1F@==AMLW4HV4D!d9`aK34kCoT5?rM82j3Bj9DCvm7GTtwBx{sj4 zpHa}6Fust}%&p5>K|WZo+jT5gDj!hb-*0(&78AjpuBbks0)=+IFa1iofe2>Ujb2El z1>Qu>5^;?U$k#U(?g0e9$_4d?EiPg@e#5i$REwCp!Z*nd?p|zo`El-!^)8H>slmVh z)-~+gcZKClkcR0P%byLXrUen&m1hEcmk|T<_m)0?2qAlIRmz9H+aXR-?>ROK-Yb84 zDdh?jSOCvV*|jG3r`YXm+07ch4J7()#8;)uq_EK?A?d8BCvxzb?_$c94kqKlLV{08 z4KI%tk(gjh@8u&b$9BUbDG$0$_MSl4lvKKW1a;x+`Hr)k={itYH%{##sSNBEwxxPF zP6bq%zAvd3lEA!y7mFEXen{=1^vwXKKKy5!S>pN}eHh(~JaaXDg?tcr?lZ>51brVw zEwB1Y0YtliA{+Myl0bbdo~_>uduC3ST9YFPLx)CY_)Jofc=C;VIVLLb57bjsruZ~0 zR#*6PP^SSwjy>%V&=Uf)d^JmFs_n5dVt0x3#CwREF#-tZL9nggO@cr9FTDaa)7y7j@B}OV7u8*?Cwqv~_OJV`fjj`SV+cp0| zL!?aqJMSLdd&ph#_5H6Shm~`DpZf18x`7NQx?iw!ZNzY4nJr?@n&1^pJ6#nSBg7VX zT@M#40FEnxpA6rtAXMrhJD6lip@=}DsMbF9< z)Xz@>?x&epCjP*sxD8Ga!u+t#Du55f-7$EVw58)ZPbl~hw}Gy%zDkIfQx>_x&Sx&o`c7~z$#L8Tliwg?+_xMK;~EI#TYXWv=gX>2xM zd)X^Q4};0U?zG3aKyjlpFFx-J;=b;mtTfLB3@@?CUldaUA4D8aY@iXy#=eYciFtnb zcsRSvX5kH1Yd)_&rN9T2FFgOAyrsk1hRTtkhbvRexj#u9JCsS!5RK$2PkWuHY-oS2 zoKV-GF!uTpmSC39c}VXaK9Khv+2b!7fTs@==sG6>cIq^kguk%GpOh9)V$O5NZVO%g zFyI%1Elgi6X|I|>f}d$f80Y39jq`R6QPm7!Wq8j4`+h1cv~ot5(VGP1?=hjj1VsKTZ{?`Bw6@5e;N?cQ@eISHRx z;#ut;l0Dj?XD?Pr~q`&EyYK!OB%rN{2tO zgkn$g-@f`bejbmm-f7;4kilVS{NkpO6*gDgOjUlw3K_K+^>e_SFrrb0TL}-(Vx6Yv zQb^xP;|&Vff1GQF&yx}pbZJ19wt^fUc-PJY&nC5stT`8*kky47U-Z+ybV3%83Z_ z0)C4wlLAIVb?Ns%ry*c%O675q9W>z@#qB!eg;5`o+}P8TjJHu#xH+wyNL1(GPK}klFo<1{J*m1(xhaKzb624^B2Qx@CLO?paMtb1 zBlKCq_)H>U3?JWb%59Q_T=&}{`ZY=wN*Es{J{hNm5glFUE>kSUOQzSqe$^uj9rk=X zAd>eP@zuWgZJL=EO1Ry9LMM%Y3i;SqeMaxGDDARj?6Ed-<^D_6xwj~kNoa4lo^}U0 z)xD$kRI?x$c&58|`lLJ{im&G@VHiNPm`&}6h!mkbr3!y|(s?8b_i1-x^AHlzF-DwD zPX^@$FSL?N?}4|kKMZGT{Eie8`x~v-5(AUgwzX!hGJMoPeTto&uy3(A3;c*5RH5IVSzKoE~4mmtnllHQ@!2FVv_cjT;BV zVqwp{8arUjtAx7=xr1PQ(Kqwi<53W`skN)`!~)QL8@$qDFa-ibxaljZ$078{Vrq*R z0R!o}B*%qD0X0>@qg!6xfPuvMRYuNJko(nW*gowEsJnRj77trF%rGI-O?}w__EHeZ zxUfD4#tv&41xgP_h?x>un&qX%zrjb4&DG zUK+yFmQCH3BZW{*l0&ZXs0k=!eors;BnglhOOFe1C4x-lKlZ6Q8$w=x)>sp@2yo%` ztoCP}Fqk01@b*e;Ds1Z*?63*02R+LooIGJ8z}ISNP>jkE#M0LhPiSQWv;3RXpC*{$ z0{$`+hlMG~FIJAaFx&c{rf;;p6~f0 zK^y3$AYD%v7zUmuU!rWDHiVckvlsMM0h9T=MkEtEpNU~G$I3_m?;T8>Pn_)`kJ;I8M2n^H@m=@WjD9oF2rs@2OAiOm53SGbphO^D zp2x@%qa0+}7yscM+6;~?R%Gz3&VymSs3-9)W>C${)`}st37&eVTJt0x!gQhmn$g4F zz~RY?Df#oKP`5|@zEZalY>5gr%WNwL#fqB_>}ocUCsuIf?p0s#VgI`ijdLzgLpj5P zT+ACv!D-P@vu1E7d0o9|uLY>dIuYkbS_&?$9Sobj8wteiik#0>90d)Vo?P8b=`g6@ z`f%w(Zy5cgYqWd@fy*40);VnckV)v}!7xz^Kx?v?y1{G%hn9rYVk~aJ3oZ4&uawn+ zKzp^Bw_rV}EuQ77$$J6HKanxVWm^G$L9!&vsykqEms}7PXDe`LzO0}>m;ra8ZoRy$ zG4PrTpJ+f>Dpa}9T-lf%1(f4g(--9)!&R8IW1*=DULETmJ!(4+r#hUOv*R4$u(ykX z=+`_z(k|D!OKI9e3=CjL`r}pPMd9ce;eHYhv-bK`z4s3 zU#MTgaTa)na0}k^X#{VqI}TY_x`E22sk+1#G5G330rQ&;7ie-=I=A^cy(RM9Vt z!(_nux~JjeMgeTN`07#j9tqeZV~I+&M*;Z~eE9@z7nEWgBTp)j2U)W)uJPq#;D@fu z9``&4sE+Bry(b<7S&p$qkK8DRk5v3vcHB3F-6=6&pUI){fW^oy-E>#LAUGcA6)g^O zdHK^U{1X7P+}Pw5R%>9*B^sn~z6z=ug?U?3nZo|hqKrkSJwdScd~I_|%wcjyj{!e{L2}QWKWB(3$|wzb(J^fu<4; z6J^x7`5b^$2{LBuq4$8~d{OkSF=>dh#bk@9^Fs4VUM7pPZD7ygmk$U1r-0I>Q!}~g zApkX`Xk43Y1dB+k<@#w&z+hzEQE1`}OHQopIAKu+?#ZhWr*pN!*`!5rI-6z?h6AG{_k=`Oz|M8Af~iHnGfJTZmw#~6@ZD3Y;%pkJMbLs9o{sjqrf0}Zf~ht6kMmI zid!6b0^weE=E3iwfJ1iAW@m8|@cuFu5yWy1dT=gz_$^j~GZ1S|xtF`WV#VdXArV904?*OUoe|C&5*kftGdO z3DB6y{8DQ<3&t$OcIT@k1625;{_Ly^l%Vw)5?}I!8rNoSy6W7A#hLYH(h6KK=Q0Rc zzTFBN&vF*Xt`x($7CDQKhD;E|xU99Ao(dTQ8Y`72&p_*p;!|aJ&Eco=7^k@DFc{O@ zAHla_4>&Sd87zhWfLWmj%V>BpXk@7<5VGqI@O>4Vb0oe1)=?heNrsN_DAWCqS>~0n zder}O6+a%R4hk}o^KG4%9r@I?y8Qs4wFI}VoYEgp@B)cX4y%O@ z$*_^DFgIci4^&jcq;a7)p>L9O(3ccNn1}Cg8eq8v8*Im%YtD#6me{s*^?r4*DOM!j zynYc_3-6?oG^GKOU494q)iZ!w!m~#GyLfoKz>%6S)d7;!21VZSuYlQEB*rSw>;Px+ zr6dbi6Sx-rKu)6|7%sF}hXYFrwfLVBI7tDzVO>TDI>RG#>#q4Em&xl&^ zrErG*OIjIpUNB_Z@MoGdCQ9XJl#=B(>By6%8vu`;ufm}Ah!+uXPC^&L=sw^_TiT>>61=^CT2_5>ZD zZ9>*q8DNI~aKR>34XmLor@wyR8Ag`+MZT|70Z(;mkG{Dp1bfYb!+El-!4V(JsN-5x zupgCoQg%eEj|%q{v%qc<|JNzM<$u5kvG;n0# z>qGF0%b`x&{56=(=Sc8!OND(O_@hMLJOmw0e%rvkB(!=`<1C z@d$dUGblCYwZaop47E;h}t}{qDvJxgbH}5*+>S8pl2wv=M56H zP!~S!kN72O)TV@17l)HaU6^yY&0njbeYvGphXxL!>U#Qjhk_(geaB-9oS_n^6p=&N ziBe6peC+(BR2e_o!Th|tMOGcHw(64ZlMzRo9u`B|(%tBZHzbdOJP|a0ZpSKTI}a*~ zPUr}|)kbek4+`sFmPX@TjoE3Xx9)ZRm0)f_kM0GyQ>?$Fm(hmH4P;(j>6SCz~1|S1T`Ba36AB*KbGg5 zeVr`N**iNr`TA@7UD_ww96oa+%cDGO|CHNeh!u5>t~1 z6H%LQP4B=_Sh}3E_IC84rlusvk-OM?yW6``vrXomTrDqzo*8Lds+H;dHendLBP}eE1vdW@N~b% z({IN!{Do)yH#`e9JtY&4+SS>`-qqR3!^7?`U5s0);QoyDW0rGE5c4l0{&xh?R~wi-F+N9yxr{WES=pw{d~8ounR|L`PaOqgF7|d z))bYcjq@3MTVD_FzYuJ{N3d^4u>Xu8m_!i6u}uu;@5B&(LP&o1?<4Qo9(m8tkqL;s zzenubj@b7z0!K|t$%Ui*(L3(8_CIREw>8K8&pB#FN*)}otG&CUual3hwX40)k5x2V zPVnN0P5vq)-|sWw-<}Eo&zTU!2>c!)xE&$*Gr|q$NKJ2~qNk~%s-tFUq@rV}hNE)y zw3M(Uv_6N{uePu_;gR?+TS#0?#lS#MQ`OKwO<(-qu|Gr;T=c@ZYzs;AkC22t#-a0@ zpoE8iKP&~Gdf{?nr06-V;-#gY6UDh?s!Z;L|+`kxht&`Bb{?riGTVzM^KFVdharzgwN{RpT4i^9Oxc__A-M#e+qkv=i>mv0b z+_JVVgm;gv6EOtmzb#oxpFdMG`$cLJ;{WwN^XKrNWk)!b!-#Rg|Cc1J{vVR~*Zc18 zm5GqZuf6-{26XvlCfi==#JA6w{Qac<{~eP2)0%%6^}piK&q@66IVAZDKmJ=CV%&PS WQp6EUYz;~{V#%#WA~e(1_x}Lz{dr;l diff --git a/docs/notebooks/weights.index b/docs/notebooks/weights.index deleted file mode 100644 index 690a59bd89b78233cf94aa222dd70a807c824b4d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1298 zcmZQzVB=tvV&Y(Akl~Ma_HcFf4)FK%3vqPvagFzP@^Wrr{x#rrl!Pa<`tBd=<7L#gammyg@(8W>xVf8d4k;#=I9gZ%E2VWA;iQX z3B-&F9Xc8(7)=w-Zu}+cEtH*Fl$V;L52bQa^U_N)ijxy_Qj5v4gavFtgN_D==?=@d zWy+R(U~l9lr;=kDgTfDOph=yx`-DUt#Bx&;^WxJ=^O8$4^Yio_$uSTV28>`QJ^&dU zYwlL6Y$TLKj!_Vwz5p4c$vlHy)KsJ}KDU${li(2pij@ej{fER&C5j7+O2{#b6YN1| zj-yNpCm1zWh?q*MuhkHa5I4knF31N*u3eL&QM$UJ3k+?uCt33;PFEK| zCVjZ5*C=W#PI0^`d=LeBylduFdFn*n4slS_*_)o;BJ9Rzq@RNV8qPWJY2gM2M&?|GJ)Cec+oMb#2RS*;aq@$N@PqK*4c#iG G?zaIvGKNV2 From 78f3cc1b060424be17670255ccc8aa2134a35e30 Mon Sep 17 00:00:00 2001 From: hstojic Date: Fri, 25 Nov 2022 11:01:08 +0000 Subject: [PATCH 15/25] added contributors --- CONTRIBUTORS.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index f7a9ad67..da214008 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -11,8 +11,12 @@ Because GitHub's [graph of contributors](http://github.com/secondmind-labs/GPflu [James A. Leedham](https://github.com/JamesALeedham) [Felix Leibfried](https://github.com/fleibfried), [John A. McLeod](https://github.com/johnamcleod), +[Jesper Nielsen](https://github.com/jesnie), +[Sebastian Ober](https://github.com/sebastianober), +[Sebastian Popescu](https://github.com/SebastianPopescu), [Hugh Salimbeni](https://github.com/hughsalimbeni), +[Hrvoje Stojic](https://github.com/hstojic), [Marcin B. Tomczak](https://github.com/marctom) -Feel free to add yourself when you first contribute to GPflux's code, tests, or documentation! \ No newline at end of file +Feel free to add yourself when you first contribute to GPflux's code, tests, or documentation! From d9130d04b55bf4e1efe362157bde4f1a59c98c8b Mon Sep 17 00:00:00 2001 From: hstojic Date: Fri, 25 Nov 2022 11:13:13 +0000 Subject: [PATCH 16/25] typing --- .../fourier_features/multioutput/base.py | 4 +- .../test_multioutput_rff_cosine.py | 43 +++++++++---------- 2 files changed, 23 insertions(+), 24 deletions(-) diff --git a/gpflux/layers/basis_functions/fourier_features/multioutput/base.py b/gpflux/layers/basis_functions/fourier_features/multioutput/base.py index c014cb35..d5dcc274 100644 --- a/gpflux/layers/basis_functions/fourier_features/multioutput/base.py +++ b/gpflux/layers/basis_functions/fourier_features/multioutput/base.py @@ -87,14 +87,14 @@ def call(self, inputs: TensorType) -> tf.Tensor: else: raise ValueError("kernel is not supported.") - print('-- size of inputs ---') + print("-- size of inputs ---") print(inputs) X = tf.divide( tf.cast(inputs, tf.float64), # [N, D] or [P, M, D] _lengthscales, # [P, 1, D] ) # [P, N, D] or [P, M, D] - print('--- size of X ---') + print("--- size of X ---") print(X) const = self._compute_constant()[..., None, None] # [P,1,1] diff --git a/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff_cosine.py b/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff_cosine.py index 0317dea2..13a1a249 100644 --- a/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff_cosine.py +++ b/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff_cosine.py @@ -27,6 +27,7 @@ SeparateMultiOutputKernelWithFeatureDecomposition, SharedMultiOutputKernelWithFeatureDecomposition, ) +from gpflux.helpers import construct_basic_kernel from gpflux.layers.basis_functions.fourier_features import ( MultiOutputRandomFourierFeatures, MultiOutputRandomFourierFeaturesCosine, @@ -34,21 +35,19 @@ from gpflux.layers.basis_functions.fourier_features.random.base import RFF_SUPPORTED_KERNELS from tests.conftest import skip_serialization_tests -from gpflux.helpers import construct_basic_kernel @pytest.fixture(name="n_dims", params=[1, 2, 3, 5, 10, 20]) def _n_dims_fixture(request): return request.param - -#@pytest.fixture(name="variance", params=[0.5, 1.0, 2.0]) +# @pytest.fixture(name="variance", params=[0.5, 1.0, 2.0]) @pytest.fixture(name="variance", params=[0.5]) def _variance_fixture(request): return request.param -#@pytest.fixture(name="lengthscale", params=[0.1, 1.0, 5.0]) +# @pytest.fixture(name="lengthscale", params=[0.1, 1.0, 5.0]) @pytest.fixture(name="lengthscale", params=[0.1]) def _lengthscale_fixture(request): return request.param @@ -84,6 +83,7 @@ def _random_basis_func_cls_fixture(request): def _basis_func_cls_fixture(request): return request.param + @pytest.mark.skip def test_throw_for_unsupported_separate_kernel(basis_func_cls): base_kernel = gpflow.kernels.Constant() @@ -92,6 +92,7 @@ def test_throw_for_unsupported_separate_kernel(basis_func_cls): basis_func_cls(kernel, n_components=1) assert "Unsupported Kernel" in str(excinfo.value) + @pytest.mark.skip def test_throw_for_unsupported_shared_kernel(basis_func_cls): base_kernel = gpflow.kernels.Constant() @@ -101,25 +102,23 @@ def test_throw_for_unsupported_shared_kernel(basis_func_cls): assert "Unsupported Kernel" in str(excinfo.value) - - - - @pytest.mark.parametrize("output_dim", [2]) @pytest.mark.parametrize("n_components", [100]) @pytest.mark.parametrize("size_dataset", [10]) -def test_separate_kernel_multioutput_rff_cosine(n_components: int, output_dim : int, size_dataset : int, variance, lengthscale) -> None: +def test_separate_kernel_multioutput_rff_cosine( + n_components: int, output_dim: int, size_dataset: int, variance, lengthscale +) -> None: + + # search_space = Box([0.0], [1.0]) ** output_dim + # x = search_space.sample(size_dataset) + # print('--- shape of samples ----') + # print(x.shape) - #search_space = Box([0.0], [1.0]) ** output_dim - #x = search_space.sample(size_dataset) - #print('--- shape of samples ----') - #print(x.shape) - x = tf.random.uniform((size_dataset, output_dim), dtype=tf.float64) - print('----x ----') + print("----x ----") print(x) lengthscales = np.random.rand((output_dim)) * lengthscale - lengthscales = tf.cast(lengthscales, dtype = tf.float64) + lengthscales = tf.cast(lengthscales, dtype=tf.float64) print(lengthscales) print("size of sampled lengthscales") @@ -127,20 +126,20 @@ def test_separate_kernel_multioutput_rff_cosine(n_components: int, output_dim : base_kernel = gpflow.kernels.SquaredExponential(variance=variance, lengthscales=lengthscales) - #kernel = construct_basic_kernel( + # kernel = construct_basic_kernel( # [base_kernel for _ in range(output_dim)], share_hyperparams=False - #) + # ) kernel = SeparateIndependent(kernels=[base_kernel for _ in range(output_dim)]) - rff = MultiOutputRandomFourierFeaturesCosine(kernel = kernel, n_components = n_components) - output = rff(inputs = tf.cast(x, tf.float64)) + rff = MultiOutputRandomFourierFeaturesCosine(kernel=kernel, n_components=n_components) + output = rff(inputs=tf.cast(x, tf.float64)) - print('---- shape of output ----') + print("---- shape of output ----") print(output) tf.debugging.assert_shapes([(output, [output_dim, size_dataset, n_components])]) - + @pytest.mark.skip def test_random_fourier_features_can_approximate_multi_output_separate_kernel_multidim( From 31438e4e43722e5a68849d18d55b4f23c240627f Mon Sep 17 00:00:00 2001 From: hstojic Date: Fri, 25 Nov 2022 12:38:58 +0000 Subject: [PATCH 17/25] undone black changes --- .../notebooks/efficient_posterior_sampling.py | 37 ++++--------------- docs/notebooks/efficient_sampling.py | 3 -- docs/notebooks/gpflux_features.py | 5 +-- docs/notebooks/keras_integration.py | 10 +---- docs/notebooks/weight_space_approximation.py | 12 ++---- .../constant_input_dim_deep_gp.py | 5 +-- .../directly_parameterized_encoder.py | 6 +-- gpflux/experiment_support/plotting.py | 5 +-- .../basis_functions/fourier_features/base.py | 10 +---- gpflux/layers/gp_layer.py | 10 +---- gpflux/layers/latent_variable_layer.py | 5 +-- gpflux/models/deep_gp.py | 4 +- tests/conftest.py | 4 +- .../fourier_features/test_random.py | 6 +-- tests/gpflux/layers/test_likelihood_layer.py | 5 +-- tests/gpflux/test_helpers.py | 6 +-- tests/integration/test_svgp_equivalence.py | 5 +-- 17 files changed, 26 insertions(+), 112 deletions(-) diff --git a/docs/notebooks/efficient_posterior_sampling.py b/docs/notebooks/efficient_posterior_sampling.py index 95821d1a..aa406296 100644 --- a/docs/notebooks/efficient_posterior_sampling.py +++ b/docs/notebooks/efficient_posterior_sampling.py @@ -80,10 +80,7 @@ from gpflow.models import GPR from gpflux.layers.basis_functions.fourier_features import RandomFourierFeaturesCosine -from gpflux.feature_decomposition_kernels.kernel_with_feature_decomposition import ( - KernelWithFeatureDecomposition, -) - +from gpflux.feature_decomposition_kernels.kernel_with_feature_decomposition import KernelWithFeatureDecomposition # %% [markdown] """ @@ -99,13 +96,7 @@ # settings that vary across experiments num_input_dimensions = [2, 4, 8] # number of input dimensions -train_sample_exponents = [ - 2, - 4, - 6, - 8, - 10, -] # num_train_samples = 2 ** train_sample_exponents +train_sample_exponents = [2, 4, 6, 8, 10] # num_train_samples = 2 ** train_sample_exponents num_train_samples = [2 ** train_sample_exponent for train_sample_exponent in train_sample_exponents] num_features = [ 1024, @@ -269,9 +260,7 @@ def conduct_experiment(num_input_dimensions, num_train_samples, num_features): ) feature_coefficients = np.ones((num_features, 1), dtype=default_float()) approximate_kernel = KernelWithFeatureDecomposition( - kernel=None, - feature_functions=feature_functions, - feature_coefficients=feature_coefficients, + kernel=None, feature_functions=feature_functions, feature_coefficients=feature_coefficients ) # create training data set and test points for evaluation @@ -305,11 +294,7 @@ def conduct_experiment(num_input_dimensions, num_train_samples, num_features): # identify mean and covariance of the analytic GPR posterior when using the weight space approximated kernel f_mean_weight, f_var_weight = compute_analytic_GP_predictions( - X=X, - y=y, - kernel=approximate_kernel, - noise_variance=noise_variance, - X_star=X_star, + X=X, y=y, kernel=approximate_kernel, noise_variance=noise_variance, X_star=X_star ) # identify mean and covariance using the hybrid approximation @@ -436,7 +421,7 @@ def conduct_experiment_for_different_num_features(num_input_dimensions): ) # for the analytic solution using the weight space approximated kernel list_of_hybrid_results = [] # for the hybrid-rule approximation for nf in num_features: - (weight_results, hybrid_results,) = conduct_experiment_for_different_train_data_sizes( + weight_results, hybrid_results = conduct_experiment_for_different_train_data_sizes( num_input_dimensions=num_input_dimensions, num_features=nf ) print() @@ -473,11 +458,7 @@ def conduct_experiment_for_different_num_features(num_input_dimensions): for j in range(len(weight_results)): weight_result = weight_results[j] axs[i].fill_between( - num_train_samples, - weight_result[0], - weight_result[2], - color=colors[j], - alpha=0.1, + num_train_samples, weight_result[0], weight_result[2], color=colors[j], alpha=0.1 ) axs[i].plot(num_train_samples, weight_result[1], "o", color=colors[j]) axs[i].plot(num_train_samples, weight_result[1], color=colors[j], linewidth=0.5) @@ -488,11 +469,7 @@ def conduct_experiment_for_different_num_features(num_input_dimensions): for j in range(len(hybrid_results)): hybrid_result = hybrid_results[j] axs[i].fill_between( - num_train_samples, - hybrid_result[0], - hybrid_result[2], - color=colors[j], - alpha=0.1, + num_train_samples, hybrid_result[0], hybrid_result[2], color=colors[j], alpha=0.1 ) axs[i].plot(num_train_samples, hybrid_result[1], "o", color=colors[j]) axs[i].plot(num_train_samples, hybrid_result[1], color=colors[j], linewidth=0.5) diff --git a/docs/notebooks/efficient_sampling.py b/docs/notebooks/efficient_sampling.py index fa4ae370..225f67ad 100644 --- a/docs/notebooks/efficient_sampling.py +++ b/docs/notebooks/efficient_sampling.py @@ -67,16 +67,13 @@ Z = np.linspace(X.min(), X.max(), 10).reshape(-1, 1).astype(np.float64) inducing_variable = gpflow.inducing_variables.InducingPoints(Z) - gpflow.utilities.set_trainable(inducing_variable, False) num_rff = 1000 eigenfunctions = RandomFourierFeaturesCosine(kernel, num_rff, dtype=default_float()) eigenvalues = np.ones((num_rff, 1), dtype=default_float()) - kernel_with_features = KernelWithFeatureDecomposition(kernel, eigenfunctions, eigenvalues) - # %% [markdown] """ ## Building and training the single-layer GP diff --git a/docs/notebooks/gpflux_features.py b/docs/notebooks/gpflux_features.py index d6bc45b2..909ea7fd 100644 --- a/docs/notebooks/gpflux_features.py +++ b/docs/notebooks/gpflux_features.py @@ -67,10 +67,7 @@ def motorcycle_data(): from gpflux.models import DeepGP config = Config( - num_inducing=25, - inner_layer_qsqrt_factor=1e-5, - likelihood_noise_variance=1e-2, - whiten=True, + num_inducing=25, inner_layer_qsqrt_factor=1e-5, likelihood_noise_variance=1e-2, whiten=True ) deep_gp: DeepGP = build_constant_input_dim_deep_gp(X, num_layers=2, config=config) diff --git a/docs/notebooks/keras_integration.py b/docs/notebooks/keras_integration.py index 09e7ea68..80083b66 100644 --- a/docs/notebooks/keras_integration.py +++ b/docs/notebooks/keras_integration.py @@ -99,10 +99,7 @@ def create_model(model_class): dgp_train.compile(tf.optimizers.Adam(learning_rate=0.1)) history = dgp_train.fit( - {"inputs": X, "targets": Y}, - batch_size=batch_size, - epochs=num_epochs, - callbacks=callbacks, + {"inputs": X, "targets": Y}, batch_size=batch_size, epochs=num_epochs, callbacks=callbacks ) # %% @@ -132,10 +129,7 @@ def create_model(model_class): ) history_natgrad = dgp_natgrad_train.fit( - {"inputs": X, "targets": Y}, - batch_size=batch_size, - epochs=num_epochs, - callbacks=callbacks, + {"inputs": X, "targets": Y}, batch_size=batch_size, epochs=num_epochs, callbacks=callbacks ) # %% diff --git a/docs/notebooks/weight_space_approximation.py b/docs/notebooks/weight_space_approximation.py index 55d8ac8d..512b395b 100644 --- a/docs/notebooks/weight_space_approximation.py +++ b/docs/notebooks/weight_space_approximation.py @@ -103,16 +103,12 @@ # %% # generate training data and evaluation points for both sets of experiments kernel = kernel_class(lengthscales=lengthscale) # kernel object to draw training dataset from -X, y, X_star = ( - [], - [], - [], -) # training points, training observations, and test points for evaluation +X, y, X_star = [], [], [] # training points, training observations, and test points for evaluation # 1st iteration: experiments with few training points -- 2nd iteration: experiments with many training points for i in range(len(number_of_train_samples)): - # training pointsnumber_of_train_samples + # training points X.append(np.linspace(start=X_interval[0], stop=X_interval[1], num=number_of_train_samples[i])) # training observations generated from a zero-mean GP corrupted with Gaussian noise @@ -275,9 +271,7 @@ def optimize_model_with_scipy(model): ) feature_coefficients = np.ones((number_of_features, 1), dtype=default_float()) kernel = KernelWithFeatureDecomposition( - kernel=None, - feature_functions=feature_functions, - feature_coefficients=feature_coefficients, + kernel=None, feature_functions=feature_functions, feature_coefficients=feature_coefficients ) gpr_model = GPR( data=(X[experiment][..., None], y[experiment][..., None]), diff --git a/gpflux/architectures/constant_input_dim_deep_gp.py b/gpflux/architectures/constant_input_dim_deep_gp.py index bc18d89e..50c07418 100644 --- a/gpflux/architectures/constant_input_dim_deep_gp.py +++ b/gpflux/architectures/constant_input_dim_deep_gp.py @@ -133,10 +133,7 @@ def build_constant_input_dim_deep_gp(X: np.ndarray, num_layers: int, config: Con # Pass in kernels, specify output dim (shared hyperparams/variables) inducing_var = construct_basic_inducing_variables( - num_inducing=config.num_inducing, - input_dim=D_in, - share_variables=True, - z_init=centroids, + num_inducing=config.num_inducing, input_dim=D_in, share_variables=True, z_init=centroids ) kernel = construct_basic_kernel( diff --git a/gpflux/encoders/directly_parameterized_encoder.py b/gpflux/encoders/directly_parameterized_encoder.py index a3418472..9823dd4e 100644 --- a/gpflux/encoders/directly_parameterized_encoder.py +++ b/gpflux/encoders/directly_parameterized_encoder.py @@ -109,10 +109,6 @@ def call( """ if inputs is not None: tf.debugging.assert_shapes( - [ - (self.means, ["N", "W"]), - (self.stds, ["N", "W"]), - (inputs, ["N", "D"]), - ] + [(self.means, ["N", "W"]), (self.stds, ["N", "W"]), (inputs, ["N", "D"])] ) return self.means, self.stds diff --git a/gpflux/experiment_support/plotting.py b/gpflux/experiment_support/plotting.py index 87d7bff9..bf656b5e 100644 --- a/gpflux/experiment_support/plotting.py +++ b/gpflux/experiment_support/plotting.py @@ -63,10 +63,7 @@ def plot_layer( def plot_layers( - X: TensorType, - means: List[TensorType], - covs: List[TensorType], - samples: List[TensorType], + X: TensorType, means: List[TensorType], covs: List[TensorType], samples: List[TensorType] ) -> None: # pragma: no cover L = len(means) fig, axes = plt.subplots(3, L, figsize=(L * 3.33, 10)) diff --git a/gpflux/layers/basis_functions/fourier_features/base.py b/gpflux/layers/basis_functions/fourier_features/base.py index 503a6a51..80461c80 100644 --- a/gpflux/layers/basis_functions/fourier_features/base.py +++ b/gpflux/layers/basis_functions/fourier_features/base.py @@ -48,9 +48,8 @@ def call(self, inputs: TensorType) -> tf.Tensor: :param inputs: The evaluation points, a tensor with the shape ``[N, D]``. - :return: A tensor with the shape ``[N, M]``.mypy + :return: A tensor with the shape ``[N, M]``. """ - X = tf.divide(inputs, self.kernel.lengthscales) # [N, D] const = self._compute_constant() bases = self._compute_bases(X) @@ -66,7 +65,6 @@ def compute_output_shape(self, input_shape: ShapeType) -> tf.TensorShape: """ # TODO: Keras docs say "If the layer has not been built, this method # will call `build` on the layer." -- do we need to do so? - tensor_shape = tf.TensorShape(input_shape).with_rank(2) output_dim = self._compute_output_dim(input_shape) return tensor_shape[:-1].concatenate(output_dim) @@ -79,11 +77,7 @@ def get_config(self) -> Mapping: """ config = super(FourierFeaturesBase, self).get_config() config.update( - { - "kernel": self.kernel, - "n_components": self.n_components, - "input_dim": self._input_dim, - } + {"kernel": self.kernel, "n_components": self.n_components, "input_dim": self._input_dim} ) return config diff --git a/gpflux/layers/gp_layer.py b/gpflux/layers/gp_layer.py index 04ff5f98..a9324555 100644 --- a/gpflux/layers/gp_layer.py +++ b/gpflux/layers/gp_layer.py @@ -208,10 +208,6 @@ def __init__( num_latent_gps, ) - print("**************888") - print(num_inducing) - print(self.num_latent_gps) - self.q_mu = Parameter( np.zeros((num_inducing, self.num_latent_gps)), dtype=default_float(), @@ -311,11 +307,7 @@ def prior_kl(self) -> tf.Tensor: :attr:`whiten`\ ed representation, returns ``KL[q(v)∥p(v)]``. """ return prior_kl( - self.inducing_variable, - self.kernel, - self.q_mu, - self.q_sqrt, - whiten=self.whiten, + self.inducing_variable, self.kernel, self.q_mu, self.q_sqrt, whiten=self.whiten ) def _make_distribution_fn( diff --git a/gpflux/layers/latent_variable_layer.py b/gpflux/layers/latent_variable_layer.py index 6ce576e0..b8e16d59 100644 --- a/gpflux/layers/latent_variable_layer.py +++ b/gpflux/layers/latent_variable_layer.py @@ -183,10 +183,7 @@ def _inference_posteriors( return posteriors def _inference_latent_samples_and_loss( - self, - layer_inputs: TensorType, - observations: ObservationType, - seed: Optional[int] = None, + self, layer_inputs: TensorType, observations: ObservationType, seed: Optional[int] = None ) -> Tuple[tf.Tensor, tf.Tensor]: r""" Sample latent variables during the *training* forward pass, hence requiring diff --git a/gpflux/models/deep_gp.py b/gpflux/models/deep_gp.py index f3650637..529e2ca7 100644 --- a/gpflux/models/deep_gp.py +++ b/gpflux/models/deep_gp.py @@ -291,9 +291,7 @@ def as_prediction_model( return model_class(self.inputs, outputs) -def sample_dgp( - model: DeepGP, -) -> Sample: # TODO: should this be part of a [Vanilla]DeepGP class? +def sample_dgp(model: DeepGP) -> Sample: # TODO: should this be part of a [Vanilla]DeepGP class? function_draws = [layer.sample() for layer in model.f_layers] # TODO: error check that all layers implement .sample()? diff --git a/tests/conftest.py b/tests/conftest.py index 7b42b147..69b39d72 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -24,9 +24,7 @@ def test_data(): input_data = np.concatenate([x_data, w_data], axis=1) assert input_data.shape == (num_data, x_dim + w_dim) y_data = np.random.multivariate_normal( - mean=np.zeros(num_data), - cov=SquaredExponential(variance=0.1)(input_data), - size=y_dim, + mean=np.zeros(num_data), cov=SquaredExponential(variance=0.1)(input_data), size=y_dim ).T assert y_data.shape == (num_data, y_dim) return x_data, y_data diff --git a/tests/gpflux/layers/basis_functions/fourier_features/test_random.py b/tests/gpflux/layers/basis_functions/fourier_features/test_random.py index f897bad4..774a6997 100644 --- a/tests/gpflux/layers/basis_functions/fourier_features/test_random.py +++ b/tests/gpflux/layers/basis_functions/fourier_features/test_random.py @@ -70,11 +70,7 @@ def _random_basis_func_cls_fixture(request): @pytest.fixture( name="basis_func_cls", - params=[ - RandomFourierFeatures, - RandomFourierFeaturesCosine, - OrthogonalRandomFeatures, - ], + params=[RandomFourierFeatures, RandomFourierFeaturesCosine, OrthogonalRandomFeatures], ) def _basis_func_cls_fixture(request): return request.param diff --git a/tests/gpflux/layers/test_likelihood_layer.py b/tests/gpflux/layers/test_likelihood_layer.py index 0b227b88..a978aca2 100644 --- a/tests/gpflux/layers/test_likelihood_layer.py +++ b/tests/gpflux/layers/test_likelihood_layer.py @@ -53,10 +53,7 @@ def make_data(input_dim: int, output_dim: int, num_data: int): cov = Matern52()(X) + np.eye(num_data) * sigma ** 2 Y = [np.random.multivariate_normal(np.zeros(num_data), cov)[:, None] for _ in range(output_dim)] Y = np.hstack(Y) - return ( - X, - Y, - ) # TODO: improve this test; for most of the likelihoods, Y won't actually be valid + return X, Y # TODO: improve this test; for most of the likelihoods, Y won't actually be valid @pytest.mark.parametrize("GPflowLikelihood", TEST_GPFLOW_LIKELIHOODS) diff --git a/tests/gpflux/test_helpers.py b/tests/gpflux/test_helpers.py index 203550c2..04517deb 100644 --- a/tests/gpflux/test_helpers.py +++ b/tests/gpflux/test_helpers.py @@ -131,11 +131,7 @@ def test_construct_inducing_shared_independent_duplicates(z_init): z_init = None moiv = construct_basic_inducing_variables( - num_inducing, - input_dim, - output_dim=output_dim, - share_variables=True, - z_init=z_init, + num_inducing, input_dim, output_dim=output_dim, share_variables=True, z_init=z_init ) assert isinstance(moiv, SharedIndependentInducingVariables) diff --git a/tests/integration/test_svgp_equivalence.py b/tests/integration/test_svgp_equivalence.py index 18143d7a..ab7d86dc 100644 --- a/tests/integration/test_svgp_equivalence.py +++ b/tests/integration/test_svgp_equivalence.py @@ -132,10 +132,7 @@ def test_svgp_equivalence_after_assign(): def fit_adam( - model: Union[gpflow.models.SVGP, gpflux.models.DeepGP], - data, - maxiter, - adam_learning_rate=0.01, + model: Union[gpflow.models.SVGP, gpflux.models.DeepGP], data, maxiter, adam_learning_rate=0.01 ): X, Y = data num_data = len(X) From 39b5739439d530fc68a80316280d16ff7b16e2c6 Mon Sep 17 00:00:00 2001 From: hstojic Date: Fri, 25 Nov 2022 14:39:55 +0000 Subject: [PATCH 18/25] fixed dtype error --- .../notebooks/efficient_posterior_sampling.py | 4 ++- .../test_multioutput_rff_cosine.py | 34 ++++--------------- 2 files changed, 9 insertions(+), 29 deletions(-) diff --git a/docs/notebooks/efficient_posterior_sampling.py b/docs/notebooks/efficient_posterior_sampling.py index aa406296..22d7a22b 100644 --- a/docs/notebooks/efficient_posterior_sampling.py +++ b/docs/notebooks/efficient_posterior_sampling.py @@ -80,7 +80,9 @@ from gpflow.models import GPR from gpflux.layers.basis_functions.fourier_features import RandomFourierFeaturesCosine -from gpflux.feature_decomposition_kernels.kernel_with_feature_decomposition import KernelWithFeatureDecomposition +from gpflux.feature_decomposition_kernels.kernel_with_feature_decomposition import ( + KernelWithFeatureDecomposition, +) # %% [markdown] """ diff --git a/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff_cosine.py b/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff_cosine.py index 13a1a249..c54275c2 100644 --- a/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff_cosine.py +++ b/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff_cosine.py @@ -106,24 +106,13 @@ def test_throw_for_unsupported_shared_kernel(basis_func_cls): @pytest.mark.parametrize("n_components", [100]) @pytest.mark.parametrize("size_dataset", [10]) def test_separate_kernel_multioutput_rff_cosine( - n_components: int, output_dim: int, size_dataset: int, variance, lengthscale + n_components: int, output_dim: int, size_dataset: int, variance: float, lengthscale: float ) -> None: - - # search_space = Box([0.0], [1.0]) ** output_dim - # x = search_space.sample(size_dataset) - # print('--- shape of samples ----') - # print(x.shape) - x = tf.random.uniform((size_dataset, output_dim), dtype=tf.float64) - print("----x ----") - print(x) + lengthscales = np.random.rand((output_dim)) * lengthscale lengthscales = tf.cast(lengthscales, dtype=tf.float64) - print(lengthscales) - print("size of sampled lengthscales") - print(lengthscales.shape) - base_kernel = gpflow.kernels.SquaredExponential(variance=variance, lengthscales=lengthscales) # kernel = construct_basic_kernel( @@ -132,11 +121,8 @@ def test_separate_kernel_multioutput_rff_cosine( kernel = SeparateIndependent(kernels=[base_kernel for _ in range(output_dim)]) - rff = MultiOutputRandomFourierFeaturesCosine(kernel=kernel, n_components=n_components) - output = rff(inputs=tf.cast(x, tf.float64)) - - print("---- shape of output ----") - print(output) + rff = MultiOutputRandomFourierFeaturesCosine(kernel=kernel, n_components=n_components, dtype=tf.float64) + output = rff(inputs=x) tf.debugging.assert_shapes([(output, [output_dim, size_dataset, n_components])]) @@ -146,14 +132,10 @@ def test_random_fourier_features_can_approximate_multi_output_separate_kernel_mu random_basis_func_cls, base_kernel_cls, variance, lengthscale, n_dims ): n_components = 40000 - x_rows = 20 y_rows = 30 - # ARD - lengthscales = np.random.rand((n_dims)) * lengthscale - print("size of sampled lengthscales") - print(lengthscales.shape) + lengthscales = np.random.rand((n_dims)) * lengthscale base_kernel = base_kernel_cls(variance=variance, lengthscales=lengthscales) @@ -185,14 +167,10 @@ def test_random_fourier_features_can_approximate_multi_output_shared_kernel_mult random_basis_func_cls, base_kernel_cls, variance, lengthscale, n_dims ): n_components = 40000 - x_rows = 20 y_rows = 30 - # ARD - lengthscales = np.random.rand((n_dims)) * lengthscale - print("size of sampled lengthscales") - print(lengthscales.shape) + lengthscales = np.random.rand((n_dims)) * lengthscale base_kernel = base_kernel_cls(variance=variance, lengthscales=lengthscales) From a30b5710db9161ef387ed38797d18e11b6911f6e Mon Sep 17 00:00:00 2001 From: hstojic Date: Fri, 25 Nov 2022 14:41:59 +0000 Subject: [PATCH 19/25] removed prints --- .../fourier_features/multioutput/base.py | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/gpflux/layers/basis_functions/fourier_features/multioutput/base.py b/gpflux/layers/basis_functions/fourier_features/multioutput/base.py index d5dcc274..4ba4fbf4 100644 --- a/gpflux/layers/basis_functions/fourier_features/multioutput/base.py +++ b/gpflux/layers/basis_functions/fourier_features/multioutput/base.py @@ -50,10 +50,8 @@ def call(self, inputs: TensorType) -> tf.Tensor: Evaluate the basis functions at ``inputs``. :param inputs: The evaluation points, a tensor with the shape ``[N, D]``. - :return: A tensor with the shape ``[P, N, M]``.mypy """ - P = self.kernel.num_latent_gps D = tf.shape(inputs)[-1] @@ -71,8 +69,6 @@ def call(self, inputs: TensorType) -> tf.Tensor: ], axis=0, ) # [P, 1, D] - print("size of _lengthscales") - print(_lengthscales) tf.debugging.assert_equal(tf.shape(_lengthscales), [P, 1, D]) elif isinstance(self.kernel, gpflow.kernels.SharedIndependent): @@ -87,15 +83,10 @@ def call(self, inputs: TensorType) -> tf.Tensor: else: raise ValueError("kernel is not supported.") - print("-- size of inputs ---") - print(inputs) - X = tf.divide( - tf.cast(inputs, tf.float64), # [N, D] or [P, M, D] + inputs, # [N, D] or [P, M, D] _lengthscales, # [P, 1, D] ) # [P, N, D] or [P, M, D] - print("--- size of X ---") - print(X) const = self._compute_constant()[..., None, None] # [P,1,1] bases = self._compute_bases(X) # [P, N, L] for X*, or [P,M,L] in the case of Z From 825a460db6954a8026e3ded08a6c7cc9c2b5e997 Mon Sep 17 00:00:00 2001 From: hstojic Date: Fri, 25 Nov 2022 14:42:28 +0000 Subject: [PATCH 20/25] formatting --- .../fourier_features/test_multioutput_rff_cosine.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff_cosine.py b/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff_cosine.py index c54275c2..e4bd8e65 100644 --- a/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff_cosine.py +++ b/tests/gpflux/layers/basis_functions/fourier_features/test_multioutput_rff_cosine.py @@ -109,7 +109,7 @@ def test_separate_kernel_multioutput_rff_cosine( n_components: int, output_dim: int, size_dataset: int, variance: float, lengthscale: float ) -> None: x = tf.random.uniform((size_dataset, output_dim), dtype=tf.float64) - + lengthscales = np.random.rand((output_dim)) * lengthscale lengthscales = tf.cast(lengthscales, dtype=tf.float64) @@ -121,7 +121,9 @@ def test_separate_kernel_multioutput_rff_cosine( kernel = SeparateIndependent(kernels=[base_kernel for _ in range(output_dim)]) - rff = MultiOutputRandomFourierFeaturesCosine(kernel=kernel, n_components=n_components, dtype=tf.float64) + rff = MultiOutputRandomFourierFeaturesCosine( + kernel=kernel, n_components=n_components, dtype=tf.float64 + ) output = rff(inputs=x) tf.debugging.assert_shapes([(output, [output_dim, size_dataset, n_components])]) From e3998a86383ee35101905e65062b26a59e70cc22 Mon Sep 17 00:00:00 2001 From: SebastianPopescu Date: Tue, 29 Nov 2022 15:42:59 +0000 Subject: [PATCH 21/25] added comments --- .../kernel_with_feature_decomposition.py | 15 +++++++++++---- .../basis_functions/fourier_features/base.py | 1 - .../fourier_features/multioutput/base.py | 6 +++++- .../fourier_features/multioutput/random/base.py | 12 ++++++++++-- gpflux/sampling/multioutput/sample.py | 4 ++++ 5 files changed, 30 insertions(+), 8 deletions(-) diff --git a/gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py b/gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py index 5e1a9289..1f64234b 100644 --- a/gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py +++ b/gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py @@ -38,9 +38,11 @@ NoneType = type(None) - +#TODO -- this needs to be a subclass of ApproximateKernel and maybe MultiOutputKernel as well +#NOTE -- I think the MultiOutputKernel needs to be here for the dispatcher in the covariances class _MultiOutputApproximateKernel(gpflow.kernels.MultioutputKernel): r""" + #TODO -- update documentation to suit multioutput case This class approximates a kernel by the finite feature decomposition: .. math:: k(x, x') = \sum_{i=0}^L \lambda_i \phi_i(x) \phi_i(x'), @@ -134,7 +136,7 @@ def __call__( X: TensorType, X2: Optional[TensorType] = None, *, - full_cov: bool = True, # NOTE -- otherwise will throw errors + full_cov: bool = True, # NOTE -- otherwise will throw errors, isn't this problematic though? full_output_cov: bool = True, presliced: bool = False, ) -> tf.Tensor: @@ -213,12 +215,14 @@ def __init__( ``feature_functions(X)`` returns a tensor with the shape ``[P, N, L]``. :param feature_coefficients: A tensor with the shape ``[P, L, 1]`` with coefficients associated with the features, :math:`\lambda_i`. + #TODO -- add output_dim """ if kernel is None: # NOTE -- this is a subclass of gpflow.kernels.SharedIndependent # (needed to be used with dispatchers from gpflow.covariances) - # so it needs to be initialized somehow. Not sure if efficient + # so it needs to be initialized somehow. + # TODO -- Not sure if most efficient way _dummy_kernel = SquaredExponential() super().__init__(_dummy_kernel, output_dim) self._kernel = _MultiOutputApproximateKernel(feature_functions, feature_coefficients) @@ -267,6 +271,7 @@ def K_diag(self, X: TensorType, full_output_cov: bool = True) -> tf.Tensor: return self._kernel.K_diag(X, full_output_cov) +#NOTE -- this is the same as the Shared case above class SeparateMultiOutputKernelWithFeatureDecompositionBase(gpflow.kernels.SeparateIndependent): """ @@ -282,7 +287,7 @@ def __call__( X: TensorType, X2: Optional[TensorType] = None, *, - full_cov: bool = True, # NOTE -- otherwise will throw errors + full_cov: bool = True, # NOTE -- otherwise will throw errors, again this might be problematic here full_output_cov: bool = True, presliced: bool = False, ) -> tf.Tensor: @@ -297,6 +302,7 @@ def __call__( return self.K(X, X2, full_output_cov=full_output_cov) +#NOTE -- this is the same as the Shared case above class SeparateMultiOutputKernelWithFeatureDecomposition( SeparateMultiOutputKernelWithFeatureDecompositionBase ): @@ -367,6 +373,7 @@ def __init__( # NOTE -- this is a subclass of gpflow.kernels.SeparateIndependent # (needed to be used with dispatchers from gpflow.covariances) # so it needs to be initialized somehow. Not sure if efficient + #TODO -- this is dodgy, needs smarter solution _dummy_kernels = [SquaredExponential() for _ in range(output_dim)] super().__init__(_dummy_kernels) self._kernel = _MultiOutputApproximateKernel(feature_functions, feature_coefficients) diff --git a/gpflux/layers/basis_functions/fourier_features/base.py b/gpflux/layers/basis_functions/fourier_features/base.py index 80461c80..6282606b 100644 --- a/gpflux/layers/basis_functions/fourier_features/base.py +++ b/gpflux/layers/basis_functions/fourier_features/base.py @@ -22,7 +22,6 @@ import gpflow from gpflow.base import TensorType - from gpflux.types import ShapeType diff --git a/gpflux/layers/basis_functions/fourier_features/multioutput/base.py b/gpflux/layers/basis_functions/fourier_features/multioutput/base.py index 4ba4fbf4..fab26679 100644 --- a/gpflux/layers/basis_functions/fourier_features/multioutput/base.py +++ b/gpflux/layers/basis_functions/fourier_features/multioutput/base.py @@ -22,7 +22,6 @@ import gpflow from gpflow.base import TensorType - from gpflux.types import ShapeType @@ -37,6 +36,7 @@ def __init__( quadrature nodes, etc.) used to numerically approximate the kernel. """ super(MultiOutputFourierFeaturesBase, self).__init__(**kwargs) + #NOTE -- same as univariate case from here till the end of __init__ self.kernel = kernel self.n_components = n_components if kwargs.get("input_dim", None): @@ -108,6 +108,7 @@ def compute_output_shape(self, input_shape: ShapeType) -> tf.TensorShape: output_dim = self._compute_output_dim(input_shape) return tensor_shape[:-1].concatenate(output_dim) + #NOTE -- same as univariate case def get_config(self) -> Mapping: """ Returns the config of the layer. @@ -125,10 +126,12 @@ def get_config(self) -> Mapping: return config + #NOTE -- same as univariate case @abstractmethod def _compute_output_dim(self, input_shape: ShapeType) -> int: pass + #NOTE -- same as univariate case @abstractmethod def _compute_constant(self) -> tf.Tensor: """ @@ -136,6 +139,7 @@ def _compute_constant(self) -> tf.Tensor: """ pass + #NOTE -- same as univariate case @abstractmethod def _compute_bases(self, inputs: TensorType) -> tf.Tensor: """ diff --git a/gpflux/layers/basis_functions/fourier_features/multioutput/random/base.py b/gpflux/layers/basis_functions/fourier_features/multioutput/random/base.py index 9b225c48..c6a5feec 100644 --- a/gpflux/layers/basis_functions/fourier_features/multioutput/random/base.py +++ b/gpflux/layers/basis_functions/fourier_features/multioutput/random/base.py @@ -44,7 +44,7 @@ gpflow.kernels.Matern52, ) - +#TODO -- import this from the univariate folder def _sample_students_t(nu: float, shape: ShapeType, dtype: DType) -> TensorType: """ Draw samples from a (central) Student's t-distribution using the following: @@ -88,6 +88,7 @@ def __init__( raise ValueError("kernel specified is not supported.") super(MultiOutputRandomFourierFeaturesBase, self).__init__(kernel, n_components, **kwargs) + #NOTE -- same as univariate case def build(self, input_shape: ShapeType) -> None: """ Creates the variables of the layer. @@ -136,6 +137,7 @@ def _weights_init(self, shape: TensorType, dtype: Optional[DType] = None) -> Ten else: raise ValueError("kernel is not supported.") + #NOTE -- same as univariate case @staticmethod def rff_constant(variance: TensorType, output_dim: int) -> tf.Tensor: """ @@ -146,6 +148,7 @@ def rff_constant(variance: TensorType, output_dim: int) -> tf.Tensor: class MultiOutputRandomFourierFeatures(MultiOutputRandomFourierFeaturesBase): r""" + #TODO -- update documentation to suit multioutput case Random Fourier features (RFF) is a method for approximating kernels. The essential element of the RFF approach :cite:p:`rahimi2007random` is the realization that Bochner's theorem for stationary kernels can be approximated by a Monte Carlo sum. @@ -178,6 +181,7 @@ class MultiOutputRandomFourierFeatures(MultiOutputRandomFourierFeaturesBase): from phase-shifted cosines :class:`RandomFourierFeaturesCosine` :cite:p:`sutherland2015error`. """ + #NOTE -- same as univariate case def _compute_output_dim(self, input_shape: ShapeType) -> int: return 2 * self.n_components @@ -213,6 +217,7 @@ def _compute_constant(self) -> tf.Tensor: class MultiOutputRandomFourierFeaturesCosine(MultiOutputRandomFourierFeaturesBase): r""" + #TODO -- update documentation to suit multioutput case Random Fourier Features (RFF) is a method for approximating kernels. The essential element of the RFF approach :cite:p:`rahimi2007random` is the realization that Bochner's theorem for stationary kernels can be approximated by a Monte Carlo sum. @@ -262,12 +267,15 @@ def _bias_build(self, n_components: int) -> None: initializer=self._bias_init, ) + #NOTE -- same as univariate case def _bias_init(self, shape: TensorType, dtype: Optional[DType] = None) -> TensorType: return tf.random.uniform(shape=shape, maxval=2.0 * np.pi, dtype=dtype) - + + #NOTE -- same as univariate case def _compute_output_dim(self, input_shape: ShapeType) -> int: return self.n_components + #NOTE -- same as univariate case def _compute_bases(self, inputs: TensorType) -> tf.Tensor: """ Compute basis functions. diff --git a/gpflux/sampling/multioutput/sample.py b/gpflux/sampling/multioutput/sample.py index bbfaf191..b6e0f9fc 100644 --- a/gpflux/sampling/multioutput/sample.py +++ b/gpflux/sampling/multioutput/sample.py @@ -71,6 +71,10 @@ def _efficient_multi_output_sample_matheron_rule( :param whiten: Determines the parameterisation of the inducing variables. """ + #TODO -- this makes sense just in the case of SeparateMultiOutputKernelWithFeatureDecomposition + #NOTE -- in the case of SharedMdultiOutputKernelWithFeatureDecomposition we can just rely on gpflux.sampliung.sample._efficient_sample_matheron_rule + + # Reshape kernel.feature_coefficients _feature_coefficients = tf.transpose(kernel.feature_coefficients[..., 0]) # [L,P] From a5dce5ce267e5d037f15edfaca05cba36671557d Mon Sep 17 00:00:00 2001 From: Simon Chiu Date: Wed, 30 Nov 2022 10:31:47 +0000 Subject: [PATCH 22/25] Comments --- .../kernel_with_feature_decomposition.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py b/gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py index 1f64234b..24c202d1 100644 --- a/gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py +++ b/gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py @@ -38,7 +38,7 @@ NoneType = type(None) -#TODO -- this needs to be a subclass of ApproximateKernel and maybe MultiOutputKernel as well +#TODO -- this needs to be a subclass of ApproximateKernel and maybe MultioutputKernel as well #NOTE -- I think the MultiOutputKernel needs to be here for the dispatcher in the covariances class _MultiOutputApproximateKernel(gpflow.kernels.MultioutputKernel): r""" @@ -49,6 +49,10 @@ class _MultiOutputApproximateKernel(gpflow.kernels.MultioutputKernel): where :math:`\lambda_i` and :math:`\phi_i(\cdot)` are the coefficients and features, respectively. + + This class deals with the case of multiple kernels producing multiple outputs. + They are computed together here for improved efficiency dervied from vectorizing the whole + lot together before putting it through tensorflow (improve this comment) """ @@ -67,11 +71,13 @@ def __init__( self._feature_functions = feature_functions # [P, N, L] self._feature_coefficients = feature_coefficients # [P, L, 1] + # Concretises ABC methods from MultioutputKernel @property def num_latent_gps(self) -> int: # In this case number of latent GPs (L) == output_dim (P) return tf.shape(self._feature_coefficients)[0] + # Concretises ABC methods from MultioutputKernel @property def latent_kernels(self) -> Any: """In this scenario we do not have access to the underlying kernels, @@ -121,6 +127,11 @@ def K_diag(self, X: TensorType, full_output_cov: bool = False) -> tf.Tensor: return r +# The difference between shared and separate case is the *kernel*. +# Shared: kernel is SharedIndependent +# Separate: kernel is SeparateIndependent. +# Use static typing (?) +# TODO: DRY class SharedMultiOutputKernelWithFeatureDecompositionBase(gpflow.kernels.SharedIndependent): """ From f0fcba32cc3a6f9f13c2d9cd0f685e8bbcbd2856 Mon Sep 17 00:00:00 2001 From: Simon Chiu Date: Wed, 30 Nov 2022 13:32:57 +0000 Subject: [PATCH 23/25] Comment --- .../multioutput/kernel_with_feature_decomposition.py | 1 + 1 file changed, 1 insertion(+) diff --git a/gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py b/gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py index 24c202d1..a2974887 100644 --- a/gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py +++ b/gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py @@ -43,6 +43,7 @@ class _MultiOutputApproximateKernel(gpflow.kernels.MultioutputKernel): r""" #TODO -- update documentation to suit multioutput case + TODO: unless # [P, N, L] etc. are used in static analysis, we can probably unify this with _ApproximateKernel This class approximates a kernel by the finite feature decomposition: .. math:: k(x, x') = \sum_{i=0}^L \lambda_i \phi_i(x) \phi_i(x'), From 97b0b1f1ccddc550b52a3c126f79acd3e6e7078b Mon Sep 17 00:00:00 2001 From: Simon Chiu Date: Wed, 30 Nov 2022 13:36:40 +0000 Subject: [PATCH 24/25] format --- .../kernel_with_feature_decomposition.py | 14 +++++++------- .../fourier_features/multioutput/base.py | 10 +++++----- .../fourier_features/multioutput/random/base.py | 16 ++++++++-------- gpflux/sampling/multioutput/sample.py | 5 ++--- 4 files changed, 22 insertions(+), 23 deletions(-) diff --git a/gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py b/gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py index a2974887..87fd118f 100644 --- a/gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py +++ b/gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py @@ -38,8 +38,8 @@ NoneType = type(None) -#TODO -- this needs to be a subclass of ApproximateKernel and maybe MultioutputKernel as well -#NOTE -- I think the MultiOutputKernel needs to be here for the dispatcher in the covariances +# TODO -- this needs to be a subclass of ApproximateKernel and maybe MultioutputKernel as well +# NOTE -- I think the MultiOutputKernel needs to be here for the dispatcher in the covariances class _MultiOutputApproximateKernel(gpflow.kernels.MultioutputKernel): r""" #TODO -- update documentation to suit multioutput case @@ -50,7 +50,7 @@ class _MultiOutputApproximateKernel(gpflow.kernels.MultioutputKernel): where :math:`\lambda_i` and :math:`\phi_i(\cdot)` are the coefficients and features, respectively. - + This class deals with the case of multiple kernels producing multiple outputs. They are computed together here for improved efficiency dervied from vectorizing the whole lot together before putting it through tensorflow (improve this comment) @@ -233,7 +233,7 @@ def __init__( if kernel is None: # NOTE -- this is a subclass of gpflow.kernels.SharedIndependent # (needed to be used with dispatchers from gpflow.covariances) - # so it needs to be initialized somehow. + # so it needs to be initialized somehow. # TODO -- Not sure if most efficient way _dummy_kernel = SquaredExponential() super().__init__(_dummy_kernel, output_dim) @@ -283,7 +283,7 @@ def K_diag(self, X: TensorType, full_output_cov: bool = True) -> tf.Tensor: return self._kernel.K_diag(X, full_output_cov) -#NOTE -- this is the same as the Shared case above +# NOTE -- this is the same as the Shared case above class SeparateMultiOutputKernelWithFeatureDecompositionBase(gpflow.kernels.SeparateIndependent): """ @@ -314,7 +314,7 @@ def __call__( return self.K(X, X2, full_output_cov=full_output_cov) -#NOTE -- this is the same as the Shared case above +# NOTE -- this is the same as the Shared case above class SeparateMultiOutputKernelWithFeatureDecomposition( SeparateMultiOutputKernelWithFeatureDecompositionBase ): @@ -385,7 +385,7 @@ def __init__( # NOTE -- this is a subclass of gpflow.kernels.SeparateIndependent # (needed to be used with dispatchers from gpflow.covariances) # so it needs to be initialized somehow. Not sure if efficient - #TODO -- this is dodgy, needs smarter solution + # TODO -- this is dodgy, needs smarter solution _dummy_kernels = [SquaredExponential() for _ in range(output_dim)] super().__init__(_dummy_kernels) self._kernel = _MultiOutputApproximateKernel(feature_functions, feature_coefficients) diff --git a/gpflux/layers/basis_functions/fourier_features/multioutput/base.py b/gpflux/layers/basis_functions/fourier_features/multioutput/base.py index fab26679..b707de82 100644 --- a/gpflux/layers/basis_functions/fourier_features/multioutput/base.py +++ b/gpflux/layers/basis_functions/fourier_features/multioutput/base.py @@ -36,7 +36,7 @@ def __init__( quadrature nodes, etc.) used to numerically approximate the kernel. """ super(MultiOutputFourierFeaturesBase, self).__init__(**kwargs) - #NOTE -- same as univariate case from here till the end of __init__ + # NOTE -- same as univariate case from here till the end of __init__ self.kernel = kernel self.n_components = n_components if kwargs.get("input_dim", None): @@ -108,7 +108,7 @@ def compute_output_shape(self, input_shape: ShapeType) -> tf.TensorShape: output_dim = self._compute_output_dim(input_shape) return tensor_shape[:-1].concatenate(output_dim) - #NOTE -- same as univariate case + # NOTE -- same as univariate case def get_config(self) -> Mapping: """ Returns the config of the layer. @@ -126,12 +126,12 @@ def get_config(self) -> Mapping: return config - #NOTE -- same as univariate case + # NOTE -- same as univariate case @abstractmethod def _compute_output_dim(self, input_shape: ShapeType) -> int: pass - #NOTE -- same as univariate case + # NOTE -- same as univariate case @abstractmethod def _compute_constant(self) -> tf.Tensor: """ @@ -139,7 +139,7 @@ def _compute_constant(self) -> tf.Tensor: """ pass - #NOTE -- same as univariate case + # NOTE -- same as univariate case @abstractmethod def _compute_bases(self, inputs: TensorType) -> tf.Tensor: """ diff --git a/gpflux/layers/basis_functions/fourier_features/multioutput/random/base.py b/gpflux/layers/basis_functions/fourier_features/multioutput/random/base.py index c6a5feec..fc864ba2 100644 --- a/gpflux/layers/basis_functions/fourier_features/multioutput/random/base.py +++ b/gpflux/layers/basis_functions/fourier_features/multioutput/random/base.py @@ -44,7 +44,7 @@ gpflow.kernels.Matern52, ) -#TODO -- import this from the univariate folder +# TODO -- import this from the univariate folder def _sample_students_t(nu: float, shape: ShapeType, dtype: DType) -> TensorType: """ Draw samples from a (central) Student's t-distribution using the following: @@ -88,7 +88,7 @@ def __init__( raise ValueError("kernel specified is not supported.") super(MultiOutputRandomFourierFeaturesBase, self).__init__(kernel, n_components, **kwargs) - #NOTE -- same as univariate case + # NOTE -- same as univariate case def build(self, input_shape: ShapeType) -> None: """ Creates the variables of the layer. @@ -137,7 +137,7 @@ def _weights_init(self, shape: TensorType, dtype: Optional[DType] = None) -> Ten else: raise ValueError("kernel is not supported.") - #NOTE -- same as univariate case + # NOTE -- same as univariate case @staticmethod def rff_constant(variance: TensorType, output_dim: int) -> tf.Tensor: """ @@ -181,7 +181,7 @@ class MultiOutputRandomFourierFeatures(MultiOutputRandomFourierFeaturesBase): from phase-shifted cosines :class:`RandomFourierFeaturesCosine` :cite:p:`sutherland2015error`. """ - #NOTE -- same as univariate case + # NOTE -- same as univariate case def _compute_output_dim(self, input_shape: ShapeType) -> int: return 2 * self.n_components @@ -267,15 +267,15 @@ def _bias_build(self, n_components: int) -> None: initializer=self._bias_init, ) - #NOTE -- same as univariate case + # NOTE -- same as univariate case def _bias_init(self, shape: TensorType, dtype: Optional[DType] = None) -> TensorType: return tf.random.uniform(shape=shape, maxval=2.0 * np.pi, dtype=dtype) - - #NOTE -- same as univariate case + + # NOTE -- same as univariate case def _compute_output_dim(self, input_shape: ShapeType) -> int: return self.n_components - #NOTE -- same as univariate case + # NOTE -- same as univariate case def _compute_bases(self, inputs: TensorType) -> tf.Tensor: """ Compute basis functions. diff --git a/gpflux/sampling/multioutput/sample.py b/gpflux/sampling/multioutput/sample.py index b6e0f9fc..53db3684 100644 --- a/gpflux/sampling/multioutput/sample.py +++ b/gpflux/sampling/multioutput/sample.py @@ -71,9 +71,8 @@ def _efficient_multi_output_sample_matheron_rule( :param whiten: Determines the parameterisation of the inducing variables. """ - #TODO -- this makes sense just in the case of SeparateMultiOutputKernelWithFeatureDecomposition - #NOTE -- in the case of SharedMdultiOutputKernelWithFeatureDecomposition we can just rely on gpflux.sampliung.sample._efficient_sample_matheron_rule - + # TODO -- this makes sense just in the case of SeparateMultiOutputKernelWithFeatureDecomposition + # NOTE -- in the case of SharedMdultiOutputKernelWithFeatureDecomposition we can just rely on gpflux.sampliung.sample._efficient_sample_matheron_rule # Reshape kernel.feature_coefficients _feature_coefficients = tf.transpose(kernel.feature_coefficients[..., 0]) # [L,P] From 87c63b3fb4efedceda7e3ea1d31e3c261bf8b333 Mon Sep 17 00:00:00 2001 From: Simon Chiu Date: Wed, 30 Nov 2022 16:07:07 +0000 Subject: [PATCH 25/25] Format --- .../multioutput/kernel_with_feature_decomposition.py | 8 +++++--- .../fourier_features/multioutput/random/base.py | 1 + gpflux/sampling/multioutput/sample.py | 3 ++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py b/gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py index 87fd118f..56170c1d 100644 --- a/gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py +++ b/gpflux/feature_decomposition_kernels/multioutput/kernel_with_feature_decomposition.py @@ -38,12 +38,14 @@ NoneType = type(None) + # TODO -- this needs to be a subclass of ApproximateKernel and maybe MultioutputKernel as well # NOTE -- I think the MultiOutputKernel needs to be here for the dispatcher in the covariances class _MultiOutputApproximateKernel(gpflow.kernels.MultioutputKernel): r""" #TODO -- update documentation to suit multioutput case - TODO: unless # [P, N, L] etc. are used in static analysis, we can probably unify this with _ApproximateKernel + TODO: unless # [P, N, L] etc. are used in static analysis, we can probably unify this with + _ApproximateKernel This class approximates a kernel by the finite feature decomposition: .. math:: k(x, x') = \sum_{i=0}^L \lambda_i \phi_i(x) \phi_i(x'), @@ -148,7 +150,7 @@ def __call__( X: TensorType, X2: Optional[TensorType] = None, *, - full_cov: bool = True, # NOTE -- otherwise will throw errors, isn't this problematic though? + full_cov: bool = True, # NOTE -- otherwise will throw errors (possibly posterior related) full_output_cov: bool = True, presliced: bool = False, ) -> tf.Tensor: @@ -299,7 +301,7 @@ def __call__( X: TensorType, X2: Optional[TensorType] = None, *, - full_cov: bool = True, # NOTE -- otherwise will throw errors, again this might be problematic here + full_cov: bool = True, # NOTE -- otherwise will throw errors, might be problematic here full_output_cov: bool = True, presliced: bool = False, ) -> tf.Tensor: diff --git a/gpflux/layers/basis_functions/fourier_features/multioutput/random/base.py b/gpflux/layers/basis_functions/fourier_features/multioutput/random/base.py index fc864ba2..4959f7b5 100644 --- a/gpflux/layers/basis_functions/fourier_features/multioutput/random/base.py +++ b/gpflux/layers/basis_functions/fourier_features/multioutput/random/base.py @@ -44,6 +44,7 @@ gpflow.kernels.Matern52, ) + # TODO -- import this from the univariate folder def _sample_students_t(nu: float, shape: ShapeType, dtype: DType) -> TensorType: """ diff --git a/gpflux/sampling/multioutput/sample.py b/gpflux/sampling/multioutput/sample.py index 53db3684..3cc1bab5 100644 --- a/gpflux/sampling/multioutput/sample.py +++ b/gpflux/sampling/multioutput/sample.py @@ -72,7 +72,8 @@ def _efficient_multi_output_sample_matheron_rule( """ # TODO -- this makes sense just in the case of SeparateMultiOutputKernelWithFeatureDecomposition - # NOTE -- in the case of SharedMdultiOutputKernelWithFeatureDecomposition we can just rely on gpflux.sampliung.sample._efficient_sample_matheron_rule + # NOTE -- in the case of SharedMdultiOutputKernelWithFeatureDecomposition we can just rely on + # gpflux.sampliung.sample._efficient_sample_matheron_rule # Reshape kernel.feature_coefficients _feature_coefficients = tf.transpose(kernel.feature_coefficients[..., 0]) # [L,P]