MATLAB中的mrdivide函数:它是做什么的,我该如何在Python中实现?

13

我有这一行MATLAB代码:

a/b

我正在使用这些输入:

a = [1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9]   
b = ones(25, 18)

这是结果(一个1x25的矩阵):

[5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]

MATLAB在做什么? 我正在尝试在Python中复制此行为,但MATLAB中的mrdivide文档没有帮助。5从哪里来的?其余的值为什么都是0?
我已经尝试了其他输入,结果类似,通常只有不同的第一个元素和填充矩阵剩余部分的零。在Python中,当我使用linalg.lstsq(b.T,a.T)时,返回的第一个矩阵中的所有值(即不是奇异值)都是0.2。我已经尝试在Python中进行右除运算,但它给出了完全错误且维度不对的答案。
我理解最小二乘逼近的含义,我只需要知道mrdivide在做什么。
相关链接:
4个回答

13

MRDIVIDE或者操作符/实际上解决的是线性方程组xb = a,而不是MLDIVIDE或者操作符\所解决的方程组bx = a

要解决一个非对称、非可逆矩阵b的方程组xb = a,你可以使用mridivide()通过高斯消元分解 b 来完成,或者使用pinv()通过奇异值分解并将奇异值下降到(默认)容差水平以下来完成。

这里是它们之间的区别(对于mldivide的情况):求解A*x=b时,PINV和MLDIVIDE有什么区别?

当系统是超定的时候,两种算法提供相同的答案。当系统是欠定的时候,PINV将返回具有最小范数(min NORM(x))的解x。而MLDIVIDE将选择具有最少非零元素的解。

在你的例子中:

% solve xb = a
a = [1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9];
b = ones(25, 18);

该系统是欠定的,因此存在两个不同的解决方案:

x1 = a/b; % MRDIVIDE: sparsest solution (min L0 norm) 
x2 = a*pinv(b); % PINV: minimum norm solution (min L2)

>> x1 = a/b
Warning: Rank deficient, rank = 1,  tol = 2.3551e-014.
ans =

    5.0000 0 0 ... 0 

>> x2 = a*pinv(b)
ans =

    0.2 0.2 0.2 ... 0.2 

在两种情况下,xb-a的近似误差是非常重要的(非精确解),且相同,即norm(x1*b-a)norm(x2*b-a)将返回相同的结果。

MATLAB正在做什么?

这篇帖子在scicomp.stackexchange.com中提供了关于“\”操作符所涉及到的算法(以及属性检查)的详细分解,具体取决于矩阵b的结构。我假设类似的选项适用于“/”操作符。

对于你的例子,MATLAB很可能执行高斯消元,在无穷多个最稀疏的解中给出最稀疏的解(这就是5的来源)。

Python正在做什么?

Python的linalg.lstsq使用伪逆/SVD,如上所示(这就是为什么您会得到一组0.2的向量)。实际上,以下两种方法都会给出与MATLAB的pinv()相同的结果:

from numpy import *

a = array([1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9])
b = ones((25, 18))

# xb = a: solve b.T x.T = a.T instead 
x2 = linalg.lstsq(b.T, a.T)[0]
x2 = dot(a, linalg.pinv(b)) 

7
TL;DR: A/B = np.linalg.solve(B.conj().T, A.conj().T).conj().T 我研究了Matlab的参考文档并找到了解决方法,以创建一个令人满意的替代方案。我无法在此解释实际的数学知识或者得分,我只是遵循Matlab的解释。此外,我想发布来自Matlab的详细信息来给予认可。如果这违反版权问题,请让我知道,我将删除实际的文字。
%/   Slash or right matrix divide.
%   A/B is the matrix division of B into A, which is roughly the
%   same as A*INV(B) , except it is computed in a different way.
%   More precisely, A/B = (B'\A')'. See MLDIVIDE for details.
%
%   C = MRDIVIDE(A,B) is called for the syntax 'A / B' when A or B is an
%   object.
%
%   See also MLDIVIDE, RDIVIDE, LDIVIDE.

%   Copyright 1984-2005 The MathWorks, Inc.


注意,' 符号表示复共轭转置。在使用numpy的Python中,需要将 .conj().T 链接在一起。

作为解释,我们正在尝试解决 XA = BX。对两边进行转置计算得到 A'X' = B'。由于 np.linalg.solve 解决了 CY = DY,那么我们可以让 C = A'D = B' 得到 Y = X'。最后,通过对 Y 进行转置,我们得到了 X - mhdadk

1

a/b 可以找到线性方程组 bx = a 的最小二乘解

如果 b 是可逆的,那么最小二乘解是 a*inv(b),但如果不可逆,则是使得 norm(bx-a) 最小的 x

您可以在 wikipedia 上了解更多关于最小二乘的知识。

根据 matlab documentation,mrdivide 返回的非零值最多为 k,其中 k 是 b 的计算秩。我猜测在您的情况下,matlab 通过将 b 替换为 b(:1)(具有相同秩)来解决最小二乘问题。在这种情况下,Moore-Penrose 伪逆 b2 = b(1,:); inv(b2*b2')*b2*a' 被定义并且给出相同的答案。


1
我明白了。你有这个问题的答案吗? - EmilyS
请注意,矩阵b的秩不足(秩为1),Matlab已经做出了相应的提示。 - second
1
好的,你知道在Python中有没有办法做到这一点吗?你是否使用实际代码测试过你的想法? - EmilyS
numpy.linalg.pinv() 计算矩阵的Moore-Penrose伪逆。 - jfs
1
这是错误的。在MATLAB中,bx = a 的解法是 x = b\a,而不是 x = a/ba/b 所做的是解线性方程组 xb = a - Cris Luengo

1

1
我无法让linag.lstsq给出与matlab lstsq算法相同的答案。也许它们的工作方式不同。 - Dan Lorenc

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