|
| 1 | +function [V,rho,A,rhotest]=mcca(X,d,Xtest,k) |
| 2 | +% [V,rho,A,rhotest]=mcca(X,d,Xtest,k) Multiset Canonical Correlation |
| 3 | +% Analysis. X is the data arranged as samples by dimension, whereby all |
| 4 | +% sets are concatenated along the dimensions. d is a vector with the |
| 5 | +% dimensions of each set. V are the component vectors and rho the resulting |
| 6 | +% inter-set correlations. A are the corresponding forward models, which |
| 7 | +% are returned as a list of length N. If Xtest is given, it will also |
| 8 | +% compute rho for the test data with the optimal V. If k is given then the |
| 9 | +% within-set correlation will be reduced in dimension from d to k prior to |
| 10 | +% inversion using PCA. This is useful for rank deficient data or for |
| 11 | +% regularization. If k is not given, dimension is reduced to the rank of |
| 12 | +% the data prior to inversion. |
| 13 | +% |
| 14 | +% See https://arxiv.org/abs/1802.03759, https://arxiv.org/abs/1801.08881 |
| 15 | + |
| 16 | +% Apr 30, 2018, Lucas Parra (c) |
| 17 | +% Sep 11, 2018, removed hack for forward model computation that broke the code sometimes |
| 18 | +% Sep 14, 2018, make forward model robust to ill conditioned data |
| 19 | +% Sep 15, 2018, keep simpler code in case that there is no regularization or rank problem |
| 20 | + |
| 21 | +if ~exist('k','var') || isempty(k), k=d; end |
| 22 | + |
| 23 | +N=length(d); |
| 24 | +R=cov(X); |
| 25 | +for i=N:-1:1, j=(1:d(i))+sum(d(1:i-1)); |
| 26 | + D(j,j)=R(j,j); |
| 27 | + k(i)=min(k(i),rank(D(j,j))); % check rank for oblivious users |
| 28 | +end |
| 29 | +if sum(d)==sum(k) % simple case |
| 30 | + [V,lambda]=eig(R,D); |
| 31 | +else % if rank deficient, or if regularization requested |
| 32 | + for i=N:-1:1, j=(1:d(i))+sum(d(1:i-1)); Dinv(j,j)=embedding.CCA.regInv(D(j,j),k(i)); end |
| 33 | + [V,lambda]=eigs(Dinv*R,sum(k)); |
| 34 | +end |
| 35 | +rho = (diag(lambda)-1)/(N-1); |
| 36 | +[~,indx]=sort(rho,'descend'); rho=rho(indx); V=V(:,indx); |
| 37 | + |
| 38 | +% compute forward models |
| 39 | +if nargout>2 |
| 40 | + for i=N:-1:1, j=(1:d(i))+sum(d(1:i-1)); |
| 41 | + W=V(j,1:k(i)); Rw=R(j,j); |
| 42 | + if k(i)==d(i), A{i}=Rw*W/(W'*Rw*W); % original formula, but wont work for rank deficient Rw |
| 43 | + else A{i}=Rw*W*diag(1./diag(W'*Rw*W)); end % ignores correlation of components but robust to ill conditioned Rw |
| 44 | + end |
| 45 | +end |
| 46 | + |
| 47 | +% compute rho for test data |
| 48 | +if exist('Xtest') && ~isempty(Xtest) |
| 49 | + R=cov(Xtest); |
| 50 | + for i=N:-1:1, j=(1:d(i))+sum(d(1:i-1)); D(j,j)=R(j,j); end |
| 51 | + lambda = diag(V'*R*V)./diag(V'*D*V); |
| 52 | + rhotest = (lambda-1)/(N-1); |
| 53 | +end |
| 54 | + |
| 55 | + |
0 commit comments