当前位置: 首页 > 面试题库 >

我如何才能获得与Matlab的A \ b(mldivide)运算符使用numpy / scipy返回的欠定线性系统相同的“特殊”解决方案?

轩辕经赋
2023-03-14
问题内容

我找到了一个链接,并在其中举例说明了当线性方程组具有无限多个解时,Matlabmldivide运算符(\)提供“特殊”解。

例如:

A = [1 2 0; 0 4 3];
b = [8; 18];
c_mldivide = A \ b
c_pinv = pinv(A) * b

给出输出:

c_mldivide =
                 0
                 4
  0.66666666666667


c_pinv =

  0.918032786885245
  3.54098360655738
  1.27868852459016

在解决方案中非零项的数量c_mldivide等于rank(A)(在这种情况下为2)的意义上,解决方案是“特殊”的。我在numpy中使用尝试了相同的操作numpy.linalg.lstsq,它给带来了相同的结果c_pinv

有没有c_mldivide办法用Python实现解决方案?

还有一个非常类似的问题在这里,但我想这个词“特殊”的解释是不够清晰。
另一个问题询问了mldivide操作员的内部工作原理,但被接受的答案似乎并未解决此问题。

编辑1:numpy代码

In [149]: test_A = np.array([[1,2,0],[0,4,3]])
          test_b = np.array([[8],[18]])
          np.linalg.lstsq(test_A,test_b)

Out[149]:
(array([[ 0.918 ],
    [ 3.541 ],
    [ 1.2787]]), array([], dtype=float64), 2, array([ 5.2732,  1.4811]))

编辑2:使用 scipy.optimize.nnls

In[189]:
from scipy.optimize import nnls
nnls(test_A,test_b)
Out[190]:
    ValueError                                Traceback (most recent call last)
<ipython-input-165-19ed603bd86c> in <module>()
      1 from scipy.optimize import nnls
      2 
----> 3 nnls(test_A,test_b)

C:\Users\abhishek\Anaconda\lib\site-packages\scipy\optimize\nnls.py in nnls(A, b)
     43         raise ValueError("expected matrix")
     44     if len(b.shape) != 1:
---> 45         raise ValueError("expected vector")
     46 
     47     m, n = A.shape

    ValueError: expected vector

问题答案:

