{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"# Mixture Models"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"###### COMP4670/8600 - Statistical Machine Learning - Tutorial\n",
"\n",
"## Textbook Questions\n",
"These questions are hand picked to both be of reasonable difficulty and demonstrate what you are expected to be able to solve. The questions are labelled in Bishop as either $\\star$, $\\star\\star$, or $\\star\\star\\star$ to rate its difficulty.\n",
"\n",
"\n",
"- **Question 9.2**: ($\\star$) This requires the Robbins-Monro sequential estimation described in 2.3.5. The derivative of w.r.t. $\\boldsymbol{\\mu}$ is the M-step to compute $\\boldsymbol{\\mu}$. Note that $\\eta$ in (9.5) represents a constant.\n",
"\n",
"- **Question 9.6**: ($\\star$) There is a change from $\\boldsymbol{\\Sigma}_k$ to $\\boldsymbol{\\Sigma}$ for every $k$.\n",
"\n",
"- **Question 9.10**: ($\\star\\star$) Hint: state the property of conditional probability density function $p({x}_a \\mid {x}_b)$.\n",
"\n",
"- **Question 9.12**: ($\\star$) Hint: $\\mathbb{E}[\\boldsymbol{x}] = \\int \\boldsymbol{x} p(\\boldsymbol{x}) dx$.\n",
"\n",
"- **Question 9.15**: ($\\star$) Show that M-step equation (9.59) can be derived from (9.55) w.r.t. $\\boldsymbol{\\mu}_k$. Please revisit Bernoulli distribution in 9.3.3.\n",
"\n",
"- **Question 9.16**: ($\\star$) Show that M-step equation (9.60) can be derived from (9.55) w.r.t. $\\pi_k$. Lagrange multipliers for $\\pi_k$ is required. Please revisit Bernoulli distribution in 9.3.3.\n",
"\n",
"- **Question 9.13**: ($\\star\\star$) This question requires (9.48) - (9.60).\n",
"\n",
"- **Question 9.23**: ($\\star$) It is restricted to stationary points of the objective function. The optimization has converged in this case.\n",
"\n",
"- **Question 9.25**: ($\\star\\star$) (9.70), (9.71), and (9.72) can be used to show the lower bound.\n",
"\n",
"\n",
"In this lab, we will use expectation-maximisation to model the eruptions of the Old Faithful geyser with a two-component Gaussian mixture model. \n",
"\n",
"### Assumed knowledge\n",
"- Gaussian mixture models and expectation-maximisation (lectures)\n",
"- Normalising data\n",
"\n",
"### After this lab, you should be comfortable with:\n",
"- Modelling data with a Gaussian mixture model\n",
"- Understanding why and how this model is an instance of EM\n",
"- Visualising the convergence of the Gaussian mixture model algorithm## Textbook Questions\n",
"These questions are hand picked to both be of reasonable difficulty and demonstrate what you are expected to be able to solve. The questions are labelled in Bishop as either $\\star$, $\\star\\star$, or $\\star\\star\\star$ to rate its difficulty."
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"$\\newcommand{\\trace}[1]{\\operatorname{tr}\\left\\{#1\\right\\}}$\n",
"$\\newcommand{\\Norm}[1]{\\lVert#1\\rVert}$\n",
"$\\newcommand{\\RR}{\\mathbb{R}}$\n",
"$\\newcommand{\\inner}[2]{\\langle #1, #2 \\rangle}$\n",
"$\\newcommand{\\DD}{\\mathscr{D}}$\n",
"$\\newcommand{\\grad}[1]{\\operatorname{grad}#1}$\n",
"$\\DeclareMathOperator*{\\argmin}{arg\\,min}$\n",
"Run this cell to set up $\\LaTeX$."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"import numpy as np\n",
"import matplotlib.pyplot as plt"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"## Recap of Gaussian Mixture Models\n",
"\n",
"Given a collection of data $\\{\\mathbf{x}_1, \\ldots, \\mathbf{x}_n \\}$, where $\\mathbf{x}_i \\in \\mathbb{R}^D$\n",
"we assume that the data was drawn from\n",
"a probability distrubtion $p$, modelled as a mixture of $K$ many Gaussians.\n",
"$$\n",
"p(\\mathbf{x}) := \\sum_{k=1}^K \\pi_k \\mathcal{N}(x \\mid \\mu_k, \\Sigma_k )\n",
"$$\n",
"\n",
"We assume that the data $\\mathbf{X} = \\{\\mathbf{x}_1, \\ldots, \\mathbf{x}_n \\} \\in \\mathbb{R}^{N \\times D}$ is known, the number of gaussians $K$ is known,\n",
"and we would like to find the parameters $\\pi_k, \\mu_k, \\Sigma_k$.\n",
"\n",
"Note that the mixture weights must satisfy\n",
"$$\n",
"\\sum_{k=1}^K \\pi_k = 1\n",
"$$\n",
"\n",
"In practise, when we want to sample a point from $p(\\mathbf{x})$, we sample a number $p$ uniformly from\n",
"the interval $[0,1)$, and then if $p$ satisfies $\\sum_{i=1}^{k-1} \\pi_i \\leq p < \\sum_{i=1}^{k} \\pi_k$,\n",
"we then sample $\\mathbf{x}$ from the corresponding $K^\\text{th}$ gaussian $\\mathcal{N}(x \\mid \\mu_k, \\Sigma_k )$.\n",
"\n",
"For example, given three gaussians, and the mixture coefficients $\\pi_1,\\pi_2, \\pi_3 = 0.3, 0.3, 0.4$,\n",
"we draw $p$ from the half-open unit interval, see which of the three intervals \n",
"$$[0,0.3), [0.3, 0.6), [0.6, 1)$$\n",
"$p$ lies in, and then sample $\\mathbf{x}$ from the corresponding gaussian. \n",
"\n",
"### Latent Variables\n",
"\n",
"For a data point $\\mathbf{x}$, we define a latent variable $\\mathbf{z}$, and denote the $k^\\text{th}$\n",
"term in vector $\\mathbf{z}$ as $z_k$. \n",
"The latent varaible $\\mathbf{z}$ is a 1-of-$K$ (or a one-hot encoding) \n",
"indicating which gaussian the point $\\mathbf{x}$ was sampled from. \n",
"(A one-hot encoding means that one of the $z_k$'s\n",
"will be one, and the rest will be zero.)\n",
"By doing this, we can define the conditional probablity\n",
"$$\n",
"p(\\mathbf{x} \\mid z_k = 1) := \\mathcal{N}(X \\mid \\mu_k, \\Sigma_k)\n",
"$$\n",
"\n",
"In practise, for each data point $\\mathbf{x}_n$, we introduce a corresponding latent variable $\\mathbf{z}_n$ \n",
"that represents which gaussian that $\\mathbf{x}_n$ came from. Of course, we don't know what the $\\mathbf{z}_n$'s are, otherwise the problem would already be solved. We let $(z_n)_k$, or simply $z_{nk}$, to denote the $k^\\text{th}$ term\n",
"in the $n^\\text{th}$ latent variable, corresponding to the data point $\\mathbf{x}_n$.\n",
"So, we should write the above as\n",
"$$\n",
"p(\\mathbf{x}_n \\mid z_{nk} = 1) := \\mathcal{N}(X \\mid \\mu_k, \\Sigma_k)\n",
"$$\n",
"\n",
"### Responsibilities\n",
"\n",
"We define\n",
"$$\n",
"\\gamma (z_{nk}) := p(z_{nk} = 1 \\mid \\mathbf{x}_n ) \n",
"$$\n",
"which denotes how \"responsible\" the component $k$ of is for explaining the observation $\\mathbf{x}_n$.\n",
"By Bayes' Law, we can write\n",
"\\begin{align}\n",
"p(z_{nk} = 1 \\mid \\mathbf{x}_n )\n",
"& = \\frac{p(\\mathbf{x}_n \\mid z_{nk} = 1) p(z_{nk} = 1)}{p(\\mathbf{x}_n)} \\\\\n",
"& = \\frac{p(z_{nk} = 1) p(\\mathbf{x}_n \\mid z_{nk} = 1) }{ \\sum_{k=1}^K p(z_{nk} = 1) p(\\mathbf{x}_n \\mid z_{nk} = 1)} \\\\\n",
"& = \\frac{\\pi_{nk} \\mathcal{N}( \\mathbf{x}_n \\mid \\mu_k, \\Sigma_k ) }\n",
" { \\sum_{k=1}^K \\pi_{nk} \\mathcal{N}( \\mathbf{x}_n \\mid \\mu_k, \\Sigma_k)}\n",
"\\end{align}\n",
"So, we have\n",
"$$\n",
"\\gamma (z_{nk}) = \n",
"\\frac{\\pi_{nk} \\mathcal{N}( \\mathbf{x}_n \\mid \\mu_k, \\Sigma_k ) }\n",
" { \\sum_{k=1}^K \\pi_{nk} \\mathcal{N}( \\mathbf{x}_n \\mid \\mu_k, \\Sigma_k)}\n",
"$$\n",
"\n",
"#### Log Likelihood\n",
"\n",
"Now, the log likelihood is given by\n",
"$$\n",
"\\log p(\\mathbf{x} \\mid \\pi, \\mu, \\Sigma) \n",
"= \\sum_{n=1}^N \\log \\left\\{ \\sum_{k=1}^K \\pi_k \\mathcal{N}(\\mathbf{x} \\mid \\mu_k, \\Sigma_k) \\right\\}\n",
"$$\n",
"and we want to choose all the parameters $\\mu, \\Sigma, \\pi$ to maximise the log likelihood.\n",
"\n",
"#### Maximising Log Likelihood\n",
"\n",
"Checking where the derivative of $\\log p(\\mathbf{x} \\mid \\pi, \\mu, \\Sigma)$ with respect to $\\mu_k$ is zero,\n",
"we obtain\n",
"$$\n",
"0 = \\sum_{n=1}^N \\frac{\\pi_{nk} \\mathcal{N}( \\mathbf{x}_n \\mid \\mu_k, \\Sigma_k ) }\n",
" { \\sum_{k=1}^K \\pi_{nk} \\mathcal{N}( \\mathbf{x}_n \\mid \\mu_k, \\Sigma_k)} \\Sigma_k^{-1}\n",
" (\\mathbf{x}_n - \\mu_k)\n",
"$$\n",
"and rearranging, we obtain \n",
"$$\n",
"\\mu_k = \\frac{1}{N_k} \\sum_{n=1}^N \\gamma(z_{nk}) \\mathbf{x}_n\n",
"$$\n",
"where \n",
"$$\n",
"N_k := \\sum_{n=1}^N \\gamma (z_{nk})\n",
"$$\n",
"is called the effective number of points assigned to the $k^\\text{th}$ gaussian.\n",
"(**Exercise: verify this**)\n",
"\n",
"Similarly, taking the derivative with respect to $\\Sigma_k$,\n",
"we obtain\n",
"$$\n",
"\\Sigma_k = \\frac{1}{N_k} \\sum_{n=1}^N \\gamma(z_{nk}) (\\mathbf{x}_n - \\mu_k) (\\mathbf{x}_n - \\mu_k)^T\n",
"$$\n",
"\n",
"and taking the derivative with respect to $\\pi_k$ (using the method of Lagrange multipliers, we can include\n",
"the constraint $\\sum_{k=1}^K \\pi_k = 1$,\n",
"$$\n",
"\\pi_k = N_k / N\n",
"$$\n",
"(**Exercise: verify this**)\n",
"\n",
"Now, the problem is that $\\gamma(z_{nk})$ is dependant on the parameters $\\mu, \\Sigma, \\pi$, but\n",
"those parameters in turn depend on the responsibilities $\\gamma(z_{nk})$. This means that we don't have\n",
"our paramters in closed form.\n",
"\n",
"#### Expectation-Maximisation (EM) Algorithm\n",
"\n",
"We use the EM algorithm to numerically find good values for the parameters $\\mu, \\Sigma, \\pi$,\n",
"that maximise the log likelihood.\n",
"\n",
"##### Step 1 (Initialise)\n",
"\n",
"Initialise the parameters $\\mu_k, \\Sigma_k, \\pi_k$, and evaluate the log-likelihood.\n",
"\n",
"##### Step 2 (Estimation)\n",
"\n",
"Compute the responsibilities (which depend on the parameters)\n",
"$$\n",
"\\gamma(z_{nk}) := \\frac{\\pi_{nk} \\mathcal{N}( \\mathbf{x}_n \\mid \\mu_k, \\Sigma_k ) }\n",
" { \\sum_{k=1}^K \\pi_{nk} \\mathcal{N}( \\mathbf{x}_n \\mid \\mu_k, \\Sigma_k)}\n",
"$$\n",
"\n",
"##### Step 3 (Maximisation)\n",
"\n",
"Compute the parameters (which depend on the responsibilities)\n",
"\n",
"\\begin{align}\n",
"N_k & := \\sum_{n=1}^N \\gamma(z_{nk}) \\\\\n",
"\\pi_k^{\\text{new}} & := \\frac{N_k^\\text{new}}{N} \\\\\n",
"\\mu_k^\\text{new} & := \\frac{1}{N_k^\\text{new}} \\sum_{k=1}^K \\gamma(z_{nk}) \\mathbf{x}_n \\\\\n",
"\\Sigma_k^\\text{new} & := \\frac{1}{N_k^\\text{new}} \\sum_{n=1}^N \\gamma(z_{nk}) (\\mathbf{x}_n - \\mu_k^\\text{new}) (\\mathbf{x}_n - \\mu_k^\\text{new})^T\n",
"\\end{align}\n",
"\n",
"##### Step 4 (Evaluate)\n",
"\n",
"Compute the log-likelihood, if it has no converges, goto 2.\n",
"$$\n",
"\\log p(\\mathbf{x} \\mid \\pi, \\mu, \\Sigma) \n",
"= \\sum_{n=1}^N \\log \\left\\{ \\sum_{k=1}^K \\pi_k \\mathcal{N}(\\mathbf{x} \\mid \\mu_k, \\Sigma_k) \\right\\}\n",
"$$\n",
"\n",
"\n",
"#### Summary of Variables\n",
"| Variable | $\\qquad \\qquad$ Type | Definition| Known? |\n",
"| --- \t | \t\t---| --- \t| --- \t\t|\n",
"| $\\mu$ | $\\mathbb{R}^{K \\times D}$ | A matrix of all the gaussian means $\\mu_1, \\ldots, \\mu_K$. | No |\n",
"| $\\Sigma$ | $\\mathbb{R}^{K \\times D \\times D}$ | A 3-tensor of all the gaussian covariances $\\Sigma_1, \\ldots, \\Sigma_K$. | No |\n",
"| $\\pi$ | $\\mathbb{R}^{K}$ | A vector of all the gaussian mixture weightings $\\pi_1, \\ldots, \\pi_K$. | No\n",
"| $\\mu_k$ \t\t| $\\mathbb{R}^D$ \t\t\t| The mean of the $k^\\text{th}$ gaussian. | No |\n",
"| $\\Sigma_k$ \t| $\\mathbb{R}^{D \\times D}$ | The covariance of the $k^\\text{th}$ gaussian. | No |\n",
"| $\\pi_k$ \t\t| $\\mathbb{R}$ \t\t\t | The mixture weighting on the $k^\\text{th}$ gaussian. | No |\n",
"| $\\mathbf{z}_n$ | $\\{0,1\\}^K$\t\t | Latent variable, a one-hot encoding of which gaussian $\\mathbf{x}_n$ was sampled from. | No |\n",
"| $(z_n)_k, z_{nk}$ | $\\{0,1\\}$\t\t\t\t| $k^\\text{th}$ term in the $n^\\text{th}$ latent variable $\\mathbf{z}_n$. | No |\n",
"| $\\gamma_{z_{nk}}$ | $\\mathbb{R}$ | The responsibility for the $k$ component to explain the observation $\\mathbb{x}_n$. | No\n",
"| $N_k$ | $\\mathbb{N}$ | The effective number of points assigned to the $k^\\text{th}$ gaussian. | No | \n",
"| $X$ | $\\mathbb{R}^{N \\times D}$ \t| Data matrix | Yes |\n",
"| $\\mathbf{x}_n$ | $\\mathbb{R}^D$ \t| A data point | Yes |\n",
"| $N$ \t\t\t | $\\mathbb{N}$ | Number of data points | Yes |\n",
"| $D$ \t\t\t\t| $\\mathbb{N}$\t\t\t\t| Dimension of data points | Yes |\n",
"| $K$\t\t\t\t| $\\mathbb{N}$\t\t\t\t| Number of gaussians | Yes |"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"## Get the data\n",
"\n",
"Download the famous *old faithful* dataset from here:\n",
"\n",
"https://machlearn.gitlab.io/sml2020/tutorials/07-dataset.csv\n",
"\n",
"Ensure you have the dataset for this week.\n",
"The data is a collection of two dimensional data points, and describes eruptions of the Old Faithful geyser in Yellowstone National Park, Wyoming, US.\n",
"The two features are the waiting time between eruptions and the duration of the eruption.\n",
"Load the data and normalise the features to have\n",
"zero mean and unit variance."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"# replace this with your solution, add and remove code and markdown cells as appropriate"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"Create variables ``mu_0``, ``pi_0`` and ``Sigma_0`` to store the initial parameters of the Gaussian mixture model for the data. Our mixture model will be made up of two gaussians, and will be initialised with means\n",
"$$\n",
"\\mu_1 =\n",
"\\begin{bmatrix}\n",
" -1\\\\+1\n",
"\\end{bmatrix}\n",
"\\qquad\n",
"\\mathrm{and}\n",
"\\qquad\n",
"\\mu_2 =\n",
"\\begin{bmatrix}\n",
" +1\\\\-1\n",
"\\end{bmatrix}\n",
"$$\n",
"respectively.\n",
"\n",
"The covariance matricies should be initialised to the identity matrix, and the mixture should start off with equal probability.\n",
"\n",
"As a reminder, `pi_0` is a vector of all the mixture weights initially,\n",
"`mu_0` is a matrix of all the means initially, and `Sigma_0` is a 3-tensor of the covariances initially.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"# replace this with your solution, add and remove code and markdown cells as appropriate"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"## Plotting the data\n",
"\n",
"To help visualise the EM process, we will plot the data and ellipses representing our two Gaussian components.\n",
"\n",
"The next cell provides some helper functions for this plotting."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"# plot_cov_ellipse was taken from here:\n",
"# http://www.nhsilbert.net/source/2014/06/bivariate-normal-ellipse-plotting-in-python/\n",
"\n",
"def plot_cov_ellipse(cov, pos, volume=.5, ax=None, fc='none', ec=[0,0,0], a=1, lw=2):\n",
" \"\"\"\n",
" Plots an ellipse enclosing *volume* based on the specified covariance\n",
" matrix (*cov*) and location (*pos*). Additional keyword arguments are passed on to the \n",
" ellipse patch artist.\n",
"\n",
" Parameters\n",
" ----------\n",
" cov : The 2x2 covariance matrix to base the ellipse on\n",
" pos : The location of the center of the ellipse. Expects a 2-element\n",
" sequence of [x0, y0].\n",
" volume : The volume inside the ellipse; defaults to 0.5\n",
" ax : The axis that the ellipse will be plotted on. Defaults to the \n",
" current axis.\n",
" \"\"\"\n",
"\n",
" import numpy as np\n",
" from scipy.stats import chi2\n",
" import matplotlib.pyplot as plt\n",
" from matplotlib.patches import Ellipse\n",
"\n",
" def eigsorted(cov):\n",
" vals, vecs = np.linalg.eigh(cov)\n",
" order = vals.argsort()[::-1]\n",
" return vals[order], vecs[:,order]\n",
"\n",
" if ax is None:\n",
" ax = plt.gca()\n",
"\n",
" vals, vecs = eigsorted(cov)\n",
" theta = np.degrees(np.arctan2(*vecs[:,0][::-1]))\n",
"\n",
" kwrg = {'facecolor':fc, 'edgecolor':ec, 'alpha':a, 'linewidth':lw}\n",
"\n",
" # Width and height are \"full\" widths, not radius\n",
" width, height = 2 * np.sqrt(chi2.ppf(volume,2)) * np.sqrt(vals)\n",
" ellip = Ellipse(xy=pos, width=width, height=height, angle=theta, **kwrg)\n",
"\n",
" ax.add_artist(ellip)\n",
" \n",
"\n",
"def plot_components(mu, Sigma, colours, *args, **kwargs):\n",
" '''\n",
" Plot ellipses for the bivariate normals with mean mu[:,i] and covariance Sigma[:,:,i]\n",
" '''\n",
" assert mu.shape[1] == Sigma.shape[2]\n",
" assert mu.shape[0] == 2\n",
" assert Sigma.shape[0] == 2\n",
" assert Sigma.shape[1] == 2\n",
" for i in range(mu.shape[1]):\n",
" kwargs['ec'] = colours[i]\n",
" plot_cov_ellipse(Sigma[i], mu[i], *args, **kwargs)\n",
"\n",
"import matplotlib.colors as mcol\n",
"\n",
"br_cmap = mcol.LinearSegmentedColormap.from_list(\"MyCmapName\",[\"b\",\"r\"])\n",
"\n",
"def plot_data(redness=None):\n",
" if redness is not None:\n",
" assert len(redness) == data.shape[1]\n",
" assert all(_ >= 0 and _ <= 1 for _ in redness)\n",
" c = redness\n",
" else:\n",
" c = 'g'\n",
" plt.figure(figsize=(8,8))\n",
" plt.scatter(data[:,0],data[:,1], marker='.', s=8, linewidths=2, c=c, cmap=br_cmap)\n",
" plt.xlabel(data_labels[0])\n",
" plt.ylabel(data_labels[1])\n",
" plt.axis([-2,2,-2,2], 'equal')\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"The following cell is an example of using these functions. It should plot the data and two ellipses representing your initial Gaussian clusters."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"if 'mu_0' in locals() and 'Sigma_0' in locals() and 'data' in locals(): # check the student has defined these vars\n",
"\n",
" plot_data()\n",
" plot_components(mu_0, Sigma_0, ['b','r'], 0.2)\n",
" plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"## Optimising the Gaussian mixture model with EM\n",
"\n",
"As discussed in Lecture 6b, we can optimise the Gaussian mixture model with expectation-maximisation,\n",
"and perform maximum likelihood estimation for $\\mathbf{\\mu}$, $\\mathbf{\\Sigma}$ and $\\mathbf{\\pi}$.\n",
"\n",
"First implement functions that perform the E-step and the M-step.\n",
"We suggest the following function signatures:\n",
"\n",
"```def e_step(X, mu, Sigma, pi):```\n",
"\n",
"and\n",
"\n",
"```def m_step(X, gamma):```\n",
"\n",
"Hint: You can use \n",
"\n",
"```from scipy.stats import multivariate_normal as mvnorm```\n",
"\n",
"```mvnorm.pdf(x, mu, sigma)```\n",
"\n",
"to compute $$\\mathcal{N}(\\mathbf{x}_N \\mid \\mu_k, \\Sigma_k)$$.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"# replace this with your solution, add and remove code and markdown cells as appropriate"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"## Evaluating the model\n",
"\n",
"Write a function to calculate the log-likehood of your model for given parameters for the Gaussian distribution"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"# replace this with your solution, add and remove code and markdown cells as appropriate"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"Plot the log-likehood of your model against the number of updates made to it. Does it converge?"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"# replace this with your solution, add and remove code and markdown cells as appropriate"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"## Visualising EM\n",
"Use ``plot_data`` and ``plot_components`` to plot the data and your current Gaussian distributions for a range of number of updates. Does the model change as you would expect?"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"# replace this with your solution, add and remove code and markdown cells as appropriate"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"## Understanding the theory"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"### Exercise 1: Conceptual understanding\n",
"Refer to Bishop and/or the lecture slides, and explain with equations:\n",
"1. the assumed generative data generating process for the mixture of Gaussians,\n",
"- what the parameters of the model are,\n",
"- what the latent (unobserved) variables are and why they make maximum likelihood parameter estimation non-trivial,\n",
"- how EM provides a solution to the maximum likelihood estimation problem."
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"### Exercise 2: Deriving the update equations\n",
"\n",
"#### Bishop Exercise 9.7\n",
"\n",
"Verify that maximization of the complete-data log likelihood\n",
"\\begin{align}\n",
"\\ln p(\\mathbf{X},\\mathbf{Z}|\\mathbf{\\mu},\\mathbf{\\Sigma},\\mathbf{\\pi}) \n",
"& = \n",
"\\sum_{n=1}^N \\sum_{k=1}^K z_{nk} \\{ \\ln \\pi_k + \\ln \\mathcal{N}(\\mathbf{x}_n | \\mathbf{\\mu}_k, \\mathbf{\\Sigma}_k \\},\n",
"\\end{align}\n",
"for a Gaussian mixture model leads to the result that the means and covariances of each component are fitted independently to the corresponding group of data points, and the mixing coefficients are given by the fractions of points in each group."
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": []
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"#### Bishop Exercise 9.8\n",
"\n",
"Show that if we maximize\n",
"\\begin{align}\n",
"\\mathbb{E}_\\mathbf{Z} \\left[ \\ln p(\\mathbf{X},\\mathbf{Z}|\\mathbf{\\mu},\\mathbf{\\Sigma},\\mathbf{\\pi}) \\right]\n",
"& = \n",
"\\sum_{n=1}^N \\sum_{k=1}^K \\gamma(z_{nk}) \\{ \\ln \\pi_k + \\ln \\mathcal{N}(\\mathbf{x}_n | \\mathbf{\\mu}_k \\mathbf{\\Sigma}_k \\},\n",
"\\end{align}\n",
"with respect to $\\mathbf{\\mu}_k$ while keeping the responsibilities $\\gamma(z_{nk})$ fixed, we obtain the closed form solution\n",
"\\begin{align}\n",
"\\mathbf{\\mu}_k & = \\frac{1}{N_k} \\sum_{n=1}^N \\gamma(z_{nk}).\n",
"\\end{align}"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": []
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": [
"#### Bishop Exercise 9.9\n",
"\n",
"Show that if we instead maximize with respect to $\\mathbf{\\Sigma}_k$ and $\\mathbf{\\pi}$ while keeping the responsibilities $\\gamma(z_{nk})$ fixed, we obtain the closed form solution\n",
"\\begin{align}\n",
"\\mathbf{\\Sigma}_k \n",
"& = \n",
"\\frac{1}{N_k} \\sum_{n=1}^N \\gamma(z_{nk}) (\\mathbf{x}_n-\\mathbf{\\mu}_k)(\\mathbf{x}_n-\\mathbf{\\mu}_k)^\\top, \\\\\n",
"\\pi_k &= \\frac{N_k}{N}.\n",
"\\end{align}"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": false
},
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (system-wide)",
"language": "python",
"metadata": {
"cocalc": {
"description": "Python 3 programming language",
"priority": 100,
"url": "https://www.python.org/"
}
},
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.9"
}
},
"nbformat": 4,
"nbformat_minor": 0
}