Converting to/from MCMCChains
You can convert FlexiChain objects to and from MCMCChains.Chains.
MCMCChains to FlexiChain
For example, let's make an MCMCChains object from a Turing model:
using DynamicPPL, MCMCChains, AbstractMCMC, Distributions, LinearAlgebra
@model function f()
x ~ Normal()
y ~ Bernoulli()
z ~ MvNormal(zeros(2), I)
end
# Sample from the prior, and tack on a random log-probability.
samples = [DynamicPPL.ParamsWithStats(rand(f()), (; logp=rand())) for _ in 1:100, _ in 1:3]
# Bundle them into a Chain
mc = AbstractMCMC.from_samples(MCMCChains.Chains, samples)Chains MCMC chain (100×5×3 Array{Float64, 3}):
Iterations = 1:1:100
Number of chains = 3
Samples per chain = 100
parameters = x, y, z[1], z[2]
internals = logp
Use `describe(chains)` for summary statistics and quantiles.The most naive conversion will create a FlexiChain{Symbol}, since that is the key type of MCMCChains:
using FlexiChains
FlexiChains.from_mcmcchains(mc)╭─FlexiChain (100 iterations, 3 chains) ───────────────────────────────────────╮
│ ↓ iter = [1 … 100] │
│ → chain = [1, 2, 3] │
│ │
│ Parameters (4) ── Symbol │
│ Float64 x, y, z[1], z[2] │
│ │
│ Extras (1) │
│ Float64 logp │
╰──────────────────────────────────────────────────────────────────────────────╯However, notice that we don't have the vector structure of the parameter z, and instead have two different scalar parameters z[1] and z[2]. We can add the structure back by specifying a set of keys as the second argument:
using FlexiChains: Parameter, Extra
fc = FlexiChains.from_mcmcchains(
mc,
(
Parameter(@varname(x)),
Parameter(@varname(y)),
Parameter(@varname(z)) => (2,),
Extra(:logp),
),
)╭─FlexiChain (100 iterations, 3 chains) ───────────────────────────────────────╮
│ ↓ iter = [1 … 100] │
│ → chain = [1, 2, 3] │
│ │
│ Parameters (3) ── VarName │
│ Float64 x, y │
│ Vector{Float64} z (2,) │
│ │
│ Extras (1) │
│ Float64 logp │
╰──────────────────────────────────────────────────────────────────────────────╯By passing VarName parameters instead of Symbols, we can 'upconvert' this into a VNChain rather than a SymChain (which is harder to index into, for example, if you want to get z[1]). Furthermore, by specifying the shape of z as (2,), we can recover the vector structure of that parameter. In general array-valued parameters can be 'recovered' in this way, but more complicated structs cannot be.
Order of parameters
The parameters provided as the second argument must add up to exactly the same number of columns in the original MCMCChains object, and must also be in the same order as they appear in the original object. The order of the parameters in an MCMCChains object is not always obvious, so be careful with this.
After that, you might also want to convert y back into a Boolean:
fc = FlexiChains.transform_values(fc, @varname(y) => Bool)╭─FlexiChain (100 iterations, 3 chains) ───────────────────────────────────────╮
│ ↓ iter = [1 … 100] │
│ → chain = [1, 2, 3] │
│ │
│ Parameters (3) ── VarName │
│ Float64 x │
│ Bool y │
│ Vector{Float64} z (2,) │
│ │
│ Extras (1) │
│ Float64 logp │
╰──────────────────────────────────────────────────────────────────────────────╯FlexiChain to MCMCChains
The conversion from FlexiChain to MCMCChains is much more straightforward. Since MCMCChains just throws away all the information, there is no behaviour to customise:
MCMCChains.Chains(fc)Chains MCMC chain (100×5×3 Array{Float64, 3}):
Iterations = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100]
Number of chains = 3
Samples per chain = 100
parameters = x, y, z[1], z[2]
internals = logp
Use `describe(chains)` for summary statistics and quantiles.Docstrings
FlexiChains.from_mcmcchains Function
FlexiChains.from_mcmcchains(chains::MCMCChains.Chains, key_spec=nothing)Convert an MCMCChains.Chains object to a FlexiChain.
If key_spec is not provided, parameters in the :parameters section are stored as Parameter{Symbol} keys and all other sections (e.g. :internals) as Extra{Symbol} keys, giving a FlexiChain{Symbol}.
If key_spec is provided, it is passed directly to the FlexiChain from-array constructor. The key type of the resulting FlexiChain is inferred from key_spec. You can pass this argument if you want to override the parameter names stored in the MCMCChains.Chains object, or to group array-valued parameters together, for example.
Please see the FlexiChain constructor documentation for details on what key_spec is allowed.
Iteration indices, chain indices, and per-chain sampling times are inherited from the MCMCChains.Chains object. If the MCMCChains.Chains object contains a samplerstate field in its info NamedTuple, this is also preserved in the resulting FlexiChain.
MCMCChains.Chains Method
MCMCChains.Chains(chain::FlexiChain)Convert a FlexiChain to an MCMCChains.Chains object.
Array-valued parameters are split up into their individual real-valued elements, much like the output that you get directly from sampling with Turing + MCMCChains.
source