2015-11-06 133 views
4

matlab中的A/B提供了一个特殊的解决方案,而numpy.linalg.lstsq则不提供。Numpy vs mldivide,“”matlab运算符

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. 如何mldivide在MATLAB A \ B给出了特殊的解决方案?
  2. 此解决方案是否有用于实现计算精度?
  3. 为什么是这个解决方案的特殊以及如何实现它在numpy的
+1

你是什么意思的“特殊解决方案”? 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。 – David

+0

它不只是提供任何正确的解决方案。 mldivide总是给出一个包含n个非零元素的解向量,其中n是矩阵的秩,而numpy不会这样做。我正在寻找像mldivide一样的numpy完全相同的解决方案。 – Schrodinger

+1

Octave'A \ b'解决方案与'numpy'相同。 MATLAB doc建议'pinv(A)* B'作为一种计算上更昂贵的方法。在八度产生同样的事情。 'numpy'也有'pinv',结果相同。 – hpaulj

回答

5

对于下确定的系统如你(秩小于变量的数量),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]]