数组划分 - 从MATLAB转换为Python

时间:2009-06-16 13:54:14

标签: python matlab numpy linear-algebra

我在MATLAB中有这行代码,由其他人编写:

c=a.'/b

我需要将其翻译成Python。 a,b和c都是数组。我目前用于测试代码的维度是:

a:18x1,
b:25x18,

给我c尺寸为1x25。

数组不是正方形,但我不希望代码失败。有人可以解释这条线正在做什么(数学上),以及如何在Python中做到这一点? (如果它存在于Python中,那么MATLAB中内置的mrdivide函数的等价物?)

5 个答案:

答案 0 :(得分:7)

符号/是MATLAB中的矩阵右除法运算符,它调用mrdivide函数。从文档中,矩阵右分割以下列方式与matrix left division相关:

B/A = (A'\B')'

如果A是方阵,B/A大致等于B*inv(A)(尽管它以不同的,更健壮的方式计算)。否则,x = B/A是最小二乘意义上的方程式x*A = B的方程式不足或过度确定的解。关于用于求解方程组的算法的更多细节被给出here。通常情况下会使用LAPACKBLAS等软件包。

Python的NumPy package包含一个例程lstsq,用于计算方程组的最小二乘解。这个例程可能会给你在MATLAB中使用mrdivide函数的可比结果,但它不可能是 exact 。每个函数使用的基础算法的任何差异都可能导致答案彼此略有不同(即,一个可以返回值1.0,而另一个可以返回0.999的值)。此错误的相对大小最终会变大,这在很大程度上取决于您要解决的特定方程组。

要使用lstsq,您可能需要稍微调整一下您的问题。您似乎想要解决 cB = a 形式的等式,其中 B 为25 x 18, a 为1- by-18, c 是1乘25。在两侧都应用transpose可以得到方程 B T c T = a T ,这是一种更标准的形式(即 Ax = b )。 lstsq的参数应该是(按此顺序) B T (18乘25的数组)和 a T < / sup> (一个18元素的数组)。 lstsq应返回25个元素的数组( c T )。

注意:虽然NumPy没有对1-by-N或N-by-1数组进行任何区分,但MATLAB当然会这样做,如果你没有使用正确的数组,它会对你大喊大叫。

答案 1 :(得分:7)

该行

c = a.' / b

计算 c 的等式 c b = a T 的解。 Numpy没有直接执行此操作的运算符。相反,你应该解决 b T c T = a c T 并转置结果:

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

答案 2 :(得分:5)

在Matlab中,A.'表示转置​​A矩阵。所以在数学上,代码中实现的是A T / B.


如何在Python(或任何语言)中实现矩阵划分 (注意:让我们来看一下A/B形式的简单划分;对于你的例子,你会需要首先进行A T 然后进行A T / B,并且在Python中进行转置操作非常容易| left-as-an-exercise:)| )

你有一个矩阵方程 C * B = A(你想找到C作为A / B)

RIGHT DIVISION(/)如下:

13 C *(B *Ť)= A *Ť

然后通过反转来隔离C(B * B T

即,

C = A * B T *(B * B T )'----- [1 ]

因此,要在Python(或任何语言)中实现矩阵划分,请获取以下三种方法。

  • 矩阵乘法
  • Matrix transpose
  • Matrix inverse

然后迭代地应用它们以实现[1]中的除法。

只有,你需要做一个 T / B,因此在实施三种基本方法后你的最终操作应该是:

A Ť *Ť *(B *Ť)'< / p>

注意:不要忘记运算符优先级的基本规则:)

答案 3 :(得分: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

答案 4 :(得分:1)

您也可以使用B的伪逆来对此进行处理,然后将该结果与A相乘。尝试使用numpy.linalg.pinv,然后通过numpy.dot

将其与矩阵乘法相结合
c = numpy.dot(a, numpy.linalg.pinv(b))