Variational Bayes: the KL split, mean-field updates, and a worked Normal example

Background notes (after Tran, Nguyen and Dao, 2021) · Foundations

In one paragraph

Bayesian inference wants the posterior p(\theta\mid y)=p(\theta)p(y\mid\theta)/p(y), but the normaliser p(y)=\int p(\theta)p(y\mid\theta)\,d\theta is usually an integral we cannot do. Variational Bayes (VB) replaces the posterior by the closest member q^* of a family \mathcal Q of tractable distributions, where “closest” means smallest \mathrm{KL}(q\|p(\cdot\mid y)). The KL itself contains the intractable p(y), but it only enters as an additive constant, so minimising the KL over q is exactly the same as maximising a quantity, the ELBO, that never needs p(y). All of the approximation error comes from restricting q to \mathcal Q.

1. Questions, in plain words and in symbols

# Plain-language question Mathematical question
1 The distance between my guess and the true posterior mentions the very number I cannot compute. How can I minimise it? Show \mathrm{KL}(q\|p(\cdot\mid y))=-\int q\log\frac{p(\theta)p(y\mid\theta)}{q}\,d\theta+\log p(y).
2 Is swapping the distance for the computable part an approximation? Is \arg\min_q\mathrm{KL}=\arg\max_q\mathrm{ELBO} exact? Where does the approximation enter?
3 What does “assume the pieces are independent” cost, and what are the alternatives? Define the mean-field family; compare it with fixed-form VB and normalizing flows.
4 With two independent pieces, how do I improve one while the other is frozen? Write the ELBO for q_1q_2, isolate q_1, and find \arg\max_{q_1}.
5 When does each update land in a familiar distribution? State conditional conjugacy and show q_1 stays in the prior’s family.
6 Does all of this really work on a small problem? Run it on Example 2.1 and compare with the exact posterior.

Notation

Symbol Meaning
y observed data
\theta unknown parameters (\theta=(\theta_1,\dots,\theta_d) when split into blocks)
p(\theta), p(y\mid\theta) prior, likelihood
p(\theta\mid y) posterior =p(\theta)p(y\mid\theta)/p(y)
p(y) evidence =\int p(\theta)p(y\mid\theta)\,d\theta, the intractable normaliser
q(\theta) the approximating density; \mathcal Q is the family it is chosen from
\mathrm{ELBO}(q) \int q(\theta)\log\frac{p(\theta)p(y\mid\theta)}{q(\theta)}\,d\theta (the paper writes \mathrm{LB})
E_{-\theta_1}[\cdot] average over every block except \theta_1, under the current q of those blocks

2. Question 1: the KL splits into two pieces

Start from the definition and substitute Bayes’ rule inside the logarithm.

\mathrm{KL}(q\,\|\,p(\cdot\mid y))=\int q(\theta)\log\frac{q(\theta)}{p(\theta\mid y)}\,d\theta,\qquad p(\theta\mid y)=\frac{p(\theta)p(y\mid\theta)}{p(y)}.

Plugging in, the ratio becomes \log\frac{q(\theta)}{p(\theta\mid y)}=\log\frac{q(\theta)\,p(y)}{p(\theta)p(y\mid\theta)} =\log\frac{q(\theta)}{p(\theta)p(y\mid\theta)}+\log p(y), using \log(ab)=\log a+\log b. Integrate against q, term by term:

\boxed{\ \mathrm{KL}(q\|p(\cdot\mid y))=-\mathrm{ELBO}(q)+\log p(y)\ } \qquad\Longleftrightarrow\qquad \log p(y)=\mathrm{ELBO}(q)+\mathrm{KL}(q\|p(\cdot\mid y)).

The ELBO involves only the prior, the likelihood and q, all of which we can evaluate. \log p(y) is the part we cannot compute, and it does not depend on q.

3. Question 2: exact, not an approximation

Because \log p(y) is a constant in q, every increase of the ELBO is an equal decrease of the KL. So for any family \mathcal Q, \arg\min_{q\in\mathcal Q}\mathrm{KL}(q\|p(\cdot\mid y))=\arg\max_{q\in\mathcal Q}\mathrm{ELBO}(q). Since \mathrm{KL}\ge0, also \mathrm{ELBO}(q)\le\log p(y), which is where the name (evidence lower bound) comes from.

