def log_important_ratio(approx, nsample): logp_func = approx.model.logp # in ADVI there are only 1 group approximation approx_group = approx.groups[0] if approx.short_name == "mean_field": mu_q = approx_group.params[0].eval() std_q = rho2sd(approx_group.params[1]).eval() logq_func = st.norm(mu_q, std_q) elif approx.short_name == "full_rank": packed_chol_q = approx_group.params[0] mu_q = approx_group.params[1].eval() dim = mu_q.shape[0] chol_q = pm.expand_packed_triangular( dim, packed_chol_q, lower=True).eval() cov_q = np.dot(chol_q, chol_q.T) logq_func = st.multivariate_normal(mu_q, cov_q) dict_to_array = approx_group.bij.map p_theta_y = [] q_theta = [] samples = approx.sample_dict_fn(nsample) # type: dict points = ({name: records[i] for name, records in samples.items()} for i in range(nsample)) for point in points: p_theta_y.append(logp_func(point)) q_theta.append(np.sum(logq_func.logpdf(dict_to_array(point)))) p_theta_y = np.asarray(p_theta_y) q_theta = np.asarray(q_theta) return p_theta_y, q_theta, p_theta_y - q_theta
def symbolic_logq_not_scaled(self): z0 = self.symbolic_initial std = rho2sd(self.rho) logdet = tt.log(std) logq = pm.Normal.dist().logp(z0) - logdet return logq.sum(range(1, logq.ndim))
def std(self): return rho2sd(self.rho)
def cov(self): var = rho2sd(self.rho)**2 if self.batched: return batched_diag(var) else: return tt.diag(var)
def __init__(self, rho=None, **kwargs): super(ScaleFlow, self).__init__(**kwargs) rho = self.add_param(rho, 'rho') self.scale = rho2sd(rho) self.shared_params = dict(rho=rho)
def random_global(self, size=None, no_rand=False): initial = self.initial(size, no_rand, l=self.global_size) sd = rho2sd(self.rho) mu = self.mean return sd * initial + mu
def cov(self): return tt.diag(rho2sd(self.rho)**2)
def symbolic_random_global_matrix(self): initial = self.symbolic_initial_global_matrix sd = rho2sd(self.rho) mu = self.mean return sd * initial + mu
def __init__(self, rho=None, **kwargs): super(ScaleFlow, self).__init__(**kwargs) rho = self.add_param(rho, 'rho') self.scale = rho2sd(rho) self.shared_params = dict(rho=rho)
def symbolic_random_global_matrix(self): initial = self.symbolic_initial_global_matrix sd = rho2sd(self.rho) mu = self.mean return sd * initial + mu
def cov(self): return tt.diag(rho2sd(self.rho)**2)