changeset 0:ded78d0b4987

init
author Jordi Gutiérrez Hermoso <jordigh@octave.org>
date Mon, 05 Dec 2011 00:19:20 -0500
parents
children 90d2a292663c
files bird_small.png computeCentroids.m displayData.m drawLine.m ex7.m ex7_pca.m ex7data1.mat ex7data2.mat featureNormalize.m findClosestCentroids.m kMeansInitCentroids.m pca.m plotDataPoints.m plotProgresskMeans.m projectData.m recoverData.m runkMeans.m submit.m submitWeb.m
diffstat 19 files changed, 1462 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..a3cd00c107b1b8740280b9c28dcdbec299325d3e
GIT binary patch
literal 33031
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
new file mode 100644
--- /dev/null
+++ b/computeCentroids.m
@@ -0,0 +1,40 @@
+function centroids = computeCentroids(X, idx, K)
+%COMPUTECENTROIDS returs the new centroids by computing the means of the 
+%data points assigned to each centroid.
+%   centroids = COMPUTECENTROIDS(X, idx, K) returns the new centroids by 
+%   computing the means of the data points assigned to each centroid. It is
+%   given a dataset X where each row is a single data point, a vector
+%   idx of centroid assignments (i.e. each entry in range [1..K]) for each
+%   example, and K, the number of centroids. You should return a matrix
+%   centroids, where each row of centroids is the mean of the data points
+%   assigned to it.
+%
+
+% Useful variables
+[m n] = size(X);
+
+% You need to return the following variables correctly.
+centroids = zeros(K, n);
+
+
+% ====================== YOUR CODE HERE ======================
+% Instructions: Go over every centroid and compute mean of all points that
+%               belong to it. Concretely, the row vector centroids(i, :)
+%               should contain the mean of the data points assigned to
+%               centroid i.
+%
+% Note: You can use a for-loop over the centroids to compute this.
+%
+
+
+
+
+
+
+
+
+% =============================================================
+
+
+end
+
new file mode 100644
--- /dev/null
+++ b/displayData.m
@@ -0,0 +1,59 @@
+function [h, display_array] = displayData(X, example_width)
+%DISPLAYDATA Display 2D data in a nice grid
+%   [h, display_array] = DISPLAYDATA(X, example_width) displays 2D data
+%   stored in X in a nice grid. It returns the figure handle h and the 
+%   displayed array if requested.
+
+% Set example_width automatically if not passed in
+if ~exist('example_width', 'var') || isempty(example_width) 
+	example_width = round(sqrt(size(X, 2)));
+end
+
+% Gray Image
+colormap(gray);
+
+% Compute rows, cols
+[m n] = size(X);
+example_height = (n / example_width);
+
+% Compute number of items to display
+display_rows = floor(sqrt(m));
+display_cols = ceil(m / display_rows);
+
+% Between images padding
+pad = 1;
+
+% Setup blank display
+display_array = - ones(pad + display_rows * (example_height + pad), ...
+                       pad + display_cols * (example_width + pad));
+
+% Copy each example into a patch on the display array
+curr_ex = 1;
+for j = 1:display_rows
+	for i = 1:display_cols
+		if curr_ex > m, 
+			break; 
+		end
+		% Copy the patch
+		
+		% Get the max value of the patch
+		max_val = max(abs(X(curr_ex, :)));
+		display_array(pad + (j - 1) * (example_height + pad) + (1:example_height), ...
+		              pad + (i - 1) * (example_width + pad) + (1:example_width)) = ...
+						reshape(X(curr_ex, :), example_height, example_width) / max_val;
+		curr_ex = curr_ex + 1;
+	end
+	if curr_ex > m, 
+		break; 
+	end
+end
+
+% Display Image
+h = imagesc(display_array, [-1 1]);
+
+% Do not show axis
+axis image off
+
+drawnow;
+
+end
new file mode 100644
--- /dev/null
+++ b/drawLine.m
@@ -0,0 +1,8 @@
+function drawLine(p1, p2, varargin)
+%DRAWLINE Draws a line from point p1 to point p2
+%   DRAWLINE(p1, p2) Draws a line from point p1 to point p2 and holds the
+%   current figure
+
+plot([p1(1) p2(1)], [p1(2) p2(2)], varargin{:});
+
+end
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/ex7.m
@@ -0,0 +1,170 @@
+%% Machine Learning Online Class
+%  Exercise 7 | Principle Component Analysis and K-Means Clustering
+%
+%  Instructions
+%  ------------
+%
+%  This file contains code that helps you get started on the
+%  exercise. You will need to complete the following functions:
+%
+%     pca.m
+%     projectData.m
+%     recoverData.m
+%     computeCentroids.m
+%     findClosestCentroids.m
+%     kMeansInitCentroids.m
+%
+%  For this exercise, you will not need to change any code in this file,
+%  or any other files other than those mentioned above.
+%
+
+%% Initialization
+clear ; close all; clc
+
+%% ================= Part 1: Find Closest Centroids ====================
+%  To help you implement K-Means, we have divided the learning algorithm 
+%  into two functions -- findClosestCentroids and computeCentroids. In this
+%  part, you shoudl complete the code in the findClosestCentroids function. 
+%
+fprintf('Finding closest centroids.\n\n');
+
+% Load an example dataset that we will be using
+load('ex7data2.mat');
+
+% Select an initial set of centroids
+K = 3; % 3 Centroids
+initial_centroids = [3 3; 6 2; 8 5];
+
+% Find the closest centroids for the examples using the
+% initial_centroids
+idx = findClosestCentroids(X, initial_centroids);
+
+fprintf('Closest centroids for the first 3 examples: \n')
+fprintf(' %d', idx(1:3));
+fprintf('\n(the closest centroids should be 1, 3, 2 respectively)\n');
+
+fprintf('Program paused. Press enter to continue.\n');
+pause;
+
+%% ===================== Part 2: Compute Means =========================
+%  After implementing the closest centroids function, you should now
+%  complete the computeCentroids function.
+%
+fprintf('\nComputing centroids means.\n\n');
+
+%  Compute means based on the closest centroids found in the previous part.
+centroids = computeCentroids(X, idx, K);
+
+fprintf('Centroids computed after initial finding of closest centroids: \n')
+fprintf(' %f %f \n' , centroids');
+fprintf('\n(the centroids should be\n');
+fprintf('   [ 2.428301 3.157924 ]\n');
+fprintf('   [ 5.813503 2.633656 ]\n');
+fprintf('   [ 7.119387 3.616684 ]\n\n');
+
+fprintf('Program paused. Press enter to continue.\n');
+pause;
+
+
+%% =================== Part 3: K-Means Clustering ======================
+%  After you have completed the two functions computeCentroids and
+%  findClosestCentroids, you have all the necessary pieces to run the
+%  kMeans algorithm. In this part, you will run the K-Means algorithm on
+%  the example dataset we have provided. 
+%
+fprintf('\nRunning K-Means clustering on example dataset.\n\n');
+
+% Load an example dataset
+load('ex7data2.mat');
+
+% Settings for running K-Means
+K = 3;
+max_iters = 10;
+
+% For consistency, here we set centroids to specific values
+% but in practice you want to generate them automatically, such as by
+% settings them to be random examples (as can be seen in
+% kMeansInitCentroids).
+initial_centroids = [3 3; 6 2; 8 5];
+
+% Run K-Means algorithm. The 'true' at the end tells our function to plot
+% the progress of K-Means
+[centroids, idx] = runkMeans(X, initial_centroids, max_iters, true);
+fprintf('\nK-Means Done.\n\n');
+
+fprintf('Program paused. Press enter to continue.\n');
+pause;
+
+%% ============= Part 4: K-Means Clustering on Pixels ===============
+%  In this exercise, you will use K-Means to compress an image. To do this,
+%  you will first run K-Means on the colors of the pixels in the image and
+%  then you will map each pixel on to it's closest centroid.
+%  
+%  You should now complete the code in kMeansInitCentroids.m
+%
+
+fprintf('\nRunning K-Means clustering on pixels from an image.\n\n');
+
+%  Load an image of a bird
+A = double(imread('bird_small.png'));
+A = A / 255; % Divide by 255 so that all values are in the range 0 - 1
+
+% Size of the image
+img_size = size(A);
+
+% Reshape the image into an Nx3 matrix where N = number of pixels.
+% Each row will contain the Red, Green and Blue pixel values
+% This gives us our dataset matrix X that we will use K-Means on.
+X = reshape(A, img_size(1) * img_size(2), 3);
+
+% Run your K-Means algorithm on this data
+% You should try different values of K and max_iters here
+K = 16; 
+max_iters = 10;
+
+% When using K-Means, it is important the initialize the centroids
+% randomly. 
+% You should complete the code in kMeansInitCentroids.m before proceeding
+initial_centroids = kMeansInitCentroids(X, K);
+
+% Run K-Means
+[centroids, idx] = runkMeans(X, initial_centroids, max_iters);
+
+fprintf('Program paused. Press enter to continue.\n');
+pause;
+
+
+%% ================= Part 5: Image Compression ======================
+%  In this part of the exercise, you will use the clusters of K-Means to
+%  compress an image. To do this, we first find the closest clusters for
+%  each example. After that, we 
+
+fprintf('\nApplying K-Means to compress an image.\n\n');
+
+% Find closest cluster members
+idx = findClosestCentroids(X, centroids);
+
+% Essentially, now we have represented the image X as in terms of the
+% indices in idx. 
+
+% We can now recover the image from the indices (idx) by mapping each pixel
+% (specified by it's index in idx) to the centroid value
+X_recovered = centroids(idx,:);
+
+% Reshape the recovered image into proper dimensions
+X_recovered = reshape(X_recovered, img_size(1), img_size(2), 3);
+
+% Display the original image 
+subplot(1, 2, 1);
+imagesc(A); 
+title('Original');
+
+% Display compressed image side by side
+subplot(1, 2, 2);
+imagesc(X_recovered)
+title(sprintf('Compressed, with %d colors.', K));
+
+
+fprintf('Program paused. Press enter to continue.\n');
+pause;
+
new file mode 100644
--- /dev/null
+++ b/ex7_pca.m
@@ -0,0 +1,231 @@
+%% Machine Learning Online Class
+%  Exercise 7 | Principle Component Analysis and K-Means Clustering
+%
+%  Instructions
+%  ------------
+%
+%  This file contains code that helps you get started on the
+%  exercise. You will need to complete the following functions:
+%
+%     pca.m
+%     projectData.m
+%     recoverData.m
+%     computeCentroids.m
+%     findClosestCentroids.m
+%     kMeansInitCentroids.m
+%
+%  For this exercise, you will not need to change any code in this file,
+%  or any other files other than those mentioned above.
+%
+
+%% Initialization
+clear ; close all; clc
+
+%% ================== Part 1: Load Example Dataset  ===================
+%  We start this exercise by using a small dataset that is easily to
+%  visualize
+%
+fprintf('Visualizing example dataset for PCA.\n\n');
+
+%  The following command loads the dataset. You should now have the 
+%  variable X in your environment
+load ('ex7data1.mat');
+
+%  Visualize the example dataset
+plot(X(:, 1), X(:, 2), 'bo');
+axis([0.5 6.5 2 8]); axis square;
+
+fprintf('Program paused. Press enter to continue.\n');
+pause;
+
+
+%% =============== Part 2: Principal Component Analysis ===============
+%  You should now implement PCA, a dimension reduction technique. You
+%  should complete the code in pca.m
+%
+fprintf('\nRunning PCA on example dataset.\n\n');
+
+%  Before running PCA, it is important to first normalize X
+[X_norm, mu, sigma] = featureNormalize(X);
+
+%  Run PCA
+[U, S] = pca(X_norm);
+
+%  Compute mu, the mean of the each feature
+
+%  Draw the eigenvectors centered at mean of data. These lines show the
+%  directions of maximum variations in the dataset.
+hold on;
+drawLine(mu, mu + 1.5 * S(1,1) * U(:,1)', '-k', 'LineWidth', 2);
+drawLine(mu, mu + 1.5 * S(2,2) * U(:,2)', '-k', 'LineWidth', 2);
+hold off;
+
+fprintf('Top eigenvector: \n');
+fprintf(' U(:,1) = %f %f \n', U(1,1), U(2,1));
+fprintf('\n(you should expect to see -0.707107 -0.707107)\n');
+
+fprintf('Program paused. Press enter to continue.\n');
+pause;
+
+
+%% =================== Part 3: Dimension Reduction ===================
+%  You should now implement the projection step to map the data onto the 
+%  first k eigenvectors. The code will then plot the data in this reduced 
+%  dimensional space.  This will show you what the data looks like when 
+%  using only the corresponding eigenvectors to reconstruct it.
+%
+%  You should complete the code in projectData.m
+%
+fprintf('\nDimension reduction on example dataset.\n\n');
+
+%  Plot the normalized dataset (returned from pca)
+plot(X_norm(:, 1), X_norm(:, 2), 'bo');
+axis([-4 3 -4 3]); axis square
+
+%  Project the data onto K = 1 dimension
+K = 1;
+Z = projectData(X_norm, U, K);
+fprintf('Projection of the first example: %f\n', Z(1));
+fprintf('\n(this value should be about 1.481274)\n\n');
+
+X_rec  = recoverData(Z, U, K);
+fprintf('Approximation of the first example: %f %f\n', X_rec(1, 1), X_rec(1, 2));
+fprintf('\n(this value should be about  -1.047419 -1.047419)\n\n');
+
+%  Draw lines connecting the projected points to the original points
+hold on;
+plot(X_rec(:, 1), X_rec(:, 2), 'ro');
+for i = 1:size(X_norm, 1)
+    drawLine(X_norm(i,:), X_rec(i,:), '--k', 'LineWidth', 1);
+end
+hold off
+
+fprintf('Program paused. Press enter to continue.\n');
+pause;
+
+%% =============== Part 4: Loading and Visualizing Face Data =============
+%  We start the exercise by first loading and visualizing the dataset.
+%  The following code will load the dataset into your environment
+%
+fprintf('\nLoading face dataset.\n\n');
+
+%  Load Face dataset
+load ('ex7faces.mat')
+
+%  Display the first 100 faces in the dataset
+displayData(X(1:100, :));
+
+fprintf('Program paused. Press enter to continue.\n');
+pause;
+
+%% =========== Part 5: PCA on Face Data: Eigenfaces  ===================
+%  Run PCA and visualize the eigenvectors which are in this case eigenfaces
+%  We display the first 36 eigenfaces.
+%
+fprintf(['\nRunning PCA on face dataset.\n' ...
+         '(this mght take a minute or two ...)\n\n']);
+
+%  Before running PCA, it is important to first normalize X by subtracting 
+%  the mean value from each feature
+[X_norm, mu, sigma] = featureNormalize(X);
+
+%  Run PCA
+[U, S] = pca(X_norm);
+
+%  Visualize the top 36 eigenvectors found
+displayData(U(:, 1:36)');
+
+fprintf('Program paused. Press enter to continue.\n');
+pause;
+
+
+%% ============= Part 6: Dimension Reduction for Faces =================
+%  Project images to the eigen space using the top k eigenvectors 
+%  If you are applying a machine learning algorithm 
+fprintf('\nDimension reduction for face dataset.\n\n');
+
+K = 100;
+Z = projectData(X_norm, U, K);
+
+fprintf('The projected data Z has a size of: ')
+fprintf('%d ', size(Z));
+
+fprintf('\n\nProgram paused. Press enter to continue.\n');
+pause;
+
+%% ==== Part 7: Visualization of Faces after PCA Dimension Reduction ====
+%  Project images to the eigen space using the top K eigen vectors and 
+%  visualize only using those K dimensions
+%  Compare to the original input, which is also displayed
+
+fprintf('\nVisualizing the projected (reduced dimension) faces.\n\n');
+
+K = 100;
+X_rec  = recoverData(Z, U, K);
+
+% Display normalized data
+subplot(1, 2, 1);
+displayData(X_norm(1:100,:));
+title('Original faces');
+axis square;
+
+% Display reconstructed data from only k eigenfaces
+subplot(1, 2, 2);
+displayData(X_rec(1:100,:));
+title('Recovered faces');
+axis square;
+
+fprintf('Program paused. Press enter to continue.\n');
+pause;
+
+
+%% === Part 8(a): Optional (ungraded) Exercise: PCA for Visualization ===
+%  One useful application of PCA is to use it to visualize high-dimensional
+%  data. In the last K-Means exercise you ran K-Means on 3-dimensional 
+%  pixel colors of an image. We first visualize this output in 3D, and then
+%  apply PCA to obtain a visualization in 2D.
+
+close all; close all; clc
+
+% Re-load the image from the previous exercise and run K-Means on it
+% For this to work, you need to complete the K-Means assignment first
+A = double(imread('bird_small.png'));
+A = A / 255;
+img_size = size(A);
+X = reshape(A, img_size(1) * img_size(2), 3);
+K = 16; 
+max_iters = 10;
+initial_centroids = kMeansInitCentroids(X, K);
+[centroids, idx] = runkMeans(X, initial_centroids, max_iters);
+
+%  Sample 1000 random indexes (since working with all the data is
+%  too expensive. If you have a fast computer, you may increase this.
+sel = floor(rand(1000, 1) * size(X, 1)) + 1;
+
+%  Setup Color Palette
+palette = hsv(K);
+colors = palette(idx(sel), :);
+
+%  Visualize the data and centroid memberships in 3D
+figure;
+scatter3(X(sel, 1), X(sel, 2), X(sel, 3), 10, colors);
+title('Pixel dataset plotted in 3D. Color shows centroid memberships');
+fprintf('Program paused. Press enter to continue.\n');
+pause;
+
+%% === Part 8(b): Optional (ungraded) Exercise: PCA for Visualization ===
+% Use PCA to project this cloud to 2D for visualization
+
+% Subtract the mean to use PCA
+[X_norm, mu, sigma] = featureNormalize(X);
+
+% PCA and project the data to 2D
+[U, S] = pca(X_norm);
+Z = projectData(X_norm, U, 2);
+
+% Plot in 2D
+figure;
+plotDataPoints(Z(sel, :), idx(sel), K);
+title('Pixel dataset plotted in 2D, using PCA for dimensionality reduction');
+fprintf('Program paused. Press enter to continue.\n');
+pause;
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..f9c396160204acdf128b42882e1824ecd75bda6d
GIT binary patch
literal 995
zc$@*_104KKK~zjZLLfCRFd$7qR4ry{Y-KDUP;6mzW^ZzBIv`L(S4mDbG%O%Pa%Ew3
zWn>_4ZaN@MZ*Cw?Z+0LtG$1lEIy5mlG&CSGFflP8ARr(hARr(hARr(hARr(hARr(h
zARr(hARr(hARr(hARr(hARr(hARr(hARr(B0ZB~{000160{{ScoGp=UOj8FGhVOu0
zT4=fS-rEnLoopI4fUbqwEg8}mqsBoTAWK$L+AU(LKn7B}O6p)ZVGb||i>p|PX4A4w
z;))p*i%ADbOQd`VS)<|>jdSC}O{ESEFk!pPc21r=Imt=hA8#B%5c!b=L2~93|M}nH
z{eP!(L~y*st)8=hBbob8ZrAi562*eNt}r$$Xw)9}ym~W>htb+1L&h2s{AT*?!2pTz
zk4@*~$rKFH_GQa>EXp$~%Tir3oEAKJ_Fg%KvZAy=fsTe{W2AK|mqt^T@9NhdiP3A^
zVb1l(qiN5)Exg2H`;(Oyqiz!GG7qe+Z<3<G{>qjyAB~a0@r9`|5_gq3%-A6oiQgps
z9qwoG+XeT;?vNDkYtDD6F9=aPutnf)kwR5=tUD+Y<5a|n;^CYq2wPNl%|QX~AF1gX
z>0_||j8eIhDnnT4?w|RLM2WO9l&7HZfT?T?`(kiyy@#Btm!VX2=ERR7J`Qfo$+Q(p
zP|V*yc8`dK!}(!vK@x+MroERR9pGVa-DtxuLJE_n`SI+)3ti!@g52yJG5X)g3MRS5
zQ2Um*YAOV<Z2Eo2mF;{u9mkgzD`?oLw2_;=(O4E7KA1X0!QK<lX8!V2#}{dfc|EJT
zMX$eFf02SOzDqq^&BA}OPBEj1#i>WUOP5P!*!sX0zV8y_9i}sw;uT@lS@pc{`*_ex
zpC}U-60o5vB9e(0q0VaGm*h=En?s<wv7g0Cc3$eXS}CYcqkQVq5`^B8``^4RL7IP0
z`q@baF?E0Oj4m4U!mFF7*To^6-aY5kC7?aS^IY?-6ssNM12so!5akmSb5%;*GFa@S
zgGQ^?)VPn!q1@>kgjxpH$;y+3N90&wJ1;E_(lE{#rYjf<9iH~0O#ud`#fR?sNf`vD
zLC0!2i|PjL?T(!c23+@aLuM8_Yt74+&t({D&CPl&k)r#L?~dtzii54RrGfQw`T9S<
zc)E?o!a2_e)~E!yuFPE{r$q3q#LNu$NfFh3wDZ}r0A@p1MWB+!&Y$!1vlHb|-D%F#
z{~(4bT$0xoqVN@UM?K5+-Prot*;#W8s$cJ%Zun9HqWD*TYjiZq>ib5n?_v>5DLHKA
R(RipbI+gFr@edSNPof^A*x~>H
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..de3f5b9b487beebcc79b7c28386d2c1d84f8bd3b
GIT binary patch
literal 4784
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
K7W@xVK`_vz&>xTh
new file mode 100644
--- /dev/null
+++ b/featureNormalize.m
@@ -0,0 +1,17 @@
+function [X_norm, mu, sigma] = featureNormalize(X)
+%FEATURENORMALIZE Normalizes the features in X 
+%   FEATURENORMALIZE(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.
+
+mu = mean(X);
+X_norm = bsxfun(@minus, X, mu);
+
+sigma = std(X_norm);
+X_norm = bsxfun(@rdivide, X_norm, sigma);
+
+
+% ============================================================
+
+end
new file mode 100644
--- /dev/null
+++ b/findClosestCentroids.m
@@ -0,0 +1,33 @@
+function idx = findClosestCentroids(X, centroids)
+%FINDCLOSESTCENTROIDS computes the centroid memberships for every example
+%   idx = FINDCLOSESTCENTROIDS (X, centroids) returns the closest centroids
+%   in idx for a dataset X where each row is a single example. idx = m x 1 
+%   vector of centroid assignments (i.e. each entry in range [1..K])
+%
+
+% Set K
+K = size(centroids, 1);
+
+% You need to return the following variables correctly.
+idx = zeros(size(X,1), 1);
+
+% ====================== YOUR CODE HERE ======================
+% Instructions: Go over every example, find its closest centroid, and store
+%               the index inside idx at the appropriate location.
+%               Concretely, idx(i) should contain the index of the centroid
+%               closest to example i. Hence, it should be a value in the 
+%               range 1..K
+%
+% Note: You can use a for-loop over the examples to compute this.
+%
+
+
+
+
+
+
+
+% =============================================================
+
+end
+
new file mode 100644
--- /dev/null
+++ b/kMeansInitCentroids.m
@@ -0,0 +1,26 @@
+function centroids = kMeansInitCentroids(X, K)
+%KMEANSINITCENTROIDS This function initializes K centroids that are to be 
+%used in K-Means on the dataset X
+%   centroids = KMEANSINITCENTROIDS(X, K) returns K initial centroids to be
+%   used with the K-Means on the dataset X
+%
+
+% You should return this values correctly
+centroids = zeros(K, size(X, 2));
+
+% ====================== YOUR CODE HERE ======================
+% Instructions: You should set centroids to randomly chosen examples from
+%               the dataset X
+%
+
+
+
+
+
+
+
+
+% =============================================================
+
+end
+
new file mode 100644
--- /dev/null
+++ b/pca.m
@@ -0,0 +1,31 @@
+function [U, S] = pca(X)
+%PCA Run principal component analysis on the dataset X
+%   [U, S, X] = pca(X) computes eigenvectors of the covariance matrix of X
+%   Returns the eigenvectors U, the eigenvalues (on diagonal) in S
+%
+
+% Useful values
+[m, n] = size(X);
+
+% You need to return the following variables correctly.
+U = zeros(n);
+S = zeros(n);
+
+% ====================== YOUR CODE HERE ======================
+% Instructions: You should first compute the covariance matrix. Then, you
+%               should use the "svd" function to compute the eigenvectors
+%               and eigenvalues of the covariance matrix. 
+%
+% Note: When computing the covariance matrix, remember to divide by m (the
+%       number of examples).
+%
+
+
+
+
+
+
+
+% =========================================================================
+
+end
new file mode 100644
--- /dev/null
+++ b/plotDataPoints.m
@@ -0,0 +1,14 @@
+function plotDataPoints(X, idx, K)
+%PLOTDATAPOINTS plots data points in X, coloring them so that those with the same
+%index assignments in idx have the same color
+%   PLOTDATAPOINTS(X, idx, K) plots data points in X, coloring them so that those 
+%   with the same index assignments in idx have the same color
+
+% Create palette
+palette = hsv(K + 1);
+colors = palette(idx, :);
+
+% Plot the data
+scatter(X(:,1), X(:,2), 15, colors);
+
+end
new file mode 100644
--- /dev/null
+++ b/plotProgresskMeans.m
@@ -0,0 +1,27 @@
+function plotProgresskMeans(X, centroids, previous, idx, K, i)
+%PLOTPROGRESSKMEANS is a helper function that displays the progress of 
+%k-Means as it is running. It is intended for use only with 2D data.
+%   PLOTPROGRESSKMEANS(X, centroids, previous, idx, K, i) plots the 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.
+%
+
+% Plot the examples
+plotDataPoints(X, idx, K);
+
+% Plot the centroids as black x's
+plot(centroids(:,1), centroids(:,2), 'x', ...
+     'MarkerEdgeColor','k', ...
+     'MarkerSize', 10, 'LineWidth', 3);
+
+% Plot the history of the centroids with lines
+for j=1:size(centroids,1)
+    drawLine(centroids(j, :), previous(j, :));
+end
+
+% Title
+title(sprintf('Iteration number %d', i))
+
+end
+
new file mode 100644
--- /dev/null
+++ b/projectData.m
@@ -0,0 +1,26 @@
+function Z = projectData(X, U, K)
+%PROJECTDATA Computes the reduced data representation when projecting only 
+%on to the top k eigenvectors
+%   Z = projectData(X, U, K) computes the projection of 
+%   the normalized inputs X into the reduced dimensional space spanned by
+%   the first K columns of U. It returns the projected examples in Z.
+%
+
+% You need to return the following variables correctly.
+Z = zeros(size(X, 1), K);
+
+% ====================== YOUR CODE HERE ======================
+% Instructions: Compute the projection of the data using only the top K 
+%               eigenvectors in U (first K columns). 
+%               For the i-th example X(i,:), the projection on to the k-th 
+%               eigenvector is given as follows:
+%                    x = X(i, :)';
+%                    projection_k = x' * U(:, k);
+%
+
+
+
+
+% =============================================================
+
+end
new file mode 100644
--- /dev/null
+++ b/recoverData.m
@@ -0,0 +1,28 @@
+function X_rec = recoverData(Z, U, K)
+%RECOVERDATA Recovers an approximation of the original data when using the 
+%projected data
+%   X_rec = RECOVERDATA(Z, U, K) recovers an approximation the 
+%   original data that has been reduced to K dimensions. It returns the
+%   approximate reconstruction in X_rec.
+%
+
+% You need to return the following variables correctly.
+X_rec = zeros(size(Z, 1), size(U, 1));
+
+% ====================== YOUR CODE HERE ======================
+% Instructions: Compute the approximation of the data by projecting back
+%               onto the original space using the top K eigenvectors in U.
+%
+%               For the i-th example Z(i,:), the (approximate)
+%               recovered data for dimension j is given as follows:
+%                    v = Z(i, :)';
+%                    recovered_j = v' * U(j, 1:K)';
+%
+%               Notice that U(j, 1:K) is a row vector.
+%               
+
+
+
+% =============================================================
+
+end
new file mode 100644
--- /dev/null
+++ b/runkMeans.m
@@ -0,0 +1,64 @@
+function [centroids, idx] = runkMeans(X, initial_centroids, ...
+                                      max_iters, plot_progress)
+%RUNKMEANS runs the K-Means algorithm on data matrix X, where each row of X
+%is a single example
+%   [centroids, idx] = RUNKMEANS(X, initial_centroids, max_iters, ...
+%   plot_progress) runs the K-Means algorithm on data matrix X, where each 
+%   row of X is a single example. It uses initial_centroids used as the
+%   initial centroids. max_iters specifies the total number of interactions 
+%   of K-Means to execute. plot_progress is a true/false flag that 
+%   indicates if the function should also plot its progress as the 
+%   learning happens. This is set to false by default. runkMeans returns 
+%   centroids, a Kxn matrix of the computed centroids and idx, a m x 1 
+%   vector of centroid assignments (i.e. each entry in range [1..K])
+%
+
+% Set default value for plot progress
+if ~exist('plot_progress', 'var') || isempty(plot_progress)
+    plot_progress = false;
+end
+
+% Plot the data if we are plotting progress
+if plot_progress
+    figure;
+    hold on;
+end
+
+% Initialize values
+[m n] = size(X);
+K = size(initial_centroids, 1);
+centroids = initial_centroids;
+previous_centroids = centroids;
+idx = zeros(m, 1);
+
+% Run K-Means
+for i=1:max_iters
+    
+    % Output progress
+    fprintf('K-Means iteration %d/%d...\n', i, max_iters);
+    if exist('OCTAVE_VERSION')
+        fflush(stdout);
+    end
+    
+    % For each example in X, assign it to the closest centroid
+    idx = findClosestCentroids(X, centroids);
+    
+    % Optionally, plot progress here
+    if plot_progress
+        plotProgresskMeans(X, centroids, previous_centroids, idx, K, i);
+        previous_centroids = centroids;
+        fprintf('Press enter to continue.\n');
+        pause;
+    end
+    
+    % Given the memberships, compute new centroids
+    centroids = computeCentroids(X, idx, K);
+end
+
+% Hold off if we are plotting progress
+if plot_progress
+    hold off;
+end
+
+end
+
new file mode 100644
--- /dev/null
+++ b/submit.m
@@ -0,0 +1,336 @@
+function submit(partId)
+%SUBMIT Submit your code and output to the ml-class servers
+%   SUBMIT() will connect to the ml-class server and submit your solution
+
+  fprintf('==\n== [ml-class] Submitting Solutions | Programming Exercise %s\n==\n', ...
+          homework_id());
+  if ~exist('partId', 'var') || isempty(partId)
+    partId = promptPart();
+  end
+  
+  % Check valid partId
+  partNames = validParts();
+  if ~isValidPartId(partId)
+    fprintf('!! Invalid homework part selected.\n');
+    fprintf('!! Expected an integer from 1 to %d.\n', numel(partNames) + 1);
+    fprintf('!! Submission Cancelled\n');
+    return
+  end
+
+  [login password] = loginPrompt();
+  if isempty(login)
+    fprintf('!! Submission Cancelled\n');
+    return
+  end
+
+  fprintf('\n== Connecting to ml-class ... '); 
+  if exist('OCTAVE_VERSION') 
+    fflush(stdout);
+  end
+  
+  % Setup submit list
+  if partId == numel(partNames) + 1
+    submitParts = 1:numel(partNames);
+  else
+    submitParts = [partId];
+  end
+
+  for s = 1:numel(submitParts)
+    % Submit this part
+    partId = submitParts(s);
+    
+    % Get Challenge
+    [login, ch, signature] = getChallenge(login);
+    if isempty(login) || isempty(ch) || isempty(signature)
+      % Some error occured, error string in first return element.
+      fprintf('\n!! Error: %s\n\n', login);
+      return
+    end
+  
+    % Attempt Submission with Challenge
+    ch_resp = challengeResponse(login, password, ch);
+    [result, str] = submitSolution(login, ch_resp, partId, output(partId), ...
+                                 source(partId), signature);
+                                 
+    fprintf('\n== [ml-class] Submitted Homework %s - Part %d - %s\n', ...
+            homework_id(), partId, partNames{partId});
+    fprintf('== %s\n', strtrim(str));
+    if exist('OCTAVE_VERSION') 
+      fflush(stdout);
+    end
+  end
+  
+end
+
+% ================== CONFIGURABLES FOR EACH HOMEWORK ==================
+
+function id = homework_id() 
+  id = '7';
+end
+
+function [partNames] = validParts()
+  partNames = { 
+                'Find Closest Centroids (k-Means)', ...
+                'Compute Centroid Means (k-Means)' ...
+                'PCA', ...
+                'Project Data (PCA)', ...
+                'Recover Data (PCA)' ...
+                };
+end
+
+function srcs = sources()
+  % Separated by part
+  srcs = { { 'findClosestCentroids.m' }, ...
+           { 'computeCentroids.m' }, ...
+           { 'pca.m' }, ...
+           { 'projectData.m' }, ...
+           { 'recoverData.m' } ...
+           };
+end
+
+function out = output(partId)
+  % Random Test Cases
+  X = reshape(sin(1:165), 15, 11);
+  Z = reshape(cos(1:121), 11, 11);
+  C = Z(1:5, :);
+  idx = (1 + mod(1:15, 3))';
+  if partId == 1
+    idx = findClosestCentroids(X, C);
+    out = sprintf('%0.5f ', idx(:));
+  elseif partId == 2
+    centroids = computeCentroids(X, idx, 3);
+    out = sprintf('%0.5f ', centroids(:));
+  elseif partId == 3
+    [U, S] = pca(X);
+    out = sprintf('%0.5f ', abs([U(:); S(:)]));
+  elseif partId == 4
+    X_proj = projectData(X, Z, 5);
+    out = sprintf('%0.5f ', X_proj(:));
+  elseif partId == 5
+    X_rec = recoverData(X(:,1:5), Z, 5);
+    out = sprintf('%0.5f ', X_rec(:));
+  end 
+end
+
+function url = challenge_url()
+  url = 'http://www.ml-class.org/course/homework/challenge';
+end
+
+function url = submit_url()
+  url = 'http://www.ml-class.org/course/homework/submit';
+end
+
+% ========================= CHALLENGE HELPERS =========================
+
+function src = source(partId)
+  src = '';
+  src_files = sources();
+  if partId <= numel(src_files)
+      flist = src_files{partId};
+      for i = 1:numel(flist)
+          fid = fopen(flist{i});
+          while ~feof(fid)
+            line = fgets(fid);
+            src = [src line];
+          end
+          fclose(fid);
+          src = [src '||||||||'];
+      end
+  end
+end
+
+function ret = isValidPartId(partId)
+  partNames = validParts();
+  ret = (~isempty(partId)) && (partId >= 1) && (partId <= numel(partNames) + 1);
+end
+
+function partId = promptPart()
+  fprintf('== Select which part(s) to submit:\n', ...
+          homework_id());
+  partNames = validParts();
+  srcFiles = sources();
+  for i = 1:numel(partNames)
+    fprintf('==   %d) %s [', i, partNames{i});
+    fprintf(' %s ', srcFiles{i}{:});
+    fprintf(']\n');
+  end
+  fprintf('==   %d) All of the above \n==\nEnter your choice [1-%d]: ', ...
+          numel(partNames) + 1, numel(partNames) + 1);
+  selPart = input('', 's');
+  partId = str2num(selPart);
+  if ~isValidPartId(partId)
+    partId = -1;
+  end
+end
+
+function [email,ch,signature] = getChallenge(email)
+  str = urlread(challenge_url(), 'post', {'email_address', email});
+
+  str = strtrim(str);
+  [email, str] = strtok (str, '|');
+  [ch, str] = strtok (str, '|');
+  [signature, str] = strtok (str, '|');
+end
+
+
+function [result, str] = submitSolution(email, ch_resp, part, output, ...
+                                        source, signature)
+
+  params = {'homework', homework_id(), ...
+            'part', num2str(part), ...
+            'email', email, ...
+            'output', output, ...
+            'source', source, ...
+            'challenge_response', ch_resp, ...
+            'signature', signature};
+
+  str = urlread(submit_url(), 'post', params);
+  
+  % Parse str to read for success / failure
+  result = 0;
+
+end
+
+% =========================== LOGIN HELPERS ===========================
+
+function [login password] = loginPrompt()
+  % Prompt for password
+  [login password] = basicPrompt();
+  
+  if isempty(login) || isempty(password)
+    login = []; password = [];
+  end
+end
+
+
+function [login password] = basicPrompt()
+  login = input('Login (Email address): ', 's');
+  password = input('Password: ', 's');
+end
+
+
+function [str] = challengeResponse(email, passwd, challenge)
+  salt = ')~/|]QMB3[!W`?OVt7qC"@+}';
+  str = sha1([challenge sha1([salt email passwd])]);
+  sel = randperm(numel(str));
+  sel = sort(sel(1:16));
+  str = str(sel);
+end
+
+
+% =============================== SHA-1 ================================
+
+function hash = sha1(str)
+  
+  % Initialize variables
+  h0 = uint32(1732584193);
+  h1 = uint32(4023233417);
+  h2 = uint32(2562383102);
+  h3 = uint32(271733878);
+  h4 = uint32(3285377520);
+  
+  % Convert to word array
+  strlen = numel(str);
+
+  % Break string into chars and append the bit 1 to the message
+  mC = [double(str) 128];
+  mC = [mC zeros(1, 4-mod(numel(mC), 4), 'uint8')];
+  
+  numB = strlen * 8;
+  if exist('idivide')
+    numC = idivide(uint32(numB + 65), 512, 'ceil');
+  else
+    numC = ceil(double(numB + 65)/512);
+  end
+  numW = numC * 16;
+  mW = zeros(numW, 1, 'uint32');
+  
+  idx = 1;
+  for i = 1:4:strlen + 1
+    mW(idx) = bitor(bitor(bitor( ...
+                  bitshift(uint32(mC(i)), 24), ...
+                  bitshift(uint32(mC(i+1)), 16)), ...
+                  bitshift(uint32(mC(i+2)), 8)), ...
+                  uint32(mC(i+3)));
+    idx = idx + 1;
+  end
+  
+  % Append length of message
+  mW(numW - 1) = uint32(bitshift(uint64(numB), -32));
+  mW(numW) = uint32(bitshift(bitshift(uint64(numB), 32), -32));
+
+  % Process the message in successive 512-bit chs
+  for cId = 1 : double(numC)
+    cSt = (cId - 1) * 16 + 1;
+    cEnd = cId * 16;
+    ch = mW(cSt : cEnd);
+    
+    % Extend the sixteen 32-bit words into eighty 32-bit words
+    for j = 17 : 80
+      ch(j) = ch(j - 3);
+      ch(j) = bitxor(ch(j), ch(j - 8));
+      ch(j) = bitxor(ch(j), ch(j - 14));
+      ch(j) = bitxor(ch(j), ch(j - 16));
+      ch(j) = bitrotate(ch(j), 1);
+    end
+  
+    % Initialize hash value for this ch
+    a = h0;
+    b = h1;
+    c = h2;
+    d = h3;
+    e = h4;
+    
+    % Main loop
+    for i = 1 : 80
+      if(i >= 1 && i <= 20)
+        f = bitor(bitand(b, c), bitand(bitcmp(b), d));
+        k = uint32(1518500249);
+      elseif(i >= 21 && i <= 40)
+        f = bitxor(bitxor(b, c), d);
+        k = uint32(1859775393);
+      elseif(i >= 41 && i <= 60)
+        f = bitor(bitor(bitand(b, c), bitand(b, d)), bitand(c, d));
+        k = uint32(2400959708);
+      elseif(i >= 61 && i <= 80)
+        f = bitxor(bitxor(b, c), d);
+        k = uint32(3395469782);
+      end
+      
+      t = bitrotate(a, 5);
+      t = bitadd(t, f);
+      t = bitadd(t, e);
+      t = bitadd(t, k);
+      t = bitadd(t, ch(i));
+      e = d;
+      d = c;
+      c = bitrotate(b, 30);
+      b = a;
+      a = t;
+      
+    end
+    h0 = bitadd(h0, a);
+    h1 = bitadd(h1, b);
+    h2 = bitadd(h2, c);
+    h3 = bitadd(h3, d);
+    h4 = bitadd(h4, e);
+
+  end
+
+  hash = reshape(dec2hex(double([h0 h1 h2 h3 h4]), 8)', [1 40]);
+  
+  hash = lower(hash);
+
+end
+
+function ret = bitadd(iA, iB)
+  ret = double(iA) + double(iB);
+  ret = bitset(ret, 33, 0);
+  ret = uint32(ret);
+end
+
+function ret = bitrotate(iA, places)
+  t = bitshift(iA, places - 32);
+  ret = bitshift(iA, places);
+  ret = bitor(ret, t);
+end
new file mode 100644
--- /dev/null
+++ b/submitWeb.m
@@ -0,0 +1,352 @@
+function submitWeb(partId)
+%SUBMITWEB Generates a base64 encoded string for web-based submissions
+%   SUBMITWEB() will generate a base64 encoded string so that you can submit your
+%   solutions via a web form
+
+  fprintf('==\n== [ml-class] Submitting Solutions | Programming Exercise %s\n==\n', ...
+          homework_id());
+  if ~exist('partId', 'var') || isempty(partId)
+    partId = promptPart();
+  end
+  
+  % Check valid partId
+  partNames = validParts();
+  if ~isValidPartId(partId)
+    fprintf('!! Invalid homework part selected.\n');
+    fprintf('!! Expected an integer from 1 to %d.\n', numel(partNames));
+    fprintf('!! Submission Cancelled\n');
+    return
+  end
+
+  [login] = loginPrompt();
+  if isempty(login)
+    fprintf('!! Submission Cancelled\n');
+    return
+  end
+  
+  [result] = submitSolution(login, partId, output(partId), ...
+                            source(partId));
+  result = base64encode(result);
+
+  fprintf('\nSave as submission file [submit_ex%s_part%d.txt]: ', ...
+          homework_id(), partId);
+  saveAsFile = input('', 's');
+  if (isempty(saveAsFile))
+    saveAsFile = sprintf('submit_ex%s_part%d.txt', homework_id(), partId);
+  end
+
+  fid = fopen(saveAsFile, 'w');
+  if (fid)
+    fwrite(fid, result);
+    fclose(fid);
+    fprintf('\nSaved your solutions to %s.\n\n', saveAsFile);
+    fprintf(['You can now submit your solutions through the web \n' ...
+             'form in the programming exercises. Select the corresponding \n' ...
+             'programming exercise to access the form.\n']);
+
+  else
+    fprintf('Unable to save to %s\n\n', saveAsFile);
+    fprintf(['You can create a submission file by saving the \n' ...
+             'following text in a file: (press enter to continue)\n\n']);
+    pause;
+    fprintf(result);
+  end                  
+
+end
+
+% ================== CONFIGURABLES FOR EACH HOMEWORK ==================
+
+function id = homework_id() 
+  id = '7';
+end
+
+function [partNames] = validParts()
+  partNames = { 
+                'Find Closest Centroids (k-Means)', ...
+                'Compute Centroid Means (k-Means)' ...
+                'PCA', ...
+                'Project Data (PCA)', ...
+                'Recover Data (PCA)' ...
+                };
+end
+
+function srcs = sources()
+  % Separated by part
+  srcs = { { 'findClosestCentroids.m' }, ...
+           { 'computeCentroids.m' }, ...
+           { 'pca.m' }, ...
+           { 'projectData.m' }, ...
+           { 'recoverData.m' } ...
+           };
+end
+
+function out = output(partId)
+  % Random Test Cases
+  X = reshape(sin(1:165), 15, 11);
+  Z = reshape(cos(1:121), 11, 11);
+  C = Z(1:5, :);
+  idx = (1 + mod(1:15, 3))';
+  if partId == 1
+    idx = findClosestCentroids(X, C);
+    out = sprintf('%0.5f ', idx(:));
+  elseif partId == 2
+    centroids = computeCentroids(X, idx, 3);
+    out = sprintf('%0.5f ', centroids(:));
+  elseif partId == 3
+    [U, S] = pca(X);
+    out = sprintf('%0.5f ', abs([U(:); S(:)]));
+  elseif partId == 4
+    X_proj = projectData(X, Z, 5);
+    out = sprintf('%0.5f ', X_proj(:));
+  elseif partId == 5
+    X_rec = recoverData(X(:,1:5), Z, 5);
+    out = sprintf('%0.5f ', X_rec(:));
+  end 
+end
+
+
+% ========================= SUBMIT HELPERS =========================
+
+function src = source(partId)
+  src = '';
+  src_files = sources();
+  if partId <= numel(src_files)
+      flist = src_files{partId};
+      for i = 1:numel(flist)
+          fid = fopen(flist{i});
+          while ~feof(fid)
+            line = fgets(fid);
+            src = [src line];
+          end
+          fclose(fid);
+          src = [src '||||||||'];
+      end
+  end
+end
+
+function ret = isValidPartId(partId)
+  partNames = validParts();
+  ret = (~isempty(partId)) && (partId >= 1) && (partId <= numel(partNames));
+end
+
+function partId = promptPart()
+  fprintf('== Select which part(s) to submit:\n', ...
+          homework_id());
+  partNames = validParts();
+  srcFiles = sources();
+  for i = 1:numel(partNames)
+    fprintf('==   %d) %s [', i, partNames{i});
+    fprintf(' %s ', srcFiles{i}{:});
+    fprintf(']\n');
+  end
+  fprintf('\nEnter your choice [1-%d]: ', ...
+          numel(partNames));
+  selPart = input('', 's');
+  partId = str2num(selPart);
+  if ~isValidPartId(partId)
+    partId = -1;
+  end
+end
+
+
+function [result, str] = submitSolution(email, part, output, source)
+
+  result = ['a:5:{' ...
+            p_s('homework') p_s64(homework_id()) ...
+            p_s('part') p_s64(part) ...
+            p_s('email') p_s64(email) ...
+            p_s('output') p_s64(output) ...
+            p_s('source') p_s64(source) ...
+            '}'];
+
+end
+
+function s = p_s(str)
+   s = ['s:' num2str(numel(str)) ':"' str '";'];
+end
+
+function s = p_s64(str)
+   str = base64encode(str, '');
+   s = ['s:' num2str(numel(str)) ':"' str '";'];
+end
+
+% =========================== LOGIN HELPERS ===========================
+
+function [login] = loginPrompt()
+  % Prompt for password
+  [login] = basicPrompt();
+end
+
+
+function [login] = basicPrompt()
+  login = input('Login (Email address): ', 's');
+end
+
+
+% =========================== Base64 Encoder ============================
+% Thanks to Peter John Acklam
+%
+
+function y = base64encode(x, eol)
+%BASE64ENCODE Perform base64 encoding on a string.
+%
+%   BASE64ENCODE(STR, EOL) encode the given string STR.  EOL is the line ending
+%   sequence to use; it is optional and defaults to '\n' (ASCII decimal 10).
+%   The returned encoded string is broken into lines of no more than 76
+%   characters each, and each line will end with EOL unless it is empty.  Let
+%   EOL be empty if you do not want the encoded string broken into lines.
+%
+%   STR and EOL don't have to be strings (i.e., char arrays).  The only
+%   requirement is that they are vectors containing values in the range 0-255.
+%
+%   This function may be used to encode strings into the Base64 encoding
+%   specified in RFC 2045 - MIME (Multipurpose Internet Mail Extensions).  The
+%   Base64 encoding is designed to represent arbitrary sequences of octets in a
+%   form that need not be humanly readable.  A 65-character subset
+%   ([A-Za-z0-9+/=]) of US-ASCII is used, enabling 6 bits to be represented per
+%   printable character.
+%
+%   Examples
+%   --------
+%
+%   If you want to encode a large file, you should encode it in chunks that are
+%   a multiple of 57 bytes.  This ensures that the base64 lines line up and
+%   that you do not end up with padding in the middle.  57 bytes of data fills
+%   one complete base64 line (76 == 57*4/3):
+%
+%   If ifid and ofid are two file identifiers opened for reading and writing,
+%   respectively, then you can base64 encode the data with
+%
+%      while ~feof(ifid)
+%         fwrite(ofid, base64encode(fread(ifid, 60*57)));
+%      end
+%
+%   or, if you have enough memory,
+%
+%      fwrite(ofid, base64encode(fread(ifid)));
+%
+%   See also BASE64DECODE.
+
+%   Author:      Peter John Acklam
+%   Time-stamp:  2004-02-03 21:36:56 +0100
+%   E-mail:      pjacklam@online.no
+%   URL:         http://home.online.no/~pjacklam
+
+   if isnumeric(x)
+      x = num2str(x);
+   end
+
+   % make sure we have the EOL value
+   if nargin < 2
+      eol = sprintf('\n');
+   else
+      if sum(size(eol) > 1) > 1
+         error('EOL must be a vector.');
+      end
+      if any(eol(:) > 255)
+         error('EOL can not contain values larger than 255.');
+      end
+   end
+
+   if sum(size(x) > 1) > 1
+      error('STR must be a vector.');
+   end
+
+   x   = uint8(x);
+   eol = uint8(eol);
+
+   ndbytes = length(x);                 % number of decoded bytes
+   nchunks = ceil(ndbytes / 3);         % number of chunks/groups
+   nebytes = 4 * nchunks;               % number of encoded bytes
+
+   % add padding if necessary, to make the length of x a multiple of 3
+   if rem(ndbytes, 3)
+      x(end+1 : 3*nchunks) = 0;
+   end
+
+   x = reshape(x, [3, nchunks]);        % reshape the data
+   y = repmat(uint8(0), 4, nchunks);    % for the encoded data
+
+   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+   % Split up every 3 bytes into 4 pieces
+   %
+   %    aaaaaabb bbbbcccc ccdddddd
+   %
+   % to form
+   %
+   %    00aaaaaa 00bbbbbb 00cccccc 00dddddd
+   %
+   y(1,:) = bitshift(x(1,:), -2);                  % 6 highest bits of x(1,:)
+
+   y(2,:) = bitshift(bitand(x(1,:), 3), 4);        % 2 lowest bits of x(1,:)
+   y(2,:) = bitor(y(2,:), bitshift(x(2,:), -4));   % 4 highest bits of x(2,:)
+
+   y(3,:) = bitshift(bitand(x(2,:), 15), 2);       % 4 lowest bits of x(2,:)
+   y(3,:) = bitor(y(3,:), bitshift(x(3,:), -6));   % 2 highest bits of x(3,:)
+
+   y(4,:) = bitand(x(3,:), 63);                    % 6 lowest bits of x(3,:)
+
+   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+   % Now perform the following mapping
+   %
+   %   0  - 25  ->  A-Z
+   %   26 - 51  ->  a-z
+   %   52 - 61  ->  0-9
+   %   62       ->  +
+   %   63       ->  /
+   %
+   % We could use a mapping vector like
+   %
+   %   ['A':'Z', 'a':'z', '0':'9', '+/']
+   %
+   % but that would require an index vector of class double.
+   %
+   z = repmat(uint8(0), size(y));
+   i =           y <= 25;  z(i) = 'A'      + double(y(i));
+   i = 26 <= y & y <= 51;  z(i) = 'a' - 26 + double(y(i));
+   i = 52 <= y & y <= 61;  z(i) = '0' - 52 + double(y(i));
+   i =           y == 62;  z(i) = '+';
+   i =           y == 63;  z(i) = '/';
+   y = z;
+
+   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+   % Add padding if necessary.
+   %
+   npbytes = 3 * nchunks - ndbytes;     % number of padding bytes
+   if npbytes
+      y(end-npbytes+1 : end) = '=';     % '=' is used for padding
+   end
+
+   if isempty(eol)
+
+      % reshape to a row vector
+      y = reshape(y, [1, nebytes]);
+
+   else
+
+      nlines = ceil(nebytes / 76);      % number of lines
+      neolbytes = length(eol);          % number of bytes in eol string
+
+      % pad data so it becomes a multiple of 76 elements
+      y = [y(:) ; zeros(76 * nlines - numel(y), 1)];
+      y(nebytes + 1 : 76 * nlines) = 0;
+      y = reshape(y, 76, nlines);
+
+      % insert eol strings
+      eol = eol(:);
+      y(end + 1 : end + neolbytes, :) = eol(:, ones(1, nlines));
+
+      % remove padding, but keep the last eol string
+      m = nebytes + neolbytes * (nlines - 1);
+      n = (76+neolbytes)*nlines - neolbytes;
+      y(m+1 : n) = '';
+
+      % extract and reshape to row vector
+      y = reshape(y, 1, m+neolbytes);
+
+   end
+
+   % output is a character array
+   y = char(y);
+
+end