numpy: возможно ли инвертировать нулевую детерминантную матрицу?

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

Что потенциально может пойти не так? Должен ли я не доверять выходу определителя или не доверять обратной матрице ковариаций? Или оба?

Фрагмент моего кода:

cov_matrix = np.cov(data)
adjusted_cov = cov_matrix + weight*np.identity(cov_matrix.shape[0]) # add small weight to ensure cov_matrix is non-singular
inv_cov = np.linalg.inv(adjusted_cov) # runs with no error, outputs a matrix
det = np.linalg.det(adjusted_cov) # ends up being 0.0

person kk415kk    schedule 25.02.2015    source источник
comment
Не могли бы вы показать нам пример ввода и вывода? Ваш комментарий подразумевает, что вы пытаетесь сделать матрицу невырожденной, что означает, что матрица должна иметь действительную обратную.   -  person BobChao87    schedule 25.02.2015
comment
Хм, мой набор данных состоит из изображений 28x28, где я использую необработанные пиксели в качестве функций, поэтому я думаю, что входной вывод будет слишком большим для копирования (матрицы ковариации 784x487). Я считаю, что добавление веса приводит к правильному обратному результату, однако, почему тогда определитель равен нулю? Если я не добавлю вес, я получу сингулярную ошибку лин-алгебры. Будет ли ошибка округления применяться к определителю, где он округляется до 0,0?   -  person kk415kk    schedule 25.02.2015
comment
Когда вы пишете nv_cov = np.linalg(adjusted_cov), вы имеете в виду nv_cov = np.linalg.inv(adjusted_cov)? и действительно ли det = np.linalg(adjusted_cov) должно быть det = np.linalg.det(adjusted_cov) ?   -  person gboffi    schedule 25.02.2015
comment
@ kk415kk Поскольку числа ковариантной матрицы малы (согласно вашему комментарию), возможно, вы столкнулись с проблемой не округления, а скорее точности. Произведение 784 чисел со средним размером даже всего 0,3 слишком мало, чтобы его можно было поместить в число с плавающей запятой Python. Если у numpy есть метод вычисления обратной матрицы без вычисления определителя, то это может привести к описанному вами поведению.   -  person BobChao87    schedule 25.02.2015
comment
Ааа ладно. Контекст моей проблемы заключается в том, что я пытаюсь смоделировать эти изображения (отсортированные по классам) как многомерное распределение Гаусса, что требует от меня вычисления ковариационной матрицы и ее обратной. Есть ли лучший способ сделать это, если точность является проблемой?   -  person kk415kk    schedule 25.02.2015
comment
@ kk415kk Возможно, это исправление моделирует numpy. Это может быть только детерминант, который терпит неудачу. Чтобы проверить это, я рекомендую посмотреть, является ли произведение adjusted_cov и inv_cov (приблизительно) единичной матрицей. Если это так, то numpy, вероятно, не за горами, особенно если это происходит для нескольких тестовых случаев.   -  person BobChao87    schedule 25.02.2015
comment
Похоже, что матрица cov, умноженная на обратную, дает единичную матрицу. Есть ли способ более точно представить детерминант для моего сценария?   -  person kk415kk    schedule 25.02.2015
comment
Если вам требуется значение определителя по другим причинам, я бы посоветовал посмотреть, можете ли вы интегрировать numpy с классом decimal.Decimal, который поддерживает произвольную точность. Это добавит много накладных расходов к любым вычислениям, выполняемым с помощью этого метода, поэтому я бы рекомендовал использовать Decimal только в случае крайней необходимости.   -  person BobChao87    schedule 25.02.2015


Ответы (1)


численная инверсия матриц не требует вычисления определителя. (формула Крамера для обратной непрактична для больших матриц.) Итак, тот факт, что определитель равен 0 (из-за недостаточной точности чисел с плавающей запятой) не является препятствием для процедуры обращения матрицы.

В продолжение комментариев BobChao87, вот упрощенный тестовый пример (консоль Python 3.4, numpy импортирована как np)

A = 0.2*np.identity(500)
np.linalg.inv(A)

Выход: матрица с 5 на главной диагонали, которая является правильной обратной матрицей A.

np.linalg.det(A)

Выход: 0,0, потому что определитель (0,2^500) слишком мал для представления с двойной точностью.

Возможным решением является своего рода предварительное обусловливание (здесь просто изменение масштаба): перед вычислением определителя , умножьте матрицу на коэффициент, который приблизит ее элементы к 1 в среднем. В моем примере np.linalg.det(5*A) возвращает 1.

Конечно, использование коэффициента 5 здесь является мошенничеством, но np.linalg.det(3*A) также возвращает ненулевое значение (около 1,19e-111). Если вы попробуете np.linalg.det(2**k*A) для k пробежать через скромные положительные целые числа, вы, скорее всего, наткнетесь на то, что вернет ненулевое значение. Тогда вы узнаете, что определитель исходной матрицы примерно в 2**(-k*n) раз больше выходного, где n — размер матрицы.

person Community    schedule 25.02.2015