在Python中解决看似(但实际上不是!)过度确定的稀疏线性系统

时间:2014-04-16 07:59:02

标签: python scipy linear-algebra

我有一个稀疏矩阵A(使用scipy.sparse)和一个向量b,想要解决Ax = b for x。 A的行数多于列数,因此它似乎超定;然而,A的行是线性相关的,因此实际上A的行级等于列的数量。例如,A可能是

A = np.array([[1., 1.], [-1., -1.], [1., 0.]])

而b是

b = np.array([0., 0., 1.])
然后解决方案是x = [1.,-1。]。我想知道如何使用scipy.sparse.linalg中提供的函数在Python中解决这个系统。谢谢!

2 个答案:

答案 0 :(得分:4)

您的系统可能欠定吗?如果不是,并且实际上有解决方案,则最小二乘解决方案将是该解决方案,因此您可以尝试

from scipy.sparse.linalg import lsqr
return_values = lsqr(A, b)
x = return_values[0]

如果您的系统实际上是欠定的,那么应该找到最小的L2规范解决方案。如果它不起作用,请将参数damp设置为非常小的值(例如1e-5)。

如果您的系统完全确定(即A是满级的)并且有一个解决方案,并且您的矩阵A很高,正如您所描述的那样,那么你可以在正规方程中找到一个等价的系统:

A.T.dot(A).dot(x) == A.T.dot(b)

x中有一个独特的解决方案。这是一个方形线性系统,因此可以使用scipy.sparse.linalg.spsolve

等线性系统求解器求解

答案 1 :(得分:2)

解决问题的正式方法是使用SVD。你有一个表格

的系统
A [MxN] * x [Nx1] = b [Mx1]

SVD将矩阵A分解为另外三个,所以你得到:

U [MxM] * S[MxN] * V[N*N] * x[Nx1] = b[Mx1]

矩阵UV都是正交的(它们的倒数是它们的转置),S是对角矩阵。如果我们改写上面的内容,我们得到:

S[MxN] * V [N * N] * x[Nx1] = U.T [MxM] * b [Mx1]

如果M > N,则矩阵S的最后M - N行将为零,如果您的系统确实存在,那么U.T b也应该具有最后一行M - N行为零。这意味着您可以将您的系统解决为:

>>> a = np.array([[1., 1.], [-1., -1.], [1., 0.]])
>>> b = np.array([0., 0., 1.])
>>> u, s, v = np.linalg.svd(a)
>>> np.allclose(u.T.dot(b)[-m+n:], 0) #check system is not overdetermined
True
>>> np.linalg.solve(s[:, None] * v, u.T.dot(b)[:n])
array([ 1., -1.])