% Qiang Qiu, Guillermo Sapiro, "Learning Transformations for Clustering and Classification", 
% JMLR 2015, http://jmlr.org/papers/volume16/qiu15a/qiu15a.pdf
% 
% Copyright @ Qiang Qiu, 2015
% qiang.qiu@duke.edu

clear all;
% warning off;

rng('default')
%% prepare data

% X1/Y1: train data/label (half (32) illumination for training)
% X2/Y2: test data/label (remaining half for testing)
load('X.mat', 'X1', 'Y1', 'X2', 'Y2');
% figure; im=imshow(reshape(X1(:,1), [16 16]), []); % 16x16 faces

N_class=length(unique(Y1)); % number of class
classid = unique(Y1);
T = eye(size(X1,1));

% visualize the original space
[mappedX, mapping] = laplacian_eigen(X1', 3, 12, 1, 'Matlab');
figure; 
subplot(1,2,1); scatter3(mappedX(:,1), mappedX(:,2), mappedX(:,3), 50, Y1, 'fill');
 
[IDXpred, accuracy, IDXdist] = knnprobe(X2', Y2', X1', Y1', 1);
fprintf(1,'(Before transform) NN recognition acc: %f  \n', accuracy);  

%% learn transformation T
t=cputime;

groupN = N_class;
X = X1;
groupcnt = 1;
sampleN = 30; 

for cc=1:N_class
    idx = find(Y1==classid(cc));
    idxN =length(idx);    
    ranidx = randperm(idxN);    
    if(idxN > sampleN)  % balance number of training samples
        idxN = sampleN;
    end    
    pfeat = normcol(X(:, [idx((1:idxN))]));
    F{groupcnt} = pfeat;
    groupcnt=groupcnt+1;
end

[T] = lowrankT([], F); % learn low-rank transform T.

fprintf(1,'learning transformation %f seconds\n',cputime-t);

% visualize the transformed space
[mappedX, mapping] = laplacian_eigen((T*X1)', 3, 12, 1, 'Matlab');
subplot(1,2,2); scatter3(mappedX(:,1), mappedX(:,2), mappedX(:,3), 50, Y1, 'fill');

[IDXpred, accuracy, IDXdist] = knnprobe((T*X2)', Y2', (T*X1)', Y1', 1);
fprintf(1,'(After transform) NN recognition acc: %f  \n', accuracy);  

