{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Matrix decomposition"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"###### COMP4670/8600 - Statistical Machine Learning - Tutorial"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Setting up the environment"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"import scipy.optimize as opt\n",
"import pickle\n",
"\n",
"%matplotlib inline"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Covariance matrix and positive semidefinite matrix\n",
"\n",
"For a dataset $X$ with $N$ examples and $D$ features, we can represent it as a matrix. What is the dimensions of this matrix $X$? The covariance matrix $C$ is the matrix representing the variance and covariance between each pair of features. What is the size of this matrix $C$?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Answer\n",
"*--- replace this with your solution, add and remove code and markdown cells as appropriate ---*"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Generate a data matrix $X$ using ```gen_data``` from Tutorial 1a. Compute the covariance matrix $C$ and its eigenvalue decomposition using ```np.linalg.eigh```."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"# replace this with your solution, add and remove code and markdown cells as appropriate"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Covariance matrices are an example of a class of matrices which are *positive semidefinite*. A matrix $A$ is called symmetric if $A_{ij}=A_{ji}$. Another way to say this is that $A=A^\\top$. A matrix $A\\in\\mathbb{R}^{n\\times n}$ is called **positive semidefinite**, if for all vectors $x\\in\\mathbb{R}^n$,\n",
"$$\n",
" x^\\top A x \\geqslant 0.\n",
"$$\n",
"Show that the eigenvalues of a positive semidefinite matrix are non-negative."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Answer\n",
"*--- replace this with your solution, add and remove code and markdown cells as appropriate ---*"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Principal component analysis (PCA)\n",
"\n",
"You will see more about principal component analysis later in the course. For now, we will treat PCA as an exercise in matrix manipulation.\n",
"\n",
"The **Singular Values** of a square matrix $A$ is defined as the square root of the eigenvalues of $A^T A$. Given a matrix $X$, the singular value decomposition (SVD) is given by\n",
"$$\n",
"X = U S V^T\n",
"$$\n",
"where $U$ and $V$ are orthogonal matrices containing the left and right singular vectors respectively. And $S$ is a matrix with the singular values along the diagonal.\n",
"\n",
"Using the definition of the covariance matrix $C$:\n",
"1. Substitute the singular value decomposition of $X$\n",
"2. Simplify the resulting expression. You should have an expression of $C$ in terms of $U$ and $S$.\n",
"3. Recall from Tutorial 2, the definition of an eigenvalue decomposition.\n",
"4. What is the matrix that contains the eigenvectors corresponding to the $k$ largest eigenvalues of $C$?\n",
"\n",
"\n",
"\n",
"Recall that PCA considers the covariance matrix of a data matrix $X$. Using the definition of SVD above, derive expressions for:\n",
"1. the eigenvectors\n",
"2. the projection of $X$ onto the $k$ largest eigenvalues\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Answer\n",
"*--- replace this with your solution, add and remove code and markdown cells as appropriate ---*"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Implement PCA\n",
"\n",
"Implement the principal component analysis method, using ```numpy.linalg.svd```. Your function should take the data matrix and return two matrices:\n",
"1. The projection of the data onto the principal components\n",
"2. The actual components (eigenvectors) themselves.\n",
"\n",
"*Hint: do not forget to center the data by removing the mean*"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# replace this with your solution, add and remove code and markdown cells as appropriate"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Use the code from Tutorial 1 to generate toy data with 100 samples in 5 dimensions. Recall that the data is from two Gaussians with unit variance, centered at $\\mathbf{1}$ and $-\\mathbf{1}$ respectively.\n",
"\n",
"Obtain the projection of the toy data to its first two principal components. Plot the results. You should be able to see that the first principal component already gives you the axis of discrimination. Revisit the question of the effect of dimension on two Gaussians with unit variance."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# replace this with your solution, add and remove code and markdown cells as appropriate"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## (optional) Effect of normalisation on principal components\n",
"\n",
"The toy dataset is generated from spherical Gaussians. Explore the following effects on PCA:\n",
"- Multiply each feature by a different scaling factor.\n",
"- Write a new function for generating data from more than 2 Gaussians, placed at different locations.\n",
"- Write a new function for generating data that generates Gaussians which are not spherical."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# replace this with your solution, add and remove code and markdown cells as appropriate"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Eigenfaces\n",
"\n",
"The aim of this section of the tutorial is to see that in some cases, the principal components can be human interpretable.\n",
"\n",
"The images below are of Colin Powell, resized to a smaller image, from [LFW](http://vis-www.cs.umass.edu/lfw/). Download the images from [the course website](https://machlearn.gitlab.io/sml2020/tutorials/lfw_colin.pkl)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Visualising images\n",
"def plot_gallery(images, titles, h, w, n_row=2, n_col=6):\n",
" \"\"\"Helper function to plot a gallery of portraits\"\"\"\n",
" plt.figure(figsize=(1.8 * n_col, 2.4 * n_row))\n",
" plt.subplots_adjust(bottom=0, left=.01, right=.99, top=.90, hspace=.35)\n",
" for i in range(n_row * n_col):\n",
" plt.subplot(n_row, n_col, i + 1)\n",
" plt.imshow(images[i].reshape((h, w)), cmap=plt.cm.gray)\n",
" plt.title(titles[i], size=12)\n",
" plt.xticks(())\n",
" plt.yticks(())\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"lfw_colin = pickle.load(open('lfw_colin.pkl', 'rb'))\n",
"\n",
"# introspect the images array to find the shapes (for plotting)\n",
"n_samples, h, w = lfw_colin['images'].shape\n",
"plot_gallery(lfw_colin['images'], range(n_samples), h, w)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Use the ```pca``` function you wrote above to find the first 15 principal components. Visualise them. Discuss what the components potentially capture, for example lighting from the right.\n",
"\n",
"*Hint: Images need to be converted into a vector for PCA, and the results need to be converted back*"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# replace this with your solution, add and remove code and markdown cells as appropriate"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"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.7.6"
}
},
"nbformat": 4,
"nbformat_minor": 1
}