Messages implementation
In our message passing framework one of the most important concepts is the message (wow!). Messages flow along edges of a factor graph and hold information about the part of the graph that it originates from. Usually this information is in a form of a probability distribution. Two common messages are belief propagation messages and variational messages, with are computed differently as shown below.
Abstract message type
Both belief propagation and variational messages are subtypes of a AbstractMessage
supertype.
ReactiveMP.AbstractMessage
— TypeBelief-Propagation (or Sum-Product) message
Belief propagation message
Variational message
Variational message with structured factorisation q(x, y)q(z) assumption
Message type
All messages are encoded with the type Message
.
ReactiveMP.Message
— TypeMessage{D, A} <: AbstractMessage
Message
structure encodes a Belief Propagation message, which holds some data
that usually a probability distribution, but can also be an arbitrary object. Message acts as a proxy structure to data
object and proxies most of the statistical functions, e.g. mean
, mode
, cov
etc.
Arguments
data::D
: message always holds some data object associated with itis_clamped::Bool
, specifies if this message is clampedis_initial::Bool
, specifies if this message is initialaddons::A
, specifies the addons of the message
Example
julia> distribution = Gamma(10.0, 2.0)
Gamma{Float64}(α=10.0, θ=2.0)
julia> message = Message(distribution, false, true, nothing)
Message(Gamma{Float64}(α=10.0, θ=2.0))
julia> mean(message)
20.0
julia> getdata(message)
Gamma{Float64}(α=10.0, θ=2.0)
julia> is_clamped(message)
false
julia> is_initial(message)
true
See also: AbstractMessage
, ReactiveMP.materialize!
ReactiveMP.materialize!
— Functionmaterialize!(message::AbstractMessage)
Materializes an abstract message and converts it to be of type Message
.
See also: Message
From an implementation point a view the Message
structure does nothing but hold some data
object and redirects most of the statistical related functions to that data
object. However, this object is used extensively in Julia's multiple dispatch. Our implementation also uses extra is_initial
and is_clamped
fields to determine if product of two messages results in is_initial
or is_clamped
posterior marginal. The final field contains the addons. These contain additional information on top of the functional form of the distribution, such as its scaling or computation history.
distribution = NormalMeanPrecision(0.0, 1.0)
message = Message(distribution, false, true, nothing)
Message(NormalMeanPrecision{Float64}(μ=0.0, w=1.0))
mean(message), precision(message)
(0.0, 1.0)
logpdf(message, 1.0)
-1.4189385332046727
is_clamped(message), is_initial(message)
(false, true)
The user should not really interact with Message
structure while working with ReactiveMP
unless doing some advanced inference procedures that involve prediction.