1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- function [U,S,V] = spm_svd(X,U)
- % Computationally efficient SVD (that can handle sparse arguments)
- % FORMAT [U,S,V] = spm_svd(X,u)
- % X - (m x n) matrix
- % u - threshold (1 > u > 0) for normalized eigenvalues (default = 1e-6)
- % - a value of zero induces u = 64*eps
- %
- % U - {m x p} singular vectors
- % V - {m x p} singular variates
- % S - {p x p} singular values
- %__________________________________________________________________________
- % Copyright (C) 1994-2011 Wellcome Trust Centre for Neuroimaging
- % Karl Friston
- % $Id: spm_svd.m 6110 2014-07-21 09:36:13Z karl $
- % default thresholds - preclude singular vectors with small singular values
- %--------------------------------------------------------------------------
- if nargin < 2, U = 1e-6; end
- if U >= 1; U = U - 1e-6; end
- if U <= 0; U = 64*eps; end
- % deal with sparse matrices
- %--------------------------------------------------------------------------
- [M,N] = size(X);
- p = find(any(X,2));
- q = find(any(X,1));
- X = X(p,q);
- % SVD
- %--------------------------------------------------------------------------
- [i, j, s] = find(X);
- [m, n] = size(X);
- if any(i - j)
-
- % off-leading diagonal elements - full SVD
- %----------------------------------------------------------------------
- X = full(X);
- if m > n
-
- [v, S, v] = svd(X'*X,0);
- S = sparse(S);
- s = diag(S);
- j = find(s*length(s)/sum(s) > U);
- v = v(:,j);
- u = spm_en(X*v);
- S = sqrt(S(j,j));
-
- elseif m < n
-
- [u, S, u] = svd(X*X',0);
- S = sparse(S);
- s = diag(S);
- j = find(s*length(s)/sum(s) > U);
- u = u(:,j);
- v = spm_en(X'*u);
- S = sqrt(S(j,j));
-
- else
-
- [u, S, v] = svd(X,0);
- S = sparse(S);
- s = diag(S).^2;
- j = find(s*length(s)/sum(s) > U);
- v = v(:,j);
- u = u(:,j);
- S = S(j,j);
- end
-
- else
- S = sparse(1:n,1:n,s,m,n);
- u = speye(m,n);
- v = speye(m,n);
- [i, j] = sort(-s);
- S = S(j,j);
- v = v(:,j);
- u = u(:,j);
- s = diag(S).^2;
- j = find(s*length(s)/sum(s) > U);
- v = v(:,j);
- u = u(:,j);
- S = S(j,j);
-
- end
- % replace in full matrices
- %--------------------------------------------------------------------------
- j = length(j);
- U = sparse(M,j);
- V = sparse(N,j);
- if j
- U(p,:) = u;
- V(q,:) = v;
- end
|