在MATLAB中找到矩阵的逆,inv(A)和A\eye(size(A))哪个更精确?

5
标题已经解释了一切。如果我需要找到矩阵的逆,是否有必要使用A\eye(size(A))而不是inv(A)呢? 在您问之前: 是的,我确实需要逆,不仅仅是为了计算。
PS:
isequal(inv(A), A\eye(size(A)))
ans =
 0

那么哪一个更精确呢?

更新:本问题被关闭,因为它似乎是一个重复的问题,与问题"为什么MATLAB中的inv如此缓慢和不准确"相同。然而,与这个问题不同的是,它没有涉及到函数inv的速度或准确性,而是讨论了使用inv.\eye计算矩阵的真实逆的差异。


inv 在 rand(4000) 矩阵上似乎比较快,但我不知道为什么。无穷范数的差异为 1e-10。这真是一个有趣的问题。 - Zoltán Csáti
只是出于好奇,你需要求逆矩阵做什么? - Rody Oldenhuis
1
更具体地说,为什么您需要精确计算逆矩阵呢?抄送:@RodyOldenhuis - Stewie Griffin
1
在计算机中求逆通常是一个坏主意!\<- 这会进行非常高级的数学运算,以便得到更好的解决方案。 - Ander Biguri
@RodyOldenhuis,我不想深入细节,但我们有一个优化方案,为了计算和基准灵敏度,我们需要复杂矩阵的逆。我已经成功地克服了实际计算逆矩阵的需求,然而,我认为这个问题很有趣。 - rst
有一些好的答案,该接受哪一个? - rst
3个回答

8

先不考虑性能(速度)和最佳实践。


eps(n) 是 MATLAB 中的一个命令,用于返回 n 下一个更大的双精度数与 n 的距离。因此,eps(1) = 2.2204e-16 表示在 1 后面的第一个数字是 1 + 2.2204e-16。同样地,eps(3000) = 4.5475e-13。现在,让我们来看看你的计算精度:

n = 100;
A = rand(n);
inv_A_1 = inv(A);
inv_A_2 = A \ eye(n);

max(max(abs(inv_A_1-inv_A_2)))
ans =
   1.6431e-14

eps(127) = 1.4211e-14
eps(128) = 2.8422e-14

对于整数而言,当两个矩阵之间的最大差值小于127时,您可以使用的具有更高精度的最大数字为127。

现在,我们来检查从两个逆矩阵中尝试重新创建单位矩阵时的精度。

error_1 = max(max(abs((A\eye(size(A))*A) - eye(size(A)))))
error_1 =
   3.1114e-14
error_2 = max(max(abs((inv(A)*A) - eye(size(A)))))
error_2 =
   2.3176e-14

两种方法之间最大差异的精度更高的最大整数为255。

总之,inv(A) 更准确,但一旦开始使用逆矩阵,它们在所有意图上都是相同的。


现在,让我们来看一下这两种方法的性能:

n = fix(logspace(1,3,40));
for i = 1:numel(n)
A = rand(round(n(i)));
t1(i) = timeit(@()inv(A));
t2(i) = timeit(@()A\eye(n(i)));
end
loglog(n,[t1;t2])

enter image description here

看起来,哪种方法更快取决于矩阵的大小。例如,对于n=255,使用inv会更慢,但对于n=256,则更快。


总之,选择方法要基于你觉得重要的因素。对于大多数目的,这两种方法是相同的。

请注意,如果你正在处理比例不良的矩阵,则svdpinv可能会很有用。如果它真的非常重要,你应该考虑Symbolic工具箱


我知道你说你“实际上需要倒数”,但我不能不说出:使用inv(A)*b永远不是解线性方程组的最佳方法!我不会再详细解释了,因为我认为你已经知道这一点。


4
如果您需要求逆,应使用inv
通过LU分解计算逆,而反斜杠运算符mldivide根据矩阵A的属性(参见https://scicomp.stackexchange.com/a/1004)使用不同的方法计算线性系统的解,这可能会导致逆的精度较低。
值得注意的是,如果您想解决线性系统,则使用mldivide(\)计算速度可能会更快,且更加准确。 MATLAB文档中的inv基本上是一个警告,不要使用inv来解决线性系统。

2

这是一种检查方法,不确定是否完全有用:将逆矩阵的结果乘回原始版本,并检查与单位矩阵的偏差:

A = rand( 111 );
E1 = abs( (A\eye(size(A) ) * A ) - eye( size(A) ) );
E2 = abs( ( inv(A) * A )         - eye( size(A) ) );
mean(E1(:))
mean(E2(:))

inv似乎比我预期的更加准确。也许有人可以重新评估一下。 ;)


这可能不是一个取消误差吗?因为inv(A)A和A \ eye(size(A))A都接近于eye(size(A))。但是,这种取消误差会存在于两种情况下,因此inv似乎更准确。浮点算术练习会有所帮助,但我在这方面并不精通。 - Zoltán Csáti
我得到了相同的结果,E2 的平均值略微较低。 - rst

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接