<jupyter_start><jupyter_text>Homework (18 pts) - PCA<jupyter_code>from scipy.io import loadmat

# Same data file as used in lecture.
# Avaliable in lecture folder or in homework folder.
data = loadmat('eeg.mat')

# grab relevant data, EEG units are microvolts (uV), time is in milliseconds (ms)
# each channel is an electrode, each trial is a separate EEG recording from that electrode
eeg = data["EEG"][0,0]["data"]  # [channel, time point, trial]
time = data["EEG"][0,0]["times"][0]

eeg.shape, time.shape<jupyter_output><empty_output><jupyter_text>---1. (3 pts) From the EEG data above, generate the average EEG across trials for each channel for times between 0 and 500 ms (note that the first time point is NOT time zero). Plot the result for channel 20.<jupyter_code>import numpy as np
import matplotlib.pyplot as plt

mask = (time >= 0) & (time <= 500)

eeg = eeg[:,mask,:].mean(axis=2)
time = time[mask]

plt.plot(time, eeg[20,:])
plt.xlabel('Time (ms)')
plt.ylabel('EEG ($\mu$V)')
plt.title('Channel 20');<jupyter_output><empty_output><jupyter_text>---2. (3 pts) Apply PCA to the averaged EEGs from 1 above. Use as many principal components (PCs) as needed to explain 90% of the variance in the EEG waveforms. Report the number of PCs used and plot each PC as if it were an EEG waveform itself.<jupyter_code>from sklearn.decomposition import PCA

pca = PCA(0.9)
pca.fit(eeg)
pcmix = pca.transform(eeg)
n = pca.n_components_
print(f'The number of PCs needed to explain 90% of the variance in the EEGs is {n}.')

for i in range(n):
    plt.plot(time, pca.components_[i,:], label=f'PC{i}')
plt.xlabel('Time (ms)')
plt.ylabel('EEG ($\mu$V)')
plt.legend();<jupyter_output>The number of PCs needed to explain 90% of the variance in the EEGs is 3.<jupyter_text>---3. (3 pts) Replot the average EEG for channel 20 as in 1 above, and additionally overlay the plot of its projection onto the principal components from 2 above. Use a legend to label the plots as 'original' and 'projected'. Does it look like we lost a lot of information by describing each waveform using only a small number of PCs as opposed to explicit values at each time point?<jupyter_code>eeg_projected = pca.inverse_transform(pcmix);

plt.plot(time, eeg[20,:], label='original')
plt.plot(time, eeg_projected[20,:], label='projected')
plt.xlabel('Time (ms)')
plt.ylabel('EEG ($\mu$V)')
plt.title('Channel 20');<jupyter_output><empty_output><jupyter_text>Very little information appears to have been lost using only three principal components to describe the entire EEG waveform. ---4. (3 pts) How much of each of the PCs were mixed together to generate the projection for channel 20 as shown in 3 above? Plot the relative amounts of each PC as a bar graph. Use only a single tick mark on the x-axis for each PC.<jupyter_code>plt.bar(range(n), pcmix[20,:])
plt.xticks(range(n))
plt.xlabel('PC')
plt.ylabel('Weight')
plt.title('Channel 20');<jupyter_output><empty_output><jupyter_text>---5. (3 pts) Use a Gaussian mixture model (GMM) to group the EEG waveforms into three clusters in the PCA reduced dimensions. Plot the EEG waveforms as points in the PCA reduced dimensions (axes are the PCs) colored according to their cluster.<jupyter_code>from sklearn.mixture import GaussianMixture

gmm = GaussianMixture(3)
labels = gmm.fit_predict(pcmix)

ax = plt.subplot(111, projection='3d')
ax.scatter(pcmix[:,0], pcmix[:,1], pcmix[:,2], c=labels)
ax.set_xlabel('PC0')
ax.set_ylabel('PC1')
ax.set_zlabel('PC2')
plt.tight_layout();<jupyter_output><empty_output><jupyter_text>---6. (3 pts) For each of the three clusters from 5 above, plot all of the averaged EEGs belonging to that cluster overlaid on each other. Thus, you'll have a separate plot for each cluster. Additionally, overlay on each plot the average EEG for that cluster plotted as a black line.<jupyter_code>[fig, ax] = plt.subplots(3,1)
for channel in range(eeg.shape[0]):
    cluster = labels[channel]
    ax[cluster].plot(time, eeg[channel,:])
for cluster in range(3):
    mask = (labels == cluster)
    clusterAvgEEG = eeg[mask,:].mean(axis=0)
    ax[cluster].plot(time, clusterAvgEEG, 'k-', lw=2)
    ax[cluster].set_ylabel(f'Cluster {cluster}')
ax[2].set_xlabel('Time (ms)')
plt.tight_layout();<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.12218045112781954, 'fraction_numerical': 0.018796992481203006, 'mean_word_length': 5.269513991163476, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '7', 'dir': 'jupyter-structured-clean-dedup', 'id': '262990', 'license': 'Unlicense', 'n_tokens_mistral': 1533, 'n_tokens_neox': 1414, 'n_words': 516, 'path': 'homework/key-pca.ipynb', 'repo_name': 'nishadalal120/NEU-365P-385L-Spring-2021', 'size': '4256'}