From c98b1b76e0ab0f523b5a8fc308672f1edd798d31 Mon Sep 17 00:00:00 2001 From: Zhenwen Dai Date: Mon, 13 Oct 2014 13:40:10 +0100 Subject: [PATCH] add new feature about inferene X given Y --- GPy/core/model.py | 7 ++- GPy/core/parameterization/variational.py | 9 +++- GPy/examples/dimensionality_reduction.py | 10 ++-- .../var_dtc_parallel.py | 1 + GPy/models/bayesian_gplvm.py | 5 ++ GPy/models/ss_gplvm.py | 49 +++++++++++++------ .../matplot_dep/dim_reduction_plots.py | 10 ++++ 7 files changed, 65 insertions(+), 26 deletions(-) diff --git a/GPy/core/model.py b/GPy/core/model.py index 40b0841f..9cf35eaa 100644 --- a/GPy/core/model.py +++ b/GPy/core/model.py @@ -2,8 +2,7 @@ # Licensed under the BSD 3-clause license (see LICENSE.txt) -from .. import likelihoods -from ..inference import optimization +from ..inference.optimization import get_optimizer, Optimizer from ..util.misc import opt_wrapper from parameterization import Parameterized import multiprocessing as mp @@ -240,11 +239,11 @@ class Model(Parameterized): if optimizer is None: optimizer = self.preferred_optimizer - if isinstance(optimizer, optimization.Optimizer): + if isinstance(optimizer, Optimizer): opt = optimizer opt.model = self else: - optimizer = optimization.get_optimizer(optimizer) + optimizer = get_optimizer(optimizer) opt = optimizer(start, model=self, **kwargs) opt.run(f_fp=self._objective_grads, f=self._objective, fp=self._grads) diff --git a/GPy/core/parameterization/variational.py b/GPy/core/parameterization/variational.py index 5dfa022c..9f6bce96 100644 --- a/GPy/core/parameterization/variational.py +++ b/GPy/core/parameterization/variational.py @@ -110,7 +110,10 @@ class VariationalPosterior(Parameterized): self.num_data, self.input_dim = self.mean.shape if self.has_uncertain_inputs(): assert self.variance.shape == self.mean.shape, "need one variance per sample and dimenion" - + + def set_gradients(self, grad): + self.mean.gradient, self.variance.gradient = grad + def _raveled_index(self): index = np.empty(dtype=int, shape=0) size = 0 @@ -175,6 +178,10 @@ class SpikeAndSlabPosterior(VariationalPosterior): self.gamma = Param("binary_prob",binary_prob, Logistic(1e-10,1.-1e-10)) self.link_parameter(self.gamma) + + def set_gradients(self, grad): + self.mean.gradient, self.variance.gradient, self.gamma.gradient = grad + def __getitem__(self, s): if isinstance(s, (int, slice, tuple, list, np.ndarray)): import copy diff --git a/GPy/examples/dimensionality_reduction.py b/GPy/examples/dimensionality_reduction.py index 516a5be3..86c48ec4 100644 --- a/GPy/examples/dimensionality_reduction.py +++ b/GPy/examples/dimensionality_reduction.py @@ -189,7 +189,7 @@ def bgplvm_oil_100(optimize=True, verbose=1, plot=True, N=200, Q=7, num_inducing from ..util.misc import param_to_array _np.random.seed(0) - data = GPy.util.datasets.oil_100() + data = GPy.util.datasets.oil() kernel = GPy.kern.RBF(Q, 1., 1./_np.random.uniform(0,1,(Q,)), ARD=True)# + GPy.kern.Bias(Q, _np.exp(-2)) Y = data['X'][:N] @@ -209,18 +209,18 @@ def bgplvm_oil_100(optimize=True, verbose=1, plot=True, N=200, Q=7, num_inducing plt.close(fig) return m -def ssgplvm_oil(optimize=True, verbose=1, plot=True, N=200, Q=7, num_inducing=40, max_iters=1000, **k): +def ssgplvm_oil(optimize=True, verbose=1, plot=True, N=200, Q=7, num_inducing=40, max_iters=1000, useGPU=False, **k): import GPy from matplotlib import pyplot as plt from ..util.misc import param_to_array import numpy as np #_np.random.seed(0) - data = GPy.util.datasets.oil_100() + data = GPy.util.datasets.oil() - kernel = GPy.kern.RBF(Q, 1., 1./_np.random.uniform(0,1,(Q,)), ARD=True)# + GPy.kern.Bias(Q, _np.exp(-2)) + kernel = GPy.kern.RBF(Q, 1., 1./_np.random.uniform(0,1,(Q,)), ARD=True, useGPU=useGPU)# + GPy.kern.Bias(Q, _np.exp(-2)) Y = data['X'][:N] - m = GPy.models.SSGPLVM(Y, Q, kernel=kernel, num_inducing=num_inducing, group_spike=True, **k) + m = GPy.models.SSGPLVM(Y, Q, kernel=kernel, num_inducing=num_inducing, group_spike=True, learnPi=False, **k) m.data_labels = data['Y'][:N].argmax(axis=1) if optimize: diff --git a/GPy/inference/latent_function_inference/var_dtc_parallel.py b/GPy/inference/latent_function_inference/var_dtc_parallel.py index b9ecbb5c..c77401b9 100644 --- a/GPy/inference/latent_function_inference/var_dtc_parallel.py +++ b/GPy/inference/latent_function_inference/var_dtc_parallel.py @@ -406,3 +406,4 @@ def update_gradients(model, mpi_comm=None): # dL_dthetaL model.likelihood.update_gradients(dL_dthetaL) + diff --git a/GPy/models/bayesian_gplvm.py b/GPy/models/bayesian_gplvm.py index a4227119..dedd5319 100644 --- a/GPy/models/bayesian_gplvm.py +++ b/GPy/models/bayesian_gplvm.py @@ -89,6 +89,7 @@ class BayesianGPLVM(SparseGP): print 'MPI RANK: '+str(self.mpi_comm.rank)+' with datasize: '+str(self.N_range) mpi_comm.Bcast(self.param_array, root=0) + def set_X_gradients(self, X, X_grad): """Set the gradients of the posterior distribution of X in its specific form.""" X.mean.gradient, X.variance.gradient = X_grad @@ -256,6 +257,10 @@ class BayesianGPLVM(SparseGP): raise Exception("Unrecognizable flag for synchronization!") self.__IN_OPTIMIZATION__ = False + def inference_X(self, Y_new): + from ..inference.latent_function_inference.inference_X import inference_newX + return inference_newX(self, Y_new) + def latent_cost_and_grad(mu_S, input_dim, kern, Z, dL_dpsi0, dL_dpsi1, dL_dpsi2): """ diff --git a/GPy/models/ss_gplvm.py b/GPy/models/ss_gplvm.py index 88049d28..3e487146 100644 --- a/GPy/models/ss_gplvm.py +++ b/GPy/models/ss_gplvm.py @@ -35,20 +35,11 @@ class SSGPLVM(SparseGP_MPI): fracs = np.ones(input_dim) self.init = init - - if X_variance is None: # The variance of the variational approximation (S) - X_variance = np.random.uniform(0,.1,X.shape) - - if Gamma is None: - gamma = np.empty_like(X) # The posterior probabilities of the binary variable in the variational approximation - gamma[:] = 0.5 + 0.1 * np.random.randn(X.shape[0], input_dim) - gamma[gamma>1.-1e-9] = 1.-1e-9 - gamma[gamma<1e-9] = 1e-9 - else: - gamma = Gamma.copy() + + X = self._init_X(input_dim, Y, X, X_variance, Gamma, init) if Z is None: - Z = np.random.permutation(X.copy())[:num_inducing] + Z = np.random.permutation(X.mean.copy())[:num_inducing] assert Z.shape[1] == X.shape[1] if likelihood is None: @@ -67,14 +58,33 @@ class SSGPLVM(SparseGP_MPI): pi[:] = 0.5 self.variational_prior = SpikeAndSlabPrior(pi=pi,learnPi=learnPi, group_spike=group_spike) # the prior probability of the latent binary variable b - X = SpikeAndSlabPosterior(X, X_variance, gamma) - super(SSGPLVM,self).__init__(X, Y, Z, kernel, likelihood, variational_prior=self.variational_prior, inference_method=inference_method, name=name, mpi_comm=mpi_comm, normalizer=normalizer, **kwargs) # self.X.unfix() # self.X.variance.constrain_positive() if self.group_spike: [self.X.gamma[:,i].tie_together() for i in xrange(self.X.gamma.shape[1])] # Tie columns together + + def _init_X(self, input_dim, Y=None, X=None, X_variance=None, Gamma=None, init='PCA'): + if X == None: + from ..util.initialization import initialize_latent + X, fracs = initialize_latent(init, input_dim, Y) + else: + fracs = np.ones(input_dim) + + if X_variance is None: # The variance of the variational approximation (S) + X_variance = np.random.uniform(0,.1,X.shape) + + if Gamma is None: + gamma = np.empty_like(X) # The posterior probabilities of the binary variable in the variational approximation + gamma[:] = 0.5 + 0.1 * np.random.randn(X.shape[0], input_dim) + gamma[gamma>1.-1e-9] = 1.-1e-9 + gamma[gamma<1e-9] = 1e-9 + else: + gamma = Gamma.copy() + + return SpikeAndSlabPosterior(X, X_variance, gamma) + def set_X_gradients(self, X, X_grad): """Set the gradients of the posterior distribution of X in its specific form.""" @@ -102,10 +112,17 @@ class SSGPLVM(SparseGP_MPI): else: return self.variational_prior.pi - def plot_latent(self, plot_inducing=True, *args, **kwargs): + def plot_latent(self, plot_inducing=True, interactive=False, *args, **kwargs): import sys assert "matplotlib" in sys.modules, "matplotlib package has not been imported." from ..plotting.matplot_dep import dim_reduction_plots - return dim_reduction_plots.plot_latent(self, plot_inducing=plot_inducing, *args, **kwargs) + if interactive: + return dim_reduction_plots.plot_latent_interactive(self, **kwargs) + else: + return dim_reduction_plots.plot_latent(self, plot_inducing=plot_inducing, *args, **kwargs) + + def inference_X(self, Y_new): + from ..inference.latent_function_inference.inference_X import inference_newX + return inference_newX(self, Y_new) diff --git a/GPy/plotting/matplot_dep/dim_reduction_plots.py b/GPy/plotting/matplot_dep/dim_reduction_plots.py index 20e8e962..d0251a35 100644 --- a/GPy/plotting/matplot_dep/dim_reduction_plots.py +++ b/GPy/plotting/matplot_dep/dim_reduction_plots.py @@ -12,6 +12,16 @@ try: except: pass +def plot_latent_interactive(model, labels=None, **kwargs): + fig, (latent_axes, sense_axes) = pb.subplots(1, 2) + model.plot_latent(ax=latent_axes, labels=labels, **kwargs) + from .visualize import vector_show,lvm_dimselect + data_show = vector_show((model.Y[0,:])) + lvm_visualizer = lvm_dimselect(param_to_array(model.X.mean)[0:1,:], # @UnusedVariable + model, data_show, latent_axes=latent_axes, sense_axes=sense_axes, labels=labels) + raw_input('Press enter to finish') + pb.close(fig) + def most_significant_input_dimensions(model, which_indices): """ Determine which dimensions should be plotted