Ejemplo n.º 1
0
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
Ejemplo n.º 2
0
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
Ejemplo n.º 3
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
Ejemplo n.º 4
0
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
Ejemplo n.º 5
0
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