forked from viggin/yan-prtools
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathftProc_lda_tr.m
71 lines (58 loc) · 1.92 KB
/
ftProc_lda_tr.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
function [Xnew, model] = ftProc_lda_tr(X,Y,param)
%Training Linear Discriminant Analysis (LDA).
% X: a matrix, each row is a sample.
% Y: a column vector, class label for X starting from 1.
% PARAM: struct of parameters. The beginning part of this code (before
% defParam) explains each parameter, and also sets the default parameters.
% You can change parameter p to x by setting PARAM.p = x. For parameters
% that are not set, default values will be used.
% Return:
% XNEW: a matrix, each row is a new feature vector.
% MODEL: struct containing coefficients.
%
% Use the generalized eigenvalue algorithm in Matlab eig(Sb,Sw). Although
% it can handle singular Sw, but sometimes do PCA before LDA will help.
% The function do not use PCA before LDA, only subtracts the mean.
%
% Ke YAN, 2016, Tsinghua Univ. http://yanke23.com, [email protected]
nClass = length(unique(Y));
postLdaDim = nClass-1; %the dimension of projected subspace.
defParam
[nSmp,nFt] = size(X);
postLdaDim = min(postLdaDim,nFt); % could not exceed nFt
mu = mean(X,1);
X = bsxfun(@minus,X,mu);
% sort X by label
[Y, I] = sort(Y);
Xperm = X(I,:); % permuted X
[~, I ,~] = unique(Y,'legacy');
nSmpCls = [I(1);diff(I)];
J = I-nSmpCls+1;
% calculate within-class average
delta_X = Xperm;
mu_per_class = zeros(nClass,nFt);
for p = 1:nClass
mu_per_class(p,:) = mean(delta_X(J(p):I(p),:),1);
delta_X(J(p):I(p),:) = delta_X(J(p):I(p),:)-...
repmat(mu_per_class(p,:),nSmpCls(p),1);
end
% within class scatter matrix
Sw = delta_X'*delta_X;
% between class scatter matrix
Sb = zeros(nFt);
for p = 1:nClass
Sb = Sb+nSmpCls(p)*mu_per_class(p,:)'*mu_per_class(p,:);
end
% Do LDA,Sb*V = lambda*Sw*V
[LDA_V, LDA_D] = eig(Sb,Sw);
LDA_D = diag(LDA_D);
LDA_D(isnan(LDA_D)) = -inf;
[LDA_D, I] = sort(LDA_D,'descend');
LDA_V = LDA_V(:,I);
model.W_prj = LDA_V(:,1:postLdaDim);
model.mu = mu;
model.eigVals = LDA_D';
model.postLdaDim = postLdaDim;
model.param = param;
Xnew = X*model.W_prj;
end