def _log_likelihood(self): """ Returns the variational bound on the log likelihood. """ LL = [] # build a list of all the different terms in the LL # n_d term term = (gammaln(self.q_alpha.E) - gammaln(self.q_alpha.E + self.n_d)).sum() assert numpy.isfinite(term) LL.append(term) # n_dk term G_alpha_pi = self.q_alpha.G * self.G_pi f = lambda n: gammaln(G_alpha_pi + n) - gammaln(G_alpha_pi) f2 = lambda n: polygamma(1, (G_alpha_pi + n)) term = _approx_f_n(f, f2, self.counts.P_plus_n_dk, self.counts.E_plus_n_dk, self.counts.V_plus_n_dk).sum() assert numpy.isfinite(term) LL.append(term) # n_k term f = lambda n: gammaln(self.q_beta.G + n) - gammaln(self.q_beta.G) f2 = lambda n: polygamma(1, (self.q_beta.G + n)) term = - _approx_f_n(f, f2, self.counts.P_plus_n_k, self.counts.E_plus_n_k, self.counts.V_plus_n_k).sum() assert numpy.isfinite(term) LL.append(term) # n_kw term G_beta_tau = self.q_beta.G * self.q_tau.G f = lambda n: gammaln(G_beta_tau + n) - gammaln(G_beta_tau) f2 = lambda n: polygamma(1, (G_beta_tau + n)) term = _approx_f_n(f, f2, self.counts.P_plus_n_kw, self.counts.E_plus_n_kw, self.counts.V_plus_n_kw).sum() assert numpy.isfinite(term) LL.append(term) # KL(q(alpha)||p(alpha)) term a_bar = self.a_alpha + self.E_s_dk.sum() b_bar = self.b_alpha - self.E_log_eta.sum() term = - _gamma_KL(a_bar, b_bar, self.a_alpha, self.b_alpha) assert numpy.isfinite(term) LL.append(term) # KL(q(z)||p(z)) term term = sum(- _safe_x_log_x(q_zd).sum() for q_zd in self.q_z) LL.append(term) assert numpy.isfinite(term) # KL(q(beta)||p(beta)) term a_bar = self.a_beta + self.E_t_kw.sum() b_bar = self.b_beta - self.E_log_xi.sum() term = - _gamma_KL(a_bar, b_bar, self.a_beta, self.b_beta) assert numpy.isfinite(term) LL.append(term) # KL(q(pi)||p(pi)) term E_s_k = self.E_s_dk.sum(axis=0) assert E_s_k.shape == (self.K,) E_s_greater_k = _greater_than(E_s_k) # term = - ( # gammaln(1. + self.q_gamma.E + E_s_k + E_s_greater_k) # - numpy.log(self.q_gamma.E) # - gammaln(1. + E_s_k) # - gammaln(self.q_gamma.E + E_s_greater_k) # + E_s_k * numpy.log(self.q_pi_bar.G) # + E_s_greater_k * numpy.log(self.q_1_minus_pi_bar.G) # ).sum() term = - ( ( gammaln(1. + self.q_gamma.E + E_s_k + E_s_greater_k) - numpy.log(self.q_gamma.E) - gammaln(1. + E_s_k) - gammaln(self.q_gamma.E + E_s_greater_k) ) * self.q_pi_bar.G ** E_s_k * self.q_1_minus_pi_bar.G ** E_s_greater_k ).sum() #assert numpy.allclose(term, _beta_KL(self.q_pi_bar.a, self.q_pi_bar.b, 1., self.q_gamma.E)) #term = _beta_KL(self.q_pi_bar.a, self.q_pi_bar.b, 1., self.q_gamma.G).sum() assert numpy.isfinite(term) LL.append(term) # KL(q(tau)||p(tau)) term a_bar = self.q_tau.a + self.E_t_kw.sum(axis=0) term = - _dirichlet_KL(a_bar, self.q_tau.a) assert numpy.isfinite(term) LL.append(term) return LL
def _update_pi_bar(self): E_s_k = self.E_s_dk.sum(axis=0) assert E_s_k.shape == (self.K,) E_s_greater_k = _greater_than(E_s_k) self.q_pi_bar = BetaDist(E_s_k + 1., self.q_gamma.E + E_s_greater_k)