Variable States¶
Rationale behind states¶
Being geared towards statistics, Klara variables include parameters, data, transformations and constants, the specifics of
which will be delineated in Variables. A variable, be it stochastic or deterministic, can take a value, that is it can
have a state. Variables and their states are maintained in two distinct type systems in Klara.
The functionality of a variable is enclosed by its type instance. For a example, a typical parameter consists of its probability distribution, log-likelihood or log-prior fields.
It is possible to store the value of a multivariate variable in a vector. However, it might be required to save additional information. For example, the value of a parameter’s log-likelihood and associated gradient might be of interest. Variable state types exist to accommodate such states that comprise two or more entities.
From an object-oriented programming (OOP) standpoint, variable types correspond to methods while variable state types
constitute data members. Klara does not merge the functional and data components into a single type, which would had been
the analogous of a class in OOP terms. The main reasoning behind Klara’s compartmentalization of variables and their states is
code reusability. For instance, it becomes possible for different variables to share the same state type; more generally,
adhering to Julia’s multiple dispatch is facilitated.
Moreover, keeping states separate from variables helps cater to user-specific problems. Existing functionality can be deployed on user-defined states tailored to the problem at hand.
Built-in states¶
The state type system comprises two abstract and other non-abstract types. Listing 1 displays the
hierarchy of built-in state types. The two abstract types are VariableState and its sub-type ParameterState. The
non-abstract states put forward sensible defaults aimed at covering conventional use-cases. Klara’s existing functionality
relies on these defaults, yet it is possible to extend the package by defining custom state types.
Variable states are categorized as univariate or multivariate. Parameter states are further classified as discrete or
continuous. To make these distinctions, parametric abstract state types are employed by importing the VariateForm and
ValueSupport classification scheme from Distributions. Every possible category is designated a unique non-abstract
state type; for instance, BasicContMuvParameterState hosts a continuous multivariate parameter state.
The most common field, appearing in all built-in non-abstract state types, is called value. For example, in the context
of MCMC, value would hold the current or proposed state at each iteration of the sampler. Each state type and its
associated methods will be elaborated in the following sections.
VariableState
|
+-- BasicUnvVariableState
|
+-- BasicMuvVariableState
|
+-- BasicMavVariableState
|
+-- ParameterState
|
+-- BasicDiscUnvParameterState
|
+-- BasicDiscMuvParameterState
|
+-- BasicContUnvParameterState
|
+-- BasicContMuvParameterState
Abstract states¶
The type system of VariateForm and ValueSupport from Distributions
(see Listing 2 and associated
documentation in Distributions) is used for
parameterizing abstract states in Klara.
abstract VariateForm
type Univariate <: VariateForm end
type Multivariate <: VariateForm end
type Matrixvariate <: VariateForm end
abstract ValueSupport
type Discrete <: ValueSupport end
type Continuous <: ValueSupport end
VariableState is the root of Klara’s variable state type hierarchy. It is defined as
abstract VariableState{F<:VariateForm}
Being parameterized by VariateForm, the abstract type VariableState enables distinguishing between univariate,
multivariate and matrix-variate variable states.
ParameterState is the root of Klara’s parameter state types and an abstract sub-type of VariableState. It is
defined as
abstract ParameterState{S<:ValueSupport, F<:VariateForm} <: VariableState{F}
As seen from its parameterization, ParameterState makes it possible to organize parameter states by both the support of
state space and the variate form.
Basic variable states¶
Klara ships with three so-called basic variable state types, namely BasicUnvVariableState, BasicMuvVariableState
and BasicMavVariableState. These three types are used for encapsulating minimal information, that is the value of a
variable state and possibly the associated size of value.
Each of these three basic state types corresponds to a specific variate form, whereas none of them is parameterized by the
support of state space. Instead, each of them is parameterized by the type of Number of their value field, see
Table 1.
| Variable state type | value type |
size type |
|---|---|---|
| BasicUnvVariableState{N<:Number} | N | ✗ |
| BasicMuvVariableState{N<:Number} | Vector{N} | Int |
| BasicMavVariableState{N<:Number} | Matrix{N} | Tuple{Int, Int} |
In what follows, constructors are provided for the three basic variable types.
BasicUnvVariableState¶
-
BasicUnvVariableState{N<:Number}(value::N)¶ Construct a basic univariate variable state with some
value.Examples:
state = BasicUnvVariableState(1.) # Klara.BasicUnvVariableState{Float64}(1.0) state.value # 1.0
BasicMuvVariableState¶
-
BasicMuvVariableState{N<:Number}(value::Vector{N})¶ Construct a basic multivariate variable state with some
value.Examples:
state = BasicMuvVariableState([1, 2]) # Klara.BasicMuvVariableState{Int64}([1, 2], 2) state.value # 2-element Array{Int64, 1}: # 1 # 2 state.size # 2
-
BasicMuvVariableState{N<:Number}(size::Int, ::Type{N}=Float64) Construct a basic multivariate variable state with a
valueof specifiedsizeand element type.Examples:
BasicMuvVariableState(3, Float32) # Klara.BasicMuvVariableState{Float32}(3-element Array{Float32, 1}, 2)
BasicMavVariableState¶
-
BasicMavVariableState{N<:Number}(value::Matrix{N})¶ Construct a basic matrix-variate variable state with some
value.Examples:
state = BasicMavVariableState(eye(2)) # Klara.BasicMavVariableState{Float64}(2x2 Array{Float64, 2}, (2, 2)) state.value # 2x2 Array{Float64, 2}: # 1.0 0.0 # 0.0 1.0 state.size # (2, 2)
-
BasicMavVariableState{N<:Number}(size::Tuple, ::Type{N}=Float64) Construct a basic matrix-variate variable state with a
valueof specifiedsizeand element type.Examples:
BasicMavVariableState((3, 2), Float32) # Klara.BasicMavVariableState{Int16}(3x2 Array{Float32, 2}, (3, 2))
Basic parameter states¶
Four basic parameter state types are made available by Klara, namely the discrete univariate
BasicDiscUnvParameterState, discrete multivariate BasicDiscMuvParameterState, continuous univariate
BasicContUnvParameterState and continuous multivariate BasicContMuvParameterState, see Table 2.
| Parameter state type | ValueSupport | VariateForm |
|---|---|---|
| BasicDiscUnvParameterState{NI<:Integer, NR<:Real} | Discrete | Univariate |
| BasicDiscMuvParameterState{NI<:Integer, NR<:Real} | Discrete | Multivariate |
| BasicContUnvParameterState{NR<:Real} | Continuous | Univariate |
| BasicContMuvParameterState{NR<:Real} | Continuous | Multivariate |
Both basic parameter states and basic variable states contain the state’s value and value’s size. Additionally, basic
parameter states contain fields that hold information about the target distribution of the associated parameter and about
sampling diagnostics, see Table 3.
The discrete states BasicDiscUnvParameterState and BasicDiscMuvParameterState are parameterized by the element type
NI<:Integer of state value and by the element type NR<:Real of target-related fields. On the other hand, the
continuous states BasicContUnvParameterState and BasicContMuvParameterState are parameterized by the common element
type NR<:Real of state value and of target-related fields.
A parameter is characterized by its target, that is by its possibly unnormalized distribution. A target is specified via a
Distribution or via a possibly unnormalized probability distribution function (PDF). Either way, the
state.logtarget field of a parameter state stores the logarithm of the associated PDF evaluated at state.value.
A posterior target is proportional to a likelihood times a prior. Thus, if a parameter is specified via its posterior target,
the state.loglikelihood and state.logprior fields of the associated parameter state enable storing the logarithm
of the likelihood function and prior PDF evaluated at state.value. Apparently, state.logtarget is equal to the sum of
state.loglikelihood and state.logprior.
| Basic[S/F]ParameterState{P} | ||||
|---|---|---|---|---|
| S<:ValueSupport | Discrete | Discrete | Continuous | Continuous |
| F<:VariateForm | Univariate | Multivariate | Univariate | Multivariate |
| P (Parameters) | NI, NR | NI, NR | NR | NR |
| Field | Field type | |||
| value | NI | Vector{NI} | NR | Vector{NR} |
| loglikelihood | NR | NR | NR | NR |
| logprior | NR | NR | NR | NR |
| logtarget | NR | NR | NR | NR |
| gradloglikelihood | ✗ | ✗ | NR | Vector{NR} |
| gradlogprior | ✗ | ✗ | NR | Vector{NR} |
| gradlogtarget | ✗ | ✗ | NR | Vector{NR} |
| tensorloglikelihood | ✗ | ✗ | NR | Matrix{NR} |
| tensorlogprior | ✗ | ✗ | NR | Matrix{NR} |
| tensorlogtarget | ✗ | ✗ | NR | Matrix{NR} |
| dtensorloglikelihood | ✗ | ✗ | NR | Array{NR, 3} |
| dtensorlogprior | ✗ | ✗ | NR | Array{NR, 3} |
| dtensorlogtarget | ✗ | ✗ | NR | Array{NR, 3} |
| diagnosticvalues | Vector | Vector | Vector | Vector |
| size | ✗ | Int | ✗ | Int |
| diagnostickeys | Vector{Symbol} | Vector{Symbol} | Vector{Symbol} | Vector{Symbol} |
The rest of target-related fields, prefixed by grad, tensor and dtensor, appear only in continuous parameter states and correspond to first, second and third degree derivatives of the target. Such target derivatives are utilized by various MCMC algorithms.
Fields starting with grad store the gradient of the prefixed function. For example, state.gradlogtarget stores the
gradient of the log-target evaluated at state.value.
Fields starting with tensor refer to the metric tensor of the prefixed function. It is noted that the concept of metric
tensor is used in an information theoretic context referring to distance between distributions [1]. For
instance, state.tensorloglikelihood can be used for saving the expected Fisher information matrix, which is equal to the
negative expected value of the second-order derivative of the log-likelihood evaluated at state.value. Moreover,
state.tensorlogprior can be utilized for storing the negative Hessian of the log-prior evaluated at state.value. As
for state.dtensorlogtarget, it is the metric tensor of the log-target, which equals the sum of
state.tensorloglikelihood and state.tensorlogprior.
Fields prefixed by dtensor store all first-order derivatives of the metric tensor referred by the respective
tensor-prefixed field, thus yielding third-order derivatives of the target. For example, state.dtensorlogtarget saves
all first-order derivatives of state.tensorlogtarget evaluated at state.value.
state.diagnosticvalues is a Vector used for storing diagnostics pertaining to the sampling of a parameter state.
The state.diagnosticvalues are labeled by an accordingly ordered Vector{Symbol} of state.diagnostickeys.
Conceptually, state.diagnostickeys and state.diagnosticvalues can be seen as the keys and values of a dictionary of
diagnostics but are maintained in two separate vectors to improve MCMC performance. The two vectors are interfaced with a
diagnostics() function, which zips them together and returns the resulting dictionary.
-
diagnostics(state::ParameterState)¶ Return the dictionary of
statediagnostics arising fromstate.diagnostickeysandstate.diagnosticvalues.
The constructors of Klara’s basic parameter state types are elucidated in the remaining of this section.
BasicDiscUnvParameterState¶
-
BasicDiscUnvParameterState{NI, NR}(value::NI, <optional arguments>) Construct a basic discrete univariate parameter state with some
value.The parameterization is set as
NI<:Integer,NR<:Real.Optional arguments:
diagnostickeys::Vector{Symbol}=Symbol[]: the diagnostic keys of the state.::Type{NR}=Float64: the element type of target-related fields.diagnosticvalues::Vector=Array(Any, length(diagnostickeys)): the diagnostic values of the state.
Examples:
state = BasicDiscUnvParameterState(2, [:accept], Float64, [true]) # Klara.BasicDiscUnvParameterState{Int64, Float64}( # 2, NaN, NaN, NaN, Bool[true], [:accept] # ) state.value # 2 diagnostics(state) # Dict{Symbol, Bool} with 1 entry: # :accept => true
BasicDiscMuvParameterState¶
-
BasicDiscMuvParameterState{NI, NR}(value::Vector{NI}, <optional arguments>) Construct a basic discrete multivariate parameter state with some
value.The parameterization is set as
NI<:Integer,NR<:Real.Optional arguments:
diagnostickeys::Vector{Symbol}=Symbol[]: the diagnostic keys of the state.::Type{NR}=Float64: the element type of target-related fields.diagnosticvalues::Vector=Array(Any, length(diagnostickeys)): the diagnostic values of the state.
Examples:
state = BasicDiscMuvParameterState(Int64[0, 1], [:accept], Float64, [false]) # Klara.BasicDiscMuvParameterState{Int64, Float64}( # [0, 1], NaN, NaN, NaN, Bool[false], 2, [:accept] # ) state.value # 2-element Array{Int64, 1}: # 0 # 1 diagnostics(state) # Dict{Symbol, Bool} with 1 entry: # :accept => false
-
BasicDiscMuvParameterState{NI, NR}(size::Int, <optional arguments>) Construct a basic discrete multivariate parameter state with with a
valueof specifiedsize.The parameterization is set as
NI<:Integer,NR<:Real.Optional arguments:
diagnostickeys::Vector{Symbol}=Symbol[]: the diagnostic keys of the state.::Type{NI}=Int: the element type of the state value.::Type{NR}=Float64: the element type of target-related fields.diagnosticvalues::Vector=Array(Any, length(diagnostickeys)): the diagnostic values of the state.
Examples:
BasicDiscMuvParameterState(3, [:accept], Int32, Float32, [true]) # Klara.BasicDiscMuvParameterState{Int32, Float32}( # 3-element Array{Int32, 1}, NaN32, NaN32, NaN32, Bool[true], 3, [:accept] # )
BasicContUnvParameterState¶
-
BasicContUnvParameterState{N<:Real}(value::N, <optional arguments>)¶ Construct a basic continuous univariate parameter state with some
value.Optional arguments:
diagnostickeys::Vector{Symbol}=Symbol[]: the diagnostic keys of the state.diagnosticvalues::Vector=Array(Any, length(diagnostickeys)): the diagnostic values of the state.
Examples:
state = BasicContUnvParameterState(-1.25, [:accept], [false]) # Klara.BasicContUnvParameterState{Float64}( # -1.25, # NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, # Bool[false], [:accept] # ) state.value # -1.25 diagnostics(state) # Dict{Symbol, Bool} with 1 entry: # :accept => false
-
BasicContUnvParameterState{N<:Real}(<optional arguments>) Construct a basic continuous univariate parameter state with an uninitialized
value(NaN).Optional arguments:
diagnostickeys::Vector{Symbol}=Symbol[]: the diagnostic keys of the state.- ::Type{N}=Float64:: the element type of the state value.
diagnosticvalues::Vector=Array(Any, length(diagnostickeys)): the diagnostic values of the state.
Examples:
BasicContUnvParameterState() # Klara.BasicContUnvParameterState{Float64}( # NaN, # NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, # Any[], Symbol[] # )
BasicContMuvParameterState¶
-
BasicContMuvParameterState{N<:Real}(value::Vector{N}, <optional arguments>)¶ Construct a basic continuous multivariate parameter state with some
value.Optional arguments:
monitor::Vector{Bool}=fill(false, 9): 9-element Boolean vector indicating which of the target-related fields are stored by the state.diagnostickeys::Vector{Symbol}=Symbol[]: the diagnostic keys of the state.diagnosticvalues::Vector=Array(Any, length(diagnostickeys)): the diagnostic values of the state.
Examples:
state = BasicContMuvParameterState(ones(Float32, 2)) # Klara.BasicContMuvParameterState{Float32}( # Float32[1.0f0, 1.0f0], # NaN32, NaN32, NaN32, # Float32[], Float32[], Float32[], # 0x0 Array{Float32, 2}, 0x0 Array{Float32, 2}, 0x0 Array{Float32, 2}, # 0x0x0 Array{Float32, 3}, 0x0x0 Array{Float32, 3}, 0x0x0 Array{Float32, 3}, # Any[], 2, Symbol[] # ) state.value # 2-element Array{Float32,1}: # 1.0 # 1.0 size(state.gradloglikelihood) # (0,) size(state.gradlogtarget) # (0,) diagnostics(state) # Dict{Symbol,Any} with 0 entries
-
BasicContMuvParameterState{N<:Real}(value::Vector{N}, monitor::Vector{Symbol}, <optional arguments>) Construct a basic continuous multivariate parameter state with some
valueand tracked target-related fields specified bymonitor.Optional arguments:
diagnostickeys::Vector{Symbol}=Symbol[]: the diagnostic keys of the state.diagnosticvalues::Vector=Array(Any, length(diagnostickeys)): the diagnostic values of the state.
Examples:
state = BasicContMuvParameterState( zeros(Float64, 2), [:logtarget, :gradlogtarget] ) # Klara.BasicContMuvParameterState{Float64}( # [0.0, 0.0], # NaN, NaN, NaN, # Float64[], Float64[], 2-element Array{Float64, 1}, # 0x0 Array{Float64, 2}, 0x0 Array{Float64, 2}, 0x0 Array{Float64, 2}, # 0x0x0 Array{Float64, 3}, 0x0x0 Array{Float64, 3}, 0x0x0 Array{Float64, 3}, # Any[], 2, Symbol[] # ) size(state.gradloglikelihood) # (0,) size(state.gradlogtarget) # (2,)
-
BasicContMuvParameterState{N<:Real}(size::Int, <optional arguments>) Construct a basic continuous multivariate parameter state with a
valueof specifiedsize.Optional arguments:
monitor::Vector{Bool}=fill(false, 9): 9-element Boolean vector indicating which of the target-related fields are stored by the state.diagnostickeys::Vector{Symbol}=Symbol[]: the diagnostic keys of the state.::Type{N}=Float64: the element type of the state value.diagnosticvalues::Vector=Array(Any, length(diagnostickeys)): the diagnostic values of the state.
Examples:
state = BasicContMuvParameterState(3) # Klara.BasicContMuvParameterState{Float64}( # 3-element Array{Float64, 1}, # NaN, NaN, NaN, # Float64[], Float64[], Float64[], # 0x0 Array{Float64, 2}, 0x0 Array{Float64, 2}, 0x0 Array{Float64, 2}, # 0x0x0 Array{Float64, 3}, 0x0x0 Array{Float64, 3}, 0x0x0 Array{Float64, 3}, # Any[], 3, Symbol[] # ) state.size # 3 diagnostics(state) # Dict{Symbol,Any} with 0 entries
-
BasicContMuvParameterState{N<:Real}(size::Int, monitor::Vector{Symbol}, <optional arguments>) Construct a basic continuous multivariate parameter state with a
valueof specifiedsizeand tracked target-related fields specified bymonitor.Optional arguments:
diagnostickeys::Vector{Symbol}=Symbol[]: the diagnostic keys of the state.::Type{N}=Float64: the element type of the state value.diagnosticvalues::Vector=Array(Any, length(diagnostickeys)): the diagnostic values of the state.
Examples:
BasicContMuvParameterState( 3, [:loglikelihood, :logtarget], [:accept], Float16, [true] ) # Klara.BasicContMuvParameterState{Float16}( # 3-element Array{Float16, 1} # NaN16, NaN16, NaN16, # Float16[], Float16[], Float16[], # 0x0 Array{Float16, 2}, 0x0 Array{Float16, 2}, 0x0 Array{Float16, 2}, # 0x0x0 Array{Float16, 3}, 0x0x0 Array{Float16, 3}, 0x0x0 Array{Float16, 3}, # Bool[true], 3, [:accept] # )