$24
In this project, you’ll be implementing a facial analysis program using PCA, using the skills from the linear algebra + PCA lecture. You’ll also continue to build your Python skills. We’ll walk you through the process step-by-step (at a high level).
You’ll use Python 3 with the libraries NumPy, SciPy, and matplotlib (installation instructions linked). You should use a SciPy version >= 1.5.0 and the following import commands:
You will be using part of the Yale face dataset (processed). The dataset is saved in the ’YaleB_32x32.npy’ file. The ’.npy’ file format is used to store numpy arrays. We will test your code only using this provided dataset.
The dataset contains 2414 sample images, each of size 32 × 32. We will use n to refer to the number of images (so n = 2414) and d to refer to the number of features for each sample image (so d = 1024 = 32 ×32). Note, we’ll use xi to refer to the ith sample image which is a d-dimensional feature vector.
Implement these six Python functions in hw3.py to perform PCA on the dataset:
5.1 Load and Center the Dataset ([20] points)
You’ll want to use the the numpy function load() to load the YaleB_32x32.npy file into Python.
This should give you a n × d dataset (recall that n = 2414 is the number of images in the dataset and d = 1024 is the number of dimensions of each image). In other words, each row represents an image feature vector.
Your next step is to center this dataset around the origin. Recall the purpose of this step from lecture
— it is a technical condition that makes it easier to perform PCA, but it does not lose any important information.
To center the dataset is simply to subtract the mean µx from each data point xi (image, in our case), i.e., xcenti = xi − ux, where
You can take advantage of the fact that x (as defined above) is a numpy array and, as such, has this convenient behavior:
array([2., 3., 6.])
[ 1., 1., 1.]])
After you’ve implemented this function, it should work like this:
2414
1024
-8.315174931741023e-17
(Its center isn’t exactly zero, but taking into account precision errors over 2414 arrays of 1024 floats, it’s what we call “close enough.”)
From now on, we will use xi to refer to xcenti.
5.2 Find the Covariance Matrix ([15] points)
Recall, from lecture, that one of the interpretations of PCA is that it is the eigendecomposition of the sample covariance matrix. We will rely on this interpretation in this assignment, with all of the information you need below.
5.4 Get all Eigenvalues/Eigenvectors that Explain More than a Certain Pro-portion of the Variance ([8] points)
Instead of taking the top m eigenvalues/eigenvectors, we may want all the eigenvectors that explain more than a certain proportion of the variance. Let λi be an eigenvalue of the covariance matrix S. Then λi’s corresponding eigenvector’s proportion of variance is
λi
n .
λ
Return the eigenvalues as a diagonal matrix, in descending order, and the corresponding eigenvectors as columns in a matrix. Hint: subset_by_index was useful for the previous function, so perhaps something similar could come in handy here. What is the trace of a matrix?
Again, make sure to return the diagonal matrix of eigenvalues first, then the eigenvectors in corresponding columns. You may have to rearrange the output of eigh to get the eigenvalues in decreasing order and make sure to keep the eigenvectors in the corresponding columns after that rearrangement.
[[1369142.41612494 |
0. |
] |
|
[ |
0. |
1341168.50476773]] |
[[-0.01304065 -0.0432441 ]
[-0.01177219 -0.04342345]
[-0.00905278 -0.04095089]
...
5.5 Project the Images ([15] points)
Given an image in the dataset and the eigenvectors from get_eig (or get_eig_prop), compute the PCA representation of the image.
Let uj represent the jth column of U. Every uj is an eigenvector of S with size d × 1. If U has m eigenvectors, the image xi is projected into an m dimensional subspace. The PCA projection represents images as a weighted sum of the eigenvectors. This projection only needs to store the weight for each
eigenvector ( |
m dimensions) instead of the entire image (d-dimensions). The projection α |
i ∈ R |
m is computed |
||||
- |
T |
|
|
|
|
||
such that αij = uj xi. |
|
m |
|
|
|
||
The full-size representation of αi can be computed as xpca |
= |
αij uj . Notice that each eigenvector |
|||||
|
|
i |
|
j=1 |
|
|
|
uj is multiplied by its corresponding weight αij . The reconstructed image, xpcai, will not necessarily equal the original image because of the information lost projecting xi to a smaller subspace. This information loss will increase as less eigenvectors are used. Implement project_image to compute xpcai for an input image.
[6.84122225 4.83901287 1.41736694 ... 8.75796534 7.45916035 5.4548656 ]
5.6 Visualize ([25] points)
We’ll be using matplotlib’s imshow.
Follow these steps to visualize your images:
R1024).
Below is a simple snippet of code for you to test your functions. Do not include it in your submission!
Please submit your files in a .zip archive named hw3_<netid>.zip, where you replace <netid> with your netID (i.e., your wisc.edu login). Inside your zip file, there should be only one file named hw3.py. Do not submit a Jupyter notebook .ipynb file.
Be sure to remove all debugging output before submission; failure to do so will be penalized ([10] points):
ALL THE BEST!
5