数组分割 - 从MATLAB翻译到Python

8

我在 MATLAB 中看到了这行代码,是别人写的:

c=a.'/b

我需要将其翻译为Python。a、b和c都是数组。我目前用来测试代码的维度是:
a: 18x1, b: 25x18,
这给了我一个维度为1x25的c。
这些数组不是方阵,但如果它们是方阵,我也不希望代码失败。有人能解释一下这行代码(数学上)到底在做什么,以及如何在Python中实现它吗?(即,如果在Python中存在内置的mrdivide函数,则等效于MATLAB中的该函数?)

我认为你打错了字。如果“a”是1x18,你就不需要转置。 - gnovice
这不是打字错误,Matlab 代码完美运行。 - EmilyS
1
@Emily:那么“a”在转置之前必须是18行1列,而不是1行18列。否则MATLAB会报错。 - gnovice
是的,为了正确地进行A转置/B运算,A和B应该具有相同的列数。因此,A的大小应该是18x1,正如gnovice所指出的那样。 - SuPra
好的,对不起,一开始是18x1。 - EmilyS
5个回答

11

这条线

c = a.' / b

计算方程 c b = aT 的解,以求得 c。Numpy 没有直接执行此操作的运算符。相反,您应该解决 bT cT = a,以求得 cT 并转置结果:

c = numpy.linalg.lstsq(b.T, a.T)[0].T

你的方程中的"a"和"b"可能与OPs的"a"和"b"相对调换了。行"c = a.'/b"解决的是一个形如"xb = a.'"的方程,它变成了"(b.')(x.')=a"。OPs的"b"(即方程系数矩阵)应该是lstsq的第一个输入,当然要转置。 - gnovice

9
符号/是MATLAB中的矩阵右除运算符,它调用mrdivide函数。根据文档,矩阵右除与矩阵左除有以下关系:
B/A = (A'\B')'

如果A是一个方阵,那么B/A大致等于B*inv(A)(尽管它是以一种不同、更健壮的方式计算的)。否则,x = B/A是在最小二乘意义下解决欠定或超定方程组x*A = B的解。有关用于解决方程组的算法的更多详细信息,请参见此处。通常在底层使用类似于LAPACKBLAS的软件包。
Python的NumPy包中包含了一个名为lstsq的例程,用于计算方程组的最小二乘解。使用这个例程很可能会得到与在MATLAB中使用mrdivide函数相当的结果,但不太可能是完全相同的。由于每个函数使用的底层算法的差异,它们返回的答案可能略有不同(即一个可能返回值为1.0,而另一个可能返回值为0.999)。这种误差的相对大小可能会更大,具体取决于您要解决的特定方程组。
为了使用lstsq,您可能需要稍微调整一下问题。看起来您想要解决一个形式为cB = a的方程,其中B是25×18,a是1×18,c是1×25。对两边应用转置,得到等式BTcT = aT,这是一种更标准的形式(即Ax = b)。lstsq的参数应该是(按此顺序)BT(一个18×25的数组)和aT(一个18元素的数组)。lstsq应该返回一个25元素的数组(cT)。
注意:虽然NumPy不会在1×N或N×1数组之间做任何区分,但MATLAB肯定会区分,并且如果您没有使用正确的数组类型,它会向您发出警告。

1
Numpy在1xN或Nx1数组之间没有任何区别。 1D数组就是1D数组。 如果您使用一个长度为1的维度创建2D数组,则可以区分,但通常没有理由这样做。 - endolith

5
在Matlab中,A.'表示对A矩阵进行转置。因此,在代码中实现的数学操作是AT/B。
如何在Python(或任何语言)中实现矩阵除法(注意:让我们先讨论形式为A/B的简单除法;对于您的示例,您需要先执行AT,然后执行AT/B,而在Python中执行转置操作非常容易 |作为练习留给读者 :)|) 您有一个矩阵方程C*B=A(您想要将C表示为A/B)
右除(/)如下:
C*(B*BT)=A*BT 然后通过反转(B*BT)来隔离C
即,
C = A*BT*(B*BT)' ----- [1]
因此,要在Python(或任何语言)中实现矩阵除法,请获取以下三种方法。
- 矩阵乘法 - 矩阵转置 - 矩阵逆
然后迭代地应用它们以实现[1]中的除法。
只需执行AT/B,因此在实现三种基本方法后,您的最终操作应为:
AT*BT*(B*BT)'
注:不要忘记运算符优先级的基本规则 :)

2
你还可以使用伪逆矩阵B,然后将其与A进行矩阵乘法。可以尝试使用numpy.linalg.pinv并结合矩阵乘法numpy.dot来实现:
c = numpy.dot(a, numpy.linalg.pinv(b))

1

[编辑] 正如Suvesh所指出的那样,我之前完全错了。然而,numpy仍然可以轻松地执行他在帖子中提供的过程:

A = numpy.matrix(numpy.random.random((18, 1))) # as noted by others, your dimensions are off
B = numpy.matrix(numpy.random.random((25, 18)))
C = A.T * B.T * (B * B.T).I

在Python中,/运算符被定义为正方形矩阵的标准矩阵除法,即A*inv(B)。在她的例子中,她试图实现任意大小矩阵的右除法。因此,你的代码将无法工作。 - SuPra
我不知道 Python,但无论如何,我希望她能解决这个问题,所以我没有费心随着我的数学公式发布代码。在 Python 中将我的数学转换为代码 +1。 - SuPra
这至少能让我得到一个维度正确的结果矩阵c,但该矩阵中的值与Matlab中的值不匹配-有什么想法吗? - EmilyS
4
不应该直接实现所谓的正规方程,而应该使用最小二乘逼近,即numpy.linalg中的lstsq函数。 - David Cournapeau
@Autoplectic:是的。 @David:你能否解释一下如何在Python中使用这个函数来替换这行代码?我在阅读了lstsq的帮助文档后尝试使用它,但是我得到的矩阵值与Matlab中的不同,尽管它们具有相同的维度。 - EmilyS
显示剩余3条评论

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