为什么Mathematica和Python的答案在处理奇异矩阵方程时有所不同?

时间:2016-10-24 23:30:30

标签: python matlab numpy matrix linear-algebra

我一直在处理Python中 A = Bx 形式的线性代数问题,并将其与MATLAB和Mathematica中的同事代码进行比较。当 B 是一个奇异矩阵时,我们注意到了Python和其他人之间的差异。当使用numpy.linalg.solve()时,我抛出一个奇异矩阵错误,所以我反而实现了.pinv()(Moore Penrose伪逆)。

据我所知,存储逆是计算效率低的,如果有更好的方法来处理Python中的奇异矩阵,我首先会感到好奇。然而,我的问题的主旨在于Python如何从无限解空间中选择答案,以及为什么它选择与MATLAB和Mathematica不同的答案。

这是我的玩具问题:

B = np.array([[2,4,6],[1,0,3],[0,7,0]])
A = np.array([[12],[4],[7]])
BI = linalg.pinv(B)
x = BI.dot(A)

Python向我输出的答案是:

[[ 0.4]
[ 1. ]
[ 1.2]]

虽然这肯定是一个正确的答案,但它不是我想要的那个:(1,1,1)。为什么Python生成这个特定的解决方案?有没有办法返回解决方案的空间而不是一种可能的解决方案?我的同事的代码返回(1,1,1) - 是不是有一个原因使Python与Mathematica和MATLAB不同?

1 个答案:

答案 0 :(得分:2)

简而言之,您的代码(显然np.linalg.lstsq)使用了Moore-Penrose伪逆,它在np.linalg.pinv中实现。 MATLAB和Mathematica可能使用高斯消元法来解决系统问题。我们可以使用LU分解在Python中复制后一种方法:

B = np.array([[2,4,6],[1,0,3],[0,7,0]])
y = np.array([[12],[4],[7]])
P, L, U = scipy.linalg.lu(B)

这会将B分解为B = P L U,其中U现在是一个上对角矩阵,而P L是可逆的。特别是,我们发现:

>>> U
array([[ 2.,  4.,  6.],
       [ 0.,  7.,  0.],
       [ 0.,  0.,  0.]])

>>> np.linalg.inv(P @ L) @ y
array([[ 12.],
       [  7.],
       [  0.]])

目标是解决这个未确定的,转变的问题,U x = (P L)^{-1} y。解决方案集与原始问题相同。让解决方案写成x = (x_1, x_2, x_3)。然后我们立即看到任何解决方案都必须x_2 = 1。然后我们必须2 x_1 + 4 + 6 x_2 = 12。求解x_1,我们得到x_1 = 4 - 3 x_2。因此任何解决方案都采用(4 - 3 x_2, 1, x_2)形式。

为上述方法生成解决方案的最简单方法是选择x_2 = 1。然后x_1 = 1,你恢复了MATLAB给你的解决方案:(1,1,1)。

另一方面,np.linalg.pinv计算Moore-Penrose伪逆,这是满足B的伪逆属性的唯一矩阵。这里的重点是 unique 。因此,当你说:

  

我的问题在于Python如何从无限的解决方案空间中选择答案

答案是,当您使用伪逆时,所有选择都是由您完成的,因为np.linalg.pinv(B)是一个唯一矩阵,因此np.linalg.pinv(B) @ y是唯一的。

要生成完整的解决方案,请参阅@ali_m上面的评论。