From eca580651864cd185cb72a68dec363e2514c0036 Mon Sep 17 00:00:00 2001 From: Keerthana Elango Date: Tue, 24 Jul 2018 10:46:33 +0100 Subject: [PATCH] Return deserialized models with actual type instead of base type --- GPy/core/gp.py | 9 ++++-- GPy/core/sparse_gp.py | 38 +++++--------------------- GPy/models/gp_classification.py | 21 ++++++++++++-- GPy/models/sparse_gp_classification.py | 22 ++++++++++++--- GPy/testing/serialization_tests.py | 4 +++ 5 files changed, 54 insertions(+), 40 deletions(-) diff --git a/GPy/core/gp.py b/GPy/core/gp.py index ab7e8f9d..ff3a22fa 100644 --- a/GPy/core/gp.py +++ b/GPy/core/gp.py @@ -144,14 +144,14 @@ class GP(Model): return input_dict @staticmethod - def _build_from_input_dict(input_dict, data=None): + def _format_input_dict(input_dict, data=None): import GPy import numpy as np if (input_dict['X'] is None) or (input_dict['Y'] is None): assert(data is 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!") + warnings.warn("WARNING: The model has been saved with X,Y! The original values are being overridden!") 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']) @@ -173,6 +173,11 @@ class GP(Model): input_dict["normalizer"] = GPy.util.normalizer._Norm.from_dict(normalizer) else: input_dict["normalizer"] = normalizer + return input_dict + + @staticmethod + def _build_from_input_dict(input_dict, data=None): + input_dict = GP._format_input_dict(input_dict, data) return GP(**input_dict) def save_model(self, output_filename, compress=True, save_data=True): diff --git a/GPy/core/sparse_gp.py b/GPy/core/sparse_gp.py index eb3650af..d9439d28 100644 --- a/GPy/core/sparse_gp.py +++ b/GPy/core/sparse_gp.py @@ -130,37 +130,13 @@ class SparseGP(GP): input_dict["Z"] = self.Z.tolist() return input_dict + @staticmethod + def _format_input_dict(input_dict, data=None): + input_dict = GP._format_input_dict(input_dict, data) + input_dict["Z"] = np.array(input_dict["Z"]) + 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 + input_dict = SparseGP._format_input_dict(input_dict, data) return SparseGP(**input_dict) diff --git a/GPy/models/gp_classification.py b/GPy/models/gp_classification.py index 702d2105..8a68e74d 100644 --- a/GPy/models/gp_classification.py +++ b/GPy/models/gp_classification.py @@ -16,18 +16,27 @@ class GPClassification(GP): :param X: input observations :param Y: observed values, can be None if likelihood is not None :param kernel: a GPy kernel, defaults to rbf + :param likelihood: a GPy likelihood, defaults to Bernoulli + :param inference_method: Latent function inference to use, defaults to EP + :type inference_method: :class:`GPy.inference.latent_function_inference.LatentFunctionInference` .. Note:: Multiple independent outputs are allowed using columns of Y """ - def __init__(self, X, Y, kernel=None,Y_metadata=None, mean_function=None): + def __init__(self, X, Y, kernel=None,Y_metadata=None, mean_function=None, inference_method=None, + likelihood=None, normalizer=False): if kernel is None: kernel = kern.RBF(X.shape[1]) - likelihood = likelihoods.Bernoulli() + if likelihood is None: + likelihood = likelihoods.Bernoulli() - GP.__init__(self, X=X, Y=Y, kernel=kernel, likelihood=likelihood, inference_method=EP(), mean_function=mean_function, name='gp_classification') + if inference_method is None: + inference_method = EP() + + GP.__init__(self, X=X, Y=Y, kernel=kernel, likelihood=likelihood, inference_method=inference_method, + mean_function=mean_function, name='gp_classification', normalizer=normalizer) @staticmethod def from_gp(gp): @@ -48,3 +57,9 @@ class GPClassification(GP): def save_model(self, output_filename, compress=True, save_data=True): self._save_model(output_filename, compress=True, save_data=True) + + @staticmethod + def _build_from_input_dict(input_dict, data=None): + input_dict = GPClassification._format_input_dict(input_dict, data) + input_dict.pop('name', None) # Name parameter not required by GPClassification + return GPClassification(**input_dict) diff --git a/GPy/models/sparse_gp_classification.py b/GPy/models/sparse_gp_classification.py index 0e44966a..296b70f4 100644 --- a/GPy/models/sparse_gp_classification.py +++ b/GPy/models/sparse_gp_classification.py @@ -17,8 +17,10 @@ class SparseGPClassification(SparseGP): :param X: input observations :param Y: observed values - :param likelihood: a GPy likelihood, defaults to Binomial with probit link_function + :param likelihood: a GPy likelihood, defaults to Bernoulli :param kernel: a GPy kernel, defaults to rbf+white + :param inference_method: Latent function inference to use, defaults to EPDTC + :type inference_method: :class:`GPy.inference.latent_function_inference.LatentFunctionInference` :param normalize_X: whether to normalize the input data before computing (predictions will be in original scales) :type normalize_X: False|True :param normalize_Y: whether to normalize the input data before computing (predictions will be in original scales) @@ -27,11 +29,13 @@ class SparseGPClassification(SparseGP): """ - def __init__(self, X, Y=None, likelihood=None, kernel=None, Z=None, num_inducing=10, Y_metadata=None): + def __init__(self, X, Y=None, likelihood=None, kernel=None, Z=None, num_inducing=10, Y_metadata=None, + mean_function=None, inference_method=None, normalizer=False): if kernel is None: kernel = kern.RBF(X.shape[1]) - likelihood = likelihoods.Bernoulli() + if likelihood is None: + likelihood = likelihoods.Bernoulli() if Z is None: i = np.random.permutation(X.shape[0])[:num_inducing] @@ -39,7 +43,11 @@ class SparseGPClassification(SparseGP): else: assert Z.shape[1] == X.shape[1] - SparseGP.__init__(self, X, Y, Z, kernel, likelihood, inference_method=EPDTC(), name='SparseGPClassification',Y_metadata=Y_metadata) + if inference_method is None: + inference_method = EPDTC() + + SparseGP.__init__(self, X, Y, Z, kernel, likelihood, mean_function=mean_function, inference_method=inference_method, + normalizer=normalizer, name='SparseGPClassification', Y_metadata=Y_metadata) @staticmethod def from_sparse_gp(sparse_gp): @@ -58,6 +66,12 @@ class SparseGPClassification(SparseGP): model_dict["class"] = "GPy.models.SparseGPClassification" return model_dict + @staticmethod + def _build_from_input_dict(input_dict, data=None): + input_dict = SparseGPClassification._format_input_dict(input_dict, data) + input_dict.pop('name', None) # Name parameter not required by SparseGPClassification + return SparseGPClassification(**input_dict) + @staticmethod def from_dict(input_dict, data=None): """ diff --git a/GPy/testing/serialization_tests.py b/GPy/testing/serialization_tests.py index 57781bf3..d147d59c 100644 --- a/GPy/testing/serialization_tests.py +++ b/GPy/testing/serialization_tests.py @@ -237,7 +237,9 @@ class Test(unittest.TestCase): m.save_model("temp_test_gp_classifier_with_data.json", compress=True, save_data=True) m.save_model("temp_test_gp_classifier_without_data.json", compress=True, save_data=False) m1_r = GPy.models.GPClassification.load_model("temp_test_gp_classifier_with_data.json.zip") + self.assertTrue(type(m) == type(m1_r), "Incorrect model type. Expected: {} Actual: {}".format(type(m), type(m1_r))) m2_r = GPy.models.GPClassification.load_model("temp_test_gp_classifier_without_data.json.zip", (X,Y)) + self.assertTrue(type(m) == type(m2_r), "Incorrect model type. Expected: {} Actual: {}".format(type(m), type(m2_r))) os.remove("temp_test_gp_classifier_with_data.json.zip") os.remove("temp_test_gp_classifier_without_data.json.zip") @@ -259,7 +261,9 @@ class Test(unittest.TestCase): m.save_model("temp_test_sparse_gp_classifier_with_data.json", compress=True, save_data=True) m.save_model("temp_test_sparse_gp_classifier_without_data.json", compress=True, save_data=False) m1_r = GPy.models.SparseGPClassification.load_model("temp_test_sparse_gp_classifier_with_data.json.zip") + self.assertTrue(type(m) == type(m1_r), "Incorrect model type. Expected: {} Actual: {}".format(type(m), type(m1_r))) m2_r = GPy.models.SparseGPClassification.load_model("temp_test_sparse_gp_classifier_without_data.json.zip", (X,Y)) + self.assertTrue(type(m) == type(m2_r), "Incorrect model type. Expected: {} Actual: {}".format(type(m), type(m2_r))) os.remove("temp_test_sparse_gp_classifier_with_data.json.zip") os.remove("temp_test_sparse_gp_classifier_without_data.json.zip")