Recording an MCMC Chain

I’ve written my own MCMC code. MCMCChains provides some helper functions wrt working with already completed chains.

As I iterate through the chain, what is the best way to store the each pass? E.g., if I complete non-burn pass 1757/10,000, and state contains vectors and scalars, say state is (;a=3.0, b=[4.0,6.0,7.0]), should I just push the draws to a DataFrame, or is there a better purpose-built solution?

Thanks!

Without code it is hard to answer. But my advice is to allocate the whole data frame before running anything and then filling it instead of pushing.

Code @lrnv :

function recordstate(;i,state,records)
  #put state into records
end

records = #some data type
recordstate(;i=1757, state=(;a=3.0, b=[4.0,6.0,7.0]),records)

Yes, that’ll work.

What I would do is have record preallocated (maybe with a bunch of zeros) before launching the chain.

1 Like

Isn’t there some actual API for pushing new values into the chain itself rather than producing some intermediate data structure

2 Likes

@dlakelan That would be great, but I can’t seem to find it in the docs- am I missing something obvious?

It looks like even the AdvancedMH creates an intermediate structure that subtypes AbstractTransition, then all at once bundles the samples afterwards AdvancedMH.jl/mcmcchains-connect.jl at master · TuringLang/AdvancedMH.jl · GitHub

1 Like

Might just be a case where a standardized solution is more trouble than it is worth. To be fair, it is not like an intermediate structure is a huge burden to code up.

After some additional experimentation, it does seem possible to keep a handle to the underlying arrays in the chain e.g. a=rand(10); c=Chains(a,:a); creates the chain without copying. Then indexing directly into the three dimensional arrays seems to work (e.g. c[2,:a,1]=1.0) .

A bit cumbersome but serviceable if needed. However, seems like the interface intends the user to convert at the end so I might just do that, especially since I’m not sure how the copying/referencing will work in future releases.

In fact it might well be less code burden than trying to fill in an array… But it is a lot of memory, particularly if you’re doing something like sampling 10k samples in 4 chains of a model with 10k parameters.

1 Like

Yeah- I ended up creating a wrapper object around the chain instead of an intermediate object. The wrapper contains views for accessing the chains for each of my parameters. Then I overloaded getproperty so I can use the “.” syntax for further ease of access- best of all I can still use the MCMCChain analytics without needing to create a new object.

Thanks for helping me think this through.