矩阵的det在matlab中返回0

时间:2011-10-09 10:53:39

标签: matlab matrix-inverse determinants

我已经给出了一个非常大的矩阵(我不能改变矩阵的值),我需要计算(协方差)矩阵的逆。

有时我会收到错误

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

在这些情况下,我看到det的值返回0.

在计算逆(协方差矩阵)之前,我想检查det的值并执行类似的操作

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

有没有办法使用new det然后用它来计算协方差矩阵的逆?

3 个答案:

答案 0 :(得分:16)

叹息。计算确定奇点的行列式是一件荒谬的事情,完全如此。对于大型矩阵尤其如此。对不起,但确实如此。为什么?是的,有些书告诉你这样做。甚至可能是你的导师。

分析奇点是一回事。但是如何确定奇点的数值?除非您使用符号工具,否则MATLAB使用浮点运算。这意味着它将数字存储为浮点,双精度值。这些数字的数量不能小于

>> realmin
ans =
  2.2251e-308

(实际上,就非规范化数字而言,MATLAB略低于此值,可以降至约1e-323。)当我尝试存储小于该值的数字时,MATLAB认为它为零。

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

>> A = 1e-324
A =
     0

大矩阵会发生什么?例如,这个矩阵是单数的吗?

M = eye(1000);

由于M是单位矩阵,因此它非常明显。事实上,det确实表明它是非单数的。

>> det(M)
ans =
     1

但是,将它乘以某个常数。这是否使它成为非单数?没有!!!!!!!!!!!!!!!!!!!!!!!!当然不是。但无论如何都要试试。

>>     det(M*0.1)
ans =
     0

嗯。多数民众赞成。 MATLAB告诉我行列式为零。但我们知道决定因素是1e-1000。哦,是的。天哪,1e-1000比我刚刚向你展示的最小数字要小得多,MATLAB可以存储为双倍数。因此决定因素下溢,即使它明显不为零。矩阵是单数吗?当然不是。但是这里使用det失败了吗?当然会,这是完全可以预料的。

相反,使用一个好的工具来确定奇点。使用像cond或rank这样的工具。例如,我们可以欺骗排名吗?

>> rank(M)
ans =
        1000

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

看到等级知道这是一个完整的等级矩阵,无论我们是否扩展它。 cond也是如此,计算M的条件数。

>> cond(M)
ans =
     1

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

欢迎来到浮点运算世界。哦,顺便说一句,忘记det作为几乎所有使用浮点运算的计算的工具。这几乎总是一个糟糕的选择。

答案 1 :(得分:5)

Woodchips为您提供了一个非常好的解释,说明为什么不应该使用行列式。这似乎是一个常见的误解,你的问题与另一个关于反转矩阵的问题非常相关:Is there a fast way to invert a matrix in Matlab?,其中OP决定因为矩阵的行列式是1,它绝对是可逆的!这是我的答案的片段

  

而不是det(A)=1,而condition number of your matrix决定了逆的准确性或稳定性。请注意det(A)=∏i=1:n λi。因此,只需设置λ1=Mλn=1/Mλi≠1,n=1即可获得det(A)=1。但是,如M → ∞cond(A) = M2 → ∞λn → 0,意味着您的矩阵接近奇点,并且在计算逆矩阵时会出现大的数值误差。

您可以使用以下简单示例在MATLAB中对此进行测试:

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

%# calculate determinant
det(A)
ans =

     1

%# calculate condition number
cond(A)
ans =

   1.0000e+30

答案 2 :(得分:1)

在这种情况下,计算逆是不是一个好主意。如果您必须这样做,我建议使用它来提高显示精度:

format long;

其他建议可能是尝试使用矩阵的SVD并在那里修改奇异值。

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

Σ是一个对角矩阵,你会看到其中一个对角线条目接近于0.如果你想要某种近似值,请尝试使用这个数字。