For any distribution q(Z) over the hidden labels, ln p(X|θ) = L(q, θ) + KL(q ‖ p(Z|X, θ)), and the KL term is never negative, so L is a lower bound. The E step sets q to the posterior at the current θ: the bound (green) then touches the log likelihood (red). The M step moves θ to the top of the bound; since the bound sits below the red curve, the log likelihood rises at least as much as the bound did. Here the model is a mixture of two Gaussians on the line with a single free parameter θ, so everything can be drawn exactly.
Model: p(x|θ) = (1 − π) N(x|m1, s12) + π N(x|m2, s22), every value known except θ, which is either m2 or π. q(Z) gives each point a probability qn of belonging to component 2; the E step sets qn to the responsibility (9.13). The data are drawn with a seeded generator, so everyone sees the same points.
code/ch09_mixture_em.py (the mix1d_* functions and Figure 9.14) and the checks in code/checks_ch09.py.