Skip to content

Commit

Permalink
Merge pull request SheffieldML#640 from pgmoren/devel
Browse files Browse the repository at this point in the history
Sparse GP serialization
  • Loading branch information
zhenwendai authored Jun 25, 2018
2 parents d85c9d5 + 11aa6ea commit 06441f5
Show file tree
Hide file tree
Showing 25 changed files with 535 additions and 117 deletions.
13 changes: 10 additions & 3 deletions GPy/core/gp.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,14 @@ def __init__(self, X, Y, kernel, likelihood, mean_function=None, inference_metho
self.posterior = None

def to_dict(self, save_data=True):
input_dict = super(GP, self)._to_dict()
"""
Convert the object into a json serializable dictionary.
Note: It uses the private method _save_to_input_dict of the parent.
:param boolean save_data: if true, it adds the training data self.X and self.Y to the dictionary
:return dict: json serializable dictionary containing the needed information to instantiate the object
"""
input_dict = super(GP, self)._save_to_input_dict()
input_dict["class"] = "GPy.core.GP"
if not save_data:
input_dict["X"] = None
Expand All @@ -137,7 +144,7 @@ def to_dict(self, save_data=True):
return input_dict

@staticmethod
def _from_dict(input_dict, data=None):
def _build_from_input_dict(input_dict, data=None):
import GPy
import numpy as np
if (input_dict['X'] is None) or (input_dict['Y'] is None):
Expand Down Expand Up @@ -282,7 +289,7 @@ def _raw_predict(self, Xnew, full_cov=False, kern=None):
mu += self.mean_function.f(Xnew)
return mu, var

def predict(self, Xnew, full_cov=False, Y_metadata=None, kern=None,
def predict(self, Xnew, full_cov=False, Y_metadata=None, kern=None,
likelihood=None, include_likelihood=True):
"""
Predict the function(s) at the new point(s) Xnew. This includes the
Expand Down
17 changes: 14 additions & 3 deletions GPy/core/mapping.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def update_gradients(self, dL_dF, X):
def to_dict(self):
raise NotImplementedError

def _to_dict(self):
def _save_to_input_dict(self):
input_dict = {}
input_dict["input_dim"] = self.input_dim
input_dict["output_dim"] = self.output_dim
Expand All @@ -37,16 +37,27 @@ def _to_dict(self):

@staticmethod
def from_dict(input_dict):
"""
Instantiate an object of a derived class using the information
in input_dict (built by the to_dict method of the derived class).
More specifically, after reading the derived class from input_dict,
it calls the method _build_from_input_dict of the derived class.
Note: This method should not be overrided in the derived class. In case
it is needed, please override _build_from_input_dict instate.
:param dict input_dict: Dictionary with all the information needed to
instantiate the object.
"""
import copy
input_dict = copy.deepcopy(input_dict)
mapping_class = input_dict.pop('class')
input_dict["name"] = str(input_dict["name"])
import GPy
mapping_class = eval(mapping_class)
return mapping_class._from_dict(mapping_class, input_dict)
return mapping_class._build_from_input_dict(mapping_class, input_dict)

@staticmethod
def _from_dict(mapping_class, input_dict):
def _build_from_input_dict(mapping_class, input_dict):
return mapping_class(**input_dict)


Expand Down
30 changes: 27 additions & 3 deletions GPy/core/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ class Model(ParamzModel, Priorizable):
def __init__(self, name):
super(Model, self).__init__(name) # Parameterized.__init__(self)

def _to_dict(self):
def _save_to_input_dict(self):
"""
It is used by the public method to_dict to create json serializable dictionary.
"""
input_dict = {}
input_dict["name"] = self.name
return input_dict
Expand All @@ -18,16 +21,37 @@ def to_dict(self):

@staticmethod
def from_dict(input_dict, data=None):
"""
Instantiate an object of a derived class using the information
in input_dict (built by the to_dict method of the derived class).
More specifically, after reading the derived class from input_dict,
it calls the method _build_from_input_dict of the derived class.
Note: This method should not be overrided in the derived class. In case
it is needed, please override _build_from_input_dict instate.
:param dict input_dict: Dictionary with all the information needed to
instantiate the object.
"""
import copy
input_dict = copy.deepcopy(input_dict)
model_class = input_dict.pop('class')
input_dict["name"] = str(input_dict["name"])
import GPy
model_class = eval(model_class)
return model_class._from_dict(input_dict, data)
return model_class._build_from_input_dict(input_dict, data)

@staticmethod
def _from_dict(model_class, input_dict, data=None):
def _build_from_input_dict(model_class, input_dict, data=None):
"""
This method is used by the public method from_dict to build an object
of class model_class using the information contained in input_dict.
Note: This method is often overrided in the derived class to deal with
any pre-processing of the parameters in input_dict before calling the
constructor of the object.
:param str model_class: Class of the object to build.
:param dict input_dict: Extra information needed by the constructor of model_class.
"""
return model_class(**input_dict)

def save_model(self, output_filename, compress=True, save_data=True):
Expand Down
47 changes: 47 additions & 0 deletions GPy/core/sparse_gp.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,50 @@ def _update_gradients(self):
self.Z.gradient = self.kern.gradients_X(self.grad_dict['dL_dKmm'], self.Z)
self.Z.gradient += self.kern.gradients_X(self.grad_dict['dL_dKnm'].T, self.Z, self.X)
self._Zgrad = self.Z.gradient.copy()

def to_dict(self, save_data=True):
"""
Convert the object into a json serializable dictionary.
:param boolean save_data: if true, it adds the training data self.X and self.Y to the dictionary
:return dict: json serializable dictionary containing the needed information to instantiate the object
"""
input_dict = super(SparseGP, self).to_dict(save_data)
input_dict["class"] = "GPy.core.SparseGP"
input_dict["Z"] = self.Z.tolist()
return input_dict

@staticmethod
def _build_from_input_dict(input_dict, data=None):
# Called from the from_dict method.
import GPy
if (input_dict['X'] is None) or (input_dict['Y'] is None):
if data is None:
raise ValueError("The model was serialized whithout the training data. 'data' must be not None!")
input_dict["X"], input_dict["Y"] = np.array(data[0]), np.array(data[1])
elif data is not None:
print("WARNING: The model has been saved with X,Y! The original values are being overriden!")
input_dict["X"], input_dict["Y"] = np.array(data[0]), np.array(data[1])
else:
input_dict["X"], input_dict["Y"] = np.array(input_dict['X']), np.array(input_dict['Y'])

input_dict["Z"] = np.array(input_dict['Z'])
input_dict["kernel"] = GPy.kern.Kern.from_dict(input_dict["kernel"])
input_dict["likelihood"] = GPy.likelihoods.likelihood.Likelihood.from_dict(input_dict["likelihood"])
mean_function = input_dict.get("mean_function")
if mean_function is not None:
input_dict["mean_function"] = GPy.core.mapping.Mapping.from_dict(mean_function)
else:
input_dict["mean_function"] = mean_function
input_dict["inference_method"] = GPy.inference.latent_function_inference.LatentFunctionInference.from_dict(input_dict["inference_method"])

#FIXME: Assumes the Y_metadata is serializable. We should create a Metadata class
Y_metadata = input_dict.get("Y_metadata")
input_dict["Y_metadata"] = Y_metadata

normalizer = input_dict.get("normalizer")
if normalizer is not None:
input_dict["normalizer"] = GPy.util.normalizer._Norm.from_dict(normalizer)
else:
input_dict["normalizer"] = normalizer
return SparseGP(**input_dict)
18 changes: 15 additions & 3 deletions GPy/inference/latent_function_inference/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def on_optimization_end(self):
"""
pass

def _to_dict(self):
def _save_to_input_dict(self):
input_dict = {}
return input_dict

Expand All @@ -50,15 +50,27 @@ def to_dict(self):

@staticmethod
def from_dict(input_dict):
"""
Instantiate an object of a derived class using the information
in input_dict (built by the to_dict method of the derived class).
More specifically, after reading the derived class from input_dict,
it calls the method _build_from_input_dict of the derived class.
Note: This method should not be overrided in the derived class. In case
it is needed, please override _build_from_input_dict instate.
:param dict input_dict: Dictionary with all the information needed to
instantiate the object.
"""

import copy
input_dict = copy.deepcopy(input_dict)
inference_class = input_dict.pop('class')
import GPy
inference_class = eval(inference_class)
return inference_class._from_dict(inference_class, input_dict)
return inference_class._build_from_input_dict(inference_class, input_dict)

@staticmethod
def _from_dict(inference_class, input_dict):
def _build_from_input_dict(inference_class, input_dict):
return inference_class(**input_dict)

class InferenceMethodList(LatentFunctionInference, list):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,15 @@ def __init__(self):
pass#self._YYTfactor_cache = caching.cache()

def to_dict(self):
input_dict = super(ExactGaussianInference, self)._to_dict()
"""
Convert the object into a json serializable dictionary.
Note: It uses the private method _save_to_input_dict of the parent.
:return dict: json serializable dictionary containing the needed information to instantiate the object
"""

input_dict = super(ExactGaussianInference, self)._save_to_input_dict()
input_dict["class"] = "GPy.inference.latent_function_inference.exact_gaussian_inference.ExactGaussianInference"
return input_dict

Expand Down
Loading

0 comments on commit 06441f5

Please sign in to comment.