First I have to apologize because I could not write this questions as concise as I’d like to.
My goal is to implement an interface for optimisation/inference where the user can keep certain parameters fix (i.e. not inferred). Additionally, I would like that the user has only to deal with parameters in the form of
To make it more concrete assume the following example:
using TransformVariables # 1) Define model # The transform is used for flattening and transformation of the parameters tt = as(( a = asℝ₊, b = asℝ₊, w = UnitVector(5) )) function model(p::NamedTuple, x) p.a + p.b * x'*p.w end model(v::AbstractArray, x) = model(tt(v), x) # 2) User can call model with NamedTuple p = (a = 11.1, b = 2.1, w = [0.2, 0.2, 0.2, 0.2, 0.2]) x = ones(5) model(p, x) # 3) ... and optimizer/sampler routines can call model with V ∈ R^n v = randn(6) model(v, x) # 4) we can define a function to fit the model function fit_model(p_init::NamedTuple) v_init = inverse(tt, p_init) # convert into vector v_optimal = optim(v_init, model, ...) # some optimizer routine, that returns a vector p_optimal = tt(v_optimal) # user gets back a nice tuple return p_optimal end # The user provides inital parameters in # the "natural" form, i.e. as NamedTuple p_init = (a = 3.1, b = 5.1, w = [0.2, 0.2, 0.2, 0.2, 0.2]) fit_model(p_init) # ... and gets a Tuple back. All good so far!
Desired user interface
Now, how can I write a extended version
fit_model2 that can be used as follows:
# The idea is that the user has to use only the NamedTuple format, i.e. p_init = (a = 3.1, b = 5.1, w = [0.2, 0.2, 0.2, 0.2, 0.2]) p_keep_fix = (a = false, b = true, w = [false, false, true, true, false]) fit_model2(p_init, p_keep_fix) # <- how to implement this?
I think the structure would look a bit like this. I’m stuck how I can write the ‘splice’ function
function fit_model2(p_init::NamedTuple, p_keep_fix::NamedTuple) # 1) Transform the initial parameters to R^n. v_init = inverse(tt, p_init) |> filter(is_not_fixed) # 2) transform the fixed values to R^n v_fix = inverse(tt, p_keep_fix) |> filter(is_fixed) # 3) Splice the fixed and not fixed parameters together in the # right order. It is not so easy to figure how many parameters are to be optimized, # as it depends also on the transformation! For example, p.w is # UnitVector so no parameters must be estimated if either 4 or 5 # values of p.w are fixed. # Then build function to optimize: function fopt(v) v' = splice(v, v_fix) model(v') end # 4) Optimize as usual v_opt = optim(v_init, fopt) # 5) combine fiexed and optimized parameters v_opt' = splice(v_opt, v_fix) # 6) user get a Named Tuple back return tt(v_opt') end
It seems an common and not very difficult problem. Looking forward to any ideas!