非负最小二乘(scipy.optimize.nnls
不是 此问题的一般解决方案。如果所有可能的解决方案都包含负系数,则失败的简单情况是:

import numpy as np
from scipy.optimize import nnls

A = np.array([[1, 2, 0],
              [0, 4, 3]])
b = np.array([-1, -2])

print(nnls(A, b))
# (array([ 0.,  0.,  0.]), 2.23606797749979)

A·x = b 的情况下,

x1, res, rnk, s = np.linalg.lstsq(A, b)

将选择最小化 || 的解 x’* _ x_ || L2|| _ A·x_ - _ b_ || L2 = _ 0_ 。碰巧这并不是我们要寻找的特定解决方案,但是我们可以对其进行线性转换以得到我们想要的。为了做到这一点,我们首先计算正确的零空间的
一个 ,表征所有可能的解决方案的空间 A·X = b
。我们可以通过显示排名的QR分解获得此信息: _
_ _
_
* __
__*
*

from scipy.linalg import qr

def qr_null(A, tol=None):
    Q, R, P = qr(A.T, mode='full', pivoting=True)
    tol = np.finfo(R.dtype).eps if tol is None else tol
    rnk = min(A.shape) - np.abs(np.diag(R))[::-1].searchsorted(tol)
    return Q[:, rnk:].conj()

Z = qr_null(A)

Z 是一个向量(或者,在 n-rnk( A )> 1的情况下,是跨越 A 的子空间的一组基本向量),使得
A·Z
= 0

print(A.dot(Z))
# [[  0.00000000e+00]
#  [  8.88178420e-16]]

换句话说, Z 的列是与 A中的 所有行正交的向量。这意味着,对于 x A·x = b的
任何解,则 x’ = x + Z ·c也必须是任意缩放因子 c的解 。这意味着通过选择适当的 c
值,我们可以将解中系数的任何 _n-rnk( A )_设置为零。

例如,假设我们要将最后一个系数的值设置为零:

c = -x1[-1] / Z[-1, 0]
x2 = x1 + Z * c
print(x2)
# [ -8.32667268e-17  -5.00000000e-01   0.00000000e+00]
print(A.dot(x2))
# [-1. -2.]

_n-rnk( A )≤1_的更一般情况稍微复杂一些:

A = np.array([[1, 4, 9, 6, 9, 2, 7],
              [6, 3, 8, 5, 2, 7, 6],
              [7, 4, 5, 7, 6, 3, 2],
              [5, 2, 7, 4, 7, 5, 4],
              [9, 3, 8, 6, 7, 3, 1]])
x_exact = np.array([ 1,  2, -1, -2,  5,  0,  0])
b = A.dot(x_exact)
print(b)
# [33,  4, 26, 29, 30]

我们像以前一样得到 x’ Z

x1, res, rnk, s = np.linalg.lstsq(A, b)
Z = qr_null(A)

现在,为了最大限度地解向量零值系数的数目,我们希望找到一个矢量 c ^ 这样

X ‘ = X + Ž·C = [X’ 0,x ‘ 1,…,X’ RNK(A)-1,0,…,0] Ť

如果 x’ 中最后的 _n-rnk( A )个_系数为零,则这意味着 __

Z {rnk(A),…,n} ·C = -x {rnk(A),…,n}

因此,我们可以求解 C (确切地,因为我们知道那Z[rnk:]必须是全秩):

C = np.linalg.solve(Z[rnk:], -x1[rnk:])

并计算 x’

x2 = x1 + Z.dot(C)
print(x2)
# [  1.00000000e+00   2.00000000e+00  -1.00000000e+00  -2.00000000e+00
#    5.00000000e+00   5.55111512e-17   0.00000000e+00]
print(A.dot(x2))
# [ 33.   4.  26.  29.  30.]

要将它们放到一个函数中:

import numpy as np
from scipy.linalg import qr

def solve_minnonzero(A, b):
    x1, res, rnk, s = np.linalg.lstsq(A, b)
    if rnk == A.shape[1]:
        return x1   # nothing more to do if A is full-rank
    Q, R, P = qr(A.T, mode='full', pivoting=True)
    Z = Q[:, rnk:].conj()
    C = np.linalg.solve(Z[rnk:], -x1[rnk:])
    return x1 + Z.dot(C)


 类似资料:
  • 我正在用Eigen 3将一个MATLAB代码移植到C,我决定构造我的线性解算器,而不是从矩阵对象调用它,这样我就可以重用它了。不幸的是,它没有产生预期的结果。经过几次测试后,我将问题追溯到了似乎是线性解算器对象的地方,如以下相关代码所示: 结果是: 该算法在MATLAB中的第一次迭代产生了一个近似单位矩阵,可以在C中通过反转矩阵并从矩阵对象调用解算器来观察该矩阵。 但使用解算器对象时,结果完全错误

  • 本文向大家介绍SQL中的特殊运算符,包括了SQL中的特殊运算符的使用技巧和注意事项,需要的朋友参考一下 SQL中不同的特殊运算符如下- 所有运算符 任何运算符 运算符之间 EXISTS运算符 IN运算符 LIKE运算符 现在让我们创建一个表来了解特殊运算符的示例- <员工> Emp_ID Emp_Name Emp_Salary Emp_DeptID Emp_DeptName 1 亚伦 10000

  • 这是可能的还是有其他简单的解决办法?

  • 问题内容: 在C程序中,如果要从终端提供一些输入,则可以通过以下方式提供: 同样,如果我们想获得函数的返回值,那么我们如何得到它呢? 在每一个中我们写或; 我怎么知道我在航站楼退回了什么? 编辑:1 我得到的是,我们可以得到的返回值,但是它仅允许我成功返回小于125的值(在Linux中)。so 无法成功接收到大于此值的返回值 为什么是返回类型?为什么不保留它? 编辑2 如果返回的值大于125 ,我

  • 我必须使用google places api实现餐厅定位服务,如下所示: https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=43.7666321,11.2546258 但结果与使用谷歌地图进行的近距离搜索大不相同: https://www.google.it/maps/search/Ristoranti/@4

  • 我在寻求帮助。我已经创建了一个应用程序,其中一个按钮是用来打开特定文件的。 我已将指定的.txt文档放入程序的文件夹中。它与“解决方案”文件处于同一级别。现在,如何编写打开这个特定的。txt文件的代码?