1
$\begingroup$

Having some problems with the ABC SMC algorithm. I'm trying to implement the methods taken from here: Simulation-based model selection for dynamical systems in systems and population biology

How do weights scale down with increasing parameters?

I am having problems with this part of the weight calculation, w(m ,theta) . My current implementation is giving a higher weighting to particles with more parameters, which should not be the case.

enter image description here enter image description here

In the function S, KP is a perturbation kernel that describes the probability of particle having come from the previous population. A small KP makes the denominator small, and therefore the overall weighting high.

enter image description here

enter image description here

Is it not the case that the more parameters that are present, the smaller KP becomes? I can't see anywhere in the paper that describes how the weighting is adjusted according to the number of parameters.

I've written a small example to illustrate the problem, and removed parts involving model perturbation that are included in the figures. Model a has one parameter, model b has six parameters. We assume they are all accepted and given weights. What am I missing to make the weighting proportional to the number of parameters?

def get_pdf_uniform(lower_bound, upper_bound, x):
    if (x > upper_bound) or (x < lower_bound):
        print(x)
        print(upper_bound)
        print(lower_bound)
        return 0.0

    else:
        return (1 / (upper_bound - lower_bound))


def weight_problem_example():
    # Two priors, one small one large
    prior_a = [[1, 5]]
    model_a = "a"

    prior_b = [[1, 5], [1, 5], [1, 5], [1, 5], [1, 5], [1, 5]]
    model_b = "b"

    # Previous population had equal weights
    prev_weight_a = 0.5
    prev_weight_b = 0.5

    # Sampled parameters are within prior range
    particle_a_params = [np.random.uniform(x[0], x[1]) for x in prior_a]
    particle_b_params = [np.random.uniform(x[0], x[1]) for x in prior_b]

    particle_a_prev_params = [np.random.uniform(x[0], x[1]) for x in prior_a]
    particle_b_prev_params = [np.random.uniform(x[0], x[1]) for x in prior_b]

    packed_a = [prior_a, particle_a_params, particle_a_prev_params, prev_weight_a, model_a]
    packed_b = [prior_b, particle_b_params, particle_b_prev_params, prev_weight_b, model_b]


    particles = []
    particles = particles + [packed_a for x in range(1000)]
    particles =  particles + [packed_b for x in range(1000)]

    model_a_weights = []
    model_b_weights = []
    for part in particles:
        # unpack particle data
        prior = part[0]
        params = part[1]
        prev_params = part[2]
        prev_weight = part[3]
        model = part[4]

        # Numerator
        particle_prior_prob = 1
        for idx, p in enumerate(params):
            particle_prior_prob = particle_prior_prob * get_pdf_uniform(prior[idx][0], prior[idx][1], p)

        # Assume equal model probability
        particle_prior_prob = particle_prior_prob * 1


        # Denominator, assuming we only have two particles
        s = 0
        for theta in particles:
            if theta[4] == model:
                theta_prior = part[0]
                theta_params = part[1]
                theta_prev_params = part[2]
                theta_prev_weight = part[3]
                theta_model = part[4]

                k_prob = 1
                for theta_idx, theta_p in enumerate(theta_prev_params):
                    # get parameter kernel pdf
                    k_prob = k_prob * get_pdf_uniform(
                        theta_p - theta_prior[theta_idx][0]*2, 
                        theta_p + theta_prior[theta_idx][1]*2, 
                        params[theta_idx])                    

                # print(s)
                s += (theta_prev_weight * k_prob)

        part_weight = particle_prior_prob/s

        if model == "a":
            model_a_weights.append(part_weight)

        if model == "b":
            model_b_weights.append(part_weight)

    print(np.mean(model_a_weights))
    print(np.mean(model_b_weights))
$\endgroup$

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.