2017-02-06 2 views
3

Скажем, я определяю большую квадратичную матрицу (например, 150x150). Один раз это массив с множеством (матрица A), один раз это scipy разреженный массив (матрица B).Почему функция инверсии матрицы в numpy и scipy возвращает разные результаты с большими квадратичными матрицами?

import numpy as np 
import scipy as sp 

from scipy.sparse.linalg import spsolve 

size = 150 
A = np.zeros((size, size)) 
length = 1000 
# Set some random numbers at random places 
A[np.random.randint(0, size, (2, length)).tolist()] = \ 
    np.random.randint(0, size, (length,)) 
B = sp.sparse.csc_matrix(A) 

Теперь я вычисляю инверсию обеих матриц. Для матрицы B Я использую оба метода для расчета обратного (sp.sparse.linalg.inv и spsolve).

epsilon = 10.**-8 # Is needed to prevent singularity of each matrix 

inv_A = np.linalg.pinv(A+np.eye(size)*epsilon) 
inv_B = sp.sparse.linalg.inv(B+sp.sparse.identity(size)*epsilon) 
inv_B2 = spsolve(B+sp.sparse.identity(size)*epsilon, sp.sparse.identity(size)) 

Чтобы проверить, если оба обратные и B равны, я подведу различие в квадрате.

# Is not equal zero, question: Why? 
# Sometimes very small (~+-10**-27), sometimes very big (~+-10**5) 
print("np.sum((inv_A - inv_B)**2): {}".format(np.sum((inv_A - inv_B)**2))) 
# Should be zero 
print("np.sum((inv_B - inv_B2)**2): {}".format(np.sum((inv_B - inv_B2)**2))) 

Проблема заключается в следующем: если я использую малые матрицы, например. 10x10, ошибка между numpy как scipy обратными функциями очень мала (приблизительно ~ + -10 ** - 32). Но мне нужна разреженная версия для больших матриц (например, 500x500).

Я делаю здесь что-то не так, или есть возможность исправить правильный , обратный к разреженной матрице в python?

+1

Насколько велика относительная ошибка? –

+0

Вы имеете в виду возможную относительную ошибку для моей проблемы или относительную ошибку между двумя матрицами? – PiMathCLanguage

+0

Я имею в виду вычисленную ошибку, деленную на квадрат эвклидовой длины одного из двух инверсий, которые вы сравниваете. –

ответ

2

Ответ на ваш основной вопрос: из-за вашего неудачного выбора примеров матриц. Позвольте мне уточнить.

Точность машины ограничена, поэтому арифметика с плавающей запятой редко будет на 100% точнее. Просто попробуйте

>>> np.linspace(0, 0.9, 10)[1:] == np.linspace(0.1, 1, 10)[:-1] 
array([ True, True, True, True, True, False, True, True, True], dtype=bool) 

Как правило, это не проблема, потому что ошибки слишком малы, чтобы их заметить.

Однако для многих вычислений есть некоторые входы, которые трудно обрабатывать и могут перенапрягать численный алгоритм. Это, безусловно, относится к инверсии матрицы, и вам не повезло, чтобы выбрать такие сложные входы.

Фактически вы можете проверить, может ли матрица быть «плохо обусловлена», глядя на ее особые значения, например, here. Вот число обусловленности матрицы для нескольких матриц, порожденных со сценарием (size=200; благонравная матрица имеет значение гораздо ближе к 1)

971899214237.0 
5.0134186641e+12 
36848.0807109 
958492416768.0 
1.66615247737e+16 
1.42435766189e+12 
1954.62614384 
2.35259324603e+12 
5.58292606978e+12 

Переключения хорошо воспитанных матрицам вашим результаты должны существенно улучшиться.

Смежные вопросы