Logp questions, synthetic dataset to evaluate modeling

This happens because find_MAP ignores the jacobian. You should get the same if you do compile_logp(jacobian=False)(map)

Yes, although the default sampler adds an amount of jittering around these values. You can choose another init method that does not.

Hmm we should probably add a utility to do that. For now you would need to do something manual like

import pymc as pm

with pm.Model() as m:
    x = pm.Uniform("x")
    y = pm.Dirichlet("y", [x, x])
    
transformed_rvs = []
for free_rv in m.free_RVs:
    transform = m.rvs_to_transforms.get(free_rv) 
    if transform is None:
        transformed_rvs.append(free_rv)
    else:
        transformed_rv = transform.forward(free_rv, *free_rv.owner.inputs)
        transformed_rvs.append(transformed_rv)
        
fn = m.compile_fn(inputs=m.free_RVs, outs=transformed_rvs)
res = fn({"x": .75, "y": [0.3, 0.7]})
res_dict = {
    "x_interval__": res[0],
    "y_simplex__": res[1],
}
print(res_dict)
# {'x_interval__': array(1.09861229), 'y_simplex__': array([-0.42364893])}

# Going the other way around is easier:
# unobserved_value_vars includes the original variables and deterministics, so you have
# to pick the outputs manually. Or you could look into the source code and adapt to return only what you need.
fn_inv = m.compile_fn(outs=m.unobserved_value_vars)
res = fn_inv(res_dict)
res_dict = {
    "x": res[2],
    "y": res[3]
}
print(res_dict)
# {'x': array(0.75), 'y': array([0.3, 0.7])}

Alternatively if you don’t care about transforms after you fit, you could recreate your model with all variables (transform=None), so that things like the simplex__ don’t show up. Then you will be able to use the traces to evaluate the logp from model.compile_logp() out of the box.

1 Like