左矩阵除法与Numpy求解

19 投票
3 回答
39242 浏览
提问于 2025-04-17 00:11

我正在尝试把包含 \ 运算符的 Matlab (Octave) 代码转换成 Python。下面是一个示例代码:

B = [2;4]
b = [4;4]
B \ b

这个代码可以正常运行,结果是 1.2。使用这个网页:

http://mathesaurus.sourceforge.net/matlab-numpy.html

我把它翻译成了:

import numpy as np
import numpy.linalg as lin
B = np.array([[2],[4]])
b = np.array([[4],[4]])
print lin.solve(B,b)

但是这给我带来了一个错误:

numpy.linalg.linalg.LinAlgError: Array must be square

为什么 Matlab 的 \ 运算符可以在 B 不是方阵的情况下使用?

有没有解决办法?

3 个回答

3

你可以形成左逆:

import numpy as np
import numpy.linalg as lin
B = np.array([[2],[4]])
b = np.array([[4],[4]])

B_linv = lin.solve(B.T.dot(B), B.T)
c = B_linv.dot(b)
print('c\n', c)

结果:

c
 [[ 1.2]]

其实,我们可以简单地运行一次求解器,而不需要形成逆,像这样:

c = lin.solve(B.T.dot(B), B.T.dot(b))
print('c\n', c)

结果:

c
 [[ 1.2]]

.... 和之前一样

为什么呢?因为:

我们有:

这里输入图片描述

乘以 B.T,我们得到:

这里输入图片描述

现在,B.T.dot(B) 是方阵,且满秩,确实有逆。因此我们可以乘以 B.T.dot(B) 的逆,或者像上面那样使用求解器来得到 c

14

在使用\这个符号时,Matlab会根据参与运算的矩阵形状进行不同的操作(想了解更多可以查看这里)。在你的例子中,Matlab返回的是一个最小二乘解,而不是像处理方阵那样直接解线性方程。要在numpy中实现相同的效果,可以这样做:

import numpy as np
import numpy.linalg as lin
B = np.array([[2],[4]])
b = np.array([[4],[4]])
print np.linalg.lstsq(B,b)[0]

这样做应该能给你和Matlab一样的结果。

20

来自MathWorks文档关于左矩阵除法的内容:

如果A是一个m行n列的矩阵,并且m不等于n,而B是一个有m个元素的列向量,或者是一个有多个这样的列的矩阵,那么X = A\B就是AX = B这个方程组的最小二乘解。换句话说,X的目的是让A*X - B这个结果的长度最小。

在numpy中,类似的功能可以用np.linalg.lstsq来实现:

In [15]: B = np.array([[2],[4]])

In [16]: b = np.array([[4],[4]])

In [18]: x,resid,rank,s = np.linalg.lstsq(B,b)

In [19]: x
Out[19]: array([[ 1.2]])

撰写回答