def sample_mu(self, j, k, scale=5.0): current = self.mus[j,k] proposal = np.random.normal(current, scale) current_logp = np.log(laplace.pdf(current, scale=self.gamma_f)) proposal_logp = np.log(laplace.pdf(proposal, scale=self.gamma_f)) # current_logp = -1 * ((current * current) / (2.0 * self.sigmas[j,k])) # proposal_logp = -1 * ((proposal * proposal) / (2.0 * self.sigmas[j,k])) theta_olds = [] for obj in self.mixlist: if obj["ready"][j] == False: self._calc_theta(obj, j) k2 = obj["assignments"][j] current_logp += obj["logthetas"][j,k2] theta_olds.append(obj["logthetas"][j].copy()) self.mus[j,k] = proposal for obj in self.mixlist: self._calc_theta(obj, j) k2 = obj["assignments"][j] proposal_logp += obj["logthetas"][j,k2] if current_logp > proposal_logp and rand_partition_log([current_logp, proposal_logp]) == 0: # rejected, undoing changes self.mus[j,k] = current for obj, theta_old in zip(self.mixlist, theta_olds): obj["logthetas"][j] = theta_old return False else: # accepted return True
def sample_eta(self, obj, k, scale=5.0): current = obj["etas"][k] proposal = np.random.normal(current, scale) current_logp = np.log(laplace.pdf(current, scale=self.gamma_c)) proposal_logp = np.log(laplace.pdf(proposal, scale=self.gamma_c)) # current_logp = -1 * ((current * current) / (2.0 * obj["taus"][k])) # proposal_logp = -1 * ((proposal * proposal) / (2.0 * obj["taus"][k])) for j in xrange(self.dims): if obj["ready"][j] == False: self._calc_theta(obj, j) k2 = obj["assignments"][j] current_logp += obj["logthetas"][j,k2] theta_old = obj["logthetas"].copy() obj["etas"][k] = proposal for j in xrange(self.dims): self._calc_theta(obj, j) k2 = obj["assignments"][j] proposal_logp += obj["logthetas"][j,k2] if current_logp > proposal_logp and rand_partition_log([current_logp, proposal_logp]) == 0: # rejected, undoing changes obj["etas"][k] = current # do not entirely override obj["logthetas"] because it is pointed from elsewhere for j in xrange(self.dims): obj["logthetas"][j] = theta_old[j] return False else: # accepted return True
def sample_z(self, l, k, itemp=1.0): assert(not self.bias or not k == 0) z_old = self.zmat[k,l] logprob0, logprob1 = 0.0, 0.0 if not self.only_alphas: vcount = np.bincount(self.zmat[k,self.vnet[l]], minlength=2) logprob0 += self.vks[k] * vcount[0] logprob1 += self.vks[k] * vcount[1] hcount = np.bincount(self.zmat[k,self.hnet[l]], minlength=2) logprob0 += self.hks[k] * hcount[0] logprob1 += self.hks[k] * hcount[1] logprob1 += self.alphas[k] theta_new = np.empty_like(self.theta[l,:]) theta_tilde_new = np.copy(self.theta_tilde[l,:]) if z_old == False: # proposal: 1 theta_tilde_new += self.wmat[k,:] logprob_old, logprob_new = logprob0, logprob1 else: # proposal: 0 theta_tilde_new -= self.wmat[k,:] logprob_old, logprob_new = logprob1, logprob0 for p in range(self.P): j_start, T = self.p2jT[p] x = self.mat[l,p] if self.flist[p]["type"] == "cat": logprob_old += np.log(self.theta[l,j_start+x] + 1E-20) e_theta_tilde = np.exp(theta_tilde_new[j_start:j_start+T] - theta_tilde_new[j_start:j_start+T].max()) theta_new[j_start:j_start+T] = e_theta_tilde / e_theta_tilde.sum() logprob_new += np.log(theta_new[j_start+x] + 1E-20) elif self.flist[p]["type"] == "bin": logprob_old += np.log((self.theta[l,j_start] if x == 1 else (1.0 - self.theta[l,j_start])) + 1E-20) theta_new[j_start] = 0.5 * np.tanh(0.5 * theta_tilde_new[j_start]) + 0.5 logprob_new += np.log((theta_new[j_start] if x == 1 else (1.0 - theta_new[j_start])) + 1E-20) elif self.flist[p]["type"] == "count": logprob_old += x * np.log(self.theta[l,j_start] + 1E-20) theta_new[j_start] = np.fmax(theta_tilde_new[j_start], 0) + np.log1p(np.exp(-np.fabs(theta_tilde_new[j_start]))) logprob_new += x * np.log(theta_new[j_start] + 1E-20) else: raise NotImplementedError if itemp != 1.0: logprob_old *= itemp logprob_new *= itemp accepted = np.bool_(rand_partition_log((logprob_old, logprob_new))) if accepted: if z_old == False: # 0 -> 1 self.zmat[k,l] = True else: # 1 -> 0 self.zmat[k,l] = False self.theta_tilde[l,:] = theta_tilde_new self.theta[l,:] = theta_new return True else: return False
def sample_zx(self, l, k, itemp=1.0): assert (not self.bias or not k == 0) z_old = self.zmat[k, l] logprob0, logprob1 = 0.0, 0.0 if not self.only_alphas: idxs, weights = self.hnet.js[l] vals = self.zmat[k, idxs] logprob0 += self.hks[k] * ((vals == 0) * weights).sum() logprob1 += self.hks[k] * ((vals == 1) * weights).sum() logprob1 += self.alphas[k] theta_new = np.empty_like(self.theta[l, :]) theta_tilde_new = np.copy(self.theta_tilde[l, :]) if z_old == False: # proposal: 1 theta_tilde_new += self.wmat[k, :] logprob_old, logprob_new = logprob0, logprob1 else: # proposal: 0 theta_tilde_new -= self.wmat[k, :] logprob_old, logprob_new = logprob1, logprob0 xs_new = self.mat[l, :].copy() for p, (x, is_missing) in enumerate(zip(self.mat[l, :], self.mvs[l, :])): j_start, T = self.p2jT[p] e_theta_tilde = np.exp(theta_tilde_new[j_start:j_start + T] - theta_tilde_new[j_start:j_start + T].max()) theta_new[j_start:j_start + T] = e_theta_tilde / e_theta_tilde.sum() if is_missing: xs_new[p] = np.random.choice(T, p=theta_new[j_start:j_start + T]) else: logprob_old += np.log(self.theta[l, j_start + x] + 1E-20) logprob_new += np.log(theta_new[j_start + xs_new[p]] + 1E-20) if itemp != 1.0: logprob_old *= itemp logprob_new *= itemp accepted = np.bool_(rand_partition_log((logprob_old, logprob_new))) if accepted: if z_old == False: # 0 -> 1 self.zmat[k, l] = True else: # 1 -> 0 self.zmat[k, l] = False self.theta_tilde[l, :] = theta_tilde_new self.theta[l, :] = theta_new changed = (self.mat[l, :] != xs_new).sum() self.mat[l, :] = xs_new return True, changed, self.mvs[l, :].sum() else: return False, 0, self.mvs[l, :].sum()
def sample_node_state_root(self, node, k): assert (not node.is_state_frozen) oldv = node.state[k] ctmc = self.ctmcs[k] logprobs = np.log(np.maximum(ctmc.get_stationary_probs(), 1E-10)) for child in node.children: time = node.date - child.date mat = ctmc.get_transition_probs(time) logprobs += np.log( np.maximum(mat[:, child.state[k].astype(np.int32)], 1E-10)) newv = rand_partition_log(logprobs) node.state[k] = newv return not (oldv == newv)
def sample_z(self, l, p): k = self.Z[l, p] v = self.mat[l, p] self.doclist[l].remove(k) self.voclist[p][k].remove(v) logproblist = np.log(self.doclist[l].problist()) for k2 in range(self.K): logproblist[k2] += np.log(self.voclist[p][k2].prob(v)) k2 = rand_partition_log(logproblist) self.Z[l, p] = k2 self.doclist[l].add(k2) self.voclist[p][k2].add(v) return False if k == k2 else True
def sample_x(self, l): assert (self.mvs is not None and self.mvs[l]) x_old = self.vec[l] logprobs = np.zeros(self.size, dtype=np.float32) if not self.only_alphas: if not self.drop_vs: logprobs += self.v * np.bincount(self.vec[self.vnet[l]], minlength=self.size) if not self.drop_hs: logprobs += self.h * np.bincount(self.vec[self.hnet[l]], minlength=self.size) logprobs += self.alphas self.vec[l] = rand_partition_log(logprobs) return False if self.vec[l] == x_old else True
def sample_node_state_tree(self, node, k): # forward-filtering, backward-sampling def _forward(node): Ln = np.zeros(D) for child in node.children: # Lc[s_j] Lc = _forward(child) time = node.date - child.date lmat = np.log( np.maximum(ctmc.get_transition_probs(time), 1E-10)) for d in range(D): Ln[d] += logsumexp(lmat[d, :] + Lc) tscores[child] = lmat if node.is_state_frozen: for d in range(D): if node.state[k] != d: Ln[d] = -np.inf nscores[node] = Ln return Ln def _backward(node): changed, total = 0, 0 if not node.is_state_frozen: total += 1 pval = node.parent.state[k].astype(np.int32) logprobs = nscores[node] + tscores[node][pval, :] newv = rand_partition_log(logprobs) if node.state[k] != newv: changed += 1 node.state[k] = newv for child in node.children: _changed, _total = _backward(child) changed += _changed total += _total return changed, total ctmc = self.ctmcs[k] D = ctmc.D nscores, tscores = {}, {} Ln = _forward(node) Ln += np.log(np.maximum(ctmc.get_stationary_probs(), 1E-10)) changed, total = 0, 1 newv = rand_partition_log(Ln) if node.state[k] != newv: changed += 1 for child in node.children: _changed, _total = _backward(child) changed += _changed total += _total return changed, total
def sample_x(self, l): assert (self.mvs is not None and self.mvs[l]) x_old = self.vec[l] logprobs = np.zeros(self.size, dtype=np.float32) if not self.only_alphas: if not self.drop_hs: idxs, weights = self.hnet.js[l] vals = np.zeros(self.size, dtype=np.float32) for j, v in enumerate(self.vec[idxs]): vals[v] += weights[j] logprobs += self.h * vals logprobs += self.alphas self.vec[l] = rand_partition_log(logprobs) return False if self.vec[l] == x_old else True
def _backward(node): changed, total = 0, 0 if not node.is_state_frozen: total += 1 pval = node.parent.state[k].astype(np.int32) logprobs = nscores[node] + tscores[node][pval, :] newv = rand_partition_log(logprobs) if node.state[k] != newv: changed += 1 node.state[k] = newv for child in node.children: _changed, _total = _backward(child) changed += _changed total += _total return changed, total
def sample_z(self, l, k, itemp=1.0): assert (not self.bias or not k == 0) z_old = self.zmat[k, l] logprob0, logprob1 = 0.0, 0.0 if not self.only_alphas: idxs, weights = self.hnet.js[l] vals = self.zmat[k, idxs] logprob0 += self.hks[k] * ((vals == 0) * weights).sum() logprob1 += self.hks[k] * ((vals == 1) * weights).sum() logprob1 += self.alphas[k] theta_new = np.empty_like(self.theta[l, :]) theta_tilde_new = np.copy(self.theta_tilde[l, :]) if z_old == False: # proposal: 1 theta_tilde_new += self.wmat[k, :] logprob_old, logprob_new = logprob0, logprob1 else: # proposal: 0 theta_tilde_new -= self.wmat[k, :] logprob_old, logprob_new = logprob1, logprob0 for p in range(self.P): j_start, T = self.p2jT[p] x = self.mat[l, p] logprob_old += np.log(self.theta[l, j_start + x] + 1E-20) e_theta_tilde = np.exp(theta_tilde_new[j_start:j_start + T] - theta_tilde_new[j_start:j_start + T].max()) theta_new[j_start:j_start + T] = e_theta_tilde / e_theta_tilde.sum() logprob_new += np.log(theta_new[j_start + x] + 1E-20) if itemp != 1.0: logprob_old *= itemp logprob_new *= itemp accepted = np.bool_(rand_partition_log((logprob_old, logprob_new))) if accepted: if z_old == False: # 0 -> 1 self.zmat[k, l] = True else: # 1 -> 0 self.zmat[k, l] = False self.theta_tilde[l, :] = theta_tilde_new self.theta[l, :] = theta_new return True else: return False
def sample_tied_h(self): logr = 0.0 oldval = self.h P_SIGMA = 0.5 rate = np.random.lognormal(mean=0.0, sigma=P_SIGMA) irate = 1.0 / rate newval = rate * oldval lograte = np.log(rate) logirate = np.log(irate) # P(theta') / P(theta) # logr += gamma.logpdf(newval, self.gamma_shape, scale=self.gamma_scale) \ # - gamma.logpdf(oldval, self.gamma_shape, scale=self.gamma_scale) logr += (self.als[0].gamma_shape - 1.0) * (np.log(newval) - np.log(oldval)) \ - (newval - oldval) / self.als[0].gamma_scale # q(theta|theta', x) / q(theta'|theta, x) logr += (lograte * lograte - logirate * logirate) / ( 2.0 * P_SIGMA * P_SIGMA) + lograte - logirate h = newval for al in self.als: a = al.alphas net = al.hnet vec = al.vec.copy() llist = np.arange(al.L) np.random.shuffle(llist) for l in llist: logprobs = np.zeros(al.size, dtype=np.float32) idxs, weights = al.hnet.js[l] vals = np.zeros(al.size, dtype=np.float32) for j, v in enumerate(al.vec[idxs]): vals[v] += weights[j] logprobs += h * vals logprobs += a vec[l] = rand_partition_log(logprobs) oldsum = al._neighbor_sum(al.vec) newsum = al._neighbor_sum(vec) logr += (oldval - newval) * (newsum - oldsum) if logr >= 0 or np.log(np.random.rand()) < logr: # accept self.h = newval for al in self.als: al.h = newval return True else: return False
def sample_autologistic(self, t_type, k): logr = 0.0 if t_type == self.S_Z_A: oldval = self.alphas[k] pivot = min((self.zmat[k].sum() + 0.01) / self.L, 0.99) pivot = np.log(pivot / (1.0 - pivot)) oldmean = (oldval + pivot) / 2.0 oldscale = max(abs(oldval - pivot), 0.001) newval = np.random.normal(loc=oldmean, scale=oldscale) newmean = (newval + pivot) / 2.0 newscale = max(abs(newval - pivot), 0.001) # q(theta|theta', x) / q(theta'|theta, x) logr += -((oldval - newmean) ** 2) / (2.0 * newscale * newscale) - np.log(newscale) \ + ((newval - oldmean) ** 2) / (2.0 * oldscale * oldscale) + np.log(oldscale) # P(theta') / P(theta) logr += (oldval * oldval - newval * newval) / ( 2.0 * self.norm_sigma * self.norm_sigma) # skip: q(theta|theta', x) / q(theta'|theta, x) for symmetric proposal h, a = self.hks[k], newval else: assert (not self.only_alphas) assert (not (t_type == self.S_Z_H and self.drop_hs)) oldval = self.hks[k] P_SIGMA = 0.5 rate = np.random.lognormal(mean=0.0, sigma=P_SIGMA) irate = 1.0 / rate newval = rate * oldval lograte = np.log(rate) logirate = np.log(irate) # P(theta') / P(theta) logr += (self.gamma_shape - 1.0) * (np.log(newval) - np.log(oldval)) \ - (newval - oldval) / self.gamma_scale # q(theta|theta', x) / q(theta'|theta, x) logr += (lograte * lograte - logirate * logirate) / ( 2.0 * P_SIGMA * P_SIGMA) + lograte - logirate h, a = newval, self.alphas[k] net = self.hnet zvect = self.zmat[k].copy() llist = np.arange(self.L) np.random.shuffle(llist) for l in llist: logprob0, logprob1 = (0.0, 0.0) if not self.only_alphas: idxs, weights = self.hnet.js[l] vals = self.zmat[k, idxs] logprob0 += h * ((vals == 0) * weights).sum() logprob1 += h * ((vals == 1) * weights).sum() logprob1 += a zvect[l] = rand_partition_log([logprob0, logprob1]) if t_type == self.S_Z_A: logr += (oldval - newval) * (zvect.sum() - self.zmat[k].sum()) if logr >= 0 or np.log(np.random.rand()) < logr: # accept self.alphas[k] = newval return True else: return False else: oldsum = self._neighbor_sum(self.zmat[k]) newsum = self._neighbor_sum(zvect) logr += (oldval - newval) * (newsum - oldsum) if logr >= 0 or np.log(np.random.rand()) < logr: # accept self.hks[k] = newval return True else: return False
def sample_autologistic(self, t_type, k): logr = 0.0 if t_type == self.S_A: oldval = self.alphas[k] newval = np.random.normal(loc=oldval, scale=0.01) # P(theta') / P(theta) logr += (oldval**2 - newval**2) / (2.0 * self.norm_sigma * self.norm_sigma) alphas = self.alphas.copy() alphas[k] = newval v, h, a = self.v, self.h, alphas else: assert (not self.only_alphas) assert (not (t_type == self.S_V and self.drop_vs)) assert (not (t_type == self.S_H and self.drop_hs)) if t_type == self.S_V: oldval = self.v else: oldval = self.h P_SIGMA = 0.5 rate = np.random.lognormal(mean=0.0, sigma=P_SIGMA) irate = 1.0 / rate newval = rate * oldval lograte = np.log(rate) logirate = np.log(irate) # P(theta') / P(theta) # logr += gamma.logpdf(newval, self.gamma_shape, scale=self.gamma_scale) \ # - gamma.logpdf(oldval, self.gamma_shape, scale=self.gamma_scale) logr += (self.gamma_shape - 1.0) * (np.log(newval) - np.log(oldval)) \ - (newval - oldval) / self.gamma_scale # q(theta|theta', x) / q(theta'|theta, x) logr += (lograte * lograte - logirate * logirate) / ( 2.0 * P_SIGMA * P_SIGMA) + lograte - logirate if t_type == self.S_V: v, h, a = newval, self.h, self.alphas net = self.vnet else: v, h, a = self.v, newval, self.alphas net = self.hnet vec = self.vec.copy() llist = np.arange(self.L) np.random.shuffle(llist) for l in llist: logprobs = np.zeros(self.size, dtype=np.float32) if not self.only_alphas: if not self.drop_vs: logprobs += v * np.bincount(self.vec[self.vnet[l]], minlength=self.size) if not self.drop_hs: logprobs += h * np.bincount(self.vec[self.hnet[l]], minlength=self.size) logprobs += a vec[l] = rand_partition_log(logprobs) if t_type == self.S_A: logr += (oldval - newval) * ((vec == k).sum() - (self.vec == k).sum()) if logr >= 0 or np.log(np.random.rand()) < logr: # accept self.alphas[k] = newval return True else: return False else: oldsum = self._neighbor_sum(self.vec, net) newsum = self._neighbor_sum(vec, net) logr += (oldval - newval) * (newsum - oldsum) if logr >= 0 or np.log(np.random.rand()) < logr: # accept if t_type == self.S_V: self.v = newval else: self.h = newval return True else: return False
def sample_autologistic(self, t_type, k): logr = 0.0 if t_type == self.S_Z_A: oldval = self.alphas[k] pivot = min((self.zmat[k].sum() + 0.01) / self.L, 0.99) pivot = np.log(pivot / (1.0 - pivot)) oldmean = (oldval + pivot) / 2.0 oldscale = max(abs(oldval - pivot), 0.001) newval = np.random.normal(loc=oldmean, scale=oldscale) newmean = (newval + pivot) / 2.0 newscale = max(abs(newval - pivot), 0.001) # q(theta|theta', x) / q(theta'|theta, x) logr += -((oldval - newmean) ** 2) / (2.0 * newscale * newscale) - np.log(newscale) \ + ((newval - oldmean) ** 2) / (2.0 * oldscale * oldscale) + np.log(oldscale) # P(theta') / P(theta) logr += (oldval * oldval - newval * newval) / (2.0 * self.norm_sigma * self.norm_sigma) # skip: q(theta|theta', x) / q(theta'|theta, x) for symmetric proposal v, h, a = self.vks[k], self.hks[k], newval else: assert(not self.only_alphas) assert(not (t_type == self.S_Z_V and self.drop_vs)) assert(not (t_type == self.S_Z_H and self.drop_hs)) if t_type == self.S_Z_V: oldval = self.vks[k] else: oldval = self.hks[k] P_SIGMA = 0.5 rate = np.random.lognormal(mean=0.0, sigma=P_SIGMA) irate = 1.0 / rate newval = rate * oldval lograte = np.log(rate) logirate = np.log(irate) # P(theta') / P(theta) # logr += gamma.logpdf(newval, self.gamma_shape, scale=self.gamma_scale) \ # - gamma.logpdf(oldval, self.gamma_shape, scale=self.gamma_scale) logr += (self.gamma_shape - 1.0) * (np.log(newval) - np.log(oldval)) \ - (newval - oldval) / self.gamma_scale # q(theta|theta', x) / q(theta'|theta, x) logr += (lograte * lograte - logirate * logirate) / (2.0 * P_SIGMA * P_SIGMA) + lograte - logirate if t_type == self.S_Z_V: v, h, a = newval, self.hks[k], self.alphas[k] net = self.vnet else: v, h, a = self.vks[k], newval, self.alphas[k] net = self.hnet zvect = self.zmat[k].copy() llist = np.arange(self.L) np.random.shuffle(llist) for l in llist: logprob0, logprob1 = (0.0, 0.0) if not self.only_alphas: vcount = np.bincount(zvect[self.vnet[l]], minlength=2) logprob0 += v * vcount[0] logprob1 += v * vcount[1] hcount = np.bincount(zvect[self.hnet[l]], minlength=2) logprob0 += h * hcount[0] logprob1 += h * hcount[1] logprob1 += a zvect[l] = rand_partition_log([logprob0, logprob1]) # V_oldsum = self._neighbor_sum(self.zmat[k], self.vnet) # H_oldsum = self._neighbor_sum(self.zmat[k], self.hnet) # A_oldsum = self.zmat[k].sum() # V_newsum = self._neighbor_sum(zvect, self.vnet) # H_newsum = self._neighbor_sum(zvect, self.hnet) # A_newsum = zvect.sum() # logr += (self.vks[k] * V_newsum + self.hks[k] * H_newsum + self.alphas[k] * A_newsum) \ # + (v * V_oldsum + h * H_oldsum + a * A_oldsum) \ # - (self.vks[k] * V_oldsum + self.hks[k] * H_oldsum + self.alphas[k] * A_oldsum) \ # - (v * V_newsum + h * H_newsum + a * A_newsum) # logr += (self.vks[k] * (V_newsum - V_oldsum) + self.hks[k] * (H_newsum - H_oldsum) + self.alphas[k] * (A_newsum - A_oldsum)) \ # - (v * (V_newsum - V_oldsum) + h * (H_newsum - H_oldsum) + a * (A_newsum - A_oldsum)) # logr += ((self.vks[k] - v) * (V_newsum - V_oldsum) + (self.hks[k] - h) * (H_newsum - H_oldsum) + (self.alphas[k] - a) * (A_newsum - A_oldsum)) if t_type == self.S_Z_A: logr += (oldval - newval) * (zvect.sum() - self.zmat[k].sum()) if logr >= 0 or np.log(np.random.rand()) < logr: # accept self.alphas[k] = newval return True else: return False else: oldsum = self._neighbor_sum(self.zmat[k], net) newsum = self._neighbor_sum(zvect, net) logr += (oldval - newval) * (newsum - oldsum) if logr >= 0 or np.log(np.random.rand()) < logr: # accept if t_type == self.S_Z_V: self.vks[k] = newval else: self.hks[k] = newval return True else: return False
def sample_zx(self, l, k, itemp=1.0): assert(not self.bias or not k == 0) z_old = self.zmat[k,l] logprob0, logprob1 = 0.0, 0.0 if not self.only_alphas: vcount = np.bincount(self.zmat[k,self.vnet[l]], minlength=2) logprob0 += self.vks[k] * vcount[0] logprob1 += self.vks[k] * vcount[1] hcount = np.bincount(self.zmat[k,self.hnet[l]], minlength=2) logprob0 += self.hks[k] * hcount[0] logprob1 += self.hks[k] * hcount[1] logprob1 += self.alphas[k] theta_new = np.empty_like(self.theta[l,:]) theta_tilde_new = np.copy(self.theta_tilde[l,:]) if z_old == False: # proposal: 1 theta_tilde_new += self.wmat[k,:] logprob_old, logprob_new = logprob0, logprob1 else: # proposal: 0 theta_tilde_new -= self.wmat[k,:] logprob_old, logprob_new = logprob1, logprob0 xs_new = self.mat[l,:].copy() for p, (x, is_missing) in enumerate(zip(self.mat[l,:], self.mvs[l,:])): j_start, T = self.p2jT[p] if self.flist[p]["type"] == "cat": e_theta_tilde = np.exp(theta_tilde_new[j_start:j_start+T] - theta_tilde_new[j_start:j_start+T].max()) theta_new[j_start:j_start+T] = e_theta_tilde / e_theta_tilde.sum() if is_missing: xs_new[p] = np.random.choice(T, p=theta_new[j_start:j_start+T]) else: logprob_old += np.log(self.theta[l,j_start+x] + 1E-20) logprob_new += np.log(theta_new[j_start+xs_new[p]] + 1E-20) elif self.flist[p]["type"] == "bin": theta_new[j_start] = 0.5 * np.tanh(0.5 * theta_tilde_new[j_start]) + 0.5 if is_missing: xs_new[p] = np.random.random() < theta_new[j_start] else: logprob_old += np.log((self.theta[l,j_start] if x == 1 else (1.0 - self.theta[l,j_start])) + 1E-20) logprob_new += np.log((theta_new[j_start] if xs_new[p] == 1 else (1.0 - theta_new[j_start])) + 1E-20) elif self.flist[p]["type"] == "count": theta_new[j_start] = np.fmax(theta_tilde_new[j_start], 0) + np.log1p(np.exp(-np.fabs(theta_tilde_new[j_start]))) if is_missing: xs_new[p] = np.random.poisson(lam=theta_new[j_start]) else: logprob_old += x * np.log(self.theta[l,j_start] + 1E-20) logprob_new += xs_new[p] * np.log(theta_new[j_start] + 1E-20) else: raise NotImplementedError if itemp != 1.0: logprob_old *= itemp logprob_new *= itemp accepted = np.bool_(rand_partition_log((logprob_old, logprob_new))) if accepted: if z_old == False: # 0 -> 1 self.zmat[k,l] = True else: # 1 -> 0 self.zmat[k,l] = False self.theta_tilde[l,:] = theta_tilde_new self.theta[l,:] = theta_new changed = (self.mat[l,:] != xs_new).sum() self.mat[l,:] = xs_new return True, changed, self.mvs[l,:].sum() else: return False, 0, self.mvs[l,:].sum()