def __init__(self, X, Y, W, kern, feat=None, mean_function=None, Z=None, **kwargs): """ X is a data matrix, size N x D Y is a data matrix, size N x R Z is a matrix of pseudo inputs, size M x D kern, mean_function are appropriate GPflow objects This method only works with a Gaussian likelihood. """ X = DataHolder(X) Y = DataHolder(Y) likelihood = likelihoods.Gaussian() GPModel.__init__(self, X, Y, kern, likelihood, mean_function, **kwargs) self.feature = features.inducingpoint_wrapper(feat, Z) self.num_data = X.shape[0] self.W_prior = tf.ones(W.shape, dtype=settings.float_type) / W.shape[1] self.W = Parameter(W) self.num_inducing = Z.shape[0] * W.shape[1]
def __init__(self, X, Y, kern, mu_old, Su_old, Kaa_old, Z_old, Z, mean_function=Zero()): """ X is a data matrix, size N x D Y is a data matrix, size N x R Z is a matrix of pseudo inputs, size M x D kern, mean_function are appropriate gpflow objects mu_old, Su_old are mean and covariance of old q(u) Z_old is the old inducing inputs This method only works with a Gaussian likelihood. """ X = DataHolder(X, on_shape_change='pass') Y = DataHolder(Y, on_shape_change='pass') likelihood = likelihoods.Gaussian() GPModel.__init__(self, X, Y, kern, likelihood, mean_function) self.Z = Param(Z) self.num_data = X.shape[0] self.num_latent = Y.shape[1] self.mu_old = DataHolder(mu_old, on_shape_change='pass') self.M_old = Z_old.shape[0] self.Su_old = DataHolder(Su_old, on_shape_change='pass') self.Kaa_old = DataHolder(Kaa_old, on_shape_change='pass') self.Z_old = DataHolder(Z_old, on_shape_change='pass')
def __init__(self, X, Y, kern, mean_function=None, **kwargs): """ X is a data matrix, size N x D Y is a data matrix, size N x R kern, mean_function are appropriate GPflow objects """ likelihood = likelihoods.Gaussian() X = DataHolder(X) Y = DataHolder(Y) GPModel.__init__(self, X, Y, kern, likelihood, mean_function, **kwargs)
def __init__(self, x, y, kern, mean_function=None, **kwargs): """ X is a data matrix, size N x D Y is a data matrix, size N x R kern, mean_function are appropriate GPflow objects """ likelihood = likelihoods.Gaussian() x = [DataHolder(x_i) for x_i in x] y = DataHolder(y) print(x) print(y) print(kern) super().__init__(x, y, kern, likelihood, mean_function, **kwargs)
def __init__( self, encoder, kernel: Optional[Kernel] = None, inducing_variable=None, *, num_latent_gps: int = 1, #Y.shape[-1] data_dim: tuple = None, mean_function=None, q_diag: bool = False, q_mu=None, q_sqrt=None, whiten: bool = False, ): """ - kernel, likelihood, inducing_variables, mean_function are appropriate GPflow objects - num_latent_gps is the number of latent processes to use, defaults to 2, as the dimensionality reduction is at dimensions 2 - q_diag is a boolean. If True, the covariance is approximated by a diagonal matrix. - whiten is a boolean. If True, we use the whitened representation of the inducing points. - num_data is the total number of observations, defaults to X.shape[0] (relevant when feeding in external minibatches) The prior is by default a Normal Gaussian """ if kernel is None: kernel = gpflow.kernels.SquaredExponential() self.num_data = data_dim[0] self.num_latent_gps = data_dim[1] self.q_diag = q_diag self.whiten = whiten self.inducing_variable = inducingpoint_wrapper(inducing_variable) # init variational parameters num_inducing = self.inducing_variable.num_inducing self._init_variational_parameters(num_inducing, q_mu, q_sqrt, q_diag) self.loss_placeholder = defaultdict( list, {k: [] for k in ("KL_x", "ELBO", "KL_u")}) self.encoder = encoder # init the super class, accept args super().__init__(kernel, likelihoods.Gaussian(variance=0.1), mean_function, num_latent_gps)
def __init__(self, X, Y, kern, mean_function=None, minibatch_size=None, seed=0, **kwargs): likelihood = likelihoods.Gaussian() self._seed = seed self._minibatch_size = minibatch_size self._N = X.shape[0] if len(X.shape) >= 3: X = X.reshape((-1, np.prod(np.array(list(X.shape)[1:])))) if minibatch_size is None: X = DataHolder(X) Y = DataHolder(Y) self._iters_per_epoch = 1 else: X = Minibatch(X, batch_size=self._N, shuffle=True, seed=seed) Y = Minibatch(Y, batch_size=self._N, shuffle=True, seed=seed) self._iters_per_epoch = self._N//minibatch_size + min(1, self._N%minibatch_size) GPModel.__init__(self, X, Y, kern, likelihood, mean_function, **kwargs)
def __init__(self, X, Y, W1, W1_index, W2, W2_index, kern, feat=None, mean_function=None, Z=None, **kwargs): """ X is a data matrix, size N x D Y is a data matrix, size N x R Z is a matrix of pseudo inputs, size M x D W1, size NxK W1_index PxL W2, size NxL W2_index PxL kern, mean_function are appropriate GPflow objects This method only works with a Gaussian likelihood. """ X = DataHolder(X) Y = DataHolder(Y, fix_shape=True) likelihood = likelihoods.Gaussian() GPModel.__init__(self, X, Y, kern, likelihood, mean_function, **kwargs) self.feature = features.inducingpoint_wrapper(feat, Z) self.num_data = X.shape[0] self.W1_prior = Parameter(np.log( np.ones(W1.shape[1], dtype=settings.float_type) / W1.shape[1]), trainable=False) self.W1 = Parameter(W1) self.W1_index = DataHolder(W1_index, dtype=np.int32, fix_shape=True) self.K = W1.shape[1] self.W2_prior = Parameter(np.log( np.ones(W2.shape[1], dtype=settings.float_type) / W2.shape[1]), trainable=False) self.W2 = Parameter(W2) self.W2_index = DataHolder(W2_index, dtype=np.int32, fix_shape=True) self.L = W2.shape[1] self.num_inducing = Z.shape[0]
def __init__(self, X, Y, kern, Z, alpha, mean_function=Zero()): """ X is a data matrix, size N x D Y is a data matrix, size N x R Z is a matrix of pseudo inputs, size M x D kern, mean_function are appropriate gpflow objects This method only works with a Gaussian likelihood. """ X = DataHolder(X, on_shape_change='pass') Y = DataHolder(Y, on_shape_change='pass') likelihood = likelihoods.Gaussian() GPModel.__init__(self, X, Y, kern, likelihood, mean_function) self.Z = Param(Z) self.num_data = X.shape[0] self.num_latent = Y.shape[1] self.alpha = alpha
def __init__(self, X, Y, W, kern, idx=None, feat=None, Z=None, mean_function=None, q_diag=False, whiten=False, q_mu=None, q_sqrt=None, minibatch_size=None, num_latent=None, **kwargs): """ X is a data matrix, size N x D Y is a data matrix, size N x R Z is a matrix of pseudo inputs, size M x D kern, mean_function are appropriate GPflow objects This method only works with a Gaussian likelihood. """ num_data = X.shape[0] if minibatch_size is None: X = DataHolder(X, fix_shape=True) Y = DataHolder(Y, fix_shape=True) else: X = Minibatch(X, batch_size=minibatch_size, seed=0) Y = Minibatch(Y, batch_size=minibatch_size, seed=0) # init the super class likelihood = likelihoods.Gaussian() num_latent = W.shape[1] GPModel.__init__(self, X, Y, kern, likelihood, mean_function, num_latent=num_latent, **kwargs) if minibatch_size is not None: idx = Minibatch(np.arange(num_data), batch_size=minibatch_size, seed=0, dtype=np.int32) self.idx = idx self.W = Parameter(W, trainable=False) self.K = self.W.shape[1] self.W_prior = Parameter(np.ones(self.K) / self.K, trainable=False) self.num_data = num_data self.feature = features.inducingpoint_wrapper(feat, Z) self.minibatch_size = minibatch_size self.q_diag, self.whiten = q_diag, whiten # init variational parameters num_inducing = len(self.feature) self._init_variational_parameters( num_inducing, q_mu, q_sqrt, q_diag)
def __init__(self, embeds, m, name='Model'): Model.__init__(self, name) self.nkpts = len(m.Y.value[0]) self.npts = len(embeds) embeds = np.array(m.X_mean.value) self.X_mean = Param(embeds) self.Z = Param(np.array(m.Z.value)) self.kern = deepcopy(m.kern) self.X_var = Param(np.array(m.X_var.value)) self.Y = m.Y self.likelihood = likelihoods.Gaussian() self.mean_function = Zero() self.likelihood._check_targets(self.Y.value) self._session = None self.X_mean.fixed = True self.Z.fixed = True self.kern.fixed = True self.X_var.fixed = True self.likelihood.fixed = True
def __init__(self, X_variational_mean, X_variational_var, Y, kern, t, kern_t, M , Z=None): """ Initialization of Bayesian Gaussian Process Dynamics Model. This method only works with Gaussian likelihood. :param X_variational_mean: initial latent positions, size N (number of points) x Q (latent dimensions). :param X_variational_var: variance of latent positions (N x Q), for the initialisation of the latent space. :param Y: data matrix, size N (number of points) x D (dimensions). :param kern: kernel specification, by default RBF. :param t: time stamps. :param kern_t: dynamics kernel specification, by default RBF. :param M: number of inducing points. :param Z: matrix of inducing points, size M (inducing points) x Q (latent dimensions), By default random permutation of X_mean. """ super(BayesianDGPLVM, self).__init__(name='BayesianDGPLVM') self.kern = kern assert len(X_variational_mean) == len(X_variational_var), 'must be same amount of time series' self.likelihood = likelihoods.Gaussian() # multiple sequences series = [] for i in range(len(X_variational_mean)): series.append(GPTimeSeries(X_variational_mean[i], X_variational_var[i], t[i])) self.series = ParamList(series) # inducing points if Z is None: # By default we initialize by permutation of initial Z = np.random.permutation(np.concatenate(X_variational_mean, axis=0).copy())[:M] else: assert Z.shape[0] == M self.Z = Param(Z) self.kern_t = kern_t self.Y = DataHolder(Y) self.M = M self.n_s = 0
def __init__(self, embeds, skeletons, dist, m, name='Model'): Model.__init__(self, name) self.skeletons = skeletons self.dist_embeds = dist self.nkpts = len(skeletons[0, :]) self.npts = len(embeds) self.dist_skeletons = np.ones([self.npts, self.npts]) * -1 embeds = np.array(m.X_mean.value) self.X_mean = Param(embeds) self.Z = Param(np.array(m.Z.value)) self.kern = deepcopy(m.kern) self.X_var = Param(np.array(m.X_var.value)) self.Y = m.Y self.likelihood = likelihoods.Gaussian() self.mean_function = Zero() self.likelihood._check_targets(self.Y.value) self._session = None self.X_mean.fixed = True self.Z.fixed = True self.kern.fixed = True self.X_var.fixed = True self.likelihood.fixed = True
def __init__(self, Y, T, kern, M=10, num_latent=3, dynamic_kern=None, Z=None, KL_weight=None): """ Initialise VGPDS. This only works with Gaussian Likelihood for now :param Y: data matrix, size T (number of time points) x D (dimensions) :param T: time vector, positive real value, size 1 x T :param kern: Mapping kernel X -> Y specification, by default RBF :param M: Number of inducing points :param num_latent: Number of latent dimension. This is automatically found unless user force latent dimension :param force_latent_dim: Specify whether strict latent dimension is enforced :param dynamic_kern: temporal dynamics kernel specification, by default RBF :param Z: matrix of inducing points :param KL_weight: Weight of KL . weight of bound = 1 - w(KL) """ X_mean = large_PCA(Y, num_latent) GPModel.__init__(self, X_mean, Y, kern, likelihood=likelihoods.Gaussian(), mean_function=Zero()) del self.X # This is a params self.T = np.transpose(T[np.newaxis]) self.num_latent = num_latent if KL_weight is None: self.KL_weight = 0.5 else: assert KL_weight <= 1 assert KL_weight >= 0 self.KL_weight = KL_weight #This is only one way to initialize mu_bar_q mu_bar_q = X_mean lambda_q = np.ones((self.T.shape[0], self.num_latent)) if dynamic_kern is None: self.dynamic_kern = kernels.RBF(1) + kernels.Bias( 1) + kernels.White(1) else: self.dynamic_kern = dynamic_kern self.mu_bar_q = Parameter(mu_bar_q) self.lambda_q = Parameter(lambda_q) self.num_time, self.num_latent = X_mean.shape self.output_dim = Y.shape[1] # inducing points if Z is None: # By default we initialize by subset of initial latent points Z = np.random.permutation(X_mean.copy())[:M] self.feature = features.InducingPoints(Z) assert len(self.feature) == M
def __init__(self, X, Y, kern, mean_function=None, i=None, **kwargs): likelihood = likelihoods.Gaussian() X = DataHolder(X) Y = DataHolder(Y) GPModel.__init__(self, X, Y, kern, likelihood, mean_function, **kwargs) self.i = i
def __init__( self, data: OutputData, encoder, kernel: Optional[Kernel] = None, inducing_variable=None, X_prior_mean=None, X_prior_var=None, ): """ Initialise Bayesian GPLVM object. This method only works with a Gaussian likelihood. :param data: data matrix, size N (number of points) x D (dimensions) :param X_data_mean: initial latent positions, size N (number of points) x Q (latent dimensions). :param X_data_var: variance of latent positions ([N, Q]), for the initialisation of the latent space. :param kernel: kernel specification, by default Squared Exponential :param num_inducing_variables: number of inducing points, M :param inducing_variable: matrix of inducing points, size M (inducing points) x Q (latent dimensions). By default random permutation of X_data_mean. :param X_prior_mean: prior mean used in KL term of bound. By default 0. Same size as X_data_mean. :param X_prior_var: prior variance used in KL term of bound. By default 1. """ self.latent_dimensions = 2 #grab data self.data = data_input_to_tensor(data) num_data, num_latent_gps = data.shape self.num_data = num_data #def kernel if kernel is None: kernel = gpflow.kernels.SquaredExponential() #init GPMODEL super().__init__(kernel, likelihoods.Gaussian(variance=0.1), num_latent_gps=num_latent_gps) #init parameter inducing point if (inducing_variable is None): raise ValueError( "BayesianGPLVM needs exactly one of `inducing_variable` and `num_inducing_variables`" ) else: self.inducing_variable = inducingpoint_wrapper(inducing_variable) #loss placeholder for analysis purpuse self.loss_placeholder = defaultdict(list, {k: [] for k in ("KL_x", "ELBO")}) # deal with parameters for the prior mean variance of X if X_prior_mean is None: X_prior_mean = tf.zeros((self.num_data, self.latent_dimensions), dtype=default_float()) if X_prior_var is None: X_prior_var = tf.ones((self.num_data, self.latent_dimensions), dtype=default_float()) self.X_prior_mean = tf.convert_to_tensor(np.atleast_1d(X_prior_mean), dtype=default_float()) self.X_prior_var = tf.convert_to_tensor(np.atleast_1d(X_prior_var), dtype=default_float()) # Encoder self.encoder = encoder #sanity check # assert np.all(X_data_mean.shape == X_data_var.shape) # assert X_data_mean.shape[0] == self.data.shape[0], "X mean and Y must be same size." # assert X_data_var.shape[0] == self.data.shape[0], "X var and Y must be same size." # assert X_data_mean.shape[1] == self.latent_dimensions assert self.X_prior_mean.shape[0] == self.num_data assert self.X_prior_mean.shape[1] == self.latent_dimensions assert self.X_prior_var.shape[0] == self.num_data assert self.X_prior_var.shape[1] == self.latent_dimensions
def __init__( self, data: OutputData, kernel: Optional[Kernel] = None, latent_dimensions: Optional[int] = 2, num_inducing_variables: Optional[int] = None, inducing_variable=None, *, mean_function=None, q_diag: bool = False, q_mu=None, q_sqrt=None, whiten: bool = False, ): """ - kernel, likelihood, inducing_variables, mean_function are appropriate GPflow objects - num_latent_gps is the number of latent processes to use, defaults to 2, as the dimensionality reduction is at dimensions 2 - q_diag is a boolean. If True, the covariance is approximated by a diagonal matrix. - whiten is a boolean. If True, we use the whitened representation of the inducing points. - num_data is the total number of observations, defaults to X.shape[0] (relevant when feeding in external minibatches) """ self.latent_dimensions = latent_dimensions #grab data self.data = data_input_to_tensor(data) #define lat-space initialization X_data_mean = pca_reduce(data, self.latent_dimensions) num_data, num_latent_gps = data.shape self.num_data = num_data X_data_var = tf.ones((self.num_data, self.latent_dimensions), dtype=default_float()) assert X_data_var.ndim == 2 #def kernel if kernel is None: kernel = gpflow.kernels.SquaredExponential() #init Parameters latent self.X_data_mean = Parameter(X_data_mean) self.X_data_var = Parameter(X_data_var, transform=positive()) #init parameter inducing point if (inducing_variable is None) == (num_inducing_variables is None): raise ValueError( "BayesianGPLVM needs exactly one of `inducing_variable` and `num_inducing_variables`" ) if inducing_variable is None: # By default we initialize by subset of initial latent points # Note that tf.random.shuffle returns a copy, it does not shuffle in-place #maybe use k-means clustering Z = tf.random.shuffle(X_data_mean)[:num_inducing_variables] inducing_variable = InducingPoints(Z) self.inducing_variable = inducingpoint_wrapper(inducing_variable) #loss placeholder for analysis purpuse self.loss_placeholder = defaultdict( list, {k: [] for k in ("KL_x", "ELBO", "KL_u")}) # deal with parameters for the prior mean variance of X X_prior_mean = tf.zeros((self.num_data, self.latent_dimensions), dtype=default_float()) X_prior_var = tf.ones((self.num_data, self.latent_dimensions), dtype=default_float()) self.X_prior_mean = tf.convert_to_tensor(np.atleast_1d(X_prior_mean), dtype=default_float()) self.X_prior_var = tf.convert_to_tensor(np.atleast_1d(X_prior_var), dtype=default_float()) #sanity check assert np.all(X_data_mean.shape == X_data_var.shape) assert X_data_mean.shape[0] == self.data.shape[ 0], "X mean and Y must be same size." assert X_data_var.shape[0] == self.data.shape[ 0], "X var and Y must be same size." assert X_data_mean.shape[1] == self.latent_dimensions assert self.X_prior_mean.shape[0] == self.num_data assert self.X_prior_mean.shape[1] == self.latent_dimensions assert self.X_prior_var.shape[0] == self.num_data assert self.X_prior_var.shape[1] == self.latent_dimensions # init the super class, accept args super().__init__(kernel, likelihoods.Gaussian(variance=0.1), mean_function, num_latent_gps) self.q_diag = q_diag self.whiten = whiten #self.inducing_variable = inducingpoint_wrapper(inducing_variable) # init variational parameters num_inducing = self.inducing_variable.num_inducing self._init_variational_parameters(num_inducing, q_mu, q_sqrt, q_diag)
def __init__(self, X_variational_mean, X_variational_var, Y, Kern, M, Z=None, X_prior_mean=None, X_prior_var=None): """ Initialise Bayesian GPLVM object. This method only works with a Gaussian likelihood. :param X_variational_mean: initial latent variational distribution mean, size N (number of points) x Q (latent dimensions) :param X_variational_var: initial latent variational distribution std (N X Q) :param Y: data matrix, size N (number of points) x D (dimensions) :param Kern: kernal specification, by default RBF-ARD :param M: number of inducing points :param Z: matrix of inducing points, size M (inducing points) x Q (latent dimensions). By default random permutation of X_mean. :param X_prior_mean: prior mean used in KL term of bound. By default 0. Same size as X_mean. :param X_prior_var: prior variance used in KL term of bound. By default 1. """ GPModel.__init__(self, X_variational_mean, Y, Kern, likelihood=likelihoods.Gaussian(), mean_function=Zero()) del self.X # in GPLVM this is a Param self.X_variational_mean = Param(X_variational_mean) assert X_variational_var.ndim == 2, 'Incorrect number of dimensions for X_std.' self.X_variational_var = Param(X_variational_var, transforms.positive) self.num_data = X_variational_mean.shape[0] self.output_dim = Y.shape[1] assert np.all((X_variational_mean.shape == X_variational_var.shape)) assert X_variational_mean.shape[0] == Y.shape[ 0], 'X variational mean and Y must be the same size.' assert X_variational_var.shape[0] == Y.shape[ 0], 'X variational std and Y must be the same size.' # inducing points if Z is None: # By default it's initialized by random permutation of the latent inputs. Z = np.random.permutation(X_variational_mean.copy())[:M] else: assert Z.shape[ 0] == M, 'Only M inducing points are allowed, however {} are provided.'.format( Z.shape[0]) self.Z = Param(Z) self.num_latent = Z.shape[1] assert X_variational_mean.shape[1] == self.num_latent # Prior mean and variance for X TODO: the dynamic case is different if X_prior_mean is None: X_prior_mean = np.zeros((self.num_data, self.num_latent)) self.X_prior_mean = X_prior_mean if X_prior_var is None: X_prior_var = np.ones((self.num_data, self.num_latent)) self.X_prior_var = X_prior_var assert X_prior_var.shape[0] == self.num_data assert X_prior_var.shape[1] == self.num_latent assert X_prior_mean.shape[0] == self.num_data assert X_prior_mean.shape[1] == self.num_latent
def __init__( self, data: OutputData, split_space: bool, Xp_mean: tf.Tensor, Xp_var: tf.Tensor, pi: tf.Tensor, kernel_K: List[Kernel], Zp: tf.Tensor, Xs_mean=None, Xs_var=None, kernel_s=None, Zs=None, Xs_prior_mean=None, Xs_prior_var=None, Xp_prior_mean=None, Xp_prior_var=None, pi_prior=None ): """ Initialise Bayesian GPLVM object. This method only works with a Gaussian likelihood. :param data: data matrix, size N (number of points) x D (dimensions) :param: split_space, if true, have both shared and private space; if false, only have private spaces (note: to recover GPLVM, set split_space=False and let K=1) :param Xp_mean: mean latent positions in the private space [N, Qp] (Qp is the dimension of the private space) :param Xp_var: variance of the latent positions in the private space [N, Qp] :param pi: mixture responsibility of each category to each point [N, K] (K is the number of categories), i.e. q(c) :param kernel_K: private space kernel, one for each category :param Zp: inducing inputs of the private space [M, Qp] :param num_inducing_variables: number of inducing points, M :param Xs_mean: mean latent positions in the shared space [N, Qs] (Qs is the dimension of the shared space). i.e. mus in q(Xs) ~ N(Xs | mus, Ss) :param Xs_var: variance of latent positions in shared space [N, Qs], i.e. Ss, assumed diagonal :param kernel_s: shared space kernel :param Zs: inducing inputs of the shared space [M, Qs] (M is the number of inducing points) :param Xs_prior_mean: prior mean used in KL term of bound, [N, Qs]. By default 0. mean in p(Xs) :param Xs_prior_var: prior variance used in KL term of bound, [N, Qs]. By default 1. variance in p(Xs) :param Xp_prior_mean: prior mean used in KL term of bound, [N, Qp]. By default 0. mean in p(Xp) :param Xp_prior_var: prior variance used in KL term of bound, [N, Qp]. By default 1. variance in p(Xp) :param pi_prior: prior mixture weights used in KL term of the bound, [N, K]. By default uniform. p(c) """ # if don't want shared space, set shared space to none --> get a mixture of GPLVM # if don't want private space, set shared space to none, set K = 1 and only include 1 kernel in `kernel_K` --> recover the original GPLVM # TODO: think about how to do this with minibatch # it's awkward since w/ minibatch the model usually doesn't store the data internally # but for gplvm, you need to keep the q(xn) for all the n's # so you need to know which ones to update for each minibatch, probably can be solved but not pretty # using inference network / back constraints will solve this, since we will be keeping a global set of parameters # rather than a set for each q(xn) self.N, self.D = data.shape self.Qp = Xp_mean.shape[1] self.K = pi.shape[1] self.split_space = split_space assert Xp_var.ndim == 2 assert len(kernel_K) == self.K assert np.all(Xp_mean.shape == Xp_var.shape) assert Xp_mean.shape[0] == self.N, "Xp_mean and Y must be of same size" assert pi.shape[0] == self.N, "pi and Y must be of the same size" super().__init__() self.likelihood = likelihoods.Gaussian() self.kernel_K = kernel_K self.data = data_input_to_tensor(data) # the covariance of q(X) as a [N, Q] matrix, the assumption is that Sn's are diagonal # i.e. the latent dimensions are uncorrelated # otherwise would require a [N, Q, Q] matrix self.Xp_mean = Parameter(Xp_mean) self.Xp_var = Parameter(Xp_var, transform=positive()) self.pi = Parameter(pi, transform=tfp.bijectors.SoftmaxCentered()) self.Zp = inducingpoint_wrapper(Zp) self.M = len(self.Zp) # initialize the variational parameters for q(U), same way as in SVGP # q_mu: List[K], mean of the inducing variables U [M, D], i.e m in q(U) ~ N(U | m, S), # initialized as zeros # q_sqrt: List[K], cholesky of the covariance matrix of the inducing variables [D, M, M] # q_diag is false because natural gradient only works for full covariance # initialized as all identities # we need K sets of q(Uk), each approximating fs+fk self.q_mu = [] self.q_sqrt = [] for k in range(self.K): q_mu = np.zeros((self.M, self.D)) q_mu = Parameter(q_mu, dtype=default_float()) # [M, D] self.q_mu.append(q_mu) q_sqrt = [ np.eye(self.M, dtype=default_float()) for _ in range(self.D) ] q_sqrt = np.array(q_sqrt) q_sqrt = Parameter(q_sqrt, transform=triangular()) # [D, M, M] self.q_sqrt.append(q_sqrt) # deal with parameters for the prior if Xp_prior_mean is None: Xp_prior_mean = tf.zeros((self.N, self.Qp), dtype=default_float()) if Xp_prior_var is None: Xp_prior_var = tf.ones((self.N, self.Qp)) if pi_prior is None: pi_prior = tf.ones((self.N, self.K), dtype=default_float()) * 1/self.K self.Xp_prior_mean = tf.convert_to_tensor(np.atleast_1d(Xp_prior_mean), dtype=default_float()) self.Xp_prior_var = tf.convert_to_tensor(np.atleast_1d(Xp_prior_var), dtype=default_float()) self.pi_prior = tf.convert_to_tensor(np.atleast_1d(pi_prior), dtype=default_float()) # if we have both shared space and private space, need to initialize the parameters for the shared space if split_space: assert Xs_mean is not None and Xs_var is not None and kernel_s is not None and Zs is not None, 'Xs_mean, Xs_var, kernel_s, Zs need to be initialize if `split_space=True`' assert Xs_var.ndim == 2 assert np.all(Xs_mean.shape == Xs_var.shape) assert Xs_mean.shape[0] == self.N, "Xs_mean and Y must be of same size" self.Qs = Xs_mean.shape[1] self.kernel_s = kernel_s self.Xs_mean = Parameter(Xs_mean) self.Xs_var = Parameter(Xs_var, transform=positive()) self.Zs = inducingpoint_wrapper(Zs) if len(Zs) != len(Zp): raise ValueError( '`Zs` and `Zp` should have the same length' ) if Xs_prior_mean is None: Xs_prior_mean = tf.zeros((self.N, self.Qs), dtype=default_float()) if Xs_prior_var is None: Xs_prior_var = tf.ones((self.N, self.Qs)) self.Xs_prior_mean = tf.convert_to_tensor(np.atleast_1d(Xs_prior_mean), dtype=default_float()) self.Xs_prior_var = tf.convert_to_tensor(np.atleast_1d(Xs_prior_var), dtype=default_float()) self.Fq = tf.zeros((self.N, self.K), dtype=default_float())
def __init__( self, data: OutputData, X_data_mean: Optional[tf.Tensor] = None, X_data_var: Optional[tf.Tensor] = None, kernel: Optional[Kernel] = None, num_inducing_variables: Optional[int] = None, inducing_variable=None, X_prior_mean=None, X_prior_var=None, ): """ Initialise Bayesian GPLVM object. This method only works with a Gaussian likelihood. :param data: data matrix, size N (number of points) x D (dimensions) :param X_data_mean: initial latent positions, size N (number of points) x Q (latent dimensions). :param X_data_var: variance of latent positions ([N, Q]), for the initialisation of the latent space. :param kernel: kernel specification, by default Squared Exponential :param num_inducing_variables: number of inducing points, M :param inducing_variable: matrix of inducing points, size M (inducing points) x Q (latent dimensions). By default random permutation of X_data_mean. :param X_prior_mean: prior mean used in KL term of bound. By default 0. Same size as X_data_mean. :param X_prior_var: prior variance used in KL term of bound. By default 1. """ self.latent_dimensions = 2 #grab data self.data = data_input_to_tensor(data) #define lat-space initialization if X_data_mean is None: X_data_mean = pca_reduce(data, self.latent_dimensions) num_data, num_latent_gps = X_data_mean.shape self.num_data = num_data if X_data_var is None: X_data_var = tf.ones((self.num_data, self.latent_dimensions), dtype=default_float()) assert X_data_var.ndim == 2 self.output_dim = self.data.shape[-1] #num_latent maybe #def kernel if kernel is None: kernel = gpflow.kernels.SquaredExponential() #init GPMODEL super().__init__(kernel, likelihoods.Gaussian(variance=0.1), num_latent_gps=num_latent_gps) #init Parameters latent self.X_data_mean = Parameter(X_data_mean) self.X_data_var = Parameter(X_data_var, transform=positive()) #init parameter inducing point if (inducing_variable is None) == (num_inducing_variables is None): raise ValueError( "BayesianGPLVM needs exactly one of `inducing_variable` and `num_inducing_variables`" ) if inducing_variable is None: # By default we initialize by subset of initial latent points # Note that tf.random.shuffle returns a copy, it does not shuffle in-place #maybe use k-means clustering Z = tf.random.shuffle(X_data_mean)[:num_inducing_variables] inducing_variable = InducingPoints(Z) self.inducing_variable = inducingpoint_wrapper(inducing_variable) #loss placeholder for analysis purpuse self.loss_placeholder = defaultdict(list, {k: [] for k in ("KL_x", "ELBO")}) # deal with parameters for the prior mean variance of X if X_prior_mean is None: X_prior_mean = tf.zeros((self.num_data, self.latent_dimensions), dtype=default_float()) if X_prior_var is None: X_prior_var = tf.ones((self.num_data, self.latent_dimensions), dtype=default_float()) self.X_prior_mean = tf.convert_to_tensor(np.atleast_1d(X_prior_mean), dtype=default_float()) self.X_prior_var = tf.convert_to_tensor(np.atleast_1d(X_prior_var), dtype=default_float()) #sanity check assert np.all(X_data_mean.shape == X_data_var.shape) assert X_data_mean.shape[0] == self.data.shape[ 0], "X mean and Y must be same size." assert X_data_var.shape[0] == self.data.shape[ 0], "X var and Y must be same size." assert X_data_mean.shape[1] == self.latent_dimensions assert self.X_prior_mean.shape[0] == self.num_data assert self.X_prior_mean.shape[1] == self.latent_dimensions assert self.X_prior_var.shape[0] == self.num_data assert self.X_prior_var.shape[1] == self.latent_dimensions