forked from PRML/PRMLT
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfa.m
49 lines (42 loc) · 1.26 KB
/
fa.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
function [model, llh] = fa(X, q)
% Perform EM algorithm for factor analysis model
% X: m x n data matrix
% q: dimension of target space
% Reference: Pattern Recognition and Machine Learning by Christopher M. Bishop
% Written by Mo Chen ([email protected]).
[m,n] = size(X);
mu = mean(X,2);
X = bsxfun(@minus,X,mu);
tol = 1e-4;
maxiter = 500;
llh = -inf(1,maxiter);
I = eye(q);
r = dot(X,X,2);
W = rand(m,q);
invpsi = 1./rand(m,1);
for iter = 2:maxiter
% compute quantities needed
T = bsxfun(@times,W,sqrt(invpsi));
M = T'*T+I; % M = W'*inv(Psi)*W+I
U = chol(M);
G = U\(U'\I);
WinvPsiX = bsxfun(@times,W,invpsi)'*X; % WinvPsiX = W'*inv(Psi)*X
% likelihood
logdetC = 2*sum(log(diag(U)))-sum(log(invpsi)); % log(det(C))
Q = U'\WinvPsiX;
trinvCS = (r'*invpsi-dot(Q(:),Q(:)))/n; % trace(inv(C)*S)
llh(iter) = -n*(m*log(2*pi)+logdetC+trinvCS)/2;
if abs(llh(iter)-llh(iter-1)) < tol*abs(llh(iter-1)); break; end % check likelihood for convergence
% E step
Ez = G*WinvPsiX;
Ezz = n*G+Ez*Ez';
% M step
U = chol(Ezz);
XEz = X*Ez';
W = (XEz/U)/U';
invpsi = n./(r-dot(W,XEz,2));
end
llh = llh(2:iter);
model.W = W;
model.mu = mu;
model.psi = 1./invpsi;