First commit
BIN
Exercise7/Data/bird_small.mat
Executable file
BIN
Exercise7/Data/bird_small.png
Executable file
|
After Width: | Height: | Size: 32 KiB |
BIN
Exercise7/Data/ex7data1.mat
Executable file
BIN
Exercise7/Data/ex7data2.mat
Executable file
BIN
Exercise7/Data/ex7faces.mat
Executable file
BIN
Exercise7/Figures/bird_compression.png
Executable file
|
After Width: | Height: | Size: 70 KiB |
BIN
Exercise7/Figures/faces.png
Executable file
|
After Width: | Height: | Size: 174 KiB |
BIN
Exercise7/Figures/faces_original.png
Executable file
|
After Width: | Height: | Size: 154 KiB |
BIN
Exercise7/Figures/faces_reconstructed.png
Executable file
|
After Width: | Height: | Size: 125 KiB |
BIN
Exercise7/Figures/kmeans_result.png
Executable file
|
After Width: | Height: | Size: 28 KiB |
BIN
Exercise7/Figures/pca_components.png
Executable file
|
After Width: | Height: | Size: 7.4 KiB |
BIN
Exercise7/Figures/pca_reconstruction.png
Executable file
|
After Width: | Height: | Size: 17 KiB |
1194
Exercise7/exercise7.ipynb
Executable file
236
Exercise7/utils.py
Executable file
@@ -0,0 +1,236 @@
|
||||
import sys
|
||||
import numpy as np
|
||||
from matplotlib import pyplot
|
||||
from matplotlib.animation import FuncAnimation
|
||||
import matplotlib as mpl
|
||||
|
||||
sys.path.append('..')
|
||||
from submission import SubmissionBase
|
||||
|
||||
|
||||
def displayData(X, example_width=None, figsize=(10, 10)):
|
||||
"""
|
||||
Displays 2D data in a nice grid.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
X : array_like
|
||||
The input data of size (m x n) where m is the number of examples and n is the number of
|
||||
features.
|
||||
|
||||
example_width : int, optional
|
||||
THe width of each 2-D image in pixels. If not provided, the image is assumed to be square,
|
||||
and the width is the floor of the square root of total number of pixels.
|
||||
|
||||
figsize : tuple, optional
|
||||
A 2-element tuple indicating the width and height of figure in inches.
|
||||
"""
|
||||
# Compute rows, cols
|
||||
if X.ndim == 2:
|
||||
m, n = X.shape
|
||||
elif X.ndim == 1:
|
||||
n = X.size
|
||||
m = 1
|
||||
X = X[None] # Promote to a 2 dimensional array
|
||||
else:
|
||||
raise IndexError('Input X should be 1 or 2 dimensional.')
|
||||
|
||||
example_width = example_width or int(np.round(np.sqrt(n)))
|
||||
example_height = int(n / example_width)
|
||||
|
||||
# Compute number of items to display
|
||||
display_rows = int(np.floor(np.sqrt(m)))
|
||||
display_cols = int(np.ceil(m / display_rows))
|
||||
|
||||
fig, ax_array = pyplot.subplots(display_rows, display_cols, figsize=figsize)
|
||||
fig.subplots_adjust(wspace=0.025, hspace=0.025)
|
||||
|
||||
ax_array = [ax_array] if m == 1 else ax_array.ravel()
|
||||
|
||||
for i, ax in enumerate(ax_array):
|
||||
ax.imshow(X[i].reshape(example_height, example_width, order='F'), cmap='gray')
|
||||
ax.axis('off')
|
||||
|
||||
|
||||
def featureNormalize(X):
|
||||
"""
|
||||
Normalizes the features in X returns a normalized version of X where the mean value of each
|
||||
feature is 0 and the standard deviation is 1. This is often a good preprocessing step to do when
|
||||
working with learning algorithms.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
X : array_like
|
||||
An dataset which is a (m x n) matrix, where m is the number of examples,
|
||||
and n is the number of dimensions for each example.
|
||||
|
||||
Returns
|
||||
-------
|
||||
X_norm : array_like
|
||||
The normalized input dataset.
|
||||
|
||||
mu : array_like
|
||||
A vector of size n corresponding to the mean for each dimension across all examples.
|
||||
|
||||
sigma : array_like
|
||||
A vector of size n corresponding to the standard deviations for each dimension across
|
||||
all examples.
|
||||
"""
|
||||
mu = np.mean(X, axis=0)
|
||||
X_norm = X - mu
|
||||
|
||||
sigma = np.std(X_norm, axis=0, ddof=1)
|
||||
X_norm /= sigma
|
||||
return X_norm, mu, sigma
|
||||
|
||||
|
||||
def plotProgresskMeans(i, X, centroid_history, idx_history):
|
||||
"""
|
||||
A helper function that displays the progress of k-Means as it is running. It is intended for use
|
||||
only with 2D data. It plots data points with colors assigned to each centroid. With the
|
||||
previous centroids, it also plots a line between the previous locations and current locations
|
||||
of the centroids.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
i : int
|
||||
Current iteration number of k-means. Used for matplotlib animation function.
|
||||
|
||||
X : array_like
|
||||
The dataset, which is a matrix (m x n). Note since the plot only supports 2D data, n should
|
||||
be equal to 2.
|
||||
|
||||
centroid_history : list
|
||||
A list of computed centroids for all iteration.
|
||||
|
||||
idx_history : list
|
||||
A list of computed assigned indices for all iterations.
|
||||
"""
|
||||
K = centroid_history[0].shape[0]
|
||||
pyplot.gcf().clf()
|
||||
cmap = pyplot.cm.rainbow
|
||||
norm = mpl.colors.Normalize(vmin=0, vmax=2)
|
||||
|
||||
for k in range(K):
|
||||
current = np.stack([c[k, :] for c in centroid_history[:i+1]], axis=0)
|
||||
pyplot.plot(current[:, 0], current[:, 1],
|
||||
'-Xk',
|
||||
mec='k',
|
||||
lw=2,
|
||||
ms=10,
|
||||
mfc=cmap(norm(k)),
|
||||
mew=2)
|
||||
|
||||
pyplot.scatter(X[:, 0], X[:, 1],
|
||||
c=idx_history[i],
|
||||
cmap=cmap,
|
||||
marker='o',
|
||||
s=8**2,
|
||||
linewidths=1,)
|
||||
pyplot.grid(False)
|
||||
pyplot.title('Iteration number %d' % (i+1))
|
||||
|
||||
|
||||
def runkMeans(X, centroids, findClosestCentroids, computeCentroids,
|
||||
max_iters=10, plot_progress=False):
|
||||
"""
|
||||
Runs the K-means algorithm.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
X : array_like
|
||||
The data set of size (m, n). Each row of X is a single example of n dimensions. The
|
||||
data set is a total of m examples.
|
||||
|
||||
centroids : array_like
|
||||
Initial centroid location for each clusters. This is a matrix of size (K, n). K is the total
|
||||
number of clusters and n is the dimensions of each data point.
|
||||
|
||||
findClosestCentroids : func
|
||||
A function (implemented by student) reference which computes the cluster assignment for
|
||||
each example.
|
||||
|
||||
computeCentroids : func
|
||||
A function(implemented by student) reference which computes the centroid of each cluster.
|
||||
|
||||
max_iters : int, optional
|
||||
Specifies the total number of interactions of K-Means to execute.
|
||||
|
||||
plot_progress : bool, optional
|
||||
A flag that indicates if the function should also plot its progress as the learning happens.
|
||||
This is set to false by default.
|
||||
|
||||
Returns
|
||||
-------
|
||||
centroids : array_like
|
||||
A (K x n) matrix of the computed (updated) centroids.
|
||||
idx : array_like
|
||||
A vector of size (m,) for cluster assignment for each example in the dataset. Each entry
|
||||
in idx is within the range [0 ... K-1].
|
||||
|
||||
anim : FuncAnimation, optional
|
||||
A matplotlib animation object which can be used to embed a video within the jupyter
|
||||
notebook. This is only returned if `plot_progress` is `True`.
|
||||
"""
|
||||
K = centroids.shape[0]
|
||||
idx = None
|
||||
idx_history = []
|
||||
centroid_history = []
|
||||
|
||||
for i in range(max_iters):
|
||||
idx = findClosestCentroids(X, centroids)
|
||||
|
||||
if plot_progress:
|
||||
idx_history.append(idx)
|
||||
centroid_history.append(centroids)
|
||||
|
||||
centroids = computeCentroids(X, idx, K)
|
||||
|
||||
if plot_progress:
|
||||
fig = pyplot.figure()
|
||||
anim = FuncAnimation(fig, plotProgresskMeans,
|
||||
frames=max_iters,
|
||||
interval=500,
|
||||
repeat_delay=2,
|
||||
fargs=(X, centroid_history, idx_history))
|
||||
return centroids, idx, anim
|
||||
|
||||
return centroids, idx
|
||||
|
||||
|
||||
class Grader(SubmissionBase):
|
||||
# Random Test Cases
|
||||
X = np.sin(np.arange(1, 166)).reshape(15, 11, order='F')
|
||||
Z = np.cos(np.arange(1, 122)).reshape(11, 11, order='F')
|
||||
C = Z[:5, :]
|
||||
idx = np.arange(1, 16) % 3
|
||||
|
||||
def __init__(self):
|
||||
part_names = ['Find Closest Centroids (k-Means)',
|
||||
'Compute Centroid Means (k-Means)',
|
||||
'PCA',
|
||||
'Project Data (PCA)',
|
||||
'Recover Data (PCA)']
|
||||
super().__init__('k-means-clustering-and-pca', part_names)
|
||||
|
||||
def __iter__(self):
|
||||
for part_id in range(1, 6):
|
||||
try:
|
||||
func = self.functions[part_id]
|
||||
# Each part has different expected arguments/different function
|
||||
if part_id == 1:
|
||||
res = 1 + func(self.X, self.C)
|
||||
elif part_id == 2:
|
||||
res = func(self.X, self.idx, 3)
|
||||
elif part_id == 3:
|
||||
U, S = func(self.X)
|
||||
res = np.hstack([U.ravel('F'), np.diag(S).ravel('F')]).tolist()
|
||||
elif part_id == 4:
|
||||
res = func(self.X, self.Z, 5)
|
||||
elif part_id == 5:
|
||||
res = func(self.X[:, :5], self.Z, 5)
|
||||
else:
|
||||
raise KeyError
|
||||
yield part_id, res
|
||||
except KeyError:
|
||||
yield part_id, 0
|
||||