if ~exist('filenamesTrain','var')
    clear all;
    load('eth-80_small.mat');
end

% addpaths
addpath('..\11.clustern');
addpath('..\7.lineare_modelle');

cluster_centers = 512;
num_examples = 1000;
numClasses = 4;
normalization = 1;

if ~exist('Means','var')    
    %%% start k-means and create cluster centers
    % make flexible
    allData = [];
    for j = 1:100
        data    = trainFeatures{j}.data;
        rnd     = randperm(size(data,1));
        data    = data(rnd(1:100),:);
        allData = [allData; data];
    end

    %%% start kmeans
    fprintf('start kmeans...');
    Means = kmeans_means(allData, cluster_centers);

    %%% compute how many clusters are NaN
    % tmpMean = Means(:,1);
    % sum(isnan(tmpMean))
    fprintf('done.\n');
end

if ~exist('trainFeatureMatrix','var')
    %%% find mapping and create histograms for each picture
    tic
    fprintf('extract histograms...');
    trainFeatureMatrix  = zeros(size(trainFeatures,1),cluster_centers);
    testFeatureMatrix   = zeros(size(testFeatures,1),cluster_centers);
    for i = 1:size(trainFeatureMatrix,1)
        % map points to clusters
        tmpMapping      = findMapping(trainFeatures{i}.data,Means);
        % map vectors to integers
        integerMapping  = tmpMapping*(1:cluster_centers)';
        % create histogram
        trainFeatureMatrix(i,:) = hist(integerMapping,1:cluster_centers);
        % normalization
        if ((norm(trainFeatureMatrix(i,:)) ~= 0) && normalization)
            trainFeatureMatrix(i,:) = trainFeatureMatrix(i,:)./norm(trainFeatureMatrix(i,:));
        end
    end
    for i = 1:size(testFeatureMatrix,1)
        % map points to clusters
        tmpMapping      = findMapping(testFeatures{i}.data,Means);
        % map vectors to integers
        integerMapping  = tmpMapping*(1:cluster_centers)';
        % create histogram
        testFeatureMatrix(i,:) = hist(integerMapping,1:cluster_centers);
        % normalization
        if ((norm(testFeatureMatrix(i,:)) ~= 0) && normalization)
            testFeatureMatrix(i,:) = testFeatureMatrix(i,:)./norm(testFeatureMatrix(i,:));
        end
    end
    fprintf('done.\n');
    toc
end




% Anzahl von Trainingsdaten, die zur Evaluierung genutzt werden
numEval = 250;
% Permutiere Trainingsdaten um Evaluationdaten auszuwählen
rndIds  = randperm(numel(trainLabels));
% Setze den Bereich für mögliche C's in der Holdout-Validierung
C = [0.1,1,10];
if ~exist('models','var')
    % Lerne ein Modell für jede Klasse
    models = zeros(cluster_centers,numClasses);
    for i = 1:numClasses
        fprintf(['start to learn a model for class ' num2str(i) '...']);
        classID = i;
        Ytr = 2*(trainLabels == classID)-1;
        Xtr = trainFeatureMatrix;
        Ytest = 2*(testLabels == classID)-1;
        Xtest = testFeatureMatrix;
        Yeval   = Ytr(rndIds(1:numEval));
        Xeval   = Xtr(rndIds(1:numEval),:);
        Ytr     = Ytr(rndIds(numEval + 1:end));
        Xtr     = Xtr(rndIds(numEval + 1:end),:);
        % Starte Hold-out Validierung zur Bestimmung des optimalen C's
        accs = [];
        parfor j = 1:numel(C)
            %fprintf('train model...');
            %tic
            w = learnRegERM(Xtr, Ytr, C(j), @hinge, @omega2);
            %toc
            %fprintf('done.\n');
            %fprintf('test model on evaluation set...')
            Ypred = classRegERM(w, Xeval);
            Accuracy = 100*sum(Ypred == Yeval)/length(Yeval)
            %fprintf('done.\n')
            accs = [accs; Accuracy];
        end
        % lerne Modell auf gesamten Trainingsdaten mit optimalen C
        [valueMax,idxMax] = max(accs);
        w = learnRegERM([Xtr;Xeval],[Ytr;Yeval],C(idxMax), @hinge, @omega2);
        models(:,i) = w;
        fprintf(['done.\n']);
        % Ypred = classRegERM(w, Xtest);
        % 
        % % Genauigkeit auf allen Testbeispielen
        % Accuracy = 100*sum(Ypred == Ytest)/length(Ytest)
        % 
        % % Genauigkeit auf positiven Testbeispielen
        % i = find(Ytest > 0);
        % Accuracy_pos = 100*sum(Ypred(i) == Ytest(i))/length(i)
        % 
        % % Genauigkeit auf positiven Testbeispielen
        % i = find(Ytest < 0);
        % Accuracy_neg = 100*sum(Ypred(i) == Ytest(i))/length(i)
    end
end


% Klassifiziere die Testbilder
decMatrix = zeros(size(Xtest,1),numClasses);
for i = 1:numClasses
    decMatrix(:,i) = Xtest*models(:,i);
end
[valuesMax,Ypred] = max(decMatrix,[],2);
% Bestimmt Genauigkeit
Accuracy = 100*sum(Ypred == testLabels)/length(testLabels)


% Zeige die 10 bilder mit dem höchsten Score für jede Klasse
figure(2);
hold on;
counter = 1;
for i = 1:numClasses
    [~, sortIdx] = sort(decMatrix(:,i),'descend');
    for j = 1:10
        subplot(4,10,counter);
        counter = counter + 1;
        imshow(filenamesTest{sortIdx(j)});
    end
end
hold off;