The approximation is the restriction q\in\mathcal Q.

One more thing is fixed by the objective, not by \mathcal Q: the KL is taken in the order \mathrm{KL}(q\|p), the “reverse” direction, which tends to make q^* settle on one region of the posterior and understate its spread. §8 shows this on a real example (the standard deviation of \mu).

4. Question 3: choosing the family \mathcal Q

Mean-field. \mathcal Q is every q that factorises across blocks of parameters: q(\theta)=q_1(\theta_1)\,q_2(\theta_2)\cdots q_d(\theta_d). The form of each factor is not chosen; it falls out of the optimisation (§6). The price is that the dependence between blocks in the true posterior is thrown away. If the true posterior of two parameters is a tilted ellipse, the best product is an axis-aligned blob, so it cannot tilt.

Fixed-form VB (FFVB) and mean-field VB (MFVB) are the two classes the paper distinguishes. They differ in how \mathcal Q is specified and fitted, not in the objective:

MFVB FFVB
What is restricted q factorises q has a parametric form chosen in advance (e.g. a Gaussian N(\mu,\Sigma))
Form of each factor determined by the model chosen by you
Dependence between coordinates none possible (a full-covariance Gaussian keeps it)
Optimisation coordinate ascent, closed-form updates stochastic gradient ascent on the parameters of q
Needs model-specific derivation only the ability to evaluate \log p(\theta)p(y\mid\theta)

They can overlap: a diagonal Gaussian fitted by gradients is fixed-form and mean-field in structure.

Normalizing flows are a very flexible fixed form. Take a simple base density q_0(z) and an invertible, differentiable map T_\phi, set \theta=T_\phi(z), and the density is exact: q_\phi(\theta)=q_0(z)\,\bigl|\det\partial T_\phi/\partial z\bigr|^{-1},\quad z=T_\phi^{-1}(\theta). If T_\phi mixes coordinates, q_\phi has dependence between them; if it acts coordinate by coordinate, you get a mean-field q. So mean-field is one end of the scale (cheap, restrictive) and a rich flow is the other (expensive, nearly unrestricted).

5. Question 4: the ELBO for two factors

Take \theta=(\theta_1,\theta_2) and q=q_1q_2. Write \log p(\theta,y) for \log p(\theta)p(y\mid\theta).

\mathrm{ELBO}(q_1,q_2)=\iint q_1q_2\log p(\theta,y)\,d\theta_1d\theta_2-\iint q_1q_2\log(q_1q_2)\,d\theta_1d\theta_2.

The entropy term splits. \log(q_1q_2)=\log q_1+\log q_2. In \iint q_1q_2\log q_1 the factor q_1\log q_1 does not involve \theta_2, so it leaves the inner integral, which is \int q_2\,d\theta_2=1: \iint q_1q_2\log(q_1q_2)=\int q_1\log q_1\,d\theta_1+\int q_2\log q_2\,d\theta_2. (The entropy of independent pieces is the sum of their entropies.)

The first term, as an iterated integral. \iint q_1q_2\log p(\theta,y)=\int q_1(\theta_1)\Bigl[\int q_2(\theta_2)\log p(\theta,y)\,d\theta_2\Bigr]d\theta_1 =\int q_1(\theta_1)\,E_{-\theta_1}[\log p(y,\theta)]\,d\theta_1, where E_{-\theta_1}[\log p(y,\theta)]:=E_{q_2}[\log p(y,\theta)] is a function of \theta_1 only, since \theta_2 has been averaged out.

Putting the pieces together, \mathrm{ELBO}(q_1,q_2)=\int q_1E_{-\theta_1}[\log p(y,\theta)]\,d\theta_1-\int q_1\log q_1\,d\theta_1+C(q_2), \qquad C(q_2)=-\int q_2\log q_2\,d\theta_2.

C(q_2) is “a constant” only with respect to q_1: the ELBO still depends on both factors. In coordinate ascent q_2 is frozen while q_1 is updated, then the roles swap, and the term that was a constant becomes the one being optimised.

