def _set_initial_values(self, alpha0, nu0, Phi0, mu0, Sigma0, weights0, alpha_a0, alpha_b0): if nu0 is None: nu0 = 3 if Phi0 is None: Phi0 = np.empty((self.ncomp, self.ndim, self.ndim)) Phi0[:] = np.eye(self.ndim) * (nu0 - 1) if Sigma0 is None: # draw from prior Sigma0 = np.empty((self.ncomp, self.ndim, self.ndim)) for j in xrange(self.ncomp): Sigma0[j] = pm.rinverse_wishart_prec(nu0 + 2 + self.ncomp, Phi0[j]) # starting values, are these sensible? if mu0 is None: mu0 = np.empty((self.ncomp, self.ndim)) for j in xrange(self.ncomp): mu0[j] = pm.rmv_normal_cov(self.mu_prior_mean, self.gamma[j] * Sigma0[j]) if weights0 is None: _, weights0 = stick_break_proc(1, 1, size=self.ncomp - 1) self._alpha0 = alpha0 self._alpha_a0 = alpha_a0 self._alpha_b0 = alpha_b0 self._weights0 = weights0 self._mu0 = mu0 self._Sigma0 = Sigma0 self._nu0 = nu0 # prior degrees of freedom self._Phi0 = Phi0 # prior location for Sigma_j's
def _update_mu_Sigma(self, Sigma, component_mask): mu_output = np.zeros((self.ncomp, self.ndim)) Sigma_output = np.zeros((self.ncomp, self.ndim, self.ndim)) for j in xrange(self.ncomp): mask = component_mask[j] Xj = self.data[mask] nj = len(Xj) # TODO: sample from prior if nj == 0 sumxj = Xj.sum(0) gam = self.gamma[j] mu_hyper = self.mu_prior_mean post_mean = (mu_hyper / gam + sumxj) / (1 / gam + nj) post_cov = 1 / (1 / gam + nj) * Sigma[j] new_mu = pm.rmv_normal_cov(post_mean, post_cov) Xj_demeaned = Xj - new_mu mu_SS = np.outer(new_mu - mu_hyper, new_mu - mu_hyper) / gam data_SS = np.dot(Xj_demeaned.T, Xj_demeaned) post_Phi = data_SS + mu_SS + self._nu0 * self._Phi0[j] # symmetrize post_Phi = (post_Phi + post_Phi.T) / 2 # P(Sigma) ~ IW(nu + 2, nu * Phi) # P(Sigma | theta, Y) ~ post_nu = nj + self.ncomp + self._nu0 + 3 # pymc rinverse_wishart takes new_Sigma = pm.rinverse_wishart_prec(post_nu, post_Phi) mu_output[j] = new_mu Sigma_output[j] = new_Sigma return mu_output, Sigma_output