【问题标题】:mrdivide function in MATLAB: what is it doing, and how can I do it in Python?MATLAB 中的 mrdivide 函数:它在做什么,我如何在 Python 中做到这一点?
【发布时间】:2010-11-03 16:39:22
【问题描述】:

我有这行 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 在做什么。

相关:

【问题讨论】:

    标签: python matlab numpy linear-algebra


    【解决方案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' 并给出了相同的答案

    【讨论】:

    • 我意识到这一点。你有这个问题的答案吗?
    • 请注意 b 等级不足(等级 1)和 matlab 对此的评论。
    • 好的,你知道在 python 中这样做的方法吗?您是否使用实际代码测试了您的想法?
    • numpy.linalg.pinv() 计算矩阵的 Moore-Penrose 伪逆
    • 这是错误的。 bx = a 在 MATLAB 中用x = b\a 求解,与x = a/b 不同。 a/b 所做的是求解线性系统 xb = a
    【解决方案2】:

    对于 matlab 用户来说,对于 numpy 的 this handy "cheat sheet"linalg.lstsq(b,a) -- linalgnumpy.linalg.linalg,是完整 scipy.linalg 的轻量级版本。

    【讨论】:

    • 我无法让 linag.lstsq 给出与 matlab lstsq 算法相同的答案。也许它们的工作方式不同。
    【解决方案3】:

    MRDIVIDE/ 运算符实际上解决了 xb = a 线性系统,而不是 MLDIVIDE\ 运算符将解决系统 bx = a

    要求解具有非对称、不可逆矩阵b 的系统xb = a,您可以依赖mridivide(),这是通过使用高斯消元法对b 进行因式分解完成的,或者pinv() ,这是通过奇异值分解和低于(默认)容差水平的奇异值归零完成的。

    这里是区别(mldivide 的情况):What is the difference between PINV and MLDIVIDE when I solve A*x=b?

    当系统超定时,两种算法都提供 相同的答案。当系统不确定时,PINV 将返回 解 x,具有最小范数 (min NORM(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 在做什么?

    根据矩阵b 的结构,'\' 运算符调用的算法(和属性检查)的详细分解在scicomp.stackexchange.com 的这篇文章中给出。我假设类似的选项适用于 / 运算符。

    对于您的示例,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)) 
    

    【讨论】:

      【解决方案4】:

      TL;DR:A/B = np.linalg.solve(B.conj().T, A.conj().T).conj().T

      我没有找到较早的答案来创建令人满意的替代品,因此我进一步挖掘了 Matlab 的 mrdivide 参考文档并找到了解决方案。我无法在这里解释实际的数学,也无法将答案归功于自己。我只是按照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 链接在一起。

      【讨论】:

        猜你喜欢
        • 2019-07-25
        • 2013-04-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-12-05
        • 1970-01-01
        相关资源
        最近更新 更多