Fixed: σ₁=σ₂=1.5, π₁=π₂=0.5 (initial). True values: μ=(0, 4), σ=(1.0, 1.5), π=(0.4, 0.6), N=200.
Top: histogram (gray) / true mixture density (black dashed) / estimated mixture density (blue solid) / component 1 (green dashed) / component 2 (red dashed). Bottom: log-likelihood LL[t] per iteration (red line, monotonically non-decreasing).
A two-component Gaussian mixture $p(x)=\pi_1\mathcal{N}(x|\mu_1,\sigma_1^2)+\pi_2\mathcal{N}(x|\mu_2,\sigma_2^2)$ is estimated by iterating the E and M steps of the EM algorithm.
E step (the responsibility $\gamma_{ik}$ is the posterior probability that point $x_i$ was generated by component $k$):
$$\gamma_{ik}=\frac{\pi_k\,\mathcal{N}(x_i|\mu_k,\sigma_k^2)}{\sum_j \pi_j\,\mathcal{N}(x_i|\mu_j,\sigma_j^2)}$$M step (update $\mu_k, \sigma_k^2, \pi_k$ using responsibility-weighted estimates):
$$N_k=\sum_i \gamma_{ik},\quad \mu_k\leftarrow\frac{1}{N_k}\sum_i \gamma_{ik}\,x_i,\quad \sigma_k^2\leftarrow\frac{1}{N_k}\sum_i \gamma_{ik}(x_i-\mu_k)^2,\quad \pi_k\leftarrow\frac{N_k}{N}$$Log-likelihood (guaranteed non-decreasing across EM iterations):
$$\mathrm{LL}=\sum_i \log\!\left(\sum_k \pi_k\,\mathcal{N}(x_i|\mu_k,\sigma_k^2)\right)$$The monotonic rise of LL is a check on the implementation. If LL ever decreases between iterations, the update equations have a bug.