PairPlots.jl
Documentation for PairPlots.jl ↗
FlexiChains provides two ways to interact with PairPlots.jl.
pairplot()
Firstly, you can directly call pairplot(chn[, param_or_params]) on a FlexiChain. This is a convenience method which includes extra functionality for e.g. highlighting divergent transitions.
using DynamicPPL, Distributions, LinearAlgebra, FlexiChains
J = 8
y = [28, 8, -3, 7, -1, 1, 18, 12]
sigma = [15, 10, 16, 11, 9, 11, 10, 18]
@model function eightsch(J, y, sigma)
mu ~ Normal(0, 5)
tau ~ truncated(Cauchy(0, 5); lower=0)
theta ~ MvNormal(fill(mu, J), tau^2 * I)
for i in 1:J
y[i] ~ Normal(theta[i], sigma[i])
end
end
model = eightsch(J, y, sigma)
chn = FlexiChains._make_posterior_chain(model, 1000, 4)╭─FlexiChain (1000 iterations, 4 chains) ──────────────────────────────────────╮
│ ↓ iter = 1:1000 │
│ → chain = 1:4 │
│ │
│ Parameters (3) ── VarName │
│ Float64 mu, tau │
│ Vector{Float64} theta (8,) │
│ │
│ Extras (3) │
│ Float64 logprior, loglikelihood, logjoint │
╰──────────────────────────────────────────────────────────────────────────────╯When sampling with Turing's HMC or NUTS, the resulting chain will contain an Extra(:numerical_error) key, which is a Boolean indicating whether or not the transition was divergent. Because in this docs page we aren't actually sampling with Turing.jl, the chain above doesn't have this, so we'll add it in ourselves.
The following says: 'transform each sample of mu into a random Boolean, and store it in the Extra(:numerical_error) key'. (See the Modifying data section for more details on transform_values.)
# Make approximately 5% of the samples 'divergent'.
chn = FlexiChains.transform_values(
chn,
@varname(mu) => (_ -> rand() < 0.05) => FlexiChains.Extra(:numerical_error),
)╭─FlexiChain (1000 iterations, 4 chains) ──────────────────────────────────────╮
│ ↓ iter = 1:1000 │
│ → chain = 1:4 │
│ │
│ Parameters (3) ── VarName │
│ Float64 mu, tau │
│ Vector{Float64} theta (8,) │
│ │
│ Extras (4) │
│ Float64 logprior, loglikelihood, logjoint │
│ Bool numerical_error │
╰──────────────────────────────────────────────────────────────────────────────╯Carrying on with our plotting:
# Limit the parameters being plotted for readability
vns = [@varname(tau), @varname(theta[1]), @varname(theta[2])]
using PairPlots, CairoMakie
pairplot(chn, vns; divergences=:numerical_error)
Conversion to Series
For more low-level control, you can also convert a FlexiChain into a PairPlots.Series, so that you can combine it with other data or fixed values in custom plots.
# Just some random values.
expected_means = (tau=0.0, var"theta[1]"=2.5, var"theta[2]"=5.0)
pairplot(PairPlots.Series(chn[vns]), PairPlots.Truth(expected_means, label="True"))
Notice that Series(chn) will pool the samples in all four chains together. If you want to plot each chain separately, split them up into separate Series objects:
pairplot(
(
PairPlots.Series(chn[vns, chain=i], label="Chain $i") for
i in FlexiChains.chain_indices(chn)
)...,
PairPlots.Truth(expected_means, label="True"),
)
Docstrings
PairPlots.pairplot Function
PairPlots.pairplot(
chn::FlexiChain[, param_or_params];
args::Tuple=(),
pool_chains::Bool=false,
divergences=nothing,
divergences_kwargs::NamedTuple=(; markersize=3, color=:red),
kwargs...
)Create a pair plot for the given chain. Note that PairPlots.jl uses Makie.jl as its plotting backend, so you will additionally need to load a Makie backend (e.g. with using GLMakie or using CairoMakie) before calling this function.
If no parameters are specified, this will plot all parameters in the chain. Note that non-parameter, i.e. Extra, keys are excluded by default. If you want to plot all keys, you can explicitly pass all keys with pairplot(chn, :).
Keyword arguments
args: a tuple of additional arguments to pass toPairPlots.pairplot. This can be used to specify additional series to plot, for example.pool_chains: controls whether to pool all chains together into a single series, or to plot each chain separately.divergences: specifies a key name in the chain that contains a boolean array indicating which samples are divergences. If provided, divergent samples will be highlighted in the plot. Note that for HMC/NUTS chains sampled with Turing.jl, the key name for divergences is (as of Turing v0.43):numerical_error. By default this isnothing, which disables plotting of divergences (because not all chains will have this information).divergences_kwargs: aNamedTupleof keyword arguments which is eventually passed toMakie.scatter, which can be used to control the appearance of the points. Defaults to(; markersize=3, color=:red).
Other keyword arguments are passed to PairPlots.pairplot.
PairPlots.Series Type
PairPlots.Series(chn::FlexiChain; split_varnames=true, kwargs...)Create a PairPlots.Series from the given FlexiChain. The series data will contain one column for each key in the chain.
Note that this function will include all keys in the chain, including Extra keys. If you only want to include a subset of keys, you should first subset the chain, for example with chn[[key1, key2, ...]], and then pass that subsetted chain in.
If split_varnames is true, then parameters in the chain will be split into their constituent real-valued elements. This is necessary for plotting. In practice there should never be any reason for end users to set this to false, unless you already know that your chain contains only scalar variables and you want to avoid the cost of splitting the variable names again.