为啥 numpy.linalg.solve() 提供比 numpy.linalg.inv() 更精确的矩阵求逆?

Posted

技术标签:

【中文标题】为啥 numpy.linalg.solve() 提供比 numpy.linalg.inv() 更精确的矩阵求逆?【英文标题】:Why does numpy.linalg.solve() offer more precise matrix inversions than numpy.linalg.inv()?为什么 numpy.linalg.solve() 提供比 numpy.linalg.inv() 更精确的矩阵求逆? 【发布时间】:2015-09-24 05:08:13 【问题描述】:

我不太明白为什么numpy.linalg.solve() 给出了更准确的答案,而numpy.linalg.inv() 则有些崩溃,给出了(我相信的)估计值。

举一个具体的例子,我正在求解方程C^-1 * d,其中C 表示一个矩阵,d 是一个向量数组。为便于讨论,C 的尺寸为形状(1000,1000)d 的尺寸为形状(1,1000)

numpy.linalg.solve(A, b) 为 x 求解方程 A*x=b,即 x = A^-1 * b. 因此,我可以通过以下方式求解这个方程

(1)

inverse = numpy.linalg.inv(C)
result = inverse * d

或 (2)

numpy.linalg.solve(C, d)

方法 (2) 给出了更精确的结果。为什么是这样?

究竟发生了什么使得一个“工作得更好”比另一个?

【问题讨论】:

最好拿起一本教科书。 Golub 和 van Loan 将是一个不错的选择。 只是一个猜测(可能来自 Gilbert Strang Books 的某处):我认为在调用底层 LAPACK 例程期间从未真正计算过逆。如果您尝试 pinv() 而不是 inv() 怎么办?看pinv()的引用 在大多数情况下,线性方程解法比反演和乘法更快,产生的舍入误差更小。从根本上说,这些是对“浮动”数字表示的操作,而不是实数本身。 知道pinv与solve的比较会很有趣 你几乎从不想计算一个矩阵的逆......它效率低下,而且误差通常高于其他方法。 【参考方案1】:

np.linalg.solve(A, b)计算A的逆。相反,它调用gesv LAPACK routines 之一,它首先使用LU 分解分解A,然后使用前向和后向替换求解x(参见here)。

np.linalg.inv 使用相同的方法来计算 A 的逆,通过在 A·A 中求解 A-1 -1 = I 其中 I 是身份*。分解步骤与上面完全相同,但需要更多的浮点运算来求解A-1(一个n×n矩阵) 而不是 x (一个 n-long 向量)。此外,如果您想通过身份 A-1·b = x 获得 x,那么额外的矩阵乘法将导致更多的浮动点操作,因此性能更慢,数值错误更多。

不需要计算A-1的中间步骤——直接得到x更快更准确。 p>


* inv 的相关源位是here。不幸的是,由于它是模板化的 C,因此有点难以理解。需要注意的重要一点是,单位矩阵作为参数 B 传递给 LAPACK 求解器。

【讨论】:

以上是关于为啥 numpy.linalg.solve() 提供比 numpy.linalg.inv() 更精确的矩阵求逆?的主要内容,如果未能解决你的问题,请参考以下文章

机器学习必备知识NumPy线性代数详解

具有不同 BLAS 实现的 NumPy 的性能

我应该为“名称”属性提啥?为啥会出现此验证错误?

为啥我VS老出着问题 求解答

C语言指针初学者 请帮我看看下面的提 为啥调用函数返回值是char型的 这样不就只能返回一个字符了吗

Eigen的速度为啥这么快