-
Notifications
You must be signed in to change notification settings - Fork 2
/
myLDA.m
98 lines (80 loc) · 3.19 KB
/
myLDA.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
%
% myLDA( data, labels, numberOfFeatures )
%
% Arguments: data: is an MxN matrix, where M is the number of examples and
% n is the number of digits
% labels: Mx1 vector
% featuresToExtract: number of features to be extracted from the
% data (max is numberOfUniqueClasses-1)
%
% Returns: ldaData: the output data from the LDA algrorithm
% projectionVectors: the projection vectors from LDA
% eigVec: the eigenvectors from LDA
% eigVal the eigenvalues from LDA
%
% TODO add case where N > M (Use PCA to reduce N to M-1 then continue with
% LDA)
function [ldaData,projectionVectors,SB,eigVal] = myLDA( data, labels, featuresToExtract)
% Check the arguments
if ~exist('data', 'var')
error('Data argument required.');
end
if ~exist('labels', 'var')
error('Labels argument required.');
end
% Convert data and labels to double
data = double(data);
labels = double(labels);
% Get the number of features and examples of the data
numberOfExamples = size(data,1);
numberOfLabels = length(unique(labels));
uniqueLabels = unique(labels);
% LDA can produce at most (numberOfClasses - 1) new features
if exist('featuresToExtract', 'var')
if( featuresToExtract > (numberOfLabels-1))
error('LDA can produce at most numberOfClasses-1 new features');
end
else
featuresToExtract = numberOfLabels-1;
end
% Step 1: Find the indices for each class
for i = 1 : numberOfLabels
classExamples{i} = data(labels == uniqueLabels(i),:)';
meanClass{i} = mean(classExamples{i},2);
end
% Step 2: Calculate the within class scatter matrix
% This matrix gives the area each class covers
% classExamples{i} is MxN matrix - M is the number of features
% N is the number of examples
% Allocate space for SW
SW = zeros(size(classExamples{1},1),size(classExamples{1},1));
for i = 1 : numberOfLabels
for j = 1 : size(classExamples{i},2)
centeredData(j,:) = classExamples{i}(:,j) - meanClass{i};
end
SW = SW+ centeredData' * centeredData;
end
% Step 3: Calculate between class scatter matrix
% This matrix gives the entire area covered by the classes
%Calculate the mean of the entire data
meanData = mean(data,1);
% Allocate space for SB
SB = zeros(length(meanClass{1}));
for i = 1 : numberOfLabels
numberOfExamplesForClass = size(classExamples{i},2);
MeanData = meanClass{i}' - meanData;
SB = SB + numberOfExamplesForClass * (MeanData' * MeanData);
end
% Step 4: Calculate eigenvectors and eigenvalues of the
% inv(SW) * SB - Matlab suggest to use SW\SB
[eigVec, eigVal] = eig(SW\SB);
% Get the eigenvalues
bestEigVal = sortrows(diag(eigVal),-1);
for i = 1 : featuresToExtract
projectionVectors(:,i) = eigVec(:,diag(eigVal) == bestEigVal(i));
end
for i = 1 : numberOfExamples
centeredData(i,:) = data(i,:) - meanData;
end
ldaData = centeredData * projectionVectors;
end