Cryptic matlab error when computing eigs - matlab

I am trying to find the 2 eignevectors of the 2 smallest eigenvalues of a laplacian. I do this by
[v,c]=eigs(L,M,2,'SM');
Where L is the lapalcian and M is the mass matrix.
As a result I get the error
Error using eigs/checkInputs/LUfactorAminusSigmaB (line 1041)
The shifted operator is singular. The shift is an eigenvalue.
Try to use some other shift please.
Error in eigs/checkInputs (line 855)
[L,U,pp,qq,dgAsB] = LUfactorAminusSigmaB;
Error in eigs (line 94)
[A,Amatrix,isrealprob,issymA,n,B,classAB,k,eigs_sigma,whch, ...
Does this mean I am doing something wrong, or is this just matlab choosing a bad initial guess for its iteration process?
The matrices I am using should have a descent condition number...

I ran into the same problem while implementing normalized cuts segmentation. The condition number is actually infinite because the smallest eigenvalue is 0, and this is basically what MATLAB's error message is about. It's running LU decomposition first.
I just added a multiple of I, 10*eps*speye, to the normalized Laplacian to improve conditioning and that fixed it.

I had the same problem with the eigs function. So I went the long (and maybe stupid) way but it did the job for me as my problem is not that big: (I will try to keep your notation)
% Solve the eigenvalue problem using the full matrices
[v,c]=eig(full(L),full(M));
% Sort out the eigenvalues using the sort function (the "-" sign is because you want the smallest real eigenvalues in magnitude)
[E,P] = sort(real(c),'descend'); % Here I am assuming you know all the eigenvalues have` negative real parts
% Now P is a vector that contains (in order) the indices of the row permutation operated by the % function sort.
% In order to obtain the two eigenvectors corresponding to the 2 smallest eigenvalues:
for k = 1:2
index = P(k);
lambda(k) = c(index,index); % use this to check if c(index,index)=E(k,k)
eigvec(:,k) = v(:,index); % corresponding eigenvector
end
Hope this helps
G

Related

How to multiply matrix of nxm with matrix nxmxp different dimensions in matlab

In my current analysis, I am trying to multiply a matrix (flm), of dimension nxm, with the inverse of a matrix nxmxp, and then use this result to multiply it by the inverse of the matrix (flm).
I was trying using the following code:
flm = repmat(Data.fm.flm(chan,:),[1 1 morder]); %chan -> is a vector 1by3
A = (flm(:,:,:)/A_inv(:,:,:))/flm(:,:,:);
However. due to the problem of dimensions, I am getting the following error message:
Error using ==> mrdivide
Inputs must be 2-D, or at least one
input must be scalar.
To compute elementwise RDIVIDE, use
RDIVIDE (./) instead.
I have no idea on how to proceed without using a for loop, so anyone as any suggestion?
I think you are looking for a way to conveniently multiply matrices when one is of higher dimensionality than the other. In that case you can use bxsfun to automatically 'expand' the smaller matrix.
x = rand(3,4);
y = rand(3,4,5);
bsxfun(#times,x,y)
It is quite simple, and very efficient.
Make sure to check out doc bsxfun for more examples.

Weird behavior of a sparse Matrix under MATLAB

I have been given this 63521x63521 real sparse symmetric matrix in MATLAB and for some reason it seems to be behaving weirdly for some commands.
I am not sure if there is a 'defect' in the matrix file or in the way I am using
MATLAB's commands.
Consider the following script. I have indicated the output of each of the steps.
% Gives sparsity shown as expected, so this works fine
spy(rYbus)
% I want the top 3 singular values of rYbus. But this line Returns empty matrix! Why/
S = svds(rYbus,3);
% Set exact answer and rhs and solve the linear system with iterative and direct method
b_exact = ones(size(Ybus,1),1);
rhs = rYbus*b_exact ;
% Following line gives Warning: Matrix is singular, close to singular or badly scaled.
% Results may be inaccurate. RCOND = NaN.
% > In Ybustest at 14.
b_numerical_1 = rYbus\rhs;
% Even for a single GMRES iteration b_numerical_2 is a vector of Nans. Why?
b_numerical_2 = gmres(rYbus,rhs,[],[],1);
Can anyone point out what may have gone wrong?
I have already used the "isnan" function to verify that the matrix rYbus
does not have any nans. The size of the matrix is 63521 x 63521
Have you checked if your input sparse matrix rYbus has any NaNs? If I remember correctly, svds can give you an empty matrix instead of an error.
Another possible error is the size of rYbus. What is the size of it?

Multivariate Random Number Generation in Matlab

I'm probably being a little dense but I'm not very mathsy and can't seem to understand the covariance element of creating multivariate data.
I'm after two columns of random data (representing two correlated variables).
I think I am right in needing to use the mvnrnd function and I understand that 'mu' must be a column of my mean vectors. As I need 4 distinct classes within my data these are going to be (1, 1) (-1 1) (1 -1) and (-1 -1). I assume I will have to do the function 4x with a different column of mean vectors each time and then combine them to get my full data set.
I don't understand what I should put for SIGMA - Matlab help tells me that it must be 'a d-by-d symmetric positive semi-definite matrix, or a d-by-d-by-n array' i.e. a covariance matrix. I don't understand how I create a covariance matrix for numbers that I am yet to generate.
Any advice would be greatly appreciated!
Assuming that I understood your case properly, I would go this way:
data = [normrnd(0,1,5000,1),normrnd(0,1,5000,1)]; %% your starting data series
MU = mean(data,1);
SIGMA = cov(data);
Now, it should be possible to feed mvnrnd with MU and SIGMA:
r = mvnrnd(MU,SIGMA,5000);
plot(r(:,1),r(:,2),'+') %% in case you wanna plot the results
I hope this helps.
I think your aim is to generate the simulated multivariate gaussian distributed data. For example, I use
k = 6; % feature dimension
mu = rand(1,k);
sigma = 10*eye(k,k);
unit matrix by 10 times is a symmetric positive semi-definite matrix. And the gaussian distribution will be more round than other type of sigma.
then you can use it as the above example of mvnrnd function and see the plot.

Matlab - how to compute PCA on a huge data set [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
MATLAB is running out of memory but it should not be
I want to perform PCA analysis on a huge data set of points. To be more specific, I have size(dataPoints) = [329150 132] where 328150 is the number of data points and 132 are the number of features.
I want to extract the eigenvectors and their corresponding eigenvalues so that I can perform PCA reconstruction.
However, when I am using the princomp function (i.e. [eigenVectors projectedData eigenValues] = princomp(dataPoints); I obtain the following error :
>> [eigenVectors projectedData eigenValues] = princomp(pointsData);
Error using svd
Out of memory. Type HELP MEMORY for your options.
Error in princomp (line 86)
[U,sigma,coeff] = svd(x0,econFlag); % put in 1/sqrt(n-1) later
However, if I am using a smaller data set, I have no problem.
How can I perform PCA on my whole dataset in Matlab? Have someone encountered this problem?
Edit:
I have modified the princomp function and tried to use svds instead of svd, but however, I am obtaining pretty much the same error. I have dropped the error bellow :
Error using horzcat
Out of memory. Type HELP MEMORY for your options.
Error in svds (line 65)
B = [sparse(m,m) A; A' sparse(n,n)];
Error in princomp (line 86)
[U,sigma,coeff] = svds(x0,econFlag); % put in 1/sqrt(n-1) later
Solution based on Eigen Decomposition
You can first compute PCA on X'X as #david said. Specifically, see the script below:
sz = [329150 132];
X = rand(sz);
[V D] = eig(X.' * X);
Actually, V holds the right singular vectors, and it holds the principal vectors if you put your data vectors in rows. The eigenvalues, D, are the variances among each direction. The singular vectors, which are the standard deviations, are computed as the square root of the variances:
S = sqrt(D);
Then, the left singular vectors, U, are computed using the formula X = USV'. Note that U refers to the principal components if your data vectors are in columns.
U = X*V*S^(-1);
Let us reconstruct the original data matrix and see the L2 reconstruction error:
X2 = U*S*V';
L2ReconstructionError = norm(X(:)-X2(:))
It is almost zero:
L2ReconstructionError =
6.5143e-012
If your data vectors are in columns and you want to convert your data into eigenspace coefficients, you should do U.'*X.
This code snippet takes around 3 seconds in my moderate 64-bit desktop.
Solution based on Randomized PCA
Alternatively, you can use a faster approximate method which is based on randomized PCA. Please see my answer in Cross Validated. You can directly compute fsvd and get U and V instead of using eig.
You may employ randomized PCA if the data size is too big. But, I think the previous way is sufficient for the size you gave.
My guess is that you have a huge data set. You don't need all of the svd coefficients. In this case, use svds instead of svd :
Taken directly from Matlab help:
s = svds(A,k) computes the k largest singular values and associated singular vectors of matrix A.
From your question, I understand that you don't call svd directly. But you might as well take a look at princomp (It is editable!) and alter the line that calls it.
You probably needed to calculate an n by n matrix in your computation somehow that is to say:
329150 * 329150 * 8btyes ~ 866GB`
of space which explains why you're getting a memory error. There seems to be an efficient way to calculate pca using princomp(X, 'econ') which I suggest you give it a try.
More on this in stackoverflow and mathworks..
Manually compute X'X (132x132) and svd on it. Or find NIPALS script.

Matlab inverse issue - fmri data - partial correlation algorithm

I'm using the following code To get a partial correlation matrix (original code from http://www.fmrib.ox.ac.uk/analysis/netsim/)
ic=-inv(cov(ts1)); % raw negative inverse covariance matrix
r=(ic ./ repmat(sqrt(diag(ic)),1,Nnodes)) ./ repmat(sqrt(diag(ic))',Nnodes,1); % use diagonal to get normalised coefficients
r=r+eye(Nnodes); % remove diagonal
My original matrix (ts1) is a brain activity over time course (X variable) in multiple voxels -volumetric pixel 3X3 (Y variable).
The problem is, I have more dependent variables(y -voxels ) than independent variables(x - time course).
I get the following Warning-
Warning: Matrix is close to singular or badly scaled.
Results may be inaccurate. RCOND = 4.998365e-022.
Any thoughts on how to fix the code so I'll get the partial correlation between all of the voxels?
The warning is from Matlab having a problem inverting the covariance matrix.
One solution might be to try pinv()
http://www.mathworks.com/help/techdoc/ref/pinv.html