def resample(self): al, o = np.log(self.alpha_0), self.obs_distn self.z = ma.masked_array(self.z, mask=np.zeros(self.z.shape)) model = self.model for n in np.random.permutation(self.data.shape[0]): # mask out n self.z.mask[n] = True # form the scores and sample them ks = list(model._get_occupied()) scores = np.array( [ np.log(model._get_counts(k)) + o.log_predictive(self.data[n], model._get_data_withlabel(k)) for k in ks ] + [al + o.log_marginal_likelihood(self.data[n])] ) idx = sample_discrete_from_log(scores) if idx == scores.shape[0] - 1: self.z[n] = self._new_label(ks) else: self.z[n] = ks[idx] # sample # note: the mask gets fixed by assigning into the array self.z[n] = sample_discrete_from_log(np.array(scores))
def _resample_xi_discrete(self, augmented_data_list, xi_max=20): from pybasicbayes.util.stats import sample_discrete_from_log from pyglm.internals.negbin import nb_likelihood_xi # Resample xi with uniform prior over discrete set # p(\xi | \psi, s) \propto p(\xi) * p(s | \xi, \psi) lp_xis = np.zeros((self.N, xi_max)) for d in augmented_data_list: psi = self.activation.compute_psi(d) for n in xrange(self.N): Sn = d["S"][:,n].copy() psin = psi[:,n].copy() pn = logistic(psin) pn = np.clip(pn, 1e-32, 1-1e-32) xis = np.arange(1, xi_max+1).astype(np.float) lp_xi = np.zeros(xi_max) nb_likelihood_xi(Sn, pn, xis, lp_xi) lp_xis[n] += lp_xi # lp_xi2 = (gammaln(Sn[:,None]+xis[None,:]) - gammaln(xis[None,:])).sum(0) # lp_xi2 += (xis[None,:] * np.log(1-pn)[:,None]).sum(0) # # assert np.allclose(lp_xi, lp_xi2) for n in xrange(self.N): self.xi[0,n] = xis[sample_discrete_from_log(lp_xis[n])]
def _resample_xi_discrete(self, augmented_data_list, xi_max=20): from pybasicbayes.util.stats import sample_discrete_from_log from pyglm.internals.negbin import nb_likelihood_xi # Resample xi with uniform prior over discrete set # p(\xi | \psi, s) \propto p(\xi) * p(s | \xi, \psi) lp_xis = np.zeros((self.N, xi_max)) for d in augmented_data_list: psi = self.activation.compute_psi(d) for n in xrange(self.N): Sn = d["S"][:, n].copy() psin = psi[:, n].copy() pn = logistic(psin) pn = np.clip(pn, 1e-32, 1 - 1e-32) xis = np.arange(1, xi_max + 1).astype(np.float) lp_xi = np.zeros(xi_max) nb_likelihood_xi(Sn, pn, xis, lp_xi) lp_xis[n] += lp_xi # lp_xi2 = (gammaln(Sn[:,None]+xis[None,:]) - gammaln(xis[None,:])).sum(0) # lp_xi2 += (xis[None,:] * np.log(1-pn)[:,None]).sum(0) # # assert np.allclose(lp_xi, lp_xi2) for n in xrange(self.N): self.xi[0, n] = xis[sample_discrete_from_log(lp_xis[n])]
def resample_c(self, network): """ Resample block assignments given the weighted adjacency matrix and the impulse response fits (if used) """ if self.C == 1: return A = network.A W = network.W # Sample each assignment in order for n1 in xrange(self.N): # Compute unnormalized log probs of each connection lp = np.zeros(self.C) # Prior from m lp += np.log(self.m) # Likelihood from network for cn1 in xrange(self.C): # Compute probability for each incoming and outgoing for n2 in xrange(self.N): cn2 = self.c[n2] if n2 != n1: # p(A[k,k'] | c) lp[cn1] += Bernoulli(self.p[cn1, cn2])\ .log_probability(A[n1,n2]).sum() # p(A[k',k] | c) lp[cn1] += Bernoulli(self.p[cn2, cn1])\ .log_probability(A[n2,n1]).sum() # p(W[k,k'] | c) lp[cn1] += ( A[n1, n2] * self.weight_models[cn1][cn2].log_likelihood( W[n1, n2, :])).sum() lp[cn1] += ( A[n2, n1] * self.weight_models[cn2][cn1].log_likelihood( W[n2, n1, :])).sum() else: # Self connection lp[cn1] += Bernoulli(self.p[cn1, cn1])\ .log_probability(A[n1,n1]).sum() lp[cn1] += ( A[n1, n1] * self.weight_models[cn1][cn1].log_likelihood( W[n1, n1, :])).sum() # Resample from lp self.c[n1] = sample_discrete_from_log(lp)
def _resample_c(self): from pybasicbayes.util.stats import sample_discrete_from_log kappa, omega = self.kappa, self.omega mu = kappa / omega sigmasq = 1./omega for n in xrange(self.N): lps = np.zeros(self.C) for i in xrange(self.C): lps[i] += np.sum(-0.5 * (self.psis[:,i] - mu[:,n])**2 / sigmasq[:,n]) self.c[n] = sample_discrete_from_log(lps)
def _resample_c(self): from pybasicbayes.util.stats import sample_discrete_from_log kappa, omega = self.kappa, self.omega mu = kappa / omega sigmasq = 1. / omega for n in xrange(self.N): lps = np.zeros(self.C) for i in xrange(self.C): lps[i] += np.sum(-0.5 * (self.psis[:, i] - mu[:, n])**2 / sigmasq[:, n]) self.c[n] = sample_discrete_from_log(lps)
def resample_c(self, network): """ Resample block assignments given the weighted adjacency matrix and the impulse response fits (if used) """ if self.C == 1: return A = network.A W = network.W # Sample each assignment in order for n1 in xrange(self.N): # Compute unnormalized log probs of each connection lp = np.zeros(self.C) # Prior from m lp += np.log(self.m) # Likelihood from network for cn1 in xrange(self.C): # Compute probability for each incoming and outgoing for n2 in xrange(self.N): cn2 = self.c[n2] if n2 != n1: # p(A[k,k'] | c) lp[cn1] += Bernoulli(self.p[cn1, cn2])\ .log_probability(A[n1,n2]).sum() # p(A[k',k] | c) lp[cn1] += Bernoulli(self.p[cn2, cn1])\ .log_probability(A[n2,n1]).sum() # p(W[k,k'] | c) lp[cn1] += (A[n1,n2] * self.weight_models[cn1][cn2] .log_likelihood(W[n1,n2,:])).sum() lp[cn1] += (A[n2, n1] * self.weight_models[cn2][cn1] .log_likelihood(W[n2,n1,:])).sum() else: # Self connection lp[cn1] += Bernoulli(self.p[cn1, cn1])\ .log_probability(A[n1,n1]).sum() lp[cn1] += (A[n1, n1] * self.weight_models[cn1][cn1] .log_likelihood(W[n1,n1,:])).sum() # Resample from lp self.c[n1] = sample_discrete_from_log(lp)
def resample(self): al, o = np.log(self.alpha_0), self.obs_distn self.z = ma.masked_array(self.z, mask=np.zeros(self.z.shape)) model = self.model for n in np.random.permutation(self.data.shape[0]): # mask out n self.z.mask[n] = True # form the scores and sample them ks = list(model._get_occupied()) scores = np.array([ np.log(model._get_counts(k))+ o.log_predictive(self.data[n],model._get_data_withlabel(k)) \ for k in ks] + [al + o.log_marginal_likelihood(self.data[n])]) idx = sample_discrete_from_log(scores) if idx == scores.shape[0] - 1: self.z[n] = self._new_label(ks) else: self.z[n] = ks[idx] # sample # note: the mask gets fixed by assigning into the array self.z[n] = sample_discrete_from_log(np.array(scores))
def resample_c(self, A): """ Resample block assignments given the weighted adjacency matrix and the impulse response fits (if used) """ from pybasicbayes.util.stats import sample_discrete_from_log if self.C == 1: return # Sample each assignment in order for n1 in xrange(self.N): # Compute unnormalized log probs of each connection lp = np.zeros(self.C) # Prior from m lp += np.log(self.m) # Likelihood from network for cn1 in xrange(self.C): # Compute probability for each incoming and outgoing for n2 in xrange(self.N): cn2 = self.c[n2] if n2 == n1: # If we are special casing the self connections then # we can just continue if n1==n2 since its weight has # no bearing on the cluster assignment if self.special_case_self_conns: continue else: lp[cn1] += A[n1,n1] * np.log(self.p[cn1,cn1]) + \ (1-A[n1,n1]) * np.log(1-self.p[cn1,cn1]) else: # p(An1,n2] | c) lp[cn1] += A[n1,n2] * np.log(self.p[cn1,cn2]) + \ (1-A[n1,n2]) * np.log(1-self.p[cn1,cn2]) # p(A[n2,n1] | c) lp[cn1] += A[n2,n1] * np.log(self.p[cn2,cn1]) + \ (1-A[n2,n1]) * np.log(1-self.p[cn2,cn1]) # Resample from lp self.c[n1] = sample_discrete_from_log(lp)
def resample_logseriesaug(self,data=[],niter=20): # an alternative algorithm, kind of opaque and no advantages... if getdatasize(data) == 0: self.p = np.random.beta(self.alpha_0,self.beta_0) self.r = np.random.gamma(self.k_0,self.theta_0) else: data = flattendata(data) N = data.shape[0] logF = self.logF L_i = np.zeros(N) data_nz = data[data > 0] for itr in range(niter): logR = np.arange(1,logF.shape[1]+1)*np.log(self.r) + logF L_i[data > 0] = sample_discrete_from_log(logR[data_nz-1,:data_nz.max()],axis=1)+1 self.r = np.random.gamma(self.k_0 + L_i.sum(), 1/(1/self.theta_0 - np.log(1-self.p)*N)) self.p = np.random.beta(self.alpha_0 + data.sum(), self.beta_0 + N*self.r) return self
def resample(self, data): if not isinstance(data, list): assert isinstance(data, tuple) and len(data) == 2, \ "datas must be an (x,y) tuple or a list of such tuples" data = [data] # Compute the log likelihood under each mixture component and # assign datapoints accordingly zs = [] for xy in data: lls = np.array([r.log_likelihood(xy) for r in self.regressions]) from pybasicbayes.util.stats import sample_discrete_from_log zs.append(sample_discrete_from_log(lls, axis=0)) # Sample each mixture component with its assigned data for m in range(self.M): data_m = [(x[z == m], y[z == m]) for (x, y), z in zip(data, zs)] self.regressions[m].resample(data_m)
def resample_c(self, A, W): """ Resample block assignments given the weighted adjacency matrix and the impulse response fits (if used) """ if self.C == 1: return # Sample each assignment in order for k in range(self.K): # Compute unnormalized log probs of each connection lp = np.zeros(self.C) # Prior from m lp += np.log(self.m) # Likelihood from network for ck in range(self.C): c_temp = self.c.copy().astype(np.int) c_temp[k] = ck # p(A[k,k'] | c) lp[ck] += Bernoulli(self.p[ck, c_temp])\ .log_probability(A[k,:]).sum() # p(A[k',k] | c) lp[ck] += Bernoulli(self.p[c_temp, ck])\ .log_probability(A[:, k]).sum() # p(W[k,k'] | c) lp[ck] += (A[k,:] * Gamma(self.kappa, self.v[ck, c_temp])\ .log_probability(W[k,:])).sum() # p(W[k,k'] | c) lp[ck] += (A[:, k] * Gamma(self.kappa, self.v[c_temp, ck])\ .log_probability(W[:, k])).sum() # TODO: Subtract of self connection since we double counted # TODO: Get probability of impulse responses g # Resample from lp self.c[k] = sample_discrete_from_log(lp)
def resample_c(self, A, W): """ Resample block assignments given the weighted adjacency matrix and the impulse response fits (if used) """ if self.C == 1: return # Sample each assignment in order for k in range(self.K): # Compute unnormalized log probs of each connection lp = np.zeros(self.C) # Prior from m lp += np.log(self.m) # Likelihood from network for ck in range(self.C): c_temp = self.c.copy().astype(np.int) c_temp[k] = ck # p(A[k,k'] | c) lp[ck] += Bernoulli(self.p[ck, c_temp])\ .log_probability(A[k,:]).sum() # p(A[k',k] | c) lp[ck] += Bernoulli(self.p[c_temp, ck])\ .log_probability(A[:,k]).sum() # p(W[k,k'] | c) lp[ck] += (A[k,:] * Gamma(self.kappa, self.v[ck, c_temp])\ .log_probability(W[k,:])).sum() # p(W[k,k'] | c) lp[ck] += (A[:,k] * Gamma(self.kappa, self.v[c_temp, ck])\ .log_probability(W[:,k])).sum() # TODO: Subtract of self connection since we double counted # TODO: Get probability of impulse responses g # Resample from lp self.c[k] = sample_discrete_from_log(lp)
def _collapsed_resample_a(self, J_prior, h_prior, J_post, h_post): """ """ N, B, rho = self.N, self.B, self.rho perm = npr.permutation(self.N) ml_prev = self._marginal_likelihood(J_prior, h_prior, J_post, h_post) for n in perm: # TODO: Check if rho is deterministic # Compute the marginal prob with and without A[m,n] lps = np.zeros(2) # We already have the marginal likelihood for the current value of a[m] # We just need to add the prior v_prev = int(self.a[n]) lps[v_prev] += ml_prev lps[v_prev] += v_prev * np.log( rho[n]) + (1 - v_prev) * np.log(1 - rho[n]) # Now compute the posterior stats for 1-v v_new = 1 - v_prev self.a[n] = v_new ml_new = self._marginal_likelihood(J_prior, h_prior, J_post, h_post) lps[v_new] += ml_new lps[v_new] += v_new * np.log( rho[n]) + (1 - v_new) * np.log(1 - rho[n]) # Sample from the marginal probability # max_lps = max(lps[0], lps[1]) # se_lps = np.sum(np.exp(lps-max_lps)) # lse_lps = np.log(se_lps) + max_lps # ps = np.exp(lps - lse_lps) # v_smpl = npr.rand() < ps[1] v_smpl = sample_discrete_from_log(lps) self.a[n] = v_smpl # Cache the posterior stats and update the matrix objects if v_smpl != v_prev: ml_prev = ml_new
def resample(self, data): if not isinstance(data, list): assert isinstance(data, tuple) and len(data) == 2, \ "datas must be an (x,y) tuple or a list of such tuples" data = [data] # Compute the log likelihood under each mixture component and # assign datapoints accordingly zs = [] for x, y in data: # If we've only been given the first K-1 dimensions of y, # concatenate with the last one assert y.ndim == 2 and x.shape[0] == y.shape[0] if y.shape[1] == self.K - 1: y = np.column_stack((y, self.N - y.sum(1))) lls = [] for m in range(self.M): # Undo the permutation # By definition, y_t ~ P pi_t where pi_t is a column vector # equivalently, y ~ pi P^T when y and pi are T x K (i.e. y_t and pi_t are row vectors) # To undo the permutation, right multiply by P = (P^T)^{-1} y_unperm = y.dot(self.Ps[m]) ll_m = self.regressions[m].log_likelihood( (x, y_unperm[:, :-1])) ll_m += np.log(self.weights[m]) lls.append(ll_m) lls = np.array(lls) from pybasicbayes.util.stats import sample_discrete_from_log zs.append(sample_discrete_from_log(lls, axis=0)) # Sample each mixture component with its assigned data for m in range(self.M): data_m = [(x[z == m], y[z == m]) for (x, y), z in zip(data, zs)] self.regressions[m].resample(data_m) # Sample mixture weights alpha_hat = self.alpha + sum( [np.bincount(z, minlength=self.M) for z in zs]) self.weights = npr.dirichlet(alpha_hat)
def resample(self, data): if not isinstance(data, list): assert isinstance(data, tuple) and len(data) == 2, \ "datas must be an (x,y) tuple or a list of such tuples" data = [data] # Compute the log likelihood under each mixture component and # assign datapoints accordingly zs = [] for x,y in data: # If we've only been given the first K-1 dimensions of y, # concatenate with the last one assert y.ndim == 2 and x.shape[0] == y.shape[0] if y.shape[1] == self.K - 1: y = np.column_stack((y, self.N - y.sum(1))) lls = [] for m in range(self.M): # Undo the permutation # By definition, y_t ~ P pi_t where pi_t is a column vector # equivalently, y ~ pi P^T when y and pi are T x K (i.e. y_t and pi_t are row vectors) # To undo the permutation, right multiply by P = (P^T)^{-1} y_unperm = y.dot(self.Ps[m]) ll_m = self.regressions[m].log_likelihood((x, y_unperm[:, :-1])) ll_m += np.log(self.weights[m]) lls.append(ll_m) lls = np.array(lls) from pybasicbayes.util.stats import sample_discrete_from_log zs.append(sample_discrete_from_log(lls, axis=0)) # Sample each mixture component with its assigned data for m in range(self.M): data_m = [(x[z==m], y[z==m]) for (x,y),z in zip(data, zs)] self.regressions[m].resample(data_m) # Sample mixture weights alpha_hat = self.alpha + sum([np.bincount(z, minlength=self.M) for z in zs]) self.weights = npr.dirichlet(alpha_hat)
def _collapsed_resample_a(self, J_prior, h_prior, J_post, h_post): """ """ N, B, rho = self.N, self.B, self.rho perm = npr.permutation(self.N) ml_prev = self._marginal_likelihood(J_prior, h_prior, J_post, h_post) for n in perm: # TODO: Check if rho is deterministic # Compute the marginal prob with and without A[m,n] lps = np.zeros(2) # We already have the marginal likelihood for the current value of a[m] # We just need to add the prior v_prev = int(self.a[n]) lps[v_prev] += ml_prev lps[v_prev] += v_prev * np.log(rho[n]) + (1-v_prev) * np.log(1-rho[n]) # Now compute the posterior stats for 1-v v_new = 1 - v_prev self.a[n] = v_new ml_new = self._marginal_likelihood(J_prior, h_prior, J_post, h_post) lps[v_new] += ml_new lps[v_new] += v_new * np.log(rho[n]) + (1-v_new) * np.log(1-rho[n]) # Sample from the marginal probability # max_lps = max(lps[0], lps[1]) # se_lps = np.sum(np.exp(lps-max_lps)) # lse_lps = np.log(se_lps) + max_lps # ps = np.exp(lps - lse_lps) # v_smpl = npr.rand() < ps[1] v_smpl = sample_discrete_from_log(lps) self.a[n] = v_smpl # Cache the posterior stats and update the matrix objects if v_smpl != v_prev: ml_prev = ml_new
def resample_c(self, A, W): """ Resample block assignments given the weighted adjacency matrix """ from pybasicbayes.util.stats import sample_discrete_from_log if self.C == 1: return Abool = A.astype(np.bool) c_init = self.c.copy() def _evaluate_lkhd_slow(n1, cn1): ll = 0 # Compute probability for each incoming and outgoing for n2 in xrange(self.N): cn2 = self.c[n2] # If we are special casing the self connections then # we can just continue if n1==n2 since its weight has # no bearing on the cluster assignment if n2 == n1: # Self connection if self.special_case_self_conns: continue ll += self._gaussians[cn1][cn1].log_likelihood(W[n1,n1]).sum() else: # p(W[n1,n2] | c) and p(W[n2,n1] | c), only if there is a connection if A[n1,n2]: ll += self._gaussians[cn1][cn2].log_likelihood(W[n1,n2]).sum() if A[n2,n1]: ll += self._gaussians[cn2][cn1].log_likelihood(W[n2,n1]).sum() return ll def _evaluate_lkhd(n1, cn1): chat = self.c.copy() chat[n1] = cn1 # Compute log lkhd for each pair of blocks ll = 0 for c2 in xrange(self.C): # Outgoing connections out_mask = (chat == c2) & Abool[n1,:] if self.special_case_self_conns: out_mask[n1] = False ll += self._gaussians[cn1][c2].log_likelihood(W[n1,out_mask]).sum() # Handle incoming connections # Exclude self connection since it would have been handle above in_mask = (chat == c2) & Abool[:,n1] in_mask[n1] = False ll += self._gaussians[c2][cn1].log_likelihood(W[in_mask,n1]).sum() return ll # Sample each assignment in order for n1 in xrange(self.N): # Compute unnormalized log probs of each connection lp = np.zeros(self.C) # Prior from m lp += np.log(self.m) # Likelihood from network for cn1 in xrange(self.C): ll = _evaluate_lkhd(n1, cn1) # ll_slow = _evaluate_lkhd_slow(n1, cn1) # assert np.allclose(ll,ll_slow) lp[cn1] += ll # Resample from lp self.c[n1] = sample_discrete_from_log(lp)
def resample(self): scores = self._compute_scores() self.z, lognorms = sample_discrete_from_log(scores,axis=1,return_lognorms=True) self._normalizer = lognorms[~np.isnan(self.data).any(1)].sum()
def resample(self): scores = self._compute_scores() self.z, lognorms = sample_discrete_from_log(scores, axis=1, return_lognorms=True) self._normalizer = lognorms[~np.isnan(self.data).any(1)].sum()
def resample_c(self, A, W): """ Resample block assignments given the weighted adjacency matrix """ from pybasicbayes.util.stats import sample_discrete_from_log if self.C == 1: return Abool = A.astype(np.bool) c_init = self.c.copy() def _evaluate_lkhd_slow(n1, cn1): ll = 0 # Compute probability for each incoming and outgoing for n2 in xrange(self.N): cn2 = self.c[n2] # If we are special casing the self connections then # we can just continue if n1==n2 since its weight has # no bearing on the cluster assignment if n2 == n1: # Self connection if self.special_case_self_conns: continue ll += self._gaussians[cn1][cn1].log_likelihood( W[n1, n1]).sum() else: # p(W[n1,n2] | c) and p(W[n2,n1] | c), only if there is a connection if A[n1, n2]: ll += self._gaussians[cn1][cn2].log_likelihood( W[n1, n2]).sum() if A[n2, n1]: ll += self._gaussians[cn2][cn1].log_likelihood( W[n2, n1]).sum() return ll def _evaluate_lkhd(n1, cn1): chat = self.c.copy() chat[n1] = cn1 # Compute log lkhd for each pair of blocks ll = 0 for c2 in xrange(self.C): # Outgoing connections out_mask = (chat == c2) & Abool[n1, :] if self.special_case_self_conns: out_mask[n1] = False ll += self._gaussians[cn1][c2].log_likelihood( W[n1, out_mask]).sum() # Handle incoming connections # Exclude self connection since it would have been handle above in_mask = (chat == c2) & Abool[:, n1] in_mask[n1] = False ll += self._gaussians[c2][cn1].log_likelihood(W[in_mask, n1]).sum() return ll # Sample each assignment in order for n1 in xrange(self.N): # Compute unnormalized log probs of each connection lp = np.zeros(self.C) # Prior from m lp += np.log(self.m) # Likelihood from network for cn1 in xrange(self.C): ll = _evaluate_lkhd(n1, cn1) # ll_slow = _evaluate_lkhd_slow(n1, cn1) # assert np.allclose(ll,ll_slow) lp[cn1] += ll # Resample from lp self.c[n1] = sample_discrete_from_log(lp)