SoftDotMessagePassingRules
The SoftDot node and its rules: a dot product of two unknowns, softened by Gaussian noise so that every message is in closed form. Use it for a Bayesian linear regression, y ~ N(θᵀx, γ⁻¹) with the noise precision γ learnt, or wherever a dot product joins two Gaussian unknowns, which the deterministic dot product node of StandardMessagePassingRules cannot do in closed form. This site is a single page.
SoftDotMessagePassingRules — Module
SoftDotMessagePassingRulesThe SoftDot node, y ~ N(θᵀx, γ⁻¹): the dot product of θ and x softened by Gaussian noise of precision γ, with its variational rules. Where the deterministic dot product node, dot in StandardMessagePassingRules, has no closed-form messages for two Gaussian factors, SoftDot's are all in closed form. It serves Bayesian linear regression, y ~ N(θᵀx, γ⁻¹) with the regressors x known, and bilinear models with both factors unknown.
SoftDot, the node, and its aliassoftdot. It runs underDefaultAlgorithm, which a model need not name.- Its rules are variational, under the mean-field
q(y)q(θ)q(x)q(γ)or the structuredq(y, x)q(θ)q(γ), with an average energy for each. There are no belief-propagation rules.
Examples
julia> using MessagePassingRulesBase, ExponentialFamily, BayesBase
julia> q_θ = MvNormalMeanCovariance([1.0, 2.0], [1.0 0.0; 0.0 1.0]);
julia> q_x = MvNormalMeanCovariance([3.0, 1.0], [1.0 0.0; 0.0 1.0]);
julia> result = @call_message_update_rule(node = SoftDot, target = :y, q = (θ = q_θ, x = q_x, γ = GammaShapeRate(2.0, 1.0)));
julia> all(mean_precision(getresult(result)) .≈ (5.0, 2.0))
trueReactiveMP runs these rules on a factor graph, which RxInfer builds from a GraphPPL model. The examples here call the rules directly, as a test does.
Overview
A deterministic node y = θᵀx with both θ and x unknown has no closed-form messages. SoftDot replaces the constraint by a Gaussian likelihood of precision γ around it. The softening makes it a stochastic node, a density over its variables.
Under variational message passing, the node then sends a normal message towards each of y, θ and x and a gamma message towards γ, all in closed form. It contributes an average energy to the Bethe free energy. A large γ, or a prior on γ concentrated at large values, brings it close to the deterministic dot product.
Definition
\[p(y \mid θ, x, γ) = \mathcal{N}\left(y \mid θ^\top x, γ^{-1}\right) = \sqrt{\frac{γ}{2π}} \exp\left(-\frac{γ}{2} \left(y - θ^\top x\right)^2\right)\]
The output y is normal around the dot product θᵀx, with variance γ⁻¹. y is a scalar; θ and x are both scalars or both vectors of the same length.
Interfaces
using SoftDotMessagePassingRules, MessagePassingRulesBase, BayesBase, ExponentialFamily
MessagePassingRulesBase.nodespec(SoftDot)| interface | aliases | |
|---|---|---|
y | ||
θ | theta | |
x | ||
γ | gamma |
| default algorithm | MessagePassingRulesBase.DefaultAlgorithm() |
|---|---|
| static inputs | none |
| defined | src/node.jl:38 |
The node has four interfaces, two of them with an alias that a model may write instead of the Greek name. The node itself has the alias softdot.
| name | alias | meaning | its rules read |
|---|---|---|---|
y | the result of the soft dot product, a scalar | q(y) a univariate normal; under q(y, x), the message on y, a univariate normal | |
θ | theta | the first factor | q(θ) a normal, univariate or multivariate |
x | the second factor | q(x) a normal, or a point mass for known regressors; under q(y, x), the message on x, a normal | |
γ | gamma | the precision of the noise | q(γ) a gamma, through its mean (and the mean of its logarithm for the energy) |
Here q(θ) is the marginal of θ. The rules towards θ and x return a normal in weighted-mean–precision form, univariate or multivariate as the factor is. The rule towards y returns a univariate normal and the rule towards γ a GammaShapeRate. Under the structured factorisation the joint q(y, x) is a multivariate normal over [y; x].
Algorithm
SoftDot runs under DefaultAlgorithm, which takes no parameters; a model need not name it. The node declares no dependencies, so each rule takes the inputs of the default scheme.
Supported rules
MessagePassingRulesBase.rule_coverage(SoftDot)| DefaultAlgorithm | |
|---|---|
| → y | ✓×2 |
| → θ | ✓×2 |
| → x | ✓×2 |
| → γ | ✓×2 |
| average energy | ✓×2 |
| q(y, x) | ✓ |
rule_coverage counts two rules per target, one per factorisation:
- the mean field
q(y)q(θ)q(x)q(γ), where every rule reads the marginals of the other interfaces; - the structured
q(y, x)q(θ)q(γ), where the rules towardsyandxread the other one's message and the rules towardsθandγread the jointq(y, x).
The marginal rule q(y, x) computes that joint from the messages on y and x. There are two average energies, one per factorisation. There are no belief propagation rules.
Example
The message towards γ under mean field is Γ(3/2, ⟨(y - θᵀx)²⟩ / 2). With every marginal N(1, 1), the expected square is E[y²] - 2E[y]E[θ]E[x] + E[θ²]E[x²] = 2 - 2 + 4:
@call_message_update_rule(
node = SoftDot, target = :γ,
q = (y = NormalMeanVariance(1.0, 1.0), θ = NormalMeanVariance(1.0, 1.0), x = NormalMeanVariance(1.0, 1.0)),
)Result
| value | ExponentialFamily.GammaShapeRate{Float64}(a=1.5, b=2.0) |
|---|---|
| type | ExponentialFamily.GammaShapeRate{Float64} |
| log scale | undefined: the message rule for SoftDot towards :γ under MessagePassingRulesBase.DefaultAlgorithm declares no `logscale` |
Inputs
| edge | value | |
|---|---|---|
| y | q | ExponentialFamily.NormalMeanVariance{Float64}(μ=1.0, v=1.0) |
| θ | q | ExponentialFamily.NormalMeanVariance{Float64}(μ=1.0, v=1.0) |
| x | q | ExponentialFamily.NormalMeanVariance{Float64}(μ=1.0, v=1.0) |
Rule
| declared inputs | q[:y]::Any, q[:θ]::Any, q[:x]::Any |
|---|---|
| algorithm | DefaultAlgorithm() |
| log scale | none |
| checks | check_y_θ_x(args.q[:y], args.q[:θ], args.q[:x]) |
| defined | src/rules.jl:70 |
| body | args->begin
(my, Vy) = mean_cov(args.q[:y])
(mθ, Vθ) = mean_cov(args.q[:θ])
(mx, Vx) = mean_cov(args.q[:x])
T = promote_paramfloattype(args.q[:y], args.q[:θ], args.q[:x])
β = add_outer(Vy, my) / 2
β -= my * mθ' * mx
β += (trace_product(Vx, Vθ) + (mθ' * Vx) * mθ + (mx' * Vθ) * mx + (mθ' * mx) * (mx' * mθ)) / 2
GammaShapeRate(convert(T, 3 / 2), β)
end |
Other rules for this target (1)
src/rules.jl:86| ✓ | algorithm MessagePassingRulesBase.DefaultAlgorithm |
| ✗ | q[:y, :x]::Union{ExponentialFamily.MultivariateNormalDistributionsFamily{T}, ExponentialFamily.MultivariateGaussianDistributionsFamily{T}} where T not provided |
| ✓ | q[:θ]::Any got ExponentialFamily.NormalMeanVariance{Float64} |
| ✗ | q[:x]::ExponentialFamily.NormalMeanVariance{Float64} provided but not consumed |
| ✗ | q[:y]::ExponentialFamily.NormalMeanVariance{Float64} provided but not consumed |
@call_message_update_rule runs the rule and draws the marginals it read. The result is Γ(1.5, 2.0), which getresult extracts:
julia> using MessagePassingRulesBase, SoftDotMessagePassingRules, ExponentialFamily, BayesBase
julia> q = (y = NormalMeanVariance(1.0, 1.0), θ = NormalMeanVariance(1.0, 1.0), x = NormalMeanVariance(1.0, 1.0));
julia> message = getresult(@call_message_update_rule(node = SoftDot, target = :γ, q = q));
julia> shape(message) ≈ 1.5 && rate(message) ≈ 2.0
trueLimitations
- Variational rules only: there is no belief propagation rule, so the node needs a factorisation, mean-field or
q(y, x)q(θ)q(γ). It also needs initial marginals where the schedule reads them before they are computed. - No rules for other factorisations, such as a joint over
θandxor overyandθ. yis a scalar: a vector-valued output needs one node per component. The mean-field rules and energy check it, and thatθandxare both univariate or both multivariate, and throw aRuleInputErrorotherwise.- The rules take normal marginals and messages on
y,θandxand a gamma-like marginal onγ(anything with a mean, and a mean of the logarithm for the energy).
API
The node and its alias, the name an RxInfer model writes:
SoftDotMessagePassingRules.SoftDot — Type
SoftDotThe SoftDot node, the density
p(y | θ, x, γ) = N(y | θᵀx, γ⁻¹),a dot product of θ and x softened by Gaussian noise of precision γ. A stochastic node with the interfaces, in order:
y, the result, a scalar;θ(aliastheta), the first factor, a scalar or a vector;x, the second factor, of the same dimension asθ;γ(aliasgamma), the precision of the noise, a positive scalar.
It runs under DefaultAlgorithm, which a model need not name. Its rules are variational and in closed form: every message reads the marginals of the other interfaces, under the mean-field q(y)q(θ)q(x)q(γ) or the structured q(y, x)q(θ)q(γ), where the rules towards y and x read the message on the other one and the joint q(y, x) has its own rule. The marginals on y, θ and x are normals and the one on γ a gamma: the rules read their means and covariances, and the mean and the mean of the logarithm of q(γ).
There are no belief-propagation rules, and other factorisations, such as a joint over θ and x, have no rules. There is an average energy for the two factorisations above.
See also: softdot
SoftDotMessagePassingRules.softdot — Type
softdotAn alias of SoftDot, the node y ~ N(θᵀx, γ⁻¹).