def inverse_sample_rvs(log_f, a, b, mesh_size=100): ''' Sample from a continuous univariate density using the inverse transform method. Args: log_f : (function) A function which computes the unnormalised of the density. a : (float) Left side of the support for the denstiy. b : (float) Right side of the support for the density. Kwargs: mesh_size : (int) How many points to use to approximate the integral for computing CDF. Returns: x : (float) Sampled value log_q : (float) The value of the density at x. ''' u = uniform_rvs(0, 1) log_u = log(u) step_size = (b - a) / mesh_size log_step_size = log(b - a) - log(mesh_size) knots = [i * step_size + a for i in range(0, mesh_size + 1)] mid_points = [(x_l + x_r) / 2 for x_l, x_r in zip(knots[:-1], knots[1:])] log_likelihood = [log_f(x) for x in mid_points] log_riemann_sum = [] for y in log_likelihood: log_riemann_sum.append(y + log_step_size) log_norm_const = log_sum_exp(log_riemann_sum) log_cdf = None for x, y in zip(mid_points, log_likelihood): log_q = y - log_norm_const log_partial_pdf_riemann_sum = log_q + log_step_size if log_cdf is None: log_cdf = log_partial_pdf_riemann_sum else: log_cdf = log_sum_exp([log_cdf, log_partial_pdf_riemann_sum]) if log_u < log_cdf: break return x, log_q
def bernoulli_rvs(p): ''' Return a Bernoulli distributed random variable. Args: p : (float) Probability of success. Returns: x : (int) Binary indicator of success/failure. ''' u = uniform_rvs(0, 1) if u <= p: return 1 else: return 0
def poisson_rvs(l): u = uniform_rvs(0, 1) log_u = log(u) i = 0 log_l = log(l) log_p = -l log_F = log_p while True: if log_u < log_F: return i log_p += log_l - log(i + 1) log_F = log_sum_exp([log_F, log_p]) i += 1
def discrete_rvs(p): ''' Sample a discrete (Categorical) random variable. Args: p : (list) Probabilities for each class from 0 to len(p) - 1 Returns: i : (int) Id of class sampled. ''' total = 0 u = uniform_rvs(0, 1) for i, p_i in enumerate(p): total += p_i if u < total: break return i
def binomial_rvs(n, p): ''' Sample a binomial distributed random variable. Args: n : (int) Number of trials performed. p : (int) Probability of success for each trial. Returns: x : (int) Number of successful trials. ''' if p > 0.5: return n - binomial_rvs(n, 1 - p) if p == 0: return 0 u = uniform_rvs(0, 1) log_u = log(u) log_c = log(p) - log(1 - p) i = 0 log_prob = n * log(1 - p) log_F = log_prob while True: if log_u < log_F: return i log_prob += log_c + log(n - i) - log(i + 1) log_F = log_sum_exp([log_F, log_prob]) i += 1