2015-11-06 2 views
4

A/B в matlab дает специальное решение, а 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 A \ B в MATLAB дает специальное решение?
  2. Является ли это решение полезным для достижения вычислительной точности?
  3. Почему это решение особенный и как реализовать его в Numpy
+1

Что вы подразумеваете под "специальным решением"? Решение из python ('[0.918 3.541 1.279]') также является правильным решением. У вас есть 2 уравнения в 3 unkowns, поэтому нет единственного решения. Решениями являются '[-1 9/2 0] + s * [3/2 -3/4 1]' для любого действительного числа 's'. Задайте 's = 2/3' для решения Matlab и' s = 1.27868852' для решения Python. – David

+0

Это не просто предоставление правильного решения. mldivide всегда дает вектор решения n ненулевых элементов, где n - ранг матрицы, где numpy не делает этого. Я ищу, чтобы получить то же самое решение в numpy, как и mldivide. – Schrodinger

+1

Решение Octave 'A \ b' такое же, как и« numpy ». Документ MATLAB предлагает «pinv (A) * B' как более дорогостоящий метод. В Октаве получается то же самое. 'numpy' также имеет' pinv', с тем же результатом. – hpaulj

ответ

5

Для недоопределенной системы, такие, как ваши (ранг меньше числа переменных), mldivide возвращает решение с так многими нулями насколько это возможно. Какая из переменных будет равна нулю, зависит от ее произвольного выбора.

В отличие от этого, метод возвращает lstsqрешение минимальной нормы в таких случаях: то есть, среди бесконечного семейства точных решений будет выбрать тот, который имеет наименьшую сумму квадратов переменных.

Итак, «специальное» решение Matlab несколько произвольно: в этой задаче можно установить любую из трех переменных в нуль. Решение, данное NumPy, на самом деле является более особенным: существует уникальное решение минимальной нормы.

Какое решение лучше для вашей цели, зависит от вашей цели. Неединственность решения обычно является поводом для пересмотра вашего подхода к уравнениям. Но так как вы спросили, вот код NumPy, который создает решения типа Matlab.

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]]