Подтвердить что ты не робот

Эффективная и pythonic проверка для сингулярной матрицы

Работа над некоторой матричной алгеброй здесь. Иногда мне нужно инвертировать матрицу, которая может быть сингулярной или плохо обусловленной. Я понимаю, что это просто pythonic:

try:
    i = linalg.inv(x)
except LinAlgErr as err:
    #handle it

но я не уверен, насколько это эффективно. Разве это не лучше?

if linalg.cond(x) < 1/sys.float_info.epsilon:
    i = linalg.inv(x)
else:
    #handle it

Выполняет ли numpy.linalg перед началом теста, который я запретил?

4b9b3361

Ответ 1

Итак, основываясь на входах здесь, я отмечаю свой исходный код с явным тестом в качестве решения:

if linalg.cond(x) < 1/sys.float_info.epsilon:
    i = linalg.inv(x)
else:
    #handle it

Удивительно, что функция numpy.linalg.inv не выполняет этот тест. Я проверил код и обнаружил, что он проходит через все его махинации, а затем просто вызывает рутинную процедуру - кажется довольно неэффективным. Кроме того, я бы сделал 2-ой пункт, сделанный DaveP: что обратная матрица не должна вычисляться, если она явно не нужна.

Ответ 2

Ваше первое решение ловит случай, когда ваша матрица настолько необычна, что numpy не справляется вообще - потенциально весьма экстремальный случай. Второе решение лучше, потому что оно улавливает случай, когда numpy дает ответ, но этот ответ потенциально поврежден ошибкой округления - это кажется гораздо более разумным.

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

Если вы не хотите SVD, см. также мой комментарий об использовании lu_factor вместо inv.

Ответ 3

Вы должны вычислить номер условия матрицы, чтобы убедиться, что она обратима.

import numpy.linalg

if numpy.isfinite(numpy.linalg.cond(A)):
    B = numpy.linalg.inv(A)
else:
    # handle it

Ответ 4

Почему бы просто не проверить, отличен ли определитель?

det = numpy.linalg.det(A)
if det != 0:
   #proceed