Commit | Line | Data |
---|---|---|
c3bc4705 BA |
1 | #helper to always have matrices as arg (TODO: put this elsewhere? improve?) |
2 | matricize <- function(X) | |
3 | { | |
4 | if (!is.matrix(X)) | |
5 | return (t(as.matrix(X))) | |
6 | return (X) | |
7 | } | |
8 | ||
c3b2c1ab BG |
9 | require(MASS) |
10 | EMGrank = function(Pi, Rho, mini, maxi, X, Y, tau, rank){ | |
c2028869 BG |
11 | #matrix dimensions |
12 | n = dim(X)[1] | |
13 | p = dim(X)[2] | |
14 | m = dim(Rho)[2] | |
15 | k = dim(Rho)[3] | |
16 | ||
17 | #init outputs | |
18 | phi = array(0, dim=c(p,m,k)) | |
19 | Z = rep(1, n) | |
c3bc4705 | 20 | # Pi = piInit |
c2028869 BG |
21 | LLF = 0 |
22 | ||
23 | #local variables | |
24 | Phi = array(0, dim=c(p,m,k)) | |
25 | deltaPhi = c(0) | |
26 | sumDeltaPhi = 0 | |
27 | deltaPhiBufferSize = 20 | |
28 | ||
29 | #main loop | |
30 | ite = 1 | |
c3bc4705 BA |
31 | while(ite<=mini || (ite<=maxi && sumDeltaPhi>tau)) |
32 | { | |
c2028869 | 33 | #M step: Mise à jour de Beta (et donc phi) |
c3bc4705 BA |
34 | for(r in 1:k) |
35 | { | |
36 | Z_indice = seq_len(n)[Z==r] #indices où Z == r | |
37 | if (length(Z_indice) == 0) | |
c2028869 | 38 | next |
c2028869 | 39 | #U,S,V = SVD of (t(Xr)Xr)^{-1} * t(Xr) * Yr |
c3bc4705 BA |
40 | s = svd( ginv(crossprod(matricize(X[Z_indice,]))) %*% |
41 | crossprod(matricize(X[Z_indice,]),matricize(Y[Z_indice,])) ) | |
42 | S = s$d | |
43 | U = s$u | |
44 | V = s$v | |
c2028869 BG |
45 | #Set m-rank(r) singular values to zero, and recompose |
46 | #best rank(r) approximation of the initial product | |
c3bc4705 BA |
47 | if(rank[r] < length(S)) |
48 | S[(rank[r]+1):length(S)] = 0 | |
49 | phi[,,r] = U %*% diag(S) %*% t(V) %*% Rho[,,r] | |
c2028869 BG |
50 | } |
51 | ||
c3bc4705 BA |
52 | #Etape E et calcul de LLF |
53 | sumLogLLF2 = 0 | |
54 | for(i in 1:n){ | |
55 | sumLLF1 = 0 | |
56 | maxLogGamIR = -Inf | |
57 | for(r in 1:k){ | |
58 | dotProduct = tcrossprod(Y[i,]%*%Rho[,,r]-X[i,]%*%phi[,,r]) | |
59 | logGamIR = log(Pi[r]) + log(det(Rho[,,r])) - 0.5*dotProduct | |
60 | #Z[i] = index of max (gam[i,]) | |
61 | if(logGamIR > maxLogGamIR){ | |
62 | Z[i] = r | |
63 | maxLogGamIR = logGamIR | |
64 | } | |
65 | sumLLF1 = sumLLF1 + exp(logGamIR) / (2*pi)^(m/2) | |
66 | } | |
67 | sumLogLLF2 = sumLogLLF2 + log(sumLLF1) | |
68 | } | |
c2028869 | 69 | |
c3bc4705 | 70 | LLF = -1/n * sumLogLLF2 |
c2028869 | 71 | |
c3bc4705 BA |
72 | #update distance parameter to check algorithm convergence (delta(phi, Phi)) |
73 | deltaPhi = c(deltaPhi, max(max(max((abs(phi-Phi))/(1+abs(phi))))) ) | |
74 | if(length(deltaPhi) > deltaPhiBufferSize){ | |
75 | l_1 = c(2:length(deltaPhi)) | |
76 | deltaPhi = deltaPhi[l_1] | |
77 | } | |
78 | sumDeltaPhi = sum(abs(deltaPhi)) | |
c2028869 | 79 | |
c3bc4705 BA |
80 | #update other local variables |
81 | Phi = phi | |
82 | ite = ite+1 | |
c2028869 BG |
83 | } |
84 | return(list(phi=phi, LLF=LLF)) | |
9ade3f1b | 85 | } |