def elbo(self, variational_posterior, datas, inputs=None, masks=None, tags=None, n_samples=1): """ Lower bound on the marginal likelihood p(y | theta) using variational posterior q(x; phi) where phi = variational_params """ elbo = 0 for sample in range(n_samples): # Sample x from the variational posterior xs = variational_posterior.sample() # log p(theta) elbo += self.log_prior() # log p(x, y | theta) = log \sum_z p(x, y, z | theta) for x, data, input, mask, tag in zip(xs, datas, inputs, masks, tags): # The "mask" for x is all ones x_mask = np.ones_like(x, dtype=bool) pi0 = self.init_state_distn.initial_state_distn Ps = self.transitions.transition_matrices(x, input, x_mask, tag) log_likes = self.dynamics.log_likelihoods(x, input, x_mask, tag) log_likes += self.emissions.log_likelihoods(data, input, mask, tag, x) elbo += hmm_normalizer(pi0, Ps, log_likes) # -log q(x) elbo -= variational_posterior.log_density(xs) assert np.isfinite(elbo) return elbo / n_samples
def elbo(self, variational_params, datas, inputs=None, masks=None, tags=None, n_samples=1): """ Lower bound on the marginal likelihood p(y | theta) using variational posterior q(x; phi) where phi = variational_params """ elbo = 0 for data, input, mask, tag, (q_mu, q_sigma_inv) in \ zip(datas, inputs, masks, tags, variational_params): q_sigma = np.exp(q_sigma_inv) for sample in range(n_samples): # log p(theta) elbo += self.log_prior() # Sample x from the variational posterior x = q_mu + np.sqrt(q_sigma) * npr.randn(data.shape[0], self.D) # Compute log p(x | theta) = log \sum_z p(x, z | theta) # The "mask" for x is all ones x_mask = np.ones_like(x, dtype=bool) log_pi0 = self.init_state_distn.log_initial_state_distn(x, input, x_mask, tag) log_Ps = self.transitions.log_transition_matrices(x, input, x_mask, tag) log_likes = self.dynamics.log_likelihoods(x, input, x_mask, tag) log_likes += self.emissions.log_likelihoods(data, input, mask, tag, x) elbo += hmm_normalizer(log_pi0, log_Ps, log_likes) # -log q(x) elbo -= np.sum(-0.5 * np.log(2 * np.pi * q_sigma)) elbo -= np.sum(-0.5 * (x - q_mu)**2 / q_sigma) assert np.isfinite(elbo) return elbo / n_samples
def log_likelihood(self, datas, inputs=None, masks=None, tags=None): """ Compute the log probability of the data under the current model parameters. :param datas: single array or list of arrays of data. :return total log probability of the data. """ ll = 0 for data, input, mask, tag in zip(datas, inputs, masks, tags): log_pi0 = self.init_state_distn.log_initial_state_distn(data, input, mask, tag) log_Ps = self.transitions.log_transition_matrices(data, input, mask, tag) log_likes = self.observations.log_likelihoods(data, input, mask, tag) ll += hmm_normalizer(log_pi0, log_Ps, log_likes) assert np.isfinite(ll) return ll