Merging the q_1 terms (linearity of the integral, \int f-\int g=\int(f-g)), then using x=\log e^x and \log a-\log b=\log(a/b): \mathrm{ELBO}=\int q_1\Bigl\{E_{-\theta_1}[\log p(y,\theta)]-\log q_1\Bigr\}d\theta_1+C(q_2) =\int q_1\log\frac{\exp\bigl(E_{-\theta_1}[\log p(y,\theta)]\bigr)}{q_1}\,d\theta_1+C(q_2).

This has the shape of the ELBO from §2. The function in the numerator is not a density yet; normalise it, q_1^*(\theta_1)=\frac{\exp(E_{-\theta_1}[\log p(y,\theta)])}{Z},\qquad Z=\int\exp(E_{-\theta_1}[\log p(y,\theta)])\,d\theta_1, and the q_1-part of the ELBO equals -\mathrm{KL}(q_1\|q_1^*)+\log Z. The KL is smallest (zero) at q_1=q_1^*, so \boxed{\ \log q_1^*(\theta_1)=E_{-\theta_1}[\log p(y,\theta)]+\text{const}\ } is the exact best q_1 given q_2, and the same holds for every block.

Why coordinate ascent here, rather than gradient ascent.

Gradient ascent is used when this expectation has no closed form, when q must keep dependence between coordinates, or when minibatches are needed for large data: that is FFVB. The weakness of coordinate ascent is that it zigzags when coordinates are strongly dependent in the true posterior.

6. Question 5: conjugacy, and why q_1 stays in the prior’s family

A prior is conjugate to a likelihood if their product is in the prior’s family. Beta prior, Bernoulli likelihood: \theta^{a-1}(1-\theta)^{b-1}\cdot\theta^h(1-\theta)^{n-h}\propto\theta^{a+h-1}(1-\theta)^{b+n-h-1} is Beta(a+h,\,b+n-h) again, with updated numbers. A model is conditionally conjugate if each block, given all the others, has this property.

In the update \log q_1^*=E_{-\theta_1}[\log p(y,\theta)]+\text{const}, only the terms with \theta_1 matter, so \log q_1^*=E_{q_2}[\log p(\theta_1\mid\theta_2,y)]+\text{const}. If the full conditional is an exponential-family member of the prior’s family, \log p(\theta_1\mid\theta_2,y)=\eta(\theta_2,y)^\top T(\theta_1)+\log h(\theta_1)+\text{const}, then only \eta involves \theta_2, and the average over q_2 just replaces \eta by E_{q_2}[\eta]: q_1^*(\theta_1)\propto h(\theta_1)\exp\bigl(E_{q_2}[\eta]^\top T(\theta_1)\bigr), the same family with the “expected parameters”. Without conditional conjugacy, \log p(\theta_1\mid\theta_2,y) is not of this form, q_1^* is not a recognisable distribution, and the exact update is not available.

7. Example 2.1 set up

Ten observations y=(11,12,8,10,9,8,9,10,13,7) from N(\mu,\sigma^2), with priors \mu\sim N(\mu_0,\sigma_0^2), \sigma^2\sim\text{Inverse-Gamma}(\alpha_0,\beta_0), and \mu_0=0, \sigma_0^2=100, \alpha_0=\beta_0=1. Factorise q(\mu,\sigma^2)=q(\mu)q(\sigma^2). The model is conditionally conjugate (a Normal given \sigma^2, an Inverse-Gamma given \mu) but not jointly conjugate, so the posterior has no closed form, which is why VB is used.

Update for q(\mu)=N(m,s^2). Keep the \mu-terms of \log p(y,\mu,\sigma^2) and average \sigma^2 out; it appears only through \tau:=E_{q(\sigma^2)}[1/\sigma^2]. \log q(\mu)=-\tfrac{\tau}{2}\sum_i(y_i-\mu)^2-\frac{(\mu-\mu_0)^2}{2\sigma_0^2}+\text{const} =-\tfrac12\mu^2\Bigl(n\tau+\tfrac1{\sigma_0^2}\Bigr)+\mu\Bigl(\tau\textstyle\sum y_i+\tfrac{\mu_0}{\sigma_0^2}\Bigr)+\text{const}. A N(m,s^2) has log-density -\mu^2/(2s^2)+\mu m/s^2+\text{const}. Matching coefficients: \frac1{s^2}=n\tau+\frac1{\sigma_0^2},\qquad m=s^2\Bigl(\tau\sum y_i+\frac{\mu_0}{\sigma_0^2}\Bigr). The data precision n\tau adds to the prior precision, and m is a precision-weighted average of data and prior mean.

Update for q(\sigma^2)=\text{IG}(\alpha,\beta). Keep the \sigma^2-terms and average \mu out: \log q(\sigma^2)=-\Bigl(\alpha_0+\tfrac n2+1\Bigr)\log\sigma^2-\frac{\beta_0+\tfrac12E_{q(\mu)}\sum_i(y_i-\mu)^2}{\sigma^2}+\text{const}. Under q(\mu)=N(m,s^2), E[(y_i-\mu)^2]=(y_i-m)^2+s^2, so E\sum(y_i-\mu)^2=\sum(y_i-m)^2+ns^2. The extra ns^2 is the price of not knowing \mu exactly. Matching -(\alpha+1)\log\sigma^2-\beta/\sigma^2: \alpha=\alpha_0+\tfrac n2,\qquad \beta=\beta_0+\tfrac12\Bigl[\sum_i(y_i-m)^2+ns^2\Bigr],\qquad \tau=E[1/\sigma^2]=\alpha/\beta. The two factors pass information through \tau (from q(\sigma^2) to q(\mu)) and through (m,s^2) (the other way). \alpha=6 never changes; \beta moves until m and s^2 settle.

8. The code, line by line

code/mfvb_normal.py implements §7 and checks it against the exact posterior on a grid. The comments in the file carry the same explanations as below.

Code What it does
s2 = 1/(n*tau + 1/s0sq) s^2: data precision n\tau plus prior precision 1/\sigma_0^2, inverted
m = s2*tau*y.sum() m=s^2(\tau\sum y_i+\mu_0/\sigma_0^2) with the \mu_0 term dropped because \mu_0=0 (a nonzero \mu_0 needs + mu0/s0sq inside the bracket)
a = a0 + n/2 \alpha=\alpha_0+n/2=6, fixed
b = b0 + 0.5*(((y-m)**2).sum() + n*s2) \beta: the residual sum of squares around m plus ns^2 for the uncertainty in \mu
tau = a/b E[1/\sigma^2] under \text{IG}(\alpha,\beta), fed into the next sweep
M, S = np.meshgrid(mu, sg) two arrays holding \mu and \sigma^2 at every grid point, so each density is evaluated at all points at once
lp = norm_logpdf(M, mu0, s0sq) + ig_logpdf(S, a0, b0) log prior of \mu plus log prior of \sigma^2
lp = lp + norm_logpdf(yi, M, S) per data point adds the log-likelihood (a sum, since observations are independent); lp is then \log p(\mu,\sigma^2,y), the true log-posterior up to the constant \log p(y)
P = np.exp(lp - lp.max()) exponentiate; subtracting the maximum first avoids underflow and only rescales by a constant
P / (P.sum() * dmu * dsg) normalise by a Riemann sum of \iint P, a numerical stand-in for the intractable p(y); the result integrates to about 1
mean_field_density(...) q(\mu)q(\sigma^2) on the same grid; already normalised, since each factor is
P.sum(0)*dsg, P.sum(1)*dmu exact marginals of \mu and \sigma^2: sum the grid over the other variable

9. Results

Running the script gives, for the first sweeps and at convergence:

sweep m s^2 \alpha \beta
1 9.6903 0.0999 6 17.5500
2 9.6717 0.2916 6 18.5122
3 9.6702 0.3076 6 18.5924
5 9.6700 0.3090 6 18.5996

So q(\mu)=N(9.670,\,0.309) and q(\sigma^2)=\text{IG}(6,\,18.60), after about five sweeps.

Parameters over sweeps

Against the exact posterior on a grid:

exact VB
E[\mu] 9.664 9.670
sd of \mu 0.611 0.556
E[\sigma^2] 3.784 3.720
Joint posterior and its mean-field approximation
Marginals

Questions and doubts

Cheat sheet