
% A naive bayes classifier. Takes in test data, training data,
% and correct classes for training data. Outputs a vector of
% predicted classes for test data.

function classVector = naiveBayes(testData, trainingX, trainingY)


%
% SECTION 1.
% LEARNING
%

trainingSize = size(trainingX);

samples = trainingSize(1);    % amount of samples
sampleSize = trainingSize(2); % amount of features in a sample
classes = max(trainingY);     % amount of classes

% structure for knowledge that we have learned.

% P(X|Y), how many ones have we seen for each y?
learn(1:classes, 1:sampleSize) = 0;

% P(Y), How many samples seen for each y in total?
counts(1:classes) = 0;

% go through all samples
for i=1:samples;
    yval = trainingY(i);
    sample = trainingX(i, :);
    
    % increment 1 events, do nothing with 0 events.
    % increment counter for this class.
    learn(yval, :) = learn(yval, :) + sample;
    counts(yval) = counts(yval) + 1;
end

% normalize to probabilities P(X|Y)
for i=1:classes;
    learn(i, :) = learn(i, :) / counts(i);
end

% normalize to probabilities P(Y)
counts(:) = counts(:) / sum(counts);





%
% SECTION 2.
% CLASSIFYING
%

% Go through the test data to classify it.
testSize = size(testData);
numSamples = testSize(1);
classVector(1:numSamples) = 0;

for i=1:numSamples;
    sample = testData(i, :);     % take sample
    y_approx(1:classes) = 0;     % at first everything has same probability
    y_approx = y_approx + log(counts); % then probabilities biased on P(Y)
    
    for y = 1:classes;
        for k=1:sampleSize;
            if sample(k) == 1
                y_approx(y) = y_approx(y) + log(learn(y, k));
            else
                y_approx(y) = y_approx(y) + log(1 - learn(y, k));
            end
        end
    end
    
    [y_approx, index] = sort(y_approx, 'descend');
    classVector(i) = index(1);
end

