Thanks for all the answers. Another option I found is DynamicPPL.syms(DynamicPPL.VarInfo(m)) (but I’m not sure how advisable it is to use these unexported DynamicPPL methods).
Uhh… good question! It seems to be working as expected with the order from DynamicPPL.syms(DynamicPPL.VarInfo(m)). It’s also the order of the data in the chain’s underlying AxisArrays (see ch.value).
I wonder what the ch.name_map.parameters order is about… Just displaying the chain (display(ch)) shows this order in the header, and the other order in the summary stats:
There really needs to be a public API for this. A lot of examples have 1 to 10 parameters, and rely on people entering stuff by hand, but I work with models with 2000 parameters easily (let’s say one parameter for each person in a survey or whatever), and if I want to do initialization or describe a complex Gibbs update (ie. update all the discrete parameters with one kind of update, and some of the continuous parameters with a diffusive update, and others with NUTS) then you need to do stuff programmatically.
Of course, the provided solution works, but it should be documented somewhere and if it’s not intended to be the public API why not create a public API.
So yeah, years later, is there an “approved” way to get the names of the parameters?
Specifically I’m using a Turing model to construct a custom “tempered model” struct which just uses a LogDensityFunction struct to evaluate the logdensity of the turing model and divides by a given constant temperature. Then I’m slice-sampling this model, and I get a vector of SliceSampling.Transition objects. I want to manually construct a Chains object and I want to know what names I should put for each dimension…
It’s been a while since I messed with it, but IIRC there are some methods in the MCMCChains package for getting parameter names from output, e.g., names(chains::Chains) or the like.
It is beginning to look like the easiest way for me though is to simply sample a single sample from the underlying Turing model, and then use the names there to construct the chain from the slice sampling transitions
I see that turing does some stuff in _params_to_array inside src/mcmc/inference.jl to get these names, and it’s nontrivial voodoo.
I don’t know if it preserves the order you want for initialization (it seems to), but you can also call keys(rand(model)), which it at least doesn’t have the overhead of constructing the chains object, so it feels less annoying.
Purely because I was curious myself, and because I sometimes would also like a way to easily extract coefficients without needing to create mock data or actually call sample, here’s a horrible hacky (and probably fragile) function that returns the parameters, given a model and a tuple listing the data variables in the model.
It instantiates the model with data as missing. A rand call creates a Dict with keys that tell us all the variables in the model. Then filter is used to remove the data variables, leaving only the parameters.
# 'model' is a Turing model before data has been passed
# 'data_args' is a tuple of the names of the data
# (e.g., non-parameter) variables in your model
function parameters(model, data_args)
# Number of variables that aren't parameters
n_data_params = length(data_args)
# Filter out the variables that represent data
filter(a -> ∉(a, data_args), keys(rand((model)(fill(missing, n_data_params)...))))
end