开发者

det of a matrix returns 0 in matlab

I have been give a very large matrix (I cannot change the values of the matrix) and I need to calculate the inverse of a (covariance) matrix.

Sometimes I get the error saying

 Matrix is close to singular or badly scaled.
     Results may be inaccurate

In these situations I see that t开发者_开发知识库he value of the det returns 0.

Before calculating inverse (of a covariance matrix) I want to check the value of the det and perform something like this

covarianceFea=cov(fea_class);
covdet=det(covarianceFea);
if(covdet ==0)
    covdet=covdet+.00001;
    %calculate the covariance using this new det
end 

Is there any way to use the new det and then use this to calculate the inverse of the covariance matrix?


Sigh. Computation of the determinant to determine singularity is a ridiculous thing to do, utterly so. Especially so for a large matrix. Sorry, but it is. Why? Yes, some books tell you to do it. Maybe even your instructor.

Analytical singularity is one thing. But how about numerical determination of singularity? Unless you are using a symbolic tool, MATLAB uses floating point arithmetic. This means it stores numbers as floating point, double precision values. Those numbers cannot be smaller in magnitude than

>> realmin
ans =
  2.2251e-308

(Actually, MATLAB goes a bit lower than that, in terms of denormalized numbers, which can go down to approximately 1e-323.) See that when I try to store a number smaller than that, MATLAB thinks it is zero.

>> A = 1e-323
A =
  9.8813e-324

>> A = 1e-324
A =
     0

What happens with a large matrix? For example, is this matrix singular:

M = eye(1000);

Since M is an identity matrix, it is fairly clearly non-singular. In fact, det does suggest that it is non-singular.

>> det(M)
ans =
     1

But, multiply it by some constant. Does that make it non-singular? NO!!!!!!!!!!!!!!!!!!!!!!!! Of course not. But try it anyway.

>>     det(M*0.1)
ans =
     0

Hmm. Thats is odd. MATLAB tells me the determinant is zero. But we know that the determinant is 1e-1000. Oh, yes. Gosh, 1e-1000 is smaller, by a considerable amount than the smallest number that I just showed you that MATLAB can store as a double. So the determinant underflows, even though it is obviously non-zero. Is the matrix singular? Of course not. But does the use of det fail here? Of course it will, and this is completely expected.

Instead, use a good tool for the determination of singularity. Use a tool like cond, or rank. For example, can we fool rank?

>> rank(M)
ans =
        1000

>> rank(M*.1)
ans =
        1000

See that rank knows this is a full rank matrix, regardless of whether we scale it or not. The same is true of cond, computing the condition number of M.

>> cond(M)
ans =
     1

>> cond(M*.1)
ans =
     1

Welcome to the world of floating point arithmetic. And oh, by the way, forget about det as a tool for almost any computation using floating point arithmetic. It is a poor choice almost always.


Woodchips has given you a very good explanation for why you shouldn't use the determinant. This seems to be a common misconception and your question is very related to another question on inverting matrices: Is there a fast way to invert a matrix in Matlab?, where the OP decided that because the determinant of his matrix was 1, it was definitely invertible! Here's a snippet from my answer

Rather than det(A)=1, it is the condition number of your matrix that dictates how accurate or stable the inverse will be. Note that det(A)=∏i=1:n λi. So just setting λ1=M, λn=1/M and λi≠1,n=1 will give you det(A)=1. However, as M → ∞, cond(A) = M2 → ∞ and λn → 0, meaning your matrix is approaching singularity and there will be large numerical errors in computing the inverse.

You can test this in MATLAB with the following simple example:

A = eye(10);
A([1 2]) = [1e15 1e-15];

%# calculate determinant
det(A)
ans =

     1

%# calculate condition number
cond(A)
ans =

   1.0000e+30


In such a scenario, calculating an inverse is not a very good idea. If you just have to do it, I would suggest using this to increase display precision:

format long;

Other suggestion could be to try using an SVD of the matrix and tinker around with singular values there.

A = U∑V'
inv(A) = V*inv(∑)*U'

∑ is a diagonal matrix where you will see one of the diagonal entries close to 0. Try playing around with this number if you want some sort of an approximation.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