class StickbreakingCorrelatedLDA(_LDABase): "Correlated LDA with the stick breaking representation" def __init__(self, data, T, alpha_beta): mu, sigma = compute_uniform_mean_psi(T) self.theta_prior = Gaussian( mu=mu, sigma=sigma, mu_0=mu, sigma_0=T * sigma / 10.0, nu_0=T / 10.0, kappa_0=1.0 / 10 ) self.ppgs = initialize_polya_gamma_samplers() self.omega = np.zeros((data.shape[0], T - 1)) super(StickbreakingCorrelatedLDA, self).__init__(data, T, alpha_beta) @property def theta(self): return psi_to_pi(self.psi) @theta.setter def theta(self, theta): self.psi = pi_to_psi(theta) def initialize_theta(self): self.psi = np.tile(self.theta_prior.mu, (self.D, 1)) def resample_theta(self): self.resample_omega() self.resample_psi() def resample(self): super(StickbreakingCorrelatedLDA, self).resample() self.resample_theta_prior() def resample_omega(self): pgdrawvpar( self.ppgs, N_vec(self.doc_topic_counts).astype("float64").ravel(), self.psi.ravel(), self.omega.ravel() ) np.clip(self.omega, 1e-32, np.inf, out=self.omega) def resample_psi(self): Lmbda = np.linalg.inv(self.theta_prior.sigma) h = Lmbda.dot(self.theta_prior.mu) randvec = np.random.randn(self.D, self.T - 1) # pre-generate randomness for d, c in enumerate(self.doc_topic_counts): self.psi[d] = sample_infogaussian(Lmbda + np.diag(self.omega[d]), h + kappa_vec(c), randvec[d]) def resample_theta_prior(self): self.theta_prior.resample(self.psi) def copy_sample(self): new = copy.copy(self) new.beta = self.beta.copy() new.psi = self.psi.copy() new.theta_prior = self.theta_prior.copy_sample() del new.z del new.omega return new
class LogisticNormalCorrelatedLDA(_LDABase): "Correlated LDA with the stick breaking representation" def __init__(self, data, T, alpha_beta): mu, sigma = np.zeros(T), np.eye(T) self.theta_prior = \ Gaussian( mu=mu, sigma=sigma, mu_0=mu, sigma_0=T*sigma/10., nu_0=T/10., kappa_0=10.) self.ppgs = initialize_polya_gamma_samplers() self.omega = np.zeros((data.shape[0], T)) super(LogisticNormalCorrelatedLDA, self).__init__(data, T, alpha_beta) @property def theta(self): return ln_psi_to_pi(self.psi) @theta.setter def theta(self, theta): self.psi = ln_pi_to_psi(theta) def initialize_theta(self): self.psi = np.tile(self.theta_prior.mu, (self.D, 1)) def resample_theta(self): self.resample_psi_and_omega() def resample(self): super(LogisticNormalCorrelatedLDA, self).resample() self.resample_theta_prior() def resample_psi_and_omega(self): Lmbda = np.linalg.inv(self.theta_prior.sigma) for d in xrange(self.D): N = self.data[d].sum() c = self.doc_topic_counts[d] for t in xrange(self.T): self.omega[d, t] = self.ppgs[0].pgdraw( N, self._conditional_omega(d, t)) mu_cond, sigma_cond = self._conditional_psi(d, t, Lmbda, N, c) self.psi[d, t] = np.random.normal(mu_cond, np.sqrt(sigma_cond)) def _conditional_psi(self, d, t, Lmbda, N, c): nott = np.arange(self.T) != t psi = self.psi[d] omega = self.omega[d] mu = self.theta_prior.mu zetat = logsumexp(psi[nott]) mut_marg = mu[t] - 1. / Lmbda[t, t] * Lmbda[t, nott].dot(psi[nott] - mu[nott]) sigmat_marg = 1. / Lmbda[t, t] sigmat_cond = 1. / (omega[t] + 1. / sigmat_marg) # kappa is the mean dot precision, i.e. the sufficient statistic of a Gaussian # therefore we can sum over datapoints kappa = (c[t] - N / 2.0).sum() mut_cond = sigmat_cond * (kappa + mut_marg / sigmat_marg + omega[t] * zetat) return mut_cond, sigmat_cond def _conditional_omega(self, d, t): nott = np.arange(self.T) != t psi = self.psi[d] zetat = logsumexp(psi[nott]) return psi[t] - zetat def resample_theta_prior(self): self.theta_prior.resample(self.psi) def copy_sample(self): new = copy.copy(self) new.beta = self.beta.copy() new.psi = self.psi.copy() new.theta_prior = self.theta_prior.copy_sample() del new.z del new.omega return new
class StickbreakingCorrelatedLDA(_LDABase): "Correlated LDA with the stick breaking representation" def __init__(self, data, T, alpha_beta): mu, sigma = compute_uniform_mean_psi(T) self.theta_prior = Gaussian(mu=mu, sigma=sigma, mu_0=mu, sigma_0=T * sigma / 10., nu_0=T / 10., kappa_0=1. / 10) self.ppgs = initialize_polya_gamma_samplers() self.omega = np.zeros((data.shape[0], T - 1)) super(StickbreakingCorrelatedLDA, self).__init__(data, T, alpha_beta) @property def theta(self): return psi_to_pi(self.psi) @theta.setter def theta(self, theta): self.psi = pi_to_psi(theta) def initialize_theta(self): self.psi = np.tile(self.theta_prior.mu, (self.D, 1)) def resample_theta(self): self.resample_omega() self.resample_psi() def resample(self): super(StickbreakingCorrelatedLDA, self).resample() self.resample_theta_prior() def resample_omega(self): pgdrawvpar(self.ppgs, N_vec(self.doc_topic_counts).astype('float64').ravel(), self.psi.ravel(), self.omega.ravel()) np.clip(self.omega, 1e-32, np.inf, out=self.omega) def resample_psi(self): Lmbda = np.linalg.inv(self.theta_prior.sigma) h = Lmbda.dot(self.theta_prior.mu) randvec = np.random.randn(self.D, self.T - 1) # pre-generate randomness for d, c in enumerate(self.doc_topic_counts): self.psi[d] = sample_infogaussian(Lmbda + np.diag(self.omega[d]), h + kappa_vec(c), randvec[d]) def resample_theta_prior(self): self.theta_prior.resample(self.psi) def copy_sample(self): new = copy.copy(self) new.beta = self.beta.copy() new.psi = self.psi.copy() new.theta_prior = self.theta_prior.copy_sample() del new.z del new.omega return new
class LogisticNormalCorrelatedLDA(_LDABase): "Correlated LDA with the stick breaking representation" def __init__(self, data, T, alpha_beta): mu, sigma = np.zeros(T), np.eye(T) self.theta_prior = \ Gaussian( mu=mu, sigma=sigma, mu_0=mu, sigma_0=T*sigma/10., nu_0=T/10., kappa_0=10.) self.ppgs = initialize_polya_gamma_samplers() self.omega = np.zeros((data.shape[0], T)) super(LogisticNormalCorrelatedLDA, self).__init__(data, T, alpha_beta) @property def theta(self): return ln_psi_to_pi(self.psi) @theta.setter def theta(self, theta): self.psi = ln_pi_to_psi(theta) def initialize_theta(self): self.psi = np.tile(self.theta_prior.mu, (self.D, 1)) def resample_theta(self): self.resample_psi_and_omega() def resample(self): super(LogisticNormalCorrelatedLDA, self).resample() self.resample_theta_prior() def resample_psi_and_omega(self): Lmbda = np.linalg.inv(self.theta_prior.sigma) for d in xrange(self.D): N = self.data[d].sum() c = self.doc_topic_counts[d] for t in xrange(self.T): self.omega[d,t] = self.ppgs[0].pgdraw( N, self._conditional_omega(d,t)) mu_cond, sigma_cond = self._conditional_psi(d, t, Lmbda, N, c) self.psi[d,t] = np.random.normal(mu_cond, np.sqrt(sigma_cond)) def _conditional_psi(self, d, t, Lmbda, N, c): nott = np.arange(self.T) != t psi = self.psi[d] omega = self.omega[d] mu = self.theta_prior.mu zetat = logsumexp(psi[nott]) mut_marg = mu[t] - 1./Lmbda[t,t] * Lmbda[t,nott].dot(psi[nott] - mu[nott]) sigmat_marg = 1./Lmbda[t,t] sigmat_cond = 1./(omega[t] + 1./sigmat_marg) # kappa is the mean dot precision, i.e. the sufficient statistic of a Gaussian # therefore we can sum over datapoints kappa = (c[t] - N/2.0).sum() mut_cond = sigmat_cond * (kappa + mut_marg / sigmat_marg + omega[t]*zetat) return mut_cond, sigmat_cond def _conditional_omega(self, d, t): nott = np.arange(self.T) != t psi = self.psi[d] zetat = logsumexp(psi[nott]) return psi[t] - zetat def resample_theta_prior(self): self.theta_prior.resample(self.psi) def copy_sample(self): new = copy.copy(self) new.beta = self.beta.copy() new.psi = self.psi.copy() new.theta_prior = self.theta_prior.copy_sample() del new.z del new.omega return new