【问题标题】:Numpy vs mldivide,"\" matlab operatorNumpy vs mldivide,"\" matlab 运算符
【发布时间】:2016-02-07 04:42:12
【问题描述】:

matlab 中的A \ B 给出了一个特殊的解决方案,而 numpy.linalg.lstsq 没有。

A = [1 2 0; 0 4 3];
b = [8; 18];
c_mldivide = A \ b
c_mldivide =

                 0
                 4
  0.66666666666667
 c_lstsq = np.linalg.lstsq([[1 ,2, 0],[0, 4, 3]],[[8],[18]])
 print c_lstsq
 c_lstsq = (array([[ 0.91803279],
                   [ 3.54098361],
                   [ 1.27868852]]), array([], dtype=float64), 2, array([ 5.27316304,1.48113184]))
  1. matlab中mldivideA \ B如何给出特殊解?
  2. 此解决方案是否有助于实现计算精度?
  3. 为什么这个解决方案特别,你如何在 numpy 中实现它?

【问题讨论】:

  • “特殊解决方案”是什么意思? python ([0.918 3.541 1.279]) 的解决方案也是一个正确的解决方案。您有 3 个未知数中的 2 个方程,因此没有唯一解。对于任何实数s,解决方案是[-1 9/2 0]+s*[3/2 -3/4 1]。为 Matlab 解决方案设置 s=2/3,为 Python 解决方案设置s=1.27868852
  • Octave A\b 解决方案与numpy 解决方案相同。 MATLAB 文档建议将pinv(A)*B 作为一种计算成本更高的方法。在 Octave 中产生同样的东西。 numpy 也有 pinv,结果相同。
  • 对此没有最小二乘解——有无数个精确解。如果您的代码中的其他内容取决于获得“正确”的解决方案,那么您要么需要指定另一个条件,要么您的算法存在问题。
  • @David 当存在无限个精确解时,lstsq 返回最小范数的解;即,变量平方和最小的变量。这可能被描述为“最小二乘”,尽管“最小范数”是避免混淆的一个更可取的术语。
  • @Bookend 我不认为我完全同意。最小二乘解意味着近似解中的残差(误差)在最小二乘意义上被最小化,即从真实解到近似解的距离被最小化。选择具有最小范数的解决方案是一种确定选择哪个解决方案的方法,就像 Matlab 试图使向量的尽可能多的元素为零一样。因此,我认为您的方法提供了最小二乘解决方案,但使用了不同的方式来选择要返回的解决方案。

标签: python matlab numpy


【解决方案1】:

对于像您这样的欠定系统(等级小于变量的数量),mldivide 返回一个具有尽可能多的零值的解决方案。哪个变量将被设置为零取决于它的任意选择。

相比之下,lstsq 方法在这种情况下返回最小范数的解:也就是说,在无限的精确解族中,它会选择平方和最小的那个的变量。

因此,Matlab 的“特殊”解决方案有些随意:在这个问题中,可以将三个变量中的任何一个设置为零。 NumPy 给出的解其实更特殊:有一个唯一的最小范数解

哪种解决方案更适合您的目的取决于您的目的。解的非唯一性通常是重新考虑方程方法的原因。但既然你问了,这里是生成 Matlab 类型解决方案的 NumPy 代码。

import numpy as np
from itertools import combinations
A = np.matrix([[1 ,2, 0],[0, 4, 3]])
b = np.matrix([[8],[18]])

num_vars = A.shape[1]
rank = np.linalg.matrix_rank(A)
if rank == num_vars:              
    sol = np.linalg.lstsq(A, b)[0]    # not under-determined
else:
    for nz in combinations(range(num_vars), rank):    # the variables not set to zero
        try: 
            sol = np.zeros((num_vars, 1))  
            sol[nz, :] = np.asarray(np.linalg.solve(A[:, nz], b))
            print(sol)
        except np.linalg.LinAlgError:     
            pass                    # picked bad variables, can't solve

对于您的示例,它输出三个“特殊”解决方案,最后一个是 Matlab 选择的解决方案。

[[-1. ]
 [ 4.5]
 [ 0. ]]

[[ 8.]
 [ 0.]
 [ 6.]]

[[ 0.        ]
 [ 4.        ]
 [ 0.66666667]] 

【讨论】:

  • 似乎np.linalg.solve(mA, vB) 仅适用于平方矩阵。是否有任何大小的矩阵的求解器(当然,它的行数与vB 相同)?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-16
  • 2012-02-15
  • 1970-01-01
  • 1970-01-01
  • 2013-03-07
  • 1970-01-01
相关资源
最近更新 更